diff --git a/lib/pages/consume.dart b/lib/pages/consume.dart index f32c582..231bcec 100644 --- a/lib/pages/consume.dart +++ b/lib/pages/consume.dart @@ -1,4 +1,5 @@ import 'package:cdb_ui/api.dart'; +import 'package:cdb_ui/pages/supply.dart'; import 'package:flutter/material.dart'; class ConsumePage extends StatefulWidget { @@ -64,45 +65,18 @@ class _ConsumePageState extends State { crossAxisAlignment: CrossAxisAlignment.start, children: [ // Destination Field with Dropdown and Text Input - Autocomplete( - optionsBuilder: (TextEditingValue textEditingValue) { - if (textEditingValue.text.isEmpty) { - return destinations; - } - return destinations.where((String option) { - return option - .toLowerCase() - .contains(textEditingValue.text.toLowerCase()); - }); - }, - onSelected: (String selection) { - setState(() { - _selectedDestination = selection; - }); - }, - fieldViewBuilder: (context, textEditingController, - focusNode, onFieldSubmitted) { - textEditingController.text = _selectedDestination; - return TextFormField( - onChanged: (value) { - _selectedDestination = value; - }, - controller: textEditingController, - focusNode: focusNode, - decoration: const InputDecoration( - labelText: 'Destination', - border: OutlineInputBorder(), - ), - validator: (value) { - if (value?.isEmpty ?? true) { - return "Please enter a destination"; - } - - return null; - }, - ); - }, - ), + AutocompletedTextField( + options: destinations, + getValue: () => _selectedDestination, + onChanged: (value) { + _selectedDestination = value; + }, + onSelection: (selection) { + setState(() { + _selectedDestination = selection; + }); + }, + label: "Destination"), const SizedBox(height: 16), diff --git a/lib/pages/supply.dart b/lib/pages/supply.dart index 75c13cb..5df8bda 100644 --- a/lib/pages/supply.dart +++ b/lib/pages/supply.dart @@ -89,45 +89,25 @@ class _SupplyPageState extends State { const SizedBox(height: 16), // Origin Field with Dropdown and Text Input - Autocomplete( - optionsBuilder: (TextEditingValue textEditingValue) { - if (textEditingValue.text.isEmpty) { - return origins; - } - return origins.where((String option) { - return option - .toLowerCase() - .contains(textEditingValue.text.toLowerCase()); - }); - }, - onSelected: (String selection) async { - var price = _price.isEmpty - ? await API() - .getLatestPrice(widget.item.id, variant, - origin: selection) - .then((x) => x.value.toStringAsFixed(2)) - : _price; - setState(() { - _price = price; - _selectedOrigin = selection; - }); - }, - fieldViewBuilder: (context, textEditingController, - focusNode, onFieldSubmitted) { - textEditingController.text = _selectedOrigin; - return TextFormField( - onChanged: (value) { - _selectedOrigin = value; - }, - controller: textEditingController, - focusNode: focusNode, - decoration: const InputDecoration( - labelText: 'Origin', - border: OutlineInputBorder(), - ), - ); - }, - ), + AutocompletedTextField( + options: origins, + getValue: () => _selectedOrigin, + onChanged: (value) { + _selectedOrigin = value; + }, + onSelection: (String selection) async { + var price = _price.isEmpty + ? await API() + .getLatestPrice(widget.item.id, variant, + origin: selection) + .then((x) => x.value.toStringAsFixed(2)) + : _price; + setState(() { + _price = price; + _selectedOrigin = selection; + }); + }, + label: "Origin"), const SizedBox(height: 16), @@ -220,3 +200,50 @@ class _SupplyPageState extends State { return {'locations': locations, 'origins': origins}; } } + +// ignore: must_be_immutable +class AutocompletedTextField extends StatelessWidget { + late List options; + late Function(String) onChanged; + late String Function() getValue; + late Function(String) onSelection; + late String label; + + AutocompletedTextField( + {super.key, + required this.options, + required this.getValue, + required this.onChanged, + required this.onSelection, + required this.label}); + + @override + Widget build(BuildContext context) { + return Autocomplete( + optionsBuilder: (TextEditingValue textEditingValue) { + if (textEditingValue.text.isEmpty) { + return options; + } + return options.where((String option) { + return option + .toLowerCase() + .contains(textEditingValue.text.toLowerCase()); + }); + }, + onSelected: onSelection, + fieldViewBuilder: + (context, textEditingController, focusNode, onFieldSubmitted) { + textEditingController.text = getValue(); + return TextFormField( + onChanged: onChanged, + controller: textEditingController, + focusNode: focusNode, + decoration: InputDecoration( + labelText: label, + border: const OutlineInputBorder(), + ), + ); + }, + ); + } +}