diameter/lib/components/forms.dart

240 lines
6.1 KiB
Dart

import 'package:flutter/material.dart';
class FormWrapper extends StatefulWidget {
final List<Widget>? fields;
final List<Widget>? buttons;
final GlobalKey<FormState>? formState;
const FormWrapper({Key? key, this.formState, this.fields, this.buttons})
: super(key: key);
@override
_FormWrapperState createState() => _FormWrapperState();
}
class _FormWrapperState extends State<FormWrapper> {
@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;
final EdgeInsets? contentPadding;
const BooleanFormField(
{Key? key,
required this.value,
required this.label,
required this.onChanged,
this.enabled,
this.contentPadding})
: super(key: key);
@override
_BooleanFormFieldState createState() => _BooleanFormFieldState();
}
class _BooleanFormFieldState extends State<BooleanFormField> {
@override
Widget build(BuildContext context) {
return FormField<bool>(builder: (state) {
return ListTile(
contentPadding: widget.contentPadding,
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<DateTimeFormField> {
@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().add(const Duration(days: 365)),
);
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<TimeOfDayFormField> {
@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 NumberFormField extends StatefulWidget {
final TextEditingController controller;
final String label;
final String? suffix;
final void Function(double?) onChanged;
final double? min;
final double? max;
final double step;
const NumberFormField(
{Key? key,
required this.controller,
required this.label,
this.suffix,
required this.onChanged,
this.min,
this.max,
this.step = 1})
: super(key: key);
@override
_NumberFormFieldState createState() => _NumberFormFieldState();
}
class _NumberFormFieldState extends State<NumberFormField> {
void onIncrease() {
double value = double.tryParse(widget.controller.text) ?? 0;
if (widget.max == null || value + widget.step <= widget.max!) {
value += widget.step;
widget.onChanged(value);
}
}
void onDecrease() {
double value = double.tryParse(widget.controller.text) ?? 0;
if (widget.min == null || value - widget.step >= widget.min!) {
value -= widget.step;
widget.onChanged(value);
}
}
@override
Widget build(BuildContext context) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
IconButton(
onPressed: onDecrease,
icon: const Icon(Icons.remove),
),
Expanded(
child: TextFormField(
controller: widget.controller,
decoration: InputDecoration(
labelText: widget.label,
suffixText: widget.suffix,
),
keyboardType: const TextInputType.numberWithOptions(decimal: true),
onChanged: (value) async {
await Future.delayed(const Duration(seconds: 1));
widget.onChanged(double.tryParse(value));
},
),
),
IconButton(
onPressed: onIncrease,
icon: const Icon(Icons.add),
),
],
);
}
}