mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 13:13:44 +02:00
fix: extract deeply nested widgets
This commit is contained in:
parent
9efbcbf48b
commit
cdaca15901
5 changed files with 153 additions and 129 deletions
|
@ -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<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,
|
||||
),
|
||||
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),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,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<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 {
|
||||
///
|
||||
|
|
|
@ -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),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue