mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 13:13:44 +02:00
feat: add week template overview
This commit is contained in:
parent
5b54111850
commit
c7ea82677c
3 changed files with 214 additions and 0 deletions
|
@ -125,6 +125,7 @@ class AvailabilityColors {
|
|||
this.outsideMonthTextColor,
|
||||
this.textDarkColor,
|
||||
this.textLightColor,
|
||||
this.templateWeekOverviewBackgroundColor,
|
||||
this.templateColors = const [
|
||||
Color(0xFF9bb8f2),
|
||||
Color(0xFF4b77d0),
|
||||
|
@ -160,6 +161,11 @@ class AvailabilityColors {
|
|||
/// If not provided the text color will be the theme's text color
|
||||
final Color? textDarkColor;
|
||||
|
||||
/// The color of the background in the template week overview that creates a
|
||||
/// layered effect by interchanging a color and a transparent color
|
||||
/// If not provided the color will be the theme's [ColorScheme.surface]
|
||||
final Color? templateWeekOverviewBackgroundColor;
|
||||
|
||||
/// The colors that are used for the templates
|
||||
final List<Color> templateColors;
|
||||
}
|
||||
|
|
|
@ -43,9 +43,13 @@ class AvailabilityTranslations {
|
|||
required this.templateTitleHintText,
|
||||
required this.templateTitleLabel,
|
||||
required this.templateColorLabel,
|
||||
required this.weekTemplateOverviewTitle,
|
||||
required this.pause,
|
||||
required this.unavailable,
|
||||
required this.time,
|
||||
required this.timeSeparator,
|
||||
required this.timeMinutes,
|
||||
required this.timeMinutesShort,
|
||||
required this.templateTimeLabel,
|
||||
required this.pauseSectionTitle,
|
||||
required this.pauseSectionOptional,
|
||||
|
@ -105,9 +109,13 @@ class AvailabilityTranslations {
|
|||
this.templateTitleHintText = "What do you want to call this template?",
|
||||
this.templateTitleLabel = "Template Title",
|
||||
this.templateColorLabel = "Colorlabel",
|
||||
this.weekTemplateOverviewTitle = "Overview availability",
|
||||
this.pause = "Pause",
|
||||
this.unavailable = "Unavailable",
|
||||
this.time = "Time",
|
||||
this.timeSeparator = "to",
|
||||
this.timeMinutes = "minutes",
|
||||
this.timeMinutesShort = "min",
|
||||
this.templateTimeLabel = "When are you available?",
|
||||
this.pauseSectionTitle = "Add a pause",
|
||||
this.pauseSectionOptional = "(Optional)",
|
||||
|
@ -229,6 +237,15 @@ class AvailabilityTranslations {
|
|||
/// The title above the color selection for templates
|
||||
final String templateColorLabel;
|
||||
|
||||
/// The title for the week overview section
|
||||
final String weekTemplateOverviewTitle;
|
||||
|
||||
/// The label used for pause
|
||||
final String pause;
|
||||
|
||||
/// The label used for unavailable
|
||||
final String unavailable;
|
||||
|
||||
/// The title for time sections
|
||||
final String time;
|
||||
|
||||
|
@ -238,6 +255,9 @@ class AvailabilityTranslations {
|
|||
/// The text used for minutes
|
||||
final String timeMinutes;
|
||||
|
||||
/// The text used for minutes in a short form
|
||||
final String timeMinutesShort;
|
||||
|
||||
/// The label for the template time input
|
||||
final String templateTimeLabel;
|
||||
|
||||
|
|
|
@ -0,0 +1,188 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_availability/src/ui/models/view_template_daydata.dart";
|
||||
import "package:flutter_availability/src/ui/widgets/calendar_grid.dart";
|
||||
import "package:flutter_availability/src/util/scope.dart";
|
||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||
|
||||
/// Shows an overview of the template of a week before saving it
|
||||
class TemplateWeekOverview extends StatelessWidget {
|
||||
///
|
||||
const TemplateWeekOverview({
|
||||
required this.template,
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// The template to show
|
||||
final AvailabilityTemplateModel template;
|
||||
|
||||
@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 colors = options.colors;
|
||||
|
||||
var dayNames = getDaysOfTheWeekAsStrings(translations, context);
|
||||
|
||||
var templateData = template.templateData as WeekTemplateData;
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
translations.weekTemplateOverviewTitle,
|
||||
style: textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
DecoratedBox(
|
||||
decoration: BoxDecoration(
|
||||
color: colors.templateWeekOverviewBackgroundColor ??
|
||||
theme.colorScheme.primaryContainer,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(
|
||||
color: theme.dividerColor,
|
||||
),
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
for (var day in WeekDay.values) ...[
|
||||
_TemplateDayDetailRow(
|
||||
dayName: dayNames[day.index],
|
||||
dayData: templateData.data.containsKey(day)
|
||||
? ViewDayTemplateData.fromDayTemplateData(
|
||||
templateData.data[day]!,
|
||||
)
|
||||
: null,
|
||||
isOdd: day.index.isOdd,
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _TemplateDayDetailRow extends StatelessWidget {
|
||||
const _TemplateDayDetailRow({
|
||||
required this.dayName,
|
||||
required this.dayData,
|
||||
required this.isOdd,
|
||||
});
|
||||
|
||||
/// The name of the day
|
||||
final String dayName;
|
||||
|
||||
/// There odd rows do not have a background color
|
||||
/// This causes a layered effect
|
||||
final bool isOdd;
|
||||
|
||||
/// The data of the day
|
||||
final ViewDayTemplateData? dayData;
|
||||
|
||||
@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 startTime = dayData?.startTime;
|
||||
var endTime = dayData?.endTime;
|
||||
var dayHasAvailability = startTime != null && endTime != null;
|
||||
String? dayPeriod;
|
||||
if (dayHasAvailability) {
|
||||
dayPeriod = "${translations.timeFormatter(context, startTime)} - "
|
||||
"${translations.timeFormatter(context, endTime)}";
|
||||
} else {
|
||||
dayPeriod = translations.unavailable;
|
||||
}
|
||||
|
||||
var breaks = dayData?.breaks ?? <AvailabilityBreakModel>[];
|
||||
|
||||
BoxDecoration? boxDecoration;
|
||||
if (isOdd) {
|
||||
boxDecoration = BoxDecoration(
|
||||
color: Colors.white,
|
||||
border: Border(
|
||||
left: BorderSide(
|
||||
color: theme.dividerColor,
|
||||
),
|
||||
right: BorderSide(
|
||||
color: theme.dividerColor,
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
return Container(
|
||||
decoration: boxDecoration,
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(dayName, style: textTheme.bodyLarge),
|
||||
Text(dayPeriod, style: textTheme.bodyLarge),
|
||||
],
|
||||
),
|
||||
// for each break add a line
|
||||
for (var dayBreak in breaks) ...[
|
||||
const SizedBox(height: 4),
|
||||
_TemplateDayDetailPauseRow(dayBreak: dayBreak),
|
||||
],
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _TemplateDayDetailPauseRow extends StatelessWidget {
|
||||
const _TemplateDayDetailPauseRow({
|
||||
required this.dayBreak,
|
||||
});
|
||||
|
||||
final AvailabilityBreakModel dayBreak;
|
||||
|
||||
@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 startTime = TimeOfDay.fromDateTime(dayBreak.startTime);
|
||||
var endTime = TimeOfDay.fromDateTime(dayBreak.endTime);
|
||||
var startTimeString = translations.timeFormatter(context, startTime);
|
||||
var endTimeString = translations.timeFormatter(context, endTime);
|
||||
var pausePeriod =
|
||||
"$startTimeString - $endTimeString (${dayBreak.duration.inMinutes} "
|
||||
"${translations.timeMinutesShort})";
|
||||
var pauseTextStyle = textTheme.bodyMedium?.copyWith(
|
||||
fontStyle: FontStyle.italic,
|
||||
);
|
||||
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 16),
|
||||
child: Text(
|
||||
translations.pause,
|
||||
style: pauseTextStyle,
|
||||
),
|
||||
),
|
||||
Text(
|
||||
pausePeriod,
|
||||
style: pauseTextStyle,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue