mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 05:03:44 +02:00
feat: add week template day selector
This commit is contained in:
parent
92703d536d
commit
5b54111850
3 changed files with 197 additions and 5 deletions
|
@ -38,6 +38,8 @@ class AvailabilityTranslations {
|
|||
required this.createWeekTemplate,
|
||||
required this.deleteTemplateButton,
|
||||
required this.dayTemplateTitle,
|
||||
required this.weekTemplateTitle,
|
||||
required this.weekTemplateDayTitle,
|
||||
required this.templateTitleHintText,
|
||||
required this.templateTitleLabel,
|
||||
required this.templateColorLabel,
|
||||
|
@ -61,6 +63,7 @@ class AvailabilityTranslations {
|
|||
required this.periodFormatter,
|
||||
required this.monthYearFormatter,
|
||||
required this.weekDayAbbreviatedFormatter,
|
||||
required this.weekDayFormatter,
|
||||
});
|
||||
|
||||
/// AvailabilityTranslations constructor where everything is optional.
|
||||
|
@ -97,6 +100,8 @@ class AvailabilityTranslations {
|
|||
this.createWeekTemplate = "Create week template",
|
||||
this.deleteTemplateButton = "Delete template",
|
||||
this.dayTemplateTitle = "Day template",
|
||||
this.weekTemplateTitle = "Week template",
|
||||
this.weekTemplateDayTitle = "When",
|
||||
this.templateTitleHintText = "What do you want to call this template?",
|
||||
this.templateTitleLabel = "Template Title",
|
||||
this.templateColorLabel = "Colorlabel",
|
||||
|
@ -123,6 +128,7 @@ class AvailabilityTranslations {
|
|||
this.periodFormatter = _defaultPeriodFormatter,
|
||||
this.monthYearFormatter = _defaultMonthYearFormatter,
|
||||
this.weekDayAbbreviatedFormatter = _defaultWeekDayAbbreviatedFormatter,
|
||||
this.weekDayFormatter = _defaultWeekDayFormatter,
|
||||
this.timeFormatter = _defaultTimeFormatter,
|
||||
});
|
||||
|
||||
|
@ -208,6 +214,12 @@ class AvailabilityTranslations {
|
|||
/// The title for the day template edit screen
|
||||
final String dayTemplateTitle;
|
||||
|
||||
/// The title for the week template edit screen
|
||||
final String weekTemplateTitle;
|
||||
|
||||
/// The title above the section with the week template days
|
||||
final String weekTemplateDayTitle;
|
||||
|
||||
/// The hint text for the template title input field
|
||||
final String templateTitleHintText;
|
||||
|
||||
|
@ -286,12 +298,20 @@ class AvailabilityTranslations {
|
|||
/// the weekday in english
|
||||
final String Function(BuildContext, DateTime) weekDayAbbreviatedFormatter;
|
||||
|
||||
/// Gets the weekday formatted as a string
|
||||
///
|
||||
/// The default implementation is the full name of the weekday in english
|
||||
final String Function(BuildContext, DateTime) weekDayFormatter;
|
||||
|
||||
/// Get the time formatted as a string
|
||||
///
|
||||
/// The default implementation is `HH:mm`
|
||||
final String Function(BuildContext, TimeOfDay) timeFormatter;
|
||||
}
|
||||
|
||||
String _defaultWeekDayFormatter(BuildContext context, DateTime date) =>
|
||||
_getDayName(date.weekday);
|
||||
|
||||
String _defaultTimeFormatter(BuildContext context, TimeOfDay time) =>
|
||||
"${time.hour.toString().padLeft(2, '0')}:"
|
||||
"${time.minute.toString().padLeft(2, '0')}";
|
||||
|
|
|
@ -37,11 +37,8 @@ class CalendarGrid extends StatelessWidget {
|
|||
var calendarDays =
|
||||
_generateCalendarDays(month, days, selectedRange, colors, colorScheme);
|
||||
|
||||
// get the names of the days of the week
|
||||
var dayNames = List.generate(7, (index) {
|
||||
var day = DateTime(2024, 7, 8 + index); // this is a monday
|
||||
return translations.weekDayAbbreviatedFormatter(context, day);
|
||||
});
|
||||
var dayNames =
|
||||
getDaysOfTheWeekAsAbbreviatedStrings(translations, context);
|
||||
|
||||
var calendarDaysRow = Row(
|
||||
children: List.generate(13, (index) {
|
||||
|
@ -122,6 +119,31 @@ class CalendarGrid 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 {
|
||||
///
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
// ignore_for_file: avoid_positional_boolean_parameters
|
||||
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_availability/src/ui/widgets/calendar_grid.dart";
|
||||
import "package:flutter_availability/src/util/scope.dart";
|
||||
|
||||
/// A widget for selecting a day of the week
|
||||
class TemplateWeekDaySelection extends StatefulWidget {
|
||||
/// Creates a [TemplateWeekDaySelection]
|
||||
const TemplateWeekDaySelection({
|
||||
required this.onDaySelected,
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// Callback for when a day is selected
|
||||
final void Function(int) onDaySelected;
|
||||
|
||||
@override
|
||||
State<TemplateWeekDaySelection> createState() =>
|
||||
_TemplateWeekDaySelectionState();
|
||||
}
|
||||
|
||||
class _TemplateWeekDaySelectionState extends State<TemplateWeekDaySelection> {
|
||||
int _selectedDayIndex = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
var textTheme = theme.textTheme;
|
||||
var availabilityScope = AvailabilityScope.of(context);
|
||||
var options = availabilityScope.options;
|
||||
var translations = options.translations;
|
||||
|
||||
var days = getDaysOfTheWeekAsAbbreviatedStrings(translations, context);
|
||||
|
||||
void onDaySelected(bool selected, int index) {
|
||||
if (!selected) return;
|
||||
widget.onDaySelected(index);
|
||||
setState(() {
|
||||
_selectedDayIndex = index;
|
||||
});
|
||||
}
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(translations.weekTemplateDayTitle, style: textTheme.titleMedium),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
height: 72,
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
for (var day in days) ...[
|
||||
_DaySelectionCard(
|
||||
day: day,
|
||||
days: days,
|
||||
selectedDayIndex: _selectedDayIndex,
|
||||
onDaySelected: (selected) =>
|
||||
onDaySelected(selected, days.indexOf(day)),
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DaySelectionCard extends StatelessWidget {
|
||||
const _DaySelectionCard({
|
||||
required this.selectedDayIndex,
|
||||
required this.day,
|
||||
required this.days,
|
||||
required this.onDaySelected,
|
||||
});
|
||||
|
||||
final String day;
|
||||
final List<String> days;
|
||||
|
||||
final int selectedDayIndex;
|
||||
|
||||
final void Function(bool) onDaySelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var index = days.indexOf(day);
|
||||
var isSelected = index == selectedDayIndex;
|
||||
|
||||
return _DaySelectionCardLayout(
|
||||
day: day,
|
||||
isSelected: isSelected,
|
||||
onDaySelected: onDaySelected,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _DaySelectionCardLayout extends StatelessWidget {
|
||||
const _DaySelectionCardLayout({
|
||||
required this.day,
|
||||
required this.isSelected,
|
||||
required this.onDaySelected,
|
||||
});
|
||||
|
||||
final String day;
|
||||
final bool isSelected;
|
||||
|
||||
final void Function(bool) onDaySelected;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
var textTheme = theme.textTheme;
|
||||
var abbreviationTextStyle = textTheme.headlineMedium;
|
||||
|
||||
abbreviationTextStyle = isSelected
|
||||
? abbreviationTextStyle?.copyWith(
|
||||
color: theme.colorScheme.onPrimary,
|
||||
)
|
||||
: abbreviationTextStyle;
|
||||
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: AnimatedContainer(
|
||||
duration: const Duration(milliseconds: 300),
|
||||
height: isSelected ? 72 : 64,
|
||||
width: isSelected ? 72 : 64,
|
||||
child: ChoiceChip(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
padding: EdgeInsets.zero,
|
||||
label: Center(
|
||||
child: Text(
|
||||
day.toUpperCase(),
|
||||
style: abbreviationTextStyle,
|
||||
),
|
||||
),
|
||||
selected: isSelected,
|
||||
showCheckmark: theme.chipTheme.showCheckmark ?? false,
|
||||
onSelected: onDaySelected,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue