diff --git a/lib/widgets/alarm_widgets/relative_time_alarm_form.dart b/lib/widgets/alarm_widgets/relative_time_alarm_form.dart index f5cd82b..bde98d9 100644 --- a/lib/widgets/alarm_widgets/relative_time_alarm_form.dart +++ b/lib/widgets/alarm_widgets/relative_time_alarm_form.dart @@ -1,9 +1,11 @@ import 'package:flutter/material.dart'; +import '../../app_theme.dart'; import '../../model/requests/create_alarm_request.dart'; import '../../model/requests/create_relative_time_alarm_request.dart'; +import '../../service/validators.dart'; -class RelativeTimeAlarmForm extends StatelessWidget { +class RelativeTimeAlarmForm extends StatefulWidget { const RelativeTimeAlarmForm({ super.key, required this.request, @@ -12,8 +14,134 @@ class RelativeTimeAlarmForm extends StatelessWidget { final CreateRelativeTimeAlarmRequest request; final ValueChanged onChanged; + @override + State createState() => _RelativeTimeAlarmFormState(); +} + +class _RelativeTimeAlarmFormState extends State { + final timeController = TextEditingController(); + + static const List> timeUnitOptions = [ + DropdownMenuEntry(value: TimeUnit.minute, label: 'Minutes'), + DropdownMenuEntry(value: TimeUnit.hour, label: 'Hours'), + DropdownMenuEntry(value: TimeUnit.day, label: 'Days'), + ]; + + static const List> timeRelationOptions = [ + DropdownMenuEntry( + value: TimeRelation.before, + label: 'Before', + ), + DropdownMenuEntry(value: TimeRelation.after, label: 'After'), + ]; + + late TimeUnit selectedTimeUnit; + late TimeRelation selectedTimeRelation; + + @override + void initState() { + super.initState(); + + if (widget.request.triggerAt == null) { + selectedTimeUnit = TimeUnit.minute; + selectedTimeRelation = TimeRelation.before; + return; + } + + final duration = widget.request.triggerAt!; + + selectedTimeRelation = duration.isNegative + ? TimeRelation.before + : TimeRelation.after; + + final absDuration = duration.abs(); + + if (absDuration.inMinutes <= 99 && absDuration.inMinutes % 60 != 0) { + selectedTimeUnit = TimeUnit.minute; + timeController.text = absDuration.inMinutes.toString(); + } else if (absDuration.inHours <= 99 && absDuration.inHours % 24 != 0) { + selectedTimeUnit = TimeUnit.hour; + timeController.text = absDuration.inHours.toString(); + } else { + selectedTimeUnit = TimeUnit.day; + timeController.text = absDuration.inDays.toString(); + } + } + @override Widget build(BuildContext context) { - return const Placeholder(); + return Flex( + direction: Axis.horizontal, + spacing: AppTheme.formColumnSpacing, + children: [ + Flexible( + flex: 7, + child: TextFormField( + controller: timeController, + maxLength: 2, + onChanged: onTimeChanged, + validator: (value) => + notEmptyValidator(value) ?? wholeNumberValidator(value), + keyboardType: TextInputType.number, + textInputAction: TextInputAction.next, + decoration: InputDecoration(label: Text('Time'), counterText: ''), + ), + ), + Flexible( + flex: 10, + child: DropdownMenuFormField( + dropdownMenuEntries: timeUnitOptions, + initialSelection: selectedTimeUnit, + showTrailingIcon: false, + onSelected: (value) { + selectedTimeUnit = value!; + onTimeChanged(timeController.text); + }, + ), + ), + Flexible( + flex: 10, + child: DropdownMenuFormField( + dropdownMenuEntries: timeRelationOptions, + initialSelection: selectedTimeRelation, + showTrailingIcon: false, + onSelected: (value) { + selectedTimeRelation = value!; + onTimeChanged(timeController.text); + }, + ), + ), + ], + ); + } + + void onTimeChanged(String value) { + int? time = int.tryParse(value); + if (wholeNumberValidator(value) != null || time == null) return; + Duration duration; + int signedTime = selectedTimeRelation.apply(time); + + switch (selectedTimeUnit) { + case TimeUnit.minute: + duration = Duration(minutes: signedTime); + case TimeUnit.hour: + duration = Duration(hours: signedTime); + case TimeUnit.day: + duration = Duration(days: signedTime); + } + + widget.onChanged(CreateRelativeTimeAlarmRequest(triggerAt: duration)); } } + +enum TimeRelation { + before, + after; + + int apply(int value) => switch (this) { + TimeRelation.before => -value, + TimeRelation.after => value, + }; +} + +enum TimeUnit { minute, hour, day }