From f35a7a74b32f13f57d839a9da2d68f9b41d4cdbd Mon Sep 17 00:00:00 2001 From: HammadAsiif Date: Fri, 15 Nov 2024 14:38:42 +0100 Subject: [PATCH] feat(controls): add date control implementation --- apps/example/lib/main.dart | 36 ++++++ apps/example/pubspec.yaml | 1 + .../lib/src/config/controls/controls.dart | 31 +++++ .../lib/src/config/controls/date.dart | 106 ++++++++++++++++++ packages/flutter_settings/pubspec.yaml | 1 + 5 files changed, 175 insertions(+) create mode 100644 packages/flutter_settings/lib/src/config/controls/date.dart diff --git a/apps/example/lib/main.dart b/apps/example/lib/main.dart index 4d6a199..ee924dc 100644 --- a/apps/example/lib/main.dart +++ b/apps/example/lib/main.dart @@ -42,6 +42,42 @@ var settingControls = [ ), ], ), + ControlConfig.group( + title: "Date Input Examples", + children: [ + ControlConfig.date( + key: "basic_date_picker", + title: "Pick a Date", + description: "Select a date using a calendar picker.", + hintText: "Select Date", + maxwidth: 160, + ), + ControlConfig.date( + key: "custom_date_picker", + title: "Pick a Date with Custom Range", + description: "Choose a date within a limited range and custom format.", + hintText: "DD/MM/YYYY", + firstDate: DateTime(2000), + lastDate: DateTime(2001), + suffixIcon: const Icon(Icons.calendar_today), + maxwidth: 200, + ), + ControlConfig.date( + key: "styled_date_picker", + title: "Styled Date Picker", + description: "A date picker with custom input decoration.", + hintText: "DD/MM/YYYY", + maxwidth: 240, + inputDecoration: InputDecoration( + fillColor: Colors.deepPurple[200], + filled: true, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + ), + ], + ), ControlConfig.group( title: "Radio Options", children: [ diff --git a/apps/example/pubspec.yaml b/apps/example/pubspec.yaml index 9702a1a..aab0a38 100644 --- a/apps/example/pubspec.yaml +++ b/apps/example/pubspec.yaml @@ -38,6 +38,7 @@ dependencies: device_settings_repository: path: ../../packages/device_settings_repository image_picker: ^1.1.2 + intl: ^0.20.0 dev_dependencies: flutter_test: diff --git a/packages/flutter_settings/lib/src/config/controls/controls.dart b/packages/flutter_settings/lib/src/config/controls/controls.dart index 918e998..d6bd9d7 100644 --- a/packages/flutter_settings/lib/src/config/controls/controls.dart +++ b/packages/flutter_settings/lib/src/config/controls/controls.dart @@ -1,4 +1,7 @@ +import "package:flutter/material.dart"; import "package:flutter_settings/flutter_settings.dart"; +import "package:flutter_settings/src/config/controls/checkbox.dart"; +import "package:flutter_settings/src/config/controls/date.dart"; import "package:flutter_settings/src/config/controls/radio.dart"; import "package:settings_repository/settings_repository.dart"; @@ -28,6 +31,34 @@ abstract final class ControlConfig { wrapperBuilder: wrapperBuilder ?? defaultDescriptionTitleControlWrapper, ); + /// + static DateControlConfig date({ + required String key, + required String title, + String? description, + String? hintText, + String? dateFormat, + double? maxwidth, + Widget? suffixIcon, + DateTime? firstDate, + DateTime? lastDate, + InputDecoration? inputDecoration, + ControlWrapperBuilder? wrapperBuilder, + }) => + DateControlConfig( + title: title, + description: description, + hintText: hintText, + suffixIcon: suffixIcon, + dateFormat: dateFormat, + maxwidth: maxwidth, + firstDate: firstDate, + lastDate: lastDate, + inputDecoration: inputDecoration, + initialValue: SettingsControl(key: key), + wrapperBuilder: wrapperBuilder ?? defaultDescriptionTitleControlWrapper, + ); + /// static SettingsControlConfig toggle({ required String key, diff --git a/packages/flutter_settings/lib/src/config/controls/date.dart b/packages/flutter_settings/lib/src/config/controls/date.dart new file mode 100644 index 0000000..ada5f05 --- /dev/null +++ b/packages/flutter_settings/lib/src/config/controls/date.dart @@ -0,0 +1,106 @@ +import "package:flutter/material.dart"; +import "package:flutter_settings/flutter_settings.dart"; +import "package:intl/intl.dart"; +import "package:settings_repository/settings_repository.dart"; + +/// Date Control Configuration +class DateControlConfig + extends DescriptiveTitleControlConfig { + /// Constructor for Date Control Config + DateControlConfig({ + required super.title, + required super.description, + required super.initialValue, + this.maxwidth, + this.hintText, + this.suffixIcon, + this.dateFormat = "dd-MM-yyyy", + this.firstDate, + this.lastDate, + this.inputDecoration, + super.wrapperBuilder = defaultDescriptionTitleControlWrapper, + }); + + /// Max width for the input field + final double? maxwidth; + + /// Hint text for the date picker + final String? hintText; + + /// Icon to display as suffix in the input field + final Widget? suffixIcon; + + /// Date format (using `intl` package) + final String? dateFormat; + + /// Minimum selectable date + final DateTime? firstDate; + + /// Maximum selectable date + final DateTime? lastDate; + + /// Optional custom `InputDecoration` for the date control + final InputDecoration? inputDecoration; + + @override + Widget buildSetting( + BuildContext context, + SettingsControl control, + SettingsControlController controller, + ) { + var theme = Theme.of(context); + var initialDate = control.value != null + ? DateFormat(dateFormat).parse(control.value!) + : DateTime.now(); + + return InkWell( + onTap: () async { + var pickedDate = await showDatePicker( + context: context, + initialDate: initialDate, + firstDate: firstDate ?? DateTime(1900), + lastDate: lastDate ?? DateTime(2100), + ); + + if (pickedDate != null) { + var formattedDate = DateFormat(dateFormat).format(pickedDate); + await controller.updateControl(control.update(formattedDate)); + } + }, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16.0), + child: Container( + constraints: BoxConstraints(maxWidth: maxwidth ?? 200), + child: InputDecorator( + decoration: inputDecoration ?? + InputDecoration( + hintText: hintText, + suffixIcon: suffixIcon, + fillColor: theme.colorScheme.surface, + filled: true, + contentPadding: + const EdgeInsets.symmetric(horizontal: 20, vertical: 10), + enabledBorder: OutlineInputBorder( + borderSide: BorderSide.none, + borderRadius: BorderRadius.circular(12), + ), + focusedBorder: OutlineInputBorder( + borderSide: + BorderSide(color: theme.colorScheme.primary, width: 2), + borderRadius: BorderRadius.circular(12), + ), + errorBorder: OutlineInputBorder( + borderSide: + BorderSide(color: theme.colorScheme.error, width: 2), + borderRadius: BorderRadius.circular(12), + ), + ), + child: Text( + control.value ?? hintText ?? "Select a date", + ), + ), + ), + ), + ); + } +} diff --git a/packages/flutter_settings/pubspec.yaml b/packages/flutter_settings/pubspec.yaml index a3ac19d..c64259d 100644 --- a/packages/flutter_settings/pubspec.yaml +++ b/packages/flutter_settings/pubspec.yaml @@ -13,6 +13,7 @@ dependencies: flutter: sdk: flutter flutter_hooks: ^0.20.5 + intl: ^0.20.0 settings_repository: hosted: https://forgejo.internal.iconica.nl/api/packages/internal/pub version: ^1.0.0