mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 13:13:44 +02:00
feat: add week template modification screen
This commit is contained in:
parent
c7ea82677c
commit
fd81964b75
5 changed files with 341 additions and 14 deletions
|
@ -37,6 +37,7 @@ class AvailabilityTranslations {
|
|||
required this.createDayTemplate,
|
||||
required this.createWeekTemplate,
|
||||
required this.deleteTemplateButton,
|
||||
required this.editTemplateButton,
|
||||
required this.dayTemplateTitle,
|
||||
required this.weekTemplateTitle,
|
||||
required this.weekTemplateDayTitle,
|
||||
|
@ -60,6 +61,7 @@ class AvailabilityTranslations {
|
|||
required this.pauseDialogPeriodDescription,
|
||||
required this.saveButton,
|
||||
required this.addButton,
|
||||
required this.nextButton,
|
||||
required this.confirmText,
|
||||
required this.cancelText,
|
||||
required this.timeFormatter,
|
||||
|
@ -103,6 +105,7 @@ class AvailabilityTranslations {
|
|||
this.createDayTemplate = "Create day template",
|
||||
this.createWeekTemplate = "Create week template",
|
||||
this.deleteTemplateButton = "Delete template",
|
||||
this.editTemplateButton = "Edit template",
|
||||
this.dayTemplateTitle = "Day template",
|
||||
this.weekTemplateTitle = "Week template",
|
||||
this.weekTemplateDayTitle = "When",
|
||||
|
@ -130,6 +133,7 @@ class AvailabilityTranslations {
|
|||
"Select between which times you want to take a break",
|
||||
this.saveButton = "Save",
|
||||
this.addButton = "Add",
|
||||
this.nextButton = "Next",
|
||||
this.confirmText = "Yes",
|
||||
this.cancelText = "No",
|
||||
this.dayMonthFormatter = _defaultDayMonthFormatter,
|
||||
|
@ -219,6 +223,9 @@ class AvailabilityTranslations {
|
|||
/// The label on the button to delete a template
|
||||
final String deleteTemplateButton;
|
||||
|
||||
/// The label on the button to edit a template
|
||||
final String editTemplateButton;
|
||||
|
||||
/// The title for the day template edit screen
|
||||
final String dayTemplateTitle;
|
||||
|
||||
|
@ -291,6 +298,9 @@ class AvailabilityTranslations {
|
|||
/// The text on the add button
|
||||
final String addButton;
|
||||
|
||||
/// The text on the next button
|
||||
final String nextButton;
|
||||
|
||||
/// The text on the confirm button in the confirmation dialog
|
||||
final String confirmText;
|
||||
|
||||
|
|
|
@ -4,6 +4,7 @@ import "package:flutter_availability/src/service/availability_service.dart";
|
|||
import "package:flutter_availability/src/ui/screens/availability_modification.dart";
|
||||
import "package:flutter_availability/src/ui/screens/template_day_modification.dart";
|
||||
import "package:flutter_availability/src/ui/screens/template_overview.dart";
|
||||
import "package:flutter_availability/src/ui/screens/template_week_modification.dart";
|
||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||
|
||||
///
|
||||
|
@ -17,6 +18,17 @@ MaterialPageRoute homePageRoute(VoidCallback onExit) => MaterialPageRoute(
|
|||
),
|
||||
);
|
||||
|
||||
Future _routeToTemplateEditScreen(
|
||||
BuildContext context,
|
||||
AvailabilityTemplateModel template,
|
||||
) async {
|
||||
if (template.templateType == AvailabilityTemplateType.day) {
|
||||
await Navigator.of(context).push(templateEditDayRoute(template));
|
||||
} else if (template.templateType == AvailabilityTemplateType.week) {
|
||||
await Navigator.of(context).push(templateEditWeekRoute(template));
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
MaterialPageRoute<AvailabilityTemplateModel?> templateOverviewRoute({
|
||||
bool allowSelection = false,
|
||||
|
@ -24,21 +36,22 @@ MaterialPageRoute<AvailabilityTemplateModel?> templateOverviewRoute({
|
|||
MaterialPageRoute(
|
||||
builder: (context) => AvailabilityTemplateOverview(
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
onEditTemplate: (template) async {
|
||||
if (template.templateType == AvailabilityTemplateType.day) {
|
||||
await Navigator.of(context).push(templateEditDayRoute(template));
|
||||
}
|
||||
},
|
||||
onEditTemplate: (template) async =>
|
||||
_routeToTemplateEditScreen(context, template),
|
||||
onAddTemplate: (type) async {
|
||||
if (type == AvailabilityTemplateType.day) {
|
||||
await Navigator.of(context).push(templateEditDayRoute(null));
|
||||
} else if (type == AvailabilityTemplateType.week) {
|
||||
await Navigator.of(context).push(templateEditWeekRoute(null));
|
||||
}
|
||||
},
|
||||
onSelectTemplate: (template) async {
|
||||
if (allowSelection) {
|
||||
Navigator.of(context).pop(template);
|
||||
} else {
|
||||
await _routeToTemplateEditScreen(context, template);
|
||||
}
|
||||
},
|
||||
onSelectTemplate: allowSelection
|
||||
? (template) async {
|
||||
Navigator.of(context).pop(template);
|
||||
}
|
||||
: null,
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -51,6 +64,15 @@ MaterialPageRoute templateEditDayRoute(AvailabilityTemplateModel? template) =>
|
|||
),
|
||||
);
|
||||
|
||||
///
|
||||
MaterialPageRoute templateEditWeekRoute(AvailabilityTemplateModel? template) =>
|
||||
MaterialPageRoute(
|
||||
builder: (context) => WeekTemplateModificationScreen(
|
||||
template: template,
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
),
|
||||
);
|
||||
|
||||
///
|
||||
MaterialPageRoute availabilityViewRoute(
|
||||
DateTimeRange dateRange,
|
||||
|
|
|
@ -0,0 +1,296 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_availability/src/ui/models/view_template_daydata.dart";
|
||||
import "package:flutter_availability/src/ui/widgets/color_selection.dart";
|
||||
import "package:flutter_availability/src/ui/widgets/template_name_input.dart";
|
||||
import "package:flutter_availability/src/ui/widgets/template_time_break.dart";
|
||||
import "package:flutter_availability/src/ui/widgets/template_week_day_selection.dart";
|
||||
import "package:flutter_availability/src/ui/widgets/template_week_overview.dart";
|
||||
import "package:flutter_availability/src/util/scope.dart";
|
||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||
|
||||
/// Page for creating or editing a day template
|
||||
class WeekTemplateModificationScreen extends StatefulWidget {
|
||||
/// Constructor
|
||||
const WeekTemplateModificationScreen({
|
||||
required this.template,
|
||||
required this.onExit,
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// The week template to edit or null if creating a new one
|
||||
final AvailabilityTemplateModel? template;
|
||||
|
||||
/// Callback for when the user wants to navigate back
|
||||
final VoidCallback onExit;
|
||||
|
||||
@override
|
||||
State<WeekTemplateModificationScreen> createState() =>
|
||||
_WeekTemplateModificationScreenState();
|
||||
}
|
||||
|
||||
class _WeekTemplateModificationScreenState
|
||||
extends State<WeekTemplateModificationScreen> {
|
||||
late int? _selectedColor;
|
||||
late AvailabilityTemplateModel _template;
|
||||
bool _editing = true;
|
||||
WeekDay _selectedDay = WeekDay.monday;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
_selectedColor = widget.template?.color;
|
||||
_template = widget.template ??
|
||||
AvailabilityTemplateModel(
|
||||
userId: "1",
|
||||
name: "",
|
||||
color: 0,
|
||||
templateType: AvailabilityTemplateType.week,
|
||||
templateData: WeekTemplateData.forDays(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
var textTheme = theme.textTheme;
|
||||
var availabilityScope = AvailabilityScope.of(context);
|
||||
var service = availabilityScope.service;
|
||||
var options = availabilityScope.options;
|
||||
var translations = options.translations;
|
||||
var spacing = options.spacing;
|
||||
|
||||
var weekTemplateDate = _template.templateData as WeekTemplateData;
|
||||
var selectedDayData = weekTemplateDate.data[_selectedDay];
|
||||
|
||||
Future<void> onDeletePressed() async {
|
||||
await service.deleteTemplate(_template);
|
||||
widget.onExit();
|
||||
}
|
||||
|
||||
void onNextPressed() {
|
||||
setState(() {
|
||||
_editing = false;
|
||||
});
|
||||
}
|
||||
|
||||
void onBackPressed() {
|
||||
if (_editing) {
|
||||
widget.onExit();
|
||||
} else {
|
||||
setState(() {
|
||||
_editing = true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> onSavePressed() async {
|
||||
if (widget.template == null) {
|
||||
await service.createTemplate(_template);
|
||||
} else {
|
||||
await service.updateTemplate(_template);
|
||||
}
|
||||
widget.onExit();
|
||||
}
|
||||
|
||||
var canSave = _template.name.isNotEmpty && _selectedColor != null;
|
||||
var nextButton = options.primaryButtonBuilder(
|
||||
context,
|
||||
canSave ? onNextPressed : null,
|
||||
Text(translations.nextButton),
|
||||
);
|
||||
|
||||
var saveButton = options.primaryButtonBuilder(
|
||||
context,
|
||||
canSave ? onSavePressed : null,
|
||||
Text(translations.saveButton),
|
||||
);
|
||||
|
||||
var deleteButton = options.bigTextButtonBuilder(
|
||||
context,
|
||||
onDeletePressed,
|
||||
Text(translations.deleteTemplateButton),
|
||||
);
|
||||
|
||||
var previousButton = options.bigTextButtonBuilder(
|
||||
context,
|
||||
onBackPressed,
|
||||
Text(translations.editTemplateButton),
|
||||
);
|
||||
|
||||
var title = Center(
|
||||
child: Text(
|
||||
translations.weekTemplateTitle,
|
||||
style: theme.textTheme.displaySmall,
|
||||
),
|
||||
);
|
||||
|
||||
var templateTitleSection = TemplateNameInput(
|
||||
initialValue: _template.name,
|
||||
onNameChanged: (name) {
|
||||
setState(() {
|
||||
_template = _template.copyWith(name: name);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
var colorSection = TemplateColorSelection(
|
||||
selectedColor: _selectedColor,
|
||||
onColorSelected: (color) {
|
||||
setState(() {
|
||||
_selectedColor = color;
|
||||
_template = _template.copyWith(color: color);
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
var editPage = [
|
||||
_WeekTemplateSidePadding(child: templateTitleSection),
|
||||
const SizedBox(height: 24),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: spacing.sidePadding),
|
||||
child: TemplateWeekDaySelection(
|
||||
onDaySelected: (day) {
|
||||
setState(() {
|
||||
_selectedDay = WeekDay.values[day];
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_WeekTemplateSidePadding(
|
||||
child: TemplateTimeAndBreakSection(
|
||||
dayData: selectedDayData != null
|
||||
? ViewDayTemplateData.fromDayTemplateData(
|
||||
selectedDayData,
|
||||
)
|
||||
: const ViewDayTemplateData(),
|
||||
onDayDataChanged: (data) {
|
||||
setState(() {
|
||||
_template = _template.copyWith(
|
||||
templateData:
|
||||
// create a copy of the week template data
|
||||
WeekTemplateData(
|
||||
data: {
|
||||
for (var entry in weekTemplateDate.data.entries)
|
||||
entry.key: entry.value,
|
||||
_selectedDay: data.toDayTemplateData(),
|
||||
},
|
||||
),
|
||||
);
|
||||
});
|
||||
},
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
_WeekTemplateSidePadding(child: colorSection),
|
||||
];
|
||||
|
||||
var overviewPage = _WeekTemplateSidePadding(
|
||||
child: Column(
|
||||
children: [
|
||||
Text(translations.templateTitleLabel, style: textTheme.titleMedium),
|
||||
const SizedBox(height: 8),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.primary,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Color(_template.color),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
width: 20,
|
||||
height: 20,
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Text(_template.name, style: textTheme.bodyLarge),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
TemplateWeekOverview(
|
||||
template: _template,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
||||
var body = CustomScrollView(
|
||||
slivers: [
|
||||
SliverList.list(
|
||||
children: [
|
||||
const SizedBox(height: 40),
|
||||
_WeekTemplateSidePadding(child: title),
|
||||
const SizedBox(height: 24),
|
||||
if (_editing) ...[
|
||||
...editPage,
|
||||
] else ...[
|
||||
overviewPage,
|
||||
],
|
||||
const SizedBox(height: 32),
|
||||
],
|
||||
),
|
||||
SliverFillRemaining(
|
||||
fillOverscroll: false,
|
||||
hasScrollBody: false,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.symmetric(
|
||||
horizontal: spacing.sidePadding,
|
||||
).copyWith(
|
||||
bottom: spacing.bottomButtonPadding,
|
||||
),
|
||||
child: Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
if (_editing) ...[
|
||||
nextButton,
|
||||
] else ...[
|
||||
saveButton,
|
||||
const SizedBox(height: 8),
|
||||
previousButton,
|
||||
],
|
||||
if (widget.template != null) ...[
|
||||
const SizedBox(height: 8),
|
||||
deleteButton,
|
||||
],
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
return options.baseScreenBuilder(context, onBackPressed, body);
|
||||
}
|
||||
}
|
||||
|
||||
/// One of the elements in the week template modification screen doesn't have a
|
||||
/// padding around it that is why all the other elements are wrapped in
|
||||
/// [_WeekTemplateSidePadding]
|
||||
class _WeekTemplateSidePadding extends StatelessWidget {
|
||||
const _WeekTemplateSidePadding({
|
||||
required this.child,
|
||||
});
|
||||
|
||||
final Widget child;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var availabilityScope = AvailabilityScope.of(context);
|
||||
var sidePadding = availabilityScope.options.spacing.sidePadding;
|
||||
return Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: sidePadding),
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
}
|
|
@ -37,8 +37,7 @@ class CalendarGrid extends StatelessWidget {
|
|||
var calendarDays =
|
||||
_generateCalendarDays(month, days, selectedRange, colors, colorScheme);
|
||||
|
||||
var dayNames =
|
||||
getDaysOfTheWeekAsAbbreviatedStrings(translations, context);
|
||||
var dayNames = getDaysOfTheWeekAsAbbreviatedStrings(translations, context);
|
||||
|
||||
var calendarDaysRow = Row(
|
||||
children: List.generate(13, (index) {
|
||||
|
|
Loading…
Reference in a new issue