diff --git a/lib/widgets/alarm_widgets/fixed_time_alarm_form.dart b/lib/widgets/alarm_widgets/fixed_time_alarm_form.dart index 6f34537..f674e4b 100644 --- a/lib/widgets/alarm_widgets/fixed_time_alarm_form.dart +++ b/lib/widgets/alarm_widgets/fixed_time_alarm_form.dart @@ -1,19 +1,160 @@ import 'package:flutter/material.dart'; -import '../../model/requests/create_alarm_request.dart'; +import '../../app_theme.dart' show AppTheme; import '../../model/requests/create_fixed_time_alarm_request.dart'; +import '../../service/tools.dart'; +import '../../service/validators.dart'; -class FixedTimeAlarmForm extends StatelessWidget { +class FixedTimeAlarmForm extends StatefulWidget { const FixedTimeAlarmForm({ super.key, required this.request, required this.onChanged, }); final CreateFixedTimeAlarmRequest request; - final ValueChanged onChanged; + final ValueChanged onChanged; + + @override + State createState() => _FixedTimeAlarmFormState(); +} + +class _FixedTimeAlarmFormState extends State { + final dueDateController = TextEditingController(); + final dueTimeController = TextEditingController(); + final dueDateFocusNode = FocusNode(); + final dueTimeFocusNode = FocusNode(); + bool isDueTimeEnabled = false; + + @override + void initState() { + dueDateController.addListener(onDueDateChanged); + dueTimeController.addListener(onDueTimeChanged); + + super.initState(); + } @override Widget build(BuildContext context) { - return const Placeholder(); + return Flex( + direction: Axis.horizontal, + children: [ + Flexible( + flex: 3, + child: TextFormField( + focusNode: dueDateFocusNode, + controller: dueDateController, + onFieldSubmitted: (_) { + isDueTimeEnabled ? dueDateFocusNode.nextFocus() : null; + }, + decoration: InputDecoration( + label: Text('Due Date'), + suffixIcon: IconButton( + onPressed: () async { + final result = await onOpenCalendarPickerPressed(); + if (result != null) { + final dateString = getIsoDateString(result); + dueDateController.text = dateString; + maybeEnableDueTime(dateString); + dueTimeFocusNode.requestFocus(); + } + }, + icon: Icon(Icons.calendar_month), + ), + ), + validator: dateTimeValidator, + keyboardType: TextInputType.datetime, + textInputAction: TextInputAction.next, + ), + ), + Padding( + padding: EdgeInsetsGeometry.only(left: AppTheme.formColumnSpacing), + ), + Flexible( + flex: 2, + child: TextFormField( + focusNode: dueTimeFocusNode, + onFieldSubmitted: (_) => dueTimeFocusNode.nextFocus(), + controller: dueTimeController, + enabled: isDueTimeEnabled, + onChanged: (value) {}, + decoration: InputDecoration( + label: Text('Due Time'), + suffixIcon: IconButton( + onPressed: () async { + final result = await onOpenTimePickerPressed(); + if (result != null && context.mounted) { + dueTimeController.text = result.format(context); + } + }, + icon: Icon(Icons.schedule), + ), + ), + validator: timeValidator, + keyboardType: TextInputType.text, + textInputAction: TextInputAction.next, + ), + ), + ], + ); + } + + Future onOpenCalendarPickerPressed() { + return showDialog( + context: context, + builder: (context) => DatePickerDialog( + firstDate: DateTime(DateTime.now().year - 100), + lastDate: DateTime(DateTime.now().year + 100), + initialDate: + DateTime.tryParse(dueDateController.text) ?? DateTime.now(), + ), + ); + } + + Future onOpenTimePickerPressed() { + return showDialog( + context: context, + builder: (context) => TimePickerDialog( + initialTime: TimeOfDay.fromDateTime( + widget.request.triggerAt ?? DateTime.now(), + ), + ), + ); + } + + void maybeEnableDueTime(String value) { + if (value.isNotEmpty && dateTimeValidator(value) == null) { + setState(() { + isDueTimeEnabled = true; + }); + } else if (isDueTimeEnabled) { + setState(() { + isDueTimeEnabled = false; + }); + } + } + + void onDueDateChanged() { + final String value = dueDateController.text; + maybeEnableDueTime(value); + if (dateTimeValidator(value) == null) { + final dateTime = DateTime.tryParse( + '$value ${dueTimeController.text}'.trim(), + ); + if (dateTime != null) { + widget.onChanged(CreateFixedTimeAlarmRequest(triggerAt: dateTime)); + } + } + } + + void onDueTimeChanged() { + final String value = dueTimeController.text; + if (timeValidator(value) == null) { + final dateTime = DateTime.tryParse( + '${dueDateController.text} $value'.trim(), + ); + if (dateTime != null) { + widget.onChanged(CreateFixedTimeAlarmRequest(triggerAt: dateTime)); + } + } } }