Merge pull request #54 from SyncrowIOT/SP-496

Sp 496
This commit is contained in:
mohammadnemer1
2024-09-29 12:08:13 +03:00
committed by GitHub
24 changed files with 1788 additions and 1282 deletions

View File

@ -2,9 +2,11 @@ import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.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/bloc/one_gang_bloc/one_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_control_model.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart';
import 'package:syncrow_app/features/devices/model/one_gang_model.dart';
import 'package:syncrow_app/features/devices/model/schedule_model.dart';
import 'package:syncrow_app/features/devices/model/status_model.dart';
@ -41,6 +43,10 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
on<DeleteScheduleEvent>(deleteSchedule);
on<ToggleSelectedEvent>(toggleSelectedIndex);
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
on<InitialWizardEvent>(_fetchOneGangWizardStatus);
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
on<GroupAllOnEvent>(_groupAllOn);
on<GroupAllOffEvent>(_groupAllOff);
}
void _fetchOneGangStatus(InitialEvent event, Emitter<OneGangState> emit) async {
@ -290,15 +296,6 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
}
}
// void toggleCreateSchedule() {
// emit(LoadingInitialState());
// createSchedule = !createSchedule;
// selectedDays.clear();
// selectedTime = DateTime.now();
// emit(UpdateCreateScheduleState(createSchedule));
// emit(ChangeSlidingSegmentState(value: 1));
// }
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<OneGangState> emit) {
emit(LoadingInitialState());
@ -324,7 +321,7 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
selectedDays.add(event.key);
}
emit(ChangeTimeState());
add(ChangeSlidingSegment(value: 1));
add(const ChangeSlidingSegment(value: 1));
}
int selectedTabIndex = 0;
@ -334,4 +331,140 @@ class OneGangBloc extends Bloc<OneGangEvent, OneGangState> {
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
List<GroupOneGangModel> groupOneGangList = [];
bool allSwitchesOn = true;
void _fetchOneGangWizardStatus(InitialWizardEvent event, Emitter<OneGangState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
groupOneGangList = [];
allSwitchesOn = true;
devicesList = await DevicesAPI.getDeviceByGroupName(
HomeCubit.getInstance().selectedSpace?.id ?? '', '1G');
for (int i = 0; i < devicesList.length; i++) {
var response = await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = OneGangModel.fromJson(statusModelList);
groupOneGangList.add(GroupOneGangModel(
deviceId: devicesList[i].uuid ?? '',
deviceName: devicesList[i].name ?? '',
firstSwitch: deviceStatus.firstSwitch,
));
}
if (groupOneGangList.isNotEmpty) {
groupOneGangList.firstWhere((element) {
if (!element.firstSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(
ChangeFirstWizardSwitchStatusEvent event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
groupOneGangList.forEach((element) {
if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value;
}
if (!element.firstSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: [event.deviceId],
value: !event.value,
);
if (response['failedResults'].toString() != '[]') {
add(InitialEvent(groupScreen: oneGangGroup));
}
} catch (_) {
add(InitialEvent(groupScreen: oneGangGroup));
}
}
void _groupAllOn(GroupAllOnEvent event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
try {
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
for (int i = 0; i < groupOneGangList.length; i++) {
groupOneGangList[i].firstSwitch = true;
}
// Emit the state with updated values
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: true));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
// First call for switch_1
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1', // Controls first switch for all devices
devicesUuid: allDeviceIds,
value: true, // true (on) or false (off) depending on the event value
);
// Check if either response is unsuccessful, then reset to initial state
if (response['failedResults'].toString() != '[]') {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: true));
}
} catch (_) {
// In case of an error, delay and reset the screen to initial state
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: true));
}
}
void _groupAllOff(GroupAllOffEvent event, Emitter<OneGangState> emit) async {
emit(LoadingNewSate(oneGangModel: deviceStatus));
try {
// Set all switches (firstSwitch and secondSwitch) based on the event value (on/off)
for (int i = 0; i < groupOneGangList.length; i++) {
groupOneGangList[i].firstSwitch = false;
}
// Emit the state with updated values
emit(UpdateGroupState(oneGangList: groupOneGangList, allSwitches: false));
// Get a list of all device IDs
List<String> allDeviceIds = groupOneGangList.map((device) => device.deviceId).toList();
// First call for switch_1
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1', // Controls first switch for all devices
devicesUuid: allDeviceIds,
value: false, // true (on) or false (off) depending on the event value
);
// Check if either response is unsuccessful, then reset to initial state
if (response['failedResults'].toString() != '[]') {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: true));
}
} catch (_) {
// In case of an error, delay and reset the screen to initial state
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: true));
}
}
}

View File

@ -29,12 +29,12 @@ class ChangeFirstSwitchStatusEvent extends OneGangEvent {
class ChangeSecondSwitchStatusEvent extends OneGangEvent {
final bool value;
final String deviceId;
const ChangeSecondSwitchStatusEvent({required this.value, this.deviceId = ''});
const ChangeSecondSwitchStatusEvent(
{required this.value, this.deviceId = ''});
@override
List<Object> get props => [value, deviceId];
}
class AllOffEvent extends OneGangEvent {}
class AllOnEvent extends OneGangEvent {}
@ -87,12 +87,13 @@ class StopTimer extends OneGangEvent {}
class OnClose extends OneGangEvent {}
class InitialWizardEvent extends OneGangEvent {}
//------------------- Schedule ----------=---------
class GetScheduleEvent extends OneGangEvent {}
class ScheduleSave extends OneGangEvent {}
class ToggleScheduleEvent extends OneGangEvent {
final String id;
final bool toggle;
@ -100,14 +101,15 @@ class ToggleScheduleEvent extends OneGangEvent {
@override
List<Object> get props => [toggle, id];
}
class ToggleDaySelectionEvent extends OneGangEvent {
class ToggleDaySelectionEvent extends OneGangEvent {
final String key;
const ToggleDaySelectionEvent({required this.key});
@override
List<Object> get props => [key];
}
class DeleteScheduleEvent extends OneGangEvent {
final String id;
const DeleteScheduleEvent({required this.id});
@ -115,7 +117,6 @@ class DeleteScheduleEvent extends OneGangEvent {
List<Object> get props => [id];
}
class ToggleSelectedEvent extends OneGangEvent {
final int index;
const ToggleSelectedEvent({required this.index});
@ -123,10 +124,18 @@ class ToggleSelectedEvent extends OneGangEvent {
List<Object> get props => [index];
}
class ToggleCreateScheduleEvent extends OneGangEvent {
final int index;
const ToggleCreateScheduleEvent({required this.index});
@override
List<Object> get props => [index];
}
class ChangeFirstWizardSwitchStatusEvent extends OneGangEvent {
final bool value;
final String deviceId;
const ChangeFirstWizardSwitchStatusEvent(
{required this.value, this.deviceId = ''});
@override
List<Object> get props => [value, deviceId];
}

View File

@ -25,9 +25,6 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
secondCountDown: 0,
thirdCountDown: 0);
Timer? _timer;
// Timer? _firstSwitchTimer;
// Timer? _secondSwitchTimer;
// Timer? _thirdSwitchTimer;
bool threeGangGroup = false;
List<DeviceModel> devicesList = [];
@ -606,24 +603,6 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
}
}
// void toggleCreateSchedule() {
// emit(LoadingInitialState());
// createSchedule = !createSchedule;
// selectedDays.clear();
// selectedTime = DateTime.now();
// emit(UpdateCreateScheduleState(createSchedule));
// emit(ChangeSlidingSegmentState(value: 1));
// }
// void toggleSelectedIndex(index) {
// emit(LoadingInitialState());
// selectedTabIndex = index;
// emit(ChangeSlidingSegmentState(value: selectedTabIndex));
// }
void toggleSelectedIndex(ToggleSelectedEvent event, Emitter<ThreeGangState> emit) {
emit(LoadingInitialState());
selectedTabIndex = event.index;
@ -638,7 +617,6 @@ class ThreeGangBloc extends Bloc<ThreeGangEvent, ThreeGangState> {
emit(UpdateCreateScheduleState(createSchedule));
}
int selectedTabIndex = 0;
bool toggleSchedule = true;
List<String> selectedDays = [];

View File

@ -136,3 +136,5 @@ class ToggleCreateScheduleEvent extends ThreeGangEvent {
@override
List<Object> get props => [index];
}
class InitialWizardDevises extends ThreeGangEvent {}

View File

@ -57,27 +57,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
on<DeleteScheduleEvent>(deleteSchedule);
on<ToggleSelectedEvent>(toggleSelectedIndex);
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
on<InitialWizardEvent>(_fetchTwoGangWizardStatus);
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
on<ChangeSecondWizardSwitchStatusEvent>(_changeSecondWizardSwitch);
}
DateTime? selectedTime = DateTime.now();
// void toggleCreateSchedule() {
// emit(LoadingInitialState());
// createSchedule = !createSchedule;
// selectedDays.clear();
// selectedTime = DateTime.now();
// emit(UpdateCreateScheduleState(createSchedule));
// emit(ChangeSlidingSegmentState(value: 1));
// }
int selectedTabIndex = 0;
// void toggleSelectedIndex(index) {
// emit(LoadingInitialState());
// selectedTabIndex = index;
// emit(ChangeSlidingSegmentState(value: selectedTabIndex));
// }
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<TwoGangState> emit) {
emit(LoadingInitialState());
@ -98,42 +86,6 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
InitialEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState());
try {
twoGangGroup = event.groupScreen;
if (twoGangGroup) {
devicesList = [];
groupTwoGangList = [];
allSwitchesOn = true;
devicesList = await DevicesAPI.getDeviceByGroupName(
HomeCubit.getInstance().selectedSpace?.id ?? '', '2G');
for (int i = 0; i < devicesList.length; i++) {
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = TwoGangModel.fromJson(statusModelList);
groupTwoGangList.add(GroupTwoGangModel(
deviceId: devicesList[i].uuid ?? '',
deviceName: devicesList[i].name ?? '',
firstSwitch: deviceStatus.firstSwitch,
secondSwitch: deviceStatus.secondSwitch,
));
}
if (groupTwoGangList.isNotEmpty) {
groupTwoGangList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
} else {
var response = await DevicesAPI.getDeviceStatus(twoGangId);
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
@ -142,7 +94,6 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
deviceStatus = TwoGangModel.fromJson(statusModelList);
emit(UpdateState(twoGangModel: deviceStatus));
_listenToChanges();
}
} catch (e) {
emit(FailedState(error: e.toString()));
return;
@ -193,17 +144,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
_timer = Timer(const Duration(milliseconds: 500), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangGroup ? event.deviceId : twoGangId,
code: 'switch_1',
value: !event.value),
twoGangGroup ? event.deviceId : twoGangId);
deviceId: twoGangId, code: 'switch_1', value: !event.value),
twoGangId);
if (!response['success']) {
add(InitialEvent(groupScreen: twoGangGroup));
add(const InitialEvent());
}
});
} catch (_) {
add(InitialEvent(groupScreen: twoGangGroup));
add(const InitialEvent());
}
}
@ -219,17 +168,15 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
_timer = Timer(const Duration(milliseconds: 500), () async {
final response = await DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: twoGangGroup ? event.deviceId : twoGangId,
code: 'switch_2',
value: !event.value),
twoGangGroup ? event.deviceId : twoGangId);
deviceId: twoGangId, code: 'switch_2', value: !event.value),
twoGangId);
if (!response['success']) {
add(InitialEvent(groupScreen: twoGangGroup));
add(const InitialEvent());
}
});
} catch (_) {
add(InitialEvent(groupScreen: twoGangGroup));
add(const InitialEvent());
}
}
@ -258,11 +205,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
if (response.every((element) => !element['success'])) {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: false));
add(const InitialEvent());
}
} catch (_) {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: false));
add(const InitialEvent());
}
}
@ -288,11 +235,11 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
]);
if (response.every((element) => !element['success'])) {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: false));
add(const InitialEvent());
}
} catch (_) {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: false));
add(const InitialEvent());
}
}
@ -304,32 +251,29 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
groupTwoGangList[i].secondSwitch = true;
}
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: true));
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
for (int i = 0; i < groupTwoGangList.length; i++) {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupTwoGangList[i].deviceId,
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
value: true),
groupTwoGangList[i].deviceId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupTwoGangList[i].deviceId,
code: 'switch_2',
value: true),
groupTwoGangList[i].deviceId),
]);
devicesUuid: allDeviceIds,
value: true,
);
if (response.every((element) => !element['success'])) {
final response2 = await DevicesAPI.deviceBatchController(
code: 'switch_2',
devicesUuid: allDeviceIds,
value: true,
);
if (response1['failedResults'].toString() != '[]' ||
response2['failedResults'].toString() != '[]') {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: true));
break;
}
add(InitialWizardEvent());
}
} catch (_) {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: true));
add(InitialWizardEvent());
}
}
@ -340,33 +284,32 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
groupTwoGangList[i].firstSwitch = false;
groupTwoGangList[i].secondSwitch = false;
}
emit(UpdateGroupState(twoGangList: groupTwoGangList, allSwitches: false));
for (int i = 0; i < groupTwoGangList.length; i++) {
final response = await Future.wait([
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupTwoGangList[i].deviceId,
code: 'switch_1',
value: false),
groupTwoGangList[i].deviceId),
DevicesAPI.controlDevice(
DeviceControlModel(
deviceId: groupTwoGangList[i].deviceId,
code: 'switch_2',
value: false),
groupTwoGangList[i].deviceId),
]);
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
if (response.every((element) => !element['success'])) {
final response1 = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
value: false,
);
final response2 = await DevicesAPI.deviceBatchController(
code: 'switch_2',
devicesUuid: allDeviceIds,
value: false,
);
if (response1['failedResults'].toString() != '[]' ||
response2['failedResults'].toString() != '[]') {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: true));
break;
}
add(InitialWizardEvent());
}
} catch (_) {
await Future.delayed(const Duration(milliseconds: 500));
add(const InitialEvent(groupScreen: true));
add(InitialWizardEvent());
}
}
@ -476,7 +419,7 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
selectedDays.add(event.key);
}
emit(ChangeTimeState());
add(ChangeSlidingSegment(value: 1));
add(const ChangeSlidingSegment(value: 1));
}
Future<void> saveSchedule(
@ -486,7 +429,7 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
try {
if (selectedDays.isNotEmpty) {
emit(LoadingInitialState());
final response = await DevicesAPI.postSchedule(
await DevicesAPI.postSchedule(
category: switchCode,
deviceId: twoGangId,
time: getTimeStampWithoutSeconds(selectedTime).toString(),
@ -574,4 +517,113 @@ class TwoGangBloc extends Bloc<TwoGangEvent, TwoGangState> {
emit(FailedState(error: errorMessage.toString()));
}
}
void _fetchTwoGangWizardStatus(
InitialWizardEvent event, Emitter<TwoGangState> emit) async {
emit(LoadingInitialState());
try {
devicesList = [];
groupTwoGangList = [];
allSwitchesOn = true;
devicesList = await DevicesAPI.getDeviceByGroupName(
HomeCubit.getInstance().selectedSpace?.id ?? '', '2G');
for (int i = 0; i < devicesList.length; i++) {
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = TwoGangModel.fromJson(statusModelList);
groupTwoGangList.add(GroupTwoGangModel(
deviceId: devicesList[i].uuid ?? '',
deviceName: devicesList[i].name ?? '',
firstSwitch: deviceStatus.firstSwitch,
secondSwitch: deviceStatus.secondSwitch,
));
}
if (groupTwoGangList.isNotEmpty) {
groupTwoGangList.firstWhere((element) {
if (!element.firstSwitch || !element.secondSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesOn));
} catch (e) {
emit(FailedState(error: e.toString()));
return;
}
}
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
groupTwoGangList.forEach((element) {
if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
value: !event.value,
);
if (response['failedResults'].toString() != '[]') {
add(InitialWizardEvent());
}
} catch (_) {
add(InitialWizardEvent());
}
}
void _changeSecondWizardSwitch(ChangeSecondWizardSwitchStatusEvent event,
Emitter<TwoGangState> emit) async {
emit(LoadingNewSate(twoGangModel: deviceStatus));
try {
bool allSwitchesValue = true;
groupTwoGangList.forEach((element) {
if (element.deviceId == event.deviceId) {
element.secondSwitch = !event.value;
}
if (!element.firstSwitch || !element.secondSwitch) {
allSwitchesValue = false;
}
});
List<String> allDeviceIds =
groupTwoGangList.map((device) => device.deviceId).toList();
emit(UpdateGroupState(
twoGangList: groupTwoGangList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_2',
devicesUuid: allDeviceIds,
value: !event.value,
);
if (response['failedResults'].toString() != '[]') {
add(InitialWizardEvent());
}
} catch (_) {
add(InitialWizardEvent());
}
}
}

View File

@ -10,7 +10,9 @@ abstract class TwoGangEvent extends Equatable {
class LoadingEvent extends TwoGangEvent {}
class TwoGangUpdated extends TwoGangEvent {}
class TwoGangSave extends TwoGangEvent {}
class ToggleScheduleEvent extends TwoGangEvent {
final String id;
final bool toggle;
@ -18,9 +20,10 @@ class ToggleScheduleEvent extends TwoGangEvent {
@override
List<Object> get props => [toggle, id];
}
class errorMessage extends TwoGangEvent {}
class ToggleDaySelectionEvent extends TwoGangEvent {
class errorMessage extends TwoGangEvent {}
class ToggleDaySelectionEvent extends TwoGangEvent {
final String key;
const ToggleDaySelectionEvent({required this.key});
@ -29,10 +32,9 @@ class ToggleDaySelectionEvent extends TwoGangEvent {
}
class InitialEvent extends TwoGangEvent {
final bool groupScreen;
const InitialEvent({required this.groupScreen});
const InitialEvent();
@override
List<Object> get props => [groupScreen];
List<Object> get props => [];
}
class ChangeFirstSwitchStatusEvent extends TwoGangEvent {
@ -51,7 +53,6 @@ class ChangeSecondSwitchStatusEvent extends TwoGangEvent {
List<Object> get props => [value, deviceId];
}
class AllOffEvent extends TwoGangEvent {}
class AllOnEvent extends TwoGangEvent {}
@ -60,13 +61,9 @@ class GroupAllOnEvent extends TwoGangEvent {}
class GroupAllOffEvent extends TwoGangEvent {}
// two_gang_event.dart
// class ToggleCreateScheduleEvent extends TwoGangEvent {}
class ChangeSlidingSegment extends TwoGangEvent {
final int value;
const ChangeSlidingSegment({required this.value});
@ -111,20 +108,20 @@ class StopTimer extends TwoGangEvent {}
class OnClose extends TwoGangEvent {}
class GetScheduleEvent extends TwoGangEvent {}
class DeleteScheduleEvent extends TwoGangEvent {
final String id;
const DeleteScheduleEvent({required this.id});
@override
List<Object> get props => [id];
}
class TabChangedEvent extends TwoGangEvent {
final int index;
TabChangedEvent({required this.index});
}
class ToggleSelectedEvent extends TwoGangEvent {
final int index;
const ToggleSelectedEvent({required this.index});
@ -132,7 +129,6 @@ class ToggleSelectedEvent extends TwoGangEvent {
List<Object> get props => [index];
}
class ToggleCreateScheduleEvent extends TwoGangEvent {
final int index;
const ToggleCreateScheduleEvent({required this.index});
@ -140,5 +136,20 @@ class ToggleCreateScheduleEvent extends TwoGangEvent {
List<Object> get props => [index];
}
class InitialWizardEvent extends TwoGangEvent {}
class ChangeFirstWizardSwitchStatusEvent extends TwoGangEvent {
final bool value;
final String deviceId;
const ChangeFirstWizardSwitchStatusEvent({required this.value, this.deviceId = ''});
@override
List<Object> get props => [value, deviceId];
}
class ChangeSecondWizardSwitchStatusEvent extends TwoGangEvent {
final bool value;
final String deviceId;
const ChangeSecondWizardSwitchStatusEvent({required this.value, this.deviceId = ''});
@override
List<Object> get props => [value, deviceId];
}

View File

@ -1,9 +1,12 @@
import 'dart:async';
import 'package:dio/dio.dart';
import 'package:firebase_database/firebase_database.dart';
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/bloc/water_heater_bloc/water_heater_event.dart';
import 'package:syncrow_app/features/devices/bloc/water_heater_bloc/water_heater_state.dart';
import 'package:syncrow_app/features/devices/model/GroupWHModel.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/schedule_model.dart';
@ -16,9 +19,7 @@ import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
final String whId;
final String switchCode;
WHModel deviceStatus = WHModel(
firstSwitch: false,firstCountDown: 0
);
WHModel deviceStatus = WHModel(firstSwitch: false, firstCountDown: 0);
List<WHModel> deviceStatusList = [];
List<DeviceModel> devicesList = [];
bool allAcsPage = false;
@ -27,7 +28,6 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
int globalTemp = 25;
Timer? _timer;
bool toggleSchedule = true;
List<String> selectedDays = [];
bool createSchedule = false;
@ -35,7 +35,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
List<ScheduleModel> listSchedule = [];
DateTime? selectedTime = DateTime.now();
WaterHeaterBloc({required this.whId,required this.switchCode}) : super(WHInitialState()) {
WaterHeaterBloc({required this.whId, required this.switchCode})
: super(WHInitialState()) {
on<WaterHeaterInitial>(_fetchWaterHeaterStatus);
on<WaterHeaterSwitch>(_changeFirstSwitch);
on<SetCounterValue>(_setCounterValue);
@ -51,9 +52,17 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
on<ToggleSelectedEvent>(toggleSelectedIndex);
on<ToggleCreateScheduleEvent>(toggleCreateSchedule);
on<InitialWizardEvent>(_fetchWHWizardStatus);
on<ChangeFirstWizardSwitchStatusEvent>(_changeFirstWizardSwitch);
on<GroupAllOnEvent>(_groupAllOn);
on<GroupAllOffEvent>(_groupAllOff);
on<ToggleCreateCirculate>(_toggleCreateCirculate);
on<WaterHeaterUpdated>(_waterHeaterUpdated);
}
void _fetchWaterHeaterStatus(WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
void _fetchWaterHeaterStatus(
WaterHeaterInitial event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(whId);
@ -61,18 +70,52 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = WHModel.fromJson(statusModelList, );
deviceStatus = WHModel.fromJson(
statusModelList,
);
emit(UpdateState(whModel: deviceStatus));
Future.delayed(const Duration(milliseconds: 500));
// _listenToChanges();
_listenToChanges();
} catch (e) {
emit(WHFailedState(errorMessage: e.toString()));
return;
}
}
_listenToChanges() {
try {
DatabaseReference ref =
FirebaseDatabase.instance.ref('device-status/$whId');
Stream<DatabaseEvent> stream = ref.onValue;
void _changeFirstSwitch(WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async {
stream.listen((DatabaseEvent event) async {
if (_timer != null) {
await Future.delayed(const Duration(seconds: 2));
}
Map<dynamic, dynamic> usersMap =
event.snapshot.value as Map<dynamic, dynamic>;
List<StatusModel> statusList = [];
usersMap['status'].forEach((element) {
statusList
.add(StatusModel(code: element['code'], value: element['value']));
});
deviceStatus = WHModel.fromJson(statusList);
if (!isClosed) {
add(WaterHeaterUpdated());
}
});
} catch (_) {}
}
_waterHeaterUpdated(
WaterHeaterUpdated event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
emit(UpdateState(whModel: deviceStatus));
}
void _changeFirstSwitch(
WaterHeaterSwitch event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
deviceStatus.firstSwitch = !event.whSwitch;
@ -97,19 +140,17 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
//=====================---------- timer ----------------------------------------
void _setCounterValue(SetCounterValue event, Emitter<WaterHeaterState> emit) async {
void _setCounterValue(
SetCounterValue event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
int seconds = 0;
try {
seconds = event.duration.inSeconds;
final response = await DevicesAPI.controlDevice(
DeviceControlModel(deviceId: whId, code: event.deviceCode, value: seconds),
DeviceControlModel(
deviceId: whId, code: event.deviceCode, value: seconds),
whId);
if (response['success'] ?? false) {
@ -132,7 +173,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
void _getCounterValue(GetCounterEvent event, Emitter<WaterHeaterState> emit) async {
void _getCounterValue(
GetCounterEvent event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
var response = await DevicesAPI.getDeviceStatus(whId);
@ -173,13 +215,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
//=====================---------- Schedule ----------------------------------------
List<Map<String, String>> days = [
{"day": "Sun", "key": "Sun"},
{"day": "Mon", "key": "Mon"},
@ -190,11 +227,14 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
{"day": "Sat", "key": "Sat"},
];
Future<void> saveSchedule(ScheduleSave event, Emitter<WaterHeaterState> emit,) async {
Future<void> saveSchedule(
ScheduleSave event,
Emitter<WaterHeaterState> emit,
) async {
try {
if (selectedDays.isNotEmpty) {
emit(WHLoadingState());
final response = await DevicesAPI.postSchedule(
await DevicesAPI.postSchedule(
category: switchCode,
deviceId: whId,
time: getTimeStampWithoutSeconds(selectedTime).toString(),
@ -213,7 +253,10 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
Future<void> getSchedule(GetScheduleEvent event, Emitter<WaterHeaterState> emit,) async {
Future<void> getSchedule(
GetScheduleEvent event,
Emitter<WaterHeaterState> emit,
) async {
try {
emit(WHLoadingState());
final response = await DevicesAPI.getSchedule(
@ -221,7 +264,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
deviceId: whId,
);
List<dynamic> jsonData = response;
listSchedule = jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
listSchedule =
jsonData.map((item) => ScheduleModel.fromJson(item)).toList();
emit(WHInitialState());
} on DioException catch (e) {
final errorData = e.response!.data;
@ -262,7 +306,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
emit(WHLoadingState());
final response = await DevicesAPI.deleteSchedule(
scheduleId: event.id,
deviceUuid: whId, );
deviceUuid: whId,
);
if (response == true) {
add(GetScheduleEvent());
return toggleSchedule;
@ -275,15 +320,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
}
}
// void toggleCreateSchedule() {
// emit(WHLoadingState());
// createSchedule = !createSchedule;
// selectedDays.clear();
// selectedTime=DateTime.now();
// emit(UpdateCreateScheduleState(createSchedule));
// }
void toggleCreateCirculate() {
void _toggleCreateCirculate(
ToggleCreateCirculate event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
createCirculate = !createCirculate;
selectedDays.clear();
@ -291,20 +329,15 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
emit(UpdateCreateScheduleState(createCirculate));
}
// void toggleSelectedIndex(index) {
// emit(WHLoadingState());
// selectedTabIndex = index;
// emit(ChangeSlidingSegmentState(value: selectedTabIndex));
// }
void toggleSelectedIndex( ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
void toggleSelectedIndex(
ToggleSelectedEvent event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
selectedTabIndex = event.index;
emit(ChangeSlidingSegmentState(value: selectedTabIndex));
}
void toggleCreateSchedule(ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
void toggleCreateSchedule(
ToggleCreateScheduleEvent event, Emitter<WaterHeaterState> emit) {
emit(WHLoadingState());
createSchedule = !createSchedule;
selectedDays.clear();
@ -327,9 +360,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
int selectedTabIndex = 0;
showTime(SelectTimeEvent event, Emitter<WaterHeaterState> emit) async {
final TimeOfDay? timePicked = await showTimePicker(
await showTimePicker(
context: event.context,
initialTime: TimeOfDay.now(),
builder: (context, child) {
@ -350,4 +382,137 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
},
);
}
List<GroupWHModel> groupWaterHeaterList = [];
bool allSwitchesOn = true;
void _changeFirstWizardSwitch(ChangeFirstWizardSwitchStatusEvent event,
Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
bool allSwitchesValue = true;
groupWaterHeaterList.forEach((element) {
if (element.deviceId == event.deviceId) {
element.firstSwitch = !event.value;
}
if (!element.firstSwitch) {
allSwitchesValue = false;
}
});
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesValue));
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: [event.deviceId],
value: !event.value,
);
if (response['failedResults'].toString() != '[]') {
add(InitialWizardEvent());
}
} catch (_) {
add(InitialWizardEvent());
}
}
void _fetchWHWizardStatus(
InitialWizardEvent event, Emitter<WaterHeaterState> emit) async {
emit(WHLoadingState());
try {
devicesList = [];
groupWaterHeaterList = [];
allSwitchesOn = true;
devicesList = await DevicesAPI.getDeviceByGroupName(
HomeCubit.getInstance().selectedSpace?.id ?? '', 'WH');
for (int i = 0; i < devicesList.length; i++) {
var response =
await DevicesAPI.getDeviceStatus(devicesList[i].uuid ?? '');
List<StatusModel> statusModelList = [];
for (var status in response['status']) {
statusModelList.add(StatusModel.fromJson(status));
}
deviceStatus = WHModel.fromJson(statusModelList);
groupWaterHeaterList.add(GroupWHModel(
deviceId: devicesList[i].uuid ?? '',
deviceName: devicesList[i].name ?? '',
firstSwitch: deviceStatus.firstSwitch,
));
}
if (groupWaterHeaterList.isNotEmpty) {
groupWaterHeaterList.firstWhere((element) {
if (!element.firstSwitch) {
allSwitchesOn = false;
}
return true;
});
}
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: allSwitchesOn));
} catch (e) {
// emit(FailedState(error: e.toString()));
return;
}
}
void _groupAllOn(
GroupAllOnEvent event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
for (int i = 0; i < groupWaterHeaterList.length; i++) {
groupWaterHeaterList[i].firstSwitch = true;
}
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: true));
List<String> allDeviceIds =
groupWaterHeaterList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
value: true,
);
if (response['failedResults'].toString() != '[]') {
await Future.delayed(const Duration(milliseconds: 500));
add(InitialWizardEvent());
}
} catch (_) {
await Future.delayed(const Duration(milliseconds: 500));
add(InitialWizardEvent());
}
}
void _groupAllOff(
GroupAllOffEvent event, Emitter<WaterHeaterState> emit) async {
emit(LoadingNewSate(whModel: deviceStatus));
try {
for (int i = 0; i < groupWaterHeaterList.length; i++) {
groupWaterHeaterList[i].firstSwitch = false;
}
emit(UpdateGroupState(
twoGangList: groupWaterHeaterList, allSwitches: false));
List<String> allDeviceIds =
groupWaterHeaterList.map((device) => device.deviceId).toList();
final response = await DevicesAPI.deviceBatchController(
code: 'switch_1',
devicesUuid: allDeviceIds,
value: false,
);
if (response['failedResults'].toString() != '[]') {
await Future.delayed(const Duration(milliseconds: 500));
add(InitialWizardEvent());
}
} catch (_) {
await Future.delayed(const Duration(milliseconds: 500));
add(InitialWizardEvent());
}
}
}

View File

@ -28,7 +28,6 @@ class WaterHeaterInitial extends WaterHeaterEvent {
class WaterHeaterChangeStatus extends WaterHeaterEvent {}
class GetCounterEvent extends WaterHeaterEvent {
final String deviceCode;
const GetCounterEvent({required this.deviceCode});
@ -66,10 +65,11 @@ class StopTimer extends WaterHeaterEvent {}
class OnClose extends WaterHeaterEvent {}
//------------------- Schedule ----------=---------
class GetScheduleEvent extends WaterHeaterEvent {}
class ScheduleSave extends WaterHeaterEvent {}
class ToggleScheduleEvent extends WaterHeaterEvent {
final String id;
final bool toggle;
@ -77,14 +77,15 @@ class ToggleScheduleEvent extends WaterHeaterEvent {
@override
List<Object> get props => [toggle, id];
}
class ToggleDaySelectionEvent extends WaterHeaterEvent {
class ToggleDaySelectionEvent extends WaterHeaterEvent {
final String key;
const ToggleDaySelectionEvent({required this.key});
@override
List<Object> get props => [key];
}
class DeleteScheduleEvent extends WaterHeaterEvent {
final String id;
const DeleteScheduleEvent({required this.id});
@ -100,7 +101,6 @@ class SelectTimeEvent extends WaterHeaterEvent {
List<Object> get props => [context, isEffective];
}
class ToggleSelectedEvent extends WaterHeaterEvent {
final int index;
const ToggleSelectedEvent({required this.index});
@ -108,7 +108,6 @@ class ToggleSelectedEvent extends WaterHeaterEvent {
List<Object> get props => [index];
}
class ToggleCreateScheduleEvent extends WaterHeaterEvent {
final int index;
const ToggleCreateScheduleEvent({required this.index});
@ -116,10 +115,25 @@ class ToggleCreateScheduleEvent extends WaterHeaterEvent {
List<Object> get props => [index];
}
class ToggleCreateCirculateEvent extends WaterHeaterEvent {
final int index;
const ToggleCreateCirculateEvent({required this.index});
@override
List<Object> get props => [index];
}
class InitialWizardEvent extends WaterHeaterEvent {}
class ChangeFirstWizardSwitchStatusEvent extends WaterHeaterEvent {
final bool value;
final String deviceId;
const ChangeFirstWizardSwitchStatusEvent({required this.value, this.deviceId = ''});
@override
List<Object> get props => [value, deviceId];
}
class GroupAllOnEvent extends WaterHeaterEvent {}
class GroupAllOffEvent extends WaterHeaterEvent {}
class ToggleCreateCirculate extends WaterHeaterEvent {}

View File

@ -1,4 +1,5 @@
import 'package:equatable/equatable.dart';
import 'package:syncrow_app/features/devices/model/GroupWHModel.dart';
import 'package:syncrow_app/features/devices/model/water_heater.dart';
abstract class WaterHeaterState extends Equatable {
@ -13,13 +14,8 @@ class WHInitialState extends WaterHeaterState {}
class WHLoadingState extends WaterHeaterState {}
class WHChangeLoading extends WaterHeaterState {
// final WHStatusModel WHStatusModel;
const WHChangeLoading(
// {required this. WHStatusModel}
);
// @override
// List<Object> get props => [acStatusModel];
}
class WHModifyingState extends WaterHeaterState {
@ -111,3 +107,16 @@ class ChangeSlidingSegmentState extends WaterHeaterState {
@override
List<Object> get props => [value];
}
class UpdateGroupState extends WaterHeaterState {
final List<GroupWHModel> twoGangList;
final bool allSwitches;
const UpdateGroupState({required this.twoGangList, required this.allSwitches});
@override
List<Object> get props => [twoGangList, allSwitches];
}

View File

@ -0,0 +1,11 @@
class GroupWHModel {
final String deviceId;
final String deviceName;
bool firstSwitch;
GroupWHModel({
required this.deviceId,
required this.deviceName,
required this.firstSwitch,
});
}

View File

@ -8,7 +8,8 @@ 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});
const OneGangList(
{super.key, required this.oneGangList, required this.allSwitches});
final List<GroupOneGangModel> oneGangList;
final bool allSwitches;
@ -48,7 +49,8 @@ class OneGangList extends StatelessWidget {
DevicesDefaultSwitch(
switchValue: oneGangList[index].firstSwitch,
action: () {
BlocProvider.of<OneGangBloc>(context).add(ChangeFirstSwitchStatusEvent(
BlocProvider.of<OneGangBloc>(context).add(
ChangeFirstWizardSwitchStatusEvent(
value: oneGangList[index].firstSwitch,
deviceId: oneGangList[index].deviceId));
},

View File

@ -3,9 +3,7 @@ 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';
@ -22,8 +20,7 @@ class OneGangScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) =>
OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '')
create: (context) => OneGangBloc(switchCode: 'switch_1', oneGangId: device?.uuid ?? '')
..add(const InitialEvent(groupScreen: false)),
child: BlocBuilder<OneGangBloc, OneGangState>(
builder: (context, state) {
@ -32,32 +29,20 @@ class OneGangScreen extends StatelessWidget {
firstCountDown: 0,
);
List<GroupOneGangModel> 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()),
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: device == null
? OneGangList(
oneGangList: groupOneGangModel,
allSwitches: allSwitchesOn)
: RefreshIndicator(
onRefresh: () async {
BlocProvider.of<OneGangBloc>(context).add(InitialEvent(
groupScreen: device != null ? false : true));
BlocProvider.of<OneGangBloc>(context)
.add(InitialEvent(groupScreen: device != null ? false : true));
},
child: ListView(
children: [
@ -70,10 +55,8 @@ class OneGangScreen extends StatelessWidget {
const Expanded(child: SizedBox.shrink()),
Expanded(
child: Row(
mainAxisAlignment:
MainAxisAlignment.spaceAround,
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.spaceAround,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
children: [
@ -81,12 +64,9 @@ class OneGangScreen extends StatelessWidget {
threeGangSwitch: device!,
value: oneGangModel.firstSwitch,
action: () {
BlocProvider.of<OneGangBloc>(
context)
.add(
BlocProvider.of<OneGangBloc>(context).add(
ChangeFirstSwitchStatusEvent(
value: oneGangModel
.firstSwitch));
value: oneGangModel.firstSwitch));
},
),
const SizedBox(height: 20),
@ -94,8 +74,7 @@ class OneGangScreen extends StatelessWidget {
width: 70,
child: BodySmall(
text: " Entrance Light",
fontColor: ColorsManager
.textPrimaryColor,
fontColor: ColorsManager.textPrimaryColor,
textAlign: TextAlign.center,
),
),
@ -107,8 +86,7 @@ class OneGangScreen extends StatelessWidget {
Center(
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment:
CrossAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Column(
mainAxisSize: MainAxisSize.min,
@ -116,23 +94,19 @@ class OneGangScreen extends StatelessWidget {
Card(
elevation: 3,
shape: RoundedRectangleBorder(
borderRadius:
BorderRadius.circular(100),
borderRadius: BorderRadius.circular(100),
),
child: GestureDetector(
onTap: () {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context,
animation1,
animation2) =>
pageBuilder:
(context, animation1, animation2) =>
TimerScheduleScreen(
switchCode:
'switch_1',
switchCode: 'switch_1',
device: device!,
deviceCode:
'countdown_1',
deviceCode: 'countdown_1',
)));
},
child: Stack(
@ -143,9 +117,7 @@ class OneGangScreen extends StatelessWidget {
height: 60,
decoration: BoxDecoration(
color: Colors.grey[300],
borderRadius:
BorderRadius.circular(
100),
borderRadius: BorderRadius.circular(100),
),
),
Container(
@ -153,15 +125,12 @@ class OneGangScreen extends StatelessWidget {
height: 40,
decoration: BoxDecoration(
color: Colors.white,
borderRadius:
BorderRadius.circular(
100),
borderRadius: BorderRadius.circular(100),
),
child: Center(
child: Icon(
Icons.access_time,
color: ColorsManager
.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
size: 25,
),
),
@ -174,8 +143,7 @@ class OneGangScreen extends StatelessWidget {
BodySmall(
text: "Timer",
style: context.bodyMedium.copyWith(
color: ColorsManager
.textPrimaryColor,
color: ColorsManager.textPrimaryColor,
),
),
],

View File

@ -0,0 +1,46 @@
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/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_one_gang_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/one_gang/one_gang_list.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
class OneGangWizard extends StatelessWidget {
const OneGangWizard({super.key, this.device});
final DeviceModel? device;
@override
Widget build(BuildContext context) {
List<GroupOneGangModel> groupOneGangModel = [];
return DefaultScaffold(
child: BlocProvider(
create: (context) =>
OneGangBloc(switchCode: '', oneGangId: device?.uuid ?? '')..add(InitialWizardEvent()),
child: BlocBuilder<OneGangBloc, OneGangState>(
builder: (context, state) {
bool allSwitchesOn = false;
if (state is UpdateGroupState) {
groupOneGangModel = state.oneGangList;
allSwitchesOn = state.allSwitches;
}
return state is LoadingInitialState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: OneGangList(
oneGangList: groupOneGangModel,
allSwitches: allSwitchesOn,
);
},
),
));
}
}

View File

@ -4,11 +4,9 @@ import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_blo
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_event.dart';
import 'package:syncrow_app/features/devices/bloc/three_gang_bloc/three_gang_state.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
import 'package:syncrow_app/features/devices/model/three_gang_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/gang_switch.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/schedule_screen.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_list.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
import 'package:syncrow_app/utils/context_extension.dart';
@ -22,9 +20,7 @@ class ThreeGangScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => ThreeGangBloc(
switchCode: '',
threeGangId: device?.uuid ?? '')
create: (context) => ThreeGangBloc(switchCode: '', threeGangId: device?.uuid ?? '')
..add(InitialEvent(groupScreen: device != null ? false : true)),
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
builder: (context, state) {
@ -36,27 +32,16 @@ class ThreeGangScreen extends StatelessWidget {
secondCountDown: 0,
thirdCountDown: 0);
List<GroupThreeGangModel> groupThreeGangModel = [];
bool allSwitchesOn = false;
if (state is LoadingNewSate) {
threeGangModel = state.threeGangModel;
} else if (state is UpdateState) {
threeGangModel = state.threeGangModel;
} else if (state is UpdateGroupState) {
groupThreeGangModel = state.threeGangList;
allSwitchesOn = state.allSwitches;
}
return state is LoadingInitialState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: device == null
? ThreeGangList(
threeGangList: groupThreeGangModel,
allSwitches: allSwitchesOn,
)
: RefreshIndicator(
onRefresh: () async {
BlocProvider.of<ThreeGangBloc>(context)
@ -224,8 +209,8 @@ class ThreeGangScreen extends StatelessWidget {
child: BodySmall(
text: "On",
style: context.bodyMedium.copyWith(
color: ColorsManager
.primaryColorWithOpacity,
color:
ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
@ -286,8 +271,7 @@ class ThreeGangScreen extends StatelessWidget {
child: Center(
child: Icon(
Icons.access_time,
color:
ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
size: 25,
),
),
@ -367,8 +351,8 @@ class ThreeGangScreen extends StatelessWidget {
child: BodySmall(
text: "Off",
style: context.bodyMedium.copyWith(
color: ColorsManager
.primaryColorWithOpacity,
color:
ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),

View File

@ -0,0 +1,45 @@
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/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_three_gang_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_list.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
class ThreeGangWizard extends StatelessWidget {
const ThreeGangWizard({super.key, this.device});
final DeviceModel? device;
@override
Widget build(BuildContext context) {
return DefaultScaffold(
child: BlocProvider(
create: (context) => ThreeGangBloc(switchCode: '', threeGangId: device?.uuid ?? '')
..add(InitialEvent(groupScreen: device != null ? false : true)),
child: BlocBuilder<ThreeGangBloc, ThreeGangState>(
builder: (context, state) {
List<GroupThreeGangModel> groupThreeGangModel = [];
bool allSwitchesOn = false;
if (state is UpdateGroupState) {
groupThreeGangModel = state.threeGangList;
allSwitchesOn = state.allSwitches;
}
return state is LoadingInitialState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: ThreeGangList(
threeGangList: groupThreeGangModel,
allSwitches: allSwitchesOn,
);
},
),
));
}
}

View File

@ -8,7 +8,8 @@ import 'package:syncrow_app/features/shared_widgets/devices_default_switch.dart'
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
class TwoGangList extends StatelessWidget {
const TwoGangList({super.key, required this.twoGangList, required this.allSwitches});
const TwoGangList(
{super.key, required this.twoGangList, required this.allSwitches});
final List<GroupTwoGangModel> twoGangList;
final bool allSwitches;
@ -48,7 +49,8 @@ class TwoGangList extends StatelessWidget {
DevicesDefaultSwitch(
switchValue: twoGangList[index].firstSwitch,
action: () {
BlocProvider.of<TwoGangBloc>(context).add(ChangeFirstSwitchStatusEvent(
BlocProvider.of<TwoGangBloc>(context).add(
ChangeFirstWizardSwitchStatusEvent(
value: twoGangList[index].firstSwitch,
deviceId: twoGangList[index].deviceId));
},
@ -59,7 +61,8 @@ class TwoGangList extends StatelessWidget {
DevicesDefaultSwitch(
switchValue: twoGangList[index].secondSwitch,
action: () {
BlocProvider.of<TwoGangBloc>(context).add(ChangeSecondSwitchStatusEvent(
BlocProvider.of<TwoGangBloc>(context).add(
ChangeSecondWizardSwitchStatusEvent(
value: twoGangList[index].secondSwitch,
deviceId: twoGangList[index].deviceId));
},

View File

@ -4,10 +4,8 @@ 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/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';
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_schedule_screen.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
@ -23,7 +21,7 @@ class TwoGangScreen extends StatelessWidget {
Widget build(BuildContext context) {
return BlocProvider(
create: (context) => TwoGangBloc(switchCode: switchCode ?? '', twoGangId: device?.uuid ?? '')
..add(InitialEvent(groupScreen: device != null ? false : true)),
..add(const InitialEvent()),
child: BlocBuilder<TwoGangBloc, TwoGangState>(
builder: (context, state) {
TwoGangModel twoGangModel = TwoGangModel(
@ -33,30 +31,20 @@ class TwoGangScreen extends StatelessWidget {
secondCountDown: 0,
);
List<GroupTwoGangModel> groupTwoGangModel = [];
bool allSwitchesOn = false;
if (state is LoadingNewSate) {
twoGangModel = state.twoGangModel;
} else if (state is UpdateState) {
twoGangModel = state.twoGangModel;
} else if (state is UpdateGroupState) {
groupTwoGangModel = state.twoGangList;
allSwitchesOn = state.allSwitches;
}
return state is LoadingInitialState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: device == null
? TwoGangList(
twoGangList: groupTwoGangModel,
allSwitches: allSwitchesOn,
)
: RefreshIndicator(
onRefresh: () async {
BlocProvider.of<TwoGangBloc>(context)
.add(InitialEvent(groupScreen: device != null ? false : true));
BlocProvider.of<TwoGangBloc>(context).add(const InitialEvent());
},
child: ListView(
children: [
@ -134,8 +122,7 @@ class TwoGangScreen extends StatelessWidget {
),
child: GestureDetector(
onTap: () {
BlocProvider.of<TwoGangBloc>(context)
.add(AllOnEvent());
BlocProvider.of<TwoGangBloc>(context).add(AllOnEvent());
},
child: Stack(
alignment: Alignment.center,
@ -159,8 +146,8 @@ class TwoGangScreen extends StatelessWidget {
child: BodySmall(
text: "On",
style: context.bodyMedium.copyWith(
color: ColorsManager
.primaryColorWithOpacity,
color:
ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),
@ -221,8 +208,7 @@ class TwoGangScreen extends StatelessWidget {
child: Center(
child: Icon(
Icons.access_time,
color:
ColorsManager.primaryColorWithOpacity,
color: ColorsManager.primaryColorWithOpacity,
size: 25,
),
),
@ -302,8 +288,8 @@ class TwoGangScreen extends StatelessWidget {
child: BodySmall(
text: "Off",
style: context.bodyMedium.copyWith(
color: ColorsManager
.primaryColorWithOpacity,
color:
ColorsManager.primaryColorWithOpacity,
fontWeight: FontWeight.bold),
),
),

View File

@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.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/device_model.dart';
import 'package:syncrow_app/features/devices/model/group_two_gang_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_list.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
class TwoGangWizard extends StatelessWidget {
const TwoGangWizard({super.key, this.device});
final DeviceModel? device;
@override
Widget build(BuildContext context) {
List<GroupTwoGangModel> groupTwoGangModel = [];
return DefaultScaffold(
child: BlocProvider(
create: (context) =>
TwoGangBloc(switchCode: '', twoGangId: device?.uuid ?? '')..add(InitialWizardEvent()),
child: BlocBuilder<TwoGangBloc, TwoGangState>(
builder: (context, state) {
bool allSwitchesOn = false;
if (state is UpdateGroupState) {
groupTwoGangModel = state.twoGangList;
allSwitchesOn = state.allSwitches;
}
return state is LoadingInitialState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: TwoGangList(
twoGangList: groupTwoGangModel,
allSwitches: allSwitchesOn,
);
},
),
));
}
}

View File

@ -0,0 +1,69 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/water_heater_bloc/water_heater_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/water_heater_bloc/water_heater_event.dart';
import 'package:syncrow_app/features/devices/bloc/water_heater_bloc/water_heater_state.dart';
import 'package:syncrow_app/features/devices/model/GroupWHModel.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 WHList extends StatelessWidget {
const WHList({super.key, required this.whList, required this.allSwitches});
final List<GroupWHModel> whList;
final bool allSwitches;
@override
Widget build(BuildContext context) {
return BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
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<WaterHeaterBloc>(context)
.add(GroupAllOnEvent());
},
secondAction: () {
BlocProvider.of<WaterHeaterBloc>(context)
.add(GroupAllOffEvent());
},
),
ListView.builder(
shrinkWrap: true,
physics: const NeverScrollableScrollPhysics(),
padding: const EdgeInsets.all(0),
itemCount: whList.length,
itemBuilder: (context, index) {
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 10),
BodySmall(text: whList[index].deviceName),
const SizedBox(height: 5),
DevicesDefaultSwitch(
switchValue: whList[index].firstSwitch,
action: () {
BlocProvider.of<WaterHeaterBloc>(context).add(
ChangeFirstWizardSwitchStatusEvent(
value: whList[index].firstSwitch,
deviceId: whList[index].deviceId));
},
),
],
);
},
),
],
),
);
},
);
}
}

View File

@ -25,10 +25,7 @@ class WHTimerScheduleScreen extends StatelessWidget {
final String deviceCode;
final String switchCode;
const WHTimerScheduleScreen(
{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 +35,7 @@ class WHTimerScheduleScreen extends StatelessWidget {
statusBarIconBrightness: Brightness.light,
),
child: BlocProvider(
create: (context) =>
WaterHeaterBloc(switchCode: switchCode, whId: device.uuid ?? '')
create: (context) => WaterHeaterBloc(switchCode: switchCode, whId: device.uuid ?? '')
..add(GetCounterEvent(deviceCode: deviceCode))
..add(GetScheduleEvent()),
child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
@ -87,9 +83,8 @@ class WHTimerScheduleScreen extends StatelessWidget {
? IconButton(
onPressed: () {
// waterHeaterBloc.toggleCreateSchedule();
waterHeaterBloc.add(
const ToggleCreateScheduleEvent(
index: 1));
waterHeaterBloc
.add(const ToggleCreateScheduleEvent(index: 1));
},
icon: const Icon(Icons.add),
)
@ -104,7 +99,7 @@ class WHTimerScheduleScreen extends StatelessWidget {
: waterHeaterBloc.selectedTabIndex == 2
? IconButton(
onPressed: () {
waterHeaterBloc.toggleCreateCirculate();
waterHeaterBloc.add(ToggleCreateCirculate());
},
icon: const Icon(Icons.add),
)
@ -120,8 +115,7 @@ class WHTimerScheduleScreen extends StatelessWidget {
decoration: const ShapeDecoration(
color: ColorsManager.onPrimaryColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(30)),
borderRadius: BorderRadius.all(Radius.circular(30)),
),
),
child: TabBar(
@ -130,49 +124,34 @@ class WHTimerScheduleScreen extends StatelessWidget {
labelPadding: EdgeInsets.zero,
onTap: (value) {
if (value == 0) {
if (waterHeaterBloc.createSchedule ==
true) {
if (waterHeaterBloc.createSchedule == true) {
// waterHeaterBloc
// .toggleCreateSchedule();
waterHeaterBloc.add(
const ToggleCreateScheduleEvent(
index: 1));
waterHeaterBloc
.add(const ToggleCreateScheduleEvent(index: 1));
}
waterHeaterBloc.add(
ToggleSelectedEvent(
index: value));
waterHeaterBloc.add(ToggleSelectedEvent(index: value));
// waterHeaterBloc
// .toggleSelectedIndex(value);
} else if (value == 2) {
if (waterHeaterBloc.createCirculate ==
true) {
waterHeaterBloc.add(
ToggleCreateCirculateEvent(
index: value));
if (waterHeaterBloc.createCirculate == true) {
waterHeaterBloc
.add(ToggleCreateCirculateEvent(index: value));
// waterHeaterBloc
// .toggleCreateCirculate();
}
waterHeaterBloc.add(
ToggleSelectedEvent(
index: value));
waterHeaterBloc.add(ToggleSelectedEvent(index: value));
// waterHeaterBloc
// .toggleSelectedIndex(value);
} else {
if (waterHeaterBloc.createSchedule ==
true) {
waterHeaterBloc.add(
ToggleSelectedEvent(
index: value));
if (waterHeaterBloc.createSchedule == true) {
waterHeaterBloc.add(ToggleSelectedEvent(index: value));
// waterHeaterBloc
// .toggleCreateSchedule();
}
waterHeaterBloc.createCirculate =
false;
waterHeaterBloc.createSchedule =
false;
waterHeaterBloc.add(
ToggleSelectedEvent(
index: value));
waterHeaterBloc.createCirculate = false;
waterHeaterBloc.createSchedule = false;
waterHeaterBloc.add(ToggleSelectedEvent(index: value));
// waterHeaterBloc
// .toggleSelectedIndex(value);
}
@ -183,39 +162,31 @@ class WHTimerScheduleScreen extends StatelessWidget {
indicator: const ShapeDecoration(
color: ColorsManager.slidingBlueColor,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(20)),
borderRadius: BorderRadius.all(Radius.circular(20)),
),
),
isScrollable: false,
labelColor: Colors
.white, // Text color when selected
unselectedLabelColor: ColorsManager
.blackColor, // Text color when not selected
labelColor: Colors.white, // Text color when selected
unselectedLabelColor:
ColorsManager.blackColor, // Text color when not selected
tabs: [
Tab(
icon: Padding(
padding: const EdgeInsets.only(
top: 10.0),
padding: const EdgeInsets.only(top: 10.0),
child: SvgPicture.asset(
Assets.scheduleTimeIcon,
color: waterHeaterBloc
.selectedTabIndex ==
0
color: waterHeaterBloc.selectedTabIndex == 0
? Colors.white
: ColorsManager
.blackColor, // Change icon color based on selectedIndex
),
),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 5),
padding: const EdgeInsets.symmetric(vertical: 5),
child: BodySmall(
text: 'Countdown',
style: context.bodySmall.copyWith(
color: waterHeaterBloc
.selectedTabIndex ==
0
color: waterHeaterBloc.selectedTabIndex == 0
? Colors.white
: ColorsManager
.blackColor, // Text color based on selectedTabIndex
@ -227,26 +198,20 @@ class WHTimerScheduleScreen extends StatelessWidget {
),
Tab(
icon: Padding(
padding:
const EdgeInsets.only(top: 10),
padding: const EdgeInsets.only(top: 10),
child: SvgPicture.asset(
Assets.scheduleCelenderIcon,
color: waterHeaterBloc
.selectedTabIndex ==
1
color: waterHeaterBloc.selectedTabIndex == 1
? Colors.white
: ColorsManager.blackColor,
),
),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 5),
padding: const EdgeInsets.symmetric(vertical: 5),
child: Text(
'Schedule',
style: context.bodySmall.copyWith(
color: waterHeaterBloc
.selectedTabIndex ==
1
color: waterHeaterBloc.selectedTabIndex == 1
? Colors.white
: ColorsManager.blackColor,
fontSize: 12,
@ -257,26 +222,20 @@ class WHTimerScheduleScreen extends StatelessWidget {
),
Tab(
icon: Padding(
padding:
const EdgeInsets.only(top: 10),
padding: const EdgeInsets.only(top: 10),
child: SvgPicture.asset(
Assets.scheduleCirculateIcon,
color: waterHeaterBloc
.selectedTabIndex ==
2
color: waterHeaterBloc.selectedTabIndex == 2
? Colors.white
: ColorsManager.blackColor,
),
),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 5),
padding: const EdgeInsets.symmetric(vertical: 5),
child: Text(
'Circulate',
style: context.bodySmall.copyWith(
color: waterHeaterBloc
.selectedTabIndex ==
2
color: waterHeaterBloc.selectedTabIndex == 2
? Colors.white
: ColorsManager.blackColor,
fontSize: 12,
@ -287,26 +246,20 @@ class WHTimerScheduleScreen extends StatelessWidget {
),
Tab(
icon: Padding(
padding:
const EdgeInsets.only(top: 10),
padding: const EdgeInsets.only(top: 10),
child: SvgPicture.asset(
Assets.scheduleInchingIcon,
color: waterHeaterBloc
.selectedTabIndex ==
3
color: waterHeaterBloc.selectedTabIndex == 3
? Colors.white
: ColorsManager.blackColor,
),
),
child: Container(
padding: const EdgeInsets.symmetric(
vertical: 5),
padding: const EdgeInsets.symmetric(vertical: 5),
child: Text(
'Inching',
style: context.bodySmall.copyWith(
color: waterHeaterBloc
.selectedTabIndex ==
3
color: waterHeaterBloc.selectedTabIndex == 3
? Colors.white
: ColorsManager.blackColor,
fontSize: 12,
@ -325,52 +278,37 @@ class WHTimerScheduleScreen extends StatelessWidget {
Center(
child: Container(
child: Column(
mainAxisAlignment:
MainAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
countNum > 0
? BodyLarge(
text: _formatDuration(
countNum),
fontColor: ColorsManager
.slidingBlueColor,
text: _formatDuration(countNum),
fontColor: ColorsManager.slidingBlueColor,
fontSize: 40,
)
: CupertinoTimerPicker(
mode:
CupertinoTimerPickerMode
.hm,
mode: CupertinoTimerPickerMode.hm,
onTimerDurationChanged:
(Duration
newDuration) {
(Duration newDuration) {
duration = newDuration;
},
),
GestureDetector(
onTap: () {
if (state
is LoadingNewSate) {
if (state is LoadingNewSate) {
return;
}
if (countNum > 0) {
waterHeaterBloc.add(
SetCounterValue(
deviceCode:
deviceCode,
duration: Duration
.zero));
} else if (duration !=
Duration.zero) {
waterHeaterBloc.add(
SetCounterValue(
deviceCode:
deviceCode,
duration:
duration));
waterHeaterBloc.add(SetCounterValue(
deviceCode: deviceCode,
duration: Duration.zero));
} else if (duration != Duration.zero) {
waterHeaterBloc.add(SetCounterValue(
deviceCode: deviceCode,
duration: duration));
}
},
child: SvgPicture.asset(
countNum > 0
child: SvgPicture.asset(countNum > 0
? Assets.pauseIcon
: Assets.playIcon)),
],
@ -378,53 +316,37 @@ class WHTimerScheduleScreen extends StatelessWidget {
),
),
SizedBox(
child: waterHeaterBloc.createSchedule ==
true
child: waterHeaterBloc.createSchedule == true
? CreateSchedule(
onToggleChanged: (bool isOn) {
waterHeaterBloc
.toggleSchedule = isOn;
waterHeaterBloc.toggleSchedule = isOn;
},
onDateTimeChanged:
(DateTime dateTime) {
waterHeaterBloc.selectedTime =
dateTime;
onDateTimeChanged: (DateTime dateTime) {
waterHeaterBloc.selectedTime = dateTime;
},
days: waterHeaterBloc.days,
selectDays: (List<String>
selectedDays) {
waterHeaterBloc.selectedDays =
selectedDays;
selectDays: (List<String> selectedDays) {
waterHeaterBloc.selectedDays = selectedDays;
},
)
: Padding(
padding: const EdgeInsets.only(
top: 10),
padding: const EdgeInsets.only(top: 10),
child: Column(
children: [
Expanded(
child: ScheduleListView(
listSchedule:
waterHeaterBloc
listSchedule: waterHeaterBloc
.listSchedule, // Pass the schedule list here
onDismissed:
(scheduleId) {
waterHeaterBloc
.listSchedule
.removeWhere(
onDismissed: (scheduleId) {
waterHeaterBloc.listSchedule.removeWhere(
(schedule) =>
schedule
.scheduleId ==
schedule.scheduleId ==
scheduleId);
waterHeaterBloc.add(
DeleteScheduleEvent(
id: scheduleId));
DeleteScheduleEvent(id: scheduleId));
},
onToggleSchedule:
(scheduleId,
isEnabled) {
waterHeaterBloc.add(
ToggleScheduleEvent(
onToggleSchedule: (scheduleId, isEnabled) {
waterHeaterBloc.add(ToggleScheduleEvent(
id: scheduleId,
toggle: isEnabled,
));
@ -437,56 +359,39 @@ class WHTimerScheduleScreen extends StatelessWidget {
),
Center(
child: Column(
crossAxisAlignment:
CrossAxisAlignment.center,
mainAxisAlignment:
MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
waterHeaterBloc.createCirculate ==
true
waterHeaterBloc.createCirculate == true
? CirculateWidget(
endDuration: () {
waterHeaterBloc.add(
SelectTimeEvent(
context: context,
isEffective:
false));
waterHeaterBloc.add(SelectTimeEvent(
context: context, isEffective: false));
},
startDuration: () {
waterHeaterBloc.add(
SelectTimeEvent(
context: context,
isEffective:
false));
waterHeaterBloc.add(SelectTimeEvent(
context: context, isEffective: false));
},
isStartEndTime: true,
startTime: DateTime.now(),
endTime: DateTime.now(),
days: waterHeaterBloc.days,
selectedDays: [],
onToggleStartEndTime:
(c) {},
onToggleStartEndTime: (c) {},
onTimeChanged: (x, f) {},
onDaySelected: (p0) {},
)
: CirculateListView(
listSchedule: [], // Pass the schedule list here
onDismissed: (scheduleId) {
waterHeaterBloc.listSchedule.removeWhere(
(schedule) =>
schedule.scheduleId == scheduleId);
waterHeaterBloc
.listSchedule
.removeWhere((schedule) =>
schedule
.scheduleId ==
scheduleId);
waterHeaterBloc.add(
DeleteScheduleEvent(
id: scheduleId));
.add(DeleteScheduleEvent(id: scheduleId));
},
onToggleSchedule:
(scheduleId,
isEnabled) {
waterHeaterBloc.add(
ToggleScheduleEvent(
onToggleSchedule: (scheduleId, isEnabled) {
waterHeaterBloc.add(ToggleScheduleEvent(
id: scheduleId,
toggle: isEnabled,
));

View File

@ -0,0 +1,46 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/water_heater_bloc/water_heater_bloc.dart';
import 'package:syncrow_app/features/devices/bloc/water_heater_bloc/water_heater_event.dart';
import 'package:syncrow_app/features/devices/bloc/water_heater_bloc/water_heater_state.dart';
import 'package:syncrow_app/features/devices/model/GroupWHModel.dart';
import 'package:syncrow_app/features/devices/model/device_model.dart';
import 'package:syncrow_app/features/devices/view/widgets/water_heater/wh_list.dart';
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
import 'package:syncrow_app/features/shared_widgets/default_scaffold.dart';
class WHWizard extends StatelessWidget {
const WHWizard({super.key, this.device});
final DeviceModel? device;
@override
Widget build(BuildContext context) {
List<GroupWHModel> groupModel = [];
return DefaultScaffold(
child: BlocProvider(
create: (context) =>
WaterHeaterBloc(switchCode: '', whId: device?.uuid ?? '')..add(InitialWizardEvent()),
child: BlocBuilder<WaterHeaterBloc, WaterHeaterState>(
builder: (context, state) {
bool allSwitchesOn = false;
if (state is UpdateGroupState) {
groupModel = state.twoGangList;
allSwitchesOn = state.allSwitches;
}
return state is WHLoadingState
? const Center(
child:
DefaultContainer(width: 50, height: 50, child: CircularProgressIndicator()),
)
: WHList(
whList: groupModel,
allSwitches: allSwitchesOn,
);
},
),
));
}
}

View File

@ -2,9 +2,10 @@ 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/devices/view/widgets/one_gang/one_gang_wizard.dart';
import 'package:syncrow_app/features/devices/view/widgets/three_gang/three_gang_wizard.dart';
import 'package:syncrow_app/features/devices/view/widgets/two_gang/two_gang_wizard.dart';
import 'package:syncrow_app/features/devices/view/widgets/water_heater/wh_wizard.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';
@ -32,26 +33,36 @@ class WizardPage extends StatelessWidget {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => const ACsView()));
pageBuilder: (context, animation1, animation2) =>
const ACsView()));
}
if (groupsList[index].name == '3G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const ThreeGangInterface()));
const ThreeGangWizard()));
}
if (groupsList[index].name == '2G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => const TwoGangInterface()));
pageBuilder: (context, animation1, animation2) =>
const TwoGangWizard()));
}
if (groupsList[index].name == '1G') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) => const OneGangInterface()));
pageBuilder: (context, animation1, animation2) =>
const OneGangWizard()));
}
if (groupsList[index].name == 'WH') {
Navigator.push(
context,
PageRouteBuilder(
pageBuilder: (context, animation1, animation2) =>
const WHWizard()));
}
},
child: DefaultContainer(

View File

@ -81,8 +81,7 @@ abstract class ApiEndpoints {
static const String controlGroup = '/group/control';
//GET
static const String groupBySpace = '/group/{unitUuid}';
static const String devicesByGroupName =
'/group/{unitUuid}/devices/{groupName}';
static const String devicesByGroupName = '/group/{unitUuid}/devices/{groupName}';
static const String groupByUuid = '/group/{groupUuid}';
//DELETE
@ -94,8 +93,7 @@ abstract class ApiEndpoints {
static const String addDeviceToRoom = '/device/room';
static const String addDeviceToGroup = '/device/group';
static const String controlDevice = '/device/{deviceUuid}/control';
static const String firmwareDevice =
'/device/{deviceUuid}/firmware/{firmwareVersion}';
static const String firmwareDevice = '/device/{deviceUuid}/firmware/{firmwareVersion}';
static const String getDevicesByUserId = '/device/user/{userId}';
static const String getDevicesByUnitId = '/device/unit/{unitUuid}';
static const String openDoorLock = '/door-lock/open/{doorLockUuid}';
@ -105,8 +103,7 @@ abstract class ApiEndpoints {
static const String deviceByUuid = '/device/{deviceUuid}';
static const String deviceFunctions = '/device/{deviceUuid}/functions';
static const String gatewayApi = '/device/gateway/{gatewayUuid}/devices';
static const String deviceFunctionsStatus =
'/device/{deviceUuid}/functions/status';
static const String deviceFunctionsStatus = '/device/{deviceUuid}/functions/status';
///Device Permission Module
//POST
@ -131,29 +128,24 @@ abstract class ApiEndpoints {
static const String getUnitAutomation = '/automation/{unitUuid}';
static const String getAutomationDetails =
'/automation/details/{automationId}';
static const String getAutomationDetails = '/automation/details/{automationId}';
/// PUT
static const String updateScene = '/scene/tap-to-run/{sceneId}';
static const String updateAutomation = '/automation/{automationId}';
static const String updateAutomationStatus =
'/automation/status/{automationId}';
static const String updateAutomationStatus = '/automation/status/{automationId}';
/// DELETE
static const String deleteScene = '/scene/tap-to-run/{unitUuid}/{sceneId}';
static const String deleteAutomation =
'/automation/{unitUuid}/{automationId}';
static const String deleteAutomation = '/automation/{unitUuid}/{automationId}';
//////////////////////Door Lock //////////////////////
//online
static const String addTemporaryPassword =
'/door-lock/temporary-password/online/{doorLockUuid}';
static const String getTemporaryPassword =
'/door-lock/temporary-password/online/{doorLockUuid}';
static const String addTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
static const String getTemporaryPassword = '/door-lock/temporary-password/online/{doorLockUuid}';
//one-time offline
static const String addOneTimeTemporaryPassword =
@ -185,9 +177,11 @@ abstract class ApiEndpoints {
'/door-lock/temporary-password/online/{doorLockUuid}/{passwordId}';
static const String saveSchedule = '/schedule/{deviceUuid}';
static const String getSchedule =
'/schedule/{deviceUuid}?category={category}';
static const String getSchedule = '/schedule/{deviceUuid}?category={category}';
static const String changeSchedule = '/schedule/enable/{deviceUuid}';
static const String deleteSchedule = '/schedule/{deviceUuid}/{scheduleId}';
static const String reportLogs = '/device/report-logs/{deviceUuid}?code={code}&startTime={startTime}&endTime={endTime}';
static const String reportLogs =
'/device/report-logs/{deviceUuid}?code={code}&startTime={startTime}&endTime={endTime}';
static const String controlBatch = '/device/control/batch';
static const String statusBatch = '/device/status/batch';
}

View File

@ -72,8 +72,7 @@ class DevicesAPI {
static Future<Map<String, dynamic>> 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<Map<String, dynamic>> 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<List<DeviceModel>> getDeviceByGroupName(
String unitId, String groupName) async {
static Future<List<DeviceModel>> 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<List<DeviceModel>> getDevicesByGatewayId(
String gatewayId) async {
static Future<List<DeviceModel>> 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) {
@ -378,4 +365,34 @@ class DevicesAPI {
return response;
}
static Future deviceBatchController({
List<String>? devicesUuid,
String? code,
bool? value,
}) async {
final response = await _httpService.post(
path: ApiEndpoints.controlBatch,
body: {"devicesUuid": devicesUuid, "code": code, "value": value},
showServerMessage: true,
expectedResponseModel: (json) {
return json;
},
);
return response;
}
static Future deviceBatchStatus({
List<String>? devicesUuid,
}) async {
final response = await _httpService.get(
path: ApiEndpoints.statusBatch,
queryParameters: {"devicesUuid": devicesUuid},
showServerMessage: false,
expectedResponseModel: (json) {
return json;
},
);
return response;
}
}