Compare commits

...
Author SHA1 Message Date
mohammad d3bd363b70 Fix category check in schedule dialog for water heater 2025-07-21 15:10:15 +03:00
mohammad 076c80fe44 Enhance garage door scheduling functionality and UI improvements 2025-07-17 17:02:23 +03:00
Rafeek-khoudare 75b9f4a4e6 changed the title from Routine to Workflow Automation (#354)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1851](https://syncrow.atlassian.net/browse/SP-1851)

## Description

change the Title to Work Flow 

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ] ✨ New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ] ❌ Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ] ✅ Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1851]:
https://syncrow.atlassian.net/browse/SP-1851?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-07-15 11:54:29 +03:00
Rafeek-Khoudare fe4063ef8f changed the title from Routine to Workflow Automation 2025-07-15 11:20:13 +03:00
mohammadnemer1 029b5d32e0 Adjust table scroll behavior and modify height for improved layout (#353)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Description

<!--- Describe your changes in detail -->
Adjust table scroll behavior and modify height for improved layout

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ] ✨ New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ] ❌ Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ] ✅ Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-07-15 10:43:22 +03:00
mohammad 428c81efff Adjust table scroll behavior and modify height for improved layout 2025-07-15 10:05:07 +03:00
Rafeek-khoudare 288c252f46 SP-1696-fe-edit-user-dialog-enhancements (#347)
<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1696](https://syncrow.atlassian.net/browse/SP-1696)

## Description

add company Name and replace it with job title

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [x] ✨ New feature (non-breaking change which adds functionality)
- [ ] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ] ❌ Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ] ✅ Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1696]:
https://syncrow.atlassian.net/browse/SP-1696?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-07-15 09:08:15 +03:00
Rafeek-khoudare 7399dee687 [FE] Redundant API calls on Routines page when selecting a community from the tree (#345)
…rom the tree

<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->

## Jira Ticket
[SP-1800](https://syncrow.atlassian.net/browse/SP-1800)

## Description

fix Redundant API calls when choosing devices and use Que Par to send
spaces instead of send api for every space

## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ] ✨ New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ] ❌ Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ] ✅ Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore 


[SP-1800]:
https://syncrow.atlassian.net/browse/SP-1800?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
2025-07-15 08:32:08 +03:00
Rafeek-Khoudare 08e2ed4b4c Merge branch 'dev' into revert-SP-1589 2025-07-15 08:31:45 +03:00
Rafeek-Khoudare 59e04708cd Merge branch 'main' into revert-SP-1589 2025-07-15 08:30:33 +03:00
Rafeek-Khoudare 338d4f5737 fix typo 2025-07-15 08:19:43 +03:00
mohammadnemer1 5532935a3a Enhance UI components: update color management, adjust button styles,… (#350)
… and improve text formatting for better readability

<!--
  Thanks for contributing!

Provide a description of your changes below and a general summary in the
title

Please look at the following checklist to ensure that your PR can be
accepted quickly:
-->



## Description

<!--- Describe your changes in detail -->
Enhance UI components: update color 
## Type of Change

<!--- Put an `x` in all the boxes that apply: -->

- [ ] ✨ New feature (non-breaking change which adds functionality)
- [x] 🛠️ Bug fix (non-breaking change which fixes an issue)
- [ ] ❌ Breaking change (fix or feature that would cause existing
functionality to change)
- [ ] 🧹 Code refactor
- [ ] ✅ Build configuration change
- [ ] 📝 Documentation
- [ ] 🗑️ Chore
2025-07-14 16:15:42 +03:00
Rafeek-Khoudare 2681c837f5 add company name and replace it with job title 2025-07-11 12:10:53 +03:00
Rafeek-Khoudare b6664ec1ba fix Redundant API calls on Routines page when selecting a community from the tree 2025-07-11 10:53:04 +03:00
Rafeek Alkhoudare dcf1df9b4a sp1613 delete condition word 2025-05-21 07:25:34 -05:00
22 changed files with 133 additions and 113 deletions
+3 -2
View File
@@ -132,6 +132,8 @@ class _DynamicTableState extends State<DynamicTable> {
child: SingleChildScrollView( child: SingleChildScrollView(
controller: _horizontalScrollController, controller: _horizontalScrollController,
scrollDirection: Axis.horizontal, scrollDirection: Axis.horizontal,
physics:
widget.isEmpty ? const NeverScrollableScrollPhysics() : null,
child: SizedBox( child: SizedBox(
width: _totalTableWidth, width: _totalTableWidth,
child: Column( child: Column(
@@ -164,7 +166,6 @@ class _DynamicTableState extends State<DynamicTable> {
], ],
), ),
), ),
Expanded( Expanded(
child: widget.isEmpty child: widget.isEmpty
? _buildEmptyState() ? _buildEmptyState()
@@ -265,7 +266,7 @@ class _DynamicTableState extends State<DynamicTable> {
), ),
], ],
), ),
SizedBox(height: widget.size.height * 0.5), SizedBox(height: widget.size.height * 0.2),
], ],
), ),
); );
@@ -46,15 +46,15 @@ class DeviceManagementBloc
final projectUuid = await ProjectManager.getProjectUUID() ?? ''; final projectUuid = await ProjectManager.getProjectUUID() ?? '';
if (spaceBloc.state.selectedCommunities.isEmpty) { if (spaceBloc.state.selectedCommunities.isEmpty) {
devices = await DevicesManagementApi().fetchDevices('', '', projectUuid); devices = await DevicesManagementApi().fetchDevices(
projectUuid,
);
} else { } else {
for (final community in spaceBloc.state.selectedCommunities) { for (var community in spaceBloc.state.selectedCommunities) {
final spacesList = final spacesList =
spaceBloc.state.selectedCommunityAndSpaces[community] ?? []; spaceBloc.state.selectedCommunityAndSpaces[community] ?? [];
for (final space in spacesList) {
devices.addAll(await DevicesManagementApi() devices.addAll(await DevicesManagementApi()
.fetchDevices(community, space, projectUuid)); .fetchDevices(projectUuid, spacesId: spacesList));
}
} }
} }
@@ -24,12 +24,12 @@ class DeviceManagementPage extends StatefulWidget with HelperResponsiveLayout {
} }
class _DeviceManagementPageState extends State<DeviceManagementPage> { class _DeviceManagementPageState extends State<DeviceManagementPage> {
@override
@override
void initState() { void initState() {
context.read<SpaceTreeBloc>().add(InitialEvent()); context.read<SpaceTreeBloc>().add(InitialEvent());
super.initState(); super.initState();
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return MultiBlocProvider( return MultiBlocProvider(
@@ -90,7 +90,7 @@ class _DeviceManagementPageState extends State<DeviceManagementPage> {
const TriggerSwitchTabsEvent(isRoutineTab: true)); const TriggerSwitchTabsEvent(isRoutineTab: true));
}, },
child: Text( child: Text(
'Routines', 'Workflow Automation',
style: context.textTheme.titleMedium?.copyWith( style: context.textTheme.titleMedium?.copyWith(
color: state.routineTab color: state.routineTab
? ColorsManager.whiteColors ? ColorsManager.whiteColors
@@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/device_managment/garage_door/bloc/garage_door_
import 'package:syncrow_web/pages/device_managment/garage_door/helper/garage_door_helper.dart'; import 'package:syncrow_web/pages/device_managment/garage_door/helper/garage_door_helper.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/models/garage_door_model.dart'; import 'package:syncrow_web/pages/device_managment/garage_door/models/garage_door_model.dart';
import 'package:syncrow_web/pages/device_managment/garage_door/schedule_view/schedule_garage_view.dart'; import 'package:syncrow_web/pages/device_managment/garage_door/schedule_view/schedule_garage_view.dart';
import 'package:syncrow_web/pages/device_managment/schedule_device/schedule_widgets/schedual_view.dart';
import 'package:syncrow_web/pages/device_managment/shared/icon_name_status_container.dart'; import 'package:syncrow_web/pages/device_managment/shared/icon_name_status_container.dart';
import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dart'; import 'package:syncrow_web/pages/device_managment/shared/table/report_table.dart';
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
@@ -94,11 +95,18 @@ class GarageDoorControlView extends StatelessWidget
FetchGarageDoorSchedulesEvent( FetchGarageDoorSchedulesEvent(
deviceId: deviceId, category: 'doorcontact_state'), deviceId: deviceId, category: 'doorcontact_state'),
); );
showDialog(
showDialog<void>(
context: context, context: context,
builder: (ctx) => BlocProvider.value( builder: (ctx) => BlocProvider.value(
value: BlocProvider.of<GarageDoorBloc>(context), value: BlocProvider.of<GarageDoorBloc>(context),
child: BuildGarageDoorScheduleView(status: status), child: BuildScheduleView(
deviceUuid: deviceId,
category: 'Timer',
code: 'doorcontact_state',
countdownCode: 'Timer',
deviceType: 'GD',
),
)); ));
}, },
name: 'Scheduling', name: 'Scheduling',
@@ -287,7 +287,8 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
try { try {
if (state is ScheduleLoaded) { if (state is ScheduleLoaded) {
Status status = Status(code: '', value: ''); Status status = Status(code: '', value: '');
if (event.deviceType == 'CUR_2') { if (event.deviceType == 'CUR_2' ||
event.deviceType == 'GD' ) {
status = status.copyWith( status = status.copyWith(
code: 'control', code: 'control',
value: event.functionOn == true ? 'open' : 'close'); value: event.functionOn == true ? 'open' : 'close');
@@ -69,7 +69,7 @@ class CountdownModeButtons extends StatelessWidget {
countDownCode: countDownCode), countDownCode: countDownCode),
); );
}, },
backgroundColor: ColorsManager.primaryColorWithOpacity, backgroundColor: ColorsManager.secondaryColor,
child: const Text('Save'), child: const Text('Save'),
), ),
), ),
@@ -63,7 +63,7 @@ class InchingModeButtons extends StatelessWidget {
), ),
); );
}, },
backgroundColor: ColorsManager.primaryColor, backgroundColor: ColorsManager.secondaryColor,
child: const Text('Save'), child: const Text('Save'),
), ),
), ),
@@ -31,11 +31,12 @@ class BuildScheduleView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BlocProvider( return BlocProvider(
create: (_) => ScheduleBloc(deviceId: deviceUuid,) create: (_) => ScheduleBloc(
deviceId: deviceUuid,
)
..add(ScheduleGetEvent(category: category)) ..add(ScheduleGetEvent(category: category))
..add(ScheduleFetchStatusEvent( ..add(ScheduleFetchStatusEvent(
deviceId: deviceUuid, deviceId: deviceUuid, countdownCode: countdownCode ?? '')),
countdownCode: countdownCode ?? '')),
child: Dialog( child: Dialog(
backgroundColor: Colors.white, backgroundColor: Colors.white,
insetPadding: const EdgeInsets.all(20), insetPadding: const EdgeInsets.all(20),
@@ -56,7 +57,7 @@ class BuildScheduleView extends StatelessWidget {
children: [ children: [
const ScheduleHeader(), const ScheduleHeader(),
const SizedBox(height: 20), const SizedBox(height: 20),
if (deviceType == 'CUR_2') if (deviceType == 'CUR_2' || deviceType == 'GD')
const SizedBox() const SizedBox()
else else
ScheduleModeSelector( ScheduleModeSelector(
@@ -76,8 +77,7 @@ class BuildScheduleView extends StatelessWidget {
category: category, category: category,
time: '', time: '',
function: Status( function: Status(
code: code.toString(), code: code.toString(), value: true),
value: true),
days: [], days: [],
), ),
isEdit: false, isEdit: false,
@@ -96,7 +96,7 @@ class BuildScheduleView extends StatelessWidget {
} }
}, },
), ),
if (deviceType != 'CUR_2') if (deviceType != 'CUR_2'|| deviceType != 'GD')
if (state.scheduleMode == ScheduleModes.countdown || if (state.scheduleMode == ScheduleModes.countdown ||
state.scheduleMode == ScheduleModes.inching) state.scheduleMode == ScheduleModes.inching)
CountdownInchingView( CountdownInchingView(
@@ -24,12 +24,13 @@ class ScheduleManagementUI extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
SizedBox( SizedBox(
width: 170, width: 177,
height: 40, height: 40,
child: DefaultButton( child: DefaultButton(
borderColor: ColorsManager.grayColor.withOpacity(0.5), borderWidth: 4,
padding: 2, borderColor: ColorsManager.neutralGray,
backgroundColor: ColorsManager.graysColor, padding: 8,
backgroundColor: ColorsManager.textFieldGreyColor,
borderRadius: 15, borderRadius: 15,
onPressed: onAddSchedule, onPressed: onAddSchedule,
child: Row( child: Row(
@@ -39,7 +39,7 @@ class ScheduleModeButtons extends StatelessWidget {
borderRadius: 8, borderRadius: 8,
height: 40, height: 40,
onPressed: onSave, onPressed: onSave,
backgroundColor: ColorsManager.primaryColorWithOpacity, backgroundColor: ColorsManager.secondaryColor,
child: const Text('Save'), child: const Text('Save'),
), ),
), ),
@@ -194,7 +194,7 @@ class _ScheduleTableView extends StatelessWidget {
child: Text(_getSelectedDays( child: Text(_getSelectedDays(
ScheduleModel.parseSelectedDays(schedule.days)))), ScheduleModel.parseSelectedDays(schedule.days)))),
Center(child: Text(formatIsoStringToTime(schedule.time, context))), Center(child: Text(formatIsoStringToTime(schedule.time, context))),
if (deviceType == 'CUR_2') if (deviceType == 'CUR_2' || deviceType == 'GD')
Center( Center(
child: Text(schedule.function.value == true ? 'open' : 'close')) child: Text(schedule.function.value == true ? 'open' : 'close'))
else else
@@ -23,7 +23,7 @@ class ScheduleDialogHelper {
required String deviceType, required String deviceType,
}) { }) {
bool temp; bool temp;
if (deviceType == 'CUR_2') { if (deviceType == 'CUR_2' || deviceType == 'GD') {
temp = schedule!.function.value == 'open' ? true : false; temp = schedule!.function.value == 'open' ? true : false;
} else { } else {
temp = schedule!.function.value; temp = schedule!.function.value;
@@ -116,7 +116,7 @@ class ScheduleDialogHelper {
ScheduleModeButtons( ScheduleModeButtons(
onSave: () { onSave: () {
dynamic temp; dynamic temp;
if (deviceType == 'CUR_2') { if (deviceType == 'CUR_2' || deviceType == 'GD') {
temp = functionOn! ? 'open' : 'close'; temp = functionOn! ? 'open' : 'close';
} else { } else {
temp = functionOn; temp = functionOn;
@@ -202,18 +202,23 @@ class ScheduleDialogHelper {
), ),
const SizedBox(width: 10), const SizedBox(width: 10),
Radio<bool>( Radio<bool>(
activeColor: ColorsManager.secondaryColor,
focusColor: ColorsManager.secondaryColor,
value: true, value: true,
groupValue: isOn, groupValue: isOn,
onChanged: (val) => onChanged(true), onChanged: (val) => onChanged(true),
), ),
Text(categor == 'CUR_2' ? 'open' : 'On'), Text(categor == 'CUR_2' || categor == 'GD' ? 'open' : 'On'),
const SizedBox(width: 10), const SizedBox(width: 10),
Radio<bool>( Radio<bool>(
activeColor: ColorsManager.secondaryColor,
focusColor: ColorsManager.secondaryColor,
value: false, value: false,
groupValue: isOn, groupValue: isOn,
onChanged: (val) => onChanged(false), onChanged: (val) => onChanged(false),
), ),
Text(categor == 'CUR_2' ? 'close' : 'Off'), Text(categor == 'CUR_2' || categor == 'GD' ? 'close' : 'Off'),
], ],
); );
} }
@@ -153,6 +153,7 @@ class EditUserModel {
final String? jobTitle; // can be empty final String? jobTitle; // can be empty
final String roleType; // e.g. "ADMIN" final String roleType; // e.g. "ADMIN"
final List<UserSpaceModel> spaces; final List<UserSpaceModel> spaces;
final String? companyName;
EditUserModel({ EditUserModel({
required this.uuid, required this.uuid,
@@ -167,6 +168,7 @@ class EditUserModel {
required this.jobTitle, required this.jobTitle,
required this.roleType, required this.roleType,
required this.spaces, required this.spaces,
this.companyName,
}); });
/// Create a [UserData] from JSON data /// Create a [UserData] from JSON data
@@ -182,6 +184,7 @@ class EditUserModel {
invitedBy: json['invitedBy'] as String, invitedBy: json['invitedBy'] as String,
phoneNumber: json['phoneNumber'] ?? '', phoneNumber: json['phoneNumber'] ?? '',
jobTitle: json['jobTitle'] ?? '', jobTitle: json['jobTitle'] ?? '',
companyName: json['companyName'] as String?,
roleType: json['roleType'] as String, roleType: json['roleType'] as String,
spaces: (json['spaces'] as List<dynamic>) spaces: (json['spaces'] as List<dynamic>)
.map((e) => UserSpaceModel.fromJson(e as Map<String, dynamic>)) .map((e) => UserSpaceModel.fromJson(e as Map<String, dynamic>))
@@ -12,7 +12,7 @@ class RolesUserModel {
final dynamic jobTitle; final dynamic jobTitle;
final dynamic createdDate; final dynamic createdDate;
final dynamic createdTime; final dynamic createdTime;
final String? companyName;
RolesUserModel({ RolesUserModel({
required this.uuid, required this.uuid,
required this.createdAt, required this.createdAt,
@@ -27,6 +27,7 @@ class RolesUserModel {
this.jobTitle, this.jobTitle,
required this.createdDate, required this.createdDate,
required this.createdTime, required this.createdTime,
this.companyName,
}); });
factory RolesUserModel.fromJson(Map<String, dynamic> json) { factory RolesUserModel.fromJson(Map<String, dynamic> json) {
@@ -47,6 +48,7 @@ class RolesUserModel {
: json['jobTitle'], : json['jobTitle'],
createdDate: json['createdDate'], createdDate: json['createdDate'],
createdTime: json['createdTime'], createdTime: json['createdTime'],
companyName: json['companyName'] as String?,
); );
} }
} }
@@ -52,7 +52,7 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
final TextEditingController lastNameController = TextEditingController(); final TextEditingController lastNameController = TextEditingController();
final TextEditingController emailController = TextEditingController(); final TextEditingController emailController = TextEditingController();
final TextEditingController phoneController = TextEditingController(); final TextEditingController phoneController = TextEditingController();
final TextEditingController jobTitleController = TextEditingController(); final TextEditingController companyNameController = TextEditingController();
final TextEditingController roleSearchController = TextEditingController(); final TextEditingController roleSearchController = TextEditingController();
bool? isCompleteBasics; bool? isCompleteBasics;
@@ -352,7 +352,7 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
bool res = await UserPermissionApi().sendInviteUser( bool res = await UserPermissionApi().sendInviteUser(
email: emailController.text, email: emailController.text,
firstName: firstNameController.text, firstName: firstNameController.text,
jobTitle: jobTitleController.text, companyName: companyNameController.text,
lastName: lastNameController.text, lastName: lastNameController.text,
phoneNumber: phoneController.text, phoneNumber: phoneController.text,
roleUuid: roleSelected, roleUuid: roleSelected,
@@ -405,7 +405,7 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
bool res = await UserPermissionApi().editInviteUser( bool res = await UserPermissionApi().editInviteUser(
userId: event.userId, userId: event.userId,
firstName: firstNameController.text, firstName: firstNameController.text,
jobTitle: jobTitleController.text, companyName: companyNameController.text,
lastName: lastNameController.text, lastName: lastNameController.text,
phoneNumber: phoneController.text, phoneNumber: phoneController.text,
roleUuid: roleSelected, roleUuid: roleSelected,
@@ -529,7 +529,7 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
lastNameController.text = res.lastName; lastNameController.text = res.lastName;
emailController.text = res.email; emailController.text = res.email;
phoneController.text = res.phoneNumber ?? ''; phoneController.text = res.phoneNumber ?? '';
jobTitleController.text = res.jobTitle ?? ''; companyNameController.text = res.companyName ?? '';
res.roleType; res.roleType;
res.spaces.map((space) { res.spaces.map((space) {
selectedIds.add(space.uuid); selectedIds.add(space.uuid);
@@ -645,7 +645,7 @@ class UsersBloc extends Bloc<UsersEvent, UsersState> {
lastNameController.dispose(); lastNameController.dispose();
emailController.dispose(); emailController.dispose();
phoneController.dispose(); phoneController.dispose();
jobTitleController.dispose(); companyNameController.dispose();
roleSearchController.dispose(); roleSearchController.dispose();
return super.close(); return super.close();
} }
@@ -317,7 +317,7 @@ class BasicsView extends StatelessWidget {
child: Row( child: Row(
children: [ children: [
Text( Text(
'Job Title', 'Company Name',
style: context.textTheme.bodyMedium?.copyWith( style: context.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
fontSize: 13, fontSize: 13,
@@ -328,11 +328,11 @@ class BasicsView extends StatelessWidget {
Padding( Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: TextFormField( child: TextFormField(
controller: _blocRole.jobTitleController, controller: _blocRole.companyNameController,
style: style:
const TextStyle(color: ColorsManager.blackColor), const TextStyle(color: ColorsManager.blackColor),
decoration: inputTextFormDeco( decoration: inputTextFormDeco(
hintText: "Job Title (Optional)") hintText: 'Company Name (Optional)')
.copyWith( .copyWith(
hintStyle: context.textTheme.bodyMedium?.copyWith( hintStyle: context.textTheme.bodyMedium?.copyWith(
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
@@ -411,7 +411,7 @@ class UsersPage extends StatelessWidget {
titles: const [ titles: const [
"Full Name", "Full Name",
"Email Address", "Email Address",
"Job Title", "Company Name",
"Role", "Role",
"Creation Date", "Creation Date",
"Creation Time", "Creation Time",
@@ -424,7 +424,7 @@ class UsersPage extends StatelessWidget {
return [ return [
Text('${user.firstName} ${user.lastName}'), Text('${user.firstName} ${user.lastName}'),
Text(user.email), Text(user.email),
Text(user.jobTitle), Center(child: Text(user.companyName ?? '-')),
Text(user.roleType ?? ''), Text(user.roleType ?? ''),
Text(user.createdDate ?? ''), Text(user.createdDate ?? ''),
Text(user.createdTime ?? ''), Text(user.createdTime ?? ''),
@@ -170,7 +170,7 @@ class RoutineBloc extends Bloc<RoutineEvent, RoutineState> {
} }
} }
Future<void> _onLoadScenes( Future<void> _onLoadScenes(
LoadScenes event, Emitter<RoutineState> emit) async { LoadScenes event, Emitter<RoutineState> emit) async {
emit(state.copyWith(isLoading: true, errorMessage: null)); emit(state.copyWith(isLoading: true, errorMessage: null));
List<ScenesModel> scenes = []; List<ScenesModel> scenes = [];
@@ -208,7 +208,7 @@ Future<void> _onLoadScenes(
loadAutomationErrorMessage: '', loadAutomationErrorMessage: '',
scenes: scenes)); scenes: scenes));
} }
} }
Future<void> _onLoadAutomation( Future<void> _onLoadAutomation(
LoadAutomation event, Emitter<RoutineState> emit) async { LoadAutomation event, Emitter<RoutineState> emit) async {
@@ -936,16 +936,15 @@ Future<void> _onLoadScenes(
for (var communityId in spaceBloc.state.selectedCommunities) { for (var communityId in spaceBloc.state.selectedCommunities) {
List<String> spacesList = List<String> spacesList =
spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? [];
for (var spaceId in spacesList) {
devices.addAll(await DevicesManagementApi() devices.addAll(await DevicesManagementApi()
.fetchDevices(communityId, spaceId, projectUuid)); .fetchDevices(projectUuid, spacesId: spacesList));
}
} }
} else { } else {
devices.addAll(await DevicesManagementApi().fetchDevices( devices.addAll(await DevicesManagementApi().fetchDevices(
createRoutineBloc.selectedCommunityId, projectUuid,
createRoutineBloc.selectedSpaceId, spacesId: [createRoutineBloc.selectedSpaceId],
projectUuid)); ));
} }
emit(state.copyWith(isLoading: false, devices: devices)); emit(state.copyWith(isLoading: false, devices: devices));
@@ -96,9 +96,7 @@ class _WallPresenceSensorState extends State<FlushPresenceSensor> {
child: Column( child: Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
DialogHeader(widget.dialogType == 'THEN' const DialogHeader('Presence Sensor'),
? 'Presence Sensor Functions'
: 'Presence Sensor Condition'),
Expanded(child: _buildMainContent(context, state)), Expanded(child: _buildMainContent(context, state)),
_buildDialogFooter(context, state), _buildDialogFooter(context, state),
], ],
+6 -11
View File
@@ -12,20 +12,16 @@ import 'package:syncrow_web/services/api/http_service.dart';
import 'package:syncrow_web/utils/constants/api_const.dart'; import 'package:syncrow_web/utils/constants/api_const.dart';
class DevicesManagementApi { class DevicesManagementApi {
Future<List<AllDevicesModel>> fetchDevices( Future<List<AllDevicesModel>> fetchDevices(String projectId,
String communityId, String spaceId, String projectId) async { {List<String>? spacesId}) async {
try { try {
final response = await HTTPService().get( final response = await HTTPService().get(
path: communityId.isNotEmpty && spaceId.isNotEmpty path: ApiEndpoints.getSpaceDevices.replaceAll('{projectId}', projectId),
? ApiEndpoints.getSpaceDevices queryParameters: {if (spacesId != null) 'spaces': spacesId},
.replaceAll('{spaceUuid}', spaceId)
.replaceAll('{communityUuid}', communityId)
.replaceAll('{projectId}', projectId)
: ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId),
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
List<dynamic> jsonData = json['data']; final List<dynamic> jsonData = json['data'] as List<dynamic>;
List<AllDevicesModel> devicesList = jsonData.map((jsonItem) { final List<AllDevicesModel> devicesList = jsonData.map((jsonItem) {
return AllDevicesModel.fromJson(jsonItem); return AllDevicesModel.fromJson(jsonItem);
}).toList(); }).toList();
return devicesList; return devicesList;
@@ -416,5 +412,4 @@ class DevicesManagementApi {
); );
return response; return response;
} }
} }
+19 -11
View File
@@ -34,8 +34,9 @@ class UserPermissionApi {
path: ApiEndpoints.roleTypes, path: ApiEndpoints.roleTypes,
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
final List<RoleTypeModel> fetchedRoles = final List<RoleTypeModel> fetchedRoles = (json['data'] as List)
(json['data'] as List).map((item) => RoleTypeModel.fromJson(item)).toList(); .map((item) => RoleTypeModel.fromJson(item))
.toList();
return fetchedRoles; return fetchedRoles;
}, },
); );
@@ -47,7 +48,9 @@ class UserPermissionApi {
path: ApiEndpoints.permission.replaceAll("roleUuid", roleUuid), path: ApiEndpoints.permission.replaceAll("roleUuid", roleUuid),
showServerMessage: true, showServerMessage: true,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return (json as List).map((data) => PermissionOption.fromJson(data)).toList(); return (json as List)
.map((data) => PermissionOption.fromJson(data))
.toList();
}, },
); );
return response ?? []; return response ?? [];
@@ -57,7 +60,7 @@ class UserPermissionApi {
String? firstName, String? firstName,
String? lastName, String? lastName,
String? email, String? email,
String? jobTitle, String? companyName,
String? phoneNumber, String? phoneNumber,
String? roleUuid, String? roleUuid,
List<String>? spaceUuids, List<String>? spaceUuids,
@@ -68,7 +71,7 @@ class UserPermissionApi {
"firstName": firstName, "firstName": firstName,
"lastName": lastName, "lastName": lastName,
"email": email, "email": email,
"jobTitle": jobTitle != '' ? jobTitle : null, "companyName": companyName != '' ? companyName : null,
"phoneNumber": phoneNumber != '' ? phoneNumber : null, "phoneNumber": phoneNumber != '' ? phoneNumber : null,
"roleUuid": roleUuid, "roleUuid": roleUuid,
"projectUuid": projectUuid, "projectUuid": projectUuid,
@@ -140,7 +143,7 @@ class UserPermissionApi {
String? firstName, String? firstName,
String? userId, String? userId,
String? lastName, String? lastName,
String? jobTitle, String? companyName,
String? phoneNumber, String? phoneNumber,
String? roleUuid, String? roleUuid,
List<String>? spaceUuids, List<String>? spaceUuids,
@@ -150,8 +153,8 @@ class UserPermissionApi {
final body = <String, dynamic>{ final body = <String, dynamic>{
"firstName": firstName, "firstName": firstName,
"lastName": lastName, "lastName": lastName,
"jobTitle": jobTitle != '' ? jobTitle : " ", "companyName": companyName != '' ? companyName : ' ',
"phoneNumber": phoneNumber != '' ? phoneNumber : " ", "phoneNumber": phoneNumber != '' ? phoneNumber : ' ',
"roleUuid": roleUuid, "roleUuid": roleUuid,
"projectUuid": projectUuid, "projectUuid": projectUuid,
"spaceUuids": spaceUuids, "spaceUuids": spaceUuids,
@@ -190,12 +193,17 @@ class UserPermissionApi {
} }
} }
Future<bool> changeUserStatusById(userUuid, status, String projectUuid) async { Future<bool> changeUserStatusById(
userUuid, status, String projectUuid) async {
try { try {
Map<String, dynamic> bodya = {"disable": status, "projectUuid": projectUuid}; Map<String, dynamic> bodya = {
"disable": status,
"projectUuid": projectUuid
};
final response = await _httpService.put( final response = await _httpService.put(
path: ApiEndpoints.changeUserStatus.replaceAll("{invitedUserUuid}", userUuid), path: ApiEndpoints.changeUserStatus
.replaceAll("{invitedUserUuid}", userUuid),
body: bodya, body: bodya,
expectedResponseModel: (json) { expectedResponseModel: (json) {
return json['success']; return json['success'];
+1 -2
View File
@@ -17,8 +17,7 @@ abstract class ApiEndpoints {
////// Devices Management //////////////// ////// Devices Management ////////////////
static const String getAllDevices = '/projects/{projectId}/devices'; static const String getAllDevices = '/projects/{projectId}/devices';
static const String getSpaceDevices = static const String getSpaceDevices = '/projects/{projectId}/devices';
'/projects/{projectId}/communities/{communityUuid}/spaces/{spaceUuid}/devices';
static const String getDeviceStatus = '/devices/{uuid}/functions/status'; static const String getDeviceStatus = '/devices/{uuid}/functions/status';
static const String getBatchStatus = '/devices/batch'; static const String getBatchStatus = '/devices/batch';