diameter/lib/components/forms.dart
2021-10-23 01:08:09 +02:00

223 lines
6.1 KiB
Dart

import 'package:diameter/components/progress_indicator.dart';
import 'package:flutter/material.dart';
class StyledForm extends StatefulWidget {
final List<Widget>? fields;
final List<Widget>? buttons;
final GlobalKey<FormState>? formState;
const StyledForm({Key? key, this.formState, this.fields, this.buttons})
: super(key: key);
@override
_StyledFormState createState() => _StyledFormState();
}
class _StyledFormState extends State<StyledForm> {
@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 StyledBooleanFormField extends StatefulWidget {
final bool value;
final String label;
final void Function(bool) onChanged;
final bool? enabled;
const StyledBooleanFormField(
{Key? key,
required this.value,
required this.label,
required this.onChanged,
this.enabled})
: super(key: key);
@override
_StyledBooleanFormFieldState createState() => _StyledBooleanFormFieldState();
}
class _StyledBooleanFormFieldState extends State<StyledBooleanFormField> {
@override
Widget build(BuildContext context) {
return FormField<bool>(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 StyledTimeOfDayFormField extends StatefulWidget {
final TimeOfDay time;
final TextEditingController controller;
final String label;
final void Function(TimeOfDay?) onChanged;
const StyledTimeOfDayFormField(
{Key? key,
required this.time,
required this.controller,
required this.label,
required this.onChanged})
: super(key: key);
@override
_StyledTimeOfDayFormFieldState createState() =>
_StyledTimeOfDayFormFieldState();
}
class _StyledTimeOfDayFormFieldState extends State<StyledTimeOfDayFormField> {
@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 StyledDropdownButton<T> extends StatefulWidget {
final String label;
final T? selectedItem;
final List<T> items;
final Widget Function(T item) renderItem;
final void Function(T? value) onChanged;
const StyledDropdownButton(
{Key? key,
this.selectedItem,
required this.label,
required this.items,
required this.renderItem,
required this.onChanged})
: super(key: key);
@override
_StyledDropdownButtonState<T> createState() => _StyledDropdownButtonState();
}
class _StyledDropdownButtonState<T> extends State<StyledDropdownButton<T>> {
@override
Widget build(BuildContext context) {
return DropdownButtonFormField<T>(
decoration: InputDecoration(
labelText: widget.label,
),
value: widget.selectedItem,
onChanged: widget.onChanged,
items: widget.items
.map((item) => DropdownMenuItem<T>(
value: item,
child: widget.renderItem(item),
))
.toList(),
);
}
}
class StyledFutureDropdownButton<T> extends StatefulWidget {
final String label;
final String? selectedItem;
final Future<List<T>> items;
final String? Function(T item) getItemValue;
final Widget Function(T item) renderItem;
final void Function(String? value) onChanged;
const StyledFutureDropdownButton(
{Key? key,
this.selectedItem,
required this.label,
required this.items,
required this.getItemValue,
required this.renderItem,
required this.onChanged})
: super(key: key);
@override
_StyledFutureDropdownButtonState<T> createState() =>
_StyledFutureDropdownButtonState();
}
class _StyledFutureDropdownButtonState<T>
extends State<StyledFutureDropdownButton<T>> {
@override
Widget build(BuildContext context) {
return FutureBuilder<List<T>>(
future: widget.items,
builder: (context, snapshot) {
return ViewWithProgressIndicator(
snapshot: snapshot,
padding: const EdgeInsets.all(10.0),
progressIndicatorSize: 44,
child: snapshot.data == null || snapshot.data!.isEmpty
? Row(
mainAxisAlignment: MainAxisAlignment.center,
children: const [
Padding(
padding: EdgeInsets.all(10.0),
child: Text('No Meal Sources'),
)
],
)
: DropdownButtonFormField<String>(
decoration: InputDecoration(
labelText: widget.label,
),
value: widget.selectedItem,
onChanged: widget.onChanged,
items: snapshot.data!
.map((item) => DropdownMenuItem<String>(
value: widget.getItemValue(item),
child: widget.renderItem(item),
))
.toList(),
),
);
},
);
}
}