fix: extract deeply nested widgets

This commit is contained in:
Bart Ribbers 2024-07-18 14:42:59 +02:00 committed by Freek van de Ven
parent 9efbcbf48b
commit cdaca15901
5 changed files with 153 additions and 129 deletions

View file

@ -65,17 +65,38 @@ class AvailabilityTemplateSelection extends StatelessWidget {
if (selectedTemplates.isEmpty) ...[
addButton,
] else ...[
// TODO(Joey): Extract this as a widget
Container(
_TemplateList(
selectedTemplates: selectedTemplates,
onTemplatesRemoved: onTemplatesRemoved,
),
],
],
);
}
}
class _TemplateList extends StatelessWidget {
const _TemplateList({
required this.selectedTemplates,
required this.onTemplatesRemoved,
});
final List<AvailabilityTemplateModel> 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,
),
// 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(
@ -86,8 +107,35 @@ class AvailabilityTemplateSelection extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
for (var template in selectedTemplates) ...[
// TODO(Joey): Extract this as a widget
Row(
_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(
@ -98,22 +146,7 @@ class AvailabilityTemplateSelection extends StatelessWidget {
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),
),
],
),
),
],
Text(template.name, style: theme.textTheme.bodyLarge),
],
);
}

View file

@ -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<String> 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<String> 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,116 +93,75 @@ class CalendarGrid extends StatelessWidget {
crossAxisSpacing: 12,
mainAxisSpacing: 12,
),
itemBuilder: (context, index) {
var day = calendarDays[index];
return _CalendarDayTile(
day: day,
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),
),
),
if (day.templateDeviation)
if (day.templateDeviation) ...[
Positioned(
right: 4,
child: Text("*", style: textStyle),
),
],
],
),
),
);
}
}
/// Returns the days of the week as abbreviated strings
/// The first day of the week is monday
List<String> 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<String> 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 {
///

View file

@ -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),
),
],
),
),

View file

@ -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;

View file

@ -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