mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
Add schedule saving functionality and update schedule events
This commit is contained in:
@ -37,28 +37,39 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
|||||||
Timer? _countdownTimer;
|
Timer? _countdownTimer;
|
||||||
Duration countdownRemaining = Duration.zero;
|
Duration countdownRemaining = Duration.zero;
|
||||||
|
|
||||||
void _onStopScheduleEvent(
|
Future<void> _onStopScheduleEvent(
|
||||||
StopScheduleEvent event,
|
StopScheduleEvent event,
|
||||||
Emitter<ScheduleState> emit,
|
Emitter<ScheduleState> emit,
|
||||||
) {
|
) async {
|
||||||
if (state is ScheduleLoaded) {
|
if (state is ScheduleLoaded) {
|
||||||
final currentState = state as ScheduleLoaded;
|
final currentState = state as ScheduleLoaded;
|
||||||
_countdownTimer?.cancel();
|
|
||||||
|
|
||||||
if (event.mode == ScheduleModes.countdown) {
|
final success = await RemoteControlDeviceService().controlDevice(
|
||||||
emit(currentState.copyWith(
|
deviceUuid: deviceId,
|
||||||
countdownHours: 0,
|
status: Status(
|
||||||
countdownMinutes: 0,
|
code: 'countdown_1',
|
||||||
isCountdownActive: false,
|
value: 0,
|
||||||
countdownRemaining: Duration.zero,
|
),
|
||||||
));
|
);
|
||||||
} else if (event.mode == ScheduleModes.inching) {
|
if (success) {
|
||||||
emit(currentState.copyWith(
|
_countdownTimer?.cancel();
|
||||||
inchingHours: 0,
|
if (event.mode == ScheduleModes.countdown) {
|
||||||
inchingMinutes: 0,
|
emit(currentState.copyWith(
|
||||||
isInchingActive: false,
|
countdownHours: 0,
|
||||||
countdownRemaining: Duration.zero,
|
countdownMinutes: 0,
|
||||||
));
|
isCountdownActive: false,
|
||||||
|
countdownRemaining: Duration.zero,
|
||||||
|
));
|
||||||
|
} else if (event.mode == ScheduleModes.inching) {
|
||||||
|
emit(currentState.copyWith(
|
||||||
|
inchingHours: 0,
|
||||||
|
inchingMinutes: 0,
|
||||||
|
isInchingActive: false,
|
||||||
|
countdownRemaining: Duration.zero,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emit(const ScheduleError('Failed to stop schedule'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -241,16 +252,14 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
|||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
if (state is ScheduleLoaded) {
|
if (state is ScheduleLoaded) {
|
||||||
final newSchedule = ScheduleEntry(
|
final dateTime = DateTime.parse(event.time);
|
||||||
|
final success = await DevicesManagementApi().postSchedule(
|
||||||
category: event.category,
|
category: event.category,
|
||||||
time: event.time,
|
deviceId: deviceId,
|
||||||
function: Status(code: 'switch_1', value: event.functionOn),
|
time: getTimeStampWithoutSeconds(dateTime).toString(),
|
||||||
|
code: 'switch_1',
|
||||||
|
value: event.functionOn,
|
||||||
days: event.selectedDays);
|
days: event.selectedDays);
|
||||||
final success = await DevicesManagementApi().addScheduleRecord(
|
|
||||||
newSchedule,
|
|
||||||
deviceId,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
add(const ScheduleGetEvent(category: 'switch_1'));
|
add(const ScheduleGetEvent(category: 'switch_1'));
|
||||||
} else {
|
} else {
|
||||||
@ -268,14 +277,14 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
|||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
if (state is ScheduleLoaded) {
|
if (state is ScheduleLoaded) {
|
||||||
|
final dateTime = DateTime.parse(event.time);
|
||||||
final updatedSchedule = ScheduleEntry(
|
final updatedSchedule = ScheduleEntry(
|
||||||
scheduleId: event.scheduleId,
|
scheduleId: event.scheduleId,
|
||||||
category: event.category,
|
category: event.category,
|
||||||
time: event.time,
|
time: getTimeStampWithoutSeconds(dateTime).toString(),
|
||||||
function: Status(code: 'switch_1', value: event.functionOn),
|
function: Status(code: 'switch_1', value: event.functionOn),
|
||||||
days: event.selectedDays,
|
days: event.selectedDays,
|
||||||
);
|
);
|
||||||
|
|
||||||
final success = await DevicesManagementApi().editScheduleRecord(
|
final success = await DevicesManagementApi().editScheduleRecord(
|
||||||
deviceId,
|
deviceId,
|
||||||
updatedSchedule,
|
updatedSchedule,
|
||||||
@ -299,10 +308,12 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
|||||||
try {
|
try {
|
||||||
if (state is ScheduleLoaded) {
|
if (state is ScheduleLoaded) {
|
||||||
final currentState = state as ScheduleLoaded;
|
final currentState = state as ScheduleLoaded;
|
||||||
|
|
||||||
final updatedSchedules = currentState.schedules.map((schedule) {
|
final updatedSchedules = currentState.schedules.map((schedule) {
|
||||||
if (schedule.scheduleId == event.scheduleId) {
|
if (schedule.scheduleId == event.scheduleId) {
|
||||||
return schedule.copyWith(
|
return schedule.copyWith(
|
||||||
function: Status(code: 'switch_1', value: event.functionOn),
|
function: Status(code: 'switch_1', value: event.functionOn),
|
||||||
|
enable: event.enable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
return schedule;
|
return schedule;
|
||||||
@ -491,10 +502,16 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
|||||||
try {
|
try {
|
||||||
final status =
|
final status =
|
||||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||||
|
print(status.status);
|
||||||
final deviceStatus =
|
final deviceStatus =
|
||||||
WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
||||||
|
|
||||||
final scheduleMode = deviceStatus.scheduleMode;
|
final scheduleMode =
|
||||||
|
deviceStatus.countdownHours > 0 || deviceStatus.countdownMinutes > 0
|
||||||
|
? ScheduleModes.countdown
|
||||||
|
: deviceStatus.inchingHours > 0 || deviceStatus.inchingMinutes > 0
|
||||||
|
? ScheduleModes.inching
|
||||||
|
: ScheduleModes.schedule;
|
||||||
final isCountdown = scheduleMode == ScheduleModes.countdown;
|
final isCountdown = scheduleMode == ScheduleModes.countdown;
|
||||||
final isInching = scheduleMode == ScheduleModes.inching;
|
final isInching = scheduleMode == ScheduleModes.inching;
|
||||||
|
|
||||||
@ -516,6 +533,10 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
|||||||
Duration.zero;
|
Duration.zero;
|
||||||
}
|
}
|
||||||
if (state is ScheduleLoaded) {
|
if (state is ScheduleLoaded) {
|
||||||
|
print('Updating existing state with fetched status');
|
||||||
|
print('scheduleMode: $scheduleMode');
|
||||||
|
print('countdownRemaining: $countdownRemaining');
|
||||||
|
print('isCountdownActive: $isCountdownActive');
|
||||||
final currentState = state as ScheduleLoaded;
|
final currentState = state as ScheduleLoaded;
|
||||||
emit(currentState.copyWith(
|
emit(currentState.copyWith(
|
||||||
scheduleMode: scheduleMode,
|
scheduleMode: scheduleMode,
|
||||||
@ -546,12 +567,54 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isCountdownActive && countdownRemaining != null) {
|
// if (isCountdownActive && countdownRemaining != null) {
|
||||||
_startCountdownTimer(emit, countdownRemaining);
|
// _startCountdownTimer(emit, countdownRemaining);
|
||||||
}
|
// }
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
emit(ScheduleError('Failed to fetch device status: $e'));
|
emit(ScheduleError('Failed to fetch device status: $e'));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String extractTime(String isoDateTime) {
|
||||||
|
// Example input: "2025-06-19T15:45:00.000"
|
||||||
|
return isoDateTime.split('T')[1].split('.')[0]; // gives "15:45:00"
|
||||||
|
}
|
||||||
|
|
||||||
|
int? getTimeStampWithoutSeconds(DateTime? dateTime) {
|
||||||
|
if (dateTime == null) return null;
|
||||||
|
DateTime dateTimeWithoutSeconds = DateTime(dateTime.year, dateTime.month,
|
||||||
|
dateTime.day, dateTime.hour, dateTime.minute);
|
||||||
|
return dateTimeWithoutSeconds.millisecondsSinceEpoch ~/ 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Future <void> _updateScheduleEvent(
|
||||||
|
// StatusUpdatedScheduleEvent event,
|
||||||
|
// Emitter<ScheduleState> emit,
|
||||||
|
// ) async {
|
||||||
|
// if (state is ScheduleLoaded) {
|
||||||
|
// final currentState = state as ScheduleLoaded;
|
||||||
|
|
||||||
|
// final updatedSchedules = currentState.schedules.map((schedule) {
|
||||||
|
// if (schedule.scheduleId == event.scheduleId) {
|
||||||
|
// return schedule.copyWith(
|
||||||
|
// function: Status(code: 'switch_1', value: event.functionOn),
|
||||||
|
// enable: event.enable,
|
||||||
|
// );
|
||||||
|
// }
|
||||||
|
// return schedule;
|
||||||
|
// }).toList();
|
||||||
|
|
||||||
|
// bool success = await DevicesManagementApi().updateScheduleRecord(
|
||||||
|
// enable: event.enable,
|
||||||
|
// uuid: currentState.status.uuid,
|
||||||
|
// scheduleId: event.scheduleId,
|
||||||
|
// );
|
||||||
|
|
||||||
|
// if (success) {
|
||||||
|
// emit(currentState.copyWith(schedules: updatedSchedules));
|
||||||
|
// } else {
|
||||||
|
// emit(currentState);
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
@ -68,7 +68,7 @@ class ScheduleGetEvent extends ScheduleEvent {
|
|||||||
|
|
||||||
class ScheduleAddEvent extends ScheduleEvent {
|
class ScheduleAddEvent extends ScheduleEvent {
|
||||||
final String category;
|
final String category;
|
||||||
final String time;
|
final String time;
|
||||||
final List<String> selectedDays;
|
final List<String> selectedDays;
|
||||||
final bool functionOn;
|
final bool functionOn;
|
||||||
|
|
||||||
@ -219,3 +219,12 @@ class DeleteScheduleEvent extends ScheduleEvent {
|
|||||||
@override
|
@override
|
||||||
List<Object> get props => [scheduleId];
|
List<Object> get props => [scheduleId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class StatusUpdatedScheduleEvent extends ScheduleEvent {
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
const StatusUpdatedScheduleEvent(this.id);
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Object> get props => [id];
|
||||||
|
}
|
||||||
|
@ -160,28 +160,26 @@ class _ScheduleTableView extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Center(
|
Center(
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
|
behavior: HitTestBehavior.opaque,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
///TODO: Implement toggle functionality
|
context.read<ScheduleBloc>().add(
|
||||||
|
ScheduleUpdateEntryEvent(
|
||||||
// Toggle enabled state using ScheduleBloc
|
scheduleId: schedule.scheduleId,
|
||||||
// context.read<ScheduleBloc>().add(
|
functionOn: schedule.function.value,
|
||||||
// UpdateScheduleEvent(
|
enable: !schedule.enable,
|
||||||
// scheduleId: schedule.scheduleId,
|
|
||||||
// functionOn: schedule.function.value,
|
|
||||||
// enable: !schedule.enable,
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
},
|
|
||||||
child: SizedBox(
|
|
||||||
width: 24,
|
|
||||||
height: 24,
|
|
||||||
child: schedule.enable
|
|
||||||
? const Icon(Icons.radio_button_checked,
|
|
||||||
color: ColorsManager.blueColor)
|
|
||||||
: const Icon(
|
|
||||||
Icons.radio_button_unchecked,
|
|
||||||
color: ColorsManager.grayColor,
|
|
||||||
),
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
child: schedule.enable
|
||||||
|
? const Icon(Icons.radio_button_checked,
|
||||||
|
color: ColorsManager.blueColor)
|
||||||
|
: const Icon(Icons.radio_button_unchecked,
|
||||||
|
color: ColorsManager.grayColor),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -202,7 +200,6 @@ class _ScheduleTableView extends StatelessWidget {
|
|||||||
schedule: ScheduleEntry.fromScheduleModel(schedule),
|
schedule: ScheduleEntry.fromScheduleModel(schedule),
|
||||||
isEdit: true,
|
isEdit: true,
|
||||||
).then((updatedSchedule) {
|
).then((updatedSchedule) {
|
||||||
print('updatedSchedule : $updatedSchedule');
|
|
||||||
if (updatedSchedule != null) {
|
if (updatedSchedule != null) {
|
||||||
context.read<ScheduleBloc>().add(
|
context.read<ScheduleBloc>().add(
|
||||||
ScheduleEditEvent(
|
ScheduleEditEvent(
|
||||||
@ -225,12 +222,38 @@ class _ScheduleTableView extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
context.read<ScheduleBloc>().add(
|
final confirmed = await showDialog<bool>(
|
||||||
DeleteScheduleEvent(
|
context: context,
|
||||||
schedule.scheduleId,
|
builder: (BuildContext dialogContext) {
|
||||||
),
|
return AlertDialog(
|
||||||
|
title: const Text('Confirm Delete'),
|
||||||
|
content: const Text(
|
||||||
|
'Are you sure you want to delete this schedule?'),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
Navigator.of(dialogContext).pop(false),
|
||||||
|
child: Text('Cancel'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () =>
|
||||||
|
Navigator.of(dialogContext).pop(true),
|
||||||
|
child: const Text(
|
||||||
|
'Delete',
|
||||||
|
style: TextStyle(color: Colors.red),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (confirmed == true) {
|
||||||
|
context.read<ScheduleBloc>().add(
|
||||||
|
ScheduleDeleteEvent(schedule.scheduleId),
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
child: Text(
|
child: Text(
|
||||||
'Delete',
|
'Delete',
|
||||||
@ -239,7 +262,7 @@ class _ScheduleTableView extends StatelessWidget {
|
|||||||
.bodySmall!
|
.bodySmall!
|
||||||
.copyWith(color: ColorsManager.blueColor),
|
.copyWith(color: ColorsManager.blueColor),
|
||||||
),
|
),
|
||||||
),
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@ -248,7 +271,6 @@ class _ScheduleTableView extends StatelessWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _getSelectedDays(List<bool> selectedDays) {
|
String _getSelectedDays(List<bool> selectedDays) {
|
||||||
// Use the same order as in ScheduleDialogHelper
|
|
||||||
const days = ScheduleDialogHelper.allDays;
|
const days = ScheduleDialogHelper.allDays;
|
||||||
return selectedDays
|
return selectedDays
|
||||||
.asMap()
|
.asMap()
|
||||||
@ -257,6 +279,4 @@ class _ScheduleTableView extends StatelessWidget {
|
|||||||
.map((entry) => days[entry.key])
|
.map((entry) => days[entry.key])
|
||||||
.join(', ');
|
.join(', ');
|
||||||
}
|
}
|
||||||
|
|
||||||
// Removed allDays from here as it is now in ScheduleDialogHelper
|
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:convert';
|
||||||
import 'dart:core';
|
import 'dart:core';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_reports.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_reports.dart';
|
||||||
@ -386,4 +387,34 @@ class DevicesManagementApi {
|
|||||||
);
|
);
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<bool> postSchedule({
|
||||||
|
required String category,
|
||||||
|
required String deviceId,
|
||||||
|
required String time,
|
||||||
|
required String code,
|
||||||
|
required bool value,
|
||||||
|
required List<String> days,
|
||||||
|
}) async {
|
||||||
|
final response = await HTTPService().post(
|
||||||
|
path: ApiEndpoints.saveSchedule.replaceAll('{deviceUuid}', deviceId),
|
||||||
|
showServerMessage: false,
|
||||||
|
body: jsonEncode(
|
||||||
|
{
|
||||||
|
'category': category,
|
||||||
|
'time': time,
|
||||||
|
'function': {
|
||||||
|
'code': code,
|
||||||
|
'value': value,
|
||||||
|
},
|
||||||
|
'days': days
|
||||||
|
},
|
||||||
|
),
|
||||||
|
expectedResponseModel: (json) {
|
||||||
|
return json['success'] ?? false;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return response;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -136,4 +136,5 @@ abstract class ApiEndpoints {
|
|||||||
|
|
||||||
static const String assignDeviceToRoom =
|
static const String assignDeviceToRoom =
|
||||||
'/projects/{projectUuid}/communities/{communityUuid}/spaces/{spaceUuid}/subspaces/{subSpaceUuid}/devices/{deviceUuid}';
|
'/projects/{projectUuid}/communities/{communityUuid}/spaces/{spaceUuid}/subspaces/{subSpaceUuid}/devices/{deviceUuid}';
|
||||||
|
static const String saveSchedule = '/schedule/{deviceUuid}';
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user