mirror of
https://github.com/Iconica-Development/flutter_availability.git
synced 2025-05-19 13:13:44 +02:00
Compare commits
No commits in common. "master" and "1.0.0" have entirely different histories.
26 changed files with 312 additions and 811 deletions
2
.fvmrc
2
.fvmrc
|
@ -1,3 +1,3 @@
|
||||||
{
|
{
|
||||||
"flutter": "3.24.3"
|
"flutter": "3.22.2"
|
||||||
}
|
}
|
1
.github/workflows/melos-ci.yml
vendored
1
.github/workflows/melos-ci.yml
vendored
|
@ -12,4 +12,3 @@ jobs:
|
||||||
permissions: write-all
|
permissions: write-all
|
||||||
with:
|
with:
|
||||||
subfolder: '.' # add optional subfolder to run workflow in
|
subfolder: '.' # add optional subfolder to run workflow in
|
||||||
flutter_version: 3.24.3
|
|
||||||
|
|
14
.github/workflows/release.yml
vendored
14
.github/workflows/release.yml
vendored
|
@ -1,14 +0,0 @@
|
||||||
name: Iconica Standard Component Release Workflow
|
|
||||||
# Workflow Caller version: 1.0.0
|
|
||||||
|
|
||||||
on:
|
|
||||||
release:
|
|
||||||
types: [published]
|
|
||||||
|
|
||||||
workflow_dispatch:
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
call-global-iconica-workflow:
|
|
||||||
uses: Iconica-Development/.github/.github/workflows/component-release.yml@master
|
|
||||||
secrets: inherit
|
|
||||||
permissions: write-all
|
|
14
CHANGELOG.md
14
CHANGELOG.md
|
@ -1,15 +1,3 @@
|
||||||
## 1.2.0
|
|
||||||
|
|
||||||
* Improve the UI for smaller screens to prevent overflows
|
|
||||||
|
|
||||||
## 1.1.1
|
|
||||||
|
|
||||||
* Removed custom definition of CustomSemantics to use the one from flutter_accessibility instead
|
|
||||||
|
|
||||||
## 1.1.0
|
|
||||||
|
|
||||||
* Added CustomSemantics widget that is used to wrap all the buttons, textfields and dynamic texts to make the userstory accessible for e2e testing.
|
|
||||||
|
|
||||||
## 1.0.0
|
## 1.0.0
|
||||||
|
|
||||||
* First release of flutter_availability userstory
|
- T.B.D
|
|
@ -1,202 +0,0 @@
|
||||||
/// Accessibility identifiers for all widgets in the availability userstory that
|
|
||||||
/// need to be interacted with by e2e tests. This includes buttons, textfields,
|
|
||||||
/// and dynamic texts.
|
|
||||||
class AvailabilityAccessibilityIds {
|
|
||||||
/// default [AvailabilityAccessibilityIds] constructor where all the
|
|
||||||
/// identifiers are required. This is to ensure that apps automatically break
|
|
||||||
/// when new identifiers are added.
|
|
||||||
const AvailabilityAccessibilityIds({
|
|
||||||
required this.monthNameTextIdentifier,
|
|
||||||
required this.previousMonthButtonIdentifier,
|
|
||||||
required this.nextMonthButtonIdentifier,
|
|
||||||
required this.availabilityDateButtonIdentifier,
|
|
||||||
required this.createNewTemplateButtonIdentifier,
|
|
||||||
required this.viewAvailabilitiesButtonIdentifier,
|
|
||||||
required this.clearAvailabilitiesButtonIdentifier,
|
|
||||||
required this.toggleTemplateDrawerButtonIdentifier,
|
|
||||||
required this.availabilitiesPeriodTextIdentifier,
|
|
||||||
required this.selectUnavailableForPeriodButtonIdentifier,
|
|
||||||
required this.addTemplateToAvailabilitiesButtonIdentifier,
|
|
||||||
required this.removeTemplatesFromAvailabilitiesButtonIdentifier,
|
|
||||||
required this.createNewDayTemplateButtonIdentifier,
|
|
||||||
required this.createNewWeekTemplateButtonIdentifier,
|
|
||||||
required this.dayTemplateEditButtonIdentifier,
|
|
||||||
required this.weekTemplateEditButtonIdentifier,
|
|
||||||
required this.templateNameTextFieldIdentifier,
|
|
||||||
required this.startTimeTextFieldIdentifier,
|
|
||||||
required this.endTimeTextFieldIdentifier,
|
|
||||||
required this.durationTextFieldIdentifier,
|
|
||||||
required this.addBreaksButtonIdentifier,
|
|
||||||
required this.editBreakButtonIdentifier,
|
|
||||||
required this.deleteBreakButtonIdentifier,
|
|
||||||
required this.colorSelectionButtonIdentifier,
|
|
||||||
required this.colorSelectedButtonIdentifier,
|
|
||||||
required this.weekDayButtonIdentifier,
|
|
||||||
required this.weekDayTimeIdentifier,
|
|
||||||
required this.weekDayBreakIdentifier,
|
|
||||||
required this.templateNameIdentifier,
|
|
||||||
required this.deleteTemplateButtonIdentifier,
|
|
||||||
required this.saveButtonIdentifier,
|
|
||||||
required this.addButtonIdentifier,
|
|
||||||
required this.nextButtonIdentifier,
|
|
||||||
required this.closeButtonIdentifier,
|
|
||||||
});
|
|
||||||
|
|
||||||
/// Empty [AvailabilityAccessibilityIds] constructor where all the identifiers
|
|
||||||
/// are already set to their default values. You can override all or some of
|
|
||||||
/// the default values.
|
|
||||||
const AvailabilityAccessibilityIds.empty({
|
|
||||||
this.monthNameTextIdentifier = "text_month_name",
|
|
||||||
this.previousMonthButtonIdentifier = "button_previous_month",
|
|
||||||
this.nextMonthButtonIdentifier = "button_next_month",
|
|
||||||
this.availabilityDateButtonIdentifier = "button_availability_date",
|
|
||||||
this.createNewTemplateButtonIdentifier = "button_create_template",
|
|
||||||
this.viewAvailabilitiesButtonIdentifier = "button_view_availabilities",
|
|
||||||
this.clearAvailabilitiesButtonIdentifier = "button_clear_availabilities",
|
|
||||||
this.toggleTemplateDrawerButtonIdentifier = "button_toggle_template_drawer",
|
|
||||||
this.availabilitiesPeriodTextIdentifier = "text_availabilities_period",
|
|
||||||
this.selectUnavailableForPeriodButtonIdentifier =
|
|
||||||
"button_select_unavailable_for_period",
|
|
||||||
this.addTemplateToAvailabilitiesButtonIdentifier =
|
|
||||||
"button_add_template_to_availabilities",
|
|
||||||
this.removeTemplatesFromAvailabilitiesButtonIdentifier =
|
|
||||||
"button_remove_templates_from_availabilities",
|
|
||||||
this.createNewDayTemplateButtonIdentifier = "button_create_template_day",
|
|
||||||
this.createNewWeekTemplateButtonIdentifier = "button_create_template_week",
|
|
||||||
this.dayTemplateEditButtonIdentifier = "button_edit_template_day",
|
|
||||||
this.weekTemplateEditButtonIdentifier = "button_edit_template_week",
|
|
||||||
this.templateNameTextFieldIdentifier = "textfield_template_name",
|
|
||||||
this.startTimeTextFieldIdentifier = "textfield_start_time",
|
|
||||||
this.endTimeTextFieldIdentifier = "textfield_end_time",
|
|
||||||
this.durationTextFieldIdentifier = "textfield_duration",
|
|
||||||
this.addBreaksButtonIdentifier = "button_add_breaks",
|
|
||||||
this.editBreakButtonIdentifier = "button_edit_break",
|
|
||||||
this.deleteBreakButtonIdentifier = "button_delete_break",
|
|
||||||
this.colorSelectionButtonIdentifier = "button_select_color",
|
|
||||||
this.colorSelectedButtonIdentifier = "button_selected_color",
|
|
||||||
this.weekDayButtonIdentifier = "button_select_week_day",
|
|
||||||
this.weekDayTimeIdentifier = "text_week_day_time",
|
|
||||||
this.weekDayBreakIdentifier = "text_week_day_break",
|
|
||||||
this.templateNameIdentifier = "text_template_name",
|
|
||||||
this.deleteTemplateButtonIdentifier = "button_delete_template",
|
|
||||||
this.saveButtonIdentifier = "button_save",
|
|
||||||
this.addButtonIdentifier = "button_add",
|
|
||||||
this.nextButtonIdentifier = "button_next",
|
|
||||||
this.closeButtonIdentifier = "button_close",
|
|
||||||
});
|
|
||||||
|
|
||||||
/// The identifier for the text that displays the month that is being viewed
|
|
||||||
final String monthNameTextIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to navigate to the previous month
|
|
||||||
final String previousMonthButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to navigate to the next month
|
|
||||||
final String nextMonthButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to select a date in the availability view
|
|
||||||
/// The month and day are appended to this identifier
|
|
||||||
final String availabilityDateButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to go template overview screen
|
|
||||||
final String createNewTemplateButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to view availabilities
|
|
||||||
final String viewAvailabilitiesButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to clear availabilities;
|
|
||||||
final String clearAvailabilitiesButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to toggle the template drawer
|
|
||||||
final String toggleTemplateDrawerButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the text that displays the period of availabilities
|
|
||||||
/// that are being viewed
|
|
||||||
final String availabilitiesPeriodTextIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the checkbox to clear all availabilities for a period
|
|
||||||
final String selectUnavailableForPeriodButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to add a template to a selection of
|
|
||||||
/// availabilities
|
|
||||||
final String addTemplateToAvailabilitiesButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to remove all templates from a selection of
|
|
||||||
/// availabilities
|
|
||||||
final String removeTemplatesFromAvailabilitiesButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to create a new day template
|
|
||||||
final String createNewDayTemplateButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to create a new week template
|
|
||||||
final String createNewWeekTemplateButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to edit a specific day template, the index
|
|
||||||
/// of the item in the list is appended to this identifier
|
|
||||||
final String dayTemplateEditButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to edit a specific week template, the index
|
|
||||||
/// of the item in the list is appended to this identifier
|
|
||||||
final String weekTemplateEditButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the textfield to edit the name of a template
|
|
||||||
final String templateNameTextFieldIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the textfield to edit a start time
|
|
||||||
final String startTimeTextFieldIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the textfield to edit an end time
|
|
||||||
final String endTimeTextFieldIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the textfield to edit a duration
|
|
||||||
final String durationTextFieldIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to add new breaks
|
|
||||||
final String addBreaksButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the break edit button to edit a specific break, the
|
|
||||||
/// index of the item in the list is appended to this identifier
|
|
||||||
final String editBreakButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the break delete button to delete a specific break, the
|
|
||||||
/// index of the item in the list is appended to this identifier
|
|
||||||
final String deleteBreakButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to select a color from the list of colors,
|
|
||||||
/// the index of the item in the list is appended to this identifier
|
|
||||||
final String colorSelectionButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button for the currently selected color from the
|
|
||||||
/// list of colors. This overrides [colorSelectionButtonIdentifier]
|
|
||||||
final String colorSelectedButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to select a day of the week in the template
|
|
||||||
/// modification screen. The index of the day is appended to this identifier
|
|
||||||
final String weekDayButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the time of a day in the template view
|
|
||||||
/// The index of the day is appended to this identifier
|
|
||||||
final String weekDayTimeIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the time of a break in the template view
|
|
||||||
/// The index of the day and time is appended to this identifier
|
|
||||||
final String weekDayBreakIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the name of a template
|
|
||||||
final String templateNameIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to delete a template
|
|
||||||
final String deleteTemplateButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to save (templates or availabilities)
|
|
||||||
final String saveButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to save breaks
|
|
||||||
final String addButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to navigate to next step for week templates
|
|
||||||
final String nextButtonIdentifier;
|
|
||||||
|
|
||||||
/// The identifier for the button to close a dialog
|
|
||||||
final String closeButtonIdentifier;
|
|
||||||
}
|
|
|
@ -1,7 +1,6 @@
|
||||||
import "dart:async";
|
import "dart:async";
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_availability/src/config/availability_accessibility_ids.dart";
|
|
||||||
import "package:flutter_availability/src/config/availability_translations.dart";
|
import "package:flutter_availability/src/config/availability_translations.dart";
|
||||||
import "package:flutter_availability/src/service/errors.dart";
|
import "package:flutter_availability/src/service/errors.dart";
|
||||||
import "package:flutter_availability/src/ui/widgets/defaults/default_base_screen.dart";
|
import "package:flutter_availability/src/ui/widgets/defaults/default_base_screen.dart";
|
||||||
|
@ -16,7 +15,6 @@ class AvailabilityOptions {
|
||||||
/// AvailabilityOptions constructor where everything is optional.
|
/// AvailabilityOptions constructor where everything is optional.
|
||||||
AvailabilityOptions({
|
AvailabilityOptions({
|
||||||
this.translations = const AvailabilityTranslations.empty(),
|
this.translations = const AvailabilityTranslations.empty(),
|
||||||
this.accessibilityIds = const AvailabilityAccessibilityIds.empty(),
|
|
||||||
this.baseScreenBuilder = DefaultBaseScreen.builder,
|
this.baseScreenBuilder = DefaultBaseScreen.builder,
|
||||||
this.primaryButtonBuilder = DefaultPrimaryButton.builder,
|
this.primaryButtonBuilder = DefaultPrimaryButton.builder,
|
||||||
this.secondaryButtonBuilder = DefaultSecondaryButton.builder,
|
this.secondaryButtonBuilder = DefaultSecondaryButton.builder,
|
||||||
|
@ -41,10 +39,6 @@ class AvailabilityOptions {
|
||||||
/// The translations for the availability userstory
|
/// The translations for the availability userstory
|
||||||
final AvailabilityTranslations translations;
|
final AvailabilityTranslations translations;
|
||||||
|
|
||||||
/// All the accessibility ids for the availability userstory
|
|
||||||
/// These are used to add identifiers to the elements for testing
|
|
||||||
final AvailabilityAccessibilityIds accessibilityIds;
|
|
||||||
|
|
||||||
/// The implementation for communicating with the persistance layer
|
/// The implementation for communicating with the persistance layer
|
||||||
final AvailabilityDataInterface dataInterface;
|
final AvailabilityDataInterface dataInterface;
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/flutter_availability.dart";
|
import "package:flutter_availability/flutter_availability.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/availability_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/availability_view_model.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/break_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/break_view_model.dart";
|
||||||
|
@ -63,7 +62,6 @@ class _AvailabilitiesModificationScreenState
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var spacing = options.spacing;
|
var spacing = options.spacing;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
availabilityScope.popHandler.add(widget.onExit);
|
availabilityScope.popHandler.add(widget.onExit);
|
||||||
|
@ -128,13 +126,10 @@ class _AvailabilitiesModificationScreenState
|
||||||
}
|
}
|
||||||
|
|
||||||
var canSave = _availabilityViewModel.canSave;
|
var canSave = _availabilityViewModel.canSave;
|
||||||
var saveButton = CustomSemantics(
|
var saveButton = options.primaryButtonBuilder(
|
||||||
identifier: identifiers.saveButtonIdentifier,
|
context,
|
||||||
child: options.primaryButtonBuilder(
|
canSave ? onClickSave : null,
|
||||||
context,
|
Text(translations.saveButton),
|
||||||
canSave ? onClickSave : null,
|
|
||||||
Text(translations.saveButton),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// ignore: avoid_positional_boolean_parameters
|
// ignore: avoid_positional_boolean_parameters
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/ui/widgets/base_page.dart";
|
import "package:flutter_availability/src/ui/widgets/base_page.dart";
|
||||||
import "package:flutter_availability/src/ui/widgets/calendar.dart";
|
import "package:flutter_availability/src/ui/widgets/calendar.dart";
|
||||||
import "package:flutter_availability/src/ui/widgets/template_legend.dart";
|
import "package:flutter_availability/src/ui/widgets/template_legend.dart";
|
||||||
|
@ -44,7 +43,6 @@ class _AvailabilityOverviewState extends State<AvailabilityOverview> {
|
||||||
var service = availabilityScope.service;
|
var service = availabilityScope.service;
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var availabilityStream = useMemoized(
|
var availabilityStream = useMemoized(
|
||||||
() => service.getOverviewDataForMonth(_selectedDate),
|
() => service.getOverviewDataForMonth(_selectedDate),
|
||||||
|
@ -129,22 +127,16 @@ class _AvailabilityOverviewState extends State<AvailabilityOverview> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var clearSelectedButton = CustomSemantics(
|
var clearSelectedButton = options.bigTextButtonBuilder(
|
||||||
identifier: identifiers.clearAvailabilitiesButtonIdentifier,
|
context,
|
||||||
child: options.bigTextButtonBuilder(
|
onClearButtonClicked,
|
||||||
context,
|
Text(translations.clearAvailabilityButton),
|
||||||
onClearButtonClicked,
|
|
||||||
Text(translations.clearAvailabilityButton),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var startEditButton = CustomSemantics(
|
var startEditButton = options.primaryButtonBuilder(
|
||||||
identifier: identifiers.viewAvailabilitiesButtonIdentifier,
|
context,
|
||||||
child: options.primaryButtonBuilder(
|
onButtonPress,
|
||||||
context,
|
Text(translations.editAvailabilityButton),
|
||||||
onButtonPress,
|
|
||||||
Text(translations.editAvailabilityButton),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return options.baseScreenBuilder(
|
return options.baseScreenBuilder(
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/service/errors.dart";
|
import "package:flutter_availability/src/service/errors.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/day_template_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/day_template_view_model.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/template_daydata_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/template_daydata_view_model.dart";
|
||||||
|
@ -52,7 +51,6 @@ class _DayTemplateModificationScreenState
|
||||||
var service = availabilityScope.service;
|
var service = availabilityScope.service;
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
availabilityScope.popHandler.add(widget.onExit);
|
availabilityScope.popHandler.add(widget.onExit);
|
||||||
|
@ -103,13 +101,10 @@ class _DayTemplateModificationScreenState
|
||||||
|
|
||||||
var canSave = _viewModel.canSave;
|
var canSave = _viewModel.canSave;
|
||||||
|
|
||||||
var deleteButton = CustomSemantics(
|
var deleteButton = options.bigTextButtonBuilder(
|
||||||
identifier: identifiers.deleteTemplateButtonIdentifier,
|
context,
|
||||||
child: options.bigTextButtonBuilder(
|
onDeletePressed,
|
||||||
context,
|
Text(translations.deleteTemplateButton),
|
||||||
onDeletePressed,
|
|
||||||
Text(translations.deleteTemplateButton),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
void onNameChanged(String name) {
|
void onNameChanged(String name) {
|
||||||
|
@ -158,13 +153,10 @@ class _DayTemplateModificationScreenState
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
buttons: [
|
buttons: [
|
||||||
CustomSemantics(
|
options.primaryButtonBuilder(
|
||||||
identifier: identifiers.saveButtonIdentifier,
|
context,
|
||||||
child: options.primaryButtonBuilder(
|
canSave ? onSavePressed : null,
|
||||||
context,
|
Text(translations.saveButton),
|
||||||
canSave ? onSavePressed : null,
|
|
||||||
Text(translations.saveButton),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (widget.template != null) ...[
|
if (widget.template != null) ...[
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/ui/widgets/base_page.dart";
|
import "package:flutter_availability/src/ui/widgets/base_page.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||||
|
@ -35,7 +34,6 @@ class AvailabilityTemplateOverview extends HookWidget {
|
||||||
var service = availabilityScope.service;
|
var service = availabilityScope.service;
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var dayTemplateStream = useMemoized(() => service.getDayTemplates());
|
var dayTemplateStream = useMemoized(() => service.getDayTemplates());
|
||||||
var weekTemplateStream = useMemoized(() => service.getWeekTemplates());
|
var weekTemplateStream = useMemoized(() => service.getWeekTemplates());
|
||||||
|
@ -63,7 +61,6 @@ class AvailabilityTemplateOverview extends HookWidget {
|
||||||
var dayTemplateSection = _TemplateListSection(
|
var dayTemplateSection = _TemplateListSection(
|
||||||
sectionTitle: translations.dayTemplates,
|
sectionTitle: translations.dayTemplates,
|
||||||
createButtonText: translations.createDayTemplate,
|
createButtonText: translations.createDayTemplate,
|
||||||
createButtonIdentifier: identifiers.createNewDayTemplateButtonIdentifier,
|
|
||||||
onEditTemplate: onEditTemplate,
|
onEditTemplate: onEditTemplate,
|
||||||
onSelectTemplate: onSelectTemplate,
|
onSelectTemplate: onSelectTemplate,
|
||||||
onAddTemplate: () => onAddTemplate(AvailabilityTemplateType.day),
|
onAddTemplate: () => onAddTemplate(AvailabilityTemplateType.day),
|
||||||
|
@ -75,7 +72,6 @@ class AvailabilityTemplateOverview extends HookWidget {
|
||||||
var weekTemplateSection = _TemplateListSection(
|
var weekTemplateSection = _TemplateListSection(
|
||||||
sectionTitle: translations.weekTemplates,
|
sectionTitle: translations.weekTemplates,
|
||||||
createButtonText: translations.createWeekTemplate,
|
createButtonText: translations.createWeekTemplate,
|
||||||
createButtonIdentifier: identifiers.createNewWeekTemplateButtonIdentifier,
|
|
||||||
templates: weekTemplates,
|
templates: weekTemplates,
|
||||||
isLoading:
|
isLoading:
|
||||||
weekTemplatesSnapshot.connectionState == ConnectionState.waiting,
|
weekTemplatesSnapshot.connectionState == ConnectionState.waiting,
|
||||||
|
@ -103,7 +99,6 @@ class _TemplateListSection extends StatelessWidget {
|
||||||
const _TemplateListSection({
|
const _TemplateListSection({
|
||||||
required this.sectionTitle,
|
required this.sectionTitle,
|
||||||
required this.createButtonText,
|
required this.createButtonText,
|
||||||
required this.createButtonIdentifier,
|
|
||||||
required this.templates,
|
required this.templates,
|
||||||
required this.isLoading,
|
required this.isLoading,
|
||||||
required this.onEditTemplate,
|
required this.onEditTemplate,
|
||||||
|
@ -113,10 +108,6 @@ class _TemplateListSection extends StatelessWidget {
|
||||||
|
|
||||||
final String sectionTitle;
|
final String sectionTitle;
|
||||||
final String createButtonText;
|
final String createButtonText;
|
||||||
|
|
||||||
/// The accessibility identifier for the create button
|
|
||||||
final String createButtonIdentifier;
|
|
||||||
|
|
||||||
// transform the stream to a snapshot as low as possible to reduce rebuilds
|
// transform the stream to a snapshot as low as possible to reduce rebuilds
|
||||||
final List<AvailabilityTemplateModel> templates;
|
final List<AvailabilityTemplateModel> templates;
|
||||||
final bool isLoading;
|
final bool isLoading;
|
||||||
|
@ -149,14 +140,11 @@ class _TemplateListSection extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
const Icon(Icons.add),
|
const Icon(Icons.add),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
CustomSemantics(
|
options.smallTextButtonBuilder(
|
||||||
identifier: createButtonIdentifier,
|
context,
|
||||||
child: options.smallTextButtonBuilder(
|
onAddTemplate,
|
||||||
context,
|
Text(
|
||||||
onAddTemplate,
|
createButtonText,
|
||||||
Text(
|
|
||||||
createButtonText,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
@ -169,10 +157,9 @@ class _TemplateListSection extends StatelessWidget {
|
||||||
Text(sectionTitle, style: textTheme.titleMedium),
|
Text(sectionTitle, style: textTheme.titleMedium),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
for (var (index, template) in templates.indexed) ...[
|
for (var template in templates) ...[
|
||||||
_TemplateListSectionItem(
|
_TemplateListSectionItem(
|
||||||
template: template,
|
template: template,
|
||||||
index: index,
|
|
||||||
onTemplateClicked: onClickTemplate,
|
onTemplateClicked: onClickTemplate,
|
||||||
onEditTemplate: onEditTemplate,
|
onEditTemplate: onEditTemplate,
|
||||||
),
|
),
|
||||||
|
@ -190,16 +177,12 @@ class _TemplateListSection extends StatelessWidget {
|
||||||
class _TemplateListSectionItem extends StatelessWidget {
|
class _TemplateListSectionItem extends StatelessWidget {
|
||||||
const _TemplateListSectionItem({
|
const _TemplateListSectionItem({
|
||||||
required this.template,
|
required this.template,
|
||||||
required this.index,
|
|
||||||
required this.onTemplateClicked,
|
required this.onTemplateClicked,
|
||||||
required this.onEditTemplate,
|
required this.onEditTemplate,
|
||||||
});
|
});
|
||||||
|
|
||||||
final AvailabilityTemplateModel template;
|
final AvailabilityTemplateModel template;
|
||||||
|
|
||||||
/// The index of the template in the list
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
final void Function(AvailabilityTemplateModel template) onTemplateClicked;
|
final void Function(AvailabilityTemplateModel template) onTemplateClicked;
|
||||||
final void Function(AvailabilityTemplateModel template) onEditTemplate;
|
final void Function(AvailabilityTemplateModel template) onEditTemplate;
|
||||||
|
|
||||||
|
@ -208,52 +191,43 @@ class _TemplateListSectionItem extends StatelessWidget {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
var templateTypeIdentifer =
|
|
||||||
template.templateType == AvailabilityTemplateType.day
|
|
||||||
? identifiers.dayTemplateEditButtonIdentifier
|
|
||||||
: identifiers.weekTemplateEditButtonIdentifier;
|
|
||||||
var templateIdentifier = "${templateTypeIdentifer}_$index";
|
|
||||||
|
|
||||||
return CustomSemantics(
|
return InkWell(
|
||||||
identifier: templateIdentifier,
|
onTap: () => onTemplateClicked(template),
|
||||||
child: InkWell(
|
child: Container(
|
||||||
onTap: () => onTemplateClicked(template),
|
padding: const EdgeInsets.all(12),
|
||||||
child: Container(
|
margin: const EdgeInsets.only(top: 8),
|
||||||
padding: const EdgeInsets.all(12),
|
decoration: BoxDecoration(
|
||||||
margin: const EdgeInsets.only(top: 8),
|
border: Border.all(
|
||||||
decoration: BoxDecoration(
|
color: theme.dividerColor,
|
||||||
border: Border.all(
|
width: 1,
|
||||||
color: theme.dividerColor,
|
),
|
||||||
width: 1,
|
borderRadius: options.borderRadius,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Color(template.color),
|
||||||
|
borderRadius: options.borderRadius,
|
||||||
|
),
|
||||||
|
height: 20,
|
||||||
|
width: 20,
|
||||||
),
|
),
|
||||||
borderRadius: options.borderRadius,
|
const SizedBox(width: 8),
|
||||||
),
|
Expanded(
|
||||||
child: Row(
|
child: Text(
|
||||||
children: [
|
template.name,
|
||||||
Container(
|
style: theme.textTheme.bodyLarge,
|
||||||
decoration: BoxDecoration(
|
overflow: TextOverflow.ellipsis,
|
||||||
color: Color(template.color),
|
|
||||||
borderRadius: options.borderRadius,
|
|
||||||
),
|
|
||||||
height: 20,
|
|
||||||
width: 20,
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
),
|
||||||
Expanded(
|
const SizedBox(width: 4),
|
||||||
child: Text(
|
InkWell(
|
||||||
template.name,
|
onTap: () => onEditTemplate(template),
|
||||||
style: theme.textTheme.bodyLarge,
|
child: const Icon(Icons.edit),
|
||||||
overflow: TextOverflow.ellipsis,
|
),
|
||||||
),
|
],
|
||||||
),
|
|
||||||
const SizedBox(width: 4),
|
|
||||||
InkWell(
|
|
||||||
onTap: () => onEditTemplate(template),
|
|
||||||
child: const Icon(Icons.edit),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/service/errors.dart";
|
import "package:flutter_availability/src/service/errors.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/template_daydata_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/template_daydata_view_model.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/week_template_view_models.dart";
|
import "package:flutter_availability/src/ui/view_models/week_template_view_models.dart";
|
||||||
|
@ -54,7 +53,6 @@ class _WeekTemplateModificationScreenState
|
||||||
var service = availabilityScope.service;
|
var service = availabilityScope.service;
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
var spacing = options.spacing;
|
var spacing = options.spacing;
|
||||||
|
|
||||||
var weekTemplateDate = _viewModel.data;
|
var weekTemplateDate = _viewModel.data;
|
||||||
|
@ -136,31 +134,22 @@ class _WeekTemplateModificationScreenState
|
||||||
});
|
});
|
||||||
|
|
||||||
var canSave = _viewModel.canSave;
|
var canSave = _viewModel.canSave;
|
||||||
var nextButton = CustomSemantics(
|
var nextButton = options.primaryButtonBuilder(
|
||||||
identifier: identifiers.nextButtonIdentifier,
|
context,
|
||||||
child: options.primaryButtonBuilder(
|
canSave ? onNextPressed : null,
|
||||||
context,
|
Text(translations.nextButton),
|
||||||
canSave ? onNextPressed : null,
|
|
||||||
Text(translations.nextButton),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var saveButton = CustomSemantics(
|
var saveButton = options.primaryButtonBuilder(
|
||||||
identifier: identifiers.saveButtonIdentifier,
|
context,
|
||||||
child: options.primaryButtonBuilder(
|
canSave ? onSavePressed : null,
|
||||||
context,
|
Text(translations.saveButton),
|
||||||
canSave ? onSavePressed : null,
|
|
||||||
Text(translations.saveButton),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var deleteButton = CustomSemantics(
|
var deleteButton = options.bigTextButtonBuilder(
|
||||||
identifier: identifiers.deleteTemplateButtonIdentifier,
|
context,
|
||||||
child: options.bigTextButtonBuilder(
|
onDeletePressed,
|
||||||
context,
|
Text(translations.deleteTemplateButton),
|
||||||
onDeletePressed,
|
|
||||||
Text(translations.deleteTemplateButton),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var title = Center(
|
var title = Center(
|
||||||
|
@ -241,13 +230,10 @@ class _WeekTemplateModificationScreenState
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomSemantics(
|
child: Text(
|
||||||
identifier: identifiers.templateNameIdentifier,
|
_viewModel.name ?? "",
|
||||||
child: Text(
|
style: textTheme.bodyLarge,
|
||||||
_viewModel.name ?? "",
|
overflow: TextOverflow.ellipsis,
|
||||||
style: textTheme.bodyLarge,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
///
|
///
|
||||||
|
@ -31,7 +30,6 @@ class AvailabilityClearSection extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var isSingleDay = range.start.isAtSameMomentAs(range.end);
|
var isSingleDay = range.start.isAtSameMomentAs(range.end);
|
||||||
|
|
||||||
|
@ -45,36 +43,27 @@ class AvailabilityClearSection extends StatelessWidget {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
CustomSemantics(
|
Text(
|
||||||
identifier: identifiers.availabilitiesPeriodTextIdentifier,
|
titleText,
|
||||||
child: Text(
|
style: textTheme.titleMedium,
|
||||||
titleText,
|
|
||||||
style: textTheme.titleMedium,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
CustomSemantics(
|
Checkbox(
|
||||||
identifier:
|
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
||||||
identifiers.selectUnavailableForPeriodButtonIdentifier,
|
visualDensity: VisualDensity.compact,
|
||||||
child: Checkbox(
|
splashRadius: 0,
|
||||||
materialTapTargetSize: MaterialTapTargetSize.shrinkWrap,
|
value: clearAvailable,
|
||||||
visualDensity: VisualDensity.compact,
|
onChanged: (value) {
|
||||||
splashRadius: 0,
|
if (value == null) return;
|
||||||
value: clearAvailable,
|
onChanged(value);
|
||||||
onChanged: (value) {
|
},
|
||||||
if (value == null) return;
|
|
||||||
onChanged(value);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(
|
Text(
|
||||||
child: Text(
|
unavailableText,
|
||||||
unavailableText,
|
style: textTheme.bodyMedium,
|
||||||
style: textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||||
|
|
||||||
|
@ -35,7 +34,6 @@ class AvailabilityTemplateSelection extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var titleText = translations.availabilityAddTemplateTitle;
|
var titleText = translations.availabilityAddTemplateTitle;
|
||||||
if (selectedTemplates.isNotEmpty) {
|
if (selectedTemplates.isNotEmpty) {
|
||||||
|
@ -49,13 +47,10 @@ class AvailabilityTemplateSelection extends StatelessWidget {
|
||||||
var addButton = options.bigTextButtonWrapperBuilder(
|
var addButton = options.bigTextButtonWrapperBuilder(
|
||||||
context,
|
context,
|
||||||
onTemplateAdd,
|
onTemplateAdd,
|
||||||
CustomSemantics(
|
options.bigTextButtonBuilder(
|
||||||
identifier: identifiers.addTemplateToAvailabilitiesButtonIdentifier,
|
context,
|
||||||
child: options.bigTextButtonBuilder(
|
onTemplateAdd,
|
||||||
context,
|
Text(translations.addButton),
|
||||||
onTemplateAdd,
|
|
||||||
Text(translations.addButton),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -94,7 +89,6 @@ class _TemplateList extends StatelessWidget {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
padding: const EdgeInsets.all(12),
|
padding: const EdgeInsets.all(12),
|
||||||
|
@ -113,8 +107,8 @@ class _TemplateList extends StatelessWidget {
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
for (var (index, template) in selectedTemplates.indexed) ...[
|
for (var template in selectedTemplates) ...[
|
||||||
_TemplateListItem(template: template, index: index),
|
_TemplateListItem(template: template),
|
||||||
if (template != selectedTemplates.last) ...[
|
if (template != selectedTemplates.last) ...[
|
||||||
const SizedBox(height: 12),
|
const SizedBox(height: 12),
|
||||||
],
|
],
|
||||||
|
@ -123,13 +117,9 @@ class _TemplateList extends StatelessWidget {
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
CustomSemantics(
|
InkWell(
|
||||||
identifier:
|
onTap: onTemplatesRemoved,
|
||||||
identifiers.removeTemplatesFromAvailabilitiesButtonIdentifier,
|
child: const Icon(Icons.remove),
|
||||||
child: InkWell(
|
|
||||||
onTap: onTemplatesRemoved,
|
|
||||||
child: const Icon(Icons.remove),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -138,22 +128,15 @@ class _TemplateList extends StatelessWidget {
|
||||||
}
|
}
|
||||||
|
|
||||||
class _TemplateListItem extends StatelessWidget {
|
class _TemplateListItem extends StatelessWidget {
|
||||||
const _TemplateListItem({
|
const _TemplateListItem({required this.template});
|
||||||
required this.template,
|
|
||||||
required this.index,
|
|
||||||
});
|
|
||||||
|
|
||||||
final AvailabilityTemplateModel template;
|
final AvailabilityTemplateModel template;
|
||||||
|
|
||||||
/// The index of the template in the list of selected templates
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
|
@ -167,13 +150,10 @@ class _TemplateListItem extends StatelessWidget {
|
||||||
),
|
),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 12),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomSemantics(
|
child: Text(
|
||||||
identifier: "${identifiers.templateNameIdentifier}_$index",
|
template.name,
|
||||||
child: Text(
|
style: theme.textTheme.bodyLarge,
|
||||||
template.name,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: theme.textTheme.bodyLarge,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/flutter_availability.dart";
|
import "package:flutter_availability/flutter_availability.dart";
|
||||||
import "package:flutter_availability/src/ui/widgets/calendar_grid.dart";
|
import "package:flutter_availability/src/ui/widgets/calendar_grid.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
@ -66,59 +65,44 @@ class CalendarView extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var mappedCalendarDays = _mapAvailabilitiesToCalendarDays(availabilities);
|
var mappedCalendarDays = _mapAvailabilitiesToCalendarDays(availabilities);
|
||||||
var existsTemplateDeviations = mappedCalendarDays.any(
|
var existsTemplateDeviations = mappedCalendarDays.any(
|
||||||
(element) => element.templateDeviation,
|
(element) => element.templateDeviation,
|
||||||
);
|
);
|
||||||
|
|
||||||
var monthDateSelector = LayoutBuilder(
|
var monthDateSelector = Row(
|
||||||
builder: (context, constraints) {
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
var monthWidth =
|
children: [
|
||||||
_calculateTextWidthOfLongestMonth(context, translations);
|
IconButton(
|
||||||
var sideSpace =
|
padding: EdgeInsets.zero,
|
||||||
((constraints.maxWidth - monthWidth) / 2 - 44).clamp(0.0, 44.0);
|
icon: const Icon(Icons.chevron_left),
|
||||||
|
onPressed: () {
|
||||||
return Row(
|
onMonthChanged(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
DateTime(month.year, month.month - 1),
|
||||||
children: [
|
);
|
||||||
CustomSemantics(
|
},
|
||||||
identifier: identifiers.previousMonthButtonIdentifier,
|
),
|
||||||
child: IconButton(
|
const SizedBox(width: 44),
|
||||||
padding: EdgeInsets.zero,
|
SizedBox(
|
||||||
icon: const Icon(Icons.chevron_left),
|
width: _calculateTextWidthOfLongestMonth(context, translations),
|
||||||
onPressed: () {
|
child: Text(
|
||||||
onMonthChanged(DateTime(month.year, month.month - 1));
|
translations.monthYearFormatter(context, month),
|
||||||
},
|
style: textTheme.titleMedium,
|
||||||
),
|
textAlign: TextAlign.center,
|
||||||
),
|
),
|
||||||
SizedBox(width: sideSpace),
|
),
|
||||||
SizedBox(
|
const SizedBox(width: 44),
|
||||||
width: monthWidth,
|
IconButton(
|
||||||
child: CustomSemantics(
|
padding: EdgeInsets.zero,
|
||||||
identifier: identifiers.monthNameTextIdentifier,
|
icon: const Icon(Icons.chevron_right),
|
||||||
child: Text(
|
onPressed: () {
|
||||||
translations.monthYearFormatter(context, month),
|
onMonthChanged(
|
||||||
style: textTheme.titleMedium,
|
DateTime(month.year, month.month + 1),
|
||||||
textAlign: TextAlign.center,
|
);
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
SizedBox(width: sideSpace),
|
|
||||||
CustomSemantics(
|
|
||||||
identifier: identifiers.nextMonthButtonIdentifier,
|
|
||||||
child: IconButton(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
icon: const Icon(Icons.chevron_right),
|
|
||||||
onPressed: () {
|
|
||||||
onMonthChanged(DateTime(month.year, month.month + 1));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
|
|
||||||
var calendarGrid = CalendarGrid(
|
var calendarGrid = CalendarGrid(
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/flutter_availability.dart";
|
import "package:flutter_availability/flutter_availability.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
|
@ -120,7 +119,6 @@ class _CalendarDay extends StatelessWidget {
|
||||||
var colorScheme = theme.colorScheme;
|
var colorScheme = theme.colorScheme;
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
var colors = options.colors;
|
var colors = options.colors;
|
||||||
|
|
||||||
var dayColor = day.color ??
|
var dayColor = day.color ??
|
||||||
|
@ -136,10 +134,6 @@ class _CalendarDay extends StatelessWidget {
|
||||||
textStyle = textTheme.titleMedium?.copyWith(color: textColor);
|
textStyle = textTheme.titleMedium?.copyWith(color: textColor);
|
||||||
}
|
}
|
||||||
|
|
||||||
var dayIdentifier =
|
|
||||||
"${identifiers.availabilityDateButtonIdentifier}_${day.date.year}_"
|
|
||||||
"${day.date.month}_${day.date.day}";
|
|
||||||
|
|
||||||
var decoration = day.outsideMonth
|
var decoration = day.outsideMonth
|
||||||
? null
|
? null
|
||||||
: BoxDecoration(
|
: BoxDecoration(
|
||||||
|
@ -151,38 +145,32 @@ class _CalendarDay extends StatelessWidget {
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
return CustomSemantics(
|
return InkWell(
|
||||||
identifier: dayIdentifier,
|
onTap: () => onDayTap(day.date),
|
||||||
child: InkWell(
|
child: DecoratedBox(
|
||||||
onTap: () => onDayTap(day.date),
|
decoration: BoxDecoration(
|
||||||
child: DecoratedBox(
|
borderRadius: options.borderRadius,
|
||||||
decoration: BoxDecoration(
|
border: Border.all(
|
||||||
borderRadius: options.borderRadius,
|
color: day.isSelected ? theme.dividerColor : Colors.transparent,
|
||||||
border: Border.all(
|
width: 1.5,
|
||||||
color: day.isSelected ? theme.dividerColor : Colors.transparent,
|
|
||||||
width: 1.5,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
child: Stack(
|
),
|
||||||
children: [
|
child: Stack(
|
||||||
Center(
|
children: [
|
||||||
child: Container(
|
Center(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 2),
|
child: Container(
|
||||||
decoration: decoration,
|
padding: const EdgeInsets.symmetric(horizontal: 4),
|
||||||
child: Text(
|
decoration: decoration,
|
||||||
day.date.day.toString(),
|
child: Text(day.date.day.toString(), style: textStyle),
|
||||||
style: textStyle,
|
),
|
||||||
),
|
),
|
||||||
),
|
if (day.templateDeviation) ...[
|
||||||
|
Positioned(
|
||||||
|
right: 4,
|
||||||
|
child: Text("*", style: textStyle),
|
||||||
),
|
),
|
||||||
if (day.templateDeviation) ...[
|
|
||||||
Positioned(
|
|
||||||
right: 4,
|
|
||||||
child: Text("*", style: textStyle),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import "dart:math";
|
import "dart:math";
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
/// Widget for selecting a color for a template
|
/// Widget for selecting a color for a template
|
||||||
|
@ -41,10 +40,9 @@ class TemplateColorSelection extends StatelessWidget {
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
children: [
|
children: [
|
||||||
for (var (index, color) in colors.templateColors.indexed) ...[
|
for (var color in colors.templateColors) ...[
|
||||||
_TemplateColorItem(
|
_TemplateColorItem(
|
||||||
color: color,
|
color: color,
|
||||||
index: index,
|
|
||||||
selectedColor: selectedColor,
|
selectedColor: selectedColor,
|
||||||
onColorSelected: onColorSelected,
|
onColorSelected: onColorSelected,
|
||||||
),
|
),
|
||||||
|
@ -59,7 +57,6 @@ class TemplateColorSelection extends StatelessWidget {
|
||||||
class _TemplateColorItem extends StatelessWidget {
|
class _TemplateColorItem extends StatelessWidget {
|
||||||
const _TemplateColorItem({
|
const _TemplateColorItem({
|
||||||
required this.color,
|
required this.color,
|
||||||
required this.index,
|
|
||||||
required this.selectedColor,
|
required this.selectedColor,
|
||||||
required this.onColorSelected,
|
required this.onColorSelected,
|
||||||
});
|
});
|
||||||
|
@ -69,20 +66,14 @@ class _TemplateColorItem extends StatelessWidget {
|
||||||
|
|
||||||
final Color color;
|
final Color color;
|
||||||
|
|
||||||
/// The index of the color in the list of colors
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
final int? selectedColor;
|
final int? selectedColor;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
var colors = options.colors;
|
var colors = options.colors;
|
||||||
|
|
||||||
var isSelected = selectedColor == color.value;
|
|
||||||
|
|
||||||
/// If the color is selected, deselect it, otherwise select it
|
/// If the color is selected, deselect it, otherwise select it
|
||||||
void onColorClick(Color color) => onColorSelected(
|
void onColorClick(Color color) => onColorSelected(
|
||||||
color.value == selectedColor ? null : color.value,
|
color.value == selectedColor ? null : color.value,
|
||||||
|
@ -92,25 +83,20 @@ class _TemplateColorItem extends StatelessWidget {
|
||||||
? colors.templateColorLightCheckmarkColor
|
? colors.templateColorLightCheckmarkColor
|
||||||
: colors.templateColorDarkCheckmarkColor;
|
: colors.templateColorDarkCheckmarkColor;
|
||||||
|
|
||||||
var icon = isSelected ? Icon(Icons.check, color: checkMarkColor) : null;
|
var icon = selectedColor == color.value
|
||||||
|
? Icon(Icons.check, color: checkMarkColor)
|
||||||
|
: null;
|
||||||
|
|
||||||
var colorIdentifier = isSelected
|
return GestureDetector(
|
||||||
? identifiers.colorSelectedButtonIdentifier
|
onTap: () => onColorClick(color),
|
||||||
: "${identifiers.colorSelectionButtonIdentifier}_$index";
|
child: Container(
|
||||||
|
width: 40,
|
||||||
return CustomSemantics(
|
height: 40,
|
||||||
identifier: colorIdentifier,
|
decoration: BoxDecoration(
|
||||||
child: GestureDetector(
|
color: color,
|
||||||
onTap: () => onColorClick(color),
|
borderRadius: options.borderRadius,
|
||||||
child: Container(
|
|
||||||
width: 40,
|
|
||||||
height: 40,
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: color,
|
|
||||||
borderRadius: options.borderRadius,
|
|
||||||
),
|
|
||||||
child: icon,
|
|
||||||
),
|
),
|
||||||
|
child: icon,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,7 +44,6 @@ class TimeSelection extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: crossAxisAlignment,
|
crossAxisAlignment: crossAxisAlignment,
|
||||||
|
@ -64,7 +63,6 @@ class TimeSelection extends StatelessWidget {
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: TimeInputField(
|
child: TimeInputField(
|
||||||
identifier: identifiers.startTimeTextFieldIdentifier,
|
|
||||||
initialValue: startTime,
|
initialValue: startTime,
|
||||||
onTimeChanged: onStartChanged,
|
onTimeChanged: onStartChanged,
|
||||||
),
|
),
|
||||||
|
@ -80,7 +78,6 @@ class TimeSelection extends StatelessWidget {
|
||||||
Expanded(
|
Expanded(
|
||||||
flex: 2,
|
flex: 2,
|
||||||
child: TimeInputField(
|
child: TimeInputField(
|
||||||
identifier: identifiers.endTimeTextFieldIdentifier,
|
|
||||||
initialValue: endTime,
|
initialValue: endTime,
|
||||||
onTimeChanged: onEndChanged,
|
onTimeChanged: onEndChanged,
|
||||||
),
|
),
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter/services.dart";
|
import "package:flutter/services.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
/// An input field for time selection
|
/// An input field for time selection
|
||||||
|
@ -9,16 +8,12 @@ class TimeInputField extends StatelessWidget {
|
||||||
const TimeInputField({
|
const TimeInputField({
|
||||||
required this.initialValue,
|
required this.initialValue,
|
||||||
required this.onTimeChanged,
|
required this.onTimeChanged,
|
||||||
required this.identifier,
|
|
||||||
super.key,
|
super.key,
|
||||||
});
|
});
|
||||||
|
|
||||||
///
|
///
|
||||||
final TimeOfDay? initialValue;
|
final TimeOfDay? initialValue;
|
||||||
|
|
||||||
/// The accessibility identifier for this input field
|
|
||||||
final String identifier;
|
|
||||||
|
|
||||||
///
|
///
|
||||||
final void Function(TimeOfDay) onTimeChanged;
|
final void Function(TimeOfDay) onTimeChanged;
|
||||||
|
|
||||||
|
@ -42,25 +37,21 @@ class TimeInputField extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return CustomSemantics(
|
return TextFormField(
|
||||||
identifier: identifier,
|
decoration: InputDecoration(
|
||||||
isTextField: true,
|
suffixIcon: const Icon(Icons.access_time),
|
||||||
child: TextFormField(
|
hintText: translations.time,
|
||||||
decoration: InputDecoration(
|
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
suffixIcon: const Icon(Icons.access_time),
|
border: OutlineInputBorder(
|
||||||
hintText: translations.time,
|
borderRadius: BorderRadius.circular(10),
|
||||||
hintStyle: theme.inputDecorationTheme.hintStyle,
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
initialValue: initialValue != null
|
|
||||||
? translations.timeFormatter(context, initialValue!)
|
|
||||||
: null,
|
|
||||||
readOnly: true,
|
|
||||||
style: options.textStyles.inputFieldTextStyle,
|
|
||||||
onTap: onFieldtap,
|
|
||||||
),
|
),
|
||||||
|
initialValue: initialValue != null
|
||||||
|
? translations.timeFormatter(context, initialValue!)
|
||||||
|
: null,
|
||||||
|
readOnly: true,
|
||||||
|
style: options.textStyles.inputFieldTextStyle,
|
||||||
|
onTap: onFieldtap,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -131,7 +122,6 @@ class _DurationInputFieldState extends State<DurationInputField> {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
return Focus(
|
return Focus(
|
||||||
onFocusChange: (hasFocus) {
|
onFocusChange: (hasFocus) {
|
||||||
|
@ -141,26 +131,22 @@ class _DurationInputFieldState extends State<DurationInputField> {
|
||||||
_removeOverlay();
|
_removeOverlay();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: CustomSemantics(
|
child: TextFormField(
|
||||||
identifier: identifiers.durationTextFieldIdentifier,
|
decoration: InputDecoration(
|
||||||
isTextField: true,
|
labelText: translations.time,
|
||||||
child: TextFormField(
|
labelStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
decoration: InputDecoration(
|
border: OutlineInputBorder(
|
||||||
labelText: translations.time,
|
borderRadius: BorderRadius.circular(10),
|
||||||
labelStyle: theme.inputDecorationTheme.hintStyle,
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
suffixIcon: const Icon(Icons.access_time),
|
|
||||||
),
|
),
|
||||||
initialValue: widget.initialValue?.inMinutes.toString(),
|
suffixIcon: const Icon(Icons.access_time),
|
||||||
keyboardType: TextInputType.number,
|
|
||||||
style: options.textStyles.inputFieldTextStyle,
|
|
||||||
onChanged: _onFieldChanged,
|
|
||||||
inputFormatters: [
|
|
||||||
FilteringTextInputFormatter.digitsOnly,
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
|
initialValue: widget.initialValue?.inMinutes.toString(),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
style: options.textStyles.inputFieldTextStyle,
|
||||||
|
onChanged: _onFieldChanged,
|
||||||
|
inputFormatters: [
|
||||||
|
FilteringTextInputFormatter.digitsOnly,
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/flutter_availability.dart";
|
import "package:flutter_availability/flutter_availability.dart";
|
||||||
import "package:flutter_availability/src/service/pop_handler.dart";
|
import "package:flutter_availability/src/service/pop_handler.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/break_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/break_view_model.dart";
|
||||||
|
@ -33,7 +32,6 @@ class PauseSelection extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
var popHandler = availabilityScope.popHandler;
|
var popHandler = availabilityScope.popHandler;
|
||||||
|
|
||||||
Future<BreakViewModel?> openBreakDialog(
|
Future<BreakViewModel?> openBreakDialog(
|
||||||
|
@ -75,16 +73,13 @@ class PauseSelection extends StatelessWidget {
|
||||||
|
|
||||||
var sortedBreaks = breaks.toList()..sort((a, b) => a.compareTo(b));
|
var sortedBreaks = breaks.toList()..sort((a, b) => a.compareTo(b));
|
||||||
|
|
||||||
var addButton = CustomSemantics(
|
var addButton = options.bigTextButtonWrapperBuilder(
|
||||||
identifier: identifiers.addBreaksButtonIdentifier,
|
context,
|
||||||
child: options.bigTextButtonWrapperBuilder(
|
onClickAddBreak,
|
||||||
|
options.bigTextButtonBuilder(
|
||||||
context,
|
context,
|
||||||
onClickAddBreak,
|
onClickAddBreak,
|
||||||
options.bigTextButtonBuilder(
|
Text(translations.addButton),
|
||||||
context,
|
|
||||||
onClickAddBreak,
|
|
||||||
Text(translations.addButton),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -104,11 +99,10 @@ class PauseSelection extends StatelessWidget {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
for (var (index, breakModel) in sortedBreaks.indexed) ...[
|
for (var breakModel in sortedBreaks) ...[
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
BreakDisplay(
|
BreakDisplay(
|
||||||
breakModel: breakModel,
|
breakModel: breakModel,
|
||||||
index: index,
|
|
||||||
onRemove: () => onDeleteBreak(breakModel),
|
onRemove: () => onDeleteBreak(breakModel),
|
||||||
onClick: () async => onEditBreak(breakModel),
|
onClick: () async => onEditBreak(breakModel),
|
||||||
),
|
),
|
||||||
|
@ -125,7 +119,6 @@ class BreakDisplay extends StatelessWidget {
|
||||||
/// Creates a new break display
|
/// Creates a new break display
|
||||||
const BreakDisplay({
|
const BreakDisplay({
|
||||||
required this.breakModel,
|
required this.breakModel,
|
||||||
required this.index,
|
|
||||||
required this.onRemove,
|
required this.onRemove,
|
||||||
required this.onClick,
|
required this.onClick,
|
||||||
super.key,
|
super.key,
|
||||||
|
@ -134,9 +127,6 @@ class BreakDisplay extends StatelessWidget {
|
||||||
/// The break to display
|
/// The break to display
|
||||||
final BreakViewModel breakModel;
|
final BreakViewModel breakModel;
|
||||||
|
|
||||||
/// The index of the break in the list
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
/// Callback for when the minus button is clicked
|
/// Callback for when the minus button is clicked
|
||||||
final VoidCallback onRemove;
|
final VoidCallback onRemove;
|
||||||
|
|
||||||
|
@ -150,7 +140,6 @@ class BreakDisplay extends StatelessWidget {
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var colors = options.colors;
|
var colors = options.colors;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var starTime = translations.timeFormatter(
|
var starTime = translations.timeFormatter(
|
||||||
context,
|
context,
|
||||||
|
@ -162,9 +151,6 @@ class BreakDisplay extends StatelessWidget {
|
||||||
);
|
);
|
||||||
|
|
||||||
var breakDuration = breakModel.duration.inMinutes;
|
var breakDuration = breakModel.duration.inMinutes;
|
||||||
var editBreakIdentifier = "${identifiers.editBreakButtonIdentifier}_$index";
|
|
||||||
var deleteBreakIdentifier =
|
|
||||||
"${identifiers.deleteBreakButtonIdentifier}_$index";
|
|
||||||
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
onTap: onClick,
|
onTap: onClick,
|
||||||
|
@ -177,22 +163,16 @@ class BreakDisplay extends StatelessWidget {
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12),
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
CustomSemantics(
|
Text(
|
||||||
identifier: editBreakIdentifier,
|
"$breakDuration "
|
||||||
child: Text(
|
"${translations.timeMinutes} | "
|
||||||
"$breakDuration "
|
"$starTime - "
|
||||||
"${translations.timeMinutes} | "
|
"$endTime",
|
||||||
"$starTime - "
|
|
||||||
"$endTime",
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
CustomSemantics(
|
InkWell(
|
||||||
identifier: deleteBreakIdentifier,
|
onTap: onRemove,
|
||||||
child: InkWell(
|
child: const Icon(Icons.remove),
|
||||||
onTap: onRemove,
|
|
||||||
child: const Icon(Icons.remove),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -271,7 +251,6 @@ class _AvailabilityBreakSelectionDialogState
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
var spacing = options.spacing;
|
var spacing = options.spacing;
|
||||||
|
|
||||||
void onUpdateDuration(Duration? duration) {
|
void onUpdateDuration(Duration? duration) {
|
||||||
|
@ -320,16 +299,13 @@ class _AvailabilityBreakSelectionDialogState
|
||||||
|
|
||||||
var onSaveButtonPress = canSave ? onSave : null;
|
var onSaveButtonPress = canSave ? onSave : null;
|
||||||
|
|
||||||
var saveButton = CustomSemantics(
|
var saveButton = options.primaryButtonBuilder(
|
||||||
identifier: identifiers.addButtonIdentifier,
|
context,
|
||||||
child: options.primaryButtonBuilder(
|
onSaveButtonPress,
|
||||||
context,
|
Text(
|
||||||
onSaveButtonPress,
|
widget.initialBreak == null
|
||||||
Text(
|
? translations.addButton
|
||||||
widget.initialBreak == null
|
: translations.saveButton,
|
||||||
? translations.addButton
|
|
||||||
: translations.saveButton,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -405,13 +381,10 @@ class _AvailabilityBreakSelectionDialogState
|
||||||
Positioned(
|
Positioned(
|
||||||
right: 0,
|
right: 0,
|
||||||
top: 0,
|
top: 0,
|
||||||
child: CustomSemantics(
|
child: IconButton(
|
||||||
identifier: identifiers.closeButtonIdentifier,
|
padding: const EdgeInsets.all(16),
|
||||||
child: IconButton(
|
icon: const Icon(Icons.close),
|
||||||
padding: const EdgeInsets.all(16),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
icon: const Icon(Icons.close),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/config/availability_options.dart";
|
import "package:flutter_availability/src/config/availability_options.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
import "package:flutter_availability_data_interface/flutter_availability_data_interface.dart";
|
||||||
|
@ -37,7 +36,6 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var colors = options.colors;
|
var colors = options.colors;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
var featureSet = options.featureSet;
|
var featureSet = options.featureSet;
|
||||||
|
|
||||||
var templatesLoading =
|
var templatesLoading =
|
||||||
|
@ -65,25 +63,20 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
var createNewTemplateButton = CustomSemantics(
|
var createNewTemplateButton = GestureDetector(
|
||||||
identifier: identifiers.createNewTemplateButtonIdentifier,
|
onTap: () => widget.onViewTemplates(),
|
||||||
child: GestureDetector(
|
child: ColoredBox(
|
||||||
onTap: () => widget.onViewTemplates(),
|
color: Colors.transparent,
|
||||||
child: ColoredBox(
|
child: Row(
|
||||||
color: Colors.transparent,
|
children: [
|
||||||
child: Row(
|
const SizedBox(width: 12),
|
||||||
children: [
|
const Icon(Icons.add, size: 20),
|
||||||
const SizedBox(width: 12),
|
const SizedBox(width: 6),
|
||||||
const Icon(Icons.add, size: 20),
|
Text(
|
||||||
const SizedBox(width: 6),
|
translations.createTemplateButton,
|
||||||
Expanded(
|
style: textTheme.bodyLarge,
|
||||||
child: Text(
|
),
|
||||||
translations.createTemplateButton,
|
],
|
||||||
style: textTheme.bodyLarge,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -111,7 +104,6 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
left: 12,
|
left: 12,
|
||||||
),
|
),
|
||||||
child: _TemplateLegendItem(
|
child: _TemplateLegendItem(
|
||||||
index: 0,
|
|
||||||
name: translations.templateSelectionLabel,
|
name: translations.templateSelectionLabel,
|
||||||
backgroundColor: Colors.white,
|
backgroundColor: Colors.white,
|
||||||
borderColor: colorScheme.primary,
|
borderColor: colorScheme.primary,
|
||||||
|
@ -124,7 +116,6 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
left: 12,
|
left: 12,
|
||||||
),
|
),
|
||||||
child: _TemplateLegendItem(
|
child: _TemplateLegendItem(
|
||||||
index: 1,
|
|
||||||
name: translations.availabilityWithoutTemplateLabel,
|
name: translations.availabilityWithoutTemplateLabel,
|
||||||
backgroundColor: colors.customAvailabilityColor ??
|
backgroundColor: colors.customAvailabilityColor ??
|
||||||
colorScheme.secondary,
|
colorScheme.secondary,
|
||||||
|
@ -132,14 +123,13 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
if (featureSet.require(AvailabilityFeature.templates)) ...[
|
if (featureSet.require(AvailabilityFeature.templates)) ...[
|
||||||
for (var (index, template) in templates.indexed) ...[
|
for (var template in templates) ...[
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.only(
|
padding: const EdgeInsets.only(
|
||||||
top: 10,
|
top: 10,
|
||||||
left: 12,
|
left: 12,
|
||||||
),
|
),
|
||||||
child: _TemplateLegendItem(
|
child: _TemplateLegendItem(
|
||||||
index: index + 2,
|
|
||||||
name: template.name,
|
name: template.name,
|
||||||
backgroundColor: Color(template.color),
|
backgroundColor: Color(template.color),
|
||||||
),
|
),
|
||||||
|
@ -159,30 +149,27 @@ class _TemplateLegendState extends State<TemplateLegend> {
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
children: [
|
||||||
// a button to open/close a drawer with all the templates
|
// a button to open/close a drawer with all the templates
|
||||||
CustomSemantics(
|
GestureDetector(
|
||||||
identifier: identifiers.toggleTemplateDrawerButtonIdentifier,
|
onTap: onDrawerHeaderClick,
|
||||||
child: GestureDetector(
|
child: ColoredBox(
|
||||||
onTap: onDrawerHeaderClick,
|
color: Colors.transparent,
|
||||||
child: ColoredBox(
|
child: Row(
|
||||||
color: Colors.transparent,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
child: Row(
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
children: [
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
Text(
|
||||||
children: [
|
translations.templateLegendTitle,
|
||||||
Text(
|
style: textTheme.titleMedium,
|
||||||
translations.templateLegendTitle,
|
),
|
||||||
style: textTheme.titleMedium,
|
if (templatesAvailable ||
|
||||||
|
(_templateDrawerOpen && templatesLoading)) ...[
|
||||||
|
Icon(
|
||||||
|
_templateDrawerOpen
|
||||||
|
? Icons.arrow_drop_up
|
||||||
|
: Icons.arrow_drop_down,
|
||||||
),
|
),
|
||||||
if (templatesAvailable ||
|
|
||||||
(_templateDrawerOpen && templatesLoading)) ...[
|
|
||||||
Icon(
|
|
||||||
_templateDrawerOpen
|
|
||||||
? Icons.arrow_drop_up
|
|
||||||
: Icons.arrow_drop_down,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
],
|
],
|
||||||
),
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -221,17 +208,11 @@ class _TemplateLegendItem extends StatelessWidget {
|
||||||
const _TemplateLegendItem({
|
const _TemplateLegendItem({
|
||||||
required this.name,
|
required this.name,
|
||||||
required this.backgroundColor,
|
required this.backgroundColor,
|
||||||
required this.index,
|
|
||||||
this.borderColor,
|
this.borderColor,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String name;
|
final String name;
|
||||||
|
|
||||||
/// The index of the color in the list of colors (index 0 is the selected
|
|
||||||
/// color template, index 1 is the color for availabilities without a
|
|
||||||
/// template)
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
final Color backgroundColor;
|
final Color backgroundColor;
|
||||||
|
|
||||||
final Color? borderColor;
|
final Color? borderColor;
|
||||||
|
@ -241,9 +222,6 @@ class _TemplateLegendItem extends StatelessWidget {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var templateIdentifier = "${identifiers.templateNameIdentifier}_$index";
|
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
|
@ -260,13 +238,10 @@ class _TemplateLegendItem extends StatelessWidget {
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8),
|
const SizedBox(width: 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: CustomSemantics(
|
child: Text(
|
||||||
identifier: templateIdentifier,
|
name,
|
||||||
child: Text(
|
style: theme.textTheme.bodyLarge,
|
||||||
name,
|
overflow: TextOverflow.ellipsis,
|
||||||
style: theme.textTheme.bodyLarge,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
/// Input section for the template name
|
/// Input section for the template name
|
||||||
|
@ -24,7 +23,6 @@ class TemplateNameInput extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -34,23 +32,19 @@ class TemplateNameInput extends StatelessWidget {
|
||||||
style: textTheme.titleMedium,
|
style: textTheme.titleMedium,
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
CustomSemantics(
|
TextFormField(
|
||||||
identifier: identifiers.templateNameTextFieldIdentifier,
|
decoration: InputDecoration(
|
||||||
isTextField: true,
|
hintText: translations.templateTitleHintText,
|
||||||
child: TextFormField(
|
hintStyle: theme.inputDecorationTheme.hintStyle,
|
||||||
decoration: InputDecoration(
|
counterText: "",
|
||||||
hintText: translations.templateTitleHintText,
|
border: OutlineInputBorder(
|
||||||
hintStyle: theme.inputDecorationTheme.hintStyle,
|
borderRadius: BorderRadius.circular(10),
|
||||||
counterText: "",
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.circular(10),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
maxLength: 100,
|
|
||||||
initialValue: initialValue,
|
|
||||||
style: options.textStyles.inputFieldTextStyle,
|
|
||||||
onChanged: onNameChanged,
|
|
||||||
),
|
),
|
||||||
|
maxLength: 100,
|
||||||
|
initialValue: initialValue,
|
||||||
|
style: options.textStyles.inputFieldTextStyle,
|
||||||
|
onChanged: onNameChanged,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
// ignore_for_file: avoid_positional_boolean_parameters
|
// ignore_for_file: avoid_positional_boolean_parameters
|
||||||
|
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/ui/widgets/calendar_grid.dart";
|
import "package:flutter_availability/src/ui/widgets/calendar_grid.dart";
|
||||||
import "package:flutter_availability/src/util/scope.dart";
|
import "package:flutter_availability/src/util/scope.dart";
|
||||||
|
|
||||||
|
@ -59,10 +58,10 @@ class _TemplateWeekDaySelectionState extends State<TemplateWeekDaySelection> {
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
children: [
|
children: [
|
||||||
for (var (index, day) in days.indexed) ...[
|
for (var day in days) ...[
|
||||||
_DaySelectionCard(
|
_DaySelectionCard(
|
||||||
day: day,
|
day: day,
|
||||||
index: index,
|
days: days,
|
||||||
selectedDayIndex: _selectedDayIndex,
|
selectedDayIndex: _selectedDayIndex,
|
||||||
onDaySelected: (selected) =>
|
onDaySelected: (selected) =>
|
||||||
onDaySelected(selected, days.indexOf(day)),
|
onDaySelected(selected, days.indexOf(day)),
|
||||||
|
@ -82,12 +81,12 @@ class _DaySelectionCard extends StatelessWidget {
|
||||||
const _DaySelectionCard({
|
const _DaySelectionCard({
|
||||||
required this.selectedDayIndex,
|
required this.selectedDayIndex,
|
||||||
required this.day,
|
required this.day,
|
||||||
required this.index,
|
required this.days,
|
||||||
required this.onDaySelected,
|
required this.onDaySelected,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String day;
|
final String day;
|
||||||
final int index;
|
final List<String> days;
|
||||||
|
|
||||||
final int selectedDayIndex;
|
final int selectedDayIndex;
|
||||||
|
|
||||||
|
@ -95,11 +94,11 @@ class _DaySelectionCard extends StatelessWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
var index = days.indexOf(day);
|
||||||
var isSelected = index == selectedDayIndex;
|
var isSelected = index == selectedDayIndex;
|
||||||
|
|
||||||
return _DaySelectionCardLayout(
|
return _DaySelectionCardLayout(
|
||||||
day: day,
|
day: day,
|
||||||
index: index,
|
|
||||||
isSelected: isSelected,
|
isSelected: isSelected,
|
||||||
onDaySelected: onDaySelected,
|
onDaySelected: onDaySelected,
|
||||||
);
|
);
|
||||||
|
@ -109,7 +108,6 @@ class _DaySelectionCard extends StatelessWidget {
|
||||||
class _DaySelectionCardLayout extends StatelessWidget {
|
class _DaySelectionCardLayout extends StatelessWidget {
|
||||||
const _DaySelectionCardLayout({
|
const _DaySelectionCardLayout({
|
||||||
required this.day,
|
required this.day,
|
||||||
required this.index,
|
|
||||||
required this.isSelected,
|
required this.isSelected,
|
||||||
required this.onDaySelected,
|
required this.onDaySelected,
|
||||||
});
|
});
|
||||||
|
@ -117,9 +115,6 @@ class _DaySelectionCardLayout extends StatelessWidget {
|
||||||
final String day;
|
final String day;
|
||||||
final bool isSelected;
|
final bool isSelected;
|
||||||
|
|
||||||
/// The index of the day in the list of days
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
final void Function(bool) onDaySelected;
|
final void Function(bool) onDaySelected;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -129,7 +124,6 @@ class _DaySelectionCardLayout extends StatelessWidget {
|
||||||
var abbreviationTextStyle = textTheme.headlineMedium;
|
var abbreviationTextStyle = textTheme.headlineMedium;
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
abbreviationTextStyle = isSelected
|
abbreviationTextStyle = isSelected
|
||||||
? abbreviationTextStyle?.copyWith(
|
? abbreviationTextStyle?.copyWith(
|
||||||
|
@ -137,27 +131,22 @@ class _DaySelectionCardLayout extends StatelessWidget {
|
||||||
)
|
)
|
||||||
: abbreviationTextStyle;
|
: abbreviationTextStyle;
|
||||||
|
|
||||||
var identifier = "${identifiers.weekDayButtonIdentifier}_$index";
|
|
||||||
|
|
||||||
return AnimatedContainer(
|
return AnimatedContainer(
|
||||||
duration: const Duration(milliseconds: 300),
|
duration: const Duration(milliseconds: 300),
|
||||||
height: isSelected ? 72 : 64,
|
height: isSelected ? 72 : 64,
|
||||||
width: isSelected ? 72 : 64,
|
width: isSelected ? 72 : 64,
|
||||||
child: CustomSemantics(
|
child: ChoiceChip(
|
||||||
identifier: identifier,
|
shape: RoundedRectangleBorder(borderRadius: options.borderRadius),
|
||||||
child: ChoiceChip(
|
padding: EdgeInsets.zero,
|
||||||
shape: RoundedRectangleBorder(borderRadius: options.borderRadius),
|
label: Center(
|
||||||
padding: EdgeInsets.zero,
|
child: Text(
|
||||||
label: Center(
|
day.toUpperCase(),
|
||||||
child: Text(
|
style: abbreviationTextStyle,
|
||||||
day.toUpperCase(),
|
|
||||||
style: abbreviationTextStyle,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
selected: isSelected,
|
|
||||||
showCheckmark: theme.chipTheme.showCheckmark ?? false,
|
|
||||||
onSelected: onDaySelected,
|
|
||||||
),
|
),
|
||||||
|
selected: isSelected,
|
||||||
|
showCheckmark: theme.chipTheme.showCheckmark ?? false,
|
||||||
|
onSelected: onDaySelected,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_accessibility/flutter_accessibility.dart";
|
|
||||||
import "package:flutter_availability/src/ui/view_models/break_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/break_view_model.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/template_daydata_view_model.dart";
|
import "package:flutter_availability/src/ui/view_models/template_daydata_view_model.dart";
|
||||||
import "package:flutter_availability/src/ui/view_models/week_template_view_models.dart";
|
import "package:flutter_availability/src/ui/view_models/week_template_view_models.dart";
|
||||||
|
@ -29,24 +28,12 @@ class TemplateWeekOverview extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
var colors = options.colors;
|
var colors = options.colors;
|
||||||
|
|
||||||
var dayNames = getDaysOfTheWeekAsStrings(translations, context);
|
var dayNames = getDaysOfTheWeekAsStrings(translations, context);
|
||||||
|
|
||||||
var templateData = template.data;
|
var templateData = template.data;
|
||||||
|
|
||||||
var editButton = CustomSemantics(
|
|
||||||
identifier: identifiers.weekTemplateEditButtonIdentifier,
|
|
||||||
child: options.smallTextButtonBuilder(
|
|
||||||
context,
|
|
||||||
onClickEdit,
|
|
||||||
Text(
|
|
||||||
translations.editTemplateButton,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
@ -59,7 +46,13 @@ class TemplateWeekOverview extends StatelessWidget {
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
editButton,
|
options.smallTextButtonBuilder(
|
||||||
|
context,
|
||||||
|
onClickEdit,
|
||||||
|
Text(
|
||||||
|
translations.editTemplateButton,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const SizedBox(height: 8),
|
const SizedBox(height: 8),
|
||||||
|
@ -74,13 +67,12 @@ class TemplateWeekOverview extends StatelessWidget {
|
||||||
),
|
),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
for (var (index, day) in WeekDay.values.indexed) ...[
|
for (var day in WeekDay.values) ...[
|
||||||
_TemplateDayDetailRow(
|
_TemplateDayDetailRow(
|
||||||
dayName: dayNames[index],
|
dayName: dayNames[day.index],
|
||||||
dayData:
|
dayData:
|
||||||
templateData.containsKey(day) ? templateData[day] : null,
|
templateData.containsKey(day) ? templateData[day] : null,
|
||||||
index: index,
|
isOdd: day.index.isOdd,
|
||||||
isOdd: index.isOdd,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
@ -96,7 +88,6 @@ class _TemplateDayDetailRow extends StatelessWidget {
|
||||||
required this.dayName,
|
required this.dayName,
|
||||||
required this.dayData,
|
required this.dayData,
|
||||||
required this.isOdd,
|
required this.isOdd,
|
||||||
required this.index,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
/// The name of the day
|
/// The name of the day
|
||||||
|
@ -106,9 +97,6 @@ class _TemplateDayDetailRow extends StatelessWidget {
|
||||||
/// This causes a layered effect
|
/// This causes a layered effect
|
||||||
final bool isOdd;
|
final bool isOdd;
|
||||||
|
|
||||||
/// The index of the day
|
|
||||||
final int index;
|
|
||||||
|
|
||||||
/// The data of the day
|
/// The data of the day
|
||||||
final DayTemplateDataViewModel? dayData;
|
final DayTemplateDataViewModel? dayData;
|
||||||
|
|
||||||
|
@ -119,7 +107,6 @@ class _TemplateDayDetailRow extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var startTime = dayData?.startTime;
|
var startTime = dayData?.startTime;
|
||||||
var endTime = dayData?.endTime;
|
var endTime = dayData?.endTime;
|
||||||
|
@ -132,8 +119,6 @@ class _TemplateDayDetailRow extends StatelessWidget {
|
||||||
dayPeriod = translations.unavailable;
|
dayPeriod = translations.unavailable;
|
||||||
}
|
}
|
||||||
|
|
||||||
var dayPeriodIdentifier = "${identifiers.weekDayTimeIdentifier}_$index";
|
|
||||||
|
|
||||||
var breaks = dayData?.breaks ?? <BreakViewModel>[];
|
var breaks = dayData?.breaks ?? <BreakViewModel>[];
|
||||||
|
|
||||||
BoxDecoration? boxDecoration;
|
BoxDecoration? boxDecoration;
|
||||||
|
@ -160,23 +145,13 @@ class _TemplateDayDetailRow extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
Text(dayName, style: textTheme.bodyLarge),
|
Text(dayName, style: textTheme.bodyLarge),
|
||||||
CustomSemantics(
|
Text(dayPeriod, style: textTheme.bodyLarge),
|
||||||
identifier: dayPeriodIdentifier,
|
|
||||||
child: Text(
|
|
||||||
dayPeriod,
|
|
||||||
style: textTheme.bodyLarge,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
// for each break add a line
|
// for each break add a line
|
||||||
for (var (breakIndex, dayBreak) in breaks.indexed) ...[
|
for (var dayBreak in breaks) ...[
|
||||||
const SizedBox(height: 4),
|
const SizedBox(height: 4),
|
||||||
_TemplateDayDetailPauseRow(
|
_TemplateDayDetailPauseRow(dayBreakViewModel: dayBreak),
|
||||||
dayBreakViewModel: dayBreak,
|
|
||||||
dayIndex: index,
|
|
||||||
breakIndex: breakIndex,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@ -187,20 +162,10 @@ class _TemplateDayDetailRow extends StatelessWidget {
|
||||||
class _TemplateDayDetailPauseRow extends StatelessWidget {
|
class _TemplateDayDetailPauseRow extends StatelessWidget {
|
||||||
const _TemplateDayDetailPauseRow({
|
const _TemplateDayDetailPauseRow({
|
||||||
required this.dayBreakViewModel,
|
required this.dayBreakViewModel,
|
||||||
required this.dayIndex,
|
|
||||||
required this.breakIndex,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
final BreakViewModel dayBreakViewModel;
|
final BreakViewModel dayBreakViewModel;
|
||||||
|
|
||||||
/// The index of the day in the list of days
|
|
||||||
/// This is used to create unique identifiers when there are multiple days
|
|
||||||
/// with breaks
|
|
||||||
final int dayIndex;
|
|
||||||
|
|
||||||
/// The index of the break in the list of breaks
|
|
||||||
final int breakIndex;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var theme = Theme.of(context);
|
var theme = Theme.of(context);
|
||||||
|
@ -208,7 +173,6 @@ class _TemplateDayDetailPauseRow extends StatelessWidget {
|
||||||
var availabilityScope = AvailabilityScope.of(context);
|
var availabilityScope = AvailabilityScope.of(context);
|
||||||
var options = availabilityScope.options;
|
var options = availabilityScope.options;
|
||||||
var translations = options.translations;
|
var translations = options.translations;
|
||||||
var identifiers = options.accessibilityIds;
|
|
||||||
|
|
||||||
var dayBreak = dayBreakViewModel.toBreak();
|
var dayBreak = dayBreakViewModel.toBreak();
|
||||||
var startTime = TimeOfDay.fromDateTime(dayBreak.startTime);
|
var startTime = TimeOfDay.fromDateTime(dayBreak.startTime);
|
||||||
|
@ -222,9 +186,6 @@ class _TemplateDayDetailPauseRow extends StatelessWidget {
|
||||||
fontStyle: FontStyle.italic,
|
fontStyle: FontStyle.italic,
|
||||||
);
|
);
|
||||||
|
|
||||||
var breakIdentifier =
|
|
||||||
"${identifiers.weekDayBreakIdentifier}_${dayIndex}_$breakIndex";
|
|
||||||
|
|
||||||
return Row(
|
return Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
@ -235,12 +196,9 @@ class _TemplateDayDetailPauseRow extends StatelessWidget {
|
||||||
style: pauseTextStyle,
|
style: pauseTextStyle,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
CustomSemantics(
|
Text(
|
||||||
identifier: breakIdentifier,
|
pausePeriod,
|
||||||
child: Text(
|
style: pauseTextStyle,
|
||||||
pausePeriod,
|
|
||||||
style: pauseTextStyle,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
|
@ -29,7 +29,7 @@ class AvailabilityScope extends InheritedWidget {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool updateShouldNotify(AvailabilityScope oldWidget) =>
|
bool updateShouldNotify(AvailabilityScope oldWidget) =>
|
||||||
oldWidget.userId != userId || oldWidget.options != options;
|
oldWidget.userId != userId || options != options;
|
||||||
|
|
||||||
///
|
///
|
||||||
static AvailabilityScope of(BuildContext context) =>
|
static AvailabilityScope of(BuildContext context) =>
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_availability
|
name: flutter_availability
|
||||||
description: "Flutter availability userstory package"
|
description: "Flutter availability userstory package"
|
||||||
version: 1.2.0
|
version: 1.0.0
|
||||||
|
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
|
@ -14,10 +14,7 @@ dependencies:
|
||||||
flutter_hooks: ^0.20.5
|
flutter_hooks: ^0.20.5
|
||||||
flutter_availability_data_interface:
|
flutter_availability_data_interface:
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
version: ^1.2.0
|
version: ^1.0.0
|
||||||
flutter_accessibility:
|
|
||||||
hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
|
||||||
version: ^0.0.3
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@ -28,3 +25,4 @@ dev_dependencies:
|
||||||
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
url: https://github.com/Iconica-Development/flutter_iconica_analysis
|
||||||
ref: 7.0.0
|
ref: 7.0.0
|
||||||
|
|
||||||
|
flutter:
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
name: flutter_availability_data_interface
|
name: flutter_availability_data_interface
|
||||||
description: "The data interface for the flutter_availability component"
|
description: "The data interface for the flutter_availability component"
|
||||||
version: 1.2.0
|
version: 1.0.0
|
||||||
|
|
||||||
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
publish_to: https://forgejo.internal.iconica.nl/api/packages/internal/pub
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue