From bd065242e6fe4168f216b89add327f76a5b7e3da Mon Sep 17 00:00:00 2001 From: Dian Bayu Nugroho Date: Mon, 19 Feb 2024 22:49:43 +0700 Subject: [PATCH] feat: component date picker --- .../date_picker/date_picker_view.dart | 144 ++++++++++++++++++ pubspec.lock | 20 ++- pubspec.yaml | 2 + 3 files changed, 160 insertions(+), 6 deletions(-) create mode 100644 lib/application/component/date_picker/date_picker_view.dart diff --git a/lib/application/component/date_picker/date_picker_view.dart b/lib/application/component/date_picker/date_picker_view.dart new file mode 100644 index 0000000..59a472d --- /dev/null +++ b/lib/application/component/date_picker/date_picker_view.dart @@ -0,0 +1,144 @@ +import 'package:calendar_date_picker2/calendar_date_picker2.dart'; +import 'package:cims_apps/application/component/button/button_view.dart'; +import 'package:cims_apps/application/component/text_form/text_form_view.dart'; +import 'package:cims_apps/application/theme/color_palette.dart'; +import 'package:cims_apps/core/utils/size_config.dart'; +import 'package:flutter/material.dart'; +import 'package:intl/intl.dart'; + +class DatePickerView extends StatelessWidget { + final String name; + final TextEditingController ctrl; + final DateTime? minDate, maxDate; + final String? hintText, buttonName; + final bool isMultipleSelection, enabled; + final List? initialValue; + final ValueChanged? onChanged; + final ValueChanged>? onFinish; + final FormFieldValidator? validatorDate; + const DatePickerView( + {Key? key, + required this.name, + required this.ctrl, + this.minDate, + this.maxDate, + this.hintText, + this.buttonName, + required this.isMultipleSelection, + required this.enabled, + this.initialValue, + this.onChanged, + this.onFinish, + this.validatorDate}) + : super(key: key); + + String _dateFormat(DateTime? dateTime) => + dateTime != null ? DateFormat('dd/MM/yyyy').format(dateTime) : ""; + + @override + Widget build(BuildContext context) { + List initData = initialValue ?? []; + List dateList = []; + + String dateLabel() { + return dateList.map((e) => _dateFormat(e)).join(" - "); + } + + onChangedDatePicker(List value) { + if (isMultipleSelection) { + final pickerDateRange = PickerDateRange( + startDate: value[0] ?? DateTime.now(), + endDate: + value.length > 1 ? value[1] ?? DateTime.now() : DateTime.now(), + ); + onChanged + ?.call(OnChangedDatePickerModel(pickerDateRange: pickerDateRange)); + } else { + onChanged?.call(OnChangedDatePickerModel(dateTime: value[0])); + } + dateList = value; + } + + dialogDatePicker() { + showModalBottomSheet( + context: context, + isScrollControlled: true, + builder: (BuildContext context) { + return Container( + padding: const EdgeInsets.only(top: 16.0), + height: SizeConfig.height * .65, + child: Column( + // mainAxisAlignment: MainAxisAlignment.spaceBetween, + mainAxisSize: MainAxisSize.min, + children: [ + CalendarDatePicker2( + value: [...initData], + config: CalendarDatePicker2Config( + centerAlignModePicker: true, + calendarType: isMultipleSelection + ? CalendarDatePicker2Type.range + : CalendarDatePicker2Type.single, + customModePickerIcon: const SizedBox(), + firstDate: minDate ?? DateTime(1900), + lastDate: maxDate, + ), + // initialValue: [...initData], + onValueChanged: (value) { + onChangedDatePicker(value); + }, + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: ButtonView( + width: SizeConfig.width, + onPressed: () { + if (dateList.isNotEmpty) { + onFinish?.call(dateList); + ctrl.text = dateLabel(); + initData = dateList; + } + Navigator.pop(context); + }, + name: 'OK', + ), + ), + ], + ), + ); + }, + ); + } + + return TextFormView( + name: name, + hintText: hintText, + readOnly: true, + ctrl: ctrl, + validator: validatorDate, + enabled: enabled, + onTap: () { + if (enabled) dialogDatePicker(); + }, + suffixIcon: const UnconstrainedBox( + child: Icon( + Icons.calendar_today_rounded, + color: ColorPalette.slate400, + ), + ), + ); + } +} + +class OnChangedDatePickerModel { + final DateTime? dateTime; + final PickerDateRange? pickerDateRange; + + OnChangedDatePickerModel({this.dateTime, this.pickerDateRange}); +} + +class PickerDateRange { + final DateTime startDate; + final DateTime endDate; + + PickerDateRange({required this.startDate, required this.endDate}); +} diff --git a/pubspec.lock b/pubspec.lock index c5fcec3..6fd9b82 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -49,6 +49,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" + calendar_date_picker2: + dependency: "direct main" + description: + name: calendar_date_picker2 + sha256: b91d51b8d0928f9745e0113e86d06b161ac48c52b7530337a3b77283cbc6be27 + url: "https://pub.dev" + source: hosted + version: "0.5.3" camera: dependency: "direct main" description: @@ -292,10 +300,10 @@ packages: dependency: transitive description: name: js - sha256: "4186c61b32f99e60f011f7160e32c89a758ae9b1d0c6d28e2c02ef0382300e2b" + sha256: c1b2e9b5ea78c45e1a0788d29606ba27dc5f71f019f32ca5140f61ef071838cf url: "https://pub.dev" source: hosted - version: "0.7.0" + version: "0.7.1" lints: dependency: transitive description: @@ -625,18 +633,18 @@ packages: dependency: transitive description: name: syncfusion_flutter_core - sha256: e8580e201c7197feac830b501889e877796a9fabbe20dcdbe90a981603939101 + sha256: "4eed0d3ae50c16b5e8e4957f3c1917e9bd0315a08dfb49a104ca8fc10244bef3" url: "https://pub.dev" source: hosted - version: "24.2.4" + version: "24.2.6" syncfusion_flutter_signaturepad: dependency: "direct main" description: name: syncfusion_flutter_signaturepad - sha256: "878e1063b909a83c83677627261780d42d532d0b5e7e259d84da805008e7fb0d" + sha256: da55bd7d796f2c9b4707f3e063e443f67c355c6098002e446bbf43672952916e url: "https://pub.dev" source: hosted - version: "24.2.4" + version: "24.2.6" synchronized: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index bda08a0..2ce93d1 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -51,6 +51,8 @@ dependencies: syncfusion_flutter_signaturepad: ^24.2.4 dotted_border: ^2.1.0 shared_preferences: ^2.2.2 + calendar_date_picker2: ^0.5.3 +