start working on scheduling

This commit is contained in:
ashrafzarkanisala
2024-09-17 01:28:35 +03:00
parent e577cd3279
commit 3c8d3feba3
4 changed files with 252 additions and 33 deletions

View File

@ -12,6 +12,7 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
WaterHeaterBloc() : super(WaterHeaterInitial()) { WaterHeaterBloc() : super(WaterHeaterInitial()) {
on<WaterHeaterFetchStatusEvent>(_fetchWaterHeaterStatus); on<WaterHeaterFetchStatusEvent>(_fetchWaterHeaterStatus);
on<ToggleWaterHeaterEvent>(_controlWaterHeater); on<ToggleWaterHeaterEvent>(_controlWaterHeater);
on<ShowScheduleViewEvent>(_showScheduleView);
on<UpdateScheduleEvent>(_updateScheduleEvent); on<UpdateScheduleEvent>(_updateScheduleEvent);
on<StopScheduleEvent>(_stopScheduleEvent); on<StopScheduleEvent>(_stopScheduleEvent);
} }
@ -23,14 +24,24 @@ class WaterHeaterBloc extends Bloc<WaterHeaterEvent, WaterHeaterState> {
UpdateScheduleEvent event, UpdateScheduleEvent event,
Emitter<WaterHeaterState> emit, Emitter<WaterHeaterState> emit,
) { ) {
emit(WaterHeaterScheduleState( emit(WaterHeaterScheduleViewState(
scheduleType: event.scheduleType, scheduleMode: event.scheduleMode,
hours: event.hours, hours: event.hours,
minutes: event.minutes, minutes: event.minutes,
isActive: true, isActive: true,
)); ));
} }
FutureOr<void> _showScheduleView(
ShowScheduleViewEvent event, Emitter<WaterHeaterState> emit) {
emit(const WaterHeaterScheduleViewState(
scheduleMode: ScheduleModes.countdown,
hours: 6,
minutes: 23,
isActive: false,
));
}
FutureOr<void> _stopScheduleEvent( FutureOr<void> _stopScheduleEvent(
StopScheduleEvent event, StopScheduleEvent event,
Emitter<WaterHeaterState> emit, Emitter<WaterHeaterState> emit,

View File

@ -18,14 +18,15 @@ final class ToggleWaterHeaterEvent extends WaterHeaterEvent {
} }
final class UpdateScheduleEvent extends WaterHeaterEvent { final class UpdateScheduleEvent extends WaterHeaterEvent {
final ScheduleType scheduleType; final ScheduleModes scheduleMode;
final int hours; final int hours;
final int minutes; final int minutes;
const UpdateScheduleEvent(this.scheduleType, this.hours, this.minutes); const UpdateScheduleEvent(
{required this.scheduleMode, required this.hours, required this.minutes});
@override @override
List<Object?> get props => [scheduleType, hours, minutes]; List<Object?> get props => [scheduleMode, hours, minutes];
} }
final class StopScheduleEvent extends WaterHeaterEvent {} final class StopScheduleEvent extends WaterHeaterEvent {}
@ -47,3 +48,7 @@ class WaterHeaterFetchBatchStatusEvent extends WaterHeaterEvent {
@override @override
List<Object?> get props => [deviceId]; List<Object?> get props => [deviceId];
} }
class ShowScheduleViewEvent extends WaterHeaterEvent {
const ShowScheduleViewEvent();
}

View File

@ -21,7 +21,7 @@ final class WaterHeaterToggleState extends WaterHeaterState {
} }
final class WaterHeaterScheduleState extends WaterHeaterState { final class WaterHeaterScheduleState extends WaterHeaterState {
final ScheduleType scheduleType; final ScheduleModes scheduleType;
final int hours; final int hours;
final int minutes; final int minutes;
final bool isActive; final bool isActive;
@ -74,3 +74,20 @@ final class WaterHeaterBatchFailedState extends WaterHeaterState {
} }
final class WaterHeaterLoadingState extends WaterHeaterState {} final class WaterHeaterLoadingState extends WaterHeaterState {}
class WaterHeaterScheduleViewState extends WaterHeaterState {
final ScheduleModes scheduleMode;
final int hours;
final int minutes;
final bool isActive;
const WaterHeaterScheduleViewState({
required this.scheduleMode,
required this.hours,
required this.minutes,
required this.isActive,
});
@override
List<Object> get props => [scheduleMode, hours, minutes];
}

View File

@ -28,6 +28,8 @@ class WaterHeaterDeviceControl extends StatelessWidget
return const Center(child: CircularProgressIndicator()); return const Center(child: CircularProgressIndicator());
} else if (state is WaterHeaterDeviceStatusLoaded) { } else if (state is WaterHeaterDeviceStatusLoaded) {
return _buildStatusControls(context, state.status); return _buildStatusControls(context, state.status);
} else if (state is WaterHeaterScheduleViewState) {
return _buildScheduleView(context, state);
} else if (state is WaterHeaterFailedState || } else if (state is WaterHeaterFailedState ||
state is WaterHeaterBatchFailedState) { state is WaterHeaterBatchFailedState) {
return const Center(child: Text('Error fetching status')); return const Center(child: Text('Error fetching status'));
@ -66,39 +68,223 @@ class WaterHeaterDeviceControl extends StatelessWidget
)); ));
}, },
), ),
DeviceControlsContainer( GestureDetector(
child: Column( onTap: () {
crossAxisAlignment: CrossAxisAlignment.start, context.read<WaterHeaterBloc>().add(const ShowScheduleViewEvent());
children: [ },
Container( child: DeviceControlsContainer(
width: 60, child: Column(
height: 60, crossAxisAlignment: CrossAxisAlignment.start,
decoration: const BoxDecoration( children: [
shape: BoxShape.circle, Container(
color: ColorsManager.whiteColors, width: 60,
), height: 60,
margin: const EdgeInsets.symmetric(horizontal: 4), decoration: const BoxDecoration(
padding: const EdgeInsets.all(12), shape: BoxShape.circle,
child: ClipOval( color: ColorsManager.whiteColors,
child: SvgPicture.asset( ),
Assets.scheduling, margin: const EdgeInsets.symmetric(horizontal: 4),
fit: BoxFit.fill, padding: const EdgeInsets.all(12),
child: ClipOval(
child: SvgPicture.asset(
Assets.scheduling,
fit: BoxFit.fill,
),
), ),
), ),
), const Spacer(),
const Spacer(), Text(
Text( 'Scheduling',
'Scheduling', textAlign: TextAlign.center,
textAlign: TextAlign.center, style: context.textTheme.titleMedium!.copyWith(
style: context.textTheme.titleMedium!.copyWith( fontWeight: FontWeight.w400,
fontWeight: FontWeight.w400, color: ColorsManager.blackColor,
color: ColorsManager.blackColor, ),
), ),
), ],
], ),
), ),
) )
], ],
); );
} }
Widget _buildScheduleView(
BuildContext context, WaterHeaterScheduleViewState state) {
return Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
'Scheduling',
style: context.textTheme.titleLarge!.copyWith(
fontWeight: FontWeight.bold,
color: ColorsManager.dialogBlueTitle,
),
),
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: ListTile(
title: const Text('Countdown'),
leading: Radio<ScheduleModes>(
value: ScheduleModes.countdown,
groupValue: state.scheduleMode,
onChanged: (ScheduleModes? value) {
if (value != null) {
context.read<WaterHeaterBloc>().add(UpdateScheduleEvent(
scheduleMode: value,
hours: state.hours,
minutes: state.minutes,
));
}
},
),
),
),
Expanded(
child: ListTile(
title: const Text('Schedule'),
leading: Radio<ScheduleModes>(
value: ScheduleModes.schedule,
groupValue: state.scheduleMode,
onChanged: (ScheduleModes? value) {
if (value != null) {
context.read<WaterHeaterBloc>().add(UpdateScheduleEvent(
scheduleMode: value,
hours: state.hours,
minutes: state.minutes,
));
}
},
),
),
),
Expanded(
child: ListTile(
title: const Text('Circulate'),
leading: Radio<ScheduleModes>(
value: ScheduleModes.circulate,
groupValue: state.scheduleMode,
onChanged: (ScheduleModes? value) {
if (value != null) {
context.read<WaterHeaterBloc>().add(UpdateScheduleEvent(
scheduleMode: value,
hours: state.hours,
minutes: state.minutes,
));
}
},
),
),
),
Expanded(
child: ListTile(
title: const Text('Inching'),
leading: Radio<ScheduleModes>(
value: ScheduleModes.inching,
groupValue: state.scheduleMode,
onChanged: (ScheduleModes? value) {
if (value != null) {
context.read<WaterHeaterBloc>().add(UpdateScheduleEvent(
scheduleMode: value,
hours: state.hours,
minutes: state.minutes,
));
}
},
),
),
),
],
),
const SizedBox(height: 20),
if (state.scheduleMode == ScheduleModes.countdown ||
state.scheduleMode == ScheduleModes.inching) ...[
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
// Hours input
_buildTimeInputField(
label: 'h',
initialValue: state.hours.toString(),
onChanged: (value) {
int hours = int.tryParse(value) ?? 0;
context.read<WaterHeaterBloc>().add(UpdateScheduleEvent(
scheduleMode: state.scheduleMode,
hours: hours,
minutes: state.minutes,
));
},
),
const SizedBox(width: 10),
// Minutes input
_buildTimeInputField(
label: 'm',
initialValue: state.minutes.toString(),
onChanged: (value) {
int minutes = int.tryParse(value) ?? 0;
context.read<WaterHeaterBloc>().add(UpdateScheduleEvent(
scheduleMode: state.scheduleMode,
hours: state.hours,
minutes: minutes,
));
},
),
],
),
],
const SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: () {
Navigator.of(context)
.pop(); // Close the dialog or scheduling view
},
style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey[400],
),
child: const Text('Cancel'),
),
const SizedBox(width: 20),
ElevatedButton(
onPressed: () {
// Handle saving schedule logic
},
child: const Text('Save'),
),
],
),
],
),
);
}
Widget _buildTimeInputField({
required String label,
required String initialValue,
required Function(String) onChanged,
}) {
return Column(
children: [
Text(label, style: const TextStyle(fontSize: 18)),
SizedBox(
width: 50,
child: TextField(
keyboardType: TextInputType.number,
textAlign: TextAlign.center,
decoration: const InputDecoration(border: UnderlineInputBorder()),
onChanged: onChanged,
controller: TextEditingController(text: initialValue),
),
),
],
);
}
} }