diff --git a/packages/flutter_availability/lib/src/ui/widgets/availability_template_selection.dart b/packages/flutter_availability/lib/src/ui/widgets/availability_template_selection.dart index 3c34a51..690601f 100644 --- a/packages/flutter_availability/lib/src/ui/widgets/availability_template_selection.dart +++ b/packages/flutter_availability/lib/src/ui/widgets/availability_template_selection.dart @@ -65,56 +65,89 @@ class AvailabilityTemplateSelection extends StatelessWidget { if (selectedTemplates.isEmpty) ...[ addButton, ] else ...[ - // TODO(Joey): Extract this as a widget - Container( - padding: const EdgeInsets.all(12), - decoration: BoxDecoration( - border: Border.all( - color: theme.colorScheme.primary, - width: 1, - ), - // TODO(Joey): This seems like a repeating borderRadius. I can - // understand if these are not configurable, but I do think that - // they should be defined only once. - borderRadius: options.borderRadius, - ), - child: Row( - crossAxisAlignment: CrossAxisAlignment.center, - mainAxisAlignment: MainAxisAlignment.spaceBetween, - children: [ - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - for (var template in selectedTemplates) ...[ - // TODO(Joey): Extract this as a widget - Row( - children: [ - Container( - decoration: BoxDecoration( - color: Color(template.color), - borderRadius: options.borderRadius, - ), - width: 20, - height: 20, - ), - const SizedBox(width: 12), - Text(template.name, style: textTheme.bodyLarge), - ], - ), - if (template != selectedTemplates.last) - const SizedBox(height: 12), - ], - ], - ), - GestureDetector( - onTap: onTemplatesRemoved, - child: const Icon(Icons.remove), - ), - ], - ), + _TemplateList( + selectedTemplates: selectedTemplates, + onTemplatesRemoved: onTemplatesRemoved, ), ], ], ); } } + +class _TemplateList extends StatelessWidget { + const _TemplateList({ + required this.selectedTemplates, + required this.onTemplatesRemoved, + }); + + final List selectedTemplates; + final VoidCallback onTemplatesRemoved; + + @override + Widget build(BuildContext context) { + var theme = Theme.of(context); + var availabilityScope = AvailabilityScope.of(context); + var options = availabilityScope.options; + + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + border: Border.all( + color: theme.colorScheme.primary, + width: 1, + ), + borderRadius: options.borderRadius, + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + for (var template in selectedTemplates) ...[ + _TemplateListItem(template: template), + if (template != selectedTemplates.last) ...[ + const SizedBox(height: 12), + ], + ], + ], + ), + InkWell( + onTap: onTemplatesRemoved, + child: const Icon(Icons.remove), + ), + ], + ), + ); + } +} + +class _TemplateListItem extends StatelessWidget { + const _TemplateListItem({required this.template}); + + final AvailabilityTemplateModel template; + + @override + Widget build(BuildContext context) { + var theme = Theme.of(context); + var availabilityScope = AvailabilityScope.of(context); + var options = availabilityScope.options; + + return Row( + children: [ + Container( + decoration: BoxDecoration( + color: Color(template.color), + borderRadius: options.borderRadius, + ), + width: 20, + height: 20, + ), + const SizedBox(width: 12), + Text(template.name, style: theme.textTheme.bodyLarge), + ], + ); + } +} diff --git a/packages/flutter_availability/lib/src/ui/widgets/calendar_grid.dart b/packages/flutter_availability/lib/src/ui/widgets/calendar_grid.dart index 3743d82..80c8282 100644 --- a/packages/flutter_availability/lib/src/ui/widgets/calendar_grid.dart +++ b/packages/flutter_availability/lib/src/ui/widgets/calendar_grid.dart @@ -2,6 +2,31 @@ import "package:flutter/material.dart"; import "package:flutter_availability/flutter_availability.dart"; import "package:flutter_availability/src/util/scope.dart"; +/// Returns the days of the week as abbreviated strings +/// The first day of the week is monday +List getDaysOfTheWeekAsAbbreviatedStrings( + AvailabilityTranslations translations, + BuildContext context, +) { + var dayNames = List.generate(7, (index) { + var day = DateTime(2024, 7, 8 + index); // this is a monday + return translations.weekDayAbbreviatedFormatter(context, day); + }); + return dayNames; +} + +/// Returns the days of the week as strings +List getDaysOfTheWeekAsStrings( + AvailabilityTranslations translations, + BuildContext context, +) { + var dayNames = List.generate(7, (index) { + var day = DateTime(2024, 7, 8 + index); // this is a monday + return translations.weekDayFormatter(context, day); + }); + return dayNames; +} + /// class CalendarGrid extends StatelessWidget { /// @@ -68,84 +93,68 @@ class CalendarGrid extends StatelessWidget { crossAxisSpacing: 12, mainAxisSpacing: 12, ), - itemBuilder: (context, index) { - var day = calendarDays[index]; - return _CalendarDayTile( - day: day, - onDayTap: onDayTap, - ); - }, + itemBuilder: (context, index) => _CalendarDay( + day: calendarDays[index], + onDayTap: onDayTap, + ), ), ], ); } } -class _CalendarDayTile extends StatelessWidget { - const _CalendarDayTile({ +class _CalendarDay extends StatelessWidget { + const _CalendarDay({ required this.day, required this.onDayTap, }); final CalendarDay day; - final void Function(DateTime) onDayTap; + final void Function(DateTime date) onDayTap; @override Widget build(BuildContext context) { var theme = Theme.of(context); - var textTheme = theme.textTheme; - var colorScheme = theme.colorScheme; var availabilityScope = AvailabilityScope.of(context); var options = availabilityScope.options; var colors = options.colors; - var dayColor = - day.color ?? colors.customAvailabilityColor ?? colorScheme.secondary; + var dayColor = day.color ?? + colors.customAvailabilityColor ?? + theme.colorScheme.secondary; Color? textColor; TextStyle? textStyle; if (day.outsideMonth) { - textColor = colors.outsideMonthTextColor ?? colorScheme.onSurface; - textStyle = textTheme.bodyMedium?.copyWith(color: textColor); + textColor = colors.outsideMonthTextColor ?? theme.colorScheme.onSurface; + textStyle = theme.textTheme.bodyMedium?.copyWith(color: textColor); } else if (day.hasAvailability) { textColor = dayColor; - textStyle = textTheme.titleMedium?.copyWith(color: textColor); + textStyle = theme.textTheme.titleMedium?.copyWith(color: textColor); } - var decoration = day.outsideMonth - ? null - : BoxDecoration( - border: Border( - bottom: BorderSide( - color: textColor ?? Colors.transparent, - width: 1, - ), - ), - ); - return InkWell( onTap: () => onDayTap(day.date), child: DecoratedBox( decoration: BoxDecoration( - borderRadius: BorderRadius.circular(5), + color: dayColor, + borderRadius: options.borderRadius, border: Border.all( - color: day.isSelected ? theme.dividerColor : Colors.transparent, - width: 1.5, + color: day.isSelected && !day.outsideMonth + ? theme.colorScheme.primary + : Colors.transparent, ), ), child: Stack( children: [ Center( - child: Container( - padding: const EdgeInsets.symmetric(horizontal: 4), - decoration: decoration, - child: Text(day.date.day.toString(), style: textStyle), - ), + child: Text(day.date.day.toString(), style: textStyle), ), - if (day.templateDeviation) + if (day.templateDeviation) ...[ Positioned( right: 4, child: Text("*", style: textStyle), ), + ], ], ), ), @@ -153,31 +162,6 @@ class _CalendarDayTile extends StatelessWidget { } } -/// Returns the days of the week as abbreviated strings -/// The first day of the week is monday -List getDaysOfTheWeekAsAbbreviatedStrings( - AvailabilityTranslations translations, - BuildContext context, -) { - var dayNames = List.generate(7, (index) { - var day = DateTime(2024, 7, 8 + index); // this is a monday - return translations.weekDayAbbreviatedFormatter(context, day); - }); - return dayNames; -} - -/// Returns the days of the week as strings -List getDaysOfTheWeekAsStrings( - AvailabilityTranslations translations, - BuildContext context, -) { - var dayNames = List.generate(7, (index) { - var day = DateTime(2024, 7, 8 + index); // this is a monday - return translations.weekDayFormatter(context, day); - }); - return dayNames; -} - /// A Special day in the calendar that needs to be displayed differently class CalendarDay { /// 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 2fac5ce..29bc804 100644 --- a/packages/flutter_availability/lib/src/ui/widgets/pause_selection.dart +++ b/packages/flutter_availability/lib/src/ui/widgets/pause_selection.dart @@ -145,8 +145,7 @@ class BreakDisplay extends StatelessWidget { breakModel.endTime!, ); - // TODO(Joey): Watch out with gesture detectors - return GestureDetector( + return InkWell( onTap: onClick, child: Container( decoration: BoxDecoration( @@ -164,8 +163,10 @@ class BreakDisplay extends StatelessWidget { "$endTime", ), const Spacer(), - // TODO(Joey): Watch out with gesturedetectors - GestureDetector(onTap: onRemove, child: const Icon(Icons.remove)), + InkWell( + onTap: onRemove, + child: const Icon(Icons.remove), + ), ], ), ), diff --git a/packages/flutter_availability/lib/src/util/availability_deviation.dart b/packages/flutter_availability/lib/src/util/availability_deviation.dart index 68af7d5..9585558 100644 --- a/packages/flutter_availability/lib/src/util/availability_deviation.dart +++ b/packages/flutter_availability/lib/src/util/availability_deviation.dart @@ -8,22 +8,10 @@ bool isTemplateDeviated( AvailabilityTemplateModel template, ) { var dayOfWeek = availability.startDate.weekday; - DateTime? templateStartDate; - DateTime? templateEndDate; - - // TODO(Joey): Add a method to a templateModel: getEndTimeForDayOfWeek() - // as well as for start time. Allow polymorphism to resolve this if statement - if (template.templateType == AvailabilityTemplateType.week) { - templateStartDate = (template.templateData as WeekTemplateData) - .data[WeekDay.values[dayOfWeek - 1]] - ?.startTime; - templateEndDate = (template.templateData as WeekTemplateData) - .data[WeekDay.values[dayOfWeek - 1]] - ?.endTime; - } else { - templateStartDate = (template.templateData as DayTemplateData).startTime; - templateEndDate = (template.templateData as DayTemplateData).endTime; - } + var templateStartDate = + template.getStartTimeForDayOfWeek(WeekDay.values[dayOfWeek - 1]); + var templateEndDate = + template.getEndTimeForDayOfWeek(WeekDay.values[dayOfWeek - 1]); if (templateStartDate == null || templateEndDate == null) { return true; 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 2ca66fb..55749ad 100644 --- a/packages/flutter_availability_data_interface/lib/src/models/templates.dart +++ b/packages/flutter_availability_data_interface/lib/src/models/templates.dart @@ -95,6 +95,24 @@ class AvailabilityTemplateModel { templateType: templateType ?? this.templateType, templateData: templateData ?? this.templateData, ); + + /// Get the start time for the specified day in the week for this template + DateTime? getStartTimeForDayOfWeek(WeekDay weekDay) { + if (templateType == AvailabilityTemplateType.week) { + return (templateData as WeekTemplateData).data[weekDay]?.startTime; + } + + return (templateData as DayTemplateData).startTime; + } + + /// Get the end time for the specified day in the week for this template + DateTime? getEndTimeForDayOfWeek(WeekDay weekDay) { + if (templateType == AvailabilityTemplateType.week) { + return (templateData as WeekTemplateData).data[weekDay]?.endTime; + } + + return (templateData as DayTemplateData).endTime; + } } /// Used as the key for defining week-based templates