From abb0a58468bf6cddb2b977cc006a30d72f33699b Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Wed, 18 Sep 2024 12:27:00 +0300 Subject: [PATCH] push ac batch control --- .../device_managment/ac/bloc/ac_bloc.dart | 65 +++++++-- .../device_managment/ac/bloc/ac_event.dart | 31 +++- .../device_managment/ac/bloc/ac_state.dart | 10 ++ .../device_managment/ac/model/ac_model.dart | 8 +- .../ac/view/ac_device_batch_control.dart | 51 ++++--- .../ac/view/ac_device_control.dart | 2 +- .../batch_control_list/batch_ac_mode.dart | 82 +++++++++++ .../batch_current_temp.dart | 138 ++++++++++++++++++ .../batch_control_list/batch_fan_speed.dart | 91 ++++++++++++ .../ac/view/control_list/ac_mode.dart | 2 +- .../ac/view/control_list/ac_toggle.dart | 2 +- .../ac/view/control_list/current_temp.dart | 2 +- .../ac/view/control_list/fan_speed.dart | 2 +- .../bloc/main_door_sensor_bloc.dart | 2 +- .../view/main_door_control_view.dart | 8 +- .../view/wall_light_batch_control.dart | 2 +- .../view/wall_light_device_control.dart | 2 +- .../shared/table/report_table.dart | 3 +- .../toggle_widget.dart} | 0 .../view/living_room_batch_controls.dart | 2 +- .../view/living_room_device_control.dart | 2 +- .../view/wall_light_batch_control.dart | 2 +- .../view/wall_light_device_control.dart | 2 +- .../view/water_heater_device_control.dart | 2 +- lib/services/devices_mang_api.dart | 67 ++++++++- lib/utils/constants/api_const.dart | 2 + 26 files changed, 516 insertions(+), 66 deletions(-) create mode 100644 lib/pages/device_managment/ac/view/batch_control_list/batch_ac_mode.dart create mode 100644 lib/pages/device_managment/ac/view/batch_control_list/batch_current_temp.dart create mode 100644 lib/pages/device_managment/ac/view/batch_control_list/batch_fan_speed.dart rename lib/pages/device_managment/{three_gang_switch/widgets/living_toggle_widget.dart => shared/toggle_widget.dart} (100%) diff --git a/lib/pages/device_managment/ac/bloc/ac_bloc.dart b/lib/pages/device_managment/ac/bloc/ac_bloc.dart index ab9cc265..54f36889 100644 --- a/lib/pages/device_managment/ac/bloc/ac_bloc.dart +++ b/lib/pages/device_managment/ac/bloc/ac_bloc.dart @@ -14,13 +14,14 @@ class AcBloc extends Bloc { Timer? _timer; AcBloc({required this.deviceId}) : super(AcsInitialState()) { - on(_onFetchAcStatus); - on(_onFetchAcBatchStatus); - on(_onAcControl); + on(_onFetchAcStatus); + on(_onFetchAcBatchStatus); + on(_onAcControl); + on(_onAcBatchControl); } FutureOr _onFetchAcStatus( - AcFetchDeviceStatus event, Emitter emit) async { + AcFetchDeviceStatusEvent event, Emitter emit) async { emit(AcsLoadingState()); try { final status = @@ -32,7 +33,8 @@ class AcBloc extends Bloc { } } - FutureOr _onAcControl(AcControl event, Emitter emit) async { + FutureOr _onAcControl( + AcControlEvent event, Emitter emit) async { final oldValue = _getValueByCode(event.code); _updateLocalValue(event.code, event.value, emit); @@ -40,6 +42,7 @@ class AcBloc extends Bloc { emit(ACStatusLoaded(deviceStatus)); await _runDebounce( + isBatch: false, deviceId: event.deviceId, code: event.code, value: event.value, @@ -49,27 +52,43 @@ class AcBloc extends Bloc { } Future _runDebounce({ - required String deviceId, + required dynamic deviceId, required String code, required dynamic value, required dynamic oldValue, required Emitter emit, + required bool isBatch, }) async { + late String id; + + if (deviceId is List) { + id = deviceId.first; + } else { + id = deviceId; + } + if (_timer != null) { _timer!.cancel(); } _timer = Timer(const Duration(seconds: 1), () async { try { - final response = await DevicesManagementApi() - .deviceControl(deviceId, Status(code: code, value: value)); + late bool response; + if (isBatch) { + response = await DevicesManagementApi() + .deviceBatchControl(deviceId, code, value); + } else { + response = await DevicesManagementApi() + .deviceControl(deviceId, Status(code: code, value: value)); + } + if (!response) { - _revertValueAndEmit(deviceId, code, oldValue, emit); + _revertValueAndEmit(id, code, oldValue, emit); } } catch (e) { if (e is DioException && e.response != null) { debugPrint('Error response: ${e.response?.data}'); } - _revertValueAndEmit(deviceId, code, oldValue, emit); + _revertValueAndEmit(id, code, oldValue, emit); } }); } @@ -78,7 +97,6 @@ class AcBloc extends Bloc { String deviceId, String code, dynamic oldValue, Emitter emit) { _updateLocalValue(code, oldValue, emit); emit(ACStatusLoaded(deviceStatus)); - emit(const AcsFailedState(error: 'Failed to control the device.')); } void _updateLocalValue(String code, dynamic value, Emitter emit) { @@ -136,15 +154,34 @@ class AcBloc extends Bloc { } FutureOr _onFetchAcBatchStatus( - AcFetchBatchStatus event, Emitter emit) async { + AcFetchBatchStatusEvent event, Emitter emit) async { emit(AcsLoadingState()); try { final status = - await DevicesManagementApi().getDeviceStatus(event.deviceId); - deviceStatus = AcStatusModel.fromJson(event.deviceId, status.status); + await DevicesManagementApi().getBatchStatus(event.devicesIds); + deviceStatus = + AcStatusModel.fromJson(event.devicesIds.first, status.status); emit(ACStatusLoaded(deviceStatus)); } catch (e) { emit(AcsFailedState(error: e.toString())); } } + + FutureOr _onAcBatchControl( + AcBatchControlEvent event, Emitter emit) async { + final oldValue = _getValueByCode(event.code); + + _updateLocalValue(event.code, event.value, emit); + + emit(ACStatusLoaded(deviceStatus)); + + await _runDebounce( + isBatch: true, + deviceId: event.devicesIds, + code: event.code, + value: event.value, + oldValue: oldValue, + emit: emit, + ); + } } diff --git a/lib/pages/device_managment/ac/bloc/ac_event.dart b/lib/pages/device_managment/ac/bloc/ac_event.dart index ab743b47..acb81d95 100644 --- a/lib/pages/device_managment/ac/bloc/ac_event.dart +++ b/lib/pages/device_managment/ac/bloc/ac_event.dart @@ -7,30 +7,30 @@ sealed class AcsEvent extends Equatable { List get props => []; } -class AcFetchDeviceStatus extends AcsEvent { +class AcFetchDeviceStatusEvent extends AcsEvent { final String deviceId; - const AcFetchDeviceStatus(this.deviceId); + const AcFetchDeviceStatusEvent(this.deviceId); @override List get props => [deviceId]; } -class AcFetchBatchStatus extends AcsEvent { - final String deviceId; +class AcFetchBatchStatusEvent extends AcsEvent { + final List devicesIds; - const AcFetchBatchStatus(this.deviceId); + const AcFetchBatchStatusEvent(this.devicesIds); @override - List get props => [deviceId]; + List get props => [devicesIds]; } -class AcControl extends AcsEvent { +class AcControlEvent extends AcsEvent { final String deviceId; final String code; final dynamic value; - const AcControl({ + const AcControlEvent({ required this.deviceId, required this.code, required this.value, @@ -39,3 +39,18 @@ class AcControl extends AcsEvent { @override List get props => [deviceId, code, value]; } + +class AcBatchControlEvent extends AcsEvent { + final List devicesIds; + final String code; + final dynamic value; + + const AcBatchControlEvent({ + required this.devicesIds, + required this.code, + required this.value, + }); + + @override + List get props => [devicesIds, code, value]; +} diff --git a/lib/pages/device_managment/ac/bloc/ac_state.dart b/lib/pages/device_managment/ac/bloc/ac_state.dart index 9a3b07f9..dfd12e6d 100644 --- a/lib/pages/device_managment/ac/bloc/ac_state.dart +++ b/lib/pages/device_managment/ac/bloc/ac_state.dart @@ -22,6 +22,16 @@ class ACStatusLoaded extends AcsState { List get props => [status, timestamp]; } +class AcBatchStatusLoaded extends AcsState { + final AcStatusModel status; + final DateTime timestamp; + + AcBatchStatusLoaded(this.status) : timestamp = DateTime.now(); + + @override + List get props => [status, timestamp]; +} + class AcsFailedState extends AcsState { final String error; diff --git a/lib/pages/device_managment/ac/model/ac_model.dart b/lib/pages/device_managment/ac/model/ac_model.dart index 621b9326..2803e51e 100644 --- a/lib/pages/device_managment/ac/model/ac_model.dart +++ b/lib/pages/device_managment/ac/model/ac_model.dart @@ -40,16 +40,16 @@ class AcStatusModel { acSwitch = status.value ?? false; break; case 'mode': - mode = status.value ?? 'cold'; // default to 'cold' if null + mode = status.value ?? 'cold'; break; case 'temp_set': - tempSet = status.value ?? 210; // default value if null + tempSet = status.value ?? 210; break; case 'temp_current': - currentTemp = status.value ?? 210; // default value if null + currentTemp = status.value ?? 210; break; case 'level': - fanSpeeds = status.value ?? 'low'; // default value if null + fanSpeeds = status.value ?? 'low'; break; case 'child_lock': childLock = status.value ?? false; diff --git a/lib/pages/device_managment/ac/view/ac_device_batch_control.dart b/lib/pages/device_managment/ac/view/ac_device_batch_control.dart index dc597090..edda3c5d 100644 --- a/lib/pages/device_managment/ac/view/ac_device_batch_control.dart +++ b/lib/pages/device_managment/ac/view/ac_device_batch_control.dart @@ -3,12 +3,12 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart'; import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart'; import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_state.dart'; -import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_mode.dart'; -import 'package:syncrow_web/pages/device_managment/ac/view/control_list/ac_toggle.dart'; -import 'package:syncrow_web/pages/device_managment/ac/view/control_list/current_temp.dart'; -import 'package:syncrow_web/pages/device_managment/ac/view/control_list/fan_speed.dart'; +import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/batch_ac_mode.dart'; +import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/batch_current_temp.dart'; +import 'package:syncrow_web/pages/device_managment/ac/view/batch_control_list/batch_fan_speed.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; +import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; @@ -25,7 +25,7 @@ class AcDeviceBatchControlView extends StatelessWidget final isMedium = isMediumScreenSize(context); return BlocProvider( create: (context) => AcBloc(deviceId: devicesIds.first) - ..add(AcFetchBatchStatus(devicesIds.first)), + ..add(AcFetchBatchStatusEvent(devicesIds)), child: BlocBuilder( builder: (context, state) { if (state is ACStatusLoaded) { @@ -44,34 +44,49 @@ class AcDeviceBatchControlView extends StatelessWidget mainAxisSpacing: 12, ), children: [ - AcToggle( - value: state.status.acSwitch, - code: 'switch', + ToggleWidget( deviceId: devicesIds.first, + code: 'switch', + value: state.status.acSwitch, + label: 'ThermoState', + onChange: (value) { + context.read().add(AcBatchControlEvent( + devicesIds: devicesIds, + code: 'switch', + value: value, + )); + }, ), - CurrentTemp( + BatchCurrentTemp( currentTemp: state.status.currentTemp, tempSet: state.status.tempSet, code: 'temp_set', - deviceId: devicesIds.first, + devicesIds: devicesIds, ), - AcMode( + BatchAcMode( value: state.status.acMode, code: 'mode', - deviceId: devicesIds.first, + devicesIds: devicesIds, ), - FanSpeedControl( + BatchFanSpeedControl( value: state.status.acFanSpeed, code: 'level', - deviceId: devicesIds.first, + devicesIds: devicesIds, ), - AcToggle( - value: state.status.childLock, - code: 'child_lock', + ToggleWidget( deviceId: devicesIds.first, - description: 'Child Lock', + code: 'child_lock', + value: state.status.childLock, + label: 'Child Lock', icon: state.status.childLock ? Assets.childLock : Assets.unlock, + onChange: (value) { + context.read().add(AcBatchControlEvent( + devicesIds: devicesIds, + code: 'child_lock', + value: value, + )); + }, ), FirmwareUpdateWidget(deviceId: devicesIds.first, version: 5), FactoryResetWidget(deviceId: devicesIds.first), diff --git a/lib/pages/device_managment/ac/view/ac_device_control.dart b/lib/pages/device_managment/ac/view/ac_device_control.dart index fdfa263c..7ae6f973 100644 --- a/lib/pages/device_managment/ac/view/ac_device_control.dart +++ b/lib/pages/device_managment/ac/view/ac_device_control.dart @@ -23,7 +23,7 @@ class AcDeviceControlsView extends StatelessWidget with HelperResponsiveLayout { final isMedium = isMediumScreenSize(context); return BlocProvider( create: (context) => AcBloc(deviceId: device.uuid!) - ..add(AcFetchDeviceStatus(device.uuid!)), + ..add(AcFetchDeviceStatusEvent(device.uuid!)), child: BlocBuilder( builder: (context, state) { if (state is ACStatusLoaded) { diff --git a/lib/pages/device_managment/ac/view/batch_control_list/batch_ac_mode.dart b/lib/pages/device_managment/ac/view/batch_control_list/batch_ac_mode.dart new file mode 100644 index 00000000..8b601ac2 --- /dev/null +++ b/lib/pages/device_managment/ac/view/batch_control_list/batch_ac_mode.dart @@ -0,0 +1,82 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart'; + +class BatchAcMode extends StatelessWidget { + const BatchAcMode({ + super.key, + required this.value, + required this.code, + required this.devicesIds, + }); + + final TempModes value; + final String code; + final List devicesIds; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: ColorsManager.greyColor.withOpacity(0.2), + border: Border.all(color: ColorsManager.boxDivider), + ), + padding: const EdgeInsets.all(16), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + _buildIconContainer(context, TempModes.cold, Assets.freezing, + value == TempModes.cold), + _buildIconContainer( + context, TempModes.hot, Assets.acSun, value == TempModes.hot), + _buildIconContainer(context, TempModes.wind, Assets.acAirConditioner, + value == TempModes.wind), + ], + ), + ); + } + + Widget _buildIconContainer( + BuildContext context, TempModes mode, String assetPath, bool isSelected) { + return Flexible( + child: GestureDetector( + onTap: () { + context.read().add( + AcBatchControlEvent( + devicesIds: devicesIds, + code: code, + value: mode.name, + ), + ); + }, + child: Container( + width: 50, + height: 50, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: ColorsManager.whiteColors, + border: Border.all( + color: isSelected ? Colors.blue : Colors.transparent, + width: 2.0, + ), + ), + margin: const EdgeInsets.symmetric(horizontal: 4), + padding: const EdgeInsets.all(4), + child: ClipOval( + child: SvgPicture.asset( + assetPath, + fit: BoxFit.contain, + ), + ), + ), + ), + ); + } +} diff --git a/lib/pages/device_managment/ac/view/batch_control_list/batch_current_temp.dart b/lib/pages/device_managment/ac/view/batch_control_list/batch_current_temp.dart new file mode 100644 index 00000000..e6d9378f --- /dev/null +++ b/lib/pages/device_managment/ac/view/batch_control_list/batch_current_temp.dart @@ -0,0 +1,138 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart'; +import 'package:syncrow_web/pages/device_managment/shared/celciuse_symbol.dart'; +import 'package:syncrow_web/pages/device_managment/shared/increament_decreament.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart'; + +class BatchCurrentTemp extends StatefulWidget { + const BatchCurrentTemp({ + super.key, + required this.code, + required this.devicesIds, + required this.currentTemp, + required this.tempSet, + }); + + final String code; + final List devicesIds; + final int currentTemp; + final int tempSet; + + @override + State createState() => _CurrentTempState(); +} + +class _CurrentTempState extends State { + late double _adjustedValue; + Timer? _debounce; + + @override + void initState() { + super.initState(); + _adjustedValue = _initialAdjustedValue(widget.tempSet); + } + + double _initialAdjustedValue(dynamic value) { + if (value is int || value is double) { + double doubleValue = value.toDouble(); + return doubleValue > 99 ? doubleValue / 10 : doubleValue; + } else { + throw ArgumentError('Invalid value type: Expected int or double'); + } + } + + void _onValueChanged(double newValue) { + if (_debounce?.isActive ?? false) { + _debounce?.cancel(); + } + _debounce = Timer(const Duration(milliseconds: 500), () { + context.read().add( + AcBatchControlEvent( + devicesIds: widget.devicesIds, + code: widget.code, + value: (newValue * 10).toInt(), + ), + ); + }); + } + + @override + void dispose() { + _debounce?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: ColorsManager.greyColor.withOpacity(0.2), + border: Border.all(color: ColorsManager.boxDivider), + ), + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Current Temperature', + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.grey), + ), + const SizedBox( + height: 5, + ), + Row( + children: [ + Text( + (widget.currentTemp > 99 + ? widget.currentTemp / 10 + : widget.currentTemp) + .toString(), + style: Theme.of(context) + .textTheme + .bodySmall! + .copyWith(color: Colors.grey), + ), + const CelsiusSymbol( + color: Colors.grey, + ) + ], + ), + ], + ), + const Spacer(), + IncrementDecrementWidget( + value: _adjustedValue.toString(), + description: '°C', + descriptionColor: ColorsManager.dialogBlueTitle, + onIncrement: () { + if (_adjustedValue < 30) { + setState(() { + _adjustedValue++; + }); + _onValueChanged(_adjustedValue); + } + }, + onDecrement: () { + if (_adjustedValue > 20) { + setState(() { + _adjustedValue--; + }); + _onValueChanged(_adjustedValue); + } + }), + ], + ), + ); + } +} diff --git a/lib/pages/device_managment/ac/view/batch_control_list/batch_fan_speed.dart b/lib/pages/device_managment/ac/view/batch_control_list/batch_fan_speed.dart new file mode 100644 index 00000000..b48d602c --- /dev/null +++ b/lib/pages/device_managment/ac/view/batch_control_list/batch_fan_speed.dart @@ -0,0 +1,91 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/ac/model/ac_model.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/constants/assets.dart'; +import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/ac/bloc/ac_event.dart'; + +class BatchFanSpeedControl extends StatelessWidget { + const BatchFanSpeedControl({ + super.key, + required this.value, + required this.code, + required this.devicesIds, + }); + + final FanSpeeds value; + final String code; + final List devicesIds; + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(20), + color: ColorsManager.greyColor.withOpacity(0.2), + border: Border.all(color: ColorsManager.boxDivider), + ), + padding: const EdgeInsets.all(8), + child: Column( + children: [ + Wrap( + runSpacing: 8, + spacing: 8, + children: [ + _buildIconContainer(context, FanSpeeds.auto, Assets.acFanAuto, + value == FanSpeeds.auto), + _buildIconContainer(context, FanSpeeds.low, Assets.acFanLow, + value == FanSpeeds.low), + ], + ), + Wrap( + runSpacing: 8, + spacing: 8, + children: [ + _buildIconContainer(context, FanSpeeds.middle, Assets.acFanMiddle, + value == FanSpeeds.middle), + _buildIconContainer(context, FanSpeeds.high, Assets.acFanHigh, + value == FanSpeeds.high), + ], + ) + ], + ), + ); + } + + Widget _buildIconContainer(BuildContext context, FanSpeeds speed, + String assetPath, bool isSelected) { + return GestureDetector( + onTap: () { + context.read().add( + AcBatchControlEvent( + devicesIds: devicesIds, + code: code, + value: speed.name, + ), + ); + }, + child: Container( + width: 50, + height: 50, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: ColorsManager.whiteColors, + border: Border.all( + color: isSelected ? Colors.blue : Colors.transparent, + width: 2.0, + ), + ), + padding: const EdgeInsets.all(8), + child: ClipOval( + child: SvgPicture.asset( + assetPath, + fit: BoxFit.contain, + ), + ), + ), + ); + } +} diff --git a/lib/pages/device_managment/ac/view/control_list/ac_mode.dart b/lib/pages/device_managment/ac/view/control_list/ac_mode.dart index 0e0cd276..65c7ae0a 100644 --- a/lib/pages/device_managment/ac/view/control_list/ac_mode.dart +++ b/lib/pages/device_managment/ac/view/control_list/ac_mode.dart @@ -49,7 +49,7 @@ class AcMode extends StatelessWidget { child: GestureDetector( onTap: () { context.read().add( - AcControl( + AcControlEvent( deviceId: deviceId, code: code, value: mode.name, diff --git a/lib/pages/device_managment/ac/view/control_list/ac_toggle.dart b/lib/pages/device_managment/ac/view/control_list/ac_toggle.dart index 53f79761..b9bf6014 100644 --- a/lib/pages/device_managment/ac/view/control_list/ac_toggle.dart +++ b/lib/pages/device_managment/ac/view/control_list/ac_toggle.dart @@ -57,7 +57,7 @@ class AcToggle extends StatelessWidget { value: value, onChanged: (newValue) { context.read().add( - AcControl( + AcControlEvent( deviceId: deviceId, code: code, value: newValue, diff --git a/lib/pages/device_managment/ac/view/control_list/current_temp.dart b/lib/pages/device_managment/ac/view/control_list/current_temp.dart index 2cf35228..5ff6fea6 100644 --- a/lib/pages/device_managment/ac/view/control_list/current_temp.dart +++ b/lib/pages/device_managment/ac/view/control_list/current_temp.dart @@ -50,7 +50,7 @@ class _CurrentTempState extends State { } _debounce = Timer(const Duration(milliseconds: 500), () { context.read().add( - AcControl( + AcControlEvent( deviceId: widget.deviceId, code: widget.code, value: (newValue * 10).toInt(), diff --git a/lib/pages/device_managment/ac/view/control_list/fan_speed.dart b/lib/pages/device_managment/ac/view/control_list/fan_speed.dart index d8d61d6b..c1e95d53 100644 --- a/lib/pages/device_managment/ac/view/control_list/fan_speed.dart +++ b/lib/pages/device_managment/ac/view/control_list/fan_speed.dart @@ -60,7 +60,7 @@ class FanSpeedControl extends StatelessWidget { return GestureDetector( onTap: () { context.read().add( - AcControl( + AcControlEvent( deviceId: deviceId, code: code, value: speed.name, diff --git a/lib/pages/device_managment/main_door_sensor/bloc/main_door_sensor_bloc.dart b/lib/pages/device_managment/main_door_sensor/bloc/main_door_sensor_bloc.dart index 50281c98..71a4b699 100644 --- a/lib/pages/device_managment/main_door_sensor/bloc/main_door_sensor_bloc.dart +++ b/lib/pages/device_managment/main_door_sensor/bloc/main_door_sensor_bloc.dart @@ -124,7 +124,7 @@ class MainDoorSensorBloc Emitter emit) async { emit(MainDoorSensorLoadingState()); try { - final reports = await DevicesManagementApi.getDeviceReports( + final reports = await DevicesManagementApi.getDeviceReportsByDate( event.deviceId, event.code, event.from, event.to); emit(MainDoorSensorReportLoaded(reports)); } catch (e) { diff --git a/lib/pages/device_managment/main_door_sensor/view/main_door_control_view.dart b/lib/pages/device_managment/main_door_sensor/view/main_door_control_view.dart index 3cc3e82e..657ebfee 100644 --- a/lib/pages/device_managment/main_door_sensor/view/main_door_control_view.dart +++ b/lib/pages/device_managment/main_door_sensor/view/main_door_control_view.dart @@ -76,13 +76,7 @@ class MainDoorSensorControlView extends StatelessWidget IconNameStatusContainer( name: status.doorContactState ? 'Open' : 'Close', icon: Assets.mainDoor, - onTap: () { - context.read().add(MainDoorSensorControl( - deviceId: device.uuid!, - code: 'doorcontact_state', - value: !status.doorContactState, - )); - }, + onTap: () {}, status: status.doorContactState, textColor: ColorsManager.red, paddingAmount: 8, diff --git a/lib/pages/device_managment/one_gang_switch/view/wall_light_batch_control.dart b/lib/pages/device_managment/one_gang_switch/view/wall_light_batch_control.dart index 78de7658..ffdcfa85 100644 --- a/lib/pages/device_managment/one_gang_switch/view/wall_light_batch_control.dart +++ b/lib/pages/device_managment/one_gang_switch/view/wall_light_batch_control.dart @@ -6,7 +6,7 @@ import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_lig import 'package:syncrow_web/pages/device_managment/one_gang_switch/models/wall_light_status_model.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; -import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; +import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; class WallLightBatchControlView extends StatelessWidget diff --git a/lib/pages/device_managment/one_gang_switch/view/wall_light_device_control.dart b/lib/pages/device_managment/one_gang_switch/view/wall_light_device_control.dart index 85a4221e..a9e6ebbb 100644 --- a/lib/pages/device_managment/one_gang_switch/view/wall_light_device_control.dart +++ b/lib/pages/device_managment/one_gang_switch/view/wall_light_device_control.dart @@ -4,7 +4,7 @@ import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_lig import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_light_switch_event.dart'; import 'package:syncrow_web/pages/device_managment/one_gang_switch/bloc/wall_light_switch_state.dart'; import 'package:syncrow_web/pages/device_managment/one_gang_switch/models/wall_light_status_model.dart'; -import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; +import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; class WallLightDeviceControl extends StatelessWidget diff --git a/lib/pages/device_managment/shared/table/report_table.dart b/lib/pages/device_managment/shared/table/report_table.dart index e46242a3..3cddef37 100644 --- a/lib/pages/device_managment/shared/table/report_table.dart +++ b/lib/pages/device_managment/shared/table/report_table.dart @@ -63,7 +63,8 @@ class ReportsTable extends StatelessWidget { TableCellWidget(value: time), hideValueShowDescription == true ? TableCellWidget( - value: mainDoorSensor == true + value: (mainDoorSensor != null && + mainDoorSensor == true) ? data.value == 'true' ? 'Open' : 'Close' diff --git a/lib/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart b/lib/pages/device_managment/shared/toggle_widget.dart similarity index 100% rename from lib/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart rename to lib/pages/device_managment/shared/toggle_widget.dart diff --git a/lib/pages/device_managment/three_gang_switch/view/living_room_batch_controls.dart b/lib/pages/device_managment/three_gang_switch/view/living_room_batch_controls.dart index f70605b8..daff5e63 100644 --- a/lib/pages/device_managment/three_gang_switch/view/living_room_batch_controls.dart +++ b/lib/pages/device_managment/three_gang_switch/view/living_room_batch_controls.dart @@ -4,7 +4,7 @@ import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_ import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart'; -import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; +import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; class LivingRoomBatchControlsView extends StatelessWidget diff --git a/lib/pages/device_managment/three_gang_switch/view/living_room_device_control.dart b/lib/pages/device_managment/three_gang_switch/view/living_room_device_control.dart index 07332217..b8226f57 100644 --- a/lib/pages/device_managment/three_gang_switch/view/living_room_device_control.dart +++ b/lib/pages/device_managment/three_gang_switch/view/living_room_device_control.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/bloc/living_room_bloc.dart'; import 'package:syncrow_web/pages/device_managment/three_gang_switch/models/living_room_model.dart'; -import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; +import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/utils/helpers/responsice_layout_helper/responsive_layout_helper.dart'; class LivingRoomDeviceControlsView extends StatelessWidget diff --git a/lib/pages/device_managment/two_gang_switch/view/wall_light_batch_control.dart b/lib/pages/device_managment/two_gang_switch/view/wall_light_batch_control.dart index 4926911a..323bc3f8 100644 --- a/lib/pages/device_managment/two_gang_switch/view/wall_light_batch_control.dart +++ b/lib/pages/device_managment/two_gang_switch/view/wall_light_batch_control.dart @@ -2,7 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/factory_reset.dart'; import 'package:syncrow_web/pages/device_managment/shared/batch_control/firmware_update.dart'; -import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; +import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_bloc.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_event.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_state.dart'; diff --git a/lib/pages/device_managment/two_gang_switch/view/wall_light_device_control.dart b/lib/pages/device_managment/two_gang_switch/view/wall_light_device_control.dart index fa42d096..e72756eb 100644 --- a/lib/pages/device_managment/two_gang_switch/view/wall_light_device_control.dart +++ b/lib/pages/device_managment/two_gang_switch/view/wall_light_device_control.dart @@ -1,6 +1,6 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; +import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_bloc.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_event.dart'; import 'package:syncrow_web/pages/device_managment/two_gang_switch/bloc/two_gang_switch_state.dart'; diff --git a/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart b/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart index b1cc82d5..14193ee0 100644 --- a/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart +++ b/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart @@ -3,7 +3,7 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart'; import 'package:syncrow_web/pages/device_managment/shared/device_controls_container.dart'; -import 'package:syncrow_web/pages/device_managment/three_gang_switch/widgets/living_toggle_widget.dart'; +import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart'; import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart'; import 'package:syncrow_web/utils/color_manager.dart'; diff --git a/lib/services/devices_mang_api.dart b/lib/services/devices_mang_api.dart index b9362550..03ddf6ca 100644 --- a/lib/services/devices_mang_api.dart +++ b/lib/services/devices_mang_api.dart @@ -65,6 +65,31 @@ class DevicesManagementApi { } } + Future deviceBatchControl( + List uuids, String code, dynamic value) async { + try { + final body = { + 'devicesUuid': uuids, + 'code': code, + 'value': value, + }; + + final response = await HTTPService().post( + path: ApiEndpoints.deviceBatchControl, + body: body, + showServerMessage: true, + expectedResponseModel: (json) { + return json['success'] ?? false; + }, + ); + + return response; + } catch (e) { + debugPrint('Error fetching $e'); + return false; + } + } + static Future> getDevicesByGatewayId( String gatewayId) async { final response = await HTTPService().get( @@ -95,7 +120,23 @@ class DevicesManagementApi { return response; } - static Future getDeviceReports(String uuid, String code, + static Future getDeviceReports( + String uuid, + String code, + ) async { + final response = await HTTPService().get( + path: ApiEndpoints.getDeviceLogs + .replaceAll('{uuid}', uuid) + .replaceAll('{code}', code), + showServerMessage: false, + expectedResponseModel: (json) { + return DeviceReport.fromJson(json); + }, + ); + return response; + } + + static Future getDeviceReportsByDate(String uuid, String code, [String? from, String? to]) async { final response = await HTTPService().get( path: ApiEndpoints.getDeviceLogsByDate @@ -110,4 +151,28 @@ class DevicesManagementApi { ); return response; } + + Future getBatchStatus(List uuids) async { + try { + final queryParameters = { + 'devicesUuid': uuids.join(','), + }; + final response = await HTTPService().get( + path: ApiEndpoints.getBatchStatus, + queryParameters: queryParameters, + showServerMessage: true, + expectedResponseModel: (json) { + return DeviceStatus.fromJson(json['status']); + }, + ); + return response; + } catch (e) { + debugPrint('Error fetching $e'); + return DeviceStatus( + productUuid: '', + productType: '', + status: [], + ); + } + } } diff --git a/lib/utils/constants/api_const.dart b/lib/utils/constants/api_const.dart index 894da828..3138c502 100644 --- a/lib/utils/constants/api_const.dart +++ b/lib/utils/constants/api_const.dart @@ -28,8 +28,10 @@ abstract class ApiEndpoints { static const String getAllDevices = '/device'; static const String getDeviceStatus = '/device/{uuid}/functions/status'; + static const String getBatchStatus = '/device/status/batch'; static const String deviceControl = '/device/{uuid}/control'; + static const String deviceBatchControl = '/device/control/batch'; static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices'; static const String openDoorLock = '/door-lock/open/{doorLockUuid}';