From ba95f6774bd72f0c8d185998272bd7c80cd5c45f Mon Sep 17 00:00:00 2001 From: ashrafzarkanisala Date: Wed, 18 Sep 2024 21:29:02 +0300 Subject: [PATCH] push schedual counddown design --- .../view/water_heater_device_control.dart | 195 +--------- .../water_heater/widgets/schedual_view.dart | 361 ++++++++++++++++++ 2 files changed, 374 insertions(+), 182 deletions(-) create mode 100644 lib/pages/device_managment/water_heater/widgets/schedual_view.dart diff --git a/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart b/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart index 14193ee0..5974e735 100644 --- a/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart +++ b/lib/pages/device_managment/water_heater/view/water_heater_device_control.dart @@ -6,6 +6,7 @@ import 'package:syncrow_web/pages/device_managment/shared/device_controls_contai import 'package:syncrow_web/pages/device_managment/shared/toggle_widget.dart'; import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart'; import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart'; +import 'package:syncrow_web/pages/device_managment/water_heater/widgets/schedual_view.dart'; import 'package:syncrow_web/utils/color_manager.dart'; import 'package:syncrow_web/utils/constants/assets.dart'; import 'package:syncrow_web/utils/extension/build_context_x.dart'; @@ -29,7 +30,8 @@ class WaterHeaterDeviceControl extends StatelessWidget } else if (state is WaterHeaterDeviceStatusLoaded) { return _buildStatusControls(context, state.status); } else if (state is WaterHeaterScheduleViewState) { - return _buildScheduleView(context, state); + final status = context.read().deviceStatus; + return _buildStatusControls(context, status); } else if (state is WaterHeaterFailedState || state is WaterHeaterBatchFailedState) { return const Center(child: Text('Error fetching status')); @@ -41,7 +43,9 @@ class WaterHeaterDeviceControl extends StatelessWidget } Widget _buildStatusControls( - BuildContext context, WaterHeaterStatusModel status) { + BuildContext context, + WaterHeaterStatusModel status, + ) { final isExtraLarge = isExtraLargeScreenSize(context); final isLarge = isLargeScreenSize(context); final isMedium = isMediumScreenSize(context); @@ -71,7 +75,13 @@ class WaterHeaterDeviceControl extends StatelessWidget ), GestureDetector( onTap: () { - // context.read().add(const ShowScheduleViewEvent()); + context.read().add(const ShowScheduleViewEvent()); + showDialog( + context: context, + builder: (ctx) => BlocProvider.value( + value: BlocProvider.of(context), + child: BuildScheduleView(status: status), + )); }, child: DeviceControlsContainer( child: Column( @@ -109,183 +119,4 @@ class WaterHeaterDeviceControl extends StatelessWidget ], ); } - - 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( - value: ScheduleModes.countdown, - groupValue: state.scheduleMode, - onChanged: (ScheduleModes? value) { - if (value != null) { - context.read().add(UpdateScheduleEvent( - scheduleMode: value, - hours: state.hours, - minutes: state.minutes, - )); - } - }, - ), - ), - ), - Expanded( - child: ListTile( - title: const Text('Schedule'), - leading: Radio( - value: ScheduleModes.schedule, - groupValue: state.scheduleMode, - onChanged: (ScheduleModes? value) { - if (value != null) { - context.read().add(UpdateScheduleEvent( - scheduleMode: value, - hours: state.hours, - minutes: state.minutes, - )); - } - }, - ), - ), - ), - Expanded( - child: ListTile( - title: const Text('Circulate'), - leading: Radio( - value: ScheduleModes.circulate, - groupValue: state.scheduleMode, - onChanged: (ScheduleModes? value) { - if (value != null) { - context.read().add(UpdateScheduleEvent( - scheduleMode: value, - hours: state.hours, - minutes: state.minutes, - )); - } - }, - ), - ), - ), - Expanded( - child: ListTile( - title: const Text('Inching'), - leading: Radio( - value: ScheduleModes.inching, - groupValue: state.scheduleMode, - onChanged: (ScheduleModes? value) { - if (value != null) { - context.read().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().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().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), - ), - ), - ], - ); - } } diff --git a/lib/pages/device_managment/water_heater/widgets/schedual_view.dart b/lib/pages/device_managment/water_heater/widgets/schedual_view.dart new file mode 100644 index 00000000..411621eb --- /dev/null +++ b/lib/pages/device_managment/water_heater/widgets/schedual_view.dart @@ -0,0 +1,361 @@ +import 'package:flutter/cupertino.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_bloc/flutter_bloc.dart'; +import 'package:syncrow_web/pages/common/buttons/default_button.dart'; +import 'package:syncrow_web/pages/device_managment/water_heater/bloc/water_heater_bloc.dart'; +import 'package:syncrow_web/pages/device_managment/water_heater/models/water_heater_status_model.dart'; +import 'package:syncrow_web/utils/color_manager.dart'; +import 'package:syncrow_web/utils/extension/build_context_x.dart'; + +class BuildScheduleView extends StatelessWidget { + const BuildScheduleView({super.key, required this.status}); + + final WaterHeaterStatusModel status; + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: Colors.white, + insetPadding: const EdgeInsets.all(20), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(20), + ), + child: SizedBox( + width: 700, + child: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 40.0, vertical: 20), + child: BlocBuilder( + builder: (context, state) { + if (state is WaterHeaterScheduleViewState) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + const SizedBox(), + Text( + 'Scheduling', + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: 22, + color: ColorsManager.dialogBlueTitle, + ), + ), + Container( + width: 25, + decoration: BoxDecoration( + color: Colors.transparent, + shape: BoxShape.circle, + border: Border.all( + color: Colors.grey, + width: 1.0, + ), + ), + child: IconButton( + padding: EdgeInsets.all(1), + icon: const Icon( + Icons.close, + color: Colors.grey, + size: 18, + ), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + ), + ], + ), + const SizedBox(height: 20), + Text( + 'Type:', + style: context.textTheme.bodySmall!.copyWith( + fontSize: 13, + color: ColorsManager.grayColor, + ), + ), + const SizedBox( + height: 4, + ), + SizedBox( + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + Flexible( + child: ListTile( + contentPadding: EdgeInsets.zero, + title: Text( + 'Countdown', + style: context.textTheme.bodySmall!.copyWith( + fontSize: 13, + color: ColorsManager.blackColor, + ), + ), + leading: Radio( + value: ScheduleModes.countdown, + groupValue: state.scheduleMode, + onChanged: (ScheduleModes? value) { + if (value != null) { + context + .read() + .add(UpdateScheduleEvent( + scheduleMode: value, + hours: state.hours, + minutes: state.minutes, + )); + } + }, + ), + ), + ), + Flexible( + child: ListTile( + contentPadding: EdgeInsets.zero, + title: Text( + 'Schedule', + style: context.textTheme.bodySmall!.copyWith( + fontSize: 13, + color: ColorsManager.blackColor, + ), + ), + leading: Radio( + value: ScheduleModes.schedule, + groupValue: state.scheduleMode, + onChanged: (ScheduleModes? value) { + if (value != null) { + context + .read() + .add(UpdateScheduleEvent( + scheduleMode: value, + hours: state.hours, + minutes: state.minutes, + )); + } + }, + ), + ), + ), + Flexible( + child: ListTile( + title: Text( + 'Circulate', + style: context.textTheme.bodySmall!.copyWith( + fontSize: 13, + color: ColorsManager.blackColor, + ), + ), + leading: Radio( + value: ScheduleModes.circulate, + groupValue: state.scheduleMode, + onChanged: (ScheduleModes? value) { + if (value != null) { + context + .read() + .add(UpdateScheduleEvent( + scheduleMode: value, + hours: state.hours, + minutes: state.minutes, + )); + } + }, + ), + ), + ), + Flexible( + child: ListTile( + title: Text( + 'Inching', + style: context.textTheme.bodySmall!.copyWith( + fontSize: 13, + color: ColorsManager.blackColor, + ), + ), + leading: Radio( + value: ScheduleModes.inching, + groupValue: state.scheduleMode, + onChanged: (ScheduleModes? value) { + if (value != null) { + context + .read() + .add(UpdateScheduleEvent( + scheduleMode: value, + hours: state.hours, + minutes: state.minutes, + )); + } + }, + ), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + if (state.scheduleMode == ScheduleModes.countdown || + state.scheduleMode == ScheduleModes.inching) ...[ + Text( + 'Countdown:', + style: context.textTheme.bodySmall!.copyWith( + fontSize: 13, + color: ColorsManager.grayColor, + ), + ), + const SizedBox(height: 4), + _hourMinutesWheel(state, context) + ], + const SizedBox(height: 20), + Center( + child: SizedBox( + width: 400, + child: Center( + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Expanded( + child: DefaultButton( + height: 40, + onPressed: () { + Navigator.pop(context); + }, + backgroundColor: ColorsManager.boxColor, + child: Text( + 'Cancel', + style: context.textTheme.bodyMedium, + ), + ), + ), + const SizedBox(width: 20), + Expanded( + child: DefaultButton( + height: 40, + onPressed: () {}, + backgroundColor: ColorsManager.primaryColor, + child: const Text('Save'), + ), + ), + ], + ), + ), + ), + ), + ], + ); + } + return const SizedBox(); + }, + ), + ), + ), + ), + ); + } + + Row _hourMinutesWheel( + WaterHeaterScheduleViewState state, BuildContext context) { + return Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + // Hours Picker + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + height: 50, + width: 80, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: ColorsManager.boxColor, + borderRadius: BorderRadius.circular(8), + ), + child: ListWheelScrollView.useDelegate( + controller: + FixedExtentScrollController(initialItem: state.hours), + itemExtent: 40.0, + physics: FixedExtentScrollPhysics(), + onSelectedItemChanged: (int value) { + context.read().add( + UpdateScheduleEvent( + scheduleMode: state.scheduleMode, + hours: value, + minutes: state.minutes, + ), + ); + }, + childDelegate: ListWheelChildBuilderDelegate( + builder: (context, index) { + return Center( + child: Text( + index.toString().padLeft(2, '0'), + style: const TextStyle(fontSize: 24), + ), + ); + }, + childCount: 24, + ), + ), + ), + const SizedBox(height: 8), + const Text( + 'h', + style: TextStyle( + color: ColorsManager.grayColor, + fontSize: 18, + ), + ), + ], + ), + const SizedBox(width: 10), + // Minutes Picker + Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + height: 50, + width: 80, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: ColorsManager.boxColor, + borderRadius: BorderRadius.circular(8), + ), + child: ListWheelScrollView.useDelegate( + controller: + FixedExtentScrollController(initialItem: state.minutes), + itemExtent: 40.0, + physics: FixedExtentScrollPhysics(), + onSelectedItemChanged: (int value) { + context.read().add( + UpdateScheduleEvent( + scheduleMode: state.scheduleMode, + hours: state.hours, + minutes: value, + ), + ); + }, + childDelegate: ListWheelChildBuilderDelegate( + builder: (context, index) { + return Center( + child: Text( + index.toString().padLeft(2, '0'), + style: const TextStyle(fontSize: 24), + ), + ); + }, + childCount: 60, + ), + ), + ), + const SizedBox(height: 8), + const Text( + 'm', + style: TextStyle( + color: ColorsManager.grayColor, + fontSize: 18, + ), + ), + ], + ), + ], + ); + } +}