mirror of
https://github.com/SyncrowIOT/syncrow-app.git
synced 2025-11-27 02:24:55 +00:00
refactor effective period dialog
This commit is contained in:
132
lib/features/scene/helper/effect_period_helper.dart
Normal file
132
lib/features/scene/helper/effect_period_helper.dart
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:time_picker_spinner/time_picker_spinner.dart';
|
||||||
|
|
||||||
|
class EffectPeriodHelper {
|
||||||
|
static Future<List<String>?> showCustomTimePicker(
|
||||||
|
BuildContext context) async {
|
||||||
|
String selectedStartTime = "00:00";
|
||||||
|
String selectedEndTime = "23:59";
|
||||||
|
PageController pageController = PageController(initialPage: 0);
|
||||||
|
|
||||||
|
DateTime startDateTime = DateTime(2022, 1, 1, 0, 0); // Fixed 00:00
|
||||||
|
DateTime endDateTime = DateTime(2022, 1, 1, 23, 59); // Fixed 23:59
|
||||||
|
|
||||||
|
context.customAlertDialog(
|
||||||
|
alertBody: SizedBox(
|
||||||
|
height: 250,
|
||||||
|
child: PageView(
|
||||||
|
controller: pageController,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
children: [
|
||||||
|
_buildTimePickerPage(
|
||||||
|
context: context,
|
||||||
|
pageController: pageController,
|
||||||
|
isStartTime: true,
|
||||||
|
time: startDateTime,
|
||||||
|
onTimeChange: (time) {
|
||||||
|
selectedStartTime =
|
||||||
|
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}";
|
||||||
|
},
|
||||||
|
),
|
||||||
|
_buildTimePickerPage(
|
||||||
|
context: context,
|
||||||
|
pageController: pageController,
|
||||||
|
isStartTime: false,
|
||||||
|
time: endDateTime,
|
||||||
|
onTimeChange: (time) {
|
||||||
|
selectedEndTime =
|
||||||
|
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}";
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
title: "Custom",
|
||||||
|
onConfirm: () {
|
||||||
|
context.read<EffectPeriodBloc>().add(
|
||||||
|
SetCustomTime(selectedStartTime, selectedEndTime),
|
||||||
|
);
|
||||||
|
context.read<EffectPeriodBloc>().add(
|
||||||
|
const SetPeriod('Custom'),
|
||||||
|
);
|
||||||
|
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
static Widget _buildTimePickerPage({
|
||||||
|
required BuildContext context,
|
||||||
|
required PageController pageController,
|
||||||
|
required bool isStartTime,
|
||||||
|
required DateTime time,
|
||||||
|
required Function(DateTime) onTimeChange,
|
||||||
|
}) {
|
||||||
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
if (!isStartTime)
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
pageController.previousPage(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
curve: Curves.easeIn,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const BodyMedium(text: "Start"),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {},
|
||||||
|
child: BodyMedium(
|
||||||
|
text: isStartTime ? "Start" : "End",
|
||||||
|
style: context.bodyMedium.copyWith(
|
||||||
|
color: ColorsManager.primaryColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (isStartTime)
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
pageController.nextPage(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
curve: Curves.easeIn,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const BodyMedium(text: "End"),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TimePickerSpinner(
|
||||||
|
is24HourMode: false,
|
||||||
|
normalTextStyle: const TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
color: Colors.grey,
|
||||||
|
),
|
||||||
|
highlightedTextStyle: const TextStyle(
|
||||||
|
fontSize: 24,
|
||||||
|
color: ColorsManager.primaryColor,
|
||||||
|
),
|
||||||
|
spacing: 20,
|
||||||
|
itemHeight: 50,
|
||||||
|
isForce2Digits: true,
|
||||||
|
time: time,
|
||||||
|
onTimeChange: onTimeChange,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
|
import 'package:syncrow_app/features/scene/view/scene_tasks_view.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/bottom_sheet/effective_period_bottom_sheet.dart';
|
import 'package:syncrow_app/features/scene/widgets/effective_period_setting/effective_period_bottom_sheet.dart';
|
||||||
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
import 'package:syncrow_app/features/scene/widgets/scene_list_tile.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
import 'package:syncrow_app/features/shared_widgets/default_container.dart';
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_large.dart';
|
||||||
|
|||||||
@ -1,314 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
||||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
|
||||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart';
|
|
||||||
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
|
||||||
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
|
||||||
import 'package:syncrow_app/utils/context_extension.dart';
|
|
||||||
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
|
||||||
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
|
||||||
import 'package:time_picker_spinner/time_picker_spinner.dart';
|
|
||||||
|
|
||||||
class EffectPeriodBottomSheetContent extends StatefulWidget {
|
|
||||||
const EffectPeriodBottomSheetContent({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
State<EffectPeriodBottomSheetContent> createState() =>
|
|
||||||
_EffectPeriodBottomSheetContentState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _EffectPeriodBottomSheetContentState
|
|
||||||
extends State<EffectPeriodBottomSheetContent> {
|
|
||||||
Future<List<String>?> showCustomTimePicker(BuildContext context) async {
|
|
||||||
String selectedStartTime = "00:00";
|
|
||||||
String selectedEndTime = "23:59";
|
|
||||||
PageController pageController = PageController(initialPage: 0);
|
|
||||||
|
|
||||||
DateTime startDateTime = DateTime(2022, 1, 1, 0, 0); // Fixed 00:00
|
|
||||||
DateTime endDateTime = DateTime(2022, 1, 1, 23, 59); // Fixed 23:59
|
|
||||||
|
|
||||||
context.customAlertDialog(
|
|
||||||
alertBody: SizedBox(
|
|
||||||
height: 250,
|
|
||||||
child: PageView(
|
|
||||||
controller: pageController,
|
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {},
|
|
||||||
child: BodyMedium(
|
|
||||||
text: "Start",
|
|
||||||
style: context.bodyMedium.copyWith(
|
|
||||||
color: ColorsManager.primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
pageController.nextPage(
|
|
||||||
duration: const Duration(milliseconds: 300),
|
|
||||||
curve: Curves.easeIn,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: const BodyMedium(
|
|
||||||
text: "End",
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TimePickerSpinner(
|
|
||||||
is24HourMode: false,
|
|
||||||
normalTextStyle: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
highlightedTextStyle: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
color: ColorsManager.primaryColor,
|
|
||||||
),
|
|
||||||
spacing: 20,
|
|
||||||
itemHeight: 50,
|
|
||||||
isForce2Digits: true,
|
|
||||||
time: startDateTime,
|
|
||||||
onTimeChange: (time) {
|
|
||||||
selectedStartTime =
|
|
||||||
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}";
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16),
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
||||||
children: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
pageController.previousPage(
|
|
||||||
duration: const Duration(milliseconds: 300),
|
|
||||||
curve: Curves.easeIn,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
child: const BodyMedium(text: "Start"),
|
|
||||||
),
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {},
|
|
||||||
child: BodyMedium(
|
|
||||||
text: "End",
|
|
||||||
style: context.bodyMedium.copyWith(
|
|
||||||
color: ColorsManager.primaryColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TimePickerSpinner(
|
|
||||||
is24HourMode: false,
|
|
||||||
normalTextStyle: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
color: Colors.grey,
|
|
||||||
),
|
|
||||||
highlightedTextStyle: const TextStyle(
|
|
||||||
fontSize: 24,
|
|
||||||
color: ColorsManager.primaryColor,
|
|
||||||
),
|
|
||||||
spacing: 20,
|
|
||||||
itemHeight: 50,
|
|
||||||
isForce2Digits: true,
|
|
||||||
time: endDateTime,
|
|
||||||
onTimeChange: (time) {
|
|
||||||
selectedEndTime =
|
|
||||||
"${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}";
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
title: "Custom",
|
|
||||||
onConfirm: () {
|
|
||||||
context.read<EffectPeriodBloc>().add(
|
|
||||||
SetCustomTime(selectedStartTime, selectedEndTime),
|
|
||||||
);
|
|
||||||
context.read<EffectPeriodBloc>().add(
|
|
||||||
const SetPeriod('Custom'),
|
|
||||||
);
|
|
||||||
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return BlocProvider(
|
|
||||||
create: (context) => EffectPeriodBloc(),
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
BodyMedium(
|
|
||||||
text: 'Effective Period',
|
|
||||||
fontColor: ColorsManager.primaryColorWithOpacity,
|
|
||||||
fontWeight: FontsManager.bold,
|
|
||||||
),
|
|
||||||
const Divider(
|
|
||||||
color: ColorsManager.backgroundColor,
|
|
||||||
),
|
|
||||||
_buildPeriodOptions(context),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
_buildRepeatDays(context),
|
|
||||||
const SizedBox(height: 24),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildPeriodOptions(BuildContext context) {
|
|
||||||
return BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
_buildRadioOption(context, 'All Day', '24 Hours'),
|
|
||||||
_buildRadioOption(context, 'Daytime', 'Sunrise to Sunset'),
|
|
||||||
_buildRadioOption(context, 'Night', 'Sunset to Sunrise'),
|
|
||||||
ListTile(
|
|
||||||
contentPadding: EdgeInsets.zero,
|
|
||||||
onTap: () => showCustomTimePicker(context),
|
|
||||||
title: BodyMedium(
|
|
||||||
text: 'Custom',
|
|
||||||
fontColor: ColorsManager.primaryColorWithOpacity,
|
|
||||||
),
|
|
||||||
subtitle:
|
|
||||||
state.customStartTime != null && state.customEndTime != null
|
|
||||||
? BodySmall(
|
|
||||||
text:
|
|
||||||
'${"${state.customStartTime} AM"} - ${"${state.customEndTime} PM"}',
|
|
||||||
style: context.bodySmall.copyWith(fontSize: 10),
|
|
||||||
)
|
|
||||||
: BodySmall(
|
|
||||||
text: '00:00 AM - 11:59 PM',
|
|
||||||
style: context.bodySmall.copyWith(fontSize: 10),
|
|
||||||
),
|
|
||||||
trailing: Radio<String>(
|
|
||||||
value: 'Custom',
|
|
||||||
groupValue: state.selectedPeriod,
|
|
||||||
onChanged: (value) async {},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildRadioOption(
|
|
||||||
BuildContext context, String value, String subtitle) {
|
|
||||||
return BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return ListTile(
|
|
||||||
contentPadding: EdgeInsets.zero,
|
|
||||||
onTap: () {
|
|
||||||
context.read<EffectPeriodBloc>().add(SetPeriod(value));
|
|
||||||
},
|
|
||||||
title: BodyMedium(text: value),
|
|
||||||
subtitle: BodySmall(
|
|
||||||
text: subtitle,
|
|
||||||
style: context.bodySmall.copyWith(fontSize: 10),
|
|
||||||
),
|
|
||||||
trailing: Radio<String>(
|
|
||||||
value: value,
|
|
||||||
groupValue: state.selectedPeriod,
|
|
||||||
onChanged: (value) {
|
|
||||||
if (value != null) {
|
|
||||||
context.read<EffectPeriodBloc>().add(SetPeriod(value));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
Widget _buildRepeatDays(BuildContext context) {
|
|
||||||
final daysMap = {
|
|
||||||
'Mon': 'M',
|
|
||||||
'Tue': 'T',
|
|
||||||
'Wed': 'W',
|
|
||||||
'Thu': 'T',
|
|
||||||
'Fri': 'F',
|
|
||||||
'Sat': 'S',
|
|
||||||
'Sun': 'S',
|
|
||||||
};
|
|
||||||
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
const BodyMedium(text: 'Repeat'),
|
|
||||||
const SizedBox(width: 8),
|
|
||||||
BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
|
||||||
builder: (context, state) {
|
|
||||||
return Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
||||||
children: daysMap.entries.map((entry) {
|
|
||||||
final day = entry.key;
|
|
||||||
final abbreviation = entry.value;
|
|
||||||
final isSelected = state.selectedDays.contains(day);
|
|
||||||
return Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
|
||||||
child: GestureDetector(
|
|
||||||
onTap: () {
|
|
||||||
context.read<EffectPeriodBloc>().add(ToggleDay(day));
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
shape: BoxShape.circle,
|
|
||||||
border: Border.all(
|
|
||||||
color:
|
|
||||||
isSelected ? Colors.grey : Colors.grey.shade300,
|
|
||||||
width: 1,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: CircleAvatar(
|
|
||||||
radius: 15,
|
|
||||||
backgroundColor: Colors.white,
|
|
||||||
child: Text(
|
|
||||||
abbreviation,
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 20,
|
|
||||||
color:
|
|
||||||
isSelected ? Colors.grey : Colors.grey.shade300,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/widgets/effective_period_setting/period_options.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/widgets/effective_period_setting/repeat_days.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/font_manager.dart';
|
||||||
|
|
||||||
|
import '../../helper/effect_period_helper.dart';
|
||||||
|
|
||||||
|
class EffectPeriodBottomSheetContent extends StatelessWidget {
|
||||||
|
const EffectPeriodBottomSheetContent({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocProvider(
|
||||||
|
create: (context) => EffectPeriodBloc(),
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
BodyMedium(
|
||||||
|
text: 'Effective Period',
|
||||||
|
fontColor: ColorsManager.primaryColorWithOpacity,
|
||||||
|
fontWeight: FontsManager.bold,
|
||||||
|
),
|
||||||
|
const Divider(
|
||||||
|
color: ColorsManager.backgroundColor,
|
||||||
|
),
|
||||||
|
const PeriodOptions(
|
||||||
|
showCustomTimePicker: EffectPeriodHelper.showCustomTimePicker,
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
const RepeatDays(),
|
||||||
|
const SizedBox(height: 24),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,85 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart';
|
||||||
|
import 'package:syncrow_app/utils/context_extension.dart';
|
||||||
|
import 'package:syncrow_app/utils/resource_manager/color_manager.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_small.dart';
|
||||||
|
|
||||||
|
class PeriodOptions extends StatelessWidget {
|
||||||
|
final Future<List<String>?> Function(BuildContext) showCustomTimePicker;
|
||||||
|
|
||||||
|
const PeriodOptions({
|
||||||
|
required this.showCustomTimePicker,
|
||||||
|
super.key,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
_buildRadioOption(context, 'All Day', '24 Hours'),
|
||||||
|
_buildRadioOption(context, 'Daytime', 'Sunrise to Sunset'),
|
||||||
|
_buildRadioOption(context, 'Night', 'Sunset to Sunrise'),
|
||||||
|
ListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
onTap: () => showCustomTimePicker(context),
|
||||||
|
title: BodyMedium(
|
||||||
|
text: 'Custom',
|
||||||
|
fontColor: ColorsManager.primaryColorWithOpacity,
|
||||||
|
),
|
||||||
|
subtitle:
|
||||||
|
state.customStartTime != null && state.customEndTime != null
|
||||||
|
? BodySmall(
|
||||||
|
text:
|
||||||
|
'${"${state.customStartTime} AM"} - ${"${state.customEndTime} PM"}',
|
||||||
|
style: context.bodySmall.copyWith(fontSize: 10),
|
||||||
|
)
|
||||||
|
: BodySmall(
|
||||||
|
text: '00:00 AM - 11:59 PM',
|
||||||
|
style: context.bodySmall.copyWith(fontSize: 10),
|
||||||
|
),
|
||||||
|
trailing: Radio<String>(
|
||||||
|
value: 'Custom',
|
||||||
|
groupValue: state.selectedPeriod,
|
||||||
|
onChanged: (value) async {},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget _buildRadioOption(
|
||||||
|
BuildContext context, String value, String subtitle) {
|
||||||
|
return BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return ListTile(
|
||||||
|
contentPadding: EdgeInsets.zero,
|
||||||
|
onTap: () {
|
||||||
|
context.read<EffectPeriodBloc>().add(SetPeriod(value));
|
||||||
|
},
|
||||||
|
title: BodyMedium(text: value),
|
||||||
|
subtitle: BodySmall(
|
||||||
|
text: subtitle,
|
||||||
|
style: context.bodySmall.copyWith(fontSize: 10),
|
||||||
|
),
|
||||||
|
trailing: Radio<String>(
|
||||||
|
value: value,
|
||||||
|
groupValue: state.selectedPeriod,
|
||||||
|
onChanged: (value) {
|
||||||
|
if (value != null) {
|
||||||
|
context.read<EffectPeriodBloc>().add(SetPeriod(value));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,73 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_bloc.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_event.dart';
|
||||||
|
import 'package:syncrow_app/features/scene/bloc/effective_period/effect_period_state.dart';
|
||||||
|
import 'package:syncrow_app/features/shared_widgets/text_widgets/body_medium.dart';
|
||||||
|
|
||||||
|
class RepeatDays extends StatelessWidget {
|
||||||
|
const RepeatDays({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final daysMap = {
|
||||||
|
'Mon': 'M',
|
||||||
|
'Tue': 'T',
|
||||||
|
'Wed': 'W',
|
||||||
|
'Thu': 'T',
|
||||||
|
'Fri': 'F',
|
||||||
|
'Sat': 'S',
|
||||||
|
'Sun': 'S',
|
||||||
|
};
|
||||||
|
|
||||||
|
return Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
const BodyMedium(text: 'Repeat'),
|
||||||
|
const SizedBox(width: 8),
|
||||||
|
BlocBuilder<EffectPeriodBloc, EffectPeriodState>(
|
||||||
|
builder: (context, state) {
|
||||||
|
return Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
|
children: daysMap.entries.map((entry) {
|
||||||
|
final day = entry.key;
|
||||||
|
final abbreviation = entry.value;
|
||||||
|
final isSelected = state.selectedDays.contains(day);
|
||||||
|
return Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 3.0),
|
||||||
|
child: GestureDetector(
|
||||||
|
onTap: () {
|
||||||
|
context.read<EffectPeriodBloc>().add(ToggleDay(day));
|
||||||
|
},
|
||||||
|
child: Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
shape: BoxShape.circle,
|
||||||
|
border: Border.all(
|
||||||
|
color:
|
||||||
|
isSelected ? Colors.grey : Colors.grey.shade300,
|
||||||
|
width: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: CircleAvatar(
|
||||||
|
radius: 15,
|
||||||
|
backgroundColor: Colors.white,
|
||||||
|
child: Text(
|
||||||
|
abbreviation,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color:
|
||||||
|
isSelected ? Colors.grey : Colors.grey.shade300,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user