223 lines
6.1 KiB
Dart
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(),
|
|
),
|
|
);
|
|
},
|
|
);
|
|
}
|
|
}
|