diff --git a/assets/icons/ac_switch_ic.svg b/assets/icons/ac_switch_ic.svg new file mode 100644 index 0000000..3ee128e --- /dev/null +++ b/assets/icons/ac_switch_ic.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/ios/Podfile.lock b/ios/Podfile.lock index c859ce0..cfff9d7 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -281,4 +281,4 @@ SPEC CHECKSUMS: PODFILE CHECKSUM: cf86fcba3fb3dbd505936bc190bb0b8fe3dd2498 -COCOAPODS: 1.13.0 +COCOAPODS: 1.15.2 diff --git a/lib/features/devices/bloc/acs_bloc/acs_bloc.dart b/lib/features/devices/bloc/acs_bloc/acs_bloc.dart index 09ec737..b8dad95 100644 --- a/lib/features/devices/bloc/acs_bloc/acs_bloc.dart +++ b/lib/features/devices/bloc/acs_bloc/acs_bloc.dart @@ -1,4 +1,5 @@ import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; import 'package:syncrow_app/features/devices/model/ac_model.dart'; @@ -10,34 +11,165 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart'; class ACsBloc extends Bloc { final String acId; - late DeviceModel deviceModel; - late AcStatusModel deviceStatus; + AcStatusModel deviceStatus = AcStatusModel( + acSwitch: true, + modeString: 'hot', + tempSet: 300, + currentTemp: 315, + fanSpeedsString: 'low', + childLock: false); + List deviceStatusList = []; + List devicesList = []; + bool allAcsPage = false; + bool allAcsOn = true; + bool allTempSame = true; + int globalTemp = 25; ACsBloc({required this.acId}) : super(AcsInitialState()) { on(_fetchAcsStatus); + on(_changeAcSwitch); on(_increaseCoolTo); on(_decreaseCoolTo); on(_changeLockValue); on(_changeAcMode); on(_changeFanSpeed); + on(_changeAllAcSwitch); + on(_increaseAllTemp); + on(_decreaseAllTemp); } void _fetchAcsStatus(AcsInitial event, Emitter emit) async { emit(AcsLoadingState()); try { - var response = await DevicesAPI.getDeviceStatus(acId); - List statusModelList = []; - for (var status in response['status']) { - statusModelList.add(StatusModel.fromJson(status)); + allAcsPage = event.allAcs; + if (event.allAcs) { + await _getAllAcs(); + emit(GetAllAcsStatusState( + allAcsStatues: deviceStatusList, + allAcs: devicesList, + allOn: allAcsOn, + allTempSame: allTempSame, + temp: globalTemp)); + } else { + var response = await DevicesAPI.getDeviceStatus(acId); + List statusModelList = []; + for (var status in response['status']) { + statusModelList.add(StatusModel.fromJson(status)); + } + deviceStatus = AcStatusModel.fromJson(statusModelList); + emit(GetAcStatusState(acStatusModel: deviceStatus)); } - deviceStatus = AcStatusModel.fromJson(statusModelList); - emit(GetAcStatusState(acStatusModel: deviceStatus)); } catch (e) { emit(AcsFailedState(error: e.toString())); return; } } + _getAllAcs() async { + deviceStatusList = []; + devicesList = []; + allAcsOn = true; + allTempSame = true; + devicesList = await DevicesAPI.getDeviceByGroupName( + HomeCubit.getInstance().selectedSpace?.id ?? '', 'AC'); + + for (int i = 0; i < devicesList.length; i++) { + var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); + List statusModelList = []; + for (var status in response['status']) { + statusModelList.add(StatusModel.fromJson(status)); + } + deviceStatusList.add(AcStatusModel.fromJson(statusModelList)); + } + if (deviceStatusList.isNotEmpty) { + int temp = deviceStatusList[0].tempSet; + deviceStatusList.firstWhere((element) { + if (!element.acSwitch) { + allAcsOn = false; + } + if (element.tempSet != temp) { + allTempSame = false; + } + + return true; + }); + if (allTempSame) { + globalTemp = temp; + } + } + } + + void _changeAcSwitch(AcSwitch event, Emitter emit) async { + emit(AcChangeLoading(acStatusModel: deviceStatus)); + + final acSwitchValue = !event.acSwitch; + try { + final response = await DevicesAPI.controlDevice( + DeviceControlModel( + deviceId: allAcsPage ? event.deviceId : acId, code: 'switch', value: acSwitchValue), + allAcsPage ? event.deviceId : acId); + + if (response['success'] ?? false) { + deviceStatus.acSwitch = acSwitchValue; + } + } catch (_) {} + if (allAcsPage) { + await Future.delayed(const Duration(seconds: 1)); + add(const AcsInitial(allAcs: true)); + } else { + emit(AcModifyingState(acStatusModel: deviceStatus)); + } + } + + void _changeAllAcSwitch(ChangeAllSwitch event, Emitter emit) async { + emit(AcsLoadingState()); + try { + if (deviceStatusList.length == devicesList.length) { + for (int i = 0; i < deviceStatusList.length; i++) { + await DevicesAPI.controlDevice( + DeviceControlModel(deviceId: devicesList[i].uuid, code: 'switch', value: event.value), + devicesList[i].uuid ?? ''); + } + } + } catch (_) {} + await Future.delayed(const Duration(seconds: 1)); + add(const AcsInitial(allAcs: true)); + } + + void _increaseAllTemp(IncreaseAllTemp event, Emitter emit) async { + emit(AcsLoadingState()); + try { + double tempValue = event.value + 0.5; + int value = (tempValue * 10).toInt(); + if (deviceStatusList.length == devicesList.length) { + for (int i = 0; i < deviceStatusList.length; i++) { + await DevicesAPI.controlDevice( + DeviceControlModel(deviceId: devicesList[i].uuid, code: 'temp_set', value: value), + devicesList[i].uuid ?? ''); + } + } + } catch (_) {} + await Future.delayed(const Duration(seconds: 1)); + add(const AcsInitial(allAcs: true)); + } + + void _decreaseAllTemp(DecreaseAllTemp event, Emitter emit) async { + emit(AcsLoadingState()); + try { + double tempValue = event.value - 0.5; + int value = (tempValue * 10).toInt(); + if (deviceStatusList.length == devicesList.length) { + for (int i = 0; i < deviceStatusList.length; i++) { + await DevicesAPI.controlDevice( + DeviceControlModel(deviceId: devicesList[i].uuid, code: 'temp_set', value: value), + devicesList[i].uuid ?? ''); + } + } + } catch (_) {} + await Future.delayed(const Duration(seconds: 1)); + add(const AcsInitial(allAcs: true)); + } + void _changeLockValue(ChangeLock event, Emitter emit) async { emit(AcChangeLoading(acStatusModel: deviceStatus)); @@ -59,13 +191,20 @@ class ACsBloc extends Bloc { int value = (tempValue * 10).toInt(); try { final response = await DevicesAPI.controlDevice( - DeviceControlModel(deviceId: acId, code: 'temp_set', value: value), acId); + DeviceControlModel( + deviceId: allAcsPage ? event.deviceId : acId, code: 'temp_set', value: value), + allAcsPage ? event.deviceId : acId); if (response['success'] ?? false) { deviceStatus.tempSet = value; } } catch (_) {} - emit(AcModifyingState(acStatusModel: deviceStatus)); + if (allAcsPage) { + await Future.delayed(const Duration(seconds: 1)); + add(const AcsInitial(allAcs: true)); + } else { + emit(AcModifyingState(acStatusModel: deviceStatus)); + } } void _decreaseCoolTo(DecreaseCoolToTemp event, Emitter emit) async { @@ -75,13 +214,20 @@ class ACsBloc extends Bloc { int value = (tempValue * 10).toInt(); try { final response = await DevicesAPI.controlDevice( - DeviceControlModel(deviceId: acId, code: 'temp_set', value: value), acId); + DeviceControlModel( + deviceId: allAcsPage ? event.deviceId : acId, code: 'temp_set', value: value), + allAcsPage ? event.deviceId : acId); if (response['success'] ?? false) { deviceStatus.tempSet = value; } } catch (_) {} - emit(AcModifyingState(acStatusModel: deviceStatus)); + if (allAcsPage) { + await Future.delayed(const Duration(seconds: 1)); + add(const AcsInitial(allAcs: true)); + } else { + emit(AcModifyingState(acStatusModel: deviceStatus)); + } } void _changeAcMode(ChangeAcMode event, Emitter emit) async { @@ -89,14 +235,23 @@ class ACsBloc extends Bloc { final tempMode = tempModesMap[getNextItem(tempModesMap, event.tempModes)]!; try { final response = await DevicesAPI.controlDevice( - DeviceControlModel(deviceId: acId, code: 'mode', value: getACModeString(tempMode)), acId); + DeviceControlModel( + deviceId: allAcsPage ? event.deviceId : acId, + code: 'mode', + value: getACModeString(tempMode)), + allAcsPage ? event.deviceId : acId); if (response['success'] ?? false) { deviceStatus.modeString = getACModeString(tempMode); deviceStatus.acMode = AcStatusModel.getACMode(getACModeString(tempMode)); } } catch (_) {} - emit(AcModifyingState(acStatusModel: deviceStatus)); + if (allAcsPage) { + await Future.delayed(const Duration(seconds: 1)); + add(const AcsInitial(allAcs: true)); + } else { + emit(AcModifyingState(acStatusModel: deviceStatus)); + } } void _changeFanSpeed(ChangeFanSpeed event, Emitter emit) async { @@ -104,8 +259,11 @@ class ACsBloc extends Bloc { final fanSpeed = event.fanSpeeds; final response = await DevicesAPI.controlDevice( - DeviceControlModel(deviceId: acId, code: 'level', value: getNextFanSpeedKey(fanSpeed)), - acId); + DeviceControlModel( + deviceId: allAcsPage ? event.deviceId : acId, + code: 'level', + value: getNextFanSpeedKey(fanSpeed)), + allAcsPage ? event.deviceId : acId); try { if (response['success'] ?? false) { @@ -113,7 +271,12 @@ class ACsBloc extends Bloc { deviceStatus.acFanSpeed = AcStatusModel.getFanSpeed(getNextFanSpeedKey(fanSpeed)); } } catch (_) {} - emit(AcModifyingState(acStatusModel: deviceStatus)); + if (allAcsPage) { + await Future.delayed(const Duration(seconds: 1)); + add(const AcsInitial(allAcs: true)); + } else { + emit(AcModifyingState(acStatusModel: deviceStatus)); + } } String getACModeString(TempModes value) { diff --git a/lib/features/devices/bloc/acs_bloc/acs_event.dart b/lib/features/devices/bloc/acs_bloc/acs_event.dart index b3b7ec0..806e878 100644 --- a/lib/features/devices/bloc/acs_bloc/acs_event.dart +++ b/lib/features/devices/bloc/acs_bloc/acs_event.dart @@ -10,40 +10,58 @@ abstract class AcsEvent extends Equatable { class AcsLoading extends AcsEvent {} -class AcsInitial extends AcsEvent {} +class AcSwitch extends AcsEvent { + final bool acSwitch; + final String deviceId; + const AcSwitch({required this.acSwitch, this.deviceId = ''}); + + @override + List get props => [acSwitch, deviceId]; +} + +class AcsInitial extends AcsEvent { + final bool allAcs; + const AcsInitial({required this.allAcs}); + @override + List get props => [allAcs]; +} class ACsChangeStatus extends AcsEvent {} class IncreaseCoolToTemp extends AcsEvent { final double value; - const IncreaseCoolToTemp({required this.value}); + final String deviceId; + const IncreaseCoolToTemp({required this.value, this.deviceId = ''}); @override - List get props => [value]; + List get props => [value, deviceId]; } class DecreaseCoolToTemp extends AcsEvent { final double value; - const DecreaseCoolToTemp({required this.value}); + final String deviceId; + const DecreaseCoolToTemp({required this.value, this.deviceId = ''}); @override - List get props => [value]; + List get props => [value, deviceId]; } class ChangeAcMode extends AcsEvent { final TempModes tempModes; - const ChangeAcMode({required this.tempModes}); + final String deviceId; + const ChangeAcMode({required this.tempModes, this.deviceId = ''}); @override - List get props => [tempModes]; + List get props => [tempModes, deviceId]; } class ChangeFanSpeed extends AcsEvent { final FanSpeeds fanSpeeds; - const ChangeFanSpeed({required this.fanSpeeds}); + final String deviceId; + const ChangeFanSpeed({required this.fanSpeeds, this.deviceId = ''}); @override - List get props => [fanSpeeds]; + List get props => [fanSpeeds, deviceId]; } class ChangeLock extends AcsEvent { @@ -53,3 +71,27 @@ class ChangeLock extends AcsEvent { @override List get props => [lockBool]; } + +class ChangeAllSwitch extends AcsEvent { + final bool value; + const ChangeAllSwitch({required this.value}); + + @override + List get props => [value]; +} + +class IncreaseAllTemp extends AcsEvent { + final double value; + const IncreaseAllTemp({required this.value}); + + @override + List get props => [value]; +} + +class DecreaseAllTemp extends AcsEvent { + final double value; + const DecreaseAllTemp({required this.value}); + + @override + List get props => [value]; +} diff --git a/lib/features/devices/bloc/acs_bloc/acs_state.dart b/lib/features/devices/bloc/acs_bloc/acs_state.dart index 79288c2..fe3d8e5 100644 --- a/lib/features/devices/bloc/acs_bloc/acs_state.dart +++ b/lib/features/devices/bloc/acs_bloc/acs_state.dart @@ -1,5 +1,6 @@ import 'package:equatable/equatable.dart'; import 'package:syncrow_app/features/devices/model/ac_model.dart'; +import 'package:syncrow_app/features/devices/model/device_model.dart'; abstract class AcsState extends Equatable { const AcsState(); @@ -36,6 +37,24 @@ class GetAcStatusState extends AcsState { List get props => [acStatusModel]; } +class GetAllAcsStatusState extends AcsState { + final List allAcsStatues; + final List allAcs; + final bool allOn; + final bool allTempSame; + final int temp; + + const GetAllAcsStatusState( + {required this.allAcsStatues, + required this.allAcs, + required this.allOn, + required this.allTempSame, + required this.temp}); + + @override + List get props => [allAcsStatues, allAcs, allAcs, allTempSame, temp]; +} + class AcsFailedState extends AcsState { final String error; diff --git a/lib/features/devices/bloc/devices_cubit.dart b/lib/features/devices/bloc/devices_cubit.dart index 0f95620..5133e26 100644 --- a/lib/features/devices/bloc/devices_cubit.dart +++ b/lib/features/devices/bloc/devices_cubit.dart @@ -29,6 +29,7 @@ class DevicesCubit extends Cubit { for (var room in HomeCubit.getInstance().selectedSpace!.rooms!) { fetchDevicesByRoomId(room.id!); } + fetchGroups(HomeCubit.getInstance().selectedSpace?.id ?? ''); } } @@ -52,7 +53,7 @@ class DevicesCubit extends Cubit { static DevicesCubit get(context) => BlocProvider.of(context); - static List? allCategories; + List? allCategories; selectCategory(int index) { for (var i = 0; i < allCategories!.length; i++) { diff --git a/lib/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart b/lib/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart index 79526e2..b8550a7 100644 --- a/lib/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart +++ b/lib/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart @@ -1,16 +1,29 @@ import 'dart:async'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart'; import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart'; import 'package:syncrow_app/features/devices/model/device_control_model.dart'; +import 'package:syncrow_app/features/devices/model/device_model.dart'; +import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart'; import 'package:syncrow_app/features/devices/model/status_model.dart'; import 'package:syncrow_app/features/devices/model/three_gang_model.dart'; import 'package:syncrow_app/services/api/devices_api.dart'; class ThreeGangBloc extends Bloc { final String threeGangId; - late ThreeGangModel deviceStatus; + ThreeGangModel deviceStatus = ThreeGangModel( + firstSwitch: false, + secondSwitch: false, + thirdSwitch: false, + firstCountDown: 0, + secondCountDown: 0, + thirdCountDown: 0); Timer? _timer; + bool threeGangGroup = false; + List devicesList = []; + List groupThreeGangList = []; + bool allSwitchesOn = true; ThreeGangBloc({required this.threeGangId}) : super(InitialState()) { on(_fetchThreeGangStatus); @@ -24,18 +37,55 @@ class ThreeGangBloc extends Bloc { on(_getCounterValue); on(_onTickTimer); on(_onClose); + on(_groupAllOn); + on(_groupAllOff); } void _fetchThreeGangStatus(InitialEvent event, Emitter emit) async { emit(LoadingInitialState()); try { - var response = await DevicesAPI.getDeviceStatus(threeGangId); - List statusModelList = []; - for (var status in response['status']) { - statusModelList.add(StatusModel.fromJson(status)); + threeGangGroup = event.groupScreen; + if (threeGangGroup) { + devicesList = []; + groupThreeGangList = []; + allSwitchesOn = true; + devicesList = await DevicesAPI.getDeviceByGroupName( + HomeCubit.getInstance().selectedSpace?.id ?? '', '3G'); + + for (int i = 0; i < devicesList.length; i++) { + var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); + List statusModelList = []; + for (var status in response['status']) { + statusModelList.add(StatusModel.fromJson(status)); + } + deviceStatus = ThreeGangModel.fromJson(statusModelList); + + groupThreeGangList.add(GroupThreeGangModel( + deviceId: devicesList[i].uuid ?? '', + deviceName: devicesList[i].name ?? '', + firstSwitch: deviceStatus.firstSwitch, + secondSwitch: deviceStatus.secondSwitch, + thirdSwitch: deviceStatus.thirdSwitch)); + } + + if (groupThreeGangList.isNotEmpty) { + groupThreeGangList.firstWhere((element) { + if (!element.firstSwitch || !element.secondSwitch || !element.thirdSwitch) { + allSwitchesOn = false; + } + return true; + }); + } + emit(UpdateGroupState(threeGangList: groupThreeGangList, allSwitches: allSwitchesOn)); + } else { + var response = await DevicesAPI.getDeviceStatus(threeGangId); + List statusModelList = []; + for (var status in response['status']) { + statusModelList.add(StatusModel.fromJson(status)); + } + deviceStatus = ThreeGangModel.fromJson(statusModelList); + emit(UpdateState(threeGangModel: deviceStatus)); } - deviceStatus = ThreeGangModel.fromJson(statusModelList); - emit(UpdateState(threeGangModel: deviceStatus)); } catch (e) { emit(FailedState(error: e.toString())); return; @@ -46,14 +96,22 @@ class ThreeGangBloc extends Bloc { emit(LoadingNewSate(threeGangModel: deviceStatus)); try { final response = await DevicesAPI.controlDevice( - DeviceControlModel(deviceId: threeGangId, code: 'switch_1', value: !event.value), - threeGangId); + DeviceControlModel( + deviceId: threeGangGroup ? event.deviceId : threeGangId, + code: 'switch_1', + value: !event.value), + threeGangGroup ? event.deviceId : threeGangId); if (response['success'] ?? false) { deviceStatus.firstSwitch = !event.value; } } catch (_) {} - emit(UpdateState(threeGangModel: deviceStatus)); + if (threeGangGroup) { + await Future.delayed(const Duration(seconds: 1)); + add(const InitialEvent(groupScreen: true)); + } else { + emit(UpdateState(threeGangModel: deviceStatus)); + } } void _changeSecondSwitch( @@ -61,28 +119,44 @@ class ThreeGangBloc extends Bloc { emit(LoadingNewSate(threeGangModel: deviceStatus)); try { final response = await DevicesAPI.controlDevice( - DeviceControlModel(deviceId: threeGangId, code: 'switch_2', value: !event.value), - threeGangId); + DeviceControlModel( + deviceId: threeGangGroup ? event.deviceId : threeGangId, + code: 'switch_2', + value: !event.value), + threeGangGroup ? event.deviceId : threeGangId); if (response['success'] ?? false) { deviceStatus.secondSwitch = !event.value; } } catch (_) {} - emit(UpdateState(threeGangModel: deviceStatus)); + if (threeGangGroup) { + await Future.delayed(const Duration(seconds: 1)); + add(const InitialEvent(groupScreen: true)); + } else { + emit(UpdateState(threeGangModel: deviceStatus)); + } } void _changeThirdSwitch(ChangeThirdSwitchStatusEvent event, Emitter emit) async { emit(LoadingNewSate(threeGangModel: deviceStatus)); try { final response = await DevicesAPI.controlDevice( - DeviceControlModel(deviceId: threeGangId, code: 'switch_3', value: !event.value), - threeGangId); + DeviceControlModel( + deviceId: threeGangGroup ? event.deviceId : threeGangId, + code: 'switch_3', + value: !event.value), + threeGangGroup ? event.deviceId : threeGangId); if (response['success'] ?? false) { deviceStatus.thirdSwitch = !event.value; } } catch (_) {} - emit(UpdateState(threeGangModel: deviceStatus)); + if (threeGangGroup) { + await Future.delayed(const Duration(seconds: 1)); + add(const InitialEvent(groupScreen: true)); + } else { + emit(UpdateState(threeGangModel: deviceStatus)); + } } void _allOff(AllOffEvent event, Emitter emit) async { @@ -129,6 +203,56 @@ class ThreeGangBloc extends Bloc { emit(UpdateState(threeGangModel: deviceStatus)); } + void _groupAllOn(GroupAllOnEvent event, Emitter emit) async { + emit(LoadingNewSate(threeGangModel: deviceStatus)); + + try { + for (int i = 0; i < groupThreeGangList.length; i++) { + await Future.wait([ + DevicesAPI.controlDevice( + DeviceControlModel( + deviceId: groupThreeGangList[i].deviceId, code: 'switch_1', value: true), + groupThreeGangList[i].deviceId), + DevicesAPI.controlDevice( + DeviceControlModel( + deviceId: groupThreeGangList[i].deviceId, code: 'switch_2', value: true), + groupThreeGangList[i].deviceId), + DevicesAPI.controlDevice( + DeviceControlModel( + deviceId: groupThreeGangList[i].deviceId, code: 'switch_3', value: true), + groupThreeGangList[i].deviceId), + ]); + } + } catch (_) {} + await Future.delayed(const Duration(seconds: 1)); + add(const InitialEvent(groupScreen: true)); + } + + void _groupAllOff(GroupAllOffEvent event, Emitter emit) async { + emit(LoadingNewSate(threeGangModel: deviceStatus)); + + try { + for (int i = 0; i < groupThreeGangList.length; i++) { + await Future.wait([ + DevicesAPI.controlDevice( + DeviceControlModel( + deviceId: groupThreeGangList[i].deviceId, code: 'switch_1', value: false), + groupThreeGangList[i].deviceId), + DevicesAPI.controlDevice( + DeviceControlModel( + deviceId: groupThreeGangList[i].deviceId, code: 'switch_2', value: false), + groupThreeGangList[i].deviceId), + DevicesAPI.controlDevice( + DeviceControlModel( + deviceId: groupThreeGangList[i].deviceId, code: 'switch_3', value: false), + groupThreeGangList[i].deviceId), + ]); + } + } catch (_) {} + await Future.delayed(const Duration(seconds: 1)); + add(const InitialEvent(groupScreen: true)); + } + void _changeSliding(ChangeSlidingSegment event, Emitter emit) async { emit(ChangeSlidingSegmentState(value: event.value)); } diff --git a/lib/features/devices/bloc/three_gang_bloc/three_gang_event.dart b/lib/features/devices/bloc/three_gang_bloc/three_gang_event.dart index 2f0a8b0..2c9b82f 100644 --- a/lib/features/devices/bloc/three_gang_bloc/three_gang_event.dart +++ b/lib/features/devices/bloc/three_gang_bloc/three_gang_event.dart @@ -9,33 +9,45 @@ abstract class ThreeGangEvent extends Equatable { class LoadingEvent extends ThreeGangEvent {} -class InitialEvent extends ThreeGangEvent {} +class InitialEvent extends ThreeGangEvent { + final bool groupScreen; + const InitialEvent({required this.groupScreen}); + @override + List get props => [groupScreen]; +} class ChangeFirstSwitchStatusEvent extends ThreeGangEvent { final bool value; - const ChangeFirstSwitchStatusEvent({required this.value}); + final String deviceId; + const ChangeFirstSwitchStatusEvent({required this.value, this.deviceId = ''}); @override - List get props => [value]; + List get props => [value, deviceId]; } class ChangeSecondSwitchStatusEvent extends ThreeGangEvent { final bool value; - const ChangeSecondSwitchStatusEvent({required this.value}); + final String deviceId; + const ChangeSecondSwitchStatusEvent({required this.value, this.deviceId = ''}); @override - List get props => [value]; + List get props => [value, deviceId]; } class ChangeThirdSwitchStatusEvent extends ThreeGangEvent { final bool value; - const ChangeThirdSwitchStatusEvent({required this.value}); + final String deviceId; + const ChangeThirdSwitchStatusEvent({required this.value, this.deviceId = ''}); @override - List get props => [value]; + List get props => [value, deviceId]; } class AllOffEvent extends ThreeGangEvent {} class AllOnEvent extends ThreeGangEvent {} +class GroupAllOnEvent extends ThreeGangEvent {} + +class GroupAllOffEvent extends ThreeGangEvent {} + class ChangeSlidingSegment extends ThreeGangEvent { final int value; const ChangeSlidingSegment({required this.value}); diff --git a/lib/features/devices/bloc/three_gang_bloc/three_gang_state.dart b/lib/features/devices/bloc/three_gang_bloc/three_gang_state.dart index a124c7c..6760dea 100644 --- a/lib/features/devices/bloc/three_gang_bloc/three_gang_state.dart +++ b/lib/features/devices/bloc/three_gang_bloc/three_gang_state.dart @@ -1,4 +1,5 @@ import 'package:equatable/equatable.dart'; +import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart'; import 'package:syncrow_app/features/devices/model/three_gang_model.dart'; class ThreeGangState extends Equatable { @@ -28,6 +29,16 @@ class LoadingNewSate extends ThreeGangState { List get props => [threeGangModel]; } +class UpdateGroupState extends ThreeGangState { + final List threeGangList; + final bool allSwitches; + + const UpdateGroupState({required this.threeGangList, required this.allSwitches}); + + @override + List get props => [threeGangList, allSwitches]; +} + class FailedState extends ThreeGangState { final String error; diff --git a/lib/features/devices/model/device_category_model.dart b/lib/features/devices/model/device_category_model.dart index ba40509..99ed743 100644 --- a/lib/features/devices/model/device_category_model.dart +++ b/lib/features/devices/model/device_category_model.dart @@ -40,11 +40,9 @@ class DevicesCategoryModel { DevicesCategoryModel.fromJson(Map json) : name = json['groupName'], - id = json['groupId'], - type = devicesTypesMap[json['productType']] ?? DeviceType.Other, - icon = deviceTypeIconMap[ - devicesTypesMap[json['productType']] ?? DeviceType.Other] ?? - '', + // id = json['groupId'], + type = devicesTypesMap[json['groupName']] ?? DeviceType.Other, + icon = deviceTypeIconMap[devicesTypesMap[json['groupName']] ?? DeviceType.Other] ?? '', devices = [], isSelected = false; diff --git a/lib/features/devices/model/group_three_gang_model.dart b/lib/features/devices/model/group_three_gang_model.dart new file mode 100644 index 0000000..76ca7e9 --- /dev/null +++ b/lib/features/devices/model/group_three_gang_model.dart @@ -0,0 +1,15 @@ +class GroupThreeGangModel { + final String deviceId; + final String deviceName; + final bool firstSwitch; + final bool secondSwitch; + final bool thirdSwitch; + + GroupThreeGangModel({ + required this.deviceId, + required this.deviceName, + required this.firstSwitch, + required this.secondSwitch, + required this.thirdSwitch, + }); +} diff --git a/lib/features/devices/view/widgets/ACs/ac_interface.dart b/lib/features/devices/view/widgets/ACs/ac_interface.dart index 5a7ebd2..be6eb4f 100644 --- a/lib/features/devices/view/widgets/ACs/ac_interface.dart +++ b/lib/features/devices/view/widgets/ACs/ac_interface.dart @@ -1,10 +1,16 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; +import 'package:syncrow_app/features/devices/model/ac_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface_controls.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface_temp_unit.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/generated/assets.dart'; class AcInterface extends StatelessWidget { const AcInterface({super.key, required this.ac}); @@ -24,6 +30,23 @@ class AcInterface extends StatelessWidget { } }, builder: (context, state) { + AcStatusModel statusModel = AcStatusModel( + acSwitch: true, + modeString: 'hot', + tempSet: 300, + currentTemp: 315, + fanSpeedsString: 'low', + childLock: false); + + if (state is GetAcStatusState) { + statusModel = state.acStatusModel; + } + if (state is AcChangeLoading) { + statusModel = state.acStatusModel; + } + if (state is AcModifyingState) { + statusModel = state.acStatusModel; + } return // Scaffold( // backgroundColor: ColorsManager.backgroundColor, @@ -34,6 +57,28 @@ class AcInterface extends StatelessWidget { child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ + const SizedBox( + height: 20, + ), + DefaultContainer( + height: 65, + padding: const EdgeInsets.all(15), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + BodyLarge(text: statusModel.acSwitch ? 'On' : 'Off'), + GestureDetector( + onTap: () { + BlocProvider.of(context) + .add(AcSwitch(acSwitch: statusModel.acSwitch)); + }, + child: SvgPicture.asset(Assets.acSwitchIcon)) + ], + ), + ), + const SizedBox( + height: 10, + ), ConstrainedBox( constraints: const BoxConstraints( maxHeight: 380, @@ -51,6 +96,7 @@ class AcInterface extends StatelessWidget { ), child: AcInterfaceControls( deviceModel: ac, + deviceStatus: statusModel, ), ), ], diff --git a/lib/features/devices/view/widgets/ACs/ac_interface_controls.dart b/lib/features/devices/view/widgets/ACs/ac_interface_controls.dart index 8fe7d85..0c04cd6 100644 --- a/lib/features/devices/view/widgets/ACs/ac_interface_controls.dart +++ b/lib/features/devices/view/widgets/ACs/ac_interface_controls.dart @@ -4,45 +4,31 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; +import 'package:syncrow_app/features/devices/model/ac_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_mode_control_unit.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/generated/assets.dart'; class AcInterfaceControls extends StatelessWidget { - const AcInterfaceControls({ - super.key, - required this.deviceModel, - }); + const AcInterfaceControls({super.key, required this.deviceModel, required this.deviceStatus}); final DeviceModel deviceModel; + final AcStatusModel deviceStatus; @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - String lockIconName = Assets.assetsIconsLock; - bool lockValue = false; - - if (state is GetAcStatusState) { - lockIconName = - state.acStatusModel.childLock ? Assets.assetsIconsLock : Assets.assetsIconsUnLock; - lockValue = state.acStatusModel.childLock; - } - if (state is AcChangeLoading) { - lockIconName = - state.acStatusModel.childLock ? Assets.assetsIconsLock : Assets.assetsIconsUnLock; - lockValue = state.acStatusModel.childLock; - } - if (state is AcModifyingState) { - lockIconName = - state.acStatusModel.childLock ? Assets.assetsIconsLock : Assets.assetsIconsUnLock; - lockValue = state.acStatusModel.childLock; - } + String lockIconName = + deviceStatus.childLock ? Assets.assetsIconsLock : Assets.assetsIconsUnLock; return Column( children: [ - ACModeControlUnit(acDevice: deviceModel), + ACModeControlUnit( + acStatus: deviceStatus, + deviceId: deviceModel.uuid ?? '', + ), const SizedBox(height: 10), Row( children: [ @@ -61,7 +47,8 @@ class AcInterfaceControls extends StatelessWidget { Flexible( child: GestureDetector( onTap: () { - BlocProvider.of(context).add(ChangeLock(lockBool: lockValue)); + BlocProvider.of(context) + .add(ChangeLock(lockBool: deviceStatus.childLock)); }, child: DefaultContainer( height: 55, diff --git a/lib/features/devices/view/widgets/ACs/ac_mode_control_unit.dart b/lib/features/devices/view/widgets/ACs/ac_mode_control_unit.dart index 4e34f0e..96698bc 100644 --- a/lib/features/devices/view/widgets/ACs/ac_mode_control_unit.dart +++ b/lib/features/devices/view/widgets/ACs/ac_mode_control_unit.dart @@ -4,48 +4,41 @@ import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; -import 'package:syncrow_app/features/devices/model/device_model.dart'; +import 'package:syncrow_app/features/devices/model/ac_model.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; class ACModeControlUnit extends StatelessWidget { const ACModeControlUnit({ super.key, - required this.acDevice, + required this.acStatus, + required this.deviceId, }); - final DeviceModel acDevice; + final AcStatusModel acStatus; + final String deviceId; @override Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { - // FanSpeeds fanSpeed = FanSpeeds.middle; - // TempModes tempMode = TempModes.cold; return Row( children: [ Flexible( child: GestureDetector( onTap: () { - if (state is GetAcStatusState) { + if (state is! AcChangeLoading && state is! AcsLoadingState) { BlocProvider.of(context) - .add(ChangeFanSpeed(fanSpeeds: state.acStatusModel.acFanSpeed)); - } else if (state is AcModifyingState) { - BlocProvider.of(context) - .add(ChangeFanSpeed(fanSpeeds: state.acStatusModel.acFanSpeed)); + .add(ChangeFanSpeed(fanSpeeds: acStatus.acFanSpeed, deviceId: deviceId)); } + // else if (state is AcModifyingState) { + // BlocProvider.of(context) + // .add(ChangeFanSpeed(fanSpeeds: state.acStatusModel.acFanSpeed)); + // } }, child: DefaultContainer( height: 55, - child: Center( - child: state is GetAcStatusState - ? SvgPicture.asset(fanSpeedsIconMap[state.acStatusModel.acFanSpeed]!) - : state is AcModifyingState - ? SvgPicture.asset(fanSpeedsIconMap[state.acStatusModel.acFanSpeed]!) - : state is AcChangeLoading - ? SvgPicture.asset( - fanSpeedsIconMap[state.acStatusModel.acFanSpeed]!) - : const CircularProgressIndicator()), + child: Center(child: SvgPicture.asset(fanSpeedsIconMap[acStatus.acFanSpeed]!)), ), ), ), @@ -53,24 +46,22 @@ class ACModeControlUnit extends StatelessWidget { Flexible( child: GestureDetector( onTap: () { - if (state is GetAcStatusState) { + // if (state is GetAcStatusState) { + // BlocProvider.of(context) + // .add(ChangeAcMode(tempModes: state.acStatusModel.acMode)); + // } else if (state is AcModifyingState) { + // BlocProvider.of(context) + // .add(ChangeAcMode(tempModes: state.acStatusModel.acMode)); + // } + if (state is! AcChangeLoading && state is! AcsLoadingState) { BlocProvider.of(context) - .add(ChangeAcMode(tempModes: state.acStatusModel.acMode)); - } else if (state is AcModifyingState) { - BlocProvider.of(context) - .add(ChangeAcMode(tempModes: state.acStatusModel.acMode)); + .add(ChangeAcMode(tempModes: acStatus.acMode, deviceId: deviceId)); } }, child: DefaultContainer( height: 55, child: Center( - child: state is GetAcStatusState - ? SvgPicture.asset(tempModesIconMap[state.acStatusModel.acMode]!) - : state is AcModifyingState - ? SvgPicture.asset(tempModesIconMap[state.acStatusModel.acMode]!) - : state is AcChangeLoading - ? SvgPicture.asset(tempModesIconMap[state.acStatusModel.acMode]!) - : const CircularProgressIndicator(), + child: SvgPicture.asset(tempModesIconMap[acStatus.acMode]!), ), ), ), diff --git a/lib/features/devices/view/widgets/ACs/ac_temp_widget.dart b/lib/features/devices/view/widgets/ACs/ac_temp_widget.dart index add9bf3..3368898 100644 --- a/lib/features/devices/view/widgets/ACs/ac_temp_widget.dart +++ b/lib/features/devices/view/widgets/ACs/ac_temp_widget.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; @@ -11,12 +12,14 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/generated/assets.dart'; class ACTempWidget extends StatelessWidget { - const ACTempWidget( - this.deviceModel, { + const ACTempWidget({ + required this.deviceModel, + required this.temp, super.key, }); final DeviceModel deviceModel; + final int temp; @override Widget build(BuildContext context) { @@ -31,8 +34,11 @@ class ACTempWidget extends StatelessWidget { dimension: 24, child: InkWell( onTap: () { - // DevicesCubit.getInstance() - // .setACTemp(DeviceModel, DeviceModel.temperature - 0.5); + double tempC = temp / 10; + if (tempC > 20) { + BlocProvider.of(context) + .add(DecreaseCoolToTemp(value: tempC, deviceId: deviceModel.uuid ?? '')); + } }, child: SvgPicture.asset( Assets.assetsIconsMinus, @@ -40,8 +46,7 @@ class ACTempWidget extends StatelessWidget { ), ), BodyLarge( - // text: "${DeviceModel.temperature}° C", - text: '25 °C', + text: '${temp / 10} °C', style: context.bodyLarge.copyWith( color: ColorsManager.primaryColor.withOpacity(0.6), fontSize: 23, @@ -51,8 +56,11 @@ class ACTempWidget extends StatelessWidget { dimension: 24, child: InkWell( onTap: () { - // DevicesCubit.getInstance() - // .setACTemp(DeviceModel, DeviceModel.temperature + 0.5); + double tempC = temp / 10; + if (tempC < 30) { + BlocProvider.of(context) + .add(IncreaseCoolToTemp(value: tempC, deviceId: deviceModel.uuid ?? '')); + } }, child: SvgPicture.asset( Assets.assetsIconsPlus, diff --git a/lib/features/devices/view/widgets/ACs/acs_list.dart b/lib/features/devices/view/widgets/ACs/acs_list.dart index fe7942f..fd35cb4 100644 --- a/lib/features/devices/view/widgets/ACs/acs_list.dart +++ b/lib/features/devices/view/widgets/ACs/acs_list.dart @@ -1,13 +1,15 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; -import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart'; +import 'package:syncrow_app/features/devices/model/ac_model.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_mode_control_unit.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_temp_widget.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/universal_ac_temp.dart'; import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; @@ -20,76 +22,87 @@ class ACsList extends StatelessWidget { Widget build(BuildContext context) { return BlocBuilder( builder: (context, state) { + List devicesStatuesList = []; + List devicesList = []; + bool allOn = false; + bool allTempSame = false; + int temperature = 20; + if (state is GetAllAcsStatusState) { + devicesStatuesList = state.allAcsStatues; + devicesList = state.allAcs; + allOn = state.allOn; + allTempSame = state.allTempSame; + temperature = state.temp; + } return SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - // universal AC controller - const SizedBox(height: 10), - const BodySmall(text: "All ACs"), - const SizedBox(height: 5), - // UniversalSwitch( - // category: DevicesCubit.getInstance().chosenCategory!, - // ), - const SizedBox(height: 10), - const UniversalACTemp(), - const SizedBox(height: 10), + child: state is AcChangeLoading || state is AcsLoadingState + ? const Center( + child: + DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // universal AC controller + const SizedBox(height: 10), + const BodySmall(text: "All ACs"), + const SizedBox(height: 5), + UniversalSwitch( + allOn: allOn, + ), + const SizedBox(height: 10), + UniversalACTemp( + allTempSame: allTempSame, + temp: temperature, + ), + const SizedBox(height: 10), - // other ACs controls - ListView.builder( - shrinkWrap: true, - physics: const NeverScrollableScrollPhysics(), - padding: const EdgeInsets.all(0), - // itemCount: DevicesCubit.getInstance().chosenCategory!.devices!.length, - itemBuilder: (context, index) { - // DeviceModel ac = DevicesCubit.getInstance().chosenCategory!.devices![index]; - return Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - // BodySmall( - // text: - // DevicesCubit.getInstance().chosenCategory!.devices![index].name ?? - // ""), - IconButton( - onPressed: () { - // DevicesCubit.getInstance().selectDevice(ac); - }, - icon: const Icon( - Icons.arrow_forward_ios, + // other ACs controls + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.all(0), + itemCount: devicesList.length, + itemBuilder: (context, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox( + height: 10, ), - style: ButtonStyle( - padding: MaterialStateProperty.all( - const EdgeInsets.all(0), - ), - iconSize: MaterialStateProperty.all(15), - alignment: Alignment.bottomRight, + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + BodySmall(text: devicesList[index].name ?? ''), + ], ), - ), - ], - ), - const SizedBox(height: 5), - // DevicesDefaultSwitch( - // model: ac, - // ), - // const SizedBox(height: 10), - // ACTempWidget( - // ac, - // ), - // const SizedBox(height: 10), - // ACModeControlUnit( - // acDevice: ac, - // ), - const SizedBox(height: 10), - ], - ); - }, - ), - ], - ), + const SizedBox(height: 5), + DevicesDefaultSwitch( + switchValue: devicesStatuesList[index].acSwitch, + action: () { + BlocProvider.of(context).add(AcSwitch( + acSwitch: devicesStatuesList[index].acSwitch, + deviceId: devicesList[index].uuid ?? '')); + }, + ), + const SizedBox(height: 10), + ACTempWidget( + deviceModel: devicesList[index], + temp: devicesStatuesList[index].tempSet, + ), + const SizedBox(height: 10), + ACModeControlUnit( + acStatus: devicesStatuesList[index], + deviceId: devicesList[index].uuid ?? '', + ), + const SizedBox(height: 10), + ], + ); + }, + ), + ], + ), ); }, ); diff --git a/lib/features/devices/view/widgets/ACs/acs_view.dart b/lib/features/devices/view/widgets/ACs/acs_view.dart index 95f05c1..0567a9e 100644 --- a/lib/features/devices/view/widgets/ACs/acs_view.dart +++ b/lib/features/devices/view/widgets/ACs/acs_view.dart @@ -7,7 +7,6 @@ import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/ac_interface.dart'; import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_list.dart'; -import 'package:syncrow_app/features/devices/view/widgets/ACs/category_view_app_bar.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; @@ -22,14 +21,10 @@ class ACsView extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => ACsBloc(acId: deviceModel?.uuid ?? '')..add(AcsInitial()), + create: (context) => ACsBloc(acId: deviceModel?.uuid ?? '') + ..add(AcsInitial(allAcs: deviceModel != null ? false : true)), child: BlocBuilder( builder: (context, state) { - // BlocProvider.of(context).add(AcsInitial()); - // DeviceModel? selectedAC; - // if (DevicesCubit.getInstance().getSelectedDevice() is DeviceModel) { - // selectedAC = DevicesCubit.getInstance().getSelectedDevice() as DeviceModel; - // } return AnnotatedRegion( value: SystemUiOverlayStyle( statusBarColor: ColorsManager.primaryColor.withOpacity(0.5), @@ -43,7 +38,7 @@ class ACsView extends StatelessWidget { backgroundColor: Colors.transparent, centerTitle: true, title: BodyLarge( - text: deviceModel?.name ?? "", + text: deviceModel?.name ?? "ACs", fontColor: ColorsManager.primaryColor, fontWeight: FontsManager.bold, ), @@ -67,9 +62,10 @@ class ACsView extends StatelessWidget { width: 50, height: 50, child: CircularProgressIndicator()), ) : Container( - padding: const EdgeInsets.only(top: 25), + padding: const EdgeInsets.only(top: 40), alignment: AlignmentDirectional.center, - child: deviceModel != null ? AcInterface(ac: deviceModel!) : ACsList(), + child: + deviceModel != null ? AcInterface(ac: deviceModel!) : const ACsList(), ), ), ), diff --git a/lib/features/devices/view/widgets/ACs/universal_ac_temp.dart b/lib/features/devices/view/widgets/ACs/universal_ac_temp.dart index f6fd355..5a6e735 100644 --- a/lib/features/devices/view/widgets/ACs/universal_ac_temp.dart +++ b/lib/features/devices/view/widgets/ACs/universal_ac_temp.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_svg/svg.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; @@ -10,9 +11,9 @@ import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class UniversalACTemp extends StatelessWidget { - const UniversalACTemp({ - super.key, - }); + const UniversalACTemp({super.key, required this.temp, required this.allTempSame}); + final int temp; + final bool allTempSame; @override Widget build(BuildContext context) { @@ -27,8 +28,10 @@ class UniversalACTemp extends StatelessWidget { dimension: 24, child: InkWell( onTap: () { - // DevicesCubit.getInstance() - // .setTempToAll(DevicesCubit.universalACTemp - .5); + double temperature = temp / 10; + if (temperature < 30) { + BlocProvider.of(context).add(DecreaseAllTemp(value: temperature)); + } }, child: SvgPicture.asset( Assets.assetsIconsMinus, @@ -36,8 +39,7 @@ class UniversalACTemp extends StatelessWidget { ), ), BodyLarge( - // text: "${DevicesCubit.universalACTemp}° C", - text: '25 °C', + text: '${allTempSame ? temp / 10 : '-'} °C', style: context.bodyLarge.copyWith( color: ColorsManager.primaryColor.withOpacity(0.6), fontSize: 23, @@ -47,8 +49,10 @@ class UniversalACTemp extends StatelessWidget { dimension: 24, child: InkWell( onTap: () { - // DevicesCubit.getInstance() - // .setTempToAll(DevicesCubit.universalACTemp + .5); + double temperature = temp / 10; + if (temperature > 20) { + BlocProvider.of(context).add(IncreaseAllTemp(value: temperature)); + } }, child: SvgPicture.asset( Assets.assetsIconsPlus, diff --git a/lib/features/devices/view/widgets/devices_view_body.dart b/lib/features/devices/view/widgets/devices_view_body.dart index e1cb7ec..0da9c17 100644 --- a/lib/features/devices/view/widgets/devices_view_body.dart +++ b/lib/features/devices/view/widgets/devices_view_body.dart @@ -41,7 +41,9 @@ class DevicesViewBody extends StatelessWidget { HomeCubit.getInstance().devicesPageChanged(index); }, children: [ - const WizardPage(), + WizardPage( + groupsList: DevicesCubit.getInstance().allCategories ?? [], + ), if (HomeCubit.getInstance().selectedSpace != null) if (HomeCubit.getInstance().selectedSpace!.rooms != null) ...HomeCubit.getInstance().selectedSpace!.rooms!.map( diff --git a/lib/features/devices/view/widgets/gateway/gateway_view.dart b/lib/features/devices/view/widgets/gateway/gateway_view.dart index 25e1bb6..b677c4a 100644 --- a/lib/features/devices/view/widgets/gateway/gateway_view.dart +++ b/lib/features/devices/view/widgets/gateway/gateway_view.dart @@ -87,11 +87,22 @@ class GateWayView extends StatelessWidget { ), ]), ), - const BodyMedium( - text: 'Zigbee Devices', - fontSize: 15, - fontWeight: FontWeight.w700, - ), + if (devicesList.isEmpty && state is UpdateGatewayState) + Container( + width: MediaQuery.sizeOf(context).width, + alignment: AlignmentDirectional.center, + child: const BodyMedium( + text: 'No devices found', + fontSize: 15, + fontWeight: FontWeight.w700, + ), + ), + if (devicesList.isNotEmpty) + const BodyMedium( + text: 'Zigbee Devices', + fontSize: 15, + fontWeight: FontWeight.w700, + ), const SizedBox( height: 10, ), diff --git a/lib/features/devices/view/widgets/lights/lights_list.dart b/lib/features/devices/view/widgets/lights/lights_list.dart index ec675d7..aafc372 100644 --- a/lib/features/devices/view/widgets/lights/lights_list.dart +++ b/lib/features/devices/view/widgets/lights/lights_list.dart @@ -47,7 +47,10 @@ class LightsList extends StatelessWidget { ], ), const SizedBox(height: 5), - DevicesDefaultSwitch(model: lights[index]), + DevicesDefaultSwitch( + switchValue: false, + action: () {}, + ), const SizedBox(height: 10), LightBrightness(light: lights[index]), ], diff --git a/lib/features/devices/view/widgets/lights/lights_view.dart b/lib/features/devices/view/widgets/lights/lights_view.dart index 21f3301..ad0eb45 100644 --- a/lib/features/devices/view/widgets/lights/lights_view.dart +++ b/lib/features/devices/view/widgets/lights/lights_view.dart @@ -23,8 +23,8 @@ class LightsView extends StatelessWidget { selectedLight = DevicesCubit.getInstance().getSelectedDevice() as DeviceModel; } List lights = []; - if (DevicesCubit.allCategories![1].devices != null) { - for (var device in DevicesCubit.allCategories![1].devices!) { + if (DevicesCubit.getInstance().allCategories![1].devices != null) { + for (var device in DevicesCubit.getInstance().allCategories![1].devices!) { lights.add(device); } } diff --git a/lib/features/devices/view/widgets/lights/lights_view_list.dart b/lib/features/devices/view/widgets/lights/lights_view_list.dart index 25a3795..98e9757 100644 --- a/lib/features/devices/view/widgets/lights/lights_view_list.dart +++ b/lib/features/devices/view/widgets/lights/lights_view_list.dart @@ -29,7 +29,7 @@ class LightsViewList extends StatelessWidget { children: [ const BodySmall(text: "All Lights"), UniversalSwitch( - category: DevicesCubit.allCategories![1], + allOn: false, ), LightsList(lights: lights), ], diff --git a/lib/features/devices/view/widgets/room_page.dart b/lib/features/devices/view/widgets/room_page.dart index 89b12cd..68b2ac1 100644 --- a/lib/features/devices/view/widgets/room_page.dart +++ b/lib/features/devices/view/widgets/room_page.dart @@ -12,23 +12,19 @@ class RoomPage extends StatelessWidget { @override Widget build(BuildContext context) { return SingleChildScrollView( - child: BlocBuilder( - builder: (context, state) { - return GridView.builder( - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 10, - mainAxisSpacing: 10, - childAspectRatio: 1.5, - ), - padding: const EdgeInsets.only(top: 10), - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: room.devices!.length, - itemBuilder: (context, index) { - return RoomPageSwitch(device: room.devices![index]); - }, - ); + child: GridView.builder( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + childAspectRatio: 1.5, + ), + padding: const EdgeInsets.only(top: 10), + physics: const NeverScrollableScrollPhysics(), + shrinkWrap: true, + itemCount: room.devices!.length, + itemBuilder: (context, index) { + return RoomPageSwitch(device: room.devices![index]); }, ), ); diff --git a/lib/features/devices/view/widgets/three_gang/three_gang_interface.dart b/lib/features/devices/view/widgets/three_gang/three_gang_interface.dart index 8507d6e..a109500 100644 --- a/lib/features/devices/view/widgets/three_gang/three_gang_interface.dart +++ b/lib/features/devices/view/widgets/three_gang/three_gang_interface.dart @@ -1,6 +1,5 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; - import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_screen.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; @@ -10,9 +9,9 @@ import 'package:syncrow_app/utils/resource_manager/constants.dart'; import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; class ThreeGangInterface extends StatelessWidget { - const ThreeGangInterface({super.key, required this.gangSwitch}); + const ThreeGangInterface({super.key, this.gangSwitch}); - final DeviceModel gangSwitch; + final DeviceModel? gangSwitch; @override Widget build(BuildContext context) { return AnnotatedRegion( @@ -28,7 +27,7 @@ class ThreeGangInterface extends StatelessWidget { backgroundColor: Colors.transparent, centerTitle: true, title: BodyLarge( - text: gangSwitch.name ?? "", + text: gangSwitch?.name ?? 'Lights', fontColor: ColorsManager.primaryColor, fontWeight: FontsManager.bold, ), @@ -53,9 +52,7 @@ class ThreeGangInterface extends StatelessWidget { right: Constants.defaultPadding, bottom: Constants.bottomNavBarHeight, ), - child: ThreeGangScreen( - device: gangSwitch, - ), + child: ThreeGangScreen(device: gangSwitch), ), ), ), diff --git a/lib/features/devices/view/widgets/three_gang/three_gang_list.dart b/lib/features/devices/view/widgets/three_gang/three_gang_list.dart new file mode 100644 index 0000000..7bbf700 --- /dev/null +++ b/lib/features/devices/view/widgets/three_gang/three_gang_list.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart'; +import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart'; +import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; + +class ThreeGangList extends StatelessWidget { + const ThreeGangList({super.key, required this.threeGangList, required this.allSwitches}); + + final List threeGangList; + final bool allSwitches; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return state is LoadingNewSate + ? const Center( + child: DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), + ) + : SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + const SizedBox(height: 10), + const BodySmall(text: 'All Lights'), + const SizedBox(height: 5), + DevicesDefaultSwitch( + switchValue: allSwitches, + action: () { + BlocProvider.of(context).add(GroupAllOnEvent()); + }, + secondAction: () { + BlocProvider.of(context).add(GroupAllOffEvent()); + }, + ), + ListView.builder( + shrinkWrap: true, + physics: const NeverScrollableScrollPhysics(), + padding: const EdgeInsets.all(0), + itemCount: threeGangList.length, + itemBuilder: (context, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + BodySmall(text: '${threeGangList[index].deviceName} beside light'), + const SizedBox(height: 5), + DevicesDefaultSwitch( + switchValue: threeGangList[index].firstSwitch, + action: () { + BlocProvider.of(context).add( + ChangeFirstSwitchStatusEvent( + value: threeGangList[index].firstSwitch, + deviceId: threeGangList[index].deviceId)); + }, + ), + const SizedBox(height: 10), + BodySmall(text: '${threeGangList[index].deviceName} ceiling light'), + const SizedBox(height: 5), + DevicesDefaultSwitch( + switchValue: threeGangList[index].secondSwitch, + action: () { + BlocProvider.of(context).add( + ChangeSecondSwitchStatusEvent( + value: threeGangList[index].secondSwitch, + deviceId: threeGangList[index].deviceId)); + }, + ), + const SizedBox(height: 10), + BodySmall(text: '${threeGangList[index].deviceName} spotlight'), + const SizedBox(height: 5), + DevicesDefaultSwitch( + switchValue: threeGangList[index].thirdSwitch, + action: () { + BlocProvider.of(context).add( + ChangeThirdSwitchStatusEvent( + value: threeGangList[index].thirdSwitch, + deviceId: threeGangList[index].deviceId)); + }, + ), + ], + ); + }, + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/features/devices/view/widgets/three_gang/three_gang_screen.dart b/lib/features/devices/view/widgets/three_gang/three_gang_screen.dart index 89709c3..f0df734 100644 --- a/lib/features/devices/view/widgets/three_gang/three_gang_screen.dart +++ b/lib/features/devices/view/widgets/three_gang/three_gang_screen.dart @@ -4,26 +4,26 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_blo import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart'; import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; +import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart'; import 'package:syncrow_app/features/devices/model/three_gang_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart'; import 'package:syncrow_app/features/devices/view/widgets/three_gang/schedule_screen.dart'; +import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_list.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class ThreeGangScreen extends StatelessWidget { - const ThreeGangScreen({ - super.key, - required this.device, - }); + const ThreeGangScreen({super.key, this.device}); - final DeviceModel device; + final DeviceModel? device; @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => ThreeGangBloc(threeGangId: device.uuid ?? '')..add(InitialEvent()), + create: (context) => ThreeGangBloc(threeGangId: device?.uuid ?? '') + ..add(InitialEvent(groupScreen: device != null ? false : true)), child: BlocBuilder( builder: (context, state) { ThreeGangModel threeGangModel = ThreeGangModel( @@ -33,335 +33,348 @@ class ThreeGangScreen extends StatelessWidget { firstCountDown: 0, secondCountDown: 0, thirdCountDown: 0); + + List groupThreeGangModel = []; + bool allSwitchesOn = false; + if (state is LoadingNewSate) { threeGangModel = state.threeGangModel; } else if (state is UpdateState) { threeGangModel = state.threeGangModel; + } else if (state is UpdateGroupState) { + groupThreeGangModel = state.threeGangList; + allSwitchesOn = state.allSwitches; } return state is LoadingInitialState ? const Center( child: DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), ) - : Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Expanded(child: SizedBox.shrink()), - Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.center, + : device == null + ? ThreeGangList( + threeGangList: groupThreeGangModel, + allSwitches: allSwitchesOn, + ) + : Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - Column( - children: [ - GangSwitch( - threeGangSwitch: device, - value: threeGangModel.firstSwitch, - action: () { - BlocProvider.of(context).add( - ChangeFirstSwitchStatusEvent( - value: threeGangModel.firstSwitch)); - }, - // control: DeviceControlModel( - // deviceId: device.uuid, - // // code: 'switch_1', - // code: device.status[0].code, - // // value: true, - // value: device.status[0].value, - // ), - ), - const SizedBox(height: 20), - const SizedBox( - width: 70, - child: BodySmall( - text: "Bedside Light", - fontColor: ColorsManager.textPrimaryColor, - textAlign: TextAlign.center, - ), - ), - ], - ), - Column( - children: [ - GangSwitch( - threeGangSwitch: device, - value: threeGangModel.secondSwitch, - action: () { - BlocProvider.of(context).add( - ChangeSecondSwitchStatusEvent( - value: threeGangModel.secondSwitch)); - }, - // control: DeviceControlModel( - // // deviceId: 'bfe10693d4fd263206ocq9', - // // code: 'switch_2', - // // value: true, - // deviceId: device.uuid, - // code: device.status[1].code, - // value: device.status[1].value, - // ), - ), - const SizedBox(height: 20), - const SizedBox( - width: 70, - child: BodySmall( - text: "Ceiling Light", - fontColor: ColorsManager.textPrimaryColor, - textAlign: TextAlign.center, - ), - ), - ], - ), - Column( - children: [ - GangSwitch( - threeGangSwitch: device, - value: threeGangModel.thirdSwitch, - action: () { - BlocProvider.of(context).add( - ChangeThirdSwitchStatusEvent( - value: threeGangModel.thirdSwitch)); - }, - ), - const SizedBox(height: 20), - const SizedBox( - width: 70, - child: BodySmall( - text: "Spotlight", - fontColor: ColorsManager.textPrimaryColor, - textAlign: TextAlign.center, - ), - ), - ], - ), - ], - ), - Expanded( - child: Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, + const Expanded(child: SizedBox.shrink()), + Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, crossAxisAlignment: CrossAxisAlignment.center, children: [ Column( - mainAxisSize: MainAxisSize.min, children: [ - Card( - elevation: 3, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100), - ), - child: GestureDetector( - onTap: () { - // DevicesCubit.getInstance().deviceControl( - // DeviceControlModel( - // deviceId: device.uuid, - // code: 'switch_1', - // value: true, - // ), - // device.uuid!, - // ); - // DevicesCubit.getInstance().deviceControl( - // DeviceControlModel( - // deviceId: device.uuid, - // code: 'switch_2', - // value: true, - // ), - // device.uuid!, - // ); - // DevicesCubit.getInstance().deviceControl( - // DeviceControlModel( - // deviceId: device.uuid, - // code: 'switch_3', - // value: true, - // ), - // device.uuid!, - // ); - BlocProvider.of(context).add(AllOnEvent()); - }, - child: Stack( - alignment: Alignment.center, - children: [ - Container( - width: 60, - height: 60, - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(100), - ), - ), - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(100), - ), - child: Center( - child: BodySmall( - text: "On", - style: context.bodyMedium.copyWith( - color: ColorsManager.primaryColorWithOpacity, - fontWeight: FontWeight.bold), - ), - ), - ), - ], - ), - ), + GangSwitch( + threeGangSwitch: device!, + value: threeGangModel.firstSwitch, + action: () { + BlocProvider.of(context).add( + ChangeFirstSwitchStatusEvent( + value: threeGangModel.firstSwitch)); + }, + // control: DeviceControlModel( + // deviceId: device.uuid, + // // code: 'switch_1', + // code: device.status[0].code, + // // value: true, + // value: device.status[0].value, + // ), ), - const SizedBox(height: 10), - BodySmall( - text: "All On", - style: context.bodyMedium.copyWith( - color: ColorsManager.textPrimaryColor, + const SizedBox(height: 20), + const SizedBox( + width: 70, + child: BodySmall( + text: "Bedside Light", + fontColor: ColorsManager.textPrimaryColor, + textAlign: TextAlign.center, ), ), ], ), - const SizedBox( - width: 20, - ), Column( - mainAxisSize: MainAxisSize.min, children: [ - Card( - elevation: 3, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100), - ), - child: GestureDetector( - onTap: () { - Navigator.push( - context, - PageRouteBuilder( - pageBuilder: (context, animation1, animation2) => - ScheduleScreen( - device: device, - ))); - }, - child: Stack( - alignment: Alignment.center, - children: [ - Container( - width: 60, - height: 60, - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(100), - ), - ), - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(100), - ), - child: Center( - child: Icon( - Icons.access_time, - color: ColorsManager.primaryColorWithOpacity, - size: 25, - ), - ), - ), - ], - ), - ), + GangSwitch( + threeGangSwitch: device!, + value: threeGangModel.secondSwitch, + action: () { + BlocProvider.of(context).add( + ChangeSecondSwitchStatusEvent( + value: threeGangModel.secondSwitch)); + }, + // control: DeviceControlModel( + // // deviceId: 'bfe10693d4fd263206ocq9', + // // code: 'switch_2', + // // value: true, + // deviceId: device.uuid, + // code: device.status[1].code, + // value: device.status[1].value, + // ), ), - const SizedBox(height: 10), - BodySmall( - text: "Timer", - style: context.bodyMedium.copyWith( - color: ColorsManager.textPrimaryColor, + const SizedBox(height: 20), + const SizedBox( + width: 70, + child: BodySmall( + text: "Ceiling Light", + fontColor: ColorsManager.textPrimaryColor, + textAlign: TextAlign.center, ), ), ], ), - const SizedBox( - width: 20, - ), Column( - mainAxisSize: MainAxisSize.min, children: [ - Card( - elevation: 3, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(100), - ), - child: GestureDetector( - onTap: () { - // DevicesCubit.getInstance().deviceControl( - // DeviceControlModel( - // deviceId: device.uuid, - // code: 'switch_1', - // value: false, - // ), - // device.uuid!, - // ); - // DevicesCubit.getInstance().deviceControl( - // DeviceControlModel( - // deviceId: device.uuid, - // code: 'switch_2', - // value: false, - // ), - // device.uuid!, - // ); - // DevicesCubit.getInstance().deviceControl( - // DeviceControlModel( - // deviceId: device.uuid, - // code: 'switch_3', - // value: false, - // ), - // device.uuid!, - // ); - BlocProvider.of(context).add(AllOffEvent()); - }, - child: Stack( - alignment: Alignment.center, - children: [ - Container( - width: 60, - height: 60, - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(100), - ), - ), - Container( - width: 40, - height: 40, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(100), - ), - child: Center( - child: BodySmall( - text: "Off", - style: context.bodyMedium.copyWith( - color: ColorsManager.primaryColorWithOpacity, - fontWeight: FontWeight.bold), - ), - ), - ), - ], - ), - ), + GangSwitch( + threeGangSwitch: device!, + value: threeGangModel.thirdSwitch, + action: () { + BlocProvider.of(context).add( + ChangeThirdSwitchStatusEvent( + value: threeGangModel.thirdSwitch)); + }, ), - const SizedBox(height: 10), - BodySmall( - text: "All Off", - style: context.bodyMedium.copyWith( - color: ColorsManager.textPrimaryColor, + const SizedBox(height: 20), + const SizedBox( + width: 70, + child: BodySmall( + text: "Spotlight", + fontColor: ColorsManager.textPrimaryColor, + textAlign: TextAlign.center, ), ), ], ), ], ), - ), - ), - ], - ); + Expanded( + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Card( + elevation: 3, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100), + ), + child: GestureDetector( + onTap: () { + // DevicesCubit.getInstance().deviceControl( + // DeviceControlModel( + // deviceId: device.uuid, + // code: 'switch_1', + // value: true, + // ), + // device.uuid!, + // ); + // DevicesCubit.getInstance().deviceControl( + // DeviceControlModel( + // deviceId: device.uuid, + // code: 'switch_2', + // value: true, + // ), + // device.uuid!, + // ); + // DevicesCubit.getInstance().deviceControl( + // DeviceControlModel( + // deviceId: device.uuid, + // code: 'switch_3', + // value: true, + // ), + // device.uuid!, + // ); + BlocProvider.of(context).add(AllOnEvent()); + }, + child: Stack( + alignment: Alignment.center, + children: [ + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(100), + ), + ), + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(100), + ), + child: Center( + child: BodySmall( + text: "On", + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontWeight: FontWeight.bold), + ), + ), + ), + ], + ), + ), + ), + const SizedBox(height: 10), + BodySmall( + text: "All On", + style: context.bodyMedium.copyWith( + color: ColorsManager.textPrimaryColor, + ), + ), + ], + ), + const SizedBox( + width: 20, + ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Card( + elevation: 3, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100), + ), + child: GestureDetector( + onTap: () { + Navigator.push( + context, + PageRouteBuilder( + pageBuilder: (context, animation1, animation2) => + ScheduleScreen( + device: device!, + ))); + }, + child: Stack( + alignment: Alignment.center, + children: [ + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(100), + ), + ), + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(100), + ), + child: Center( + child: Icon( + Icons.access_time, + color: ColorsManager.primaryColorWithOpacity, + size: 25, + ), + ), + ), + ], + ), + ), + ), + const SizedBox(height: 10), + BodySmall( + text: "Timer", + style: context.bodyMedium.copyWith( + color: ColorsManager.textPrimaryColor, + ), + ), + ], + ), + const SizedBox( + width: 20, + ), + Column( + mainAxisSize: MainAxisSize.min, + children: [ + Card( + elevation: 3, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(100), + ), + child: GestureDetector( + onTap: () { + // DevicesCubit.getInstance().deviceControl( + // DeviceControlModel( + // deviceId: device.uuid, + // code: 'switch_1', + // value: false, + // ), + // device.uuid!, + // ); + // DevicesCubit.getInstance().deviceControl( + // DeviceControlModel( + // deviceId: device.uuid, + // code: 'switch_2', + // value: false, + // ), + // device.uuid!, + // ); + // DevicesCubit.getInstance().deviceControl( + // DeviceControlModel( + // deviceId: device.uuid, + // code: 'switch_3', + // value: false, + // ), + // device.uuid!, + // ); + BlocProvider.of(context) + .add(AllOffEvent()); + }, + child: Stack( + alignment: Alignment.center, + children: [ + Container( + width: 60, + height: 60, + decoration: BoxDecoration( + color: Colors.grey[300], + borderRadius: BorderRadius.circular(100), + ), + ), + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(100), + ), + child: Center( + child: BodySmall( + text: "Off", + style: context.bodyMedium.copyWith( + color: ColorsManager.primaryColorWithOpacity, + fontWeight: FontWeight.bold), + ), + ), + ), + ], + ), + ), + ), + const SizedBox(height: 10), + BodySmall( + text: "All Off", + style: context.bodyMedium.copyWith( + color: ColorsManager.textPrimaryColor, + ), + ), + ], + ), + ], + ), + ), + ), + ], + ); }, ), ); diff --git a/lib/features/devices/view/widgets/universal_switch.dart b/lib/features/devices/view/widgets/universal_switch.dart index 9112514..0cd5a85 100644 --- a/lib/features/devices/view/widgets/universal_switch.dart +++ b/lib/features/devices/view/widgets/universal_switch.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart'; -import 'package:syncrow_app/features/devices/model/device_category_model.dart'; +import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_event.dart'; +import 'package:syncrow_app/features/devices/bloc/acs_bloc/acs_state.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; @@ -9,31 +10,27 @@ import 'package:syncrow_app/utils/resource_manager/strings_manager.dart'; class UniversalSwitch extends StatelessWidget { const UniversalSwitch({ super.key, - required this.category, + required this.allOn, }); - final DevicesCategoryModel category; + final bool allOn; @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { - bool? status = category.devicesStatus; + // bool? status = category.devicesStatus; return Row( children: [ Expanded( child: InkWell( onTap: () { - DevicesCubit.getInstance().turnAllDevicesOn(category); + BlocProvider.of(context).add(const ChangeAllSwitch(value: true)); }, child: Container( height: 60, decoration: BoxDecoration( - color: status != null - ? status - ? ColorsManager.primaryColor - : Colors.white - : Colors.white, + color: allOn ? ColorsManager.primaryColor : Colors.white, borderRadius: const BorderRadius.only( topLeft: Radius.circular(15), bottomLeft: Radius.circular(15), @@ -42,11 +39,7 @@ class UniversalSwitch extends StatelessWidget { child: Center( child: BodyMedium( text: StringsManager.on, - fontColor: status != null - ? status - ? Colors.white - : null - : null, + fontColor: allOn ? Colors.white : null, fontWeight: FontWeight.bold, ), ), @@ -56,16 +49,12 @@ class UniversalSwitch extends StatelessWidget { Expanded( child: InkWell( onTap: () { - DevicesCubit.getInstance().turnAllDevicesOff(category); + BlocProvider.of(context).add(const ChangeAllSwitch(value: false)); }, child: Container( height: 60, decoration: BoxDecoration( - color: status != null - ? status - ? Colors.white - : ColorsManager.primaryColor - : Colors.white, + color: allOn ? Colors.white : ColorsManager.primaryColor, borderRadius: const BorderRadius.only( topRight: Radius.circular(15), bottomRight: Radius.circular(15), @@ -74,11 +63,7 @@ class UniversalSwitch extends StatelessWidget { child: Center( child: BodyMedium( text: StringsManager.off, - fontColor: status != null - ? status - ? null - : Colors.white - : null, + fontColor: allOn ? null : Colors.white, fontWeight: FontWeight.bold, ), ), diff --git a/lib/features/devices/view/widgets/wizard_page.dart b/lib/features/devices/view/widgets/wizard_page.dart index 9d6bf6d..6639321 100644 --- a/lib/features/devices/view/widgets/wizard_page.dart +++ b/lib/features/devices/view/widgets/wizard_page.dart @@ -1,17 +1,79 @@ -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; -import 'package:syncrow_app/features/devices/view/widgets/wizard_switches.dart'; +import 'package:flutter_svg/svg.dart'; +import 'package:syncrow_app/features/devices/model/device_category_model.dart'; +import 'package:syncrow_app/features/devices/view/widgets/ACs/acs_view.dart'; +import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart'; +import 'package:syncrow_app/features/shared_widgets/default_container.dart'; +import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; +import 'package:syncrow_app/utils/context_extension.dart'; class WizardPage extends StatelessWidget { - const WizardPage({ - super.key, - }); + final List groupsList; + const WizardPage({super.key, required this.groupsList}); @override Widget build(BuildContext context) { - return const SingleChildScrollView( - child: WizartSwitches(), + return GridView.builder( + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 10, + mainAxisSpacing: 10, + childAspectRatio: 1.5, + ), + padding: const EdgeInsets.only(top: 10), + shrinkWrap: true, + itemCount: groupsList.length, + itemBuilder: (_, index) { + return GestureDetector( + onTap: () { + if (groupsList[index].name == 'AC') { + Navigator.push( + context, + PageRouteBuilder( + pageBuilder: (context, animation1, animation2) => const ACsView())); + } + if (groupsList[index].name == '3G') { + Navigator.push( + context, + PageRouteBuilder( + pageBuilder: (context, animation1, animation2) => + const ThreeGangInterface())); + } + }, + child: DefaultContainer( + padding: const EdgeInsets.all(15), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Row( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + SvgPicture.asset( + groupsList[index].icon!, + fit: BoxFit.contain, + ), + // CustomSwitch( + ], + ), + FittedBox( + fit: BoxFit.scaleDown, + child: BodyLarge( + text: groupsList[index].name!, + style: context.bodyLarge.copyWith( + fontWeight: FontWeight.bold, + height: 0, + fontSize: 20, + color: Colors.grey, + ), + ), + ), + ], + ), + ), + ); + }, ); } } diff --git a/lib/features/devices/view/widgets/wizard_switches.dart b/lib/features/devices/view/widgets/wizard_switches.dart deleted file mode 100644 index 7ff490c..0000000 --- a/lib/features/devices/view/widgets/wizard_switches.dart +++ /dev/null @@ -1,97 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:flutter_svg/svg.dart'; -import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart'; -import 'package:syncrow_app/features/shared_widgets/default_container.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; -import 'package:syncrow_app/utils/context_extension.dart'; -import 'package:syncrow_app/utils/helpers/custom_page_route.dart'; - -class WizartSwitches extends StatelessWidget { - const WizartSwitches({ - super.key, - }); - - @override - Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return state is! DevicesLoading - ? DevicesCubit.allCategories != null - ? GridView.builder( - gridDelegate: - const SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, - crossAxisSpacing: 10, - mainAxisSpacing: 10, - childAspectRatio: 1.5, - ), - padding: const EdgeInsets.only(top: 10), - physics: const NeverScrollableScrollPhysics(), - shrinkWrap: true, - itemCount: DevicesCubit.allCategories!.length, - itemBuilder: (_, index) { - return InkWell( - onTap: () { - // DevicesCubit.getInstance().selectCategory(index); - //Navigate to the chosen category view without animation - if (DevicesCubit.getInstance().chosenCategoryView == - null) { - return; - } - Navigator.push(context, - CustomPageRoute(builder: (context) { - return DevicesCubit.getInstance() - .chosenCategoryView!; - })); - }, - child: DefaultContainer( - child: Padding( - padding: const EdgeInsets.only( - top: 10, right: 10, left: 10), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Row( - crossAxisAlignment: CrossAxisAlignment.start, - mainAxisAlignment: - MainAxisAlignment.spaceBetween, - children: [ - SvgPicture.asset( - DevicesCubit.allCategories![index].icon!, - fit: BoxFit.contain, - ), - // CustomSwitch( - ], - ), - Expanded( - child: FittedBox( - fit: BoxFit.scaleDown, - child: BodyLarge( - text: DevicesCubit - .allCategories![index].name!, - style: context.bodyLarge.copyWith( - fontWeight: FontWeight.bold, - height: 0, - fontSize: 24, - color: Colors.grey, - ), - ), - ), - ), - ], - ), - ), - ), - ); - }, - ) - : const SizedBox.shrink() - : const Center( - child: CircularProgressIndicator(), - ); - }, - ); - } -} diff --git a/lib/features/shared_widgets/devices_default_switch.dart b/lib/features/shared_widgets/devices_default_switch.dart index 80511d8..54c88bb 100644 --- a/lib/features/shared_widgets/devices_default_switch.dart +++ b/lib/features/shared_widgets/devices_default_switch.dart @@ -1,79 +1,72 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; -import 'package:syncrow_app/features/devices/bloc/devices_cubit.dart'; -import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class DevicesDefaultSwitch extends StatelessWidget { - const DevicesDefaultSwitch({ - super.key, - required this.model, - }); + const DevicesDefaultSwitch( + {super.key, required this.switchValue, required this.action, this.secondAction}); - final DeviceModel model; + final bool switchValue; + final Function action; + final Function? secondAction; @override Widget build(BuildContext context) { - return BlocBuilder( - builder: (context, state) { - return Row( - children: [ - Expanded( - child: InkWell( - onTap: () { - DevicesCubit.getInstance().turnOnOffDevice(model); - }, - child: Container( - height: 60, - decoration: BoxDecoration( - color: model.isOnline ?? false - ? ColorsManager.primaryColor - : Colors.white, - borderRadius: const BorderRadius.only( - topLeft: Radius.circular(15), - bottomLeft: Radius.circular(15), - ), - ), - child: Center( - child: BodyMedium( - text: "ON", - fontColor: model.isOnline ?? false ? Colors.white : null, - fontWeight: FontWeight.bold, - ), - ), + return Row( + children: [ + Expanded( + child: InkWell( + onTap: () { + action(); + }, + child: Container( + height: 60, + decoration: BoxDecoration( + color: switchValue ? ColorsManager.primaryColor : Colors.white, + borderRadius: const BorderRadius.only( + topLeft: Radius.circular(15), + bottomLeft: Radius.circular(15), + ), + ), + child: Center( + child: BodyMedium( + text: "ON", + fontColor: switchValue ? Colors.white : null, + fontWeight: FontWeight.bold, ), ), ), - Expanded( - child: InkWell( - onTap: () { - DevicesCubit.getInstance().turnOnOffDevice(model); - }, - child: Container( - height: 60, - decoration: BoxDecoration( - color: model.isOnline ?? false - ? Colors.white - : ColorsManager.primaryColor, - borderRadius: const BorderRadius.only( - topRight: Radius.circular(15), - bottomRight: Radius.circular(15), - ), - ), - child: Center( - child: BodyMedium( - text: "OFF", - fontColor: model.isOnline ?? false ? null : Colors.white, - fontWeight: FontWeight.bold, - ), - ), + ), + ), + Expanded( + child: InkWell( + onTap: () { + if (secondAction != null) { + secondAction!(); + } else { + action(); + } + }, + child: Container( + height: 60, + decoration: BoxDecoration( + color: switchValue ? Colors.white : ColorsManager.primaryColor, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(15), + bottomRight: Radius.circular(15), + ), + ), + child: Center( + child: BodyMedium( + text: "OFF", + fontColor: switchValue ? null : Colors.white, + fontWeight: FontWeight.bold, ), ), ), - ], - ); - }, + ), + ), + ], ); } } diff --git a/lib/generated/assets.dart b/lib/generated/assets.dart index eae0990..7cb7b59 100644 --- a/lib/generated/assets.dart +++ b/lib/generated/assets.dart @@ -20,6 +20,7 @@ class Assets { /// Assets for assetsIconsAutomatedClock /// assets/icons/automated_clock.svg static const String assetsIconsAutomatedClock = "assets/icons/automated_clock.svg"; + static const String acSwitchIcon = "assets/icons/ac_switch_ic.svg"; /// Assets for assetsIconsBatteryDmOffPerOffchargOfflowOffpmOffstChargeddmOff /// assets/icons/battery/dmOff/perOffchargOfflowOffpmOffstChargeddmOff.svg diff --git a/lib/services/api/api_links_endpoints.dart b/lib/services/api/api_links_endpoints.dart index 1555b5b..cf771f4 100644 --- a/lib/services/api/api_links_endpoints.dart +++ b/lib/services/api/api_links_endpoints.dart @@ -79,7 +79,9 @@ abstract class ApiEndpoints { static const String addGroup = '$baseUrl/group'; static const String controlGroup = '$baseUrl/group/control'; //GET - static const String groupBySpace = '$baseUrl/group/space/{spaceUuid}'; + static const String groupBySpace = '$baseUrl/group/{unitUuid}'; + static const String devicesByGroupName = '$baseUrl/group/{unitUuid}/devices/{groupName}'; + static const String groupByUuid = '$baseUrl/group/{groupUuid}'; //DELETE static const String deleteGroup = '$baseUrl/group/{groupUuid}'; @@ -96,7 +98,7 @@ abstract class ApiEndpoints { static const String deviceByRoom = '$baseUrl/device/room'; static const String deviceByUuid = '$baseUrl/device/{deviceUuid}'; static const String deviceFunctions = '$baseUrl/device/{deviceUuid}/functions'; - static const String gatewayApi = '$baseUrl/device/getaway/{gatewayUuid}/devices'; + static const String gatewayApi = '$baseUrl/device/gateway/{gatewayUuid}/devices'; static const String deviceFunctionsStatus = '$baseUrl/device/{deviceUuid}/functions/status'; ///Device Permission Module diff --git a/lib/services/api/devices_api.dart b/lib/services/api/devices_api.dart index 64ce38c..0dad548 100644 --- a/lib/services/api/devices_api.dart +++ b/lib/services/api/devices_api.dart @@ -27,13 +27,13 @@ class DevicesAPI { } static Future> fetchGroups(String spaceId) async { - Map params = {"homeId": spaceId, "pageSize": 100, "pageNo": 1}; + // Map params = {"homeId": spaceId, "pageSize": 100, "pageNo": 1}; final response = await _httpService.get( - path: ApiEndpoints.groupBySpace.replaceAll("{spaceUuid}", spaceId), - queryParameters: params, + path: ApiEndpoints.groupBySpace.replaceAll('{unitUuid}', spaceId), + // queryParameters: params, showServerMessage: false, - expectedResponseModel: (json) => DevicesCategoryModel.fromJsonList(json['groups']), + expectedResponseModel: (json) => DevicesCategoryModel.fromJsonList(json), ); return response; } @@ -49,6 +49,26 @@ class DevicesAPI { return response; } + static Future> getDeviceByGroupName(String unitId, String groupName) async { + final response = await _httpService.get( + path: ApiEndpoints.devicesByGroupName + .replaceAll('{unitUuid}', unitId) + .replaceAll('{groupName}', groupName), + showServerMessage: false, + expectedResponseModel: (json) { + if (json == null || json.isEmpty || json == []) { + return []; + } + List devices = []; + for (var device in json) { + devices.add(DeviceModel.fromJson(device)); + } + return devices; + }, + ); + return response; + } + static Future> getDevicesByRoomId(String roomId) async { final response = await _httpService.get( path: ApiEndpoints.deviceByRoom,