diff --git a/assets/images/completed_done.svg b/assets/images/completed_done.svg new file mode 100644 index 00000000..759f0cba --- /dev/null +++ b/assets/images/completed_done.svg @@ -0,0 +1,4 @@ + + + + diff --git a/lib/pages/analytics/models/analytics_device.dart b/lib/pages/analytics/models/analytics_device.dart index 869de23f..6571eae4 100644 --- a/lib/pages/analytics/models/analytics_device.dart +++ b/lib/pages/analytics/models/analytics_device.dart @@ -39,8 +39,12 @@ class AnalyticsDevice { ? ProductDevice.fromJson(json['productDevice'] as Map) : null, spaceUuid: json['spaceUuid'] as String?, - latitude: json['lat'] != null ? double.parse(json['lat'] as String? ?? '0.0') : null, - longitude: json['lon'] != null ? double.parse(json['lon'] as String? ?? '0.0') : null, + latitude: json['lat'] != null && json['lat'] != '' + ? double.tryParse(json['lat']?.toString() ?? '0.0') + : null, + longitude: json['lon'] != null && json['lon'] != '' + ? double.tryParse(json['lon']?.toString() ?? '0.0') + : null, ); } } diff --git a/lib/pages/analytics/modules/air_quality/blocs/air_quality_distribution/air_quality_distribution_bloc.dart b/lib/pages/analytics/modules/air_quality/blocs/air_quality_distribution/air_quality_distribution_bloc.dart index 40d51d2b..455dff23 100644 --- a/lib/pages/analytics/modules/air_quality/blocs/air_quality_distribution/air_quality_distribution_bloc.dart +++ b/lib/pages/analytics/modules/air_quality/blocs/air_quality_distribution/air_quality_distribution_bloc.dart @@ -46,11 +46,11 @@ class AirQualityDistributionBloc } } - Future _onClearAirQualityDistribution( + void _onClearAirQualityDistribution( ClearAirQualityDistribution event, Emitter emit, - ) async { - emit(const AirQualityDistributionState()); + ) { + emit(AirQualityDistributionState(selectedAqiType: state.selectedAqiType)); } void _onUpdateAqiTypeEvent( diff --git a/lib/pages/analytics/modules/air_quality/blocs/range_of_aqi/range_of_aqi_bloc.dart b/lib/pages/analytics/modules/air_quality/blocs/range_of_aqi/range_of_aqi_bloc.dart index 88c3715e..326a87a2 100644 --- a/lib/pages/analytics/modules/air_quality/blocs/range_of_aqi/range_of_aqi_bloc.dart +++ b/lib/pages/analytics/modules/air_quality/blocs/range_of_aqi/range_of_aqi_bloc.dart @@ -75,6 +75,6 @@ class RangeOfAqiBloc extends Bloc { ClearRangeOfAqiEvent event, Emitter emit, ) { - emit(const RangeOfAqiState()); + emit(RangeOfAqiState(selectedAqiType: state.selectedAqiType)); } } diff --git a/lib/pages/analytics/modules/air_quality/widgets/aqi_distribution_chart_title.dart b/lib/pages/analytics/modules/air_quality/widgets/aqi_distribution_chart_title.dart index f7be6ee3..7b6b113a 100644 --- a/lib/pages/analytics/modules/air_quality/widgets/aqi_distribution_chart_title.dart +++ b/lib/pages/analytics/modules/air_quality/widgets/aqi_distribution_chart_title.dart @@ -34,6 +34,7 @@ class AqiDistributionChartTitle extends StatelessWidget { alignment: AlignmentDirectional.centerEnd, fit: BoxFit.scaleDown, child: AqiTypeDropdown( + selectedAqiType: context.watch().state.selectedAqiType, onChanged: (value) { if (value != null) { final bloc = context.read(); diff --git a/lib/pages/analytics/modules/air_quality/widgets/aqi_type_dropdown.dart b/lib/pages/analytics/modules/air_quality/widgets/aqi_type_dropdown.dart index 6640c717..8233fe5a 100644 --- a/lib/pages/analytics/modules/air_quality/widgets/aqi_type_dropdown.dart +++ b/lib/pages/analytics/modules/air_quality/widgets/aqi_type_dropdown.dart @@ -18,19 +18,20 @@ enum AqiType { } class AqiTypeDropdown extends StatefulWidget { - const AqiTypeDropdown({super.key, required this.onChanged}); + const AqiTypeDropdown({ + required this.onChanged, + this.selectedAqiType, + super.key, + }); final ValueChanged onChanged; + final AqiType? selectedAqiType; @override State createState() => _AqiTypeDropdownState(); } class _AqiTypeDropdownState extends State { - AqiType? _selectedItem = AqiType.aqi; - - void _updateSelectedItem(AqiType? item) => setState(() => _selectedItem = item); - @override Widget build(BuildContext context) { return Container( @@ -41,8 +42,8 @@ class _AqiTypeDropdownState extends State { width: 1, ), ), - child: DropdownButton( - value: _selectedItem, + child: DropdownButton( + value: widget.selectedAqiType, isDense: true, borderRadius: BorderRadius.circular(16), dropdownColor: ColorsManager.whiteColors, @@ -59,10 +60,7 @@ class _AqiTypeDropdownState extends State { items: AqiType.values .map((e) => DropdownMenuItem(value: e, child: Text(e.value))) .toList(), - onChanged: (value) { - _updateSelectedItem(value); - widget.onChanged(value); - }, + onChanged: widget.onChanged, ), ); } diff --git a/lib/pages/analytics/modules/air_quality/widgets/range_of_aqi_chart_title.dart b/lib/pages/analytics/modules/air_quality/widgets/range_of_aqi_chart_title.dart index 1b0da288..421fbb13 100644 --- a/lib/pages/analytics/modules/air_quality/widgets/range_of_aqi_chart_title.dart +++ b/lib/pages/analytics/modules/air_quality/widgets/range_of_aqi_chart_title.dart @@ -63,15 +63,15 @@ class RangeOfAqiChartTitle extends StatelessWidget { fit: BoxFit.scaleDown, alignment: AlignmentDirectional.centerEnd, child: AqiTypeDropdown( + selectedAqiType: context.watch().state.selectedAqiType, onChanged: (value) { final spaceTreeState = context.read().state; final spaceUuid = spaceTreeState.selectedSpaces.firstOrNull; - - if (spaceUuid == null) return; - if (value != null) { context.read().add(UpdateAqiTypeEvent(value)); } + + if (spaceUuid == null) return; }, ), ), diff --git a/lib/pages/analytics/services/device_location/device_location_details_service_decorator.dart b/lib/pages/analytics/services/device_location/device_location_details_service_decorator.dart index f38f607d..0a49a797 100644 --- a/lib/pages/analytics/services/device_location/device_location_details_service_decorator.dart +++ b/lib/pages/analytics/services/device_location/device_location_details_service_decorator.dart @@ -17,8 +17,8 @@ class DeviceLocationDetailsServiceDecorator implements DeviceLocationService { 'reverse', queryParameters: { 'format': 'json', - 'lat': param.latitude, - 'lon': param.longitude, + 'lat': 25.1880567, + 'lon': 55.266608, }, ); diff --git a/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart index 4063692e..2c42caa6 100644 --- a/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart +++ b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart @@ -16,11 +16,12 @@ class DeviceManagementBloc int _onlineCount = 0; int _offlineCount = 0; int _lowBatteryCount = 0; - List _selectedDevices = []; + final List _selectedDevices = []; List _filteredDevices = []; String currentProductName = ''; String? currentCommunity; String? currentUnitName; + String subSpaceName = ''; DeviceManagementBloc() : super(DeviceManagementInitial()) { on(_onFetchDevices); @@ -31,24 +32,29 @@ class DeviceManagementBloc on(_onResetFilters); on(_onResetSelectedDevices); on(_onUpdateSelection); + on(_onUpdateDeviceName); + on(_onUpdateSubSpaceName); } Future _onFetchDevices( FetchDevices event, Emitter emit) async { emit(DeviceManagementLoading()); try { - List devices = []; + var devices = []; _devices.clear(); - var spaceBloc = event.context.read(); + final spaceBloc = event.context.read(); final projectUuid = await ProjectManager.getProjectUUID() ?? ''; + if (spaceBloc.state.selectedCommunities.isEmpty) { - devices = await DevicesManagementApi().fetchDevices(projectUuid); + devices = await DevicesManagementApi().fetchDevices('', '', projectUuid); } else { - for (var community in spaceBloc.state.selectedCommunities) { - List spacesList = + for (final community in spaceBloc.state.selectedCommunities) { + final spacesList = spaceBloc.state.selectedCommunityAndSpaces[community] ?? []; - devices.addAll(await DevicesManagementApi() - .fetchDevices(projectUuid, spacesId: spacesList)); + for (final space in spacesList) { + devices.addAll(await DevicesManagementApi() + .fetchDevices(community, space, projectUuid)); + } } } @@ -70,7 +76,7 @@ class DeviceManagementBloc } } - void _onFilterDevices( + Future _onFilterDevices( FilterDevices event, Emitter emit) async { if (_devices.isNotEmpty) { _filteredDevices = List.from(_devices.where((device) { @@ -152,8 +158,7 @@ class DeviceManagementBloc add(FilterDevices(_getFilterFromIndex(_selectedIndex))); } - void _onSelectDevice( - SelectDevice event, Emitter emit) { + void _onSelectDevice(SelectDevice event, Emitter emit) { final selectedUuid = event.selectedDevice.uuid; if (_selectedDevices.any((device) => device.uuid == selectedUuid)) { @@ -162,9 +167,9 @@ class DeviceManagementBloc _selectedDevices.add(event.selectedDevice); } - List clonedSelectedDevices = List.from(_selectedDevices); + final clonedSelectedDevices = List.from(_selectedDevices); - bool isControlButtonEnabled = + final isControlButtonEnabled = _checkIfControlButtonEnabled(clonedSelectedDevices); if (state is DeviceManagementLoaded) { @@ -194,8 +199,8 @@ class DeviceManagementBloc void _onUpdateSelection( UpdateSelection event, Emitter emit) { - List selectedDevices = []; - List devicesToSelectFrom = []; + final selectedDevices = []; + var devicesToSelectFrom = []; if (state is DeviceManagementLoaded) { devicesToSelectFrom = (state as DeviceManagementLoaded).devices; @@ -203,7 +208,7 @@ class DeviceManagementBloc devicesToSelectFrom = (state as DeviceManagementFiltered).filteredDevices; } - for (int i = 0; i < event.selectedRows.length; i++) { + for (var i = 0; i < event.selectedRows.length; i++) { if (event.selectedRows[i]) { selectedDevices.add(devicesToSelectFrom[i]); } @@ -249,8 +254,7 @@ class DeviceManagementBloc _onlineCount = _devices.where((device) => device.online == true).length; _offlineCount = _devices.where((device) => device.online == false).length; _lowBatteryCount = _devices - .where((device) => - device.batteryLevel != null && device.batteryLevel! < 20) + .where((device) => device.batteryLevel != null && device.batteryLevel! < 20) .length; } @@ -267,8 +271,7 @@ class DeviceManagementBloc } } - void _onSearchDevices( - SearchDevices event, Emitter emit) { + void _onSearchDevices(SearchDevices event, Emitter emit) { if ((event.community == null || event.community!.isEmpty) && (event.unitName == null || event.unitName!.isEmpty) && (event.deviceNameOrProductName == null || @@ -297,7 +300,7 @@ class DeviceManagementBloc currentCommunity = event.community; currentUnitName = event.unitName; - List devicesToSearch = _devices; + final devicesToSearch = _devices; if (devicesToSearch.isNotEmpty) { final searchText = event.deviceNameOrProductName?.toLowerCase() ?? ''; @@ -340,5 +343,134 @@ class DeviceManagementBloc } } + void _onUpdateDeviceName( + UpdateDeviceName event, Emitter emit) { + final devices = _devices.map((device) { + if (device.uuid == event.deviceId) { + final modifiedDevice = device.copyWith(name: event.newName); + _selectedDevices.removeWhere((device) => device.uuid == event.deviceId); + _selectedDevices.add(modifiedDevice); + return modifiedDevice; + } + return device; + }).toList(); + + final filteredDevices = _filteredDevices.map((device) { + if (device.uuid == event.deviceId) { + final modifiedDevice = device.copyWith(name: event.newName); + _selectedDevices.removeWhere((device) => device.uuid == event.deviceId); + _selectedDevices.add(modifiedDevice); + return modifiedDevice; + } + return device; + }).toList(); + + _devices = devices; + _filteredDevices = filteredDevices; + + if (state is DeviceManagementLoaded) { + final loaded = state as DeviceManagementLoaded; + final selectedDevices01 = _selectedDevices.map((device) { + if (device.uuid == event.deviceId) { + final modifiedDevice = device.copyWith(name: event.newName); + return modifiedDevice; + } + return device; + }).toList(); + emit(DeviceManagementLoaded( + devices: devices, + selectedIndex: loaded.selectedIndex, + onlineCount: loaded.onlineCount, + offlineCount: loaded.offlineCount, + lowBatteryCount: loaded.lowBatteryCount, + selectedDevice: selectedDevices01, + isControlButtonEnabled: loaded.isControlButtonEnabled, + )); + } else if (state is DeviceManagementFiltered) { + final filtered = state as DeviceManagementFiltered; + final selectedDevices01 = filtered.selectedDevice?.map((device) { + if (device.uuid == event.deviceId) { + final modifiedDevice = device.copyWith(name: event.newName); + return modifiedDevice; + } + return device; + }).toList(); + emit(DeviceManagementFiltered( + filteredDevices: filteredDevices, + selectedIndex: filtered.selectedIndex, + onlineCount: filtered.onlineCount, + offlineCount: filtered.offlineCount, + lowBatteryCount: filtered.lowBatteryCount, + selectedDevice: selectedDevices01, + isControlButtonEnabled: filtered.isControlButtonEnabled, + )); + } + } + + void _onUpdateSubSpaceName( + UpdateSubSpaceName event, Emitter emit) { + final devices = _devices.map((device) { + if (device.uuid == event.deviceId) { + return device.copyWith( + subspace: + device.subspace?.copyWith(subspaceName: event.newSubSpaceName)); + } + return device; + }).toList(); + + final filteredDevices = _filteredDevices.map((device) { + if (device.uuid == event.deviceId) { + return device.copyWith( + subspace: + device.subspace?.copyWith(subspaceName: event.newSubSpaceName)); + } + return device; + }).toList(); + + _devices = devices; + _filteredDevices = filteredDevices; + + if (state is DeviceManagementLoaded) { + final loaded = state as DeviceManagementLoaded; + final selectedDevices = loaded.selectedDevice?.map((device) { + if (device.uuid == event.deviceId) { + return device.copyWith( + subspace: + device.subspace?.copyWith(subspaceName: event.newSubSpaceName)); + } + return device; + }).toList(); + emit(DeviceManagementLoaded( + devices: _devices, + selectedIndex: loaded.selectedIndex, + onlineCount: loaded.onlineCount, + offlineCount: loaded.offlineCount, + lowBatteryCount: loaded.lowBatteryCount, + selectedDevice: selectedDevices, + isControlButtonEnabled: loaded.isControlButtonEnabled, + )); + } else if (state is DeviceManagementFiltered) { + // final filtered = state as DeviceManagementFiltered; + // emit(DeviceManagementFiltered( + // filteredDevices: _filteredDevices, + // selectedIndex: filtered.selectedIndex, + // onlineCount: filtered.onlineCount, + // offlineCount: filtered.offlineCount, + // lowBatteryCount: filtered.lowBatteryCount, + // selectedDevice: filtered.selectedDevice, + // isControlButtonEnabled: filtered.isControlButtonEnabled, + // )); + } + } + + void changeSubspaceName( + String deviceId, String newSubSpaceName, String subspaceId) { + add(UpdateSubSpaceName( + deviceId: deviceId, + newSubSpaceName: newSubSpaceName, + subspaceId: subspaceId, + )); + } + List get selectedDevices => _selectedDevices; } diff --git a/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_event.dart b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_event.dart index 5292de0e..e3b3acac 100644 --- a/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_event.dart +++ b/lib/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_event.dart @@ -70,3 +70,21 @@ class UpdateSelection extends DeviceManagementEvent { const UpdateSelection(this.selectedRows); } + +class UpdateDeviceName extends DeviceManagementEvent { + final String deviceId; + final String newName; + + const UpdateDeviceName({required this.deviceId, required this.newName}); +} + +class UpdateSubSpaceName extends DeviceManagementEvent { + final String deviceId; + final String newSubSpaceName; + final String subspaceId; + + const UpdateSubSpaceName( + {required this.deviceId, + required this.newSubSpaceName, + required this.subspaceId}); +} diff --git a/lib/pages/device_managment/all_devices/models/device_status.dart b/lib/pages/device_managment/all_devices/models/device_status.dart index 1f23e3f9..b0af600e 100644 --- a/lib/pages/device_managment/all_devices/models/device_status.dart +++ b/lib/pages/device_managment/all_devices/models/device_status.dart @@ -57,6 +57,16 @@ class Status { }; } + Status copyWith({ + String? code, + dynamic value, + }) { + return Status( + code: code ?? this.code, + value: value ?? this.value, + ); + } + factory Status.fromJson(String source) => Status.fromMap(json.decode(source)); String toJson() => json.encode(toMap()); diff --git a/lib/pages/device_managment/all_devices/models/device_subspace.model.dart b/lib/pages/device_managment/all_devices/models/device_subspace.model.dart index dc2386de..5d5f44bf 100644 --- a/lib/pages/device_managment/all_devices/models/device_subspace.model.dart +++ b/lib/pages/device_managment/all_devices/models/device_subspace.model.dart @@ -44,4 +44,20 @@ class DeviceSubspace { static List> listToJson(List subspaces) { return subspaces.map((subspace) => subspace.toJson()).toList(); } + + DeviceSubspace copyWith({ + String? uuid, + DateTime? createdAt, + DateTime? updatedAt, + String? subspaceName, + bool? disabled, + }) { + return DeviceSubspace( + uuid: uuid ?? this.uuid, + createdAt: createdAt ?? this.createdAt, + updatedAt: updatedAt ?? this.updatedAt, + subspaceName: subspaceName ?? this.subspaceName, + disabled: disabled ?? this.disabled, + ); + } } diff --git a/lib/pages/device_managment/all_devices/models/devices_model.dart b/lib/pages/device_managment/all_devices/models/devices_model.dart index e491214d..21fd1193 100644 --- a/lib/pages/device_managment/all_devices/models/devices_model.dart +++ b/lib/pages/device_managment/all_devices/models/devices_model.dart @@ -588,4 +588,72 @@ SOS "NCPS": DeviceType.NCPS, "PC": DeviceType.PC, }; + + AllDevicesModel copyWith({ + DevicesModelRoom? room, + DeviceSubspace? subspace, + DevicesModelUnit? unit, + DeviceCommunityModel? community, + String? productUuid, + String? productType, + String? permissionType, + int? activeTime, + String? category, + String? categoryName, + int? createTime, + String? gatewayId, + String? icon, + String? ip, + String? lat, + String? localKey, + String? lon, + String? model, + String? name, + String? nodeId, + bool? online, + String? ownerId, + bool? sub, + String? timeZone, + int? updateTime, + String? uuid, + int? batteryLevel, + String? productName, + List? spaces, + List? deviceTags, + DeviceSubSpace? deviceSubSpace, + }) { + return AllDevicesModel( + room: room ?? this.room, + subspace: subspace ?? this.subspace, + unit: unit ?? this.unit, + community: community ?? this.community, + productUuid: productUuid ?? this.productUuid, + productType: productType ?? this.productType, + permissionType: permissionType ?? this.permissionType, + activeTime: activeTime ?? this.activeTime, + category: category ?? this.category, + categoryName: categoryName ?? this.categoryName, + createTime: createTime ?? this.createTime, + gatewayId: gatewayId ?? this.gatewayId, + icon: icon ?? this.icon, + ip: ip ?? this.ip, + lat: lat ?? this.lat, + localKey: localKey ?? this.localKey, + lon: lon ?? this.lon, + model: model ?? this.model, + name: name ?? this.name, + nodeId: nodeId ?? this.nodeId, + online: online ?? this.online, + ownerId: ownerId ?? this.ownerId, + sub: sub ?? this.sub, + timeZone: timeZone ?? this.timeZone, + updateTime: updateTime ?? this.updateTime, + uuid: uuid ?? this.uuid, + batteryLevel: batteryLevel ?? this.batteryLevel, + productName: productName ?? this.productName, + spaces: spaces ?? this.spaces, + deviceTags: deviceTags ?? this.deviceTags, + deviceSubSpace: deviceSubSpace ?? this.deviceSubSpace, + ); + } } diff --git a/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart b/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart index 4f86c8e3..7ca33d1d 100644 --- a/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart +++ b/lib/pages/device_managment/all_devices/widgets/device_managment_body.dart @@ -23,6 +23,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { @override Widget build(BuildContext context) { return BlocBuilder( + buildWhen: (previous, current) => previous != current, builder: (context, state) { List devicesToShow = []; int selectedIndex = 0; @@ -31,7 +32,6 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { int lowBatteryCount = 0; bool isControlButtonEnabled = false; List selectedDevices = []; - if (state is DeviceManagementLoaded) { devicesToShow = state.devices; selectedIndex = state.selectedIndex; @@ -192,7 +192,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { 'Product Name', 'Device ID', 'Space Name', - 'location', + 'Location', 'Battery Level', 'Installation Date and Time', 'Status', @@ -244,7 +244,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { .map((device) => device.uuid!) .toList(), isEmpty: devicesToShow.isEmpty, - onSettingsPressed: (rowIndex) { + onSettingsPressed: (rowIndex) async { final device = devicesToShow[rowIndex]; showDeviceSettingsSidebar(context, device); }, @@ -266,7 +266,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { barrierDismissible: true, barrierLabel: "Device Settings", transitionDuration: const Duration(milliseconds: 300), - pageBuilder: (context, anim1, anim2) { + pageBuilder: (_, anim1, anim2) { return Align( alignment: Alignment.centerRight, child: Material( @@ -276,6 +276,7 @@ class DeviceManagementBody extends StatelessWidget with HelperResponsiveLayout { child: DeviceSettingsPanel( device: device, onClose: () => Navigator.of(context).pop(), + deviceManagementBloc: context.read(), ), ), ), diff --git a/lib/pages/device_managment/curtain_module/widgets/accurate_calibrating_dialog.dart b/lib/pages/device_managment/curtain_module/widgets/accurate_calibrating_dialog.dart index 54107420..0d3a1a92 100644 --- a/lib/pages/device_managment/curtain_module/widgets/accurate_calibrating_dialog.dart +++ b/lib/pages/device_managment/curtain_module/widgets/accurate_calibrating_dialog.dart @@ -4,6 +4,7 @@ import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_m import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/calibrate_completed_dialog.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; class AccurteCalibratingDialog extends StatelessWidget { final String deviceId; @@ -17,14 +18,15 @@ class AccurteCalibratingDialog extends StatelessWidget { @override Widget build(_) { return AlertDialog( + backgroundColor: ColorsManager.whiteColors, contentPadding: EdgeInsets.zero, content: AccurateDialogWidget( title: 'Calibrating', body: const NormalTextBodyForDialog( title: '', step1: - '1. Click Close Button to make the Curtain run to Full Close and Position.', - step2: '2. click Next to complete the Calibration.', + 'Click Close Button to make the Curtain run to Full Close and Position.', + step2: 'click Next to complete the Calibration.', ), leftOnTap: () => Navigator.of(parentContext).pop(), rightOnTap: () { diff --git a/lib/pages/device_managment/curtain_module/widgets/accurate_calibration_dialog.dart b/lib/pages/device_managment/curtain_module/widgets/accurate_calibration_dialog.dart index a9d1b010..7124639d 100644 --- a/lib/pages/device_managment/curtain_module/widgets/accurate_calibration_dialog.dart +++ b/lib/pages/device_managment/curtain_module/widgets/accurate_calibration_dialog.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_calibrating_dialog.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; class AccurateCalibrationDialog extends StatelessWidget { final String deviceId; @@ -15,13 +16,14 @@ class AccurateCalibrationDialog extends StatelessWidget { @override Widget build(_) { return AlertDialog( + backgroundColor: ColorsManager.whiteColors, contentPadding: EdgeInsets.zero, content: AccurateDialogWidget( title: 'Accurate Calibration', body: const NormalTextBodyForDialog( title: 'Prepare Calibration:', - step1: '1. Run The Curtain to the Fully Open Position,and pause.', - step2: '2. click Next to Start accurate calibration.', + step1: 'Run The Curtain to the Fully Open Position,and pause.', + step2: 'click Next to Start accurate calibration.', ), leftOnTap: () => Navigator.of(parentContext).pop(), rightOnTap: () { diff --git a/lib/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart b/lib/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart index 5be376ae..0d6ea90c 100644 --- a/lib/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart +++ b/lib/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart @@ -17,78 +17,102 @@ class AccurateDialogWidget extends StatelessWidget { @override Widget build(BuildContext context) { return SizedBox( - height: 300, - width: 400, + height: 250, + width: 500, child: Column( children: [ - Padding( - padding: const EdgeInsets.all(10), - child: Text( - title, - style: const TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: ColorsManager.blueColor, - ), + Expanded( + flex: 3, + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: Text( + title, + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: ColorsManager.dialogBlueTitle, + ), + ), + ), + const Divider( + indent: 60, + endIndent: 60, + ), + ], ), ), - const SizedBox(height: 5), - const Divider( - indent: 10, - endIndent: 10, - ), - Padding( - padding: const EdgeInsets.all(10), + Expanded( + flex: 5, child: body, ), - const SizedBox(height: 20), - const Spacer(), - const Divider(), - Row( - children: [ - Expanded( - child: InkWell( - onTap: leftOnTap, - child: Container( - height: 60, - alignment: Alignment.center, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - color: ColorsManager.grayBorder, + Expanded( + flex: 2, + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const Expanded(child: Divider()), + Row( + children: [ + Expanded( + child: InkWell( + borderRadius: const BorderRadius.only( + bottomLeft: Radius.circular(26), + ), + onTap: leftOnTap, + child: Container( + height: 40, + alignment: Alignment.center, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + color: ColorsManager.grayBorder, + ), + ), + borderRadius: BorderRadius.only( + bottomLeft: Radius.circular(26), + ), + ), + child: const Text( + 'Cancel', + style: TextStyle(color: ColorsManager.grayBorder), + ), ), ), ), - child: const Text( - 'Cancel', - style: TextStyle(color: ColorsManager.grayBorder), - ), - ), - ), - ), - Expanded( - child: InkWell( - onTap: rightOnTap, - child: Container( - height: 60, - alignment: Alignment.center, - decoration: const BoxDecoration( - border: Border( - right: BorderSide( - color: ColorsManager.grayBorder, + Expanded( + child: InkWell( + borderRadius: const BorderRadius.only( + bottomRight: Radius.circular(26), + ), + onTap: rightOnTap, + child: Container( + height: 40, + alignment: Alignment.center, + decoration: const BoxDecoration( + border: Border( + right: BorderSide( + color: ColorsManager.grayBorder, + ), + ), + borderRadius: BorderRadius.only( + bottomRight: Radius.circular(26), + ), + ), + child: const Text( + 'Next', + style: TextStyle( + color: ColorsManager.blueColor, + ), + ), ), ), - ), - child: const Text( - 'Next', - style: TextStyle( - color: ColorsManager.blueColor, - ), - ), - ), - ), - ) - ], + ) + ], + ) + ], + ), ) ], ), diff --git a/lib/pages/device_managment/curtain_module/widgets/calibrate_completed_dialog.dart b/lib/pages/device_managment/curtain_module/widgets/calibrate_completed_dialog.dart index 9b2b5ea9..bd0cbb37 100644 --- a/lib/pages/device_managment/curtain_module/widgets/calibrate_completed_dialog.dart +++ b/lib/pages/device_managment/curtain_module/widgets/calibrate_completed_dialog.dart @@ -1,7 +1,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/bloc/curtain_module_bloc.dart'; import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; class CalibrateCompletedDialog extends StatelessWidget { final BuildContext parentContext; @@ -21,52 +23,62 @@ class CalibrateCompletedDialog extends StatelessWidget { width: 400, child: Column( children: [ - const Padding( - padding: EdgeInsets.all(10), - child: Text( - 'Calibration Completed', - style: TextStyle( - fontSize: 24, - fontWeight: FontWeight.bold, - color: ColorsManager.blueColor, - ), + Expanded( + child: Column( + children: [ + Padding( + padding: const EdgeInsets.all(10), + child: Text( + 'Calibration Completed', + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: ColorsManager.dialogBlueTitle, + ), + ), + ), + const SizedBox(height: 5), + const Divider( + indent: 10, + endIndent: 10, + ), + ], ), ), - const SizedBox(height: 5), - const Divider( - indent: 10, - endIndent: 10, + Expanded( + child: SvgPicture.asset(Assets.completedDoneIcon), ), - const Icon( - Icons.check_circle, - size: 100, - color: ColorsManager.blueColor, - ), - const Spacer(), - const Divider( - indent: 10, - endIndent: 10, - ), - InkWell( - onTap: () { - parentContext.read().add( - FetchCurtainModuleStatusEvent( - deviceId: deviceId, - ), - ); - Navigator.of(parentContext).pop(); - Navigator.of(parentContext).pop(); - }, - child: Container( - height: 40, - width: double.infinity, - alignment: Alignment.center, - child: const Text( - 'Close', - style: TextStyle( - color: ColorsManager.grayBorder, + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + const Divider( + indent: 10, + endIndent: 10, ), - ), + InkWell( + onTap: () { + parentContext.read().add( + FetchCurtainModuleStatusEvent( + deviceId: deviceId, + ), + ); + Navigator.of(parentContext).pop(); + Navigator.of(parentContext).pop(); + }, + child: Container( + height: 40, + width: double.infinity, + alignment: Alignment.center, + child: const Text( + 'Close', + style: TextStyle( + color: ColorsManager.grayBorder, + ), + ), + ), + ) + ], ), ) ], diff --git a/lib/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart b/lib/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart index 8818cb7b..fa293ec6 100644 --- a/lib/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart +++ b/lib/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart @@ -15,28 +15,72 @@ class NormalTextBodyForDialog extends StatelessWidget { @override Widget build(BuildContext context) { - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - title, - style: const TextStyle( - color: ColorsManager.grayColor, + return Padding( + padding: EdgeInsetsGeometry.only(left: 15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (title.isEmpty) + const SizedBox() + else + Expanded( + child: Text( + title, + style: const TextStyle( + color: ColorsManager.grayColor, + fontSize: 15, + ), + ), + ), + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + width: 10, + ), + const Text('1. ', + style: TextStyle( + color: ColorsManager.grayColor, + fontSize: 15, + )), + SizedBox( + width: 450, + child: Text( + step1, + style: const TextStyle( + color: ColorsManager.grayColor, + fontSize: 15, + ), + ), + ), + ], + ), ), - ), - Text( - step1, - style: const TextStyle( - color: ColorsManager.grayColor, - ), - ), - Text( - step2, - style: const TextStyle( - color: ColorsManager.grayColor, - ), - ) - ], + Expanded( + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + width: 10, + ), + const Text('2. ', + style: TextStyle( + color: ColorsManager.grayColor, + fontSize: 15, + )), + Text( + step2, + style: const TextStyle( + color: ColorsManager.grayColor, + fontSize: 15, + ), + ), + ], + ), + ) + ], + ), ); } } diff --git a/lib/pages/device_managment/curtain_module/widgets/number_input_textfield.dart b/lib/pages/device_managment/curtain_module/widgets/number_input_textfield.dart index ea95f838..428f6531 100644 --- a/lib/pages/device_managment/curtain_module/widgets/number_input_textfield.dart +++ b/lib/pages/device_managment/curtain_module/widgets/number_input_textfield.dart @@ -19,7 +19,7 @@ class NumberInputField extends StatelessWidget { contentPadding: EdgeInsets.zero, ), style: const TextStyle( - fontSize: 20, + fontSize: 15, color: ColorsManager.blackColor, ), ); diff --git a/lib/pages/device_managment/curtain_module/widgets/pref_revers_card_widget.dart b/lib/pages/device_managment/curtain_module/widgets/pref_revers_card_widget.dart index 81912e80..85c45d27 100644 --- a/lib/pages/device_managment/curtain_module/widgets/pref_revers_card_widget.dart +++ b/lib/pages/device_managment/curtain_module/widgets/pref_revers_card_widget.dart @@ -18,7 +18,7 @@ class PrefReversCardWidget extends StatelessWidget { @override Widget build(BuildContext context) { return DefaultContainer( - padding: const EdgeInsets.all(12), + padding: const EdgeInsets.all(18), child: Column( crossAxisAlignment: CrossAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.spaceBetween, diff --git a/lib/pages/device_managment/curtain_module/widgets/prefrences_dialog.dart b/lib/pages/device_managment/curtain_module/widgets/prefrences_dialog.dart index 1e4f932c..35844c05 100644 --- a/lib/pages/device_managment/curtain_module/widgets/prefrences_dialog.dart +++ b/lib/pages/device_managment/curtain_module/widgets/prefrences_dialog.dart @@ -23,12 +23,12 @@ class CurtainModulePrefrencesDialog extends StatelessWidget { Widget build(_) { return AlertDialog( backgroundColor: ColorsManager.CircleImageBackground, - contentPadding: const EdgeInsets.all(30), - title: const Center( + contentPadding: const EdgeInsets.all(20), + title: Center( child: Text( 'Preferences', style: TextStyle( - color: ColorsManager.blueColor, + color: ColorsManager.dialogBlueTitle, fontSize: 24, fontWeight: FontWeight.bold, ), diff --git a/lib/pages/device_managment/curtain_module/widgets/quick_calibrating_dialog.dart b/lib/pages/device_managment/curtain_module/widgets/quick_calibrating_dialog.dart index 0b86c96e..6fc9adf2 100644 --- a/lib/pages/device_managment/curtain_module/widgets/quick_calibrating_dialog.dart +++ b/lib/pages/device_managment/curtain_module/widgets/quick_calibrating_dialog.dart @@ -63,55 +63,82 @@ class _QuickCalibratingDialogState extends State { @override Widget build(_) { return AlertDialog( + backgroundColor: ColorsManager.whiteColors, contentPadding: EdgeInsets.zero, content: AccurateDialogWidget( title: 'Calibrating', body: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ - const Text( - '1. please Enter the Travel Time:', - style: TextStyle(color: ColorsManager.grayBorder), - ), - const SizedBox(height: 10), - Container( - width: 150, - height: 40, - padding: const EdgeInsets.all(5), - decoration: BoxDecoration( - color: ColorsManager.whiteColors, - borderRadius: BorderRadius.circular(12), - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Expanded( - child: NumberInputField(controller: _controller), - ), - const Expanded( - child: Text( - 'seconds', - style: TextStyle( - fontSize: 15, - color: ColorsManager.blueColor, - fontWeight: FontWeight.bold, - ), - ), - ), - ], - ), - ), - if (_errorText != null) - Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text( - _errorText!, - style: const TextStyle( - color: ColorsManager.red, - fontSize: 14, + const Expanded( + child: Align( + alignment: Alignment.topCenter, + child: Padding( + padding: EdgeInsets.only(right: 75), + child: Text( + '1.please Enter the Travel Time:', + style: TextStyle(color: ColorsManager.lightGrayColor), ), ), ), + ), + Expanded( + child: Align( + alignment: Alignment.center, + child: Container( + width: 130, + padding: const EdgeInsets.all(5), + decoration: BoxDecoration( + color: ColorsManager.neutralGray.withValues( + alpha: 0.5, + ), + borderRadius: BorderRadius.circular(12), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Expanded( + child: Padding( + padding: const EdgeInsetsGeometry.only(left: 5), + child: NumberInputField(controller: _controller)), + ), + Expanded( + child: Text( + 'seconds', + style: TextStyle( + fontSize: 12, + color: ColorsManager.dialogBlueTitle, + fontWeight: FontWeight.bold, + ), + ), + ), + ], + ), + ), + ), + ), + if (_errorText != null) + Expanded( + child: Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Text( + _errorText!, + style: const TextStyle( + color: ColorsManager.red, + fontSize: 14, + ), + ), + ), + ), + const Expanded( + child: Align( + alignment: Alignment.bottomCenter, + child: Text( + '2.click Next to Complete the calibration', + style: TextStyle(color: ColorsManager.lightGrayColor), + ), + ), + ) ], ), leftOnTap: () => Navigator.of(widget.parentContext).pop(), diff --git a/lib/pages/device_managment/curtain_module/widgets/quick_calibration_dialog.dart b/lib/pages/device_managment/curtain_module/widgets/quick_calibration_dialog.dart index 803d904f..06b386c8 100644 --- a/lib/pages/device_managment/curtain_module/widgets/quick_calibration_dialog.dart +++ b/lib/pages/device_managment/curtain_module/widgets/quick_calibration_dialog.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/accurate_dialog_widget.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/normal_text_body_for_dialog.dart'; import 'package:syncrow_web/pages/device_managment/curtain_module/widgets/quick_calibrating_dialog.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; class QuickCalibrationDialog extends StatelessWidget { final int timControl; @@ -17,14 +18,15 @@ class QuickCalibrationDialog extends StatelessWidget { @override Widget build(_) { return AlertDialog( + backgroundColor: ColorsManager.whiteColors, contentPadding: EdgeInsets.zero, content: AccurateDialogWidget( title: 'Quick Calibration', body: const NormalTextBodyForDialog( title: 'Prepare Calibration:', step1: - '1. Confirm that the curtain is in the fully closed and suspended state.', - step2: '2. click Next to Start calibration.', + 'Confirm that the curtain is in the fully closed and suspended state.', + step2: 'click Next to Start calibration.', ), leftOnTap: () => Navigator.of(parentContext).pop(), rightOnTap: () { diff --git a/lib/pages/device_managment/device_setting/device_management_content.dart b/lib/pages/device_managment/device_setting/device_management_content.dart index a087e5bb..c73899fc 100644 --- a/lib/pages/device_managment/device_setting/device_management_content.dart +++ b/lib/pages/device_managment/device_setting/device_management_content.dart @@ -19,11 +19,14 @@ class DeviceManagementContent extends StatelessWidget { required this.device, required this.subSpaces, required this.deviceInfo, + required this.deviceManagementBloc, }); final AllDevicesModel device; final List subSpaces; final DeviceInfoModel deviceInfo; + final DeviceManagementBloc deviceManagementBloc; + @override Widget build(BuildContext context) { @@ -87,6 +90,11 @@ class DeviceManagementContent extends StatelessWidget { ), ); }); + + deviceManagementBloc.add(UpdateSubSpaceName( + subspaceId: selectedSubSpace.id!, + deviceId: device.uuid!, + newSubSpaceName: selectedSubSpace.name ?? '')); } }, child: infoRow( diff --git a/lib/pages/device_managment/device_setting/device_settings_panel.dart b/lib/pages/device_managment/device_setting/device_settings_panel.dart index 48458b3b..0856b5d0 100644 --- a/lib/pages/device_managment/device_setting/device_settings_panel.dart +++ b/lib/pages/device_managment/device_setting/device_settings_panel.dart @@ -1,13 +1,15 @@ import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; +import 'package:syncrow_web/pages/device_managment/all_devices/bloc/device_mgmt_bloc/device_managment_bloc.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; +import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_state.dart'; import 'package:syncrow_web/pages/device_managment/device_setting/device_icon_type_helper.dart'; import 'package:syncrow_web/pages/device_managment/device_setting/device_management_content.dart'; import 'package:syncrow_web/pages/device_managment/device_setting/remove_device_widget.dart'; import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/device_info_model.dart'; -import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_bloc.dart'; -import 'package:syncrow_web/pages/device_managment/device_setting/bloc/setting_bloc_state.dart'; import 'package:syncrow_web/pages/device_managment/device_setting/settings_model/sub_space_model.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; @@ -17,7 +19,13 @@ import 'package:syncrow_web/web_layout/default_container.dart'; class DeviceSettingsPanel extends StatelessWidget { final VoidCallback? onClose; final AllDevicesModel device; - const DeviceSettingsPanel({super.key, this.onClose, required this.device}); + final DeviceManagementBloc deviceManagementBloc; + const DeviceSettingsPanel({ + super.key, + this.onClose, + required this.device, + required this.deviceManagementBloc, + }); @override Widget build(BuildContext context) { @@ -71,10 +79,10 @@ class DeviceSettingsPanel extends StatelessWidget { 'Device Settings', style: context.theme.textTheme.titleLarge! .copyWith( - fontWeight: FontWeight.w700, + fontWeight: FontWeight.w700, color: ColorsManager.vividBlue .withOpacity(0.7), - fontSize: 24), + fontSize: 24), ), ], ), @@ -134,8 +142,14 @@ class DeviceSettingsPanel extends StatelessWidget { onFieldSubmitted: (value) { _bloc.add(const ChangeNameEvent( value: false)); + deviceManagementBloc + ..add(UpdateDeviceName( + deviceId: device.uuid!, + newName: _bloc + .nameController + .text))..add(ResetSelectedDevices()); }, - decoration: InputDecoration( + decoration:const InputDecoration( isDense: true, contentPadding: EdgeInsets.zero, border: InputBorder.none, @@ -157,7 +171,7 @@ class DeviceSettingsPanel extends StatelessWidget { onTap: () { _bloc.add( const ChangeNameEvent( - value: true)); + value: true)); }, child: SvgPicture.asset( Assets @@ -190,6 +204,7 @@ class DeviceSettingsPanel extends StatelessWidget { device: device, subSpaces: subSpaces.cast(), deviceInfo: deviceInfo, + deviceManagementBloc: deviceManagementBloc, ), const SizedBox(height: 32), RemoveDeviceWidget(bloc: _bloc), diff --git a/lib/pages/device_managment/one_g_glass_switch/bloc/one_gang_glass_switch_bloc.dart b/lib/pages/device_managment/one_g_glass_switch/bloc/one_gang_glass_switch_bloc.dart index c1e976ab..bb6f8e29 100644 --- a/lib/pages/device_managment/one_g_glass_switch/bloc/one_gang_glass_switch_bloc.dart +++ b/lib/pages/device_managment/one_g_glass_switch/bloc/one_gang_glass_switch_bloc.dart @@ -40,7 +40,7 @@ class OneGangGlassSwitchBloc emit(OneGangGlassSwitchLoading()); try { final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); - _listenToChanges(event.deviceId, emit); + _listenToChanges(event.deviceId); deviceStatus = OneGangGlassStatusModel.fromJson(event.deviceId, status.status); emit(OneGangGlassSwitchStatusLoaded(deviceStatus)); } catch (e) { @@ -48,42 +48,28 @@ class OneGangGlassSwitchBloc } } - void _listenToChanges( - String deviceId, - Emitter emit, - ) { + StreamSubscription? _deviceStatusSubscription; + + void _listenToChanges(String deviceId) { try { final ref = FirebaseDatabase.instance.ref('device-status/$deviceId'); - final stream = ref.onValue; + _deviceStatusSubscription = ref.onValue.listen((DatabaseEvent event) async { + if (event.snapshot.value == null) return; - stream.listen((DatabaseEvent event) { - final data = event.snapshot.value as Map?; - if (data == null) return; + final usersMap = event.snapshot.value! as Map; final statusList = []; - if (data['status'] != null) { - for (var element in data['status']) { - statusList.add( - Status( - code: element['code'].toString(), - value: element['value'].toString(), - ), - ); - } - } - if (statusList.isNotEmpty) { - final newStatus = OneGangGlassStatusModel.fromJson(deviceId, statusList); - if (newStatus != deviceStatus) { - deviceStatus = newStatus; - if (!isClosed) { - add(StatusUpdated(deviceStatus)); - } - } - } + + usersMap['status'].forEach((element) { + statusList.add(Status(code: element['code'], value: element['value'])); + }); + + deviceStatus = + OneGangGlassStatusModel.fromJson(usersMap['productUuid'], statusList); + + add(StatusUpdated(deviceStatus)); }); - } catch (e) { - emit(OneGangGlassSwitchError('Failed to listen to changes: $e')); - } + } catch (_) {} } void _onStatusUpdated( @@ -174,4 +160,10 @@ class OneGangGlassSwitchBloc deviceStatus = deviceStatus.copyWith(switch1: value); } } + + @override + Future close() { + _deviceStatusSubscription?.cancel(); + return super.close(); + } } diff --git a/lib/pages/device_managment/schedule_device/bloc/schedule_bloc.dart b/lib/pages/device_managment/schedule_device/bloc/schedule_bloc.dart index 65773590..61896a74 100644 --- a/lib/pages/device_managment/schedule_device/bloc/schedule_bloc.dart +++ b/lib/pages/device_managment/schedule_device/bloc/schedule_bloc.dart @@ -298,6 +298,15 @@ class ScheduleBloc extends Bloc { } final dateTime = DateTime.parse(event.time); + Status status = Status(code: '', value: ''); + if (event.category == 'CUR_2') { + status = status.copyWith( + code: 'control', + value: event.functionOn == true ? 'open' : 'close'); + } else { + status = + status.copyWith(code: event.category, value: event.functionOn); + } final updatedSchedule = ScheduleEntry( scheduleId: event.scheduleId, category: event.category, diff --git a/lib/pages/device_managment/schedule_device/schedule_widgets/schedule_table.dart b/lib/pages/device_managment/schedule_device/schedule_widgets/schedule_table.dart index 886a6f73..c1771c1b 100644 --- a/lib/pages/device_managment/schedule_device/schedule_widgets/schedule_table.dart +++ b/lib/pages/device_managment/schedule_device/schedule_widgets/schedule_table.dart @@ -220,7 +220,6 @@ class _ScheduleTableView extends StatelessWidget { } else { temp = updatedSchedule.function.value; } - print('deviceType $deviceType'); context.read().add( ScheduleEditEvent( deviceType: deviceType, diff --git a/lib/pages/device_managment/three_g_glass_switch/bloc/three_gang_glass_switch_bloc.dart b/lib/pages/device_managment/three_g_glass_switch/bloc/three_gang_glass_switch_bloc.dart index 766c3163..4a122345 100644 --- a/lib/pages/device_managment/three_g_glass_switch/bloc/three_gang_glass_switch_bloc.dart +++ b/lib/pages/device_managment/three_g_glass_switch/bloc/three_gang_glass_switch_bloc.dart @@ -41,7 +41,7 @@ class ThreeGangGlassSwitchBloc emit(ThreeGangGlassSwitchLoading()); try { final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); - _listenToChanges(event.deviceId, emit); + _listenToChanges(event.deviceId); deviceStatus = ThreeGangGlassStatusModel.fromJson(event.deviceId, status.status); emit(ThreeGangGlassSwitchStatusLoaded(deviceStatus)); @@ -50,42 +50,28 @@ class ThreeGangGlassSwitchBloc } } - void _listenToChanges( - String deviceId, - Emitter emit, - ) { + StreamSubscription? _deviceStatusSubscription; + + void _listenToChanges(String deviceId) { try { final ref = FirebaseDatabase.instance.ref('device-status/$deviceId'); - final stream = ref.onValue; + _deviceStatusSubscription = ref.onValue.listen((DatabaseEvent event) async { + if (event.snapshot.value == null) return; - stream.listen((DatabaseEvent event) { - final data = event.snapshot.value as Map?; - if (data == null) return; + final usersMap = event.snapshot.value! as Map; final statusList = []; - if (data['status'] != null) { - for (var element in data['status']) { - statusList.add( - Status( - code: element['code'].toString(), - value: element['value'].toString(), - ), - ); - } - } - if (statusList.isNotEmpty) { - final newStatus = ThreeGangGlassStatusModel.fromJson(deviceId, statusList); - if (newStatus != deviceStatus) { - deviceStatus = newStatus; - if (!isClosed) { - add(StatusUpdated(deviceStatus)); - } - } - } + + usersMap['status'].forEach((element) { + statusList.add(Status(code: element['code'], value: element['value'])); + }); + + deviceStatus = + ThreeGangGlassStatusModel.fromJson(usersMap['productUuid'], statusList); + + add(StatusUpdated(deviceStatus)); }); - } catch (e) { - emit(ThreeGangGlassSwitchError('Failed to listen to changes: $e')); - } + } catch (_) {} } void _onStatusUpdated( @@ -184,4 +170,10 @@ class ThreeGangGlassSwitchBloc break; } } + + @override + Future close() { + _deviceStatusSubscription?.cancel(); + return super.close(); + } } diff --git a/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart b/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart index 8f82c198..08b40362 100644 --- a/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart +++ b/lib/pages/device_managment/two_g_glass_switch/bloc/two_gang_glass_switch_bloc.dart @@ -1,173 +1,177 @@ -import 'dart:async'; -import 'dart:developer'; + import 'dart:async'; -import 'package:bloc/bloc.dart'; -import 'package:equatable/equatable.dart'; -import 'package:firebase_database/firebase_database.dart'; -import 'package:flutter/foundation.dart'; -import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; -import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; -import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart'; -import 'package:syncrow_web/services/batch_control_devices_service.dart'; -import 'package:syncrow_web/services/control_device_service.dart'; -import 'package:syncrow_web/services/devices_mang_api.dart'; + import 'package:bloc/bloc.dart'; + import 'package:equatable/equatable.dart'; + import 'package:firebase_database/firebase_database.dart'; + import 'package:flutter/foundation.dart'; + import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart'; + import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart'; + import 'package:syncrow_web/pages/device_managment/two_g_glass_switch/models/two_gang_glass_status_model.dart'; + import 'package:syncrow_web/services/batch_control_devices_service.dart'; + import 'package:syncrow_web/services/control_device_service.dart'; + import 'package:syncrow_web/services/devices_mang_api.dart'; -part 'two_gang_glass_switch_event.dart'; -part 'two_gang_glass_switch_state.dart'; + part 'two_gang_glass_switch_event.dart'; + part 'two_gang_glass_switch_state.dart'; -class TwoGangGlassSwitchBloc - extends Bloc { - final String deviceId; - final ControlDeviceService controlDeviceService; - final BatchControlDevicesService batchControlDevicesService; + class TwoGangGlassSwitchBloc + extends Bloc { + final String deviceId; + final ControlDeviceService controlDeviceService; + final BatchControlDevicesService batchControlDevicesService; - late TwoGangGlassStatusModel deviceStatus; + late TwoGangGlassStatusModel deviceStatus; - TwoGangGlassSwitchBloc({ - required this.deviceId, - required this.controlDeviceService, - required this.batchControlDevicesService, - }) : super(TwoGangGlassSwitchInitial()) { - on(_onFetchDeviceStatus); - on(_onControl); - on(_onBatchControl); - on(_onFetchBatchStatus); - on(_onFactoryReset); - on(_onStatusUpdated); - } - - Future _onFetchDeviceStatus( - TwoGangGlassSwitchFetchDeviceEvent event, - Emitter emit, - ) async { - emit(TwoGangGlassSwitchLoading()); - try { - final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); - deviceStatus = TwoGangGlassStatusModel.fromJson(event.deviceId, status.status); - _listenToChanges(event.deviceId); - emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); - } catch (e) { - emit(TwoGangGlassSwitchError(e.toString())); + TwoGangGlassSwitchBloc({ + required this.deviceId, + required this.controlDeviceService, + required this.batchControlDevicesService, + }) : super(TwoGangGlassSwitchInitial()) { + on(_onFetchDeviceStatus); + on(_onControl); + on(_onBatchControl); + on(_onFetchBatchStatus); + on(_onFactoryReset); + on(_onStatusUpdated); } - } - void _listenToChanges(String deviceId) { - try { - final ref = FirebaseDatabase.instance.ref( - 'device-status/$deviceId', - ); - - ref.onValue.listen((event) { - final eventsMap = event.snapshot.value as Map; - - List statusList = []; - eventsMap['status'].forEach((element) { - statusList.add(Status(code: element['code'], value: element['value'])); - }); - - deviceStatus = TwoGangGlassStatusModel.fromJson(deviceId, statusList); - add(StatusUpdated(deviceStatus)); - }); - } catch (_) { - log( - 'Error listening to changes', - name: 'TwoGangGlassSwitchBloc._listenToChanges', - ); - } - } - - Future _onControl( - TwoGangGlassSwitchControl event, - Emitter emit, - ) async { - emit(TwoGangGlassSwitchLoading()); - _updateLocalValue(event.code, event.value); - emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); - - try { - await controlDeviceService.controlDevice( - deviceUuid: event.deviceId, - status: Status(code: event.code, value: event.value), - ); - } catch (e) { - _updateLocalValue(event.code, !event.value); - emit(TwoGangGlassSwitchError(e.toString())); - } - } - - Future _onBatchControl( - TwoGangGlassSwitchBatchControl event, - Emitter emit, - ) async { - emit(TwoGangGlassSwitchLoading()); - _updateLocalValue(event.code, event.value); - emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus)); - - try { - await batchControlDevicesService.batchControlDevices( - uuids: event.deviceIds, - code: event.code, - value: event.value, - ); - } catch (e) { - _updateLocalValue(event.code, !event.value); - emit(TwoGangGlassSwitchError(e.toString())); - } - } - - Future _onFetchBatchStatus( - TwoGangGlassSwitchFetchBatchStatusEvent event, - Emitter emit, - ) async { - emit(TwoGangGlassSwitchLoading()); - try { - final status = await DevicesManagementApi().getBatchStatus(event.deviceIds); - deviceStatus = TwoGangGlassStatusModel.fromJson( - event.deviceIds.first, - status.status, - ); - emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus)); - } catch (e) { - emit(TwoGangGlassSwitchError(e.toString())); - } - } - - Future _onFactoryReset( - TwoGangGlassFactoryReset event, - Emitter emit, - ) async { - emit(TwoGangGlassSwitchLoading()); - try { - final response = await DevicesManagementApi().factoryReset( - event.factoryReset, - event.deviceId, - ); - if (!response) { - emit(TwoGangGlassSwitchError('Failed to reset device')); - } else { - add(TwoGangGlassSwitchFetchDeviceEvent(event.deviceId)); + Future _onFetchDeviceStatus( + TwoGangGlassSwitchFetchDeviceEvent event, + Emitter emit, + ) async { + emit(TwoGangGlassSwitchLoading()); + try { + final status = await DevicesManagementApi().getDeviceStatus(event.deviceId); + deviceStatus = TwoGangGlassStatusModel.fromJson(event.deviceId, status.status); + _listenToChanges(event.deviceId); + emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); + } catch (e) { + emit(TwoGangGlassSwitchError(e.toString())); } - } catch (e) { - emit(TwoGangGlassSwitchError(e.toString())); } - } - void _onStatusUpdated( - StatusUpdated event, - Emitter emit, - ) { - deviceStatus = event.deviceStatus; - emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); - } + StreamSubscription? _deviceStatusSubscription; - void _updateLocalValue(String code, bool value) { - switch (code) { - case 'switch_1': - deviceStatus = deviceStatus.copyWith(switch1: value); - break; - case 'switch_2': - deviceStatus = deviceStatus.copyWith(switch2: value); - break; + void _listenToChanges(String deviceId) { + try { + final ref = FirebaseDatabase.instance.ref('device-status/$deviceId'); + _deviceStatusSubscription = ref.onValue.listen((DatabaseEvent event) async { + if (event.snapshot.value == null) return; + + final usersMap = event.snapshot.value! as Map; + + final statusList = []; + + usersMap['status'].forEach((element) { + statusList.add(Status(code: element['code'], value: element['value'])); + }); + + deviceStatus = + TwoGangGlassStatusModel.fromJson(usersMap['productUuid'], statusList); + + add(StatusUpdated(deviceStatus)); + }); + } catch (_) {} } + + Future _onControl( + TwoGangGlassSwitchControl event, + Emitter emit, + ) async { + emit(TwoGangGlassSwitchLoading()); + _updateLocalValue(event.code, event.value); + emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); + + try { + await controlDeviceService.controlDevice( + deviceUuid: event.deviceId, + status: Status(code: event.code, value: event.value), + ); + } catch (e) { + _updateLocalValue(event.code, !event.value); + emit(TwoGangGlassSwitchError(e.toString())); + } + } + + Future _onBatchControl( + TwoGangGlassSwitchBatchControl event, + Emitter emit, + ) async { + emit(TwoGangGlassSwitchLoading()); + _updateLocalValue(event.code, event.value); + emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus)); + + try { + await batchControlDevicesService.batchControlDevices( + uuids: event.deviceIds, + code: event.code, + value: event.value, + ); + } catch (e) { + _updateLocalValue(event.code, !event.value); + emit(TwoGangGlassSwitchError(e.toString())); + } + } + + Future _onFetchBatchStatus( + TwoGangGlassSwitchFetchBatchStatusEvent event, + Emitter emit, + ) async { + emit(TwoGangGlassSwitchLoading()); + try { + final status = await DevicesManagementApi().getBatchStatus(event.deviceIds); + deviceStatus = TwoGangGlassStatusModel.fromJson( + event.deviceIds.first, + status.status, + ); + emit(TwoGangGlassSwitchBatchStatusLoaded(deviceStatus)); + } catch (e) { + emit(TwoGangGlassSwitchError(e.toString())); + } + } + + Future _onFactoryReset( + TwoGangGlassFactoryReset event, + Emitter emit, + ) async { + emit(TwoGangGlassSwitchLoading()); + try { + final response = await DevicesManagementApi().factoryReset( + event.factoryReset, + event.deviceId, + ); + if (!response) { + emit(TwoGangGlassSwitchError('Failed to reset device')); + } else { + add(TwoGangGlassSwitchFetchDeviceEvent(event.deviceId)); + } + } catch (e) { + emit(TwoGangGlassSwitchError(e.toString())); + } + } + + void _onStatusUpdated( + StatusUpdated event, + Emitter emit, + ) { + deviceStatus = event.deviceStatus; + emit(TwoGangGlassSwitchStatusLoaded(deviceStatus)); + } + + void _updateLocalValue(String code, bool value) { + switch (code) { + case 'switch_1': + deviceStatus = deviceStatus.copyWith(switch1: value); + break; + case 'switch_2': + deviceStatus = deviceStatus.copyWith(switch2: value); + break; + } + } + + @override + Future close() { + _deviceStatusSubscription?.cancel(); + return super.close(); } } diff --git a/lib/pages/device_managment/water_heater/helper/add_schedule_dialog_helper.dart b/lib/pages/device_managment/water_heater/helper/add_schedule_dialog_helper.dart index e483e7c1..0a65595e 100644 --- a/lib/pages/device_managment/water_heater/helper/add_schedule_dialog_helper.dart +++ b/lib/pages/device_managment/water_heater/helper/add_schedule_dialog_helper.dart @@ -135,7 +135,6 @@ class ScheduleDialogHelper { function: Status( code: code ?? 'switch_1', value: temp, - ), days: _convertSelectedDaysToStrings(selectedDays), scheduleId: schedule.scheduleId, diff --git a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart index f38ea994..3fd07834 100644 --- a/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart +++ b/lib/pages/routines/bloc/routine_bloc/routine_bloc.dart @@ -170,45 +170,45 @@ class RoutineBloc extends Bloc { } } - Future _onLoadScenes( - LoadScenes event, Emitter emit) async { - emit(state.copyWith(isLoading: true, errorMessage: null)); - List scenes = []; - try { - BuildContext context = NavigationService.navigatorKey.currentContext!; - var createRoutineBloc = context.read(); - final projectUuid = await ProjectManager.getProjectUUID() ?? ''; - if (createRoutineBloc.selectedSpaceId == '' && - createRoutineBloc.selectedCommunityId == '') { - var spaceBloc = context.read(); - for (var communityId in spaceBloc.state.selectedCommunities) { - List spacesList = - spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; - for (var spaceId in spacesList) { - scenes.addAll( - await SceneApi.getScenes(spaceId, communityId, projectUuid)); - } +Future _onLoadScenes( + LoadScenes event, Emitter emit) async { + emit(state.copyWith(isLoading: true, errorMessage: null)); + List scenes = []; + try { + BuildContext context = NavigationService.navigatorKey.currentContext!; + var createRoutineBloc = context.read(); + final projectUuid = await ProjectManager.getProjectUUID() ?? ''; + if (createRoutineBloc.selectedSpaceId == '' && + createRoutineBloc.selectedCommunityId == '') { + var spaceBloc = context.read(); + for (var communityId in spaceBloc.state.selectedCommunities) { + List spacesList = + spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; + for (var spaceId in spacesList) { + scenes.addAll( + await SceneApi.getScenes(spaceId, communityId, projectUuid)); } - } else { - scenes.addAll(await SceneApi.getScenes( - createRoutineBloc.selectedSpaceId, - createRoutineBloc.selectedCommunityId, - projectUuid)); } - - emit(state.copyWith( - scenes: scenes, - isLoading: false, - )); - } catch (e) { - emit(state.copyWith( - isLoading: false, - loadScenesErrorMessage: 'Failed to load scenes', - errorMessage: '', - loadAutomationErrorMessage: '', - scenes: scenes)); + } else { + scenes.addAll(await SceneApi.getScenes( + createRoutineBloc.selectedSpaceId, + createRoutineBloc.selectedCommunityId, + projectUuid)); } + + emit(state.copyWith( + scenes: scenes, + isLoading: false, + )); + } catch (e) { + emit(state.copyWith( + isLoading: false, + loadScenesErrorMessage: 'Failed to load scenes', + errorMessage: '', + loadAutomationErrorMessage: '', + scenes: scenes)); } +} Future _onLoadAutomation( LoadAutomation event, Emitter emit) async { @@ -936,12 +936,16 @@ class RoutineBloc extends Bloc { for (var communityId in spaceBloc.state.selectedCommunities) { List spacesList = spaceBloc.state.selectedCommunityAndSpaces[communityId] ?? []; - devices.addAll(await DevicesManagementApi() - .fetchDevices(projectUuid, spacesId: spacesList)); + for (var spaceId in spacesList) { + devices.addAll(await DevicesManagementApi() + .fetchDevices(communityId, spaceId, projectUuid)); + } } } else { - devices.addAll(await DevicesManagementApi().fetchDevices(projectUuid, - spacesId: [createRoutineBloc.selectedSpaceId])); + devices.addAll(await DevicesManagementApi().fetchDevices( + createRoutineBloc.selectedCommunityId, + createRoutineBloc.selectedSpaceId, + projectUuid)); } emit(state.copyWith(isLoading: false, devices: devices)); diff --git a/lib/pages/routines/widgets/routine_dialogs/curtain_dialog.dart b/lib/pages/routines/widgets/routine_dialogs/curtain_dialog.dart index bdf8660d..64295e2a 100644 --- a/lib/pages/routines/widgets/routine_dialogs/curtain_dialog.dart +++ b/lib/pages/routines/widgets/routine_dialogs/curtain_dialog.dart @@ -58,7 +58,9 @@ class CurtainHelper { child: Column( mainAxisSize: MainAxisSize.min, children: [ - const DialogHeader('AC Functions'), + DialogHeader(dialogType == 'THEN' + ? 'Curtain Functions' + : 'Curtain Conditions'), Expanded( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, diff --git a/lib/pages/spaces_management/all_spaces/model/product_model.dart b/lib/pages/spaces_management/all_spaces/model/product_model.dart index 8f905032..a7b23d0f 100644 --- a/lib/pages/spaces_management/all_spaces/model/product_model.dart +++ b/lib/pages/spaces_management/all_spaces/model/product_model.dart @@ -58,11 +58,14 @@ class ProductModel { '3G': Assets.Gang3SwitchIcon, '3GT': Assets.threeTouchSwitch, 'CUR': Assets.curtain, + 'CUR_2': Assets.curtain, 'GD': Assets.garageDoor, 'GW': Assets.SmartGatewayIcon, 'DL': Assets.DoorLockIcon, 'WL': Assets.waterLeakSensor, 'WH': Assets.waterHeater, + 'WM': Assets.waterLeakSensor, + 'SOS': Assets.sos, 'AC': Assets.ac, 'CPS': Assets.presenceSensor, 'PC': Assets.powerClamp, diff --git a/lib/pages/visitor_password/view/visitor_password_dialog.dart b/lib/pages/visitor_password/view/visitor_password_dialog.dart index d1fb172a..5362f448 100644 --- a/lib/pages/visitor_password/view/visitor_password_dialog.dart +++ b/lib/pages/visitor_password/view/visitor_password_dialog.dart @@ -2,10 +2,8 @@ import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; -import 'package:syncrow_web/pages/common/bloc/project_manager.dart'; import 'package:syncrow_web/pages/common/buttons/default_button.dart'; import 'package:syncrow_web/pages/common/date_time_widget.dart'; -import 'package:syncrow_web/pages/common/text_field/custom_web_textfield.dart'; import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_bloc.dart'; import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_event.dart'; import 'package:syncrow_web/pages/visitor_password/bloc/visitor_password_state.dart'; @@ -23,8 +21,8 @@ class VisitorPasswordDialog extends StatelessWidget { @override Widget build(BuildContext context) { - Size size = MediaQuery.of(context).size; - var text = Theme.of(context) + final size = MediaQuery.of(context).size; + final text = Theme.of(context) .textTheme .bodySmall! .copyWith(color: Colors.black, fontSize: 13); @@ -41,8 +39,7 @@ class VisitorPasswordDialog extends StatelessWidget { title: 'Sent Successfully', widgeta: Column( children: [ - if (visitorBloc - .passwordStatus!.failedOperations.isNotEmpty) + if (visitorBloc.passwordStatus!.failedOperations.isNotEmpty) Column( children: [ const Text('Failed Devices'), @@ -56,22 +53,19 @@ class VisitorPasswordDialog extends StatelessWidget { .passwordStatus!.failedOperations.length, itemBuilder: (context, index) { return Container( - margin: EdgeInsets.all(5), + margin: const EdgeInsets.all(5), decoration: containerDecoration, height: 45, child: Center( - child: Text(visitorBloc - .passwordStatus! - .failedOperations[index] - .deviceName)), + child: Text(visitorBloc.passwordStatus! + .failedOperations[index].deviceName)), ); }, ), ), ], ), - if (visitorBloc - .passwordStatus!.successOperations.isNotEmpty) + if (visitorBloc.passwordStatus!.successOperations.isNotEmpty) Column( children: [ const Text('Success Devices'), @@ -85,14 +79,12 @@ class VisitorPasswordDialog extends StatelessWidget { .passwordStatus!.successOperations.length, itemBuilder: (context, index) { return Container( - margin: EdgeInsets.all(5), + margin: const EdgeInsets.all(5), decoration: containerDecoration, height: 45, child: Center( - child: Text(visitorBloc - .passwordStatus! - .successOperations[index] - .deviceName)), + child: Text(visitorBloc.passwordStatus! + .successOperations[index].deviceName)), ); }, ), @@ -115,16 +107,14 @@ class VisitorPasswordDialog extends StatelessWidget { child: BlocBuilder( builder: (BuildContext context, VisitorPasswordState state) { final visitorBloc = BlocProvider.of(context); - bool isRepeat = + final isRepeat = state is IsRepeatState ? state.repeat : visitorBloc.repeat; return AlertDialog( backgroundColor: Colors.white, title: Text( 'Create visitor password', style: Theme.of(context).textTheme.headlineLarge!.copyWith( - fontWeight: FontWeight.w400, - fontSize: 24, - color: Colors.black), + fontWeight: FontWeight.w400, fontSize: 24, color: Colors.black), ), content: state is LoadingInitialState ? const Center(child: CircularProgressIndicator()) @@ -310,14 +300,12 @@ class VisitorPasswordDialog extends StatelessWidget { visitorBloc.accessTypeSelected == 'Offline Password') { visitorBloc.add(SelectTimeEvent( - context: context, - isEffective: false)); + context: context, isEffective: false)); } else { - visitorBloc.add( - SelectTimeVisitorPassword( - context: context, - isStart: false, - isRepeat: false)); + visitorBloc.add(SelectTimeVisitorPassword( + context: context, + isStart: false, + isRepeat: false)); } }, startTime: () { @@ -326,31 +314,28 @@ class VisitorPasswordDialog extends StatelessWidget { visitorBloc.accessTypeSelected == 'Offline Password') { visitorBloc.add(SelectTimeEvent( - context: context, - isEffective: true)); + context: context, isEffective: true)); } else { - visitorBloc.add( - SelectTimeVisitorPassword( - context: context, - isStart: true, - isRepeat: false)); + visitorBloc.add(SelectTimeVisitorPassword( + context: context, + isStart: true, + isRepeat: false)); } }, - firstString: (visitorBloc - .usageFrequencySelected == - 'Periodic' && - visitorBloc.accessTypeSelected == - 'Offline Password') - ? visitorBloc.effectiveTime - : visitorBloc.startTimeAccess - .toString(), + firstString: + (visitorBloc.usageFrequencySelected == + 'Periodic' && + visitorBloc.accessTypeSelected == + 'Offline Password') + ? visitorBloc.effectiveTime + : visitorBloc.startTimeAccess, secondString: (visitorBloc .usageFrequencySelected == 'Periodic' && visitorBloc.accessTypeSelected == 'Offline Password') ? visitorBloc.expirationTime - : visitorBloc.endTimeAccess.toString(), + : visitorBloc.endTimeAccess, icon: Assets.calendarIcon), const SizedBox( height: 10, @@ -410,8 +395,7 @@ class VisitorPasswordDialog extends StatelessWidget { child: CupertinoSwitch( value: visitorBloc.repeat, onChanged: (value) { - visitorBloc - .add(ToggleRepeatEvent()); + visitorBloc.add(ToggleRepeatEvent()); }, applyTheme: true, ), @@ -442,8 +426,7 @@ class VisitorPasswordDialog extends StatelessWidget { }, ).then((listDevice) { if (listDevice != null) { - visitorBloc.selectedDevices = - listDevice; + visitorBloc.selectedDevices = listDevice; } }); }, @@ -455,8 +438,7 @@ class VisitorPasswordDialog extends StatelessWidget { .bodySmall! .copyWith( fontWeight: FontWeight.w400, - color: - ColorsManager.whiteColors, + color: ColorsManager.whiteColors, fontSize: 12), ), ), @@ -495,37 +477,30 @@ class VisitorPasswordDialog extends StatelessWidget { onPressed: () { if (visitorBloc.forgetFormKey.currentState!.validate()) { if (visitorBloc.selectedDevices.isNotEmpty) { - if (visitorBloc.usageFrequencySelected == - 'One-Time' && - visitorBloc.accessTypeSelected == - 'Offline Password') { + if (visitorBloc.usageFrequencySelected == 'One-Time' && + visitorBloc.accessTypeSelected == 'Offline Password') { setPasswordFunction(context, size, visitorBloc); } else if (visitorBloc.usageFrequencySelected == 'Periodic' && - visitorBloc.accessTypeSelected == - 'Offline Password') { + visitorBloc.accessTypeSelected == 'Offline Password') { if (visitorBloc.expirationTime != 'End Time' && visitorBloc.effectiveTime != 'Start Time') { setPasswordFunction(context, size, visitorBloc); } else { visitorBloc.stateDialog( context: context, - message: - 'Please select Access Period to continue', + message: 'Please select Access Period to continue', title: 'Access Period'); } - } else if (visitorBloc.endTimeAccess.toString() != - 'End Time' && - visitorBloc.startTimeAccess.toString() != - 'Start Time') { + } else if (visitorBloc.endTimeAccess != 'End Time' && + visitorBloc.startTimeAccess != 'Start Time') { if (visitorBloc.effectiveTimeTimeStamp != null && visitorBloc.expirationTimeTimeStamp != null) { if (isRepeat == true) { if (visitorBloc.expirationTime != 'End Time' && visitorBloc.effectiveTime != 'Start Time' && visitorBloc.selectedDays.isNotEmpty) { - setPasswordFunction( - context, size, visitorBloc); + setPasswordFunction(context, size, visitorBloc); } else { visitorBloc.stateDialog( context: context, @@ -539,15 +514,13 @@ class VisitorPasswordDialog extends StatelessWidget { } else { visitorBloc.stateDialog( context: context, - message: - 'Please select Access Period to continue', + message: 'Please select Access Period to continue', title: 'Access Period'); } } else { visitorBloc.stateDialog( context: context, - message: - 'Please select Access Period to continue', + message: 'Please select Access Period to continue', title: 'Access Period'); } } else { @@ -593,17 +566,17 @@ class VisitorPasswordDialog extends StatelessWidget { alignment: Alignment.center, content: SizedBox( height: size.height * 0.25, - child: Center( - child: - CircularProgressIndicator(), // Display a loading spinner + child: const Center( + child: CircularProgressIndicator(), // Display a loading spinner ), ), ); } else { return AlertDialog( alignment: Alignment.center, + backgroundColor: Colors.white, content: SizedBox( - height: size.height * 0.25, + height: size.height * 0.13, child: Column( children: [ Column( @@ -617,13 +590,16 @@ class VisitorPasswordDialog extends StatelessWidget { width: 35, ), ), + const SizedBox( + height: 20, + ), Text( 'Set Password', style: Theme.of(context) .textTheme .headlineLarge! .copyWith( - fontSize: 30, + fontSize: 24, fontWeight: FontWeight.w400, color: Colors.black, ), @@ -631,15 +607,6 @@ class VisitorPasswordDialog extends StatelessWidget { ], ), const SizedBox(width: 15), - Text( - 'This action will update all of the selected\n door locks passwords in the property.\n\nAre you sure you want to continue?', - textAlign: TextAlign.center, - style: Theme.of(context).textTheme.bodyMedium!.copyWith( - color: ColorsManager.grayColor, - fontWeight: FontWeight.w400, - fontSize: 18, - ), - ), ], ), ), @@ -668,12 +635,12 @@ class VisitorPasswordDialog extends StatelessWidget { decoration: containerDecoration, width: size.width * 0.1, child: DefaultButton( + backgroundColor: Color(0xff023DFE), borderRadius: 8, onPressed: () { Navigator.pop(context); if (visitorBloc.usageFrequencySelected == 'One-Time' && - visitorBloc.accessTypeSelected == - 'Online Password') { + visitorBloc.accessTypeSelected == 'Online Password') { visitorBloc.add(OnlineOneTimePasswordEvent( context: context, passwordName: visitorBloc.userNameController.text, @@ -681,8 +648,7 @@ class VisitorPasswordDialog extends StatelessWidget { )); } else if (visitorBloc.usageFrequencySelected == 'Periodic' && - visitorBloc.accessTypeSelected == - 'Online Password') { + visitorBloc.accessTypeSelected == 'Online Password') { visitorBloc.add(OnlineMultipleTimePasswordEvent( passwordName: visitorBloc.userNameController.text, email: visitorBloc.emailController.text, @@ -693,8 +659,7 @@ class VisitorPasswordDialog extends StatelessWidget { )); } else if (visitorBloc.usageFrequencySelected == 'One-Time' && - visitorBloc.accessTypeSelected == - 'Offline Password') { + visitorBloc.accessTypeSelected == 'Offline Password') { visitorBloc.add(OfflineOneTimePasswordEvent( context: context, passwordName: visitorBloc.userNameController.text, @@ -702,8 +667,7 @@ class VisitorPasswordDialog extends StatelessWidget { )); } else if (visitorBloc.usageFrequencySelected == 'Periodic' && - visitorBloc.accessTypeSelected == - 'Offline Password') { + visitorBloc.accessTypeSelected == 'Offline Password') { visitorBloc.add(OfflineMultipleTimePasswordEvent( passwordName: visitorBloc.userNameController.text, email: visitorBloc.emailController.text, @@ -715,7 +679,7 @@ class VisitorPasswordDialog extends StatelessWidget { } }, child: Text( - 'Ok', + 'Confirm', style: Theme.of(context).textTheme.bodySmall!.copyWith( fontWeight: FontWeight.w400, color: ColorsManager.whiteColors, diff --git a/lib/services/devices_mang_api.dart b/lib/services/devices_mang_api.dart index dd54cfef..709d6855 100644 --- a/lib/services/devices_mang_api.dart +++ b/lib/services/devices_mang_api.dart @@ -13,13 +13,15 @@ import 'package:syncrow_web/utils/constants/api_const.dart'; class DevicesManagementApi { Future> fetchDevices( - String projectId, { - List? spacesId, - }) async { + String communityId, String spaceId, String projectId) async { try { final response = await HTTPService().get( - queryParameters: {if (spacesId != null) 'spaces': spacesId}, - path: ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId), + path: communityId.isNotEmpty && spaceId.isNotEmpty + ? ApiEndpoints.getSpaceDevices + .replaceAll('{spaceUuid}', spaceId) + .replaceAll('{communityUuid}', communityId) + .replaceAll('{projectId}', projectId) + : ApiEndpoints.getAllDevices.replaceAll('{projectId}', projectId), showServerMessage: true, expectedResponseModel: (json) { List jsonData = json['data']; @@ -414,4 +416,5 @@ class DevicesManagementApi { ); return response; } + } diff --git a/lib/utils/color_manager.dart b/lib/utils/color_manager.dart index 50170ed9..40fca1fa 100644 --- a/lib/utils/color_manager.dart +++ b/lib/utils/color_manager.dart @@ -83,7 +83,5 @@ abstract class ColorsManager { static const Color maxPurpleDot = Color(0xFF5F00BD); static const Color minBlue = Color(0xFF93AAFD); static const Color minBlueDot = Color(0xFF023DFE); - static const Color grey25 = Color(0xFFF9F9F9); - - + static const Color grey25 = Color(0xFFF9F9F9); } diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index 6dda1108..eb7b6a3e 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -18,7 +18,7 @@ abstract class ApiEndpoints { static const String getAllDevices = '/projects/{projectId}/devices'; 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 getBatchStatus = '/devices/batch'; diff --git a/lib/utils/constants/assets.dart b/lib/utils/constants/assets.dart index 8979c446..821df6e3 100644 --- a/lib/utils/constants/assets.dart +++ b/lib/utils/constants/assets.dart @@ -394,6 +394,7 @@ class Assets { static const String emptyBox = 'assets/icons/empty_box.png'; static const String completeProcessIcon = 'assets/icons/compleate_process_icon.svg'; + static const String completedDoneIcon = 'assets/images/completed_done.svg'; static const String currentProcessIcon = 'assets/icons/current_process_icon.svg'; static const String uncomplete_ProcessIcon = @@ -505,5 +506,6 @@ class Assets { static const String aqiAirQuality = 'assets/icons/aqi_air_quality.svg'; static const String temperatureAqiSidebar = 'assets/icons/thermometer.svg'; static const String humidityAqiSidebar = 'assets/icons/humidity.svg'; - static const String autocadOccupancyImage = 'assets/images/autocad_occupancy_image.png'; + static const String autocadOccupancyImage = + 'assets/images/autocad_occupancy_image.png'; }