mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 07:07:19 +00:00
fix oct/8 issues
This commit is contained in:
@ -15,6 +15,9 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
||||
List<AllDevicesModel> _selectedDevices = [];
|
||||
List<AllDevicesModel> _filteredDevices = [];
|
||||
String productName = '';
|
||||
String? currentCommunity;
|
||||
String? currentUnitName;
|
||||
String? currentProductName;
|
||||
|
||||
DeviceManagementBloc() : super(DeviceManagementInitial()) {
|
||||
on<FetchDevices>(_onFetchDevices);
|
||||
@ -234,6 +237,16 @@ class DeviceManagementBloc extends Bloc<DeviceManagementEvent, DeviceManagementS
|
||||
}
|
||||
|
||||
void _onSearchDevices(SearchDevices event, Emitter<DeviceManagementState> emit) {
|
||||
if (event.productName == currentProductName &&
|
||||
event.community == currentCommunity &&
|
||||
event.unitName == currentUnitName) {
|
||||
return;
|
||||
}
|
||||
|
||||
currentProductName = event.productName;
|
||||
currentCommunity = event.community;
|
||||
currentUnitName = event.unitName;
|
||||
|
||||
if ((event.community == null || event.community!.isEmpty) &&
|
||||
(event.unitName == null || event.unitName!.isEmpty) &&
|
||||
(event.productName == null || event.productName!.isEmpty)) {
|
||||
|
@ -38,14 +38,13 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
on<GarageDoorBatchControlEvent>(_onBatchControl);
|
||||
on<GarageDoorFetchBatchStatusEvent>(_onFetchBatchStatus);
|
||||
on<GarageDoorFactoryResetEvent>(_onFactoryReset);
|
||||
on<EditGarageDoorScheduleEvent>(_onEditSchedule);
|
||||
}
|
||||
|
||||
void _fetchGarageDoorStatus(
|
||||
GarageDoorInitialEvent event, Emitter<GarageDoorState> emit) async {
|
||||
void _fetchGarageDoorStatus(GarageDoorInitialEvent event, Emitter<GarageDoorState> emit) async {
|
||||
emit(GarageDoorLoadingState());
|
||||
try {
|
||||
var response =
|
||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
var response = await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
deviceStatus = GarageDoorStatusModel.fromJson(deviceId, response.status);
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
} catch (e) {
|
||||
@ -53,22 +52,18 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onFetchBatchStatus(GarageDoorFetchBatchStatusEvent event,
|
||||
Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _onFetchBatchStatus(GarageDoorFetchBatchStatusEvent event, Emitter<GarageDoorState> emit) async {
|
||||
emit(GarageDoorLoadingState());
|
||||
try {
|
||||
final status =
|
||||
await DevicesManagementApi().getBatchStatus(event.deviceIds);
|
||||
deviceStatus =
|
||||
GarageDoorStatusModel.fromJson(event.deviceIds.first, status.status);
|
||||
final status = await DevicesManagementApi().getBatchStatus(event.deviceIds);
|
||||
deviceStatus = GarageDoorStatusModel.fromJson(event.deviceIds.first, status.status);
|
||||
emit(GarageDoorBatchStatusLoaded(deviceStatus));
|
||||
} catch (e) {
|
||||
emit(GarageDoorBatchControlError(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _addSchedule(
|
||||
AddGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _addSchedule(AddGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||
try {
|
||||
ScheduleEntry newSchedule = ScheduleEntry(
|
||||
category: event.category,
|
||||
@ -76,11 +71,9 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
function: Status(code: 'switch_1', value: event.functionOn),
|
||||
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
||||
);
|
||||
bool success =
|
||||
await DevicesManagementApi().addScheduleRecord(newSchedule, deviceId);
|
||||
bool success = await DevicesManagementApi().addScheduleRecord(newSchedule, deviceId);
|
||||
if (success) {
|
||||
add(FetchGarageDoorSchedulesEvent(
|
||||
deviceId: deviceId, category: 'switch_1'));
|
||||
add(FetchGarageDoorSchedulesEvent(deviceId: deviceId, category: 'switch_1'));
|
||||
} else {
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
}
|
||||
@ -89,19 +82,16 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _onUpdateCountdownAlarm(
|
||||
UpdateCountdownAlarmEvent event, Emitter<GarageDoorState> emit) {
|
||||
void _onUpdateCountdownAlarm(UpdateCountdownAlarmEvent event, Emitter<GarageDoorState> emit) {
|
||||
final currentState = state;
|
||||
if (currentState is GarageDoorLoadedState) {
|
||||
emit(currentState.copyWith(
|
||||
status:
|
||||
currentState.status.copyWith(countdownAlarm: event.countdownAlarm),
|
||||
status: currentState.status.copyWith(countdownAlarm: event.countdownAlarm),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
void _onUpdateTrTimeCon(
|
||||
UpdateTrTimeConEvent event, Emitter<GarageDoorState> emit) {
|
||||
void _onUpdateTrTimeCon(UpdateTrTimeConEvent event, Emitter<GarageDoorState> emit) {
|
||||
final currentState = state;
|
||||
if (currentState is GarageDoorLoadedState) {
|
||||
emit(currentState.copyWith(
|
||||
@ -110,8 +100,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateSchedule(UpdateGarageDoorScheduleEvent event,
|
||||
Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _updateSchedule(UpdateGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||
try {
|
||||
final updatedSchedules = deviceStatus.schedules?.map((schedule) {
|
||||
if (schedule.scheduleId == event.scheduleId) {
|
||||
@ -138,15 +127,12 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _deleteSchedule(DeleteGarageDoorScheduleEvent event,
|
||||
Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _deleteSchedule(DeleteGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||
try {
|
||||
bool success = await DevicesManagementApi()
|
||||
.deleteScheduleRecord(deviceStatus.uuid, event.scheduleId);
|
||||
bool success = await DevicesManagementApi().deleteScheduleRecord(deviceStatus.uuid, event.scheduleId);
|
||||
if (success) {
|
||||
final updatedSchedules = deviceStatus.schedules
|
||||
?.where((schedule) => schedule.scheduleId != event.scheduleId)
|
||||
.toList();
|
||||
final updatedSchedules =
|
||||
deviceStatus.schedules?.where((schedule) => schedule.scheduleId != event.scheduleId).toList();
|
||||
deviceStatus = deviceStatus.copyWith(schedules: updatedSchedules);
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
} else {
|
||||
@ -157,12 +143,11 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _fetchSchedules(FetchGarageDoorSchedulesEvent event,
|
||||
Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _fetchSchedules(FetchGarageDoorSchedulesEvent event, Emitter<GarageDoorState> emit) async {
|
||||
emit(ScheduleGarageLoadingState());
|
||||
try {
|
||||
List<ScheduleModel> schedules = await DevicesManagementApi()
|
||||
.getDeviceSchedules(deviceStatus.uuid, event.category);
|
||||
List<ScheduleModel> schedules =
|
||||
await DevicesManagementApi().getDeviceSchedules(deviceStatus.uuid, event.category);
|
||||
deviceStatus = deviceStatus.copyWith(schedules: schedules);
|
||||
emit(
|
||||
GarageDoorLoadedState(
|
||||
@ -180,37 +165,30 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateSelectedTime(
|
||||
UpdateSelectedTimeEvent event, Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _updateSelectedTime(UpdateSelectedTimeEvent event, Emitter<GarageDoorState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is GarageDoorLoadedState) {
|
||||
emit(currentState.copyWith(selectedTime: event.selectedTime));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateSelectedDay(
|
||||
UpdateSelectedDayEvent event, Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _updateSelectedDay(UpdateSelectedDayEvent event, Emitter<GarageDoorState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is GarageDoorLoadedState) {
|
||||
List<bool> updatedDays = List.from(currentState.selectedDays);
|
||||
updatedDays[event.dayIndex] = event.isSelected;
|
||||
emit(currentState.copyWith(
|
||||
selectedDays: updatedDays, selectedTime: currentState.selectedTime));
|
||||
emit(currentState.copyWith(selectedDays: updatedDays, selectedTime: currentState.selectedTime));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _updateFunctionOn(
|
||||
UpdateFunctionOnEvent event, Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _updateFunctionOn(UpdateFunctionOnEvent event, Emitter<GarageDoorState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is GarageDoorLoadedState) {
|
||||
emit(currentState.copyWith(
|
||||
functionOn: event.functionOn,
|
||||
selectedTime: currentState.selectedTime));
|
||||
emit(currentState.copyWith(functionOn: event.functionOn, selectedTime: currentState.selectedTime));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _initializeAddSchedule(
|
||||
InitializeAddScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _initializeAddSchedule(InitializeAddScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||
final currentState = state;
|
||||
if (currentState is GarageDoorLoadedState) {
|
||||
emit(currentState.copyWith(
|
||||
@ -222,25 +200,20 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _fetchRecords(
|
||||
FetchGarageDoorRecordsEvent event, Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _fetchRecords(FetchGarageDoorRecordsEvent event, Emitter<GarageDoorState> emit) async {
|
||||
emit(GarageDoorReportsLoadingState());
|
||||
try {
|
||||
final from = DateTime.now()
|
||||
.subtract(const Duration(days: 30))
|
||||
.millisecondsSinceEpoch;
|
||||
final from = DateTime.now().subtract(const Duration(days: 30)).millisecondsSinceEpoch;
|
||||
final to = DateTime.now().millisecondsSinceEpoch;
|
||||
final DeviceReport records =
|
||||
await DevicesManagementApi.getDeviceReportsByDate(
|
||||
event.deviceId, 'switch_1', from.toString(), to.toString());
|
||||
await DevicesManagementApi.getDeviceReportsByDate(event.deviceId, 'switch_1', from.toString(), to.toString());
|
||||
emit(GarageDoorReportsState(deviceReport: records));
|
||||
} catch (e) {
|
||||
emit(GarageDoorReportsFailedState(error: e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onBatchControl(
|
||||
GarageDoorBatchControlEvent event, Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _onBatchControl(GarageDoorBatchControlEvent event, Emitter<GarageDoorState> emit) async {
|
||||
final oldValue = event.code == 'switch_1' ? deviceStatus.switch1 : false;
|
||||
|
||||
_updateLocalValue(event.code, event.value);
|
||||
@ -260,13 +233,11 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _backToGridView(
|
||||
BackToGarageDoorGridViewEvent event, Emitter<GarageDoorState> emit) {
|
||||
void _backToGridView(BackToGarageDoorGridViewEvent event, Emitter<GarageDoorState> emit) {
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
}
|
||||
|
||||
void _handleUpdate(
|
||||
GarageDoorUpdatedEvent event, Emitter<GarageDoorState> emit) {
|
||||
void _handleUpdate(GarageDoorUpdatedEvent event, Emitter<GarageDoorState> emit) {
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
}
|
||||
|
||||
@ -282,11 +253,9 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
late bool status;
|
||||
await Future.delayed(const Duration(milliseconds: 500));
|
||||
if (isBatch) {
|
||||
status = await DevicesManagementApi()
|
||||
.deviceBatchControl(deviceId, code, value);
|
||||
status = await DevicesManagementApi().deviceBatchControl(deviceId, code, value);
|
||||
} else {
|
||||
status = await DevicesManagementApi()
|
||||
.deviceControl(deviceId, Status(code: code, value: value));
|
||||
status = await DevicesManagementApi().deviceControl(deviceId, Status(code: code, value: value));
|
||||
}
|
||||
|
||||
if (!status) {
|
||||
@ -301,12 +270,10 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onFactoryReset(
|
||||
GarageDoorFactoryResetEvent event, Emitter<GarageDoorState> emit) async {
|
||||
Future<void> _onFactoryReset(GarageDoorFactoryResetEvent event, Emitter<GarageDoorState> emit) async {
|
||||
emit(GarageDoorLoadingState());
|
||||
try {
|
||||
final response = await DevicesManagementApi()
|
||||
.factoryReset(event.factoryReset, event.deviceId);
|
||||
final response = await DevicesManagementApi().factoryReset(event.factoryReset, event.deviceId);
|
||||
if (!response) {
|
||||
emit(const GarageDoorErrorState(message: 'Failed to reset device'));
|
||||
} else {
|
||||
@ -317,47 +284,34 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _increaseDelay(
|
||||
IncreaseGarageDoorDelayEvent event, Emitter<GarageDoorState> emit) async {
|
||||
void _increaseDelay(IncreaseGarageDoorDelayEvent event, Emitter<GarageDoorState> emit) async {
|
||||
// if (deviceStatus.countdown1 != 0) {
|
||||
try {
|
||||
deviceStatus = deviceStatus.copyWith(
|
||||
delay: deviceStatus.delay + Duration(minutes: 10));
|
||||
deviceStatus = deviceStatus.copyWith(delay: deviceStatus.delay + Duration(minutes: 10));
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
add(GarageDoorControlEvent(
|
||||
deviceId: event.deviceId,
|
||||
value: deviceStatus.delay.inSeconds,
|
||||
code: 'countdown_1'));
|
||||
add(GarageDoorControlEvent(deviceId: event.deviceId, value: deviceStatus.delay.inSeconds, code: 'countdown_1'));
|
||||
} catch (e) {
|
||||
emit(GarageDoorErrorState(message: e.toString()));
|
||||
}
|
||||
// }
|
||||
}
|
||||
|
||||
void _decreaseDelay(
|
||||
DecreaseGarageDoorDelayEvent event, Emitter<GarageDoorState> emit) async {
|
||||
void _decreaseDelay(DecreaseGarageDoorDelayEvent event, Emitter<GarageDoorState> emit) async {
|
||||
// if (deviceStatus.countdown1 != 0) {
|
||||
try {
|
||||
if (deviceStatus.delay.inMinutes > 10) {
|
||||
deviceStatus = deviceStatus.copyWith(
|
||||
delay: deviceStatus.delay - Duration(minutes: 10));
|
||||
deviceStatus = deviceStatus.copyWith(delay: deviceStatus.delay - Duration(minutes: 10));
|
||||
}
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
add(GarageDoorControlEvent(
|
||||
deviceId: event.deviceId,
|
||||
value: deviceStatus.delay.inSeconds,
|
||||
code: 'countdown_1'));
|
||||
add(GarageDoorControlEvent(deviceId: event.deviceId, value: deviceStatus.delay.inSeconds, code: 'countdown_1'));
|
||||
} catch (e) {
|
||||
emit(GarageDoorErrorState(message: e.toString()));
|
||||
}
|
||||
//}
|
||||
}
|
||||
|
||||
void _garageDoorControlEvent(
|
||||
GarageDoorControlEvent event, Emitter<GarageDoorState> emit) async {
|
||||
final oldValue = event.code == 'countdown_1'
|
||||
? deviceStatus.countdown1
|
||||
: deviceStatus.switch1;
|
||||
void _garageDoorControlEvent(GarageDoorControlEvent event, Emitter<GarageDoorState> emit) async {
|
||||
final oldValue = event.code == 'countdown_1' ? deviceStatus.countdown1 : deviceStatus.switch1;
|
||||
_updateLocalValue(event.code, event.value);
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
final success = await _runDeBouncer(
|
||||
@ -373,8 +327,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _revertValue(
|
||||
String code, dynamic oldValue, Emitter<GarageDoorState> emit) {
|
||||
void _revertValue(String code, dynamic oldValue, Emitter<GarageDoorState> emit) {
|
||||
switch (code) {
|
||||
case 'switch_1':
|
||||
if (oldValue is bool) {
|
||||
@ -383,8 +336,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
break;
|
||||
case 'countdown_1':
|
||||
if (oldValue is int) {
|
||||
deviceStatus = deviceStatus.copyWith(
|
||||
countdown1: oldValue, delay: Duration(seconds: oldValue));
|
||||
deviceStatus = deviceStatus.copyWith(countdown1: oldValue, delay: Duration(seconds: oldValue));
|
||||
}
|
||||
break;
|
||||
// Add other cases if needed
|
||||
@ -406,8 +358,7 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
break;
|
||||
case 'countdown_1':
|
||||
if (value is int) {
|
||||
deviceStatus = deviceStatus.copyWith(
|
||||
countdown1: value, delay: Duration(seconds: value));
|
||||
deviceStatus = deviceStatus.copyWith(countdown1: value, delay: Duration(seconds: value));
|
||||
}
|
||||
break;
|
||||
case 'countdown_alarm':
|
||||
@ -420,6 +371,25 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
deviceStatus = deviceStatus.copyWith(trTimeCon: value);
|
||||
}
|
||||
break;
|
||||
case 'door_state_1':
|
||||
if (value is String) {
|
||||
deviceStatus = deviceStatus.copyWith(doorState1: value);
|
||||
}
|
||||
break;
|
||||
case 'door_control_1':
|
||||
if (value is String) {
|
||||
deviceStatus = deviceStatus.copyWith(doorControl1: value);
|
||||
}
|
||||
break;
|
||||
case 'voice_control_1':
|
||||
if (value is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(voiceControl1: value);
|
||||
}
|
||||
break;
|
||||
case 'door_contact_state':
|
||||
if (value is bool) {
|
||||
deviceStatus = deviceStatus.copyWith(doorContactState: value);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
@ -430,4 +400,24 @@ class GarageDoorBloc extends Bloc<GarageDoorEvent, GarageDoorState> {
|
||||
_timer?.cancel();
|
||||
return super.close();
|
||||
}
|
||||
|
||||
FutureOr<void> _onEditSchedule(EditGarageDoorScheduleEvent event, Emitter<GarageDoorState> emit) async {
|
||||
try {
|
||||
ScheduleEntry newSchedule = ScheduleEntry(
|
||||
scheduleId: event.scheduleId,
|
||||
category: event.category,
|
||||
time: formatTimeOfDayToISO(event.time),
|
||||
function: Status(code: 'switch_1', value: event.functionOn),
|
||||
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
||||
);
|
||||
bool success = await DevicesManagementApi().editScheduleRecord(deviceId, newSchedule);
|
||||
if (success) {
|
||||
add(FetchGarageDoorSchedulesEvent(deviceId: deviceId, category: 'switch_1'));
|
||||
} else {
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
}
|
||||
} catch (e) {
|
||||
emit(GarageDoorLoadedState(status: deviceStatus));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -25,8 +25,7 @@ class GarageDoorControlEvent extends GarageDoorEvent {
|
||||
final dynamic value;
|
||||
final String code;
|
||||
|
||||
const GarageDoorControlEvent(
|
||||
{required this.deviceId, required this.value, required this.code});
|
||||
const GarageDoorControlEvent({required this.deviceId, required this.value, required this.code});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [deviceId, value];
|
||||
@ -46,6 +45,22 @@ class AddGarageDoorScheduleEvent extends GarageDoorEvent {
|
||||
});
|
||||
}
|
||||
|
||||
class EditGarageDoorScheduleEvent extends GarageDoorEvent {
|
||||
final String scheduleId;
|
||||
final String category;
|
||||
final TimeOfDay time;
|
||||
final bool functionOn;
|
||||
final List<bool> selectedDays;
|
||||
|
||||
const EditGarageDoorScheduleEvent({
|
||||
required this.scheduleId,
|
||||
required this.category,
|
||||
required this.time,
|
||||
required this.functionOn,
|
||||
required this.selectedDays,
|
||||
});
|
||||
}
|
||||
|
||||
class UpdateGarageDoorScheduleEvent extends GarageDoorEvent {
|
||||
final String deviceId;
|
||||
final String scheduleId;
|
||||
@ -106,8 +121,7 @@ class FetchGarageDoorRecordsEvent extends GarageDoorEvent {
|
||||
final String deviceId;
|
||||
final String code;
|
||||
|
||||
const FetchGarageDoorRecordsEvent(
|
||||
{required this.deviceId, required this.code});
|
||||
const FetchGarageDoorRecordsEvent({required this.deviceId, required this.code});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [deviceId, code];
|
||||
|
@ -76,13 +76,10 @@ class GarageDoorDialogHelper {
|
||||
padding: 8,
|
||||
backgroundColor: ColorsManager.boxColor,
|
||||
borderRadius: 15,
|
||||
onPressed: isEdit == true
|
||||
? null
|
||||
: () async {
|
||||
onPressed: () async {
|
||||
TimeOfDay? time = await showTimePicker(
|
||||
context: context,
|
||||
initialTime:
|
||||
state.selectedTime ?? TimeOfDay.now(),
|
||||
initialTime: state.selectedTime ?? TimeOfDay.now(),
|
||||
builder: (context, child) {
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
@ -102,9 +99,7 @@ class GarageDoorDialogHelper {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
state.selectedTime == null
|
||||
? 'Time'
|
||||
: state.selectedTime!.format(context),
|
||||
state.selectedTime == null ? 'Time' : state.selectedTime!.format(context),
|
||||
style: context.textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
),
|
||||
@ -119,8 +114,7 @@ class GarageDoorDialogHelper {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildDayCheckboxes(context, state.selectedDays,
|
||||
isEdit: isEdit),
|
||||
_buildDayCheckboxes(context, state.selectedDays, isEdit: isEdit),
|
||||
const SizedBox(height: 16),
|
||||
_buildFunctionSwitch(context, state.functionOn, isEdit),
|
||||
],
|
||||
@ -147,7 +141,13 @@ class GarageDoorDialogHelper {
|
||||
onPressed: () {
|
||||
if (state.selectedTime != null) {
|
||||
if (state.isEditing && index != null) {
|
||||
return;
|
||||
bloc.add(EditGarageDoorScheduleEvent(
|
||||
scheduleId: schedule?.scheduleId ?? '',
|
||||
category: 'switch_1',
|
||||
time: state.selectedTime!,
|
||||
selectedDays: state.selectedDays,
|
||||
functionOn: state.functionOn,
|
||||
));
|
||||
} else {
|
||||
bloc.add(AddGarageDoorScheduleEvent(
|
||||
category: 'switch_1',
|
||||
@ -199,9 +199,7 @@ class GarageDoorDialogHelper {
|
||||
return daysBoolean;
|
||||
}
|
||||
|
||||
static Widget _buildDayCheckboxes(
|
||||
BuildContext context, List<bool> selectedDays,
|
||||
{bool? isEdit}) {
|
||||
static Widget _buildDayCheckboxes(BuildContext context, List<bool> selectedDays, {bool? isEdit}) {
|
||||
final dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
|
||||
return Row(
|
||||
@ -210,12 +208,8 @@ class GarageDoorDialogHelper {
|
||||
children: [
|
||||
Checkbox(
|
||||
value: selectedDays[index],
|
||||
onChanged: isEdit == true
|
||||
? null
|
||||
: (bool? value) {
|
||||
context
|
||||
.read<GarageDoorBloc>()
|
||||
.add(UpdateSelectedDayEvent(index, value!));
|
||||
onChanged: (bool? value) {
|
||||
context.read<GarageDoorBloc>().add(UpdateSelectedDayEvent(index, value!));
|
||||
},
|
||||
),
|
||||
Text(dayLabels[index]),
|
||||
@ -225,27 +219,19 @@ class GarageDoorDialogHelper {
|
||||
);
|
||||
}
|
||||
|
||||
static Widget _buildFunctionSwitch(
|
||||
BuildContext context, bool isOn, bool? isEdit) {
|
||||
static Widget _buildFunctionSwitch(BuildContext context, bool isOn, bool? isEdit) {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
'Function:',
|
||||
style: context.textTheme.bodySmall!
|
||||
.copyWith(color: ColorsManager.grayColor),
|
||||
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.grayColor),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Radio<bool>(
|
||||
value: true,
|
||||
groupValue: isOn,
|
||||
onChanged: (bool? value) {
|
||||
if (isEdit == true) {
|
||||
return;
|
||||
} else {
|
||||
context
|
||||
.read<GarageDoorBloc>()
|
||||
.add(const UpdateFunctionOnEvent(functionOn: true));
|
||||
}
|
||||
context.read<GarageDoorBloc>().add(const UpdateFunctionOnEvent(functionOn: true));
|
||||
},
|
||||
),
|
||||
const Text('On'),
|
||||
@ -254,13 +240,7 @@ class GarageDoorDialogHelper {
|
||||
value: false,
|
||||
groupValue: isOn,
|
||||
onChanged: (bool? value) {
|
||||
if (isEdit == true) {
|
||||
return;
|
||||
} else {
|
||||
context
|
||||
.read<GarageDoorBloc>()
|
||||
.add(const UpdateFunctionOnEvent(functionOn: false));
|
||||
}
|
||||
context.read<GarageDoorBloc>().add(const UpdateFunctionOnEvent(functionOn: false));
|
||||
},
|
||||
),
|
||||
const Text('Off'),
|
||||
@ -317,33 +297,36 @@ class GarageDoorDialogHelper {
|
||||
alertBody: TimeOutAlarmDialogBody(bloc),
|
||||
title: 'Time Out Alarm',
|
||||
onConfirm: () {
|
||||
final updatedState =
|
||||
context.read<GarageDoorBloc>().state;
|
||||
if (updatedState
|
||||
is GarageDoorLoadedState) {
|
||||
final updatedState = context.read<GarageDoorBloc>().state;
|
||||
if (updatedState is GarageDoorLoadedState) {
|
||||
context.read<GarageDoorBloc>().add(
|
||||
GarageDoorControlEvent(
|
||||
deviceId:
|
||||
updatedState.status.uuid,
|
||||
deviceId: updatedState.status.uuid,
|
||||
code: 'countdown_alarm',
|
||||
value: updatedState
|
||||
.status.countdownAlarm,
|
||||
value: updatedState.status.countdownAlarm,
|
||||
),
|
||||
);
|
||||
Navigator.pop(context);
|
||||
// context.read<GarageDoorBloc>().add(
|
||||
// GarageDoorInitialEvent(
|
||||
// bloc.deviceId));
|
||||
}
|
||||
});
|
||||
},
|
||||
child: ToggleWidget(
|
||||
icon: "-1",
|
||||
value: state.status.countdownAlarm > 0,
|
||||
code: 'countdown_alarm',
|
||||
value: state.status.doorState1 == "close_time_alarm" ? false : true,
|
||||
code: 'door_state_1',
|
||||
deviceId: bloc.deviceId,
|
||||
label: 'Alarm when door is open',
|
||||
onChange: (value) {}),
|
||||
onChange: (value) {
|
||||
context.read<GarageDoorBloc>().add(
|
||||
GarageDoorControlEvent(
|
||||
deviceId: bloc.deviceId,
|
||||
code: 'door_state_1',
|
||||
value: state.status.doorState1 == "close_time_alarm"
|
||||
? "unclosed_time"
|
||||
: "close_time_alarm",
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
const SizedBox(
|
||||
@ -365,23 +348,16 @@ class GarageDoorDialogHelper {
|
||||
),
|
||||
title: 'Opening and Closing Time',
|
||||
onConfirm: () {
|
||||
final updatedState =
|
||||
context.read<GarageDoorBloc>().state;
|
||||
if (updatedState
|
||||
is GarageDoorLoadedState) {
|
||||
final updatedState = context.read<GarageDoorBloc>().state;
|
||||
if (updatedState is GarageDoorLoadedState) {
|
||||
context.read<GarageDoorBloc>().add(
|
||||
GarageDoorControlEvent(
|
||||
deviceId:
|
||||
updatedState.status.uuid,
|
||||
deviceId: updatedState.status.uuid,
|
||||
code: 'tr_timecon',
|
||||
value: updatedState
|
||||
.status.trTimeCon,
|
||||
value: updatedState.status.trTimeCon,
|
||||
),
|
||||
);
|
||||
Navigator.pop(context);
|
||||
// context.read<GarageDoorBloc>().add(
|
||||
// GarageDoorInitialEvent(
|
||||
// bloc.deviceId));
|
||||
}
|
||||
});
|
||||
},
|
||||
|
@ -65,7 +65,7 @@ class GarageDoorStatusModel {
|
||||
voiceControl1 = status.value ?? false;
|
||||
break;
|
||||
case 'door_state_1':
|
||||
doorState1 = status.value ?? 'closed';
|
||||
doorState1 = status.value ?? 'close_time_alarm';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,18 @@ import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class NotificationDialog extends StatelessWidget {
|
||||
class NotificationDialog extends StatefulWidget {
|
||||
const NotificationDialog({super.key});
|
||||
|
||||
@override
|
||||
State<NotificationDialog> createState() => _NotificationDialogState();
|
||||
}
|
||||
|
||||
class _NotificationDialogState extends State<NotificationDialog> {
|
||||
bool isLowBatteryNotificationEnabled = true;
|
||||
bool isClosingRemindersEnabled = true;
|
||||
bool isDoorAlarmEnabled = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog(
|
||||
@ -66,7 +75,11 @@ class NotificationDialog extends StatelessWidget {
|
||||
code: 'notification',
|
||||
deviceId: '',
|
||||
label: 'Low Battery',
|
||||
onChange: (v) {},
|
||||
onChange: (v) {
|
||||
setState(() {
|
||||
isLowBatteryNotificationEnabled = v;
|
||||
});
|
||||
},
|
||||
icon: '-1',
|
||||
),
|
||||
ToggleWidget(
|
||||
@ -74,7 +87,11 @@ class NotificationDialog extends StatelessWidget {
|
||||
code: 'notification',
|
||||
deviceId: '',
|
||||
label: 'Closing\nReminders',
|
||||
onChange: (v) {},
|
||||
onChange: (v) {
|
||||
setState(() {
|
||||
isClosingRemindersEnabled = v;
|
||||
});
|
||||
},
|
||||
icon: '-1',
|
||||
),
|
||||
ToggleWidget(
|
||||
@ -82,7 +99,11 @@ class NotificationDialog extends StatelessWidget {
|
||||
code: 'notification',
|
||||
deviceId: '',
|
||||
label: 'Door Alarm',
|
||||
onChange: (v) {},
|
||||
onChange: (v) {
|
||||
setState(() {
|
||||
isDoorAlarmEnabled = v;
|
||||
});
|
||||
},
|
||||
icon: '-1',
|
||||
),
|
||||
],
|
||||
|
@ -10,14 +10,12 @@ import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||
part 'one_gang_glass_switch_event.dart';
|
||||
part 'one_gang_glass_switch_state.dart';
|
||||
|
||||
class OneGangGlassSwitchBloc
|
||||
extends Bloc<OneGangGlassSwitchEvent, OneGangGlassSwitchState> {
|
||||
class OneGangGlassSwitchBloc extends Bloc<OneGangGlassSwitchEvent, OneGangGlassSwitchState> {
|
||||
OneGangGlassStatusModel deviceStatus;
|
||||
Timer? _timer;
|
||||
|
||||
OneGangGlassSwitchBloc({required String deviceId})
|
||||
: deviceStatus = OneGangGlassStatusModel(
|
||||
uuid: deviceId, switch1: false, countDown: 0),
|
||||
: deviceStatus = OneGangGlassStatusModel(uuid: deviceId, switch1: false, countDown: 0),
|
||||
super(OneGangGlassSwitchInitial()) {
|
||||
on<OneGangGlassSwitchFetchDeviceEvent>(_onFetchDeviceStatus);
|
||||
on<OneGangGlassSwitchControl>(_onControl);
|
||||
@ -26,22 +24,19 @@ class OneGangGlassSwitchBloc
|
||||
on<OneGangGlassFactoryResetEvent>(_onFactoryReset);
|
||||
}
|
||||
|
||||
Future<void> _onFetchDeviceStatus(OneGangGlassSwitchFetchDeviceEvent event,
|
||||
Emitter<OneGangGlassSwitchState> emit) async {
|
||||
Future<void> _onFetchDeviceStatus(
|
||||
OneGangGlassSwitchFetchDeviceEvent event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||
emit(OneGangGlassSwitchLoading());
|
||||
try {
|
||||
final status =
|
||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
deviceStatus =
|
||||
OneGangGlassStatusModel.fromJson(event.deviceId, status.status);
|
||||
final status = await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
deviceStatus = OneGangGlassStatusModel.fromJson(event.deviceId, status.status);
|
||||
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
||||
} catch (e) {
|
||||
emit(OneGangGlassSwitchError(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onControl(OneGangGlassSwitchControl event,
|
||||
Emitter<OneGangGlassSwitchState> emit) async {
|
||||
Future<void> _onControl(OneGangGlassSwitchControl event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||
final oldValue = _getValueByCode(event.code);
|
||||
|
||||
_updateLocalValue(event.code, event.value);
|
||||
@ -57,12 +52,10 @@ class OneGangGlassSwitchBloc
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _onFactoryReset(OneGangGlassFactoryResetEvent event,
|
||||
Emitter<OneGangGlassSwitchState> emit) async {
|
||||
Future<void> _onFactoryReset(OneGangGlassFactoryResetEvent event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||
emit(OneGangGlassSwitchLoading());
|
||||
try {
|
||||
final response = await DevicesManagementApi()
|
||||
.factoryReset(event.factoryReset, event.deviceId);
|
||||
final response = await DevicesManagementApi().factoryReset(event.factoryReset, event.deviceId);
|
||||
if (!response) {
|
||||
emit(OneGangGlassSwitchError('Failed to reset device'));
|
||||
} else {
|
||||
@ -73,12 +66,11 @@ class OneGangGlassSwitchBloc
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _onBatchControl(OneGangGlassSwitchBatchControl event,
|
||||
Emitter<OneGangGlassSwitchState> emit) async {
|
||||
Future<void> _onBatchControl(OneGangGlassSwitchBatchControl event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||
final oldValue = _getValueByCode(event.code);
|
||||
|
||||
_updateLocalValue(event.code, event.value);
|
||||
emit(OneGangGlassSwitchBatchStatusLoaded(deviceStatus));
|
||||
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
||||
|
||||
await _runDebounce(
|
||||
deviceId: event.deviceIds,
|
||||
@ -91,15 +83,12 @@ class OneGangGlassSwitchBloc
|
||||
}
|
||||
|
||||
Future<void> _onFetchBatchStatus(
|
||||
OneGangGlassSwitchFetchBatchStatusEvent event,
|
||||
Emitter<OneGangGlassSwitchState> emit) async {
|
||||
OneGangGlassSwitchFetchBatchStatusEvent event, Emitter<OneGangGlassSwitchState> emit) async {
|
||||
emit(OneGangGlassSwitchLoading());
|
||||
try {
|
||||
final status =
|
||||
await DevicesManagementApi().getBatchStatus(event.deviceIds);
|
||||
deviceStatus = OneGangGlassStatusModel.fromJson(
|
||||
event.deviceIds.first, status.status);
|
||||
emit(OneGangGlassSwitchBatchStatusLoaded(deviceStatus));
|
||||
final status = await DevicesManagementApi().getBatchStatus(event.deviceIds);
|
||||
deviceStatus = OneGangGlassStatusModel.fromJson(event.deviceIds.first, status.status);
|
||||
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
||||
} catch (e) {
|
||||
emit(OneGangGlassSwitchError(e.toString()));
|
||||
}
|
||||
@ -128,11 +117,9 @@ class OneGangGlassSwitchBloc
|
||||
try {
|
||||
late bool response;
|
||||
if (isBatch) {
|
||||
response = await DevicesManagementApi()
|
||||
.deviceBatchControl(deviceId, code, value);
|
||||
response = await DevicesManagementApi().deviceBatchControl(deviceId, code, value);
|
||||
} else {
|
||||
response = await DevicesManagementApi()
|
||||
.deviceControl(deviceId, Status(code: code, value: value));
|
||||
response = await DevicesManagementApi().deviceControl(deviceId, Status(code: code, value: value));
|
||||
}
|
||||
|
||||
if (!response) {
|
||||
@ -144,8 +131,7 @@ class OneGangGlassSwitchBloc
|
||||
});
|
||||
}
|
||||
|
||||
void _revertValueAndEmit(String deviceId, String code, bool oldValue,
|
||||
Emitter<OneGangGlassSwitchState> emit) {
|
||||
void _revertValueAndEmit(String deviceId, String code, bool oldValue, Emitter<OneGangGlassSwitchState> emit) {
|
||||
_updateLocalValue(code, oldValue);
|
||||
emit(OneGangGlassSwitchStatusLoaded(deviceStatus));
|
||||
}
|
||||
|
@ -55,7 +55,7 @@ class OneGangGlassSwitchControlView extends StatelessWidget with HelperResponsiv
|
||||
value: status.switch1,
|
||||
code: 'switch_1',
|
||||
deviceId: deviceId,
|
||||
label: 'Wall Lightً',
|
||||
label: "Wall Light",
|
||||
onChange: (value) {
|
||||
context.read<OneGangGlassSwitchBloc>().add(
|
||||
OneGangGlassSwitchControl(
|
||||
|
@ -31,6 +31,7 @@ class ToggleWidget extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
debugPrint(label.toString());
|
||||
return DeviceControlsContainer(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
|
@ -57,7 +57,7 @@ class ThreeGangGlassSwitchBatchControlView extends StatelessWidget with HelperRe
|
||||
value: status.switch1,
|
||||
code: 'switch_1',
|
||||
deviceId: deviceIds.first,
|
||||
label: 'Glass Switch 1',
|
||||
label: "Wall Light",
|
||||
onChange: (value) {
|
||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||
ThreeGangGlassSwitchBatchControl(
|
||||
@ -72,7 +72,7 @@ class ThreeGangGlassSwitchBatchControlView extends StatelessWidget with HelperRe
|
||||
value: status.switch2,
|
||||
code: 'switch_2',
|
||||
deviceId: deviceIds.first,
|
||||
label: 'Glass Switch 2',
|
||||
label: "Ceiling Light",
|
||||
onChange: (value) {
|
||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||
ThreeGangGlassSwitchBatchControl(
|
||||
@ -87,7 +87,7 @@ class ThreeGangGlassSwitchBatchControlView extends StatelessWidget with HelperRe
|
||||
value: status.switch3,
|
||||
code: 'switch_3',
|
||||
deviceId: deviceIds.first,
|
||||
label: 'Glass Switch 3',
|
||||
label: "SpotLight",
|
||||
onChange: (value) {
|
||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||
ThreeGangGlassSwitchBatchControl(
|
||||
|
@ -56,7 +56,7 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget with HelperRespons
|
||||
value: status.switch1,
|
||||
code: 'switch_1',
|
||||
deviceId: deviceId,
|
||||
label: 'Wall Light',
|
||||
label: "Wall Light",
|
||||
onChange: (value) {
|
||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||
ThreeGangGlassSwitchControl(
|
||||
@ -71,7 +71,7 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget with HelperRespons
|
||||
value: status.switch2,
|
||||
code: 'switch_2',
|
||||
deviceId: deviceId,
|
||||
label: 'Ceiling Light',
|
||||
label: "Ceiling Light",
|
||||
onChange: (value) {
|
||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||
ThreeGangGlassSwitchControl(
|
||||
@ -86,7 +86,7 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget with HelperRespons
|
||||
value: status.switch3,
|
||||
code: 'switch_3',
|
||||
deviceId: deviceId,
|
||||
label: 'SpotLight',
|
||||
label: "SpotLight",
|
||||
onChange: (value) {
|
||||
context.read<ThreeGangGlassSwitchBloc>().add(
|
||||
ThreeGangGlassSwitchControl(
|
||||
|
@ -1,6 +1,7 @@
|
||||
// water_heater_bloc.dart
|
||||
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:equatable/equatable.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
@ -30,6 +31,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
|
||||
on<GetSchedulesEvent>(_getSchedule);
|
||||
on<AddScheduleEvent>(_onAddSchedule);
|
||||
on<EditWaterHeaterScheduleEvent>(_onEditSchedule);
|
||||
on<DeleteScheduleEvent>(_onDeleteSchedule);
|
||||
on<UpdateScheduleEntryEvent>(_onUpdateSchedule);
|
||||
}
|
||||
@ -76,8 +78,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
final updatedDays = List<bool>.from(currentState.selectedDays);
|
||||
updatedDays[event.index] = event.value;
|
||||
emit(currentState.copyWith(
|
||||
selectedDays: updatedDays, selectedTime: currentState.selectedTime));
|
||||
emit(currentState.copyWith(selectedDays: updatedDays, selectedTime: currentState.selectedTime));
|
||||
}
|
||||
|
||||
FutureOr<void> _updateFunctionOn(
|
||||
@ -85,8 +86,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
Emitter<WaterHeaterState> emit,
|
||||
) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
emit(currentState.copyWith(
|
||||
functionOn: event.isOn, selectedTime: currentState.selectedTime));
|
||||
emit(currentState.copyWith(functionOn: event.isOn, selectedTime: currentState.selectedTime));
|
||||
}
|
||||
|
||||
FutureOr<void> _updateScheduleEvent(
|
||||
@ -101,8 +101,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
));
|
||||
}
|
||||
if (event.scheduleMode == ScheduleModes.countdown) {
|
||||
final countdownRemaining =
|
||||
Duration(hours: event.hours, minutes: event.minutes);
|
||||
final countdownRemaining = Duration(hours: event.hours, minutes: event.minutes);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
scheduleMode: ScheduleModes.countdown,
|
||||
@ -112,13 +111,11 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
countdownRemaining: countdownRemaining,
|
||||
));
|
||||
|
||||
if (!currentState.isCountdownActive! &&
|
||||
countdownRemaining > Duration.zero) {
|
||||
if (!currentState.isCountdownActive! && countdownRemaining > Duration.zero) {
|
||||
_startCountdownTimer(emit, countdownRemaining);
|
||||
}
|
||||
} else if (event.scheduleMode == ScheduleModes.inching) {
|
||||
final inchingDuration =
|
||||
Duration(hours: event.hours, minutes: event.minutes);
|
||||
final inchingDuration = Duration(hours: event.hours, minutes: event.minutes);
|
||||
|
||||
emit(currentState.copyWith(
|
||||
scheduleMode: ScheduleModes.inching,
|
||||
@ -220,8 +217,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
try {
|
||||
final status = await DevicesManagementApi().deviceControl(
|
||||
event.deviceId,
|
||||
Status(
|
||||
code: isCountDown ? 'countdown_1' : 'switch_inching', value: 0),
|
||||
Status(code: isCountDown ? 'countdown_1' : 'switch_inching', value: 0),
|
||||
);
|
||||
if (!status) {
|
||||
emit(const WaterHeaterFailedState(error: 'Failed to stop schedule.'));
|
||||
@ -239,10 +235,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
emit(WaterHeaterLoadingState());
|
||||
|
||||
try {
|
||||
final status =
|
||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
deviceStatus =
|
||||
WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
||||
final status = await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
deviceStatus = WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
||||
|
||||
if (deviceStatus.scheduleMode == ScheduleModes.countdown) {
|
||||
final countdownRemaining = Duration(
|
||||
@ -340,10 +334,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
|
||||
if (currentState.countdownRemaining != null &&
|
||||
currentState.countdownRemaining! > Duration.zero) {
|
||||
final newRemaining =
|
||||
currentState.countdownRemaining! - const Duration(minutes: 1);
|
||||
if (currentState.countdownRemaining != null && currentState.countdownRemaining! > Duration.zero) {
|
||||
final newRemaining = currentState.countdownRemaining! - const Duration(minutes: 1);
|
||||
|
||||
if (newRemaining <= Duration.zero) {
|
||||
_countdownTimer?.cancel();
|
||||
@ -438,8 +430,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
}
|
||||
}
|
||||
|
||||
void _revertValue(String code, dynamic oldValue,
|
||||
void Function(WaterHeaterState state) emit) {
|
||||
void _revertValue(String code, dynamic oldValue, void Function(WaterHeaterState state) emit) {
|
||||
_updateLocalValue(code, oldValue);
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
@ -486,13 +477,12 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
return super.close();
|
||||
}
|
||||
|
||||
FutureOr<void> _getSchedule(
|
||||
GetSchedulesEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
FutureOr<void> _getSchedule(GetSchedulesEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
emit(ScheduleLoadingState());
|
||||
|
||||
try {
|
||||
List<ScheduleModel> schedules = await DevicesManagementApi()
|
||||
.getDeviceSchedules(deviceStatus.uuid, event.category);
|
||||
List<ScheduleModel> schedules =
|
||||
await DevicesManagementApi().getDeviceSchedules(deviceStatus.uuid, event.category);
|
||||
|
||||
emit(WaterHeaterDeviceStatusLoaded(
|
||||
deviceStatus,
|
||||
@ -524,8 +514,35 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
|
||||
// emit(ScheduleLoadingState());
|
||||
|
||||
bool success = await DevicesManagementApi()
|
||||
.addScheduleRecord(newSchedule, currentState.status.uuid);
|
||||
bool success = await DevicesManagementApi().addScheduleRecord(newSchedule, currentState.status.uuid);
|
||||
|
||||
if (success) {
|
||||
add(GetSchedulesEvent(category: 'switch_1', uuid: deviceStatus.uuid));
|
||||
} else {
|
||||
emit(currentState);
|
||||
//emit(const WaterHeaterFailedState(error: 'Failed to add schedule.'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _onEditSchedule(EditWaterHeaterScheduleEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
|
||||
ScheduleEntry newSchedule = ScheduleEntry(
|
||||
scheduleId: event.scheduleId,
|
||||
category: event.category,
|
||||
time: formatTimeOfDayToISO(event.time),
|
||||
function: Status(code: 'switch_1', value: event.functionOn),
|
||||
days: ScheduleModel.convertSelectedDaysToStrings(event.selectedDays),
|
||||
);
|
||||
|
||||
// emit(ScheduleLoadingState());
|
||||
|
||||
bool success = await DevicesManagementApi().editScheduleRecord(
|
||||
currentState.status.uuid,
|
||||
newSchedule,
|
||||
);
|
||||
|
||||
if (success) {
|
||||
add(GetSchedulesEvent(category: 'switch_1', uuid: deviceStatus.uuid));
|
||||
@ -577,13 +594,11 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
|
||||
// emit(ScheduleLoadingState());
|
||||
|
||||
bool success = await DevicesManagementApi()
|
||||
.deleteScheduleRecord(currentState.status.uuid, event.scheduleId);
|
||||
bool success = await DevicesManagementApi().deleteScheduleRecord(currentState.status.uuid, event.scheduleId);
|
||||
|
||||
if (success) {
|
||||
final updatedSchedules = currentState.schedules
|
||||
.where((schedule) => schedule.scheduleId != event.scheduleId)
|
||||
.toList();
|
||||
final updatedSchedules =
|
||||
currentState.schedules.where((schedule) => schedule.scheduleId != event.scheduleId).toList();
|
||||
|
||||
emit(currentState.copyWith(schedules: updatedSchedules));
|
||||
} else {
|
||||
@ -593,15 +608,12 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _batchFetchWaterHeater(FetchWaterHeaterBatchStatusEvent event,
|
||||
Emitter<WaterHeaterState> emit) async {
|
||||
FutureOr<void> _batchFetchWaterHeater(FetchWaterHeaterBatchStatusEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
emit(WaterHeaterLoadingState());
|
||||
|
||||
try {
|
||||
final status =
|
||||
await DevicesManagementApi().getBatchStatus(event.devicesUuid);
|
||||
deviceStatus = WaterHeaterStatusModel.fromJson(
|
||||
event.devicesUuid.first, status.status);
|
||||
final status = await DevicesManagementApi().getBatchStatus(event.devicesUuid);
|
||||
deviceStatus = WaterHeaterStatusModel.fromJson(event.devicesUuid.first, status.status);
|
||||
|
||||
emit(WaterHeaterDeviceStatusLoaded(deviceStatus));
|
||||
} catch (e) {
|
||||
@ -609,8 +621,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
||||
}
|
||||
}
|
||||
|
||||
FutureOr<void> _batchControlWaterHeater(ControlWaterHeaterBatchEvent event,
|
||||
Emitter<WaterHeaterState> emit) async {
|
||||
FutureOr<void> _batchControlWaterHeater(ControlWaterHeaterBatchEvent event, Emitter<WaterHeaterState> emit) async {
|
||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||
|
||||
|
@ -71,6 +71,22 @@ final class AddScheduleEvent extends WaterHeaterEvent {
|
||||
List<Object?> get props => [selectedDays, time, functionOn, category];
|
||||
}
|
||||
|
||||
class EditWaterHeaterScheduleEvent extends WaterHeaterEvent {
|
||||
final String scheduleId;
|
||||
final String category;
|
||||
final TimeOfDay time;
|
||||
final bool functionOn;
|
||||
final List<bool> selectedDays;
|
||||
|
||||
const EditWaterHeaterScheduleEvent({
|
||||
required this.scheduleId,
|
||||
required this.category,
|
||||
required this.time,
|
||||
required this.functionOn,
|
||||
required this.selectedDays,
|
||||
});
|
||||
}
|
||||
|
||||
final class DeleteScheduleEvent extends WaterHeaterEvent {
|
||||
final int index;
|
||||
final String scheduleId;
|
||||
|
@ -1,14 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
import 'package:syncrow_web/pages/common/buttons/default_button.dart';
|
||||
|
||||
class ScheduleDialogHelper {
|
||||
static void showAddScheduleDialog(BuildContext context,
|
||||
{ScheduleModel? schedule, int? index, bool? isEdit}) {
|
||||
static void showAddScheduleDialog(BuildContext context, {ScheduleModel? schedule, int? index, bool? isEdit}) {
|
||||
final bloc = context.read<WaterHeaterBloc>();
|
||||
|
||||
if (schedule == null) {
|
||||
@ -70,13 +69,10 @@ class ScheduleDialogHelper {
|
||||
padding: 8,
|
||||
backgroundColor: ColorsManager.boxColor,
|
||||
borderRadius: 15,
|
||||
onPressed: isEdit == true
|
||||
? null
|
||||
: () async {
|
||||
onPressed: () async {
|
||||
TimeOfDay? time = await showTimePicker(
|
||||
context: context,
|
||||
initialTime:
|
||||
state.selectedTime ?? TimeOfDay.now(),
|
||||
initialTime: state.selectedTime ?? TimeOfDay.now(),
|
||||
builder: (context, child) {
|
||||
return Theme(
|
||||
data: Theme.of(context).copyWith(
|
||||
@ -96,9 +92,7 @@ class ScheduleDialogHelper {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
state.selectedTime == null
|
||||
? 'Time'
|
||||
: state.selectedTime!.format(context),
|
||||
state.selectedTime == null ? 'Time' : state.selectedTime!.format(context),
|
||||
style: context.textTheme.bodySmall!.copyWith(
|
||||
color: ColorsManager.grayColor,
|
||||
),
|
||||
@ -113,8 +107,7 @@ class ScheduleDialogHelper {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
_buildDayCheckboxes(context, state.selectedDays,
|
||||
isEdit: isEdit),
|
||||
_buildDayCheckboxes(context, state.selectedDays, isEdit: isEdit),
|
||||
const SizedBox(height: 16),
|
||||
_buildFunctionSwitch(context, state.functionOn, isEdit),
|
||||
],
|
||||
@ -141,7 +134,13 @@ class ScheduleDialogHelper {
|
||||
onPressed: () {
|
||||
if (state.selectedTime != null) {
|
||||
if (state.isEditing && index != null) {
|
||||
return;
|
||||
bloc.add(EditWaterHeaterScheduleEvent(
|
||||
scheduleId: schedule?.scheduleId ?? '',
|
||||
category: 'switch_1',
|
||||
time: state.selectedTime!,
|
||||
selectedDays: state.selectedDays,
|
||||
functionOn: state.functionOn,
|
||||
));
|
||||
} else {
|
||||
bloc.add(AddScheduleEvent(
|
||||
category: 'switch_1',
|
||||
@ -193,9 +192,7 @@ class ScheduleDialogHelper {
|
||||
return daysBoolean;
|
||||
}
|
||||
|
||||
static Widget _buildDayCheckboxes(
|
||||
BuildContext context, List<bool> selectedDays,
|
||||
{bool? isEdit}) {
|
||||
static Widget _buildDayCheckboxes(BuildContext context, List<bool> selectedDays, {bool? isEdit}) {
|
||||
final dayLabels = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];
|
||||
|
||||
return Row(
|
||||
@ -204,12 +201,8 @@ class ScheduleDialogHelper {
|
||||
children: [
|
||||
Checkbox(
|
||||
value: selectedDays[index],
|
||||
onChanged: isEdit == true
|
||||
? null
|
||||
: (bool? value) {
|
||||
context
|
||||
.read<WaterHeaterBloc>()
|
||||
.add(UpdateSelectedDayEvent(index, value!));
|
||||
onChanged: (bool? value) {
|
||||
context.read<WaterHeaterBloc>().add(UpdateSelectedDayEvent(index, value!));
|
||||
},
|
||||
),
|
||||
Text(dayLabels[index]),
|
||||
@ -219,27 +212,19 @@ class ScheduleDialogHelper {
|
||||
);
|
||||
}
|
||||
|
||||
static Widget _buildFunctionSwitch(
|
||||
BuildContext context, bool isOn, bool? isEdit) {
|
||||
static Widget _buildFunctionSwitch(BuildContext context, bool isOn, bool? isEdit) {
|
||||
return Row(
|
||||
children: [
|
||||
Text(
|
||||
'Function:',
|
||||
style: context.textTheme.bodySmall!
|
||||
.copyWith(color: ColorsManager.grayColor),
|
||||
style: context.textTheme.bodySmall!.copyWith(color: ColorsManager.grayColor),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Radio<bool>(
|
||||
value: true,
|
||||
groupValue: isOn,
|
||||
onChanged: (bool? value) {
|
||||
if (isEdit == true) {
|
||||
return;
|
||||
} else {
|
||||
context
|
||||
.read<WaterHeaterBloc>()
|
||||
.add(const UpdateFunctionOnEvent(true));
|
||||
}
|
||||
context.read<WaterHeaterBloc>().add(const UpdateFunctionOnEvent(true));
|
||||
},
|
||||
),
|
||||
const Text('On'),
|
||||
@ -248,13 +233,7 @@ class ScheduleDialogHelper {
|
||||
value: false,
|
||||
groupValue: isOn,
|
||||
onChanged: (bool? value) {
|
||||
if (isEdit == true) {
|
||||
return;
|
||||
} else {
|
||||
context
|
||||
.read<WaterHeaterBloc>()
|
||||
.add(const UpdateFunctionOnEvent(false));
|
||||
}
|
||||
context.read<WaterHeaterBloc>().add(const UpdateFunctionOnEvent(false));
|
||||
},
|
||||
),
|
||||
const Text('Off'),
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
|
||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||
|
||||
class ScheduleEntry {
|
||||
@ -9,12 +8,14 @@ class ScheduleEntry {
|
||||
final String time;
|
||||
final Status function;
|
||||
final List<String> days;
|
||||
final String? scheduleId;
|
||||
|
||||
ScheduleEntry({
|
||||
required this.category,
|
||||
required this.time,
|
||||
required this.function,
|
||||
required this.days,
|
||||
this.scheduleId,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -38,6 +39,7 @@ class ScheduleEntry {
|
||||
|
||||
Map<String, dynamic> toMap() {
|
||||
return {
|
||||
'scheduleId': scheduleId,
|
||||
'category': category,
|
||||
'time': time,
|
||||
'function': function.toMap(),
|
||||
@ -56,8 +58,7 @@ class ScheduleEntry {
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
|
||||
factory ScheduleEntry.fromJson(String source) =>
|
||||
ScheduleEntry.fromMap(json.decode(source));
|
||||
factory ScheduleEntry.fromJson(String source) => ScheduleEntry.fromMap(json.decode(source));
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
@ -72,9 +73,6 @@ class ScheduleEntry {
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
return category.hashCode ^
|
||||
time.hashCode ^
|
||||
function.hashCode ^
|
||||
days.hashCode;
|
||||
return category.hashCode ^ time.hashCode ^ function.hashCode ^ days.hashCode;
|
||||
}
|
||||
}
|
||||
|
@ -2,9 +2,17 @@ import 'package:flutter/material.dart';
|
||||
import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart';
|
||||
import 'package:syncrow_web/utils/color_manager.dart';
|
||||
|
||||
class WaterLeakNotificationDialog extends StatelessWidget {
|
||||
class WaterLeakNotificationDialog extends StatefulWidget {
|
||||
const WaterLeakNotificationDialog({super.key});
|
||||
|
||||
@override
|
||||
State<WaterLeakNotificationDialog> createState() => _WaterLeakNotificationDialogState();
|
||||
}
|
||||
|
||||
class _WaterLeakNotificationDialogState extends State<WaterLeakNotificationDialog> {
|
||||
bool isLowBatteryNotificationEnabled = true;
|
||||
bool isWaterLeakageNotificationEnabled = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Dialog(
|
||||
@ -66,7 +74,11 @@ class WaterLeakNotificationDialog extends StatelessWidget {
|
||||
code: 'notification',
|
||||
deviceId: '',
|
||||
label: 'Low Battery',
|
||||
onChange: (v) {},
|
||||
onChange: (v) {
|
||||
setState(() {
|
||||
isLowBatteryNotificationEnabled = v;
|
||||
});
|
||||
},
|
||||
icon: '-1',
|
||||
),
|
||||
ToggleWidget(
|
||||
@ -74,7 +86,11 @@ class WaterLeakNotificationDialog extends StatelessWidget {
|
||||
code: 'notification',
|
||||
deviceId: '',
|
||||
label: 'Water Leakage',
|
||||
onChange: (v) {},
|
||||
onChange: (v) {
|
||||
setState(() {
|
||||
isWaterLeakageNotificationEnabled = v;
|
||||
});
|
||||
},
|
||||
icon: '-1',
|
||||
),
|
||||
],
|
||||
|
@ -71,6 +71,12 @@ class DeviceModel {
|
||||
tempIcon = Assets.twoGang;
|
||||
} else if (type == DeviceType.WH) {
|
||||
tempIcon = Assets.waterHeater;
|
||||
} else if (type == DeviceType.DoorSensor) {
|
||||
tempIcon = Assets.sensors;
|
||||
} else if (type == DeviceType.GarageDoor) {
|
||||
tempIcon = Assets.openedDoor;
|
||||
} else if (type == DeviceType.WaterLeak) {
|
||||
tempIcon = Assets.waterLeakNormal;
|
||||
} else {
|
||||
tempIcon = Assets.blackLogo;
|
||||
}
|
||||
|
@ -232,6 +232,22 @@ class DevicesManagementApi {
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> editScheduleRecord(String uuid, ScheduleEntry newSchedule) async {
|
||||
try {
|
||||
final response = await HTTPService().put(
|
||||
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),
|
||||
body: newSchedule.toMap(),
|
||||
expectedResponseModel: (json) {
|
||||
return json['success'] ?? false;
|
||||
},
|
||||
);
|
||||
return response;
|
||||
} catch (e) {
|
||||
debugPrint('Error fetching $e');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<bool> deleteScheduleRecord(String uuid, String scheduleId) async {
|
||||
try {
|
||||
final response = await HTTPService().delete(
|
||||
|
@ -11,8 +11,30 @@ enum DeviceType {
|
||||
CeilingSensor,
|
||||
WallSensor,
|
||||
WH,
|
||||
DoorSensor,
|
||||
GarageDoor,
|
||||
WaterLeak,
|
||||
Other,
|
||||
}
|
||||
/*
|
||||
|
||||
3G:
|
||||
1G:
|
||||
2G:
|
||||
GW:
|
||||
DL:
|
||||
WPS:
|
||||
CPS:
|
||||
AC:
|
||||
CUR:
|
||||
WH:
|
||||
DS:
|
||||
1GT:
|
||||
2GT:
|
||||
3GT:
|
||||
GD:
|
||||
WL:
|
||||
*/
|
||||
|
||||
Map<String, DeviceType> devicesTypesMap = {
|
||||
"AC": DeviceType.AC,
|
||||
@ -25,4 +47,10 @@ Map<String, DeviceType> devicesTypesMap = {
|
||||
"1G": DeviceType.OneGang,
|
||||
"CUR": DeviceType.Curtain,
|
||||
"WH": DeviceType.WH,
|
||||
'DS': DeviceType.DoorSensor,
|
||||
"1GT": DeviceType.OneGang,
|
||||
"2GT": DeviceType.TwoGang,
|
||||
"3GT": DeviceType.ThreeGang,
|
||||
'GD': DeviceType.GarageDoor,
|
||||
'WL': DeviceType.WaterLeak
|
||||
};
|
||||
|
Reference in New Issue
Block a user