import 'package:flutter/material.dart'; class FormWrapper extends StatefulWidget { final List? fields; final List? buttons; final GlobalKey? formState; const FormWrapper({Key? key, this.formState, this.fields, this.buttons}) : super(key: key); @override _FormWrapperState createState() => _FormWrapperState(); } class _FormWrapperState extends State { @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.all(10.0), child: Form( key: widget.formState, child: Column( children: [ Column( children: widget.fields ?.map((e) => Padding( padding: const EdgeInsets.symmetric(vertical: 5.0), child: e)) .toList() ?? [], ), Container( padding: const EdgeInsets.only(top: 10.0), child: Row( mainAxisSize: MainAxisSize.max, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: widget.buttons ?? [], ), ), ], ), ), ); } } class BooleanFormField extends StatefulWidget { final bool value; final String label; final void Function(bool) onChanged; final bool? enabled; const BooleanFormField( {Key? key, required this.value, required this.label, required this.onChanged, this.enabled}) : super(key: key); @override _BooleanFormFieldState createState() => _BooleanFormFieldState(); } class _BooleanFormFieldState extends State { @override Widget build(BuildContext context) { return FormField(builder: (context) { return ListTile( onTap: () => widget.onChanged(!widget.value), trailing: Switch( value: widget.value, onChanged: widget.onChanged, ), title: Text(widget.label), enabled: widget.enabled ?? true, ); }); } } class DateTimeFormField extends StatefulWidget { final DateTime date; final DateTime? minDate; final DateTime? maxDate; final TextEditingController controller; final String label; final void Function(DateTime?) onChanged; const DateTimeFormField( {Key? key, required this.date, this.minDate, this.maxDate, required this.controller, required this.label, required this.onChanged}) : super(key: key); @override _DateTimeFormFieldState createState() => _DateTimeFormFieldState(); } class _DateTimeFormFieldState extends State { @override Widget build(BuildContext context) { return TextFormField( readOnly: true, controller: widget.controller, decoration: InputDecoration( labelText: widget.label, ), onTap: () async { final newTime = await showDatePicker( context: context, initialDate: widget.date, firstDate: widget.minDate ?? DateTime(2000,1,1), lastDate: widget.maxDate ?? DateTime.now(), ); widget.onChanged(newTime); }, ); } } class TimeOfDayFormField extends StatefulWidget { final TimeOfDay time; final TextEditingController controller; final String label; final void Function(TimeOfDay?) onChanged; const TimeOfDayFormField( {Key? key, required this.time, required this.controller, required this.label, required this.onChanged}) : super(key: key); @override _TimeOfDayFormFieldState createState() => _TimeOfDayFormFieldState(); } class _TimeOfDayFormFieldState extends State { @override Widget build(BuildContext context) { return TextFormField( readOnly: true, controller: widget.controller, decoration: InputDecoration( labelText: widget.label, ), onTap: () async { final newTime = await showTimePicker( context: context, initialTime: widget.time, ); widget.onChanged(newTime); }, ); } } class LabeledDropdownButton extends StatefulWidget { final String label; final T? selectedItem; final List items; final Widget Function(T item) renderItem; final void Function(T? value) onChanged; const LabeledDropdownButton( {Key? key, this.selectedItem, required this.label, required this.items, required this.renderItem, required this.onChanged}) : super(key: key); @override _LabeledDropdownButtonState createState() => _LabeledDropdownButtonState(); } class _LabeledDropdownButtonState extends State> { @override Widget build(BuildContext context) { return DropdownButtonFormField( decoration: InputDecoration( labelText: widget.label, ), value: widget.selectedItem, onChanged: widget.onChanged, items: widget.items .map((item) => DropdownMenuItem( value: item, child: widget.renderItem(item), )) .toList(), ); } }