mirror of
https://github.com/SyncrowIOT/web.git
synced 2025-07-09 22:57:21 +00:00
Add countdown functionality and device type support across device management views
This commit is contained in:
@ -60,4 +60,13 @@ class Status {
|
||||
factory Status.fromJson(String source) => Status.fromMap(json.decode(source));
|
||||
|
||||
String toJson() => json.encode(toMap());
|
||||
Status copyWith({
|
||||
String? code,
|
||||
dynamic value,
|
||||
}) {
|
||||
return Status(
|
||||
code: code ?? this.code,
|
||||
value: value ?? this.value,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -62,9 +62,10 @@ class CurtainModuleItems extends StatelessWidget with HelperResponsiveLayout {
|
||||
BlocProvider.of<CurtainModuleBloc>(context),
|
||||
child: BuildScheduleView(
|
||||
deviceUuid: deviceId,
|
||||
category: 'CUR_2',
|
||||
category: 'timer',
|
||||
code: 'control',
|
||||
|
||||
countdownCode: 'timer',
|
||||
deviceType: 'CUR_2',
|
||||
),
|
||||
));
|
||||
},
|
||||
|
@ -90,6 +90,8 @@ class OneGangGlassSwitchControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
category: 'switch_1',
|
||||
deviceUuid: deviceId,
|
||||
countdownCode: 'countdown_1',
|
||||
deviceType: '1GT',
|
||||
),
|
||||
));
|
||||
},
|
||||
|
@ -80,6 +80,8 @@ class WallLightDeviceControl extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
category: 'switch_1',
|
||||
deviceUuid: deviceId,
|
||||
countdownCode: 'countdown_1',
|
||||
deviceType: '1G',
|
||||
),
|
||||
));
|
||||
},
|
||||
|
@ -47,7 +47,7 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
final success = await RemoteControlDeviceService().controlDevice(
|
||||
deviceUuid: deviceId,
|
||||
status: Status(
|
||||
code: 'countdown_1',
|
||||
code: event.countdownCode,
|
||||
value: 0,
|
||||
),
|
||||
);
|
||||
@ -80,15 +80,18 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
) {
|
||||
if (state is ScheduleLoaded) {
|
||||
final currentState = state as ScheduleLoaded;
|
||||
|
||||
emit(currentState.copyWith(
|
||||
countdownSeconds: currentState.countdownSeconds,
|
||||
selectedTime: currentState.selectedTime,
|
||||
deviceId: deviceId,
|
||||
scheduleMode: event.scheduleMode,
|
||||
countdownRemaining: Duration.zero,
|
||||
countdownHours: 0,
|
||||
countdownMinutes: 0,
|
||||
inchingHours: 0,
|
||||
inchingMinutes: 0,
|
||||
isCountdownActive: false,
|
||||
countdownHours: currentState.countdownHours,
|
||||
countdownMinutes: currentState.countdownMinutes,
|
||||
inchingHours: currentState.inchingHours,
|
||||
inchingMinutes: currentState.inchingMinutes,
|
||||
isInchingActive: false,
|
||||
isCountdownActive: currentState.countdownRemaining > Duration.zero,
|
||||
));
|
||||
}
|
||||
}
|
||||
@ -221,7 +224,6 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
deviceId,
|
||||
event.category,
|
||||
);
|
||||
|
||||
if (state is ScheduleLoaded) {
|
||||
final currentState = state as ScheduleLoaded;
|
||||
emit(currentState.copyWith(
|
||||
@ -285,12 +287,22 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
) async {
|
||||
try {
|
||||
if (state is ScheduleLoaded) {
|
||||
Status status = Status(code: '', value: '');
|
||||
if (event.deviceType == 'CUR_2') {
|
||||
status = status.copyWith(
|
||||
code: 'control',
|
||||
value: event.functionOn == true ? 'open' : 'close');
|
||||
} else {
|
||||
status =
|
||||
status.copyWith(code: event.category, value: event.functionOn);
|
||||
}
|
||||
|
||||
final dateTime = DateTime.parse(event.time);
|
||||
final updatedSchedule = ScheduleEntry(
|
||||
scheduleId: event.scheduleId,
|
||||
category: event.category,
|
||||
time: getTimeStampWithoutSeconds(dateTime).toString(),
|
||||
function: Status(code: event.category, value: event.functionOn),
|
||||
function: status,
|
||||
days: event.selectedDays,
|
||||
);
|
||||
final success = await DevicesManagementApi().editScheduleRecord(
|
||||
@ -396,7 +408,7 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
final totalSeconds =
|
||||
Duration(hours: event.hours, minutes: event.minutes).inSeconds;
|
||||
final code = event.mode == ScheduleModes.countdown
|
||||
? 'countdown_1'
|
||||
? event.countDownCode
|
||||
: 'switch_inching';
|
||||
final currentState = state as ScheduleLoaded;
|
||||
final duration = Duration(seconds: totalSeconds);
|
||||
@ -423,7 +435,7 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
);
|
||||
|
||||
if (success) {
|
||||
if (code == 'countdown_1') {
|
||||
if (code == event.countDownCode) {
|
||||
final countdownDuration = Duration(seconds: totalSeconds);
|
||||
|
||||
emit(
|
||||
@ -437,7 +449,7 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
);
|
||||
|
||||
if (countdownDuration.inSeconds > 0) {
|
||||
_startCountdownTimer(emit, countdownDuration);
|
||||
_startCountdownTimer(emit, countdownDuration, event.countDownCode);
|
||||
} else {
|
||||
_countdownTimer?.cancel();
|
||||
emit(
|
||||
@ -467,9 +479,7 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
}
|
||||
|
||||
void _startCountdownTimer(
|
||||
Emitter<ScheduleState> emit,
|
||||
Duration duration,
|
||||
) {
|
||||
Emitter<ScheduleState> emit, Duration duration, String countdownCode) {
|
||||
_countdownTimer?.cancel();
|
||||
_countdownTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||
if (_currentCountdown != null && _currentCountdown! > Duration.zero) {
|
||||
@ -479,6 +489,7 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
} else {
|
||||
timer.cancel();
|
||||
add(StopScheduleEvent(
|
||||
countdownCode: countdownCode,
|
||||
mode: _currentCountdown == null
|
||||
? ScheduleModes.countdown
|
||||
: ScheduleModes.inching,
|
||||
@ -515,70 +526,75 @@ class ScheduleBloc extends Bloc<ScheduleEvent, ScheduleState> {
|
||||
try {
|
||||
final status =
|
||||
await DevicesManagementApi().getDeviceStatus(event.deviceId);
|
||||
print(status.status);
|
||||
int totalSeconds = 0;
|
||||
final countdownItem = status.status.firstWhere(
|
||||
(item) => item.code == event.countdownCode,
|
||||
orElse: () => Status(code: '', value: 0),
|
||||
);
|
||||
totalSeconds = (countdownItem.value as int?) ?? 0;
|
||||
final countdownHours = totalSeconds ~/ 3600;
|
||||
final countdownMinutes = (totalSeconds % 3600) ~/ 60;
|
||||
final countdownSeconds = totalSeconds % 60;
|
||||
|
||||
final deviceStatus =
|
||||
WaterHeaterStatusModel.fromJson(event.deviceId, status.status);
|
||||
final isCountdownActive = totalSeconds > 0;
|
||||
final isInchingActive = !isCountdownActive &&
|
||||
(deviceStatus.inchingHours > 0 || deviceStatus.inchingMinutes > 0);
|
||||
|
||||
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 isInching = scheduleMode == ScheduleModes.inching;
|
||||
final newState = state is ScheduleLoaded
|
||||
? (state as ScheduleLoaded).copyWith(
|
||||
scheduleMode: ScheduleModes.schedule,
|
||||
countdownHours: countdownHours,
|
||||
countdownMinutes: countdownMinutes,
|
||||
countdownSeconds: countdownSeconds,
|
||||
inchingHours: deviceStatus.inchingHours,
|
||||
inchingMinutes: deviceStatus.inchingMinutes,
|
||||
isCountdownActive: isCountdownActive,
|
||||
isInchingActive: isInchingActive,
|
||||
countdownRemaining: isCountdownActive
|
||||
? Duration(seconds: totalSeconds)
|
||||
: Duration.zero,
|
||||
)
|
||||
: ScheduleLoaded(
|
||||
scheduleMode: ScheduleModes.schedule,
|
||||
schedules: const [],
|
||||
selectedTime: null,
|
||||
selectedDays: List.filled(7, false),
|
||||
functionOn: false,
|
||||
isEditing: false,
|
||||
deviceId: event.deviceId,
|
||||
countdownHours: countdownHours,
|
||||
countdownMinutes: countdownMinutes,
|
||||
countdownSeconds: countdownSeconds,
|
||||
inchingHours: deviceStatus.inchingHours,
|
||||
inchingMinutes: deviceStatus.inchingMinutes,
|
||||
isCountdownActive: isCountdownActive,
|
||||
isInchingActive: isInchingActive,
|
||||
countdownRemaining: isCountdownActive
|
||||
? Duration(seconds: totalSeconds)
|
||||
: Duration.zero,
|
||||
);
|
||||
emit(newState);
|
||||
|
||||
Duration? countdownRemaining;
|
||||
var isCountdownActive = false;
|
||||
var isInchingActive = false;
|
||||
if (isCountdownActive) {
|
||||
_countdownTimer?.cancel();
|
||||
_currentCountdown = Duration(seconds: totalSeconds);
|
||||
countdownRemaining = _currentCountdown!;
|
||||
|
||||
if (isCountdown) {
|
||||
countdownRemaining = Duration(
|
||||
hours: deviceStatus.countdownHours,
|
||||
minutes: deviceStatus.countdownMinutes,
|
||||
);
|
||||
isCountdownActive = countdownRemaining > Duration.zero;
|
||||
} else if (isInching) {
|
||||
isInchingActive = Duration(
|
||||
hours: deviceStatus.inchingHours,
|
||||
minutes: deviceStatus.inchingMinutes,
|
||||
) >
|
||||
Duration.zero;
|
||||
}
|
||||
if (state is ScheduleLoaded) {
|
||||
final currentState = state as ScheduleLoaded;
|
||||
emit(currentState.copyWith(
|
||||
scheduleMode: scheduleMode,
|
||||
countdownHours: deviceStatus.countdownHours,
|
||||
countdownMinutes: deviceStatus.countdownMinutes,
|
||||
inchingHours: deviceStatus.inchingHours,
|
||||
inchingMinutes: deviceStatus.inchingMinutes,
|
||||
isCountdownActive: isCountdownActive,
|
||||
isInchingActive: isInchingActive,
|
||||
countdownRemaining: countdownRemaining ?? Duration.zero,
|
||||
));
|
||||
if (totalSeconds > 0) {
|
||||
_startCountdownTimer(
|
||||
emit, Duration(seconds: totalSeconds), event.countdownCode);
|
||||
} else {
|
||||
add(StopScheduleEvent(
|
||||
countdownCode: event.countdownCode,
|
||||
mode: ScheduleModes.countdown,
|
||||
deviceId: event.deviceId,
|
||||
));
|
||||
}
|
||||
} else {
|
||||
emit(ScheduleLoaded(
|
||||
schedules: const [],
|
||||
selectedTime: null,
|
||||
selectedDays: List.filled(7, false),
|
||||
functionOn: false,
|
||||
isEditing: false,
|
||||
deviceId: deviceId,
|
||||
scheduleMode: scheduleMode,
|
||||
countdownHours: deviceStatus.countdownHours,
|
||||
countdownMinutes: deviceStatus.countdownMinutes,
|
||||
inchingHours: deviceStatus.inchingHours,
|
||||
inchingMinutes: deviceStatus.inchingMinutes,
|
||||
isCountdownActive: isCountdownActive,
|
||||
isInchingActive: isInchingActive,
|
||||
countdownRemaining: countdownRemaining ?? Duration.zero,
|
||||
));
|
||||
_countdownTimer?.cancel();
|
||||
}
|
||||
|
||||
// if (isCountdownActive && countdownRemaining != null) {
|
||||
// _startCountdownTimer(emit, countdownRemaining);
|
||||
// }
|
||||
} catch (e) {
|
||||
emit(ScheduleError('Failed to fetch device status: $e'));
|
||||
}
|
||||
|
@ -91,6 +91,7 @@ class ScheduleEditEvent extends ScheduleEvent {
|
||||
final String time;
|
||||
final List<String> selectedDays;
|
||||
final bool functionOn;
|
||||
final String deviceType;
|
||||
|
||||
const ScheduleEditEvent({
|
||||
required this.scheduleId,
|
||||
@ -98,6 +99,7 @@ class ScheduleEditEvent extends ScheduleEvent {
|
||||
required this.time,
|
||||
required this.selectedDays,
|
||||
required this.functionOn,
|
||||
required this.deviceType,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -107,6 +109,7 @@ class ScheduleEditEvent extends ScheduleEvent {
|
||||
time,
|
||||
selectedDays,
|
||||
functionOn,
|
||||
deviceType,
|
||||
];
|
||||
}
|
||||
|
||||
@ -138,11 +141,13 @@ class ScheduleUpdateEntryEvent extends ScheduleEvent {
|
||||
|
||||
class UpdateScheduleModeEvent extends ScheduleEvent {
|
||||
final ScheduleModes scheduleMode;
|
||||
final String countdownCode;
|
||||
|
||||
const UpdateScheduleModeEvent({required this.scheduleMode});
|
||||
const UpdateScheduleModeEvent(
|
||||
{required this.scheduleMode, required this.countdownCode});
|
||||
|
||||
@override
|
||||
List<Object> get props => [scheduleMode];
|
||||
List<Object> get props => [scheduleMode, countdownCode!];
|
||||
}
|
||||
|
||||
class UpdateCountdownTimeEvent extends ScheduleEvent {
|
||||
@ -177,28 +182,32 @@ class StartScheduleEvent extends ScheduleEvent {
|
||||
final ScheduleModes mode;
|
||||
final int hours;
|
||||
final int minutes;
|
||||
final String countDownCode;
|
||||
|
||||
const StartScheduleEvent({
|
||||
required this.mode,
|
||||
required this.hours,
|
||||
required this.minutes,
|
||||
required this.countDownCode,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [mode, hours, minutes];
|
||||
List<Object?> get props => [mode, hours, minutes, countDownCode];
|
||||
}
|
||||
|
||||
class StopScheduleEvent extends ScheduleEvent {
|
||||
final ScheduleModes mode;
|
||||
final String deviceId;
|
||||
final String countdownCode;
|
||||
|
||||
const StopScheduleEvent({
|
||||
required this.mode,
|
||||
required this.deviceId,
|
||||
required this.countdownCode,
|
||||
});
|
||||
|
||||
@override
|
||||
List<Object?> get props => [mode, deviceId];
|
||||
List<Object?> get props => [mode, deviceId, countdownCode];
|
||||
}
|
||||
|
||||
class ScheduleDecrementCountdownEvent extends ScheduleEvent {
|
||||
@ -210,11 +219,13 @@ class ScheduleDecrementCountdownEvent extends ScheduleEvent {
|
||||
|
||||
class ScheduleFetchStatusEvent extends ScheduleEvent {
|
||||
final String deviceId;
|
||||
final String countdownCode;
|
||||
|
||||
const ScheduleFetchStatusEvent(this.deviceId);
|
||||
const ScheduleFetchStatusEvent(
|
||||
{required this.deviceId, required this.countdownCode});
|
||||
|
||||
@override
|
||||
List<Object> get props => [deviceId];
|
||||
List<Object> get props => [deviceId, countdownCode];
|
||||
}
|
||||
|
||||
class DeleteScheduleEvent extends ScheduleEvent {
|
||||
|
@ -29,7 +29,7 @@ class ScheduleLoaded extends ScheduleState {
|
||||
final int inchingSeconds;
|
||||
final bool isInchingActive;
|
||||
final ScheduleModes scheduleMode;
|
||||
final Duration? countdownRemaining;
|
||||
final Duration countdownRemaining;
|
||||
final int? countdownSeconds;
|
||||
|
||||
const ScheduleLoaded({
|
||||
@ -48,7 +48,7 @@ class ScheduleLoaded extends ScheduleState {
|
||||
this.inchingMinutes = 0,
|
||||
this.isInchingActive = false,
|
||||
this.scheduleMode = ScheduleModes.countdown,
|
||||
this.countdownRemaining,
|
||||
this.countdownRemaining = Duration.zero,
|
||||
});
|
||||
|
||||
ScheduleLoaded copyWith({
|
||||
|
@ -11,6 +11,7 @@ class CountdownModeButtons extends StatelessWidget {
|
||||
final String deviceId;
|
||||
final int hours;
|
||||
final int minutes;
|
||||
final String countDownCode;
|
||||
|
||||
const CountdownModeButtons({
|
||||
super.key,
|
||||
@ -18,6 +19,7 @@ class CountdownModeButtons extends StatelessWidget {
|
||||
required this.deviceId,
|
||||
required this.hours,
|
||||
required this.minutes,
|
||||
required this.countDownCode,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -43,6 +45,7 @@ class CountdownModeButtons extends StatelessWidget {
|
||||
StopScheduleEvent(
|
||||
mode: ScheduleModes.countdown,
|
||||
deviceId: deviceId,
|
||||
countdownCode: countDownCode,
|
||||
),
|
||||
);
|
||||
},
|
||||
@ -54,10 +57,10 @@ class CountdownModeButtons extends StatelessWidget {
|
||||
onPressed: () {
|
||||
context.read<ScheduleBloc>().add(
|
||||
StartScheduleEvent(
|
||||
mode: ScheduleModes.countdown,
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
),
|
||||
mode: ScheduleModes.countdown,
|
||||
hours: hours,
|
||||
minutes: minutes,
|
||||
countDownCode: countDownCode),
|
||||
);
|
||||
},
|
||||
backgroundColor: ColorsManager.primaryColor,
|
||||
|
@ -75,23 +75,33 @@ class _CountdownInchingViewState extends State<CountdownInchingView> {
|
||||
final isCountDown = state.scheduleMode == ScheduleModes.countdown;
|
||||
final isActive =
|
||||
isCountDown ? state.isCountdownActive : state.isInchingActive;
|
||||
final displayHours = isActive && state.countdownRemaining != null
|
||||
? state.countdownRemaining!.inHours
|
||||
: (isCountDown ? state.countdownHours : state.inchingHours);
|
||||
final displayMinutes = isActive && state.countdownRemaining != null
|
||||
? state.countdownRemaining!.inMinutes.remainder(60)
|
||||
: (isCountDown ? state.countdownMinutes : state.inchingMinutes);
|
||||
final displaySeconds = isActive && state.countdownRemaining != null
|
||||
? state.countdownRemaining!.inSeconds.remainder(60)
|
||||
: (isCountDown ? state.countdownSeconds : state.inchingSeconds);
|
||||
|
||||
_updateControllers(displayHours, displayMinutes, displaySeconds!);
|
||||
final displayHours =
|
||||
isActive && state.countdownRemaining != Duration.zero
|
||||
? state.countdownRemaining.inHours
|
||||
: (isCountDown ? state.countdownHours : state.inchingHours);
|
||||
|
||||
if (displayHours == 0 && displayMinutes == 0 && displaySeconds == 0) {
|
||||
final displayMinutes =
|
||||
isActive && state.countdownRemaining != Duration.zero
|
||||
? state.countdownRemaining.inMinutes.remainder(60)
|
||||
: (isCountDown ? state.countdownMinutes : state.inchingMinutes);
|
||||
|
||||
final displaySeconds =
|
||||
isActive && state.countdownRemaining != Duration.zero
|
||||
? state.countdownRemaining.inSeconds.remainder(60)
|
||||
: (isCountDown ? (state.countdownSeconds ?? 0) : 0);
|
||||
|
||||
_updateControllers(displayHours, displayMinutes, displaySeconds);
|
||||
|
||||
if (isActive &&
|
||||
displayHours == 0 &&
|
||||
displayMinutes == 0 &&
|
||||
displaySeconds == 0) {
|
||||
context.read<ScheduleBloc>().add(
|
||||
StopScheduleEvent(
|
||||
mode: ScheduleModes.countdown,
|
||||
deviceId: widget.deviceId,
|
||||
countdownCode: '',
|
||||
),
|
||||
);
|
||||
}
|
||||
|
@ -43,7 +43,9 @@ class InchingModeButtons extends StatelessWidget {
|
||||
onPressed: () {
|
||||
context.read<ScheduleBloc>().add(
|
||||
StopScheduleEvent(
|
||||
deviceId: deviceId, mode: ScheduleModes.inching),
|
||||
deviceId: deviceId,
|
||||
mode: ScheduleModes.inching,
|
||||
countdownCode: ''),
|
||||
);
|
||||
},
|
||||
backgroundColor: Colors.red,
|
||||
|
@ -18,11 +18,15 @@ class BuildScheduleView extends StatelessWidget {
|
||||
super.key,
|
||||
required this.deviceUuid,
|
||||
required this.category,
|
||||
required this.countdownCode,
|
||||
this.code,
|
||||
required this.deviceType,
|
||||
});
|
||||
final String deviceUuid;
|
||||
final String category;
|
||||
final String? code;
|
||||
final String? countdownCode;
|
||||
final String deviceType;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -31,7 +35,8 @@ class BuildScheduleView extends StatelessWidget {
|
||||
deviceId: deviceUuid,
|
||||
)
|
||||
..add(ScheduleGetEvent(category: category))
|
||||
..add(ScheduleFetchStatusEvent(deviceUuid)),
|
||||
..add(ScheduleFetchStatusEvent(
|
||||
deviceId: deviceUuid, countdownCode: countdownCode ?? '')),
|
||||
child: Dialog(
|
||||
backgroundColor: Colors.white,
|
||||
insetPadding: const EdgeInsets.all(20),
|
||||
@ -52,28 +57,32 @@ class BuildScheduleView extends StatelessWidget {
|
||||
children: [
|
||||
const ScheduleHeader(),
|
||||
const SizedBox(height: 20),
|
||||
ScheduleModeSelector(
|
||||
currentMode: state.scheduleMode,
|
||||
),
|
||||
if (deviceType == 'CUR_2')
|
||||
const SizedBox()
|
||||
else
|
||||
ScheduleModeSelector(
|
||||
countdownCode: countdownCode ?? '',
|
||||
currentMode: state.scheduleMode,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (state.scheduleMode == ScheduleModes.schedule)
|
||||
ScheduleManagementUI(
|
||||
deviceType: deviceType,
|
||||
category: category,
|
||||
deviceUuid: deviceUuid,
|
||||
onAddSchedule: () async {
|
||||
final entry = await ScheduleDialogHelper
|
||||
.showAddScheduleDialog(
|
||||
context,
|
||||
schedule: ScheduleEntry(
|
||||
category: category,
|
||||
time: '',
|
||||
function: Status(
|
||||
code: code.toString(), value: null),
|
||||
days: [],
|
||||
),
|
||||
isEdit: false,
|
||||
code: code,
|
||||
);
|
||||
.showAddScheduleDialog(context,
|
||||
schedule: ScheduleEntry(
|
||||
category: category,
|
||||
time: '',
|
||||
function: Status(
|
||||
code: code.toString(), value: null),
|
||||
days: [],
|
||||
),
|
||||
isEdit: false,
|
||||
code: code,
|
||||
deviceType: deviceType);
|
||||
if (entry != null) {
|
||||
context.read<ScheduleBloc>().add(
|
||||
ScheduleAddEvent(
|
||||
@ -87,14 +96,16 @@ class BuildScheduleView extends StatelessWidget {
|
||||
}
|
||||
},
|
||||
),
|
||||
if (state.scheduleMode == ScheduleModes.countdown ||
|
||||
state.scheduleMode == ScheduleModes.inching)
|
||||
CountdownInchingView(
|
||||
deviceId: deviceUuid,
|
||||
),
|
||||
if (deviceType != 'CUR_2')
|
||||
if (state.scheduleMode == ScheduleModes.countdown ||
|
||||
state.scheduleMode == ScheduleModes.inching)
|
||||
CountdownInchingView(
|
||||
deviceId: deviceUuid,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
if (state.scheduleMode == ScheduleModes.countdown)
|
||||
CountdownModeButtons(
|
||||
countDownCode: countdownCode ?? '',
|
||||
isActive: state.isCountdownActive,
|
||||
deviceId: deviceUuid,
|
||||
hours: state.countdownHours,
|
||||
|
@ -5,14 +5,16 @@ import 'package:syncrow_web/utils/color_manager.dart';
|
||||
import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class ScheduleManagementUI extends StatelessWidget {
|
||||
final String deviceUuid;
|
||||
final String deviceUuid;
|
||||
final VoidCallback onAddSchedule;
|
||||
final String category;
|
||||
final String deviceType;
|
||||
|
||||
const ScheduleManagementUI({
|
||||
super.key,
|
||||
required this.deviceUuid,
|
||||
required this.onAddSchedule,
|
||||
required this.deviceType,
|
||||
this.category = 'switch_1',
|
||||
});
|
||||
|
||||
@ -44,7 +46,11 @@ class ScheduleManagementUI extends StatelessWidget {
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
ScheduleTableWidget(deviceUuid: deviceUuid, category: category),
|
||||
ScheduleTableWidget(
|
||||
deviceUuid: deviceUuid,
|
||||
category: category,
|
||||
deviceType: deviceType,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
@ -7,10 +7,12 @@ import 'package:syncrow_web/utils/extension/build_context_x.dart';
|
||||
|
||||
class ScheduleModeSelector extends StatelessWidget {
|
||||
final ScheduleModes currentMode;
|
||||
final String countdownCode;
|
||||
|
||||
const ScheduleModeSelector({
|
||||
super.key,
|
||||
required this.currentMode,
|
||||
required this.countdownCode,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -71,7 +73,8 @@ class ScheduleModeSelector extends StatelessWidget {
|
||||
onChanged: (ScheduleModes? value) {
|
||||
if (value != null) {
|
||||
context.read<ScheduleBloc>().add(
|
||||
UpdateScheduleModeEvent(scheduleMode: value),
|
||||
UpdateScheduleModeEvent(
|
||||
scheduleMode: value, countdownCode: countdownCode),
|
||||
);
|
||||
if (value == ScheduleModes.schedule) {
|
||||
context.read<ScheduleBloc>().add(
|
||||
|
@ -12,11 +12,13 @@ import 'package:syncrow_web/utils/format_date_time.dart';
|
||||
class ScheduleTableWidget extends StatelessWidget {
|
||||
final String deviceUuid;
|
||||
final String category;
|
||||
final String deviceType;
|
||||
|
||||
const ScheduleTableWidget({
|
||||
super.key,
|
||||
required this.deviceUuid,
|
||||
this.category = 'switch_1',
|
||||
required this.deviceType,
|
||||
});
|
||||
|
||||
@override
|
||||
@ -25,13 +27,14 @@ class ScheduleTableWidget extends StatelessWidget {
|
||||
create: (_) => ScheduleBloc(
|
||||
deviceId: deviceUuid,
|
||||
)..add(ScheduleGetEvent(category: category)),
|
||||
child: _ScheduleTableView(),
|
||||
child: _ScheduleTableView(deviceType),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _ScheduleTableView extends StatelessWidget {
|
||||
const _ScheduleTableView();
|
||||
final String deviceType;
|
||||
const _ScheduleTableView(this.deviceType);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -81,7 +84,7 @@ class _ScheduleTableView extends StatelessWidget {
|
||||
bottomLeft: Radius.circular(20),
|
||||
bottomRight: Radius.circular(20)),
|
||||
),
|
||||
child: _buildTableBody(state.schedules, context));
|
||||
child: _buildTableBody(state.schedules, context, deviceType));
|
||||
}
|
||||
if (state is ScheduleError) {
|
||||
return Center(child: Text(state.error));
|
||||
@ -123,7 +126,8 @@ class _ScheduleTableView extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTableBody(List<ScheduleModel> schedules, BuildContext context) {
|
||||
Widget _buildTableBody(
|
||||
List<ScheduleModel> schedules, BuildContext context, String deviceType) {
|
||||
return SizedBox(
|
||||
height: 200,
|
||||
child: SingleChildScrollView(
|
||||
@ -132,7 +136,8 @@ class _ScheduleTableView extends StatelessWidget {
|
||||
defaultVerticalAlignment: TableCellVerticalAlignment.middle,
|
||||
children: [
|
||||
for (int i = 0; i < schedules.length; i++)
|
||||
_buildScheduleRow(schedules[i], i, context),
|
||||
_buildScheduleRow(schedules[i], i, context,
|
||||
deviceType: deviceType),
|
||||
],
|
||||
),
|
||||
),
|
||||
@ -155,25 +160,19 @@ class _ScheduleTableView extends StatelessWidget {
|
||||
}
|
||||
|
||||
TableRow _buildScheduleRow(
|
||||
ScheduleModel schedule, int index, BuildContext context) {
|
||||
ScheduleModel schedule, int index, BuildContext context,
|
||||
{required String deviceType}) {
|
||||
return TableRow(
|
||||
children: [
|
||||
Center(
|
||||
child: GestureDetector(
|
||||
behavior: HitTestBehavior.opaque,
|
||||
onTap: () {
|
||||
bool temp;
|
||||
if (schedule.category == 'CUR_2') {
|
||||
temp = schedule.function.value == 'open' ? true : false;
|
||||
} else {
|
||||
temp = schedule.function.value as bool;
|
||||
}
|
||||
context.read<ScheduleBloc>().add(
|
||||
ScheduleUpdateEntryEvent(
|
||||
category: schedule.category,
|
||||
scheduleId: schedule.scheduleId,
|
||||
functionOn: temp,
|
||||
// schedule.function.value,
|
||||
functionOn: schedule.function.value,
|
||||
enable: !schedule.enable,
|
||||
),
|
||||
);
|
||||
@ -195,10 +194,11 @@ class _ScheduleTableView extends StatelessWidget {
|
||||
child: Text(_getSelectedDays(
|
||||
ScheduleModel.parseSelectedDays(schedule.days)))),
|
||||
Center(child: Text(formatIsoStringToTime(schedule.time, context))),
|
||||
schedule.category == 'CUR_2'
|
||||
? Center(
|
||||
child: Text(schedule.function.value == true ? 'open' : 'close'))
|
||||
: Center(child: Text(schedule.function.value ? 'On' : 'Off')),
|
||||
if (deviceType == 'CUR_2')
|
||||
Center(
|
||||
child: Text(schedule.function.value == true ? 'open' : 'close'))
|
||||
else
|
||||
Center(child: Text(schedule.function.value ? 'On' : 'Off')),
|
||||
Center(
|
||||
child: Wrap(
|
||||
runAlignment: WrapAlignment.center,
|
||||
@ -206,18 +206,28 @@ class _ScheduleTableView extends StatelessWidget {
|
||||
TextButton(
|
||||
style: TextButton.styleFrom(padding: EdgeInsets.zero),
|
||||
onPressed: () {
|
||||
ScheduleDialogHelper.showAddScheduleDialog(
|
||||
context,
|
||||
schedule: ScheduleEntry.fromScheduleModel(schedule),
|
||||
isEdit: true,
|
||||
).then((updatedSchedule) {
|
||||
ScheduleDialogHelper.showAddScheduleDialog(context,
|
||||
schedule: ScheduleEntry.fromScheduleModel(schedule),
|
||||
isEdit: true,
|
||||
deviceType: deviceType)
|
||||
.then((updatedSchedule) {
|
||||
if (updatedSchedule != null) {
|
||||
bool temp;
|
||||
if (deviceType == 'CUR_2') {
|
||||
updatedSchedule.function.value == 'open'
|
||||
? temp = true
|
||||
: temp = false;
|
||||
} else {
|
||||
temp = updatedSchedule.function.value;
|
||||
}
|
||||
print('deviceType $deviceType');
|
||||
context.read<ScheduleBloc>().add(
|
||||
ScheduleEditEvent(
|
||||
deviceType: deviceType,
|
||||
scheduleId: schedule.scheduleId,
|
||||
category: schedule.category,
|
||||
time: updatedSchedule.time,
|
||||
functionOn: updatedSchedule.function.value,
|
||||
functionOn: temp,
|
||||
selectedDays: updatedSchedule.days),
|
||||
);
|
||||
}
|
||||
|
@ -111,6 +111,8 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
category: 'switch_1',
|
||||
deviceUuid: deviceId,
|
||||
countdownCode: 'countdown_1',
|
||||
deviceType: '3GT',
|
||||
),
|
||||
));
|
||||
},
|
||||
@ -127,6 +129,8 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
category: 'switch_2',
|
||||
deviceUuid: deviceId,
|
||||
countdownCode: 'countdown_2',
|
||||
deviceType: '3GT',
|
||||
),
|
||||
));
|
||||
},
|
||||
@ -143,6 +147,8 @@ class ThreeGangGlassSwitchControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
category: 'switch_3',
|
||||
deviceUuid: deviceId,
|
||||
countdownCode: 'countdown_3',
|
||||
deviceType: '3GT',
|
||||
),
|
||||
));
|
||||
},
|
||||
|
@ -102,6 +102,8 @@ class LivingRoomDeviceControlsView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
deviceUuid: deviceId,
|
||||
category: 'switch_1',
|
||||
countdownCode: 'countdown_1',
|
||||
deviceType: '3G',
|
||||
),
|
||||
));
|
||||
},
|
||||
@ -118,6 +120,8 @@ class LivingRoomDeviceControlsView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
deviceUuid: deviceId,
|
||||
category: 'switch_2',
|
||||
countdownCode: 'countdown_2',
|
||||
deviceType: '3G',
|
||||
),
|
||||
));
|
||||
},
|
||||
@ -134,6 +138,8 @@ class LivingRoomDeviceControlsView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
deviceUuid: deviceId,
|
||||
category: 'switch_3',
|
||||
countdownCode: 'countdown_3',
|
||||
deviceType: '3G',
|
||||
),
|
||||
));
|
||||
},
|
||||
|
@ -102,6 +102,8 @@ class TwoGangGlassSwitchControlView extends StatelessWidget
|
||||
builder: (ctx) => BlocProvider.value(
|
||||
value: BlocProvider.of<TwoGangGlassSwitchBloc>(context),
|
||||
child: BuildScheduleView(
|
||||
deviceType: '1GT',
|
||||
countdownCode: 'countdown_1',
|
||||
deviceUuid: deviceId,
|
||||
category: 'switch_1',
|
||||
),
|
||||
@ -118,6 +120,8 @@ class TwoGangGlassSwitchControlView extends StatelessWidget
|
||||
builder: (ctx) => BlocProvider.value(
|
||||
value: BlocProvider.of<TwoGangGlassSwitchBloc>(context),
|
||||
child: BuildScheduleView(
|
||||
deviceType: '1GT',
|
||||
countdownCode: 'countdown_2',
|
||||
deviceUuid: deviceId,
|
||||
category: 'switch_2',
|
||||
),
|
||||
|
@ -97,6 +97,8 @@ class TwoGangBatchControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
category: 'switch_1',
|
||||
deviceUuid: deviceIds.first,
|
||||
countdownCode: 'countdown_1',
|
||||
deviceType: '2G',
|
||||
),
|
||||
));
|
||||
},
|
||||
@ -114,6 +116,8 @@ class TwoGangBatchControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
category: 'switch_2',
|
||||
deviceUuid: deviceIds.first,
|
||||
countdownCode: 'countdown_2',
|
||||
deviceType: '2G',
|
||||
),
|
||||
));
|
||||
},
|
||||
@ -121,10 +125,7 @@ class TwoGangBatchControlView extends StatelessWidget
|
||||
subtitle: 'Scheduling',
|
||||
iconPath: Assets.scheduling,
|
||||
),
|
||||
// FirmwareUpdateWidget(
|
||||
// deviceId: deviceIds.first,
|
||||
// version: 12,
|
||||
// ),
|
||||
|
||||
FactoryResetWidget(callFactoryReset: () {
|
||||
context.read<TwoGangSwitchBloc>().add(
|
||||
TwoGangFactoryReset(
|
||||
|
@ -103,6 +103,8 @@ class TwoGangDeviceControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
deviceUuid: deviceId,
|
||||
category: 'switch_1',
|
||||
countdownCode: 'countdown_1',
|
||||
deviceType: '2G',
|
||||
),
|
||||
));
|
||||
},
|
||||
@ -125,6 +127,8 @@ class TwoGangDeviceControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
deviceUuid: deviceId,
|
||||
category: 'switch_2',
|
||||
countdownCode: 'countdown_2',
|
||||
deviceType: '2G',
|
||||
),
|
||||
));
|
||||
},
|
||||
|
@ -18,14 +18,21 @@ class ScheduleDialogHelper {
|
||||
ScheduleEntry? schedule,
|
||||
bool isEdit = false,
|
||||
String? code,
|
||||
required String deviceType,
|
||||
}) {
|
||||
bool temp;
|
||||
if (deviceType == 'CUR_2') {
|
||||
temp = schedule!.function.value == 'open' ? true : false;
|
||||
} else {
|
||||
temp = schedule!.function.value;
|
||||
}
|
||||
final initialTime = schedule != null
|
||||
? _convertStringToTimeOfDay(schedule.time)
|
||||
: TimeOfDay.now();
|
||||
final initialDays = schedule != null
|
||||
? _convertDaysStringToBooleans(schedule.days)
|
||||
: List.filled(7, false);
|
||||
bool? functionOn = schedule?.function.value ?? true;
|
||||
bool? functionOn = temp;
|
||||
TimeOfDay selectedTime = initialTime;
|
||||
List<bool> selectedDays = List.of(initialDays);
|
||||
|
||||
@ -97,8 +104,7 @@ class ScheduleDialogHelper {
|
||||
setState(() => selectedDays[i] = v);
|
||||
}),
|
||||
const SizedBox(height: 16),
|
||||
_buildFunctionSwitch(schedule!.category, ctx, functionOn!,
|
||||
(v) {
|
||||
_buildFunctionSwitch(deviceType, ctx, functionOn!, (v) {
|
||||
setState(() => functionOn = v);
|
||||
}),
|
||||
],
|
||||
@ -114,32 +120,30 @@ class ScheduleDialogHelper {
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 100,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
dynamic temp;
|
||||
if (schedule?.category == 'CUR_2') {
|
||||
temp = functionOn! ? 'open' : 'close';
|
||||
} else {
|
||||
temp = functionOn;
|
||||
}
|
||||
print(temp);
|
||||
final entry = ScheduleEntry(
|
||||
category: schedule?.category ?? 'switch_1',
|
||||
time: _formatTimeOfDayToISO(selectedTime),
|
||||
function: Status(
|
||||
code: code ?? 'switch_1',
|
||||
value: temp,
|
||||
// functionOn,
|
||||
),
|
||||
days: _convertSelectedDaysToStrings(selectedDays),
|
||||
scheduleId: schedule?.scheduleId,
|
||||
);
|
||||
Navigator.pop(ctx, entry);
|
||||
},
|
||||
child: const Text('Save'),
|
||||
),
|
||||
),
|
||||
width: 100,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
dynamic temp;
|
||||
if (deviceType == 'CUR_2') {
|
||||
temp = functionOn! ? 'open' : 'close';
|
||||
} else {
|
||||
temp = functionOn;
|
||||
}
|
||||
final entry = ScheduleEntry(
|
||||
category: schedule?.category ?? 'switch_1',
|
||||
time: _formatTimeOfDayToISO(selectedTime),
|
||||
function: Status(
|
||||
code: code ?? 'switch_1',
|
||||
value: temp,
|
||||
|
||||
),
|
||||
days: _convertSelectedDaysToStrings(selectedDays),
|
||||
scheduleId: schedule.scheduleId,
|
||||
);
|
||||
Navigator.pop(ctx, entry);
|
||||
},
|
||||
child: const Text('Save'),
|
||||
)),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
@ -84,6 +84,8 @@ class WaterHeaterDeviceControlView extends StatelessWidget
|
||||
child: BuildScheduleView(
|
||||
deviceUuid: device.uuid ?? '',
|
||||
category: 'switch_1',
|
||||
countdownCode: 'countdown_1',
|
||||
deviceType: 'WH',
|
||||
),
|
||||
));
|
||||
},
|
||||
|
Reference in New Issue
Block a user