mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-10 15:17:31 +00:00
@ -35,25 +35,15 @@ class TwoGangDeviceControlView extends StatelessWidget
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildStatusControls(BuildContext context, TwoGangStatusModel status) {
|
Widget _buildStatusControls(BuildContext context, TwoGangStatusModel status) {
|
||||||
final isExtraLarge = isExtraLargeScreenSize(context);
|
return Center(
|
||||||
final isLarge = isLargeScreenSize(context);
|
child: Wrap(
|
||||||
final isMedium = isMediumScreenSize(context);
|
alignment: WrapAlignment.center,
|
||||||
return GridView(
|
spacing: 12,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 50),
|
runSpacing: 12,
|
||||||
shrinkWrap: true,
|
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
|
||||||
crossAxisCount: isLarge || isExtraLarge
|
|
||||||
? 3
|
|
||||||
: isMedium
|
|
||||||
? 2
|
|
||||||
: 1,
|
|
||||||
mainAxisExtent: 140,
|
|
||||||
crossAxisSpacing: 12,
|
|
||||||
mainAxisSpacing: 12,
|
|
||||||
),
|
|
||||||
children: [
|
children: [
|
||||||
ToggleWidget(
|
SizedBox(
|
||||||
|
width: 200,
|
||||||
|
child: ToggleWidget(
|
||||||
value: status.switch1,
|
value: status.switch1,
|
||||||
code: 'switch_1',
|
code: 'switch_1',
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
@ -66,7 +56,10 @@ class TwoGangDeviceControlView extends StatelessWidget
|
|||||||
));
|
));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
ToggleWidget(
|
),
|
||||||
|
SizedBox(
|
||||||
|
width: 200,
|
||||||
|
child: ToggleWidget(
|
||||||
value: status.switch2,
|
value: status.switch2,
|
||||||
code: 'switch_2',
|
code: 'switch_2',
|
||||||
deviceId: deviceId,
|
deviceId: deviceId,
|
||||||
@ -79,7 +72,9 @@ class TwoGangDeviceControlView extends StatelessWidget
|
|||||||
));
|
));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ import 'package:bloc/bloc.dart';
|
|||||||
import 'package:equatable/equatable.dart';
|
import 'package:equatable/equatable.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_entry.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart';
|
import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart';
|
||||||
import 'package:syncrow_web/services/devices_mang_api.dart';
|
import 'package:syncrow_web/services/devices_mang_api.dart';
|
||||||
@ -487,10 +488,8 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
emit(ScheduleLoadingState());
|
emit(ScheduleLoadingState());
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// List<ScheduleModel> schedules = await DevicesManagementApi()
|
List<ScheduleModel> schedules = await DevicesManagementApi()
|
||||||
// .getDeviceSchedules(deviceStatus.uuid, event.category);
|
.getDeviceSchedules(deviceStatus.uuid, event.category);
|
||||||
|
|
||||||
List<ScheduleModel> schedules = const [];
|
|
||||||
|
|
||||||
emit(WaterHeaterDeviceStatusLoaded(
|
emit(WaterHeaterDeviceStatusLoaded(
|
||||||
deviceStatus,
|
deviceStatus,
|
||||||
@ -513,7 +512,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||||
|
|
||||||
ScheduleModel newSchedule = ScheduleModel(
|
ScheduleEntry newSchedule = ScheduleEntry(
|
||||||
category: event.category,
|
category: event.category,
|
||||||
time: formatTimeOfDayToISO(event.time),
|
time: formatTimeOfDayToISO(event.time),
|
||||||
function: Status(code: 'switch_1', value: event.functionOn),
|
function: Status(code: 'switch_1', value: event.functionOn),
|
||||||
@ -526,10 +525,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
.addScheduleRecord(newSchedule, currentState.status.uuid);
|
.addScheduleRecord(newSchedule, currentState.status.uuid);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
final updatedSchedules =
|
add(GetSchedulesEvent(category: 'switch_1', uuid: deviceStatus.uuid));
|
||||||
List<ScheduleModel>.from(currentState.schedules)..add(newSchedule);
|
|
||||||
|
|
||||||
emit(currentState.copyWith(schedules: updatedSchedules));
|
|
||||||
} else {
|
} else {
|
||||||
emit(currentState);
|
emit(currentState);
|
||||||
//emit(const WaterHeaterFailedState(error: 'Failed to add schedule.'));
|
//emit(const WaterHeaterFailedState(error: 'Failed to add schedule.'));
|
||||||
@ -544,23 +540,23 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
if (state is WaterHeaterDeviceStatusLoaded) {
|
if (state is WaterHeaterDeviceStatusLoaded) {
|
||||||
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
final currentState = state as WaterHeaterDeviceStatusLoaded;
|
||||||
|
|
||||||
ScheduleModel updatedSchedule = currentState.schedules[event.index]
|
final updatedSchedules = currentState.schedules.map((schedule) {
|
||||||
.copyWith(
|
if (schedule.scheduleId == event.scheduleId) {
|
||||||
function: Status(code: 'switch_1', value: event.functionOn));
|
return schedule.copyWith(
|
||||||
|
function: Status(code: 'switch_1', value: event.functionOn),
|
||||||
// emit(ScheduleLoadingState());
|
enable: event.enable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return schedule;
|
||||||
|
}).toList();
|
||||||
|
|
||||||
bool success = await DevicesManagementApi().updateScheduleRecord(
|
bool success = await DevicesManagementApi().updateScheduleRecord(
|
||||||
enable: event.functionOn,
|
enable: event.enable,
|
||||||
uuid: currentState.status.uuid,
|
uuid: currentState.status.uuid,
|
||||||
scheduleId: event.scheduleId,
|
scheduleId: event.scheduleId,
|
||||||
);
|
);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
final updatedSchedules =
|
|
||||||
List<ScheduleModel>.from(currentState.schedules)
|
|
||||||
..[event.index] = updatedSchedule;
|
|
||||||
|
|
||||||
emit(currentState.copyWith(schedules: updatedSchedules));
|
emit(currentState.copyWith(schedules: updatedSchedules));
|
||||||
} else {
|
} else {
|
||||||
emit(currentState);
|
emit(currentState);
|
||||||
@ -582,9 +578,9 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
|
|||||||
.deleteScheduleRecord(currentState.status.uuid, event.scheduleId);
|
.deleteScheduleRecord(currentState.status.uuid, event.scheduleId);
|
||||||
|
|
||||||
if (success) {
|
if (success) {
|
||||||
final updatedSchedules =
|
final updatedSchedules = currentState.schedules
|
||||||
List<ScheduleModel>.from(currentState.schedules)
|
.where((schedule) => schedule.scheduleId != event.scheduleId)
|
||||||
..removeAt(event.index);
|
.toList();
|
||||||
|
|
||||||
emit(currentState.copyWith(schedules: updatedSchedules));
|
emit(currentState.copyWith(schedules: updatedSchedules));
|
||||||
} else {
|
} else {
|
||||||
|
@ -82,23 +82,22 @@ final class DeleteScheduleEvent extends WaterHeaterEvent {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final class UpdateScheduleEntryEvent extends WaterHeaterEvent {
|
final class UpdateScheduleEntryEvent extends WaterHeaterEvent {
|
||||||
final bool functionOn;
|
final bool enable;
|
||||||
final String category;
|
final dynamic functionOn;
|
||||||
final String deviceId;
|
final String deviceId;
|
||||||
final int index;
|
final int index;
|
||||||
final String scheduleId;
|
final String scheduleId;
|
||||||
|
|
||||||
const UpdateScheduleEntryEvent({
|
const UpdateScheduleEntryEvent({
|
||||||
|
required this.enable,
|
||||||
required this.functionOn,
|
required this.functionOn,
|
||||||
required this.category,
|
|
||||||
required this.deviceId,
|
required this.deviceId,
|
||||||
required this.scheduleId,
|
required this.scheduleId,
|
||||||
required this.index,
|
required this.index,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
List<Object?> get props =>
|
List<Object?> get props => [enable, deviceId, scheduleId];
|
||||||
[category, functionOn, deviceId, scheduleId, index];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class GetSchedulesEvent extends WaterHeaterEvent {
|
class GetSchedulesEvent extends WaterHeaterEvent {
|
||||||
|
@ -118,7 +118,7 @@ class ScheduleDialogHelper {
|
|||||||
_buildDayCheckboxes(context, state.selectedDays,
|
_buildDayCheckboxes(context, state.selectedDays,
|
||||||
isEdit: isEdit),
|
isEdit: isEdit),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildFunctionSwitch(context, state.functionOn),
|
_buildFunctionSwitch(context, state.functionOn, isEdit),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
@ -143,16 +143,10 @@ class ScheduleDialogHelper {
|
|||||||
onPressed: () {
|
onPressed: () {
|
||||||
if (state.selectedTime != null) {
|
if (state.selectedTime != null) {
|
||||||
if (state.isEditing && index != null) {
|
if (state.isEditing && index != null) {
|
||||||
bloc.add(UpdateScheduleEntryEvent(
|
return;
|
||||||
index: index,
|
|
||||||
deviceId: state.status.uuid,
|
|
||||||
category: 'kg',
|
|
||||||
functionOn: state.functionOn,
|
|
||||||
scheduleId: state.schedules[index].scheduleId,
|
|
||||||
));
|
|
||||||
} else {
|
} else {
|
||||||
bloc.add(AddScheduleEvent(
|
bloc.add(AddScheduleEvent(
|
||||||
category: 'kg',
|
category: 'switch_1',
|
||||||
time: state.selectedTime!,
|
time: state.selectedTime!,
|
||||||
selectedDays: state.selectedDays,
|
selectedDays: state.selectedDays,
|
||||||
functionOn: state.functionOn,
|
functionOn: state.functionOn,
|
||||||
@ -177,8 +171,15 @@ class ScheduleDialogHelper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static TimeOfDay _convertStringToTimeOfDay(String timeString) {
|
static TimeOfDay _convertStringToTimeOfDay(String timeString) {
|
||||||
final DateTime dateTime = DateTime.parse(timeString);
|
final regex = RegExp(r'^(\d{2}):(\d{2})$');
|
||||||
return TimeOfDay(hour: dateTime.hour, minute: dateTime.minute);
|
final match = regex.firstMatch(timeString);
|
||||||
|
if (match != null) {
|
||||||
|
final hour = int.parse(match.group(1)!);
|
||||||
|
final minute = int.parse(match.group(2)!);
|
||||||
|
return TimeOfDay(hour: hour, minute: minute);
|
||||||
|
} else {
|
||||||
|
throw const FormatException('Invalid time format');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static List<bool> _convertDaysStringToBooleans(List<String> selectedDays) {
|
static List<bool> _convertDaysStringToBooleans(List<String> selectedDays) {
|
||||||
@ -220,7 +221,8 @@ class ScheduleDialogHelper {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static Widget _buildFunctionSwitch(BuildContext context, bool isOn) {
|
static Widget _buildFunctionSwitch(
|
||||||
|
BuildContext context, bool isOn, bool? isEdit) {
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
@ -233,9 +235,13 @@ class ScheduleDialogHelper {
|
|||||||
value: true,
|
value: true,
|
||||||
groupValue: isOn,
|
groupValue: isOn,
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
|
if (isEdit == true) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
context
|
context
|
||||||
.read<WaterHeaterBloc>()
|
.read<WaterHeaterBloc>()
|
||||||
.add(const UpdateFunctionOnEvent(true));
|
.add(const UpdateFunctionOnEvent(true));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Text('On'),
|
const Text('On'),
|
||||||
@ -244,9 +250,13 @@ class ScheduleDialogHelper {
|
|||||||
value: false,
|
value: false,
|
||||||
groupValue: isOn,
|
groupValue: isOn,
|
||||||
onChanged: (bool? value) {
|
onChanged: (bool? value) {
|
||||||
|
if (isEdit == true) {
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
context
|
context
|
||||||
.read<WaterHeaterBloc>()
|
.read<WaterHeaterBloc>()
|
||||||
.add(const UpdateFunctionOnEvent(false));
|
.add(const UpdateFunctionOnEvent(false));
|
||||||
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Text('Off'),
|
const Text('Off'),
|
||||||
|
@ -1,19 +1,80 @@
|
|||||||
// import 'package:flutter/material.dart';
|
import 'dart:convert';
|
||||||
|
|
||||||
// class ScheduleEntry {
|
import 'package:flutter/foundation.dart';
|
||||||
// final List<bool> selectedDays;
|
|
||||||
// final TimeOfDay time;
|
|
||||||
// final bool functionOn;
|
|
||||||
// final String category;
|
|
||||||
|
|
||||||
// ScheduleEntry({
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||||
// required this.selectedDays,
|
|
||||||
// required this.time,
|
|
||||||
// required this.functionOn,
|
|
||||||
// required this.category,
|
|
||||||
// });
|
|
||||||
|
|
||||||
// @override
|
class ScheduleEntry {
|
||||||
// String toString() =>
|
final String category;
|
||||||
// 'ScheduleEntry(selectedDays: $selectedDays, time: $time, functionOn: $functionOn)';
|
final String time;
|
||||||
// }
|
final Status function;
|
||||||
|
final List<String> days;
|
||||||
|
|
||||||
|
ScheduleEntry({
|
||||||
|
required this.category,
|
||||||
|
required this.time,
|
||||||
|
required this.function,
|
||||||
|
required this.days,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ScheduleEntry(category: $category, time: $time, function: $function, days: $days)';
|
||||||
|
}
|
||||||
|
|
||||||
|
ScheduleEntry copyWith({
|
||||||
|
String? category,
|
||||||
|
String? time,
|
||||||
|
Status? function,
|
||||||
|
List<String>? days,
|
||||||
|
}) {
|
||||||
|
return ScheduleEntry(
|
||||||
|
category: category ?? this.category,
|
||||||
|
time: time ?? this.time,
|
||||||
|
function: function ?? this.function,
|
||||||
|
days: days ?? this.days,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Map<String, dynamic> toMap() {
|
||||||
|
return {
|
||||||
|
'category': category,
|
||||||
|
'time': time,
|
||||||
|
'function': function.toMap(),
|
||||||
|
'days': days,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
factory ScheduleEntry.fromMap(Map<String, dynamic> map) {
|
||||||
|
return ScheduleEntry(
|
||||||
|
category: map['category'] ?? '',
|
||||||
|
time: map['time'] ?? '',
|
||||||
|
function: Status.fromMap(map['function']),
|
||||||
|
days: List<String>.from(map['days']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
String toJson() => json.encode(toMap());
|
||||||
|
|
||||||
|
factory ScheduleEntry.fromJson(String source) =>
|
||||||
|
ScheduleEntry.fromMap(json.decode(source));
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
if (identical(this, other)) return true;
|
||||||
|
|
||||||
|
return other is ScheduleEntry &&
|
||||||
|
other.category == category &&
|
||||||
|
other.time == time &&
|
||||||
|
other.function == function &&
|
||||||
|
listEquals(other.days, days);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
return category.hashCode ^
|
||||||
|
time.hashCode ^
|
||||||
|
function.hashCode ^
|
||||||
|
days.hashCode;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,25 +9,30 @@ class ScheduleModel {
|
|||||||
final String time;
|
final String time;
|
||||||
final Status function;
|
final Status function;
|
||||||
final List<String> days;
|
final List<String> days;
|
||||||
final TimeOfDay? timeOfDay;
|
|
||||||
final List<bool>? selectedDays;
|
final List<bool>? selectedDays;
|
||||||
|
final String timezoneId;
|
||||||
|
final bool enable;
|
||||||
|
|
||||||
ScheduleModel({
|
ScheduleModel({
|
||||||
|
required this.scheduleId,
|
||||||
required this.category,
|
required this.category,
|
||||||
required this.time,
|
required this.time,
|
||||||
required this.function,
|
required this.function,
|
||||||
required this.days,
|
required this.days,
|
||||||
this.timeOfDay,
|
|
||||||
this.selectedDays,
|
this.selectedDays,
|
||||||
this.scheduleId = '',
|
required this.timezoneId,
|
||||||
|
required this.enable,
|
||||||
});
|
});
|
||||||
|
|
||||||
Map<String, dynamic> toMap() {
|
Map<String, dynamic> toMap() {
|
||||||
return {
|
return {
|
||||||
|
'scheduleId': scheduleId,
|
||||||
'category': category,
|
'category': category,
|
||||||
'time': time,
|
'time': time,
|
||||||
'function': function.toMap(),
|
'function': function.toMap(),
|
||||||
'days': days,
|
'days': days,
|
||||||
|
'timezoneId': timezoneId,
|
||||||
|
'enable': enable,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -37,11 +42,11 @@ class ScheduleModel {
|
|||||||
category: map['category'] ?? '',
|
category: map['category'] ?? '',
|
||||||
time: map['time'] ?? '',
|
time: map['time'] ?? '',
|
||||||
function: Status.fromMap(map['function']),
|
function: Status.fromMap(map['function']),
|
||||||
days: List<String>.from(map['days']),
|
days: List<String>.from(map['days'].map((e) => e.toString())),
|
||||||
timeOfDay:
|
timezoneId: map['timezoneId'] ?? '',
|
||||||
parseTimeOfDay(map['time']),
|
enable: map['enable'] ?? false,
|
||||||
selectedDays:
|
selectedDays: parseSelectedDays(
|
||||||
parseSelectedDays(map['days']),
|
List<String>.from(map['days'].map((e) => e.toString()))),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -51,22 +56,24 @@ class ScheduleModel {
|
|||||||
ScheduleModel.fromMap(json.decode(source));
|
ScheduleModel.fromMap(json.decode(source));
|
||||||
|
|
||||||
ScheduleModel copyWith({
|
ScheduleModel copyWith({
|
||||||
|
String? scheduleId,
|
||||||
String? category,
|
String? category,
|
||||||
String? time,
|
String? time,
|
||||||
Status? function,
|
Status? function,
|
||||||
List<String>? days,
|
List<String>? days,
|
||||||
TimeOfDay? timeOfDay,
|
|
||||||
List<bool>? selectedDays,
|
List<bool>? selectedDays,
|
||||||
String? scheduleId,
|
String? timezoneId,
|
||||||
|
bool? enable,
|
||||||
}) {
|
}) {
|
||||||
return ScheduleModel(
|
return ScheduleModel(
|
||||||
|
scheduleId: scheduleId ?? this.scheduleId,
|
||||||
category: category ?? this.category,
|
category: category ?? this.category,
|
||||||
time: time ?? this.time,
|
time: time ?? this.time,
|
||||||
function: function ?? this.function,
|
function: function ?? this.function,
|
||||||
days: days ?? this.days,
|
days: days ?? this.days,
|
||||||
timeOfDay: timeOfDay ?? this.timeOfDay,
|
|
||||||
selectedDays: selectedDays ?? this.selectedDays,
|
selectedDays: selectedDays ?? this.selectedDays,
|
||||||
scheduleId: scheduleId ?? this.scheduleId,
|
timezoneId: timezoneId ?? this.timezoneId,
|
||||||
|
enable: enable ?? this.enable,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +104,7 @@ class ScheduleModel {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ScheduleModel(category: $category, time: $time, function: $function, days: $days, timeOfDay: $timeOfDay, selectedDays: $selectedDays)';
|
return 'ScheduleModel(category: $category, time: $time, function: $function, days: $days, selectedDays: $selectedDays)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -109,7 +116,7 @@ class ScheduleModel {
|
|||||||
other.time == time &&
|
other.time == time &&
|
||||||
other.function == function &&
|
other.function == function &&
|
||||||
listEquals(other.days, days) &&
|
listEquals(other.days, days) &&
|
||||||
timeOfDay == other.timeOfDay &&
|
// timeOfDay == other.timeOfDay &&
|
||||||
listEquals(other.selectedDays, selectedDays);
|
listEquals(other.selectedDays, selectedDays);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +126,7 @@ class ScheduleModel {
|
|||||||
time.hashCode ^
|
time.hashCode ^
|
||||||
function.hashCode ^
|
function.hashCode ^
|
||||||
days.hashCode ^
|
days.hashCode ^
|
||||||
timeOfDay.hashCode ^
|
// timeOfDay.hashCode ^
|
||||||
selectedDays.hashCode;
|
selectedDays.hashCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -56,8 +56,7 @@ class _BuildScheduleViewState extends State<BuildScheduleView> {
|
|||||||
context,
|
context,
|
||||||
schedule: null,
|
schedule: null,
|
||||||
index: null,
|
index: null,
|
||||||
isEdit: false
|
isEdit: false),
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (state.scheduleMode == ScheduleModes.countdown ||
|
if (state.scheduleMode == ScheduleModes.countdown ||
|
||||||
state.scheduleMode == ScheduleModes.inching)
|
state.scheduleMode == ScheduleModes.inching)
|
||||||
@ -80,15 +79,31 @@ class _BuildScheduleViewState extends State<BuildScheduleView> {
|
|||||||
if (state.scheduleMode != ScheduleModes.countdown &&
|
if (state.scheduleMode != ScheduleModes.countdown &&
|
||||||
state.scheduleMode != ScheduleModes.inching)
|
state.scheduleMode != ScheduleModes.inching)
|
||||||
ScheduleModeButtons(
|
ScheduleModeButtons(
|
||||||
onSave: () {},
|
onSave: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (state is WaterHeaterLoadingState) {
|
if (state is WaterHeaterLoadingState) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const SizedBox(
|
||||||
|
height: 200,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
ScheduleHeader(),
|
||||||
|
SizedBox(
|
||||||
|
height: 20,
|
||||||
|
),
|
||||||
|
Center(child: CircularProgressIndicator()),
|
||||||
|
],
|
||||||
|
));
|
||||||
}
|
}
|
||||||
return const SizedBox();
|
return const SizedBox(
|
||||||
|
height: 200,
|
||||||
|
child: ScheduleHeader(),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -72,7 +72,7 @@ class ScheduleModeSelector extends StatelessWidget {
|
|||||||
if (value == ScheduleModes.schedule) {
|
if (value == ScheduleModes.schedule) {
|
||||||
context.read<WaterHeaterBloc>().add(
|
context.read<WaterHeaterBloc>().add(
|
||||||
GetSchedulesEvent(
|
GetSchedulesEvent(
|
||||||
category: 'kg',
|
category: 'switch_1',
|
||||||
uuid: state.status.uuid,
|
uuid: state.status.uuid,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -1,76 +1,76 @@
|
|||||||
import 'package:flutter/material.dart';
|
// import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
// import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
||||||
import 'package:syncrow_web/utils/format_date_time.dart';
|
// import 'package:syncrow_web/utils/format_date_time.dart';
|
||||||
import 'package:syncrow_web/utils/color_manager.dart';
|
// import 'package:syncrow_web/utils/color_manager.dart';
|
||||||
|
|
||||||
class ScheduleRowWidget extends StatelessWidget {
|
// class ScheduleRowWidget extends StatelessWidget {
|
||||||
final ScheduleModel schedule;
|
// final ScheduleModel schedule;
|
||||||
final int index;
|
// final int index;
|
||||||
final Function onEdit;
|
// final Function onEdit;
|
||||||
final Function onDelete;
|
// final Function onDelete;
|
||||||
|
|
||||||
const ScheduleRowWidget({
|
// const ScheduleRowWidget({
|
||||||
super.key,
|
// super.key,
|
||||||
required this.schedule,
|
// required this.schedule,
|
||||||
required this.index,
|
// required this.index,
|
||||||
required this.onEdit,
|
// required this.onEdit,
|
||||||
required this.onDelete,
|
// required this.onDelete,
|
||||||
});
|
// });
|
||||||
|
|
||||||
@override
|
// @override
|
||||||
Widget build(BuildContext context) {
|
// Widget build(BuildContext context) {
|
||||||
return Table(
|
// return Table(
|
||||||
border: TableBorder.all(color: ColorsManager.graysColor),
|
// border: TableBorder.all(color: ColorsManager.graysColor),
|
||||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
// defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||||
children: [
|
// children: [
|
||||||
TableRow(
|
// TableRow(
|
||||||
children: [
|
// children: [
|
||||||
Center(
|
// Center(
|
||||||
child: schedule.function.value
|
// child: schedule.enable
|
||||||
? const Icon(Icons.radio_button_checked,
|
// ? const Icon(Icons.radio_button_checked,
|
||||||
color: ColorsManager.blueColor)
|
// color: ColorsManager.blueColor)
|
||||||
: const Icon(Icons.radio_button_unchecked),
|
// : const Icon(Icons.radio_button_unchecked),
|
||||||
),
|
// ),
|
||||||
Center(child: Text(_getSelectedDays(schedule.selectedDays ?? []))),
|
// Center(child: Text(_getSelectedDays(schedule.selectedDays ?? []))),
|
||||||
Center(child: Text(formatIsoStringToTime(schedule.time))),
|
// Center(child: Text(formatIsoStringToTime(schedule.time, context))),
|
||||||
Center(child: Text(schedule.function.value ? 'On' : 'Off')),
|
// Center(child: Text(schedule.enable ? 'On' : 'Off')),
|
||||||
Center(
|
// Center(
|
||||||
child: Wrap(
|
// child: Wrap(
|
||||||
runAlignment: WrapAlignment.center,
|
// runAlignment: WrapAlignment.center,
|
||||||
children: [
|
// children: [
|
||||||
TextButton(
|
// TextButton(
|
||||||
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
// style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
||||||
onPressed: () => onEdit(),
|
// onPressed: () => onEdit(),
|
||||||
child: const Text(
|
// child: const Text(
|
||||||
'Edit',
|
// 'Edit',
|
||||||
style: TextStyle(color: ColorsManager.blueColor),
|
// style: TextStyle(color: ColorsManager.blueColor),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
TextButton(
|
// TextButton(
|
||||||
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
// style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
||||||
onPressed: () => onDelete(),
|
// onPressed: () => onDelete(),
|
||||||
child: const Text(
|
// child: const Text(
|
||||||
'Delete',
|
// 'Delete',
|
||||||
style: TextStyle(color: ColorsManager.blueColor),
|
// style: TextStyle(color: ColorsManager.blueColor),
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
),
|
// ),
|
||||||
],
|
// ],
|
||||||
);
|
// );
|
||||||
}
|
// }
|
||||||
|
|
||||||
String _getSelectedDays(List<bool> selectedDays) {
|
// String _getSelectedDays(List<bool> selectedDays) {
|
||||||
final days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
// final days = ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
|
||||||
List<String> selectedDaysStr = [];
|
// List<String> selectedDaysStr = [];
|
||||||
for (int i = 0; i < selectedDays.length; i++) {
|
// for (int i = 0; i < selectedDays.length; i++) {
|
||||||
if (selectedDays[i]) {
|
// if (selectedDays[i]) {
|
||||||
selectedDaysStr.add(days[i]);
|
// selectedDaysStr.add(days[i]);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
return selectedDaysStr.join(', ');
|
// return selectedDaysStr.join(', ');
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
@ -68,7 +68,9 @@ class ScheduleTableWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
child: _buildTableBody(state, context));
|
child: _buildTableBody(state, context));
|
||||||
}
|
}
|
||||||
return const SizedBox();
|
return const SizedBox(
|
||||||
|
height: 200,
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@ -107,15 +109,18 @@ class ScheduleTableWidget extends StatelessWidget {
|
|||||||
|
|
||||||
Widget _buildTableBody(
|
Widget _buildTableBody(
|
||||||
WaterHeaterDeviceStatusLoaded state, BuildContext context) {
|
WaterHeaterDeviceStatusLoaded state, BuildContext context) {
|
||||||
return SingleChildScrollView(
|
return SizedBox(
|
||||||
|
height: 200,
|
||||||
|
child: SingleChildScrollView(
|
||||||
child: Table(
|
child: Table(
|
||||||
border: TableBorder.all(color: ColorsManager.graysColor),
|
border: TableBorder.all(color: ColorsManager.graysColor),
|
||||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||||
children: [
|
children: [
|
||||||
for (int i = 0; i < state.schedules.length; i++)
|
for (int i = 0; i < state.schedules.length; i++)
|
||||||
_buildScheduleRow(state.schedules[i], i, context),
|
_buildScheduleRow(state.schedules[i], i, context, state),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -134,19 +139,38 @@ class ScheduleTableWidget extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
TableRow _buildScheduleRow(
|
TableRow _buildScheduleRow(ScheduleModel schedule, int index,
|
||||||
ScheduleModel schedule, int index, BuildContext context) {
|
BuildContext context, WaterHeaterDeviceStatusLoaded state) {
|
||||||
return TableRow(
|
return TableRow(
|
||||||
children: [
|
children: [
|
||||||
Center(
|
Center(
|
||||||
child: schedule.function.value
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
context.read<WaterHeaterBloc>().add(UpdateScheduleEntryEvent(
|
||||||
|
index: index,
|
||||||
|
enable: !schedule.enable,
|
||||||
|
scheduleId: schedule.scheduleId,
|
||||||
|
deviceId: state.status.uuid,
|
||||||
|
functionOn: schedule.function.value,
|
||||||
|
));
|
||||||
|
},
|
||||||
|
child: SizedBox(
|
||||||
|
width: 24,
|
||||||
|
height: 24,
|
||||||
|
child: schedule.enable
|
||||||
? const Icon(Icons.radio_button_checked,
|
? const Icon(Icons.radio_button_checked,
|
||||||
color: ColorsManager.blueColor)
|
color: ColorsManager.blueColor)
|
||||||
: const Icon(Icons.radio_button_unchecked)),
|
: const Icon(
|
||||||
|
Icons.radio_button_unchecked,
|
||||||
|
color: ColorsManager.grayColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
Center(
|
Center(
|
||||||
child: Text(_getSelectedDays(
|
child: Text(_getSelectedDays(
|
||||||
ScheduleModel.parseSelectedDays(schedule.days)))),
|
ScheduleModel.parseSelectedDays(schedule.days)))),
|
||||||
Center(child: Text(formatIsoStringToTime(schedule.time))),
|
Center(child: Text(formatIsoStringToTime(schedule.time, context))),
|
||||||
Center(child: Text(schedule.function.value ? 'On' : 'Off')),
|
Center(child: Text(schedule.function.value ? 'On' : 'Off')),
|
||||||
Center(
|
Center(
|
||||||
child: Wrap(
|
child: Wrap(
|
||||||
|
@ -3,6 +3,7 @@ import 'package:syncrow_web/pages/device_managment/all_devices/models/device_rep
|
|||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/device_status.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/devices_model.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
|
import 'package:syncrow_web/pages/device_managment/all_devices/models/factory_reset_model.dart';
|
||||||
|
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_entry.dart';
|
||||||
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
import 'package:syncrow_web/pages/device_managment/water_heater/models/schedule_model.dart';
|
||||||
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
import 'package:syncrow_web/pages/visitor_password/model/device_model.dart';
|
||||||
import 'package:syncrow_web/services/api/http_service.dart';
|
import 'package:syncrow_web/services/api/http_service.dart';
|
||||||
@ -179,7 +180,7 @@ class DevicesManagementApi {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> addScheduleRecord(
|
Future<bool> addScheduleRecord(
|
||||||
ScheduleModel sendSchedule, String uuid) async {
|
ScheduleEntry sendSchedule, String uuid) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().post(
|
final response = await HTTPService().post(
|
||||||
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),
|
path: ApiEndpoints.scheduleByDeviceId.replaceAll('{deviceUuid}', uuid),
|
||||||
@ -200,14 +201,14 @@ class DevicesManagementApi {
|
|||||||
String uuid, String category) async {
|
String uuid, String category) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().get(
|
final response = await HTTPService().get(
|
||||||
path: ApiEndpoints.scheduleByDeviceId
|
path: ApiEndpoints.getScheduleByDeviceId
|
||||||
.replaceAll('{deviceUuid}', uuid)
|
.replaceAll('{deviceUuid}', uuid)
|
||||||
.replaceAll('{category}', category),
|
.replaceAll('{category}', category),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
expectedResponseModel: (json) {
|
expectedResponseModel: (json) {
|
||||||
List<ScheduleModel> schedules = [];
|
List<ScheduleModel> schedules = [];
|
||||||
for (var schedule in json['schedules']) {
|
for (var schedule in json) {
|
||||||
schedules.add(ScheduleModel.fromJson(schedule));
|
schedules.add(ScheduleModel.fromMap(schedule));
|
||||||
}
|
}
|
||||||
return schedules;
|
return schedules;
|
||||||
},
|
},
|
||||||
@ -225,7 +226,7 @@ class DevicesManagementApi {
|
|||||||
required String scheduleId}) async {
|
required String scheduleId}) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().put(
|
final response = await HTTPService().put(
|
||||||
path: ApiEndpoints.scheduleByDeviceId
|
path: ApiEndpoints.updateScheduleByDeviceId
|
||||||
.replaceAll('{deviceUuid}', uuid)
|
.replaceAll('{deviceUuid}', uuid)
|
||||||
.replaceAll('{scheduleUuid}', scheduleId),
|
.replaceAll('{scheduleUuid}', scheduleId),
|
||||||
body: {
|
body: {
|
||||||
@ -246,7 +247,7 @@ class DevicesManagementApi {
|
|||||||
Future<bool> deleteScheduleRecord(String uuid, String scheduleId) async {
|
Future<bool> deleteScheduleRecord(String uuid, String scheduleId) async {
|
||||||
try {
|
try {
|
||||||
final response = await HTTPService().delete(
|
final response = await HTTPService().delete(
|
||||||
path: ApiEndpoints.scheduleByDeviceId
|
path: ApiEndpoints.deleteScheduleByDeviceId
|
||||||
.replaceAll('{deviceUuid}', uuid)
|
.replaceAll('{deviceUuid}', uuid)
|
||||||
.replaceAll('{scheduleUuid}', scheduleId),
|
.replaceAll('{scheduleUuid}', scheduleId),
|
||||||
showServerMessage: true,
|
showServerMessage: true,
|
||||||
|
@ -25,7 +25,14 @@ String formatTimeOfDayToISO(TimeOfDay time, {DateTime? currentDate}) {
|
|||||||
return dateTime.toUtc().toIso8601String();
|
return dateTime.toUtc().toIso8601String();
|
||||||
}
|
}
|
||||||
|
|
||||||
String formatIsoStringToTime(String isoString) {
|
String formatIsoStringToTime(String isoString, BuildContext context) {
|
||||||
final dateTime = DateTime.parse(isoString);
|
try {
|
||||||
return DateFormat('hh:mm a').format(dateTime);
|
final parts = isoString.split(':');
|
||||||
|
final hour = int.parse(parts[0]);
|
||||||
|
final minute = int.parse(parts[1]);
|
||||||
|
final timeOfDay = TimeOfDay(hour: hour, minute: minute);
|
||||||
|
return timeOfDay.format(context);
|
||||||
|
} catch (e) {
|
||||||
|
return isoString;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user