From 134f827f3acf2a95afffbc5879e50bb42b69e33c Mon Sep 17 00:00:00 2001 From: Freek van de Ven Date: Fri, 19 Jul 2024 10:48:20 +0200 Subject: [PATCH] fix: allow clearing the duration from the pause dialog --- .../src/ui/view_models/break_view_model.dart | 38 +++++++++++-------- .../lib/src/ui/widgets/input_fields.dart | 4 +- .../lib/src/ui/widgets/pause_selection.dart | 13 +++++-- .../lib/src/models/availability.dart | 27 ++++++------- .../lib/src/models/templates.dart | 3 +- .../test/models_templates_test.dart | 2 +- 6 files changed, 51 insertions(+), 36 deletions(-) diff --git a/packages/flutter_availability/lib/src/ui/view_models/break_view_model.dart b/packages/flutter_availability/lib/src/ui/view_models/break_view_model.dart index b6f3aab..5bc7552 100644 --- a/packages/flutter_availability/lib/src/ui/view_models/break_view_model.dart +++ b/packages/flutter_availability/lib/src/ui/view_models/break_view_model.dart @@ -7,7 +7,7 @@ class BreakViewModel { const BreakViewModel({ this.startTime, this.endTime, - this.duration, + this.submittedDuration, }); /// Create a [BreakViewModel] from a [AvailabilityBreakModel] @@ -17,7 +17,7 @@ class BreakViewModel { BreakViewModel( startTime: TimeOfDay.fromDateTime(data.startTime), endTime: TimeOfDay.fromDateTime(data.endTime), - duration: data.duration, + submittedDuration: data.submittedDuration, ); /// The start time for this break @@ -26,20 +26,18 @@ class BreakViewModel { /// The end time for this break final TimeOfDay? endTime; - /// The full duration of the actual break. + /// The full duration of the actual break. This is filled in by the users and + /// stays null if the user has not filled it in. /// /// This is allowed to diverge from the difference between [startTime] and /// [endTime] to indicate that the break is somewhere between [startTime] and /// [endTime] - final Duration? duration; + final Duration? submittedDuration; - /// Get the duration in minutes + /// Get the duration of the break /// If the duration is null, return the difference between the start and end /// time in minutes - int get durationInMinutes => - duration?.inMinutes ?? - ((endTime!.hour * 60 + endTime!.minute) - - (startTime!.hour * 60 + startTime!.minute)); + Duration get duration => submittedDuration ?? toBreak().duration; /// Returns true if the break is valid /// The start is before the end and the duration is equal or lower than the @@ -54,11 +52,11 @@ class BreakViewModel { if (startDateTime.isAfter(endDateTime)) { return false; } - if (duration == null) { + if (submittedDuration == null) { return true; } var actualDuration = endDateTime.difference(startDateTime); - return duration! <= actualDuration; + return submittedDuration! <= actualDuration; } /// Whether the save/next button should be enabled @@ -66,21 +64,22 @@ class BreakViewModel { /// Convert to [AvailabilityBreakModel] for saving AvailabilityBreakModel toBreak() => AvailabilityBreakModel( - startTime: DateTime(0, 0, 0, startTime!.hour, startTime!.minute), - endTime: DateTime(0, 0, 0, endTime!.hour, endTime!.minute), - duration: duration, + startTime: + DateTime(0, 0, 0, startTime?.hour ?? 0, startTime?.minute ?? 0), + endTime: DateTime(0, 0, 0, endTime?.hour ?? 0, endTime?.minute ?? 0), + submittedDuration: submittedDuration, ); /// Create a copy with new values BreakViewModel copyWith({ TimeOfDay? startTime, TimeOfDay? endTime, - Duration? duration, + Duration? submittedDuration, }) => BreakViewModel( startTime: startTime ?? this.startTime, endTime: endTime ?? this.endTime, - duration: duration ?? this.duration, + submittedDuration: submittedDuration ?? this.submittedDuration, ); /// compareto method to order two breaks based on their start time @@ -92,4 +91,11 @@ class BreakViewModel { other.startTime!.minute; return difference; } + + /// Clear the duration of the break + BreakViewModel clearDuration() => BreakViewModel( + startTime: startTime, + endTime: endTime, + submittedDuration: null, + ); } diff --git a/packages/flutter_availability/lib/src/ui/widgets/input_fields.dart b/packages/flutter_availability/lib/src/ui/widgets/input_fields.dart index 9cd728a..c129db0 100644 --- a/packages/flutter_availability/lib/src/ui/widgets/input_fields.dart +++ b/packages/flutter_availability/lib/src/ui/widgets/input_fields.dart @@ -67,7 +67,7 @@ class DurationInputField extends StatelessWidget { final Duration? initialValue; /// - final void Function(Duration) onDurationChanged; + final void Function(Duration?) onDurationChanged; @override Widget build(BuildContext context) { @@ -79,6 +79,8 @@ class DurationInputField extends StatelessWidget { var duration = int.tryParse(value); if (duration != null) { onDurationChanged(Duration(minutes: duration)); + } else { + onDurationChanged(null); } } diff --git a/packages/flutter_availability/lib/src/ui/widgets/pause_selection.dart b/packages/flutter_availability/lib/src/ui/widgets/pause_selection.dart index 813ca0e..73621ad 100644 --- a/packages/flutter_availability/lib/src/ui/widgets/pause_selection.dart +++ b/packages/flutter_availability/lib/src/ui/widgets/pause_selection.dart @@ -146,7 +146,7 @@ class BreakDisplay extends StatelessWidget { breakModel.endTime!, ); - var breakDuration = breakModel.durationInMinutes; + var breakDuration = breakModel.duration.inMinutes; return InkWell( onTap: onClick, @@ -246,9 +246,14 @@ class _AvailabilityBreakSelectionDialogState var translations = options.translations; var spacing = options.spacing; - void onUpdateDuration(Duration duration) { + void onUpdateDuration(Duration? duration) { setState(() { - _breakViewModel = _breakViewModel.copyWith(duration: duration); + if (duration != null) { + _breakViewModel = + _breakViewModel.copyWith(submittedDuration: duration); + } else { + _breakViewModel = _breakViewModel.clearDuration(); + } }); } @@ -317,7 +322,7 @@ class _AvailabilityBreakSelectionDialogState Expanded( flex: 2, child: DurationInputField( - initialValue: _breakViewModel.duration, + initialValue: _breakViewModel.submittedDuration, onDurationChanged: onUpdateDuration, ), ), diff --git a/packages/flutter_availability_data_interface/lib/src/models/availability.dart b/packages/flutter_availability_data_interface/lib/src/models/availability.dart index e189bfc..0641b78 100644 --- a/packages/flutter_availability_data_interface/lib/src/models/availability.dart +++ b/packages/flutter_availability_data_interface/lib/src/models/availability.dart @@ -60,8 +60,8 @@ class AvailabilityBreakModel { const AvailabilityBreakModel({ required this.startTime, required this.endTime, - Duration? duration, - }) : _duration = duration; + this.submittedDuration, + }); /// Parses a break from a map. /// @@ -74,7 +74,7 @@ class AvailabilityBreakModel { DateTime.fromMillisecondsSinceEpoch((map["startTime"] ?? 0) as int), endTime: DateTime.fromMillisecondsSinceEpoch((map["endTime"] ?? 0) as int), - duration: map["duration"] != null + submittedDuration: map["duration"] != null ? Duration(minutes: map["duration"] as int) : null, ); @@ -83,35 +83,36 @@ class AvailabilityBreakModel { /// /// If duration is not the same as the difference between [startTime] and /// [endTime], the [startTime] is considered the start of the period of which - /// a break of [_duration] can be held. + /// a break of [submittedDuration] can be held. final DateTime startTime; /// The end time for this break /// /// If duration is not the same as the difference between [startTime] and /// [endTime], the [endTime] is considered the end of the period of which - /// a break of [_duration] can be held. + /// a break of [submittedDuration] can be held. final DateTime endTime; - /// The full duration of the actual break. + /// The full duration of the actual break. This is filled in by the users and + /// stays null if the user has not filled it in. /// /// This is allowed to diverge from the difference between [startTime] and /// [endTime] to indicate that the break is somewhere between [startTime] and /// [endTime] - final Duration? _duration; + final Duration? submittedDuration; /// Results in the set duration, or the difference between [startTime] and /// [endTime] if no duration is set. - Duration get duration => _duration ?? period; + Duration get duration => submittedDuration ?? period; /// The period in which the break will take place. /// - /// Will be the same as [duration] if the initial [_duration] is null + /// Will be the same as [duration] if the initial [submittedDuration] is null Duration get period => endTime.difference(startTime); /// Whether the duration of the break matches the difference between /// [startTime] and [endTime] - bool get isTight => _duration == null || _duration == period; + bool get isTight => submittedDuration == null || submittedDuration == period; /// Copies the current properties into a new instance of /// [AvailabilityBreakModel], except for the properties provided @@ -119,12 +120,12 @@ class AvailabilityBreakModel { AvailabilityBreakModel copyWith({ DateTime? startTime, DateTime? endTime, - Duration? duration, + Duration? submittedDuration, }) => AvailabilityBreakModel( startTime: startTime ?? this.startTime, endTime: endTime ?? this.endTime, - duration: duration ?? _duration, + submittedDuration: submittedDuration ?? this.submittedDuration, ); /// Returns a map variant of this object. @@ -135,6 +136,6 @@ class AvailabilityBreakModel { Map toMap() => { "startTime": startTime.millisecondsSinceEpoch, "endTime": endTime.millisecondsSinceEpoch, - "duration": _duration?.inMinutes, + "duration": submittedDuration?.inMinutes, }; } diff --git a/packages/flutter_availability_data_interface/lib/src/models/templates.dart b/packages/flutter_availability_data_interface/lib/src/models/templates.dart index b112020..2283b42 100644 --- a/packages/flutter_availability_data_interface/lib/src/models/templates.dart +++ b/packages/flutter_availability_data_interface/lib/src/models/templates.dart @@ -331,7 +331,8 @@ class DayTemplateData implements TemplateData { AvailabilityBreakModel( startTime: date.mergeTime(templateBreak.startTime), endTime: date.mergeTime(templateBreak.endTime), - duration: templateBreak.isTight ? null : templateBreak.duration, + submittedDuration: + templateBreak.isTight ? null : templateBreak.duration, ), ], ], diff --git a/packages/flutter_availability_data_interface/test/models_templates_test.dart b/packages/flutter_availability_data_interface/test/models_templates_test.dart index de4369f..43b7464 100644 --- a/packages/flutter_availability_data_interface/test/models_templates_test.dart +++ b/packages/flutter_availability_data_interface/test/models_templates_test.dart @@ -12,7 +12,7 @@ void main() { AvailabilityBreakModel( startTime: asTime(startHour), endTime: asTime(startHour + 1), - duration: const Duration(minutes: 30), + submittedDuration: const Duration(minutes: 30), ); DayTemplateData createTemplate(int startHour) => DayTemplateData(