diff --git a/lib/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart b/lib/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart index 971682d..636edc7 100644 --- a/lib/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart +++ b/lib/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart @@ -26,11 +26,9 @@ class DoorSensorBloc extends Bloc { bool lowBattery = false; bool closingReminder = false; bool doorAlarm = false; - DoorSensorModel deviceStatus = - DoorSensorModel(doorContactState: false, batteryPercentage: 0); + DoorSensorModel deviceStatus = DoorSensorModel(doorContactState: false, batteryPercentage: 0); - void _fetchWaterHeaterStatus( - DoorSensorInitial event, Emitter emit) async { + void _fetchWaterHeaterStatus(DoorSensorInitial event, Emitter emit) async { emit(DoorSensorLoadingState()); try { var response = await DevicesAPI.getDeviceStatus(DSId); @@ -51,8 +49,7 @@ class DoorSensorBloc extends Bloc { } // Toggle functions for each switch - void _toggleLowBattery( - ToggleLowBatteryEvent event, Emitter emit) async { + void _toggleLowBattery(ToggleLowBatteryEvent event, Emitter emit) async { emit(LoadingNewSate(doorSensor: deviceStatus)); try { lowBattery = event.isLowBatteryEnabled; @@ -93,8 +90,7 @@ class DoorSensorBloc extends Bloc { } } - void _toggleDoorAlarm( - ToggleDoorAlarmEvent event, Emitter emit) async { + void _toggleDoorAlarm(ToggleDoorAlarmEvent event, Emitter emit) async { emit(LoadingNewSate(doorSensor: deviceStatus)); try { doorAlarm = event.isDoorAlarmEnabled; @@ -114,11 +110,9 @@ class DoorSensorBloc extends Bloc { } } - DeviceReport recordGroups = DeviceReport(startTime: 0, endTime: 0, data: []); + DeviceReport recordGroups = DeviceReport(startTime: '0', endTime: '0', data: []); - - Future fetchLogsForLastMonth( - ReportLogsInitial event, Emitter emit) async { + Future fetchLogsForLastMonth(ReportLogsInitial event, Emitter emit) async { // Get the current date and time DateTime now = DateTime.now(); @@ -130,8 +124,7 @@ class DoorSensorBloc extends Bloc { int endTime = now.millisecondsSinceEpoch; try { var response = await DevicesAPI.getReportLogs( - startTime: - startTime.toString(), // Convert to String if the API expects it + startTime: startTime.toString(), // Convert to String if the API expects it endTime: endTime.toString(), // Convert to String if the API expects it deviceUuid: DSId, code: 'doorcontact_state', @@ -149,16 +142,14 @@ class DoorSensorBloc extends Bloc { _listenToChanges() { try { - DatabaseReference ref = - FirebaseDatabase.instance.ref('device-status/$DSId'); + DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$DSId'); Stream stream = ref.onValue; stream.listen((DatabaseEvent event) async { if (_timer != null) { await Future.delayed(const Duration(seconds: 2)); } - Map usersMap = - event.snapshot.value as Map; + Map usersMap = event.snapshot.value as Map; List statusList = []; usersMap['status'].forEach((element) { diff --git a/lib/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart b/lib/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart index 987b873..061dbca 100644 --- a/lib/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart +++ b/lib/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart @@ -24,7 +24,7 @@ class OneGangBloc extends Bloc { bool oneGangGroup = false; List devicesList = []; - OneGangBloc({required this.oneGangId,required this.switchCode}) : super(InitialState()) { + OneGangBloc({required this.oneGangId, required this.switchCode}) : super(InitialState()) { on(_fetchOneGangStatus); on(_oneGangUpdated); on(_changeFirstSwitch); @@ -34,9 +34,6 @@ class OneGangBloc extends Bloc { on(_onTickTimer); on(_onClose); - - - on(toggleDaySelection); on(saveSchedule); on(getSchedule); @@ -114,7 +111,6 @@ class OneGangBloc extends Bloc { } } - void _changeSliding(ChangeSlidingSegment event, Emitter emit) async { emit(ChangeSlidingSegmentState(value: event.value)); } @@ -199,11 +195,14 @@ class OneGangBloc extends Bloc { {"day": "Sat", "key": "Sat"}, ]; - Future saveSchedule(ThreeGangSave event, Emitter emit,) async { + Future saveSchedule( + ThreeGangSave event, + Emitter emit, + ) async { try { - if(selectedDays.isNotEmpty) { + if (selectedDays.isNotEmpty) { emit(LoadingInitialState()); - final response = await DevicesAPI.postSchedule( + await DevicesAPI.postSchedule( category: switchCode, deviceId: oneGangId, time: getTimeStampWithoutSeconds(selectedTime).toString(), @@ -214,7 +213,7 @@ class OneGangBloc extends Bloc { add(GetScheduleEvent()); emit(ThreeGangSaveSchedule()); toggleCreateSchedule(); - }else{ + } else { CustomSnackBar.displaySnackBar('Please select days'); } } catch (e) { @@ -222,13 +221,15 @@ class OneGangBloc extends Bloc { } } - - Future getSchedule(GetScheduleEvent event, Emitter emit,) async { + Future getSchedule( + GetScheduleEvent event, + Emitter emit, + ) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.getSchedule( category: switchCode, - deviceId: oneGangId , + deviceId: oneGangId, ); List jsonData = response; listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList(); @@ -242,13 +243,12 @@ class OneGangBloc extends Bloc { int? getTimeStampWithoutSeconds(DateTime? dateTime) { if (dateTime == null) return null; - DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month, - dateTime.day, dateTime.hour, dateTime.minute); + DateTime dateTimeWithoutSeconds = + DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; } - Future toggleChange( - ToggleScheduleEvent event, Emitter emit) async { + Future toggleChange(ToggleScheduleEvent event, Emitter emit) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.changeSchedule( @@ -267,13 +267,13 @@ class OneGangBloc extends Bloc { } } - Future deleteSchedule( - DeleteScheduleEvent event, Emitter emit) async { + Future deleteSchedule(DeleteScheduleEvent event, Emitter emit) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.deleteSchedule( scheduleId: event.id, - deviceUuid: oneGangId, ); + deviceUuid: oneGangId, + ); if (response == true) { add(GetScheduleEvent()); return toggleSchedule; @@ -291,7 +291,7 @@ class OneGangBloc extends Bloc { emit(LoadingInitialState()); createSchedule = !createSchedule; selectedDays.clear(); - selectedTime=DateTime.now(); + selectedTime = DateTime.now(); emit(UpdateCreateScheduleState(createSchedule)); emit(ChangeSlidingSegmentState(value: 1)); } @@ -300,11 +300,11 @@ class OneGangBloc extends Bloc { List selectedDays = []; bool createSchedule = false; List listSchedule = []; - DateTime? selectedTime=DateTime.now(); + DateTime? selectedTime = DateTime.now(); Future toggleDaySelection( - ToggleDaySelectionEvent event, - Emitter emit, - ) async { + ToggleDaySelectionEvent event, + Emitter emit, + ) async { emit(LoadingInitialState()); if (selectedDays.contains(event.key)) { selectedDays.remove(event.key); @@ -322,5 +322,4 @@ class OneGangBloc extends Bloc { selectedTabIndex = index; emit(ChangeSlidingSegmentState(value: selectedTabIndex)); } - } diff --git a/lib/features/devices/bloc/one_gang_bloc/one_gang_state.dart b/lib/features/devices/bloc/one_gang_bloc/one_gang_state.dart index 17f375a..4078ccf 100644 --- a/lib/features/devices/bloc/one_gang_bloc/one_gang_state.dart +++ b/lib/features/devices/bloc/one_gang_bloc/one_gang_state.dart @@ -1,9 +1,8 @@ import 'package:equatable/equatable.dart'; -import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart'; +import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart'; import 'package:syncrow_app/features/devices/model/one_gang_model.dart'; import 'package:syncrow_app/features/devices/model/two_gang_model.dart'; - class OneGangState extends Equatable { const OneGangState(); @@ -32,13 +31,13 @@ class LoadingNewSate extends OneGangState { } class UpdateGroupState extends OneGangState { - final List twoGangList; + final List oneGangList; final bool allSwitches; - const UpdateGroupState({required this.twoGangList, required this.allSwitches}); + const UpdateGroupState({required this.oneGangList, required this.allSwitches}); @override - List get props => [twoGangList, allSwitches]; + List get props => [oneGangList, allSwitches]; } class FailedState extends OneGangState { @@ -77,13 +76,17 @@ class TimerRunInProgress extends OneGangState { } class TimerRunComplete extends OneGangState {} + class ThreeGangSaveSchedule extends OneGangState {} + class IsToggleState extends OneGangState { final bool? onOff; const IsToggleState({this.onOff}); } + class ChangeTimeState extends OneGangState {} + class UpdateCreateScheduleState extends OneGangState { final bool createSchedule; UpdateCreateScheduleState(this.createSchedule); -} \ No newline at end of file +} 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 a707013..2822b1b 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 @@ -14,7 +14,6 @@ import 'package:syncrow_app/features/devices/model/three_gang_model.dart'; import 'package:syncrow_app/services/api/devices_api.dart'; import 'package:syncrow_app/utils/helpers/snack_bar.dart'; - class ThreeGangBloc extends Bloc { final String threeGangId; final String switchCode; @@ -35,7 +34,7 @@ class ThreeGangBloc extends Bloc { List groupThreeGangList = []; bool allSwitchesOn = true; - ThreeGangBloc({required this.threeGangId,required this.switchCode}) : super(InitialState()) { + ThreeGangBloc({required this.threeGangId, required this.switchCode}) : super(InitialState()) { on(_fetchThreeGangStatus); on(_threeGangUpdated); on(_changeFirstSwitch); @@ -51,8 +50,6 @@ class ThreeGangBloc extends Bloc { on(_groupAllOn); on(_groupAllOff); - - on(toggleDaySelection); on(saveSchedule); on(getSchedule); @@ -490,9 +487,6 @@ class ThreeGangBloc extends Bloc { } } - - - List> days = [ {"day": "Sun", "key": "Sun"}, {"day": "Mon", "key": "Mon"}, @@ -504,9 +498,9 @@ class ThreeGangBloc extends Bloc { ]; Future toggleDaySelection( - ToggleDaySelectionEvent event, - Emitter emit, - ) async { + ToggleDaySelectionEvent event, + Emitter emit, + ) async { emit(LoadingInitialState()); if (selectedDays.contains(event.key)) { selectedDays.remove(event.key); @@ -517,11 +511,14 @@ class ThreeGangBloc extends Bloc { add(ChangeSlidingSegment(value: 1)); } - Future saveSchedule(ThreeGangSave event, Emitter emit,) async { + Future saveSchedule( + ThreeGangSave event, + Emitter emit, + ) async { try { - if(selectedDays.isNotEmpty) { + if (selectedDays.isNotEmpty) { emit(LoadingInitialState()); - final response = await DevicesAPI.postSchedule( + await DevicesAPI.postSchedule( category: switchCode, deviceId: threeGangId, time: getTimeStampWithoutSeconds(selectedTime).toString(), @@ -532,7 +529,7 @@ class ThreeGangBloc extends Bloc { add(GetScheduleEvent()); emit(ThreeGangSaveSchedule()); toggleCreateSchedule(); - }else{ + } else { CustomSnackBar.displaySnackBar('Please select days'); } } catch (e) { @@ -540,13 +537,15 @@ class ThreeGangBloc extends Bloc { } } - - Future getSchedule(GetScheduleEvent event, Emitter emit,) async { + Future getSchedule( + GetScheduleEvent event, + Emitter emit, + ) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.getSchedule( category: switchCode, - deviceId: threeGangId , + deviceId: threeGangId, ); List jsonData = response; listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList(); @@ -560,13 +559,12 @@ class ThreeGangBloc extends Bloc { int? getTimeStampWithoutSeconds(DateTime? dateTime) { if (dateTime == null) return null; - DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month, - dateTime.day, dateTime.hour, dateTime.minute); + DateTime dateTimeWithoutSeconds = + DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; } - Future toggleChange( - ToggleScheduleEvent event, Emitter emit) async { + Future toggleChange(ToggleScheduleEvent event, Emitter emit) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.changeSchedule( @@ -585,13 +583,13 @@ class ThreeGangBloc extends Bloc { } } - Future deleteSchedule( - DeleteScheduleEvent event, Emitter emit) async { + Future deleteSchedule(DeleteScheduleEvent event, Emitter emit) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.deleteSchedule( - scheduleId: event.id, - deviceUuid: threeGangId, ); + scheduleId: event.id, + deviceUuid: threeGangId, + ); if (response == true) { add(GetScheduleEvent()); return toggleSchedule; @@ -609,7 +607,7 @@ class ThreeGangBloc extends Bloc { emit(LoadingInitialState()); createSchedule = !createSchedule; selectedDays.clear(); - selectedTime=DateTime.now(); + selectedTime = DateTime.now(); emit(UpdateCreateScheduleState(createSchedule)); emit(ChangeSlidingSegmentState(value: 1)); } @@ -626,6 +624,5 @@ class ThreeGangBloc extends Bloc { List selectedDays = []; bool createSchedule = false; List listSchedule = []; - DateTime? selectedTime=DateTime.now(); - + DateTime? selectedTime = DateTime.now(); } diff --git a/lib/features/devices/bloc/two_gang_bloc/two_gang_bloc.dart b/lib/features/devices/bloc/two_gang_bloc/two_gang_bloc.dart index b2f1e45..bb1c329 100644 --- a/lib/features/devices/bloc/two_gang_bloc/two_gang_bloc.dart +++ b/lib/features/devices/bloc/two_gang_bloc/two_gang_bloc.dart @@ -7,7 +7,7 @@ import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.d import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_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/groupTwoGangModel.dart'; +import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart'; import 'package:syncrow_app/features/devices/model/schedule_model.dart'; import 'package:syncrow_app/features/devices/model/status_model.dart'; import 'package:syncrow_app/features/devices/model/two_gang_model.dart'; @@ -35,7 +35,7 @@ class TwoGangBloc extends Bloc { bool createSchedule = false; List listSchedule = []; - TwoGangBloc({required this.twoGangId,required this.switchCode}) : super(InitialState()) { + TwoGangBloc({required this.twoGangId, required this.switchCode}) : super(InitialState()) { on(_fetchTwoGangStatus); on(_twoGangUpdated); on(_changeFirstSwitch); @@ -54,7 +54,6 @@ class TwoGangBloc extends Bloc { on(getSchedule); on(toggleRepeat); on(deleteSchedule); - } DateTime? selectedTime = DateTime.now(); @@ -63,10 +62,11 @@ class TwoGangBloc extends Bloc { emit(LoadingInitialState()); createSchedule = !createSchedule; selectedDays.clear(); - selectedTime=DateTime.now(); + selectedTime = DateTime.now(); emit(UpdateCreateScheduleState(createSchedule)); emit(ChangeSlidingSegmentState(value: 1)); } + int selectedTabIndex = 0; void toggleSelectedIndex(index) { @@ -87,8 +87,7 @@ class TwoGangBloc extends Bloc { HomeCubit.getInstance().selectedSpace?.id ?? '', '2G'); for (int i = 0; i < devicesList.length; i++) { - var response = - await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); + var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? ''); List statusModelList = []; for (var status in response['status']) { statusModelList.add(StatusModel.fromJson(status)); @@ -111,8 +110,7 @@ class TwoGangBloc extends Bloc { return true; }); } - emit(UpdateGroupState( - twoGangList: groupTwoGangList, allSwitches: allSwitchesOn)); + emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: allSwitchesOn)); } else { var response = await DevicesAPI.getDeviceStatus(twoGangId); List statusModelList = []; @@ -131,21 +129,18 @@ class TwoGangBloc extends Bloc { _listenToChanges() { try { - DatabaseReference ref = - FirebaseDatabase.instance.ref('device-status/$twoGangId'); + DatabaseReference ref = FirebaseDatabase.instance.ref('device-status/$twoGangId'); Stream stream = ref.onValue; stream.listen((DatabaseEvent event) async { if (_timer != null) { await Future.delayed(const Duration(seconds: 2)); } - Map usersMap = - event.snapshot.value as Map; + Map usersMap = event.snapshot.value as Map; List statusList = []; usersMap['status'].forEach((element) { - statusList - .add(StatusModel(code: element['code'], value: element['value'])); + statusList.add(StatusModel(code: element['code'], value: element['value'])); }); deviceStatus = TwoGangModel.fromJson(statusList); @@ -160,8 +155,7 @@ class TwoGangBloc extends Bloc { emit(UpdateState(twoGangModel: deviceStatus)); } - void _changeFirstSwitch( - ChangeFirstSwitchStatusEvent event, Emitter emit) async { + void _changeFirstSwitch(ChangeFirstSwitchStatusEvent event, Emitter emit) async { emit(LoadingNewSate(twoGangModel: deviceStatus)); try { deviceStatus.firstSwitch = !event.value; @@ -187,8 +181,7 @@ class TwoGangBloc extends Bloc { } } - void _changeSecondSwitch( - ChangeSecondSwitchStatusEvent event, Emitter emit) async { + void _changeSecondSwitch(ChangeSecondSwitchStatusEvent event, Emitter emit) async { emit(LoadingNewSate(twoGangModel: deviceStatus)); try { deviceStatus.secondSwitch = !event.value; @@ -224,15 +217,11 @@ class TwoGangBloc extends Bloc { final response = await Future.wait([ DevicesAPI.controlDevice( DeviceControlModel( - deviceId: twoGangId, - code: 'switch_1', - value: deviceStatus.firstSwitch), + deviceId: twoGangId, code: 'switch_1', value: deviceStatus.firstSwitch), twoGangId), DevicesAPI.controlDevice( DeviceControlModel( - deviceId: twoGangId, - code: 'switch_2', - value: deviceStatus.secondSwitch), + deviceId: twoGangId, code: 'switch_2', value: deviceStatus.secondSwitch), twoGangId), ]); @@ -255,15 +244,11 @@ class TwoGangBloc extends Bloc { final response = await Future.wait([ DevicesAPI.controlDevice( DeviceControlModel( - deviceId: twoGangId, - code: 'switch_1', - value: deviceStatus.firstSwitch), + deviceId: twoGangId, code: 'switch_1', value: deviceStatus.firstSwitch), twoGangId), DevicesAPI.controlDevice( DeviceControlModel( - deviceId: twoGangId, - code: 'switch_2', - value: deviceStatus.secondSwitch), + deviceId: twoGangId, code: 'switch_2', value: deviceStatus.secondSwitch), twoGangId), ]); if (response.every((element) => !element['success'])) { @@ -289,15 +274,11 @@ class TwoGangBloc extends Bloc { final response = await Future.wait([ DevicesAPI.controlDevice( DeviceControlModel( - deviceId: groupTwoGangList[i].deviceId, - code: 'switch_1', - value: true), + deviceId: groupTwoGangList[i].deviceId, code: 'switch_1', value: true), groupTwoGangList[i].deviceId), DevicesAPI.controlDevice( DeviceControlModel( - deviceId: groupTwoGangList[i].deviceId, - code: 'switch_2', - value: true), + deviceId: groupTwoGangList[i].deviceId, code: 'switch_2', value: true), groupTwoGangList[i].deviceId), ]); @@ -326,15 +307,11 @@ class TwoGangBloc extends Bloc { final response = await Future.wait([ DevicesAPI.controlDevice( DeviceControlModel( - deviceId: groupTwoGangList[i].deviceId, - code: 'switch_1', - value: false), + deviceId: groupTwoGangList[i].deviceId, code: 'switch_1', value: false), groupTwoGangList[i].deviceId), DevicesAPI.controlDevice( DeviceControlModel( - deviceId: groupTwoGangList[i].deviceId, - code: 'switch_2', - value: false), + deviceId: groupTwoGangList[i].deviceId, code: 'switch_2', value: false), groupTwoGangList[i].deviceId), ]); @@ -350,29 +327,23 @@ class TwoGangBloc extends Bloc { } } - void _changeSliding( - ChangeSlidingSegment event, Emitter emit) async { + void _changeSliding(ChangeSlidingSegment event, Emitter emit) async { emit(ChangeSlidingSegmentState(value: event.value)); } - void _setCounterValue( - SetCounterValue event, Emitter emit) async { + void _setCounterValue(SetCounterValue event, Emitter emit) async { emit(LoadingNewSate(twoGangModel: deviceStatus)); int seconds = 0; try { seconds = event.duration.inSeconds; final response = await DevicesAPI.controlDevice( - DeviceControlModel( - deviceId: twoGangId, - code: event.deviceCode, - value: seconds), + DeviceControlModel(deviceId: twoGangId, code: event.deviceCode, value: seconds), twoGangId); if (response['success'] ?? false) { if (event.deviceCode == 'countdown_1') { deviceStatus.firstCountDown = seconds; - } - else if (event.deviceCode == 'countdown_2') { + } else if (event.deviceCode == 'countdown_2') { deviceStatus.secondCountDown = seconds; } } else { @@ -391,8 +362,7 @@ class TwoGangBloc extends Bloc { } } - void _getCounterValue( - GetCounterEvent event, Emitter emit) async { + void _getCounterValue(GetCounterEvent event, Emitter emit) async { emit(LoadingInitialState()); try { add(GetScheduleEvent()); @@ -462,9 +432,12 @@ class TwoGangBloc extends Bloc { add(ChangeSlidingSegment(value: 1)); } - Future saveSchedule(TwoGangSave event, Emitter emit,) async { + Future saveSchedule( + TwoGangSave event, + Emitter emit, + ) async { try { - if(selectedDays.isNotEmpty) { + if (selectedDays.isNotEmpty) { emit(LoadingInitialState()); final response = await DevicesAPI.postSchedule( category: switchCode, @@ -477,7 +450,7 @@ class TwoGangBloc extends Bloc { add(GetScheduleEvent()); emit(TwoGangSaveSchedule()); toggleCreateSchedule(); - }else{ + } else { CustomSnackBar.displaySnackBar('Please select days'); } } catch (e) { @@ -485,7 +458,10 @@ class TwoGangBloc extends Bloc { } } - Future getSchedule(GetScheduleEvent event, Emitter emit,) async { + Future getSchedule( + GetScheduleEvent event, + Emitter emit, + ) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.getSchedule( @@ -504,19 +480,16 @@ class TwoGangBloc extends Bloc { int? getTimeStampWithoutSeconds(DateTime? dateTime) { if (dateTime == null) return null; - DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month, - dateTime.day, dateTime.hour, dateTime.minute); + DateTime dateTimeWithoutSeconds = + DateTime(dateTime.year, dateTime.month, dateTime.day, dateTime.hour, dateTime.minute); return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000; } - Future toggleRepeat( - ToggleScheduleEvent event, Emitter emit) async { + Future toggleRepeat(ToggleScheduleEvent event, Emitter emit) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.changeSchedule( - scheduleId: event.id, - deviceUuid: twoGangId, - enable: event.toggle); + scheduleId: event.id, deviceUuid: twoGangId, enable: event.toggle); if (response == true) { add(GetScheduleEvent()); toggleSchedule = event.toggle; @@ -531,13 +504,13 @@ class TwoGangBloc extends Bloc { } } - Future deleteSchedule( - DeleteScheduleEvent event, Emitter emit) async { + Future deleteSchedule(DeleteScheduleEvent event, Emitter emit) async { try { emit(LoadingInitialState()); final response = await DevicesAPI.deleteSchedule( scheduleId: event.id, - deviceUuid: twoGangId, ); + deviceUuid: twoGangId, + ); if (response == true) { add(GetScheduleEvent()); return toggleSchedule; diff --git a/lib/features/devices/bloc/two_gang_bloc/two_gang_state.dart b/lib/features/devices/bloc/two_gang_bloc/two_gang_state.dart index 72c8537..3435e4d 100644 --- a/lib/features/devices/bloc/two_gang_bloc/two_gang_state.dart +++ b/lib/features/devices/bloc/two_gang_bloc/two_gang_state.dart @@ -1,8 +1,7 @@ import 'package:equatable/equatable.dart'; -import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart'; +import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart'; import 'package:syncrow_app/features/devices/model/two_gang_model.dart'; - class TwoGangState extends Equatable { const TwoGangState(); @@ -11,7 +10,9 @@ class TwoGangState extends Equatable { } class InitialState extends TwoGangState {} + class TwoGangSaveSchedule extends TwoGangState {} + class ChangeTimeState extends TwoGangState {} class LoadingInitialState extends TwoGangState {} @@ -78,13 +79,12 @@ class TimerRunInProgress extends TwoGangState { } class TimerRunComplete extends TwoGangState {} + class IsToggleState extends TwoGangState { final bool? onOff; const IsToggleState({this.onOff}); } - - // two_gang_state.dart class UpdateCreateScheduleState extends TwoGangState { final bool createSchedule; diff --git a/lib/features/devices/model/device_report_model.dart b/lib/features/devices/model/device_report_model.dart index 05604b2..b73dc77 100644 --- a/lib/features/devices/model/device_report_model.dart +++ b/lib/features/devices/model/device_report_model.dart @@ -1,7 +1,7 @@ class DeviceReport { final String? deviceUuid; - final int? startTime; - final int? endTime; + final String? startTime; + final String? endTime; final List? data; DeviceReport({ @@ -13,8 +13,8 @@ class DeviceReport { DeviceReport.fromJson(Map json) : deviceUuid = json['deviceUuid'] as String?, - startTime = json['startTime'] as int?, - endTime = json['endTime'] as int?, + startTime = json['startTime'] as String?, + endTime = json['endTime'] as String?, data = (json['data'] as List?) ?.map((e) => DeviceEvent.fromJson(e as Map)) .toList(); diff --git a/lib/features/devices/model/group_one_gang_model.dart b/lib/features/devices/model/group_one_gang_model.dart new file mode 100644 index 0000000..419f127 --- /dev/null +++ b/lib/features/devices/model/group_one_gang_model.dart @@ -0,0 +1,11 @@ +class GroupOneGangModel { + final String deviceId; + final String deviceName; + bool firstSwitch; + + GroupOneGangModel({ + required this.deviceId, + required this.deviceName, + required this.firstSwitch, + }); +} diff --git a/lib/features/devices/model/groupTwoGangModel.dart b/lib/features/devices/model/group_two_gang_model.dart similarity index 100% rename from lib/features/devices/model/groupTwoGangModel.dart rename to lib/features/devices/model/group_two_gang_model.dart diff --git a/lib/features/devices/view/widgets/curtains/curtain_list.dart b/lib/features/devices/view/widgets/curtains/curtain_list.dart index bf3900d..4c66149 100644 --- a/lib/features/devices/view/widgets/curtains/curtain_list.dart +++ b/lib/features/devices/view/widgets/curtains/curtain_list.dart @@ -1,9 +1,6 @@ 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/devices/view/widgets/universal_switch.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 CurtainList extends StatelessWidget { diff --git a/lib/features/devices/view/widgets/curtains/curtain_view.dart b/lib/features/devices/view/widgets/curtains/curtain_view.dart index 153bce8..9f89aa2 100644 --- a/lib/features/devices/view/widgets/curtains/curtain_view.dart +++ b/lib/features/devices/view/widgets/curtains/curtain_view.dart @@ -20,16 +20,16 @@ class CurtainView extends StatelessWidget { child: BlocBuilder( builder: (context, state) { double curtainWidth = 270; - double blindHeight = 310; + // double blindHeight = 310; if (state is CurtainsOpening) { curtainWidth = state.curtainWidth; - blindHeight = state.blindHeight; + // blindHeight = state.blindHeight; } else if (state is CurtainsClosing) { curtainWidth = state.curtainWidth; - blindHeight = state.blindHeight; + // blindHeight = state.blindHeight; } else if (state is CurtainsPaused) { curtainWidth = state.curtainWidth; - blindHeight = state.blindHeight; + // blindHeight = state.blindHeight; } return DefaultScaffold( title: curtain.name, @@ -58,7 +58,8 @@ class CurtainView extends StatelessWidget { width: curtainWidth, child: Stack( children: List.generate( - 10, (index) { + 10, + (index) { double spacing = curtainWidth / 9; double leftMostPosition = index * spacing; return AnimatedPositioned( diff --git a/lib/features/devices/view/widgets/device_appbar.dart b/lib/features/devices/view/widgets/device_appbar.dart index 7de34d7..9640429 100644 --- a/lib/features/devices/view/widgets/device_appbar.dart +++ b/lib/features/devices/view/widgets/device_appbar.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/app_layout/bloc/home_cubit.dart'; import 'package:syncrow_app/features/devices/view/widgets/popup_menu_widget.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; @@ -11,30 +10,33 @@ class DeviceAppbar extends StatelessWidget implements PreferredSizeWidget { final String deviceUuid; final double appBarHeight = 56.0; final void Function()? onPressed; - const DeviceAppbar({super.key, required this.deviceName, required this.deviceUuid,this.onPressed}); + const DeviceAppbar( + {super.key, required this.deviceName, required this.deviceUuid, this.onPressed}); @override Widget build(BuildContext context) { - return AppBar( + return AppBar( backgroundColor: Colors.transparent, centerTitle: true, title: BodyLarge( - text: deviceName ?? "", + text: deviceName, fontColor: ColorsManager.primaryColor, fontWeight: FontsManager.bold, ), actions: [ - IconButton(onPressed: () { - showPopupMenu(context: context, items: [ - PopupMenuItem( - onTap: () async { - HomeCubit.getInstance().updateDevice(deviceUuid); - }, - value: 'Update', - child: const Text('Update'), - ) - ]); - }, icon: Icon(Icons.edit)) + IconButton( + onPressed: () { + showPopupMenu(context: context, items: [ + PopupMenuItem( + onTap: () async { + HomeCubit.getInstance().updateDevice(deviceUuid); + }, + value: 'Update', + child: const Text('Update'), + ) + ]); + }, + icon: Icon(Icons.edit)) ], ); } diff --git a/lib/features/devices/view/widgets/door_sensor/door_notification_settings.dart b/lib/features/devices/view/widgets/door_sensor/door_notification_settings.dart index 462e28c..6bb6d6f 100644 --- a/lib/features/devices/view/widgets/door_sensor/door_notification_settings.dart +++ b/lib/features/devices/view/widgets/door_sensor/door_notification_settings.dart @@ -4,7 +4,6 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_event.dart'; import 'package:syncrow_app/features/devices/bloc/door_sensor_bloc/door_sensor_state.dart'; -import 'package:syncrow_app/features/devices/model/door_sensor_model.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; @@ -16,24 +15,15 @@ class NotificationSettingsPage extends StatelessWidget { return DefaultScaffold( title: 'Notification Settings', child: BlocProvider( - create: (context) => - DoorSensorBloc(DSId: '')..add(const DoorSensorInitial()), + create: (context) => DoorSensorBloc(DSId: '')..add(const DoorSensorInitial()), child: BlocBuilder( builder: (context, state) { final doorSensorBloc = BlocProvider.of(context); - DoorSensorModel model = DoorSensorModel( - batteryPercentage: 0, doorContactState: false); - if (state is LoadingNewSate) { - model = state.doorSensor; - } else if (state is UpdateState) { - model = state.doorSensor; - } + return state is DoorSensorLoadingState ? const Center( child: DefaultContainer( - width: 50, - height: 50, - child: CircularProgressIndicator()), + width: 50, height: 50, child: CircularProgressIndicator()), ) : Column( children: [ @@ -56,8 +46,9 @@ class NotificationSettingsPage extends StatelessWidget { child: CupertinoSwitch( value: doorSensorBloc.lowBattery, onChanged: (value) { - context.read().add( - ToggleLowBatteryEvent(value)); + context + .read() + .add(ToggleLowBatteryEvent(value)); }, applyTheme: true, )), @@ -79,9 +70,9 @@ class NotificationSettingsPage extends StatelessWidget { child: CupertinoSwitch( value: doorSensorBloc.closingReminder, onChanged: (value) { - context.read().add( - ToggleClosingReminderEvent( - value)); + context + .read() + .add(ToggleClosingReminderEvent(value)); }, applyTheme: true, )), diff --git a/lib/features/devices/view/widgets/door_sensor/door_records_screen.dart b/lib/features/devices/view/widgets/door_sensor/door_records_screen.dart index 39635c8..11b5d34 100644 --- a/lib/features/devices/view/widgets/door_sensor/door_records_screen.dart +++ b/lib/features/devices/view/widgets/door_sensor/door_records_screen.dart @@ -35,8 +35,7 @@ class DoorRecordsScreen extends StatelessWidget { return DefaultScaffold( title: 'Records', child: BlocProvider( - create: (context) => - DoorSensorBloc(DSId: DSId)..add(const ReportLogsInitial()), + create: (context) => DoorSensorBloc(DSId: DSId)..add(const ReportLogsInitial()), child: BlocBuilder( builder: (context, state) { if (state is DoorSensorLoadingState) { @@ -49,12 +48,10 @@ class DoorRecordsScreen extends StatelessWidget { ); } - if (state is UpdateState && state.doorSensor != null) { + if (state is UpdateState) { final recordGroups = context.read().recordGroups; - if (recordGroups == null || - recordGroups.data == null || - recordGroups.data!.isEmpty) { + if (recordGroups.data == null || recordGroups.data!.isEmpty) { return const Center(child: Text('No records available.')); } @@ -66,10 +63,8 @@ class DoorRecordsScreen extends StatelessWidget { // Convert eventTime to a human-readable format final DateTime eventDateTime = DateTime.fromMillisecondsSinceEpoch(record.eventTime!); - final String formattedDate = - DateFormat('EEEE, dd/MM/yyyy').format(eventDateTime); - final String formattedTime = - DateFormat('HH:mm:ss').format(eventDateTime); + final String formattedDate = DateFormat('EEEE, dd/MM/yyyy').format(eventDateTime); + final String formattedTime = DateFormat('HH:mm:ss').format(eventDateTime); return Column( crossAxisAlignment: CrossAxisAlignment.start, @@ -92,9 +87,7 @@ class DoorRecordsScreen extends StatelessWidget { record.value == 'true' ? Icons.radio_button_checked : Icons.radio_button_unchecked, - color: record.value == 'true' - ? Colors.blue - : Colors.grey, + color: record.value == 'true' ? Colors.blue : Colors.grey, ), title: Text( 'Status: ${record.value}', diff --git a/lib/features/devices/view/widgets/gateway/gateway_view.dart b/lib/features/devices/view/widgets/gateway/gateway_view.dart index 62ce1ed..0fa9831 100644 --- a/lib/features/devices/view/widgets/gateway/gateway_view.dart +++ b/lib/features/devices/view/widgets/gateway/gateway_view.dart @@ -8,12 +8,10 @@ import 'package:syncrow_app/features/devices/bloc/gateway_bloc/gateway_state.dar import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart'; import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart'; -import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/constants.dart'; -import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; class GateWayView extends StatelessWidget { final DeviceModel gatewayObj; @@ -38,9 +36,10 @@ class GateWayView extends StatelessWidget { backgroundColor: ColorsManager.backgroundColor, extendBodyBehindAppBar: true, extendBody: true, - appBar:DeviceAppbar( - deviceName: 'Gateway', - deviceUuid: gatewayObj.uuid!,), + appBar: DeviceAppbar( + deviceName: 'Gateway', + deviceUuid: gatewayObj.uuid!, + ), body: Container( width: MediaQuery.sizeOf(context).width, height: MediaQuery.sizeOf(context).height, @@ -55,11 +54,11 @@ class GateWayView extends StatelessWidget { ), ), child: RefreshIndicator( - onRefresh:()async { - BlocProvider.of(context).add(GatewayInitial(gatewayId: gatewayObj.uuid ?? '')); - }, - child: ListView( - + onRefresh: () async { + BlocProvider.of(context) + .add(GatewayInitial(gatewayId: gatewayObj.uuid ?? '')); + }, + child: ListView( children: [ Container( height: MediaQuery.of(context).size.height, @@ -120,7 +119,8 @@ class GateWayView extends StatelessWidget { ) : Expanded( child: GridView.builder( - gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + gridDelegate: + const SliverGridDelegateWithFixedCrossAxisCount( crossAxisCount: 2, crossAxisSpacing: 10, mainAxisSpacing: 10, @@ -141,8 +141,7 @@ class GateWayView extends StatelessWidget { ], ), ), - ) - )); + ))); })); } } 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 98e9757..576a103 100644 --- a/lib/features/devices/view/widgets/lights/lights_view_list.dart +++ b/lib/features/devices/view/widgets/lights/lights_view_list.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.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/devices/view/widgets/lights/lights_list.dart'; import 'package:syncrow_app/features/devices/view/widgets/universal_switch.dart'; diff --git a/lib/features/devices/view/widgets/offline_one_time_password_page.dart b/lib/features/devices/view/widgets/offline_one_time_password_page.dart index 6c560cd..baadcc8 100644 --- a/lib/features/devices/view/widgets/offline_one_time_password_page.dart +++ b/lib/features/devices/view/widgets/offline_one_time_password_page.dart @@ -1,5 +1,3 @@ - -import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_bloc/flutter_bloc.dart'; @@ -7,7 +5,6 @@ import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_blo import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_event.dart'; import 'package:syncrow_app/features/devices/bloc/smart_door_bloc/smart_door_state.dart'; import 'package:syncrow_app/features/devices/view/widgets/smart_door/repeat_widget.dart'; -import 'package:syncrow_app/features/shared_widgets/default_button.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; import 'package:syncrow_app/features/shared_widgets/door_lock_button.dart'; @@ -29,14 +26,12 @@ class OfflineOneTimePasswordPage extends StatelessWidget { create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!), child: BlocConsumer(listener: (context, state) { if (state is FailedState) { - CustomSnackBar.displaySnackBar( - state.errorMessage - ); + CustomSnackBar.displaySnackBar(state.errorMessage); } - if (state is IsRepeatState){ + if (state is IsRepeatState) { isRepeat = state.repeat; } - if (state is GeneratePasswordOneTimestate ){ + if (state is GeneratePasswordOneTimestate) { generated = state.generated; } }, builder: (context, state) { @@ -54,170 +49,173 @@ class OfflineOneTimePasswordPage extends StatelessWidget { onPressed: () { Navigator.of(context).pop(true); }, - icon: const Icon(Icons.arrow_back) - ), + icon: const Icon(Icons.arrow_back)), ), child: state is LoadingInitialState ? const Center(child: CircularProgressIndicator()) : SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const BodyMedium( - text: 'Save the password immediately. The password is not displayed in the app.', - fontWeight: FontWeight.normal, - fontColor: ColorsManager.grayColor, - ), - const SizedBox( - height: 20, - ), - const BodyMedium( - text: '7-Digit Password', - fontWeight: FontWeight.normal, - fontColor: ColorsManager.grayColor, - ), - DefaultContainer( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, children: [ - Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.max, - children: [ - Flexible( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children:smartDoorBloc.passwordController.text.isEmpty? - List.generate(10, (index) { - return const Padding( - padding: EdgeInsets.symmetric(horizontal: 4.0,vertical: 15), - child: Icon( - Icons.circle, - size: 20.0, - color: Colors.black, - ), - ); - }) :[ - Expanded( - child: Row( - children: [ - - Expanded( - child: BodyLarge( - style: const TextStyle( - color: ColorsManager.primaryColor, - fontWeight: FontWeight.bold, - letterSpacing: 8.0 , - fontSize: 25, - wordSpacing: 2), - textAlign: TextAlign.center, - text: smartDoorBloc.passwordController.text, - fontSize: 23, - ),), - - IconButton( - onPressed: () async { - await Clipboard.setData(ClipboardData( - text: smartDoorBloc.passwordController.text)); - }, - icon: const Icon(Icons.copy) - ), - ], - ), - ), - ], - )), - const SizedBox( - width: 10, - ), - - ], + const BodyMedium( + text: + 'Save the password immediately. The password is not displayed in the app.', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, ), - if(smartDoorBloc.passwordController.text.isNotEmpty) - Column( + const SizedBox( + height: 20, + ), + const BodyMedium( + text: '7-Digit Password', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + DefaultContainer( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + child: Column( children: [ - const Divider( - color: ColorsManager.graysColor, - ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, children: [ - Expanded( - child: Container( - padding: const EdgeInsets.all(10.0), - child: const BodyMedium( - text: 'Password Name', - fontWeight: FontWeight.normal, - ), - ), + Flexible( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: smartDoorBloc.passwordController.text.isEmpty + ? List.generate(10, (index) { + return const Padding( + padding: EdgeInsets.symmetric( + horizontal: 4.0, vertical: 15), + child: Icon( + Icons.circle, + size: 20.0, + color: Colors.black, + ), + ); + }) + : [ + Expanded( + child: Row( + children: [ + Expanded( + child: BodyLarge( + style: const TextStyle( + color: ColorsManager.primaryColor, + fontWeight: FontWeight.bold, + letterSpacing: 8.0, + fontSize: 25, + wordSpacing: 2), + textAlign: TextAlign.center, + text: smartDoorBloc.passwordController.text, + fontSize: 23, + ), + ), + IconButton( + onPressed: () async { + await Clipboard.setData(ClipboardData( + text: smartDoorBloc + .passwordController.text)); + }, + icon: const Icon(Icons.copy)), + ], + ), + ), + ], + )), + const SizedBox( + width: 10, ), - SizedBox( - width: MediaQuery.of(context).size.width / 2.6, - child: TextFormField( - controller: BlocProvider.of(context).passwordNameController, - decoration: const InputDecoration( - hintText: 'Enter The Name', - hintStyle: TextStyle( - fontSize: 14, color: ColorsManager.textGray)), - )), ], ), - + if (smartDoorBloc.passwordController.text.isNotEmpty) + Column( + children: [ + const Divider( + color: ColorsManager.graysColor, + ), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Expanded( + child: Container( + padding: const EdgeInsets.all(10.0), + child: const BodyMedium( + text: 'Password Name', + fontWeight: FontWeight.normal, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width / 2.6, + child: TextFormField( + controller: BlocProvider.of(context) + .passwordNameController, + decoration: const InputDecoration( + hintText: 'Enter The Name', + hintStyle: TextStyle( + fontSize: 14, color: ColorsManager.textGray)), + )), + ], + ), + ], + ), ], ), + ), + const SizedBox( + height: 20, + ), + const BodyMedium( + textAlign: TextAlign.center, + text: + 'Save the password immediately. The password is not displayed in the app.', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + + // NameTimeWidget(type:type!), + const SizedBox( + height: 20, + ), + Center( + child: SizedBox( + width: MediaQuery.of(context).size.width / 1.5, + child: DoorLockButton( + isDone: generated, + isLoading: smartDoorBloc.isSavingPassword, + borderRadius: 30, + backgroundColor: ColorsManager.primaryColor, + onPressed: () async { + if (generated == false) { + smartDoorBloc + .add(GenerateAndSavePasswordOneTimeEvent(context: context)); + } else { + if (smartDoorBloc.passwordNameController.text.isNotEmpty) { + smartDoorBloc.add(RenamePasswordEvent()); + } + Navigator.of(context).pop(true); + } + }, + child: const BodyMedium( + text: 'Obtain Password', + fontWeight: FontWeight.bold, + fontColor: Colors.white, + ), + ), + ), + ), + const SizedBox( + height: 20, + ), + isRepeat ? const RepeatWidget() : const SizedBox(), + const SizedBox( + height: 40, + ) ], ), ), - const SizedBox( - height: 20, - ), - const BodyMedium( - textAlign: TextAlign.center, - text: 'Save the password immediately. The password is not displayed in the app.', - fontWeight: FontWeight.normal, - fontColor: ColorsManager.grayColor, - ), - - // NameTimeWidget(type:type!), - const SizedBox( - height: 20, - ), - Center( - child: SizedBox( - width: MediaQuery.of(context).size.width/1.5, - child: DoorLockButton( - isDone: generated, - isLoading: smartDoorBloc.isSavingPassword , - borderRadius: 30, - backgroundColor:ColorsManager.primaryColor , - onPressed: () async { - if(generated==false){ - smartDoorBloc.add(GenerateAndSavePasswordOneTimeEvent(context: context)); - }else{ - if(smartDoorBloc.passwordNameController.text.isNotEmpty){ - smartDoorBloc.add(RenamePasswordEvent()); - } - Navigator.of(context).pop(true); - } - }, - child: const BodyMedium( - text: 'Obtain Password', - fontWeight: FontWeight.bold, - fontColor: Colors.white, - ),), - ), - ), - const SizedBox( - height: 20, - ), - isRepeat? const RepeatWidget():const SizedBox(), - const SizedBox( - height: 40, - ) - ], - ), - ), ); })); } diff --git a/lib/features/devices/view/widgets/one_gang/one_gang_Interface.dart b/lib/features/devices/view/widgets/one_gang/one_gang_Interface.dart index 636a730..28f2728 100644 --- a/lib/features/devices/view/widgets/one_gang/one_gang_Interface.dart +++ b/lib/features/devices/view/widgets/one_gang/one_gang_Interface.dart @@ -3,7 +3,6 @@ import 'package:flutter/services.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/device_appbar.dart'; import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_screen.dart'; -import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_screen.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; diff --git a/lib/features/devices/view/widgets/one_gang/one_gang_list.dart b/lib/features/devices/view/widgets/one_gang/one_gang_list.dart new file mode 100644 index 0000000..ba03339 --- /dev/null +++ b/lib/features/devices/view/widgets/one_gang/one_gang_list.dart @@ -0,0 +1,66 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_event.dart'; +import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart'; +import 'package:syncrow_app/features/devices/model/group_one_gang_model.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 OneGangList extends StatelessWidget { + const OneGangList({super.key, required this.oneGangList, required this.allSwitches}); + + final List oneGangList; + final bool allSwitches; + + @override + Widget build(BuildContext context) { + return BlocBuilder( + builder: (context, state) { + return 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: oneGangList.length, + itemBuilder: (context, index) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 10), + BodySmall(text: oneGangList[index].deviceName), + const SizedBox(height: 5), + DevicesDefaultSwitch( + switchValue: oneGangList[index].firstSwitch, + action: () { + BlocProvider.of(context).add(ChangeFirstSwitchStatusEvent( + value: oneGangList[index].firstSwitch, + deviceId: oneGangList[index].deviceId)); + }, + ), + ], + ); + }, + ), + ], + ), + ); + }, + ); + } +} diff --git a/lib/features/devices/view/widgets/one_gang/one_gang_screen.dart b/lib/features/devices/view/widgets/one_gang/one_gang_screen.dart index 21aee6d..59ffb34 100644 --- a/lib/features/devices/view/widgets/one_gang/one_gang_screen.dart +++ b/lib/features/devices/view/widgets/one_gang/one_gang_screen.dart @@ -3,7 +3,9 @@ import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_bloc.dart'; import 'package:syncrow_app/features/devices/bloc/one_gang_bloc/one_gang_state.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; +import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart'; import 'package:syncrow_app/features/devices/model/one_gang_model.dart'; +import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_list.dart'; import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_timer_screen.dart'; import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart'; import 'package:syncrow_app/features/shared_widgets/default_container.dart'; @@ -20,10 +22,8 @@ class OneGangScreen extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => OneGangBloc( - switchCode: 'switch_1', - oneGangId : device?.uuid ?? '') - ..add(const InitialEvent(groupScreen:false)), + create: (context) => OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '') + ..add(const InitialEvent(groupScreen: false)), child: BlocBuilder( builder: (context, state) { OneGangModel oneGangModel = OneGangModel( @@ -31,141 +31,149 @@ class OneGangScreen extends StatelessWidget { firstCountDown: 0, ); + List groupOneGangModel = []; + bool allSwitchesOn = false; + if (state is LoadingNewSate) { oneGangModel = state.oneGangModel; } else if (state is UpdateState) { oneGangModel = state.oneGangModel; + } else if (state is UpdateGroupState) { + groupOneGangModel = state.oneGangList; + allSwitchesOn = state.allSwitches; } - return state is LoadingInitialState ? - const Center( - child: - DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), - ): - RefreshIndicator( - onRefresh: () async { - BlocProvider.of(context) - .add(InitialEvent(groupScreen: device != null ? false : true)); - }, - child: ListView( - children: [ - SizedBox( - height: MediaQuery.of(context).size.height, - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.stretch, - children: [ - const Expanded(child: SizedBox.shrink()), - Expanded( - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceAround, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - Column( + return state is LoadingInitialState + ? const Center( + child: + DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), + ) + : device == null + ? OneGangList(oneGangList: groupOneGangModel, allSwitches: allSwitchesOn) + : RefreshIndicator( + onRefresh: () async { + BlocProvider.of(context) + .add(InitialEvent(groupScreen: device != null ? false : true)); + }, + child: ListView( + children: [ + SizedBox( + height: MediaQuery.of(context).size.height, + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.stretch, children: [ - GangSwitch( - threeGangSwitch: device!, - value: oneGangModel.firstSwitch, - action: () { - BlocProvider.of(context).add( - ChangeFirstSwitchStatusEvent( - value: oneGangModel.firstSwitch)); - }, - ), - const SizedBox(height: 20), - const SizedBox( - width: 70, - child: BodySmall( - text:" Entrance Light", - fontColor: ColorsManager.textPrimaryColor, - textAlign: TextAlign.center, - ), - ), - ], - ), - ], - ), - ), - Center( - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.center, - children: [ - 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) => TimerScheduleScreen( - switchCode:'switch_1' , - device: device!, - deviceCode: 'countdown_1', - ))); - }, - child: Stack( - alignment: Alignment.center, - children: [ - Container( - width: 60, - height: 60, - decoration: BoxDecoration( - color: Colors.grey[300], - borderRadius: BorderRadius.circular(100), + const Expanded(child: SizedBox.shrink()), + Expanded( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceAround, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Column( + children: [ + GangSwitch( + threeGangSwitch: device!, + value: oneGangModel.firstSwitch, + action: () { + BlocProvider.of(context).add( + ChangeFirstSwitchStatusEvent( + value: oneGangModel.firstSwitch)); + }, ), - ), - 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: 20), + const SizedBox( + width: 70, + child: BodySmall( + text: " Entrance Light", + fontColor: ColorsManager.textPrimaryColor, + textAlign: TextAlign.center, ), ), - ), - ], - ), + ], + ), + ], ), ), - const SizedBox(height: 10), - BodySmall( - text: "Timer", - style: context.bodyMedium.copyWith( - color: ColorsManager.textPrimaryColor, + Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + 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) => + TimerScheduleScreen( + switchCode: 'switch_1', + device: device!, + deviceCode: 'countdown_1', + ))); + }, + 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, + ), + ), + ], + ), + ], ), ), + Expanded(child: SizedBox()) ], ), - - ], - ), + ), + ], ), - Expanded(child: SizedBox()) - ], - ), - ), - ], - ), - ); + ); }, ), ); - } } diff --git a/lib/features/devices/view/widgets/room_page.dart b/lib/features/devices/view/widgets/room_page.dart index 68b2ac1..ce2028a 100644 --- a/lib/features/devices/view/widgets/room_page.dart +++ b/lib/features/devices/view/widgets/room_page.dart @@ -1,6 +1,4 @@ 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/room_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/room_page_switch.dart'; diff --git a/lib/features/devices/view/widgets/smart_door/create_temporary_password.dart b/lib/features/devices/view/widgets/smart_door/create_temporary_password.dart index 7d2b807..efeeda3 100644 --- a/lib/features/devices/view/widgets/smart_door/create_temporary_password.dart +++ b/lib/features/devices/view/widgets/smart_door/create_temporary_password.dart @@ -23,7 +23,7 @@ class CreateTemporaryPassword extends StatelessWidget { @override Widget build(BuildContext context) { bool isRepeat = false; - bool generated = false; + // bool generated = false; return BlocProvider( create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!), child: BlocConsumer(listener: (context, state) { @@ -35,11 +35,11 @@ class CreateTemporaryPassword extends StatelessWidget { ), ); } - if (state is IsRepeatState){ + if (state is IsRepeatState) { isRepeat = state.repeat; } - if (state is GeneratePasswordOneTimestate ){ - generated = state.generated; + if (state is GeneratePasswordOneTimestate) { + // generated = state.generated; } }, builder: (context, state) { final smartDoorBloc = BlocProvider.of(context); @@ -56,141 +56,142 @@ class CreateTemporaryPassword extends StatelessWidget { onPressed: () { Navigator.of(context).pop(true); }, - icon: const Icon(Icons.arrow_back) - ), - actions: - type == 'Online Password'?[ - TextButton( - onPressed: () { - smartDoorBloc.add(SavePasswordEvent(context: context)); - }, - child: const Text('Save') - ) - ]:null, + icon: const Icon(Icons.arrow_back)), + actions: type == 'Online Password' + ? [ + TextButton( + onPressed: () { + smartDoorBloc.add(SavePasswordEvent(context: context)); + }, + child: const Text('Save')) + ] + : null, ), child: state is LoadingInitialState ? const Center(child: CircularProgressIndicator()) : SingleChildScrollView( - child: Column( - mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - const BodyMedium( - text: 'Save the password immediately. The password is not displayed in the app.', - fontWeight: FontWeight.normal, - fontColor: ColorsManager.grayColor, - ), - const SizedBox( - height: 20, - ), - const BodyMedium( - text: '7-Digit Password', - fontWeight: FontWeight.normal, - fontColor: ColorsManager.grayColor, - ), - DefaultContainer( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), - child: Padding( - padding: EdgeInsets.symmetric(horizontal: type == 'Online Password'?0:25), - child: Row( - mainAxisAlignment: MainAxisAlignment.spaceBetween, - mainAxisSize: MainAxisSize.max, - children: [ - Flexible( - flex: 2, - child: PinCodeTextField( - onCompleted: (value) { - if (value.split('').every((char) => char == '1')) { - smartDoorBloc.passwordController.clear(); - CustomSnackBar.displaySnackBar('All characters cannot be 1.'); - } - }, - autoDisposeControllers: false, - keyboardType: TextInputType.phone, - length: 7, - // enabled:type == 'Online Password'? true:false, - obscureText: false, - animationType: AnimationType.fade, - pinTheme: PinTheme( - shape: PinCodeFieldShape.underline, - fieldHeight: 45, - fieldWidth: 20, - activeFillColor: Colors.white, - disabledColor: Colors.grey, - activeColor: Colors.grey, - errorBorderColor: Colors.grey, - inactiveColor: Colors.grey, - inactiveFillColor: Colors.grey, - selectedColor: Colors.grey), - animationDuration: const Duration(milliseconds: 300), - backgroundColor: Colors.white, - enableActiveFill: false, - controller: smartDoorBloc.passwordController, - appContext: context, - )), - const SizedBox( - width: 10, + child: Column( + mainAxisAlignment: MainAxisAlignment.start, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const BodyMedium( + text: + 'Save the password immediately. The password is not displayed in the app.', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + const SizedBox( + height: 20, + ), + const BodyMedium( + text: '7-Digit Password', + fontWeight: FontWeight.normal, + fontColor: ColorsManager.grayColor, + ), + DefaultContainer( + padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 15), + child: Padding( + padding: EdgeInsets.symmetric( + horizontal: type == 'Online Password' ? 0 : 25), + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.max, + children: [ + Flexible( + flex: 2, + child: PinCodeTextField( + onCompleted: (value) { + if (value.split('').every((char) => char == '1')) { + smartDoorBloc.passwordController.clear(); + CustomSnackBar.displaySnackBar( + 'All characters cannot be 1.'); + } + }, + autoDisposeControllers: false, + keyboardType: TextInputType.phone, + length: 7, + // enabled:type == 'Online Password'? true:false, + obscureText: false, + animationType: AnimationType.fade, + pinTheme: PinTheme( + shape: PinCodeFieldShape.underline, + fieldHeight: 45, + fieldWidth: 20, + activeFillColor: Colors.white, + disabledColor: Colors.grey, + activeColor: Colors.grey, + errorBorderColor: Colors.grey, + inactiveColor: Colors.grey, + inactiveFillColor: Colors.grey, + selectedColor: Colors.grey), + animationDuration: const Duration(milliseconds: 300), + backgroundColor: Colors.white, + enableActiveFill: false, + controller: smartDoorBloc.passwordController, + appContext: context, + )), + const SizedBox( + width: 10, + ), + if (type == 'Online Password') + Flexible( + child: InkWell( + onTap: () { + smartDoorBloc.add(GeneratePasswordEvent()); + }, + child: const BodyMedium( + text: 'Generate Randomly', + fontWeight: FontWeight.bold, + fontColor: ColorsManager.primaryColor, + )), + ) + ], + ), ), - if(type == 'Online Password') - Flexible( - child: InkWell( - onTap: () { - smartDoorBloc.add(GeneratePasswordEvent()); + ), + if (smartDoorBloc.passwordController.text.isNotEmpty) + TextButton( + onPressed: () async { + await Clipboard.setData( + ClipboardData(text: smartDoorBloc.passwordController.text)); + }, + child: const Text('Copy')), + const SizedBox( + height: 20, + ), + NameTimeWidget(), + const SizedBox( + height: 20, + ), + DefaultContainer( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + child: ListTile( + contentPadding: EdgeInsets.zero, + leading: const BodyMedium( + text: 'Repeat', + fontWeight: FontWeight.normal, + ), + trailing: Transform.scale( + scale: .8, + child: CupertinoSwitch( + value: smartDoorBloc.repeat, + onChanged: (value) { + smartDoorBloc.add(ToggleRepeatEvent()); }, - child: const BodyMedium( - text: 'Generate Randomly', - fontWeight: FontWeight.bold, - fontColor: ColorsManager.primaryColor, - )), - ) - ], - ), + applyTheme: true, + )), + ), + ), + const SizedBox( + height: 20, + ), + isRepeat ? const RepeatWidget() : const SizedBox(), + const SizedBox( + height: 40, + ) + ], ), ), - if(smartDoorBloc.passwordController.text.isNotEmpty) - TextButton( - onPressed: () async { - await Clipboard.setData(ClipboardData( - text: smartDoorBloc.passwordController.text)); - }, - child: const Text('Copy') - ), - const SizedBox( - height: 20, - ), - NameTimeWidget(), - const SizedBox( - height: 20, - ), - DefaultContainer( - padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), - child: ListTile( - contentPadding: EdgeInsets.zero, - leading: const BodyMedium( - text: 'Repeat', - fontWeight: FontWeight.normal, - ), - trailing: Transform.scale( - scale: .8, - child: CupertinoSwitch( - value: smartDoorBloc.repeat, - onChanged: (value) { - smartDoorBloc.add(ToggleRepeatEvent()); - }, - applyTheme: true, - )), - ), - ) , - const SizedBox( - height: 20, - ), - isRepeat? const RepeatWidget():const SizedBox(), - const SizedBox( - height: 40, - ) - ], - ), - ), ); })); } diff --git a/lib/features/devices/view/widgets/smart_door/door_dialog.dart b/lib/features/devices/view/widgets/smart_door/door_dialog.dart index b1a672d..db95566 100644 --- a/lib/features/devices/view/widgets/smart_door/door_dialog.dart +++ b/lib/features/devices/view/widgets/smart_door/door_dialog.dart @@ -31,16 +31,18 @@ class DoorDialogState extends State { @override Widget build(BuildContext context) { - final effectiveTime = widget.temporaryPassword?.effectiveTime ??int.parse( widget.offline?.gmtStart); - final invalidTime = widget.temporaryPassword?.invalidTime ?? int.parse(widget.offline?.gmtExpired); + final effectiveTime = + widget.temporaryPassword?.effectiveTime ?? int.parse(widget.offline?.gmtStart); + final invalidTime = + widget.temporaryPassword?.invalidTime ?? int.parse(widget.offline?.gmtExpired); final DateTime effectiveDateTime = - DateTime.fromMillisecondsSinceEpoch(effectiveTime! * 1000, isUtc: false); + DateTime.fromMillisecondsSinceEpoch(effectiveTime * 1000, isUtc: false); String formattedDateEffectiveTime = DateFormat('yyyy-MM-dd').format(effectiveDateTime); String formattedTimeEffectiveTime = DateFormat('hh:mm a').format(effectiveDateTime); final DateTime expiredDateTime = - DateTime.fromMillisecondsSinceEpoch(invalidTime! * 1000, isUtc: false); + DateTime.fromMillisecondsSinceEpoch(invalidTime * 1000, isUtc: false); String formattedDateExpiredDateTime = DateFormat('yyyy-MM-dd').format(expiredDateTime); String formattedTimeExpiredDateTime = DateFormat('hh:mm a').format(expiredDateTime); return Dialog( @@ -116,60 +118,59 @@ class DoorDialogState extends State { width: double.infinity, color: ColorsManager.greyColor, ), - widget.temporaryPassword?.effectiveTime!=null? - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - InkWell( - onTap: () { - Navigator.pop(context); - }, - child: Center( - child: BodyMedium( - text: 'Cancel', - style: context.bodyMedium.copyWith(color: ColorsManager.greyColor), - ), - ), - ), - Container( - height: 50, - width: 1, - color: ColorsManager.greyColor, - ), - InkWell( - onTap: () { - Navigator.pop(context, 'delete'); - }, - child: Center( - child: BodyMedium( - text: 'Delete Password', - style: context.bodyMedium.copyWith(color: ColorsManager.primaryColorWithOpacity), - ), - ), - ), - ], - ): - Row( - mainAxisAlignment: MainAxisAlignment.spaceEvenly, - children: [ - Container( - height: 50, - child: InkWell( - onTap: () { - Navigator.pop(context); - }, - child: Center( - child: BodyMedium( - text: 'Cancel', - style: context.bodyMedium.copyWith(color: ColorsManager.greyColor), + widget.temporaryPassword?.effectiveTime != null + ? Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + InkWell( + onTap: () { + Navigator.pop(context); + }, + child: Center( + child: BodyMedium( + text: 'Cancel', + style: context.bodyMedium.copyWith(color: ColorsManager.greyColor), + ), + ), ), - ), - ), - - ), - - ], - ) + Container( + height: 50, + width: 1, + color: ColorsManager.greyColor, + ), + InkWell( + onTap: () { + Navigator.pop(context, 'delete'); + }, + child: Center( + child: BodyMedium( + text: 'Delete Password', + style: context.bodyMedium + .copyWith(color: ColorsManager.primaryColorWithOpacity), + ), + ), + ), + ], + ) + : Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Container( + height: 50, + child: InkWell( + onTap: () { + Navigator.pop(context); + }, + child: Center( + child: BodyMedium( + text: 'Cancel', + style: context.bodyMedium.copyWith(color: ColorsManager.greyColor), + ), + ), + ), + ), + ], + ) ], ), ), diff --git a/lib/features/devices/view/widgets/smart_door/door_grid.dart b/lib/features/devices/view/widgets/smart_door/door_grid.dart index fc5c290..a37be12 100644 --- a/lib/features/devices/view/widgets/smart_door/door_grid.dart +++ b/lib/features/devices/view/widgets/smart_door/door_grid.dart @@ -1,5 +1,4 @@ import 'package:flutter/material.dart'; -import 'package:flutter/widgets.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/devices/view/widgets/smart_door/members_management_view.dart'; import 'package:syncrow_app/features/devices/view/widgets/smart_door/smart_linkage_view.dart'; @@ -10,9 +9,8 @@ import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart import 'package:syncrow_app/generated/assets.dart'; class DoorLockGrid extends StatelessWidget { - String uuid; - DoorLockGrid({ - super.key,required this.uuid}); + final String uuid; + const DoorLockGrid({super.key, required this.uuid}); @override Widget build(BuildContext context) { @@ -67,24 +65,24 @@ class DoorLockGrid extends StatelessWidget { } List> doorLockButtons({val}) => [ - { - 'title': 'Unlocking Records', - 'image': Assets.assetsIconsDoorlockAssetsUnlockingRecords, - 'page': const UnlockingRecordsView(), - }, - { - 'title': 'Members Management', - 'image': Assets.assetsIconsDoorlockAssetsMembersManagement, - 'page': const MembersManagementView(), - }, - { - 'title': 'Temporary Password', - 'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword, - 'page': TemporaryPasswordPage(deviceId:val) , - }, - { - 'title': 'Smart Linkage', - 'image': Assets.assetsIconsDoorlockAssetsSmartLinkage, - 'page': const SmartLinkgeView() - }, -]; + { + 'title': 'Unlocking Records', + 'image': Assets.assetsIconsDoorlockAssetsUnlockingRecords, + 'page': const UnlockingRecordsView(), + }, + { + 'title': 'Members Management', + 'image': Assets.assetsIconsDoorlockAssetsMembersManagement, + 'page': const MembersManagementView(), + }, + { + 'title': 'Temporary Password', + 'image': Assets.assetsIconsDoorlockAssetsTemporaryPassword, + 'page': TemporaryPasswordPage(deviceId: val), + }, + { + 'title': 'Smart Linkage', + 'image': Assets.assetsIconsDoorlockAssetsSmartLinkage, + 'page': const SmartLinkgeView() + }, + ]; diff --git a/lib/features/devices/view/widgets/smart_door/onetime_password_page.dart b/lib/features/devices/view/widgets/smart_door/onetime_password_page.dart index ba54fc5..a5f1d62 100644 --- a/lib/features/devices/view/widgets/smart_door/onetime_password_page.dart +++ b/lib/features/devices/view/widgets/smart_door/onetime_password_page.dart @@ -14,98 +14,103 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; class OnetimePasswordPage extends StatelessWidget { final String? deviceId; - const OnetimePasswordPage({super.key, this.deviceId,}); + const OnetimePasswordPage({ + super.key, + this.deviceId, + }); @override Widget build(BuildContext context) { return BlocProvider( - create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialOneTimePassword( )), - child: BlocConsumer( - listener: (context, state) { - if (state is FailedState) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(state.errorMessage), - backgroundColor: Colors.red, - ), - ); - } - }, - builder: (context, state) { - final smartDoorBloc = BlocProvider.of(context); - return DefaultScaffold( - title: 'Passwords', - actions: [ - IconButton( - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (context) => OfflineOneTimePasswordPage(deviceId: deviceId, ) - )).then((result) { - if(result!=null){ - smartDoorBloc.add(InitialOneTimePassword()); - smartDoorBloc.add(InitialOneTimePassword()); - } - }); - }, - icon: const Icon(Icons.add) - ) - ], - child: Builder( - builder: (context) { - return state is LoadingInitialState - ? const Center(child: CircularProgressIndicator()) - : Center( - child: smartDoorBloc.oneTimePasswords!.isNotEmpty - ? ListView.builder( - itemCount: smartDoorBloc.oneTimePasswords!.length, - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.all(5.0), - child: DefaultContainer( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), - child: ListTile( - contentPadding: EdgeInsets.zero, - leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon), - title: BodyMedium( - text: 'Password Name: ${smartDoorBloc.oneTimePasswords![index].pwdName}', - fontWeight: FontWeight.normal, - ), - onTap: () async { - final result = await showDialog( - context: context, - builder: (context) { - return DoorDialog( - title: 'Password Information', - offline: smartDoorBloc.oneTimePasswords![index], - ); - }, - ); - - }, - trailing: const Icon( - Icons.arrow_forward_ios, - color: ColorsManager.greyColor, - size: 15, - ), - ), - ), - ); - }, - ) : Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset(Assets.noValidPasswords), - const SizedBox( - height: 10, - ), - const BodyMedium(text: 'No Valid Passwords') - ], - ), - ); + create: (BuildContext context) => + SmartDoorBloc(deviceId: deviceId!)..add(InitialOneTimePassword()), + child: BlocConsumer(listener: (context, state) { + if (state is FailedState) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(state.errorMessage), + backgroundColor: Colors.red, + ), + ); + } + }, builder: (context, state) { + final smartDoorBloc = BlocProvider.of(context); + return DefaultScaffold( + title: 'Passwords', + actions: [ + IconButton( + onPressed: () { + Navigator.of(context) + .push(MaterialPageRoute( + builder: (context) => OfflineOneTimePasswordPage( + deviceId: deviceId, + ))) + .then((result) { + if (result != null) { + smartDoorBloc.add(InitialOneTimePassword()); + smartDoorBloc.add(InitialOneTimePassword()); + } + }); }, - )); - }) - ); + icon: const Icon(Icons.add)) + ], + child: Builder( + builder: (context) { + return state is LoadingInitialState + ? const Center(child: CircularProgressIndicator()) + : Center( + child: smartDoorBloc.oneTimePasswords!.isNotEmpty + ? ListView.builder( + itemCount: smartDoorBloc.oneTimePasswords!.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.all(5.0), + child: DefaultContainer( + padding: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + child: ListTile( + contentPadding: EdgeInsets.zero, + leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon), + title: BodyMedium( + text: + 'Password Name: ${smartDoorBloc.oneTimePasswords![index].pwdName}', + fontWeight: FontWeight.normal, + ), + onTap: () async { + await showDialog( + context: context, + builder: (context) { + return DoorDialog( + title: 'Password Information', + offline: smartDoorBloc.oneTimePasswords![index], + ); + }, + ); + }, + trailing: const Icon( + Icons.arrow_forward_ios, + color: ColorsManager.greyColor, + size: 15, + ), + ), + ), + ); + }, + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(Assets.noValidPasswords), + const SizedBox( + height: 10, + ), + const BodyMedium(text: 'No Valid Passwords') + ], + ), + ); + }, + )); + })); } } diff --git a/lib/features/devices/view/widgets/smart_door/timelimited_password_page.dart b/lib/features/devices/view/widgets/smart_door/timelimited_password_page.dart index fce92b9..b07c192 100644 --- a/lib/features/devices/view/widgets/smart_door/timelimited_password_page.dart +++ b/lib/features/devices/view/widgets/smart_door/timelimited_password_page.dart @@ -19,87 +19,88 @@ class TimeLimitedPasswordPage extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (BuildContext context) => SmartDoorBloc(deviceId: deviceId!)..add(InitialTimeLimitPassword()), - child: BlocConsumer( - listener: (context, state) { - if (state is FailedState) { - CustomSnackBar.displaySnackBar( - state.errorMessage - ); - } - }, - builder: (context, state) { - final smartDoorBloc = BlocProvider.of(context); - return DefaultScaffold( - title: 'Passwords', - actions: [ - IconButton( - onPressed: () { - Navigator.of(context).push( - MaterialPageRoute(builder: (context) => CreateOfflineTimeLimitPasswordPage(deviceId: deviceId,) - )).then((result) { - smartDoorBloc.add(InitialTimeLimitPassword()); - smartDoorBloc.add(InitialTimeLimitPassword()); - }); - }, - icon: const Icon(Icons.add) - ) - ], - child: Builder( - builder: (context) { - return state is LoadingInitialState - ? const Center(child: CircularProgressIndicator()) - : Center( - child: smartDoorBloc.timeLimitPasswords!.isNotEmpty - ? ListView.builder( - itemCount: smartDoorBloc.timeLimitPasswords!.length, - itemBuilder: (context, index) { - return Padding( - padding: const EdgeInsets.all(5.0), - child: DefaultContainer( - padding: const EdgeInsets.symmetric(horizontal: 15, vertical: 10), - child: ListTile( - contentPadding: EdgeInsets.zero, - leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon), - title: BodyMedium( - text: 'Password Name: ${smartDoorBloc.timeLimitPasswords![index].pwdName}', - fontWeight: FontWeight.normal, - ), - onTap: () async { - final result = await showDialog( - context: context, - builder: (context) { - return DoorDialog( - title: 'Password Information', - offline: smartDoorBloc.timeLimitPasswords![index], - ); - }, + create: (BuildContext context) => + SmartDoorBloc(deviceId: deviceId!)..add(InitialTimeLimitPassword()), + child: BlocConsumer(listener: (context, state) { + if (state is FailedState) { + CustomSnackBar.displaySnackBar(state.errorMessage); + } + }, builder: (context, state) { + final smartDoorBloc = BlocProvider.of(context); + return DefaultScaffold( + title: 'Passwords', + actions: [ + IconButton( + onPressed: () { + Navigator.of(context) + .push(MaterialPageRoute( + builder: (context) => CreateOfflineTimeLimitPasswordPage( + deviceId: deviceId, + ))) + .then((result) { + smartDoorBloc.add(InitialTimeLimitPassword()); + smartDoorBloc.add(InitialTimeLimitPassword()); + }); + }, + icon: const Icon(Icons.add)) + ], + child: Builder( + builder: (context) { + return state is LoadingInitialState + ? const Center(child: CircularProgressIndicator()) + : Center( + child: smartDoorBloc.timeLimitPasswords!.isNotEmpty + ? ListView.builder( + itemCount: smartDoorBloc.timeLimitPasswords!.length, + itemBuilder: (context, index) { + return Padding( + padding: const EdgeInsets.all(5.0), + child: DefaultContainer( + padding: const EdgeInsets.symmetric( + horizontal: 15, vertical: 10), + child: ListTile( + contentPadding: EdgeInsets.zero, + leading: SvgPicture.asset(Assets.timeLimitedPasswordIcon), + title: BodyMedium( + text: + 'Password Name: ${smartDoorBloc.timeLimitPasswords![index].pwdName}', + fontWeight: FontWeight.normal, + ), + onTap: () async { + await showDialog( + context: context, + builder: (context) { + return DoorDialog( + title: 'Password Information', + offline: smartDoorBloc.timeLimitPasswords![index], + ); + }, + ); + }, + trailing: const Icon( + Icons.arrow_forward_ios, + color: ColorsManager.greyColor, + size: 15, + ), + ), + ), ); }, - trailing: const Icon( - Icons.arrow_forward_ios, - color: ColorsManager.greyColor, - size: 15, - ), + ) + : Column( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + SvgPicture.asset(Assets.noValidPasswords), + const SizedBox( + height: 10, + ), + const BodyMedium(text: 'No Valid Passwords') + ], ), - ), - ); - }, - ) : Column( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.center, - children: [ - SvgPicture.asset(Assets.noValidPasswords), - const SizedBox( - height: 10, - ), - const BodyMedium(text: 'No Valid Passwords') - ], - ), - ); - }, - )); - }) - ); + ); + }, + )); + })); } } diff --git a/lib/features/devices/view/widgets/three_gang/gang_switch.dart b/lib/features/devices/view/widgets/three_gang/gang_switch.dart index 8b5dc55..61afbc0 100644 --- a/lib/features/devices/view/widgets/three_gang/gang_switch.dart +++ b/lib/features/devices/view/widgets/three_gang/gang_switch.dart @@ -18,7 +18,7 @@ class GangSwitch extends StatelessWidget { @override Widget build(BuildContext context) { return InkWell( - overlayColor: MaterialStateProperty.all(Colors.transparent), + overlayColor: WidgetStateProperty.all(Colors.transparent), onTap: () { action(); // var tempControl = DeviceControlModel( diff --git a/lib/features/devices/view/widgets/three_gang/timer_screen.dart b/lib/features/devices/view/widgets/three_gang/timer_screen.dart index d15d4b1..23dcdf5 100644 --- a/lib/features/devices/view/widgets/three_gang/timer_screen.dart +++ b/lib/features/devices/view/widgets/three_gang/timer_screen.dart @@ -8,7 +8,6 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_eve 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/shared_widgets/create_schedule.dart'; -import 'package:syncrow_app/features/shared_widgets/default_container.dart'; import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart'; import 'package:syncrow_app/features/shared_widgets/schedule_list.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart'; @@ -18,17 +17,12 @@ import 'package:syncrow_app/utils/context_extension.dart'; import 'package:syncrow_app/utils/resource_manager/color_manager.dart'; import 'package:syncrow_app/utils/resource_manager/font_manager.dart'; - - class TimerScheduleScreen extends StatelessWidget { final DeviceModel device; final String deviceCode; final String switchCode; const TimerScheduleScreen( - {required this.device, - required this.deviceCode, - required this.switchCode, - super.key}); + {required this.device, required this.deviceCode, required this.switchCode, super.key}); @override Widget build(BuildContext context) { @@ -38,8 +32,7 @@ class TimerScheduleScreen extends StatelessWidget { statusBarIconBrightness: Brightness.light, ), child: BlocProvider( - create: (context) => - ThreeGangBloc(switchCode: switchCode, threeGangId: device.uuid ?? '') + create: (context) => ThreeGangBloc(switchCode: switchCode, threeGangId: device.uuid ?? '') ..add(GetCounterEvent(deviceCode: deviceCode)) ..add(GetScheduleEvent()), child: BlocBuilder( @@ -66,7 +59,7 @@ class TimerScheduleScreen extends StatelessWidget { }, child: DefaultTabController( length: 2, - child: DefaultScaffold( + child: DefaultScaffold( appBar: AppBar( backgroundColor: Colors.transparent, centerTitle: true, @@ -76,177 +69,175 @@ class TimerScheduleScreen extends StatelessWidget { fontWeight: FontsManager.bold, ), actions: [ - threeGangBloc.createSchedule == true ? - TextButton( - onPressed: () { - threeGangBloc.add(ThreeGangSave()); - }, - child: const Text('Save') - ) : - threeGangBloc.selectedTabIndex==1? IconButton( - onPressed: () { - threeGangBloc.toggleCreateSchedule(); - }, - icon: const Icon(Icons.add), - ):SizedBox(), + threeGangBloc.createSchedule == true + ? TextButton( + onPressed: () { + threeGangBloc.add(ThreeGangSave()); + }, + child: const Text('Save')) + : threeGangBloc.selectedTabIndex == 1 + ? IconButton( + onPressed: () { + threeGangBloc.toggleCreateSchedule(); + }, + icon: const Icon(Icons.add), + ) + : SizedBox(), ], ), - child: - state is LoadingInitialState? - const Center(child: CircularProgressIndicator()): - Column( - children: [ - Container( - width: MediaQuery.of(context).size.width, - decoration: const ShapeDecoration( - color: ColorsManager.onPrimaryColor, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(30)), - ), - ), - child: TabBar( - onTap: (value) { - if(value==0){ - if(threeGangBloc.createSchedule == true){ - threeGangBloc.toggleCreateSchedule(); - } - threeGangBloc.toggleSelectedIndex(0); - - }else{ - threeGangBloc.toggleSelectedIndex(1); - } - }, - indicatorColor: Colors.white, // Customize the indicator - dividerHeight: 0, - indicatorSize: TabBarIndicatorSize.tab, - indicator: const ShapeDecoration( - color: ColorsManager.slidingBlueColor, - shape: RoundedRectangleBorder( - borderRadius: - BorderRadius.all(Radius.circular(20)), - ), - ), - tabs: [ - Tab( - child: Container( - padding: const EdgeInsets.symmetric( - vertical: 10), - child: BodySmall( - text: 'Countdown', - style: context.bodySmall.copyWith( - color: ColorsManager.blackColor, - fontSize: 12, - fontWeight: FontWeight.w400, - ), - ), - ), - ), - Tab( - child: Container( - padding: const EdgeInsets.symmetric(vertical: 10), - child: Text( - 'Schedule', - style: context.bodySmall.copyWith( - color: ColorsManager.blackColor, - fontSize: 12, - fontWeight: FontWeight.w400, - ), - ), - ), - ), - ], - ), - - ), - Expanded( - child: TabBarView( + child: state is LoadingInitialState + ? const Center(child: CircularProgressIndicator()) + : Column( children: [ - Center( - child: Container( - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - countNum > 0 - ? BodyLarge( - text: _formatDuration(countNum), - fontColor: - ColorsManager.slidingBlueColor, - fontSize: 40, - ) - : CupertinoTimerPicker( - mode: CupertinoTimerPickerMode.hm, - onTimerDurationChanged: - (Duration newDuration) { - duration = newDuration; - }, - ), - GestureDetector( - onTap: () { - if (state is LoadingNewSate) { - return; - } - if (countNum > 0) { - threeGangBloc.add(SetCounterValue( - deviceCode: deviceCode, - duration: Duration.zero)); - } else if (duration != Duration.zero) { - threeGangBloc.add(SetCounterValue( - deviceCode: deviceCode, - duration: duration)); - } - }, - child: SvgPicture.asset(countNum > 0 - ? Assets.pauseIcon - : Assets.playIcon)), - ], + Container( + width: MediaQuery.of(context).size.width, + decoration: const ShapeDecoration( + color: ColorsManager.onPrimaryColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(30)), ), ), - ), - Column( - mainAxisAlignment:threeGangBloc.listSchedule.isNotEmpty? - MainAxisAlignment.start:MainAxisAlignment.center, - children: [ - SizedBox( - child: threeGangBloc.createSchedule == true ? - CreateSchedule( - onToggleChanged: (bool isOn) { - threeGangBloc.toggleSchedule = isOn; - }, - onDateTimeChanged: (DateTime dateTime) { - threeGangBloc.selectedTime=dateTime; - }, - days: threeGangBloc.days, - selectDays: (List selectedDays) { - threeGangBloc.selectedDays = selectedDays; - }, - ) - : - Padding( - padding: const EdgeInsets.only(top: 10), - child: ScheduleListView( - listSchedule: threeGangBloc.listSchedule, // Pass the schedule list here - onDismissed: (scheduleId) { - threeGangBloc.listSchedule.removeWhere((schedule) => schedule.scheduleId == scheduleId); - threeGangBloc.add(DeleteScheduleEvent(id: scheduleId)); - }, - onToggleSchedule: (scheduleId, isEnabled) { - threeGangBloc.add(ToggleScheduleEvent( - id: scheduleId, - toggle: isEnabled, - )); - }, - ), + child: TabBar( + onTap: (value) { + if (value == 0) { + if (threeGangBloc.createSchedule == true) { + threeGangBloc.toggleCreateSchedule(); + } + threeGangBloc.toggleSelectedIndex(0); + } else { + threeGangBloc.toggleSelectedIndex(1); + } + }, + indicatorColor: Colors.white, // Customize the indicator + dividerHeight: 0, + indicatorSize: TabBarIndicatorSize.tab, + indicator: const ShapeDecoration( + color: ColorsManager.slidingBlueColor, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(20)), ), ), - ], + tabs: [ + Tab( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 10), + child: BodySmall( + text: 'Countdown', + style: context.bodySmall.copyWith( + color: ColorsManager.blackColor, + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + Tab( + child: Container( + padding: const EdgeInsets.symmetric(vertical: 10), + child: Text( + 'Schedule', + style: context.bodySmall.copyWith( + color: ColorsManager.blackColor, + fontSize: 12, + fontWeight: FontWeight.w400, + ), + ), + ), + ), + ], + ), + ), + Expanded( + child: TabBarView( + children: [ + Center( + child: Container( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + countNum > 0 + ? BodyLarge( + text: _formatDuration(countNum), + fontColor: ColorsManager.slidingBlueColor, + fontSize: 40, + ) + : CupertinoTimerPicker( + mode: CupertinoTimerPickerMode.hm, + onTimerDurationChanged: + (Duration newDuration) { + duration = newDuration; + }, + ), + GestureDetector( + onTap: () { + if (state is LoadingNewSate) { + return; + } + if (countNum > 0) { + threeGangBloc.add(SetCounterValue( + deviceCode: deviceCode, + duration: Duration.zero)); + } else if (duration != Duration.zero) { + threeGangBloc.add(SetCounterValue( + deviceCode: deviceCode, + duration: duration)); + } + }, + child: SvgPicture.asset(countNum > 0 + ? Assets.pauseIcon + : Assets.playIcon)), + ], + ), + ), + ), + Column( + mainAxisAlignment: threeGangBloc.listSchedule.isNotEmpty + ? MainAxisAlignment.start + : MainAxisAlignment.center, + children: [ + SizedBox( + child: threeGangBloc.createSchedule == true + ? CreateSchedule( + onToggleChanged: (bool isOn) { + threeGangBloc.toggleSchedule = isOn; + }, + onDateTimeChanged: (DateTime dateTime) { + threeGangBloc.selectedTime = dateTime; + }, + days: threeGangBloc.days, + selectDays: (List selectedDays) { + threeGangBloc.selectedDays = selectedDays; + }, + ) + : Padding( + padding: const EdgeInsets.only(top: 10), + child: ScheduleListView( + listSchedule: threeGangBloc + .listSchedule, // Pass the schedule list here + onDismissed: (scheduleId) { + threeGangBloc.listSchedule.removeWhere( + (schedule) => + schedule.scheduleId == scheduleId); + threeGangBloc.add( + DeleteScheduleEvent(id: scheduleId)); + }, + onToggleSchedule: (scheduleId, isEnabled) { + threeGangBloc.add(ToggleScheduleEvent( + id: scheduleId, + toggle: isEnabled, + )); + }, + ), + ), + ), + ], + ), + ], + ), ), ], ), - ), - ], - ), - )) - ); + ))); }, ), ), diff --git a/lib/features/devices/view/widgets/two_gang/two_gang_list.dart b/lib/features/devices/view/widgets/two_gang/two_gang_list.dart index 065dd62..a36de97 100644 --- a/lib/features/devices/view/widgets/two_gang/two_gang_list.dart +++ b/lib/features/devices/view/widgets/two_gang/two_gang_list.dart @@ -1,10 +1,9 @@ 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/groupTwoGangModel.dart'; -import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart'; +import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_bloc.dart'; +import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.dart'; +import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_state.dart'; +import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart'; import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart'; import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart'; @@ -16,7 +15,7 @@ class TwoGangList extends StatelessWidget { @override Widget build(BuildContext context) { - return BlocBuilder( + return BlocBuilder( builder: (context, state) { return SingleChildScrollView( child: Column( @@ -28,10 +27,10 @@ class TwoGangList extends StatelessWidget { DevicesDefaultSwitch( switchValue: allSwitches, action: () { - BlocProvider.of(context).add(GroupAllOnEvent()); + BlocProvider.of(context).add(GroupAllOnEvent()); }, secondAction: () { - BlocProvider.of(context).add(GroupAllOffEvent()); + BlocProvider.of(context).add(GroupAllOffEvent()); }, ), ListView.builder( @@ -44,30 +43,27 @@ class TwoGangList extends StatelessWidget { crossAxisAlignment: CrossAxisAlignment.start, children: [ const SizedBox(height: 10), - BodySmall(text: '${twoGangList[index].deviceName} beside light'), + BodySmall(text: twoGangList[index].deviceName), const SizedBox(height: 5), DevicesDefaultSwitch( switchValue: twoGangList[index].firstSwitch, action: () { - BlocProvider.of(context).add(ChangeFirstSwitchStatusEvent( + BlocProvider.of(context).add(ChangeFirstSwitchStatusEvent( value: twoGangList[index].firstSwitch, deviceId: twoGangList[index].deviceId)); }, ), const SizedBox(height: 10), - BodySmall(text: '${twoGangList[index].deviceName} ceiling light'), + BodySmall(text: twoGangList[index].deviceName), const SizedBox(height: 5), DevicesDefaultSwitch( switchValue: twoGangList[index].secondSwitch, action: () { - BlocProvider.of(context).add(ChangeSecondSwitchStatusEvent( + BlocProvider.of(context).add(ChangeSecondSwitchStatusEvent( value: twoGangList[index].secondSwitch, deviceId: twoGangList[index].deviceId)); }, ), - const SizedBox(height: 10), - BodySmall(text: '${twoGangList[index].deviceName} spotlight'), - const SizedBox(height: 5), ], ); }, diff --git a/lib/features/devices/view/widgets/two_gang/two_gang_screen.dart b/lib/features/devices/view/widgets/two_gang/two_gang_screen.dart index d332386..240a5ff 100644 --- a/lib/features/devices/view/widgets/two_gang/two_gang_screen.dart +++ b/lib/features/devices/view/widgets/two_gang/two_gang_screen.dart @@ -4,7 +4,7 @@ import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_bloc.da import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_event.dart'; import 'package:syncrow_app/features/devices/bloc/two_gang_bloc/two_gang_state.dart'; import 'package:syncrow_app/features/devices/model/device_model.dart'; -import 'package:syncrow_app/features/devices/model/groupTwoGangModel.dart'; +import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart'; import 'package:syncrow_app/features/devices/model/two_gang_model.dart'; import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart'; import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_list.dart'; @@ -22,18 +22,16 @@ class TwoGangScreen extends StatelessWidget { @override Widget build(BuildContext context) { return BlocProvider( - create: (context) => TwoGangBloc( - switchCode: switchCode??'', - twoGangId: device?.uuid ?? '') + create: (context) => TwoGangBloc(switchCode: switchCode ?? '', twoGangId: device?.uuid ?? '') ..add(InitialEvent(groupScreen: device != null ? false : true)), child: BlocBuilder( builder: (context, state) { TwoGangModel twoGangModel = TwoGangModel( - firstSwitch: false, - secondSwitch: false, - firstCountDown: 0, - secondCountDown: 0, - ); + firstSwitch: false, + secondSwitch: false, + firstCountDown: 0, + secondCountDown: 0, + ); List groupTwoGangModel = []; bool allSwitchesOn = false; @@ -47,7 +45,9 @@ class TwoGangScreen extends StatelessWidget { } return state is LoadingInitialState ? const Center( - child: DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),) + child: + DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()), + ) : device == null ? TwoGangList( twoGangList: groupTwoGangModel, @@ -116,7 +116,6 @@ class TwoGangScreen extends StatelessWidget { ), ], ), - ], ), ), diff --git a/lib/features/devices/view/widgets/wizard_page.dart b/lib/features/devices/view/widgets/wizard_page.dart index 6639321..fdddf05 100644 --- a/lib/features/devices/view/widgets/wizard_page.dart +++ b/lib/features/devices/view/widgets/wizard_page.dart @@ -2,7 +2,9 @@ import 'package:flutter/material.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/one_gang/one_gang_Interface.dart'; import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_interface.dart'; +import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_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'; @@ -39,6 +41,18 @@ class WizardPage extends StatelessWidget { pageBuilder: (context, animation1, animation2) => const ThreeGangInterface())); } + if (groupsList[index].name == '2G') { + Navigator.push( + context, + PageRouteBuilder( + pageBuilder: (context, animation1, animation2) => const TwoGangInterface())); + } + if (groupsList[index].name == '1G') { + Navigator.push( + context, + PageRouteBuilder( + pageBuilder: (context, animation1, animation2) => const OneGangInterface())); + } }, child: DefaultContainer( padding: const EdgeInsets.all(15), diff --git a/lib/features/shared_widgets/schedule_list.dart b/lib/features/shared_widgets/schedule_list.dart index 0b48f86..15e2b6e 100644 --- a/lib/features/shared_widgets/schedule_list.dart +++ b/lib/features/shared_widgets/schedule_list.dart @@ -1,16 +1,13 @@ - import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:syncrow_app/features/devices/model/schedule_model.dart'; -import 'package:syncrow_app/features/shared_widgets/default_button.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/features/shared_widgets/text_widgets/body_medium.dart'; import 'package:syncrow_app/generated/assets.dart'; import 'empty_schedule.dart'; // for SVG icons - class ScheduleListView extends StatelessWidget { final List listSchedule; final Function(String) onDismissed; @@ -25,96 +22,93 @@ class ScheduleListView extends StatelessWidget { @override Widget build(BuildContext context) { return Center( - child: listSchedule.isNotEmpty - ? SizedBox( - child: ListView.builder( - shrinkWrap: true, - itemCount: listSchedule.length, - itemBuilder: (context, index) { - return Dismissible( - key: Key(listSchedule[index].scheduleId), - background: Container( - padding: const EdgeInsets.only(right: 10), - alignment: AlignmentDirectional.centerEnd, - decoration: const ShapeDecoration( - color: Color(0xFFFF0000), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.all(Radius.circular(20)), - ), - ), - child: Padding( - padding: const EdgeInsets.only(bottom: 10, right: 10), - child: SvgPicture.asset( - Assets.assetsDeleteIcon, - width: 20, - height: 22, - ), - ), - ), - direction: DismissDirection.endToStart, - onDismissed: (direction) { - - onDismissed(listSchedule[index].scheduleId); - - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar(content: Text('Schedule removed')), - ); - }, - child: InkWell( - onTap: () { - - }, - child: DefaultContainer( - padding: const EdgeInsets.all(20), - height: MediaQuery.of(context).size.height / 6.4, - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - BodyLarge( - text: listSchedule[index].time, - fontWeight: FontWeight.w500, - fontColor: Colors.black, - fontSize: 22, - ), - Text(listSchedule[index].days.join(' ')), - Text('Function ${listSchedule[index].function.value ? "ON" : "OFF"}'), - ], - ), - ), - Expanded( - child: ListTile( - contentPadding: EdgeInsets.zero, - leading: const BodyMedium( - text: '', - fontWeight: FontWeight.normal, + child: listSchedule.isNotEmpty + ? SizedBox( + child: ListView.builder( + shrinkWrap: true, + itemCount: listSchedule.length, + itemBuilder: (context, index) { + return Dismissible( + key: Key(listSchedule[index].scheduleId), + background: Container( + padding: const EdgeInsets.only(right: 10), + alignment: AlignmentDirectional.centerEnd, + decoration: const ShapeDecoration( + color: Color(0xFFFF0000), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.all(Radius.circular(20)), ), - trailing: Transform.scale( - scale: .8, - child: CupertinoSwitch( - value: listSchedule[index].enable, - onChanged: (value) { - onToggleSchedule( - listSchedule[index].scheduleId, - value, - ); - }, - applyTheme: true, - ), + ), + child: Padding( + padding: const EdgeInsets.only(bottom: 10, right: 10), + child: SvgPicture.asset( + Assets.assetsDeleteIcon, + width: 20, + height: 22, ), ), ), - ], - ), + direction: DismissDirection.endToStart, + onDismissed: (direction) { + onDismissed(listSchedule[index].scheduleId); + + ScaffoldMessenger.of(context).showSnackBar( + const SnackBar(content: Text('Schedule removed')), + ); + }, + child: InkWell( + onTap: () {}, + child: DefaultContainer( + padding: const EdgeInsets.all(20), + height: MediaQuery.of(context).size.height / 6.4, + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + BodyLarge( + text: listSchedule[index].time, + fontWeight: FontWeight.w500, + fontColor: Colors.black, + fontSize: 22, + ), + Text(listSchedule[index].days.join(' ')), + Text( + 'Function ${listSchedule[index].function.value ? "ON" : "OFF"}'), + ], + ), + ), + Expanded( + child: ListTile( + contentPadding: EdgeInsets.zero, + leading: const BodyMedium( + text: '', + fontWeight: FontWeight.normal, + ), + trailing: Transform.scale( + scale: .8, + child: CupertinoSwitch( + value: listSchedule[index].enable, + onChanged: (value) { + onToggleSchedule( + listSchedule[index].scheduleId, + value, + ); + }, + applyTheme: true, + ), + ), + ), + ), + ], + ), + ), + ), + ); + }, ), - ), - ); - }, - ), - ) - : const EmptySchedule() - ); + ) + : const EmptySchedule()); } } diff --git a/lib/services/api/devices_api.dart b/lib/services/api/devices_api.dart index f8a8101..1d38fd0 100644 --- a/lib/services/api/devices_api.dart +++ b/lib/services/api/devices_api.dart @@ -72,8 +72,7 @@ class DevicesAPI { static Future> getDeviceStatus(String deviceId) async { final response = await _httpService.get( - path: ApiEndpoints.deviceFunctionsStatus - .replaceAll('{deviceUuid}', deviceId), + path: ApiEndpoints.deviceFunctionsStatus.replaceAll('{deviceUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -83,9 +82,7 @@ class DevicesAPI { } static Future> renamePass( - {required String name, - required String doorLockUuid, - required String passwordId}) async { + {required String name, required String doorLockUuid, required String passwordId}) async { final response = await _httpService.put( path: ApiEndpoints.renamePassword .replaceAll('{doorLockUuid}', doorLockUuid) @@ -110,8 +107,7 @@ class DevicesAPI { return response; } - static Future> getDeviceByGroupName( - String unitId, String groupName) async { + static Future> getDeviceByGroupName(String unitId, String groupName) async { final response = await _httpService.get( path: ApiEndpoints.devicesByGroupName .replaceAll('{unitUuid}', unitId) @@ -150,8 +146,7 @@ class DevicesAPI { return response; } - static Future> getDevicesByGatewayId( - String gatewayId) async { + static Future> getDevicesByGatewayId(String gatewayId) async { final response = await _httpService.get( path: ApiEndpoints.gatewayApi.replaceAll('{gatewayUuid}', gatewayId), showServerMessage: false, @@ -173,8 +168,7 @@ class DevicesAPI { String deviceId, ) async { final response = await _httpService.get( - path: ApiEndpoints.getTemporaryPassword - .replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.getTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -185,8 +179,7 @@ class DevicesAPI { static Future getOneTimePasswords(String deviceId) async { final response = await _httpService.get( - path: ApiEndpoints.getOneTimeTemporaryPassword - .replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.getOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -197,8 +190,7 @@ class DevicesAPI { static Future getTimeLimitPasswords(String deviceId) async { final response = await _httpService.get( - path: ApiEndpoints.getMultipleTimeTemporaryPassword - .replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.getMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -223,12 +215,10 @@ class DevicesAPI { "invalidTime": invalidTime, }; if (scheduleList != null) { - body["scheduleList"] = - scheduleList.map((schedule) => schedule.toJson()).toList(); + body["scheduleList"] = scheduleList.map((schedule) => schedule.toJson()).toList(); } final response = await _httpService.post( - path: ApiEndpoints.addTemporaryPassword - .replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.addTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), body: body, showServerMessage: false, expectedResponseModel: (json) => json, @@ -239,8 +229,7 @@ class DevicesAPI { static Future generateOneTimePassword({deviceId}) async { try { final response = await _httpService.post( - path: ApiEndpoints.addOneTimeTemporaryPassword - .replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.addOneTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), showServerMessage: false, expectedResponseModel: (json) { return json; @@ -252,12 +241,10 @@ class DevicesAPI { } } - static Future generateMultiTimePassword( - {deviceId, effectiveTime, invalidTime}) async { + static Future generateMultiTimePassword({deviceId, effectiveTime, invalidTime}) async { try { final response = await _httpService.post( - path: ApiEndpoints.addMultipleTimeTemporaryPassword - .replaceAll('{doorLockUuid}', deviceId), + path: ApiEndpoints.addMultipleTimeTemporaryPassword.replaceAll('{doorLockUuid}', deviceId), showServerMessage: true, body: {"effectiveTime": effectiveTime, "invalidTime": invalidTime}, expectedResponseModel: (json) { @@ -366,7 +353,7 @@ class DevicesAPI { required String endTime, }) async { // print( - // '---------${ApiEndpoints.reportLogs.replaceAll('{deviceUuid}', deviceUuid).replaceAll('{code}', code).replaceAll('{startTime}', startTime).replaceAll('{endTime}', endTime)}'); + // '---------${ApiEndpoints.reportLogs.replaceAll('{deviceUuid}', deviceUuid).replaceAll('{code}', code).replaceAll('{startTime}', startTime).replaceAll('{endTime}', endTime)}'); final response = await _httpService.get( path: ApiEndpoints.reportLogs .replaceAll('{deviceUuid}', deviceUuid) @@ -375,7 +362,6 @@ class DevicesAPI { .replaceAll('{endTime}', endTime), expectedResponseModel: (json) { return DeviceReport.fromJson(json); - return json; }, );