feat: add default confirmation dialog

This commit is contained in:
Freek van de Ven 2024-07-10 16:07:49 +02:00 committed by Bart Ribbers
parent 25186412ba
commit e3474e779b
3 changed files with 120 additions and 0 deletions

View file

@ -5,6 +5,7 @@ import "package:flutter_availability/src/config/availability_translations.dart";
import "package:flutter_availability/src/service/local_data_interface.dart"; import "package:flutter_availability/src/service/local_data_interface.dart";
import "package:flutter_availability/src/ui/widgets/default_base_screen.dart"; import "package:flutter_availability/src/ui/widgets/default_base_screen.dart";
import "package:flutter_availability/src/ui/widgets/default_buttons.dart"; import "package:flutter_availability/src/ui/widgets/default_buttons.dart";
import "package:flutter_availability/src/ui/widgets/default_confirmation_dialog.dart";
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart"; import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
/// Class that holds all options for the availability userstory /// Class that holds all options for the availability userstory
@ -19,6 +20,7 @@ class AvailabilityOptions {
this.spacing = const AvailabilitySpacing(), this.spacing = const AvailabilitySpacing(),
this.textStyles = const AvailabilityTextStyles(), this.textStyles = const AvailabilityTextStyles(),
this.colors = const AvailabilityColors(), this.colors = const AvailabilityColors(),
this.confirmationDialogBuilder = DefaultConfirmationDialog.builder,
this.timePickerBuilder, this.timePickerBuilder,
this.loadingIndicatorBuilder = defaultLoader, this.loadingIndicatorBuilder = defaultLoader,
AvailabilityDataInterface? dataInterface, AvailabilityDataInterface? dataInterface,
@ -55,6 +57,11 @@ class AvailabilityOptions {
/// The colors used in the userstory /// The colors used in the userstory
final AvailabilityColors colors; final AvailabilityColors colors;
/// A way to provide your own confirmation dialog implementation
/// If not provided the [DefaultConfirmationDialog.builder] will be used
/// which shows a modal bottom sheet with a title and a description
final ConfirmationDialogBuilder confirmationDialogBuilder;
/// A way to provide your own time picker implementation or customize /// A way to provide your own time picker implementation or customize
/// the default time picker /// the default time picker
final TimePickerBuilder? timePickerBuilder; final TimePickerBuilder? timePickerBuilder;
@ -165,6 +172,16 @@ typedef TimePickerBuilder = Future<TimeOfDay?> Function(
TimeOfDay? initialTime, TimeOfDay? initialTime,
); );
/// Builder definition for providing a custom confirmation dialog
///
/// The function should return a [Future] that resolves to `true` if the user
/// confirms.
typedef ConfirmationDialogBuilder = Future<bool?> Function(
BuildContext context, {
required String title,
required String description,
});
/// Builder definition for providing a loading indicator implementation /// Builder definition for providing a loading indicator implementation
Widget defaultLoader( Widget defaultLoader(
BuildContext context, BuildContext context,

View file

@ -45,6 +45,8 @@ class AvailabilityTranslations {
required this.pauseDialogPeriodDescription, required this.pauseDialogPeriodDescription,
required this.saveButton, required this.saveButton,
required this.addButton, required this.addButton,
required this.confirmText,
required this.cancelText,
required this.timeFormatter, required this.timeFormatter,
required this.dayMonthFormatter, required this.dayMonthFormatter,
required this.periodFormatter, required this.periodFormatter,
@ -91,6 +93,8 @@ class AvailabilityTranslations {
"Select between which times you want to take a break", "Select between which times you want to take a break",
this.saveButton = "Save", this.saveButton = "Save",
this.addButton = "Add", this.addButton = "Add",
this.confirmText = "Yes",
this.cancelText = "No",
this.dayMonthFormatter = _defaultDayMonthFormatter, this.dayMonthFormatter = _defaultDayMonthFormatter,
this.periodFormatter = _defaultPeriodFormatter, this.periodFormatter = _defaultPeriodFormatter,
this.monthYearFormatter = _defaultMonthYearFormatter, this.monthYearFormatter = _defaultMonthYearFormatter,
@ -201,6 +205,12 @@ class AvailabilityTranslations {
/// The text on the add button /// The text on the add button
final String addButton; final String addButton;
/// The text on the confirm button in the confirmation dialog
final String confirmText;
/// The text on the cancel button in the confirmation dialog
final String cancelText;
/// Gets the day and month formatted as a string /// Gets the day and month formatted as a string
/// ///
/// The default implementation is `Dayname day monthname` in english /// The default implementation is `Dayname day monthname` in english

View file

@ -0,0 +1,93 @@
import "package:flutter/material.dart";
import "package:flutter_availability/src/util/scope.dart";
/// Default confirmation dialog that uses a modal bottom sheet, it has a title,
/// a description and it gets a secondary and primary button to confirm or
/// cancel the action
class DefaultConfirmationDialog extends StatelessWidget {
///
const DefaultConfirmationDialog({
required this.title,
required this.description,
super.key,
});
/// Shows a confirmation dialog with a title and a description
static Future<bool?> builder(
BuildContext context, {
required String title,
required String description,
}) =>
showModalBottomSheet(
context: context,
shape: const RoundedRectangleBorder(),
builder: (context) => DefaultConfirmationDialog(
title: title,
description: description,
),
);
/// The title shown in the dialog
final String title;
/// The description shown in the dialog
final String description;
@override
Widget build(BuildContext context) {
var theme = Theme.of(context);
var textTheme = theme.textTheme;
var availabilityScope = AvailabilityScope.of(context);
var options = availabilityScope.options;
var spacing = options.spacing;
var translations = options.translations;
void onCancel() => Navigator.of(context).pop(false);
void onConfirm() => Navigator.of(context).pop(true);
return Padding(
padding: EdgeInsets.only(
top: 40,
left: spacing.sidePadding,
right: spacing.sidePadding,
bottom: spacing.bottomButtonPadding,
),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
Text(
title,
style: textTheme.titleMedium,
),
const SizedBox(height: 16),
Text(
description,
style: textTheme.bodyLarge,
textAlign: TextAlign.center,
),
const SizedBox(height: 16),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: options.secondaryButtonBuilder(
context,
onCancel,
Text(translations.cancelText),
),
),
const SizedBox(width: 20),
Expanded(
child: options.primaryButtonBuilder(
context,
onConfirm,
Text(translations.confirmText),
),
),
],
),
],
),
);
}
}