mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 13:13:44 +02:00
feat: add template selection for creating availabilities
This commit is contained in:
parent
fe910ef041
commit
04b843d2fd
5 changed files with 161 additions and 9 deletions
|
@ -24,6 +24,8 @@ class AvailabilityTranslations {
|
|||
required this.unavailableForDay,
|
||||
required this.unavailableForMultipleDays,
|
||||
required this.availabilityAddTemplateTitle,
|
||||
required this.availabilityUsedTemplate,
|
||||
required this.availabilityUsedTemplates,
|
||||
required this.availabilityTimeTitle,
|
||||
required this.availabilitiesTimeTitle,
|
||||
required this.availabilityDialogConfirmTitle,
|
||||
|
@ -75,6 +77,8 @@ class AvailabilityTranslations {
|
|||
this.unavailableForDay = "I am not available this day",
|
||||
this.unavailableForMultipleDays = "I am not available these days",
|
||||
this.availabilityAddTemplateTitle = "Add template to availability",
|
||||
this.availabilityUsedTemplate = "Used template",
|
||||
this.availabilityUsedTemplates = "Used templates",
|
||||
this.availabilityTimeTitle = "Start and end time workday",
|
||||
this.availabilitiesTimeTitle = "Start and end time workdays",
|
||||
this.availabilityDialogConfirmTitle =
|
||||
|
@ -156,6 +160,12 @@ class AvailabilityTranslations {
|
|||
/// The title on the template selection section for adding availabilities
|
||||
final String availabilityAddTemplateTitle;
|
||||
|
||||
/// The title on the template selection section when a single template is used
|
||||
final String availabilityUsedTemplate;
|
||||
|
||||
/// The title on the template selection section when more templates are used
|
||||
final String availabilityUsedTemplates;
|
||||
|
||||
/// The title on the time selection section for adding a single availability
|
||||
final String availabilityTimeTitle;
|
||||
|
||||
|
|
|
@ -18,7 +18,8 @@ MaterialPageRoute homePageRoute(VoidCallback onExit) => MaterialPageRoute(
|
|||
);
|
||||
|
||||
///
|
||||
MaterialPageRoute templateOverviewRoute() => MaterialPageRoute(
|
||||
MaterialPageRoute<AvailabilityTemplateModel?> templateOverviewRoute() =>
|
||||
MaterialPageRoute(
|
||||
builder: (context) => AvailabilityTemplateOverview(
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
onEditTemplate: (template) async {
|
||||
|
@ -31,6 +32,9 @@ MaterialPageRoute templateOverviewRoute() => MaterialPageRoute(
|
|||
await Navigator.of(context).push(templateEditDayRoute(null));
|
||||
}
|
||||
},
|
||||
onSelectTemplate: (template) async {
|
||||
Navigator.of(context).pop(template);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
|
@ -52,8 +56,11 @@ MaterialPageRoute availabilityViewRoute(
|
|||
builder: (context) => AvailabilitiesModificationScreen(
|
||||
dateRange: dateRange,
|
||||
initialAvailabilities: initialAvailabilities,
|
||||
onExit: () {
|
||||
Navigator.of(context).pop();
|
||||
onTemplateSelection: () async {
|
||||
var selectedTemplate =
|
||||
Navigator.of(context).push(templateOverviewRoute());
|
||||
return selectedTemplate;
|
||||
},
|
||||
onExit: () => Navigator.of(context).pop(),
|
||||
),
|
||||
);
|
||||
|
|
|
@ -16,6 +16,7 @@ class AvailabilitiesModificationScreen extends StatefulWidget {
|
|||
required this.dateRange,
|
||||
required this.onExit,
|
||||
required this.initialAvailabilities,
|
||||
required this.onTemplateSelection,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
@ -33,6 +34,10 @@ class AvailabilitiesModificationScreen extends StatefulWidget {
|
|||
/// availabilities have been saved
|
||||
final VoidCallback onExit;
|
||||
|
||||
/// Callback for when the user wants to go to the template overview screen to
|
||||
/// select a template
|
||||
final Future<AvailabilityTemplateModel?> Function() onTemplateSelection;
|
||||
|
||||
@override
|
||||
State<AvailabilitiesModificationScreen> createState() =>
|
||||
_AvailabilitiesModificationScreenState();
|
||||
|
@ -41,6 +46,7 @@ class AvailabilitiesModificationScreen extends StatefulWidget {
|
|||
class _AvailabilitiesModificationScreenState
|
||||
extends State<AvailabilitiesModificationScreen> {
|
||||
late AvailabilityModel _availability;
|
||||
late List<AvailabilityTemplateModel> _selectedTemplates;
|
||||
bool _clearAvailability = false;
|
||||
TimeOfDay? _startTime;
|
||||
TimeOfDay? _endTime;
|
||||
|
@ -56,6 +62,7 @@ class _AvailabilitiesModificationScreenState
|
|||
endDate: widget.dateRange.end,
|
||||
breaks: [],
|
||||
);
|
||||
_selectedTemplates = widget.initialAvailabilities.getUniqueTemplates();
|
||||
}
|
||||
|
||||
@override
|
||||
|
@ -121,7 +128,22 @@ class _AvailabilitiesModificationScreenState
|
|||
},
|
||||
);
|
||||
|
||||
var templateSelection = const AvailabilityTemplateSelection();
|
||||
var templateSelection = AvailabilityTemplateSelection(
|
||||
selectedTemplates: _selectedTemplates,
|
||||
onTemplateAdd: () async {
|
||||
var template = await widget.onTemplateSelection();
|
||||
if (template != null) {
|
||||
setState(() {
|
||||
_selectedTemplates = [template];
|
||||
});
|
||||
}
|
||||
},
|
||||
onTemplatesRemoved: () {
|
||||
setState(() {
|
||||
_selectedTemplates = [];
|
||||
});
|
||||
},
|
||||
);
|
||||
|
||||
var timeSelection = AvailabilityTimeSelection(
|
||||
dateRange: widget.dateRange,
|
||||
|
|
|
@ -10,6 +10,7 @@ class AvailabilityTemplateOverview extends HookWidget {
|
|||
required this.onExit,
|
||||
required this.onEditTemplate,
|
||||
required this.onAddTemplate,
|
||||
this.onSelectTemplate,
|
||||
super.key,
|
||||
});
|
||||
|
||||
|
@ -22,6 +23,9 @@ class AvailabilityTemplateOverview extends HookWidget {
|
|||
/// Callback for when the user goes to create a new template
|
||||
final void Function(AvailabilityTemplateType type) onAddTemplate;
|
||||
|
||||
/// Callback for when the user selects a template
|
||||
final void Function(AvailabilityTemplateModel template)? onSelectTemplate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
var theme = Theme.of(context);
|
||||
|
@ -48,6 +52,7 @@ class AvailabilityTemplateOverview extends HookWidget {
|
|||
sectionTitle: translations.dayTemplates,
|
||||
createButtonText: translations.createDayTemplate,
|
||||
onEditTemplate: onEditTemplate,
|
||||
onSelectTemplate: onSelectTemplate,
|
||||
onAddTemplate: () => onAddTemplate(AvailabilityTemplateType.day),
|
||||
templatesSnapshot: dayTemplatesSnapshot,
|
||||
);
|
||||
|
@ -57,6 +62,7 @@ class AvailabilityTemplateOverview extends HookWidget {
|
|||
createButtonText: translations.createWeekTemplate,
|
||||
templatesSnapshot: weekTemplatesSnapshot,
|
||||
onEditTemplate: onEditTemplate,
|
||||
onSelectTemplate: onSelectTemplate,
|
||||
onAddTemplate: () => onAddTemplate(AvailabilityTemplateType.week),
|
||||
);
|
||||
|
||||
|
@ -89,6 +95,7 @@ class _TemplateListSection extends StatelessWidget {
|
|||
required this.templatesSnapshot,
|
||||
required this.onEditTemplate,
|
||||
required this.onAddTemplate,
|
||||
required this.onSelectTemplate,
|
||||
});
|
||||
|
||||
final String sectionTitle;
|
||||
|
@ -96,6 +103,7 @@ class _TemplateListSection extends StatelessWidget {
|
|||
final AsyncSnapshot<List<AvailabilityTemplateModel>> templatesSnapshot;
|
||||
final void Function(AvailabilityTemplateModel template) onEditTemplate;
|
||||
final VoidCallback onAddTemplate;
|
||||
final void Function(AvailabilityTemplateModel template)? onSelectTemplate;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -104,6 +112,12 @@ class _TemplateListSection extends StatelessWidget {
|
|||
var availabilityScope = AvailabilityScope.of(context);
|
||||
var options = availabilityScope.options;
|
||||
|
||||
void onClickTemplate(AvailabilityTemplateModel template) {
|
||||
// if the onSelectTemplate is set the user can select a template
|
||||
// The user will need to click on the edit button to edit
|
||||
(onSelectTemplate ?? onEditTemplate).call(template);
|
||||
}
|
||||
|
||||
var templateCreationButton = InkWell(
|
||||
hoverColor: Colors.transparent,
|
||||
onTap: onAddTemplate,
|
||||
|
@ -136,7 +150,7 @@ class _TemplateListSection extends StatelessWidget {
|
|||
for (var template
|
||||
in templatesSnapshot.data ?? <AvailabilityTemplateModel>[]) ...[
|
||||
GestureDetector(
|
||||
onTap: () => onEditTemplate(template),
|
||||
onTap: () => onClickTemplate(template),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
margin: const EdgeInsets.only(top: 8),
|
||||
|
@ -157,7 +171,10 @@ class _TemplateListSection extends StatelessWidget {
|
|||
const SizedBox(width: 8),
|
||||
Text(template.name, style: textTheme.bodyLarge),
|
||||
const Spacer(),
|
||||
const Icon(Icons.edit),
|
||||
GestureDetector(
|
||||
onTap: () => onEditTemplate(template),
|
||||
child: const Icon(Icons.edit),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
import "package:flutter/material.dart";
|
||||
import "package:flutter_availability/src/util/scope.dart";
|
||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||
|
||||
/// Selection of the template to use for the availability
|
||||
///
|
||||
|
@ -8,9 +10,103 @@ import "package:flutter/material.dart";
|
|||
/// templates.
|
||||
class AvailabilityTemplateSelection extends StatelessWidget {
|
||||
/// Constructor
|
||||
const AvailabilityTemplateSelection({super.key});
|
||||
const AvailabilityTemplateSelection({
|
||||
required this.selectedTemplates,
|
||||
required this.onTemplateAdd,
|
||||
required this.onTemplatesRemoved,
|
||||
super.key,
|
||||
});
|
||||
|
||||
/// The currently selected templates
|
||||
final List<AvailabilityTemplateModel> selectedTemplates;
|
||||
|
||||
/// Callback for when the user selects a template
|
||||
final VoidCallback onTemplateAdd;
|
||||
|
||||
/// Callback for when the user wants to remove the templates
|
||||
/// There might be multiple templates and they can only be removed all at once
|
||||
final VoidCallback onTemplatesRemoved;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) =>
|
||||
const SizedBox(height: 50, child: Placeholder());
|
||||
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 titleText = selectedTemplates.isEmpty
|
||||
? translations.availabilityAddTemplateTitle
|
||||
: selectedTemplates.length > 1
|
||||
? translations.availabilityUsedTemplates
|
||||
: translations.availabilityUsedTemplate;
|
||||
|
||||
var addButton = options.bigTextButtonWrapperBuilder(
|
||||
context,
|
||||
onTemplateAdd,
|
||||
options.bigTextButtonBuilder(
|
||||
context,
|
||||
onTemplateAdd,
|
||||
Text(translations.addButton),
|
||||
),
|
||||
);
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
titleText,
|
||||
style: textTheme.titleMedium,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
if (selectedTemplates.isEmpty) ...[
|
||||
addButton,
|
||||
] else ...[
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: theme.colorScheme.primary,
|
||||
width: 1,
|
||||
),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
),
|
||||
child: Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
for (var template in selectedTemplates) ...[
|
||||
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),
|
||||
],
|
||||
),
|
||||
if (template != selectedTemplates.last)
|
||||
const SizedBox(height: 12),
|
||||
],
|
||||
],
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: onTemplatesRemoved,
|
||||
child: const Icon(Icons.remove),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue