import 'package:flutter/material.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:outbag_app/backend/request.dart'; import 'package:outbag_app/backend/room.dart'; import 'package:outbag_app/backend/user.dart'; import 'package:outbag_app/components/category_picker.dart'; import 'package:outbag_app/components/product_picker.dart'; import 'package:outbag_app/components/value_unit_input.dart'; import 'package:outbag_app/tools/fetch_wrapper.dart'; import 'package:outbag_app/tools/snackbar.dart'; import 'package:provider/provider.dart'; class EditItemPage extends StatefulWidget { final String room; final String server; final int? item; const EditItemPage( {super.key, required this.room, required this.server, this.item}); @override State createState() => _EditItemPageState(); } class _EditItemPageState extends State { // input controllers final _ctrName = TextEditingController(); final _ctrDescription = TextEditingController(); int? _ctrCategory; int _ctrUnit = 0; String _ctrValue = ''; int? _ctrLink; // data cache List categories = []; List products = []; RoomItem? item; void fetchCategories() { final user = context.read(); // TODO: load cached categories first doNetworkRequest(ScaffoldMessenger.of(context), req: () => postWithCreadentials( credentials: user, target: user.server, path: 'getCategories', body: {'room': widget.room, 'server': widget.server}), onOK: (body) async { final resp = body['data'] .map((raw) => RoomCategory.fromJSON(raw)) .toList(); setState(() { categories = resp; }); }); } void fetchProducts() { final user = context.read(); // TODO: load cached products first doNetworkRequest(ScaffoldMessenger.of(context), req: () => postWithCreadentials( credentials: user, target: user.server, path: 'getProducts', body: {'room': widget.room, 'server': widget.server}), onOK: (body) async { final resp = body['data'] .map((raw) => RoomProduct.fromJSON(raw)) .toList(); setState(() { products = resp; }); }); } void fetchItem() { final user = context.read(); // TODO: load cached item first doNetworkRequest(ScaffoldMessenger.of(context), req: () => postWithCreadentials( credentials: user, target: user.server, path: 'getItem', body: { 'room': widget.room, 'server': widget.server, 'listItemID': widget.item }), onOK: (body) async { final resp = RoomItem.fromJSON(body['data']); setState(() { item = resp; }); }); } @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { fetchCategories(); fetchProducts(); if (widget.item != null) { fetchItem(); } }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: Text((widget.item == null) ? AppLocalizations.of(context)!.createItem : AppLocalizations.of(context)!.editItem), ), body: SingleChildScrollView( child: Center( child: Padding( padding: const EdgeInsets.all(14), child: ConstrainedBox( constraints: const BoxConstraints(maxWidth: 400), child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ Padding( padding: const EdgeInsets.all(8), child: TextField( controller: _ctrName, keyboardType: TextInputType.name, decoration: InputDecoration( prefixIcon: const Icon(Icons.badge), labelText: AppLocalizations.of(context)! .inputItemNameLabel, hintText: AppLocalizations.of(context)! .inputItemNameHint, helperText: AppLocalizations.of(context)! .inputItemNameHelp, border: const OutlineInputBorder(), ), ), ), ProductPicker( label: AppLocalizations.of(context)! .selectLinkedProductLabel, hint: AppLocalizations.of(context)! .selectLinkedProductHint, products: products, selected: _ctrLink, onSelect: (pid) { setState(() { _ctrLink = pid; }); }, ), Padding( padding: const EdgeInsets.all(8), child: TextField( controller: _ctrDescription, keyboardType: TextInputType.text, decoration: InputDecoration( labelText: AppLocalizations.of(context)! .inputItemDescriptionLabel, hintText: AppLocalizations.of(context)! .inputItemDescriptionHint, helperText: AppLocalizations.of(context)! .inputItemDescriptionHelp, prefixIcon: const Icon(Icons.dns), border: const OutlineInputBorder(), ), ), ), DynamicValueUnitInput( initialUnit: _ctrUnit, initialValue: _ctrValue, onUnitChange: (unit) { setState(() { _ctrUnit = unit; }); }, onValueChange: (value) { setState(() { _ctrValue = value; }); }, ), CategoryPicker( label: AppLocalizations.of(context)! .selectCategoryLabel, hint: AppLocalizations.of(context)! .selectCategoryHint, categories: categories, selected: _ctrCategory, onSelect: (cid) { setState(() { _ctrCategory = cid; }); }, ), ], ))))), floatingActionButton: FloatingActionButton.extended( onPressed: () async { final scaffMgr = ScaffoldMessenger.of(context); final trans = AppLocalizations.of(context); final nav = Navigator.of(context); if (_ctrName.text.isEmpty) { showSimpleSnackbar(scaffMgr, text: trans!.errorProductNameShouldNotBeEmpty, action: trans.ok); return; } final user = context.read(); if (widget.item == null) { doNetworkRequest(scaffMgr, req: () => postWithCreadentials( credentials: user, target: user.server, path: 'addItem', body: { 'room': widget.room, 'server': widget.server, 'state': 0, 'title': _ctrName.text, 'description': _ctrDescription.text, 'listCatID': _ctrCategory, 'unit': _ctrUnit, 'value': _ctrValue, 'listProdID': _ctrLink }), onOK: (_) async { nav.pop(); }); } else { doNetworkRequest(scaffMgr, req: () => postWithCreadentials( credentials: user, target: user.server, path: 'changeItem', body: { 'listItemID': widget.item, 'room': widget.room, 'server': widget.server, 'title': _ctrName.text, 'description': _ctrDescription.text, 'listCatID': _ctrCategory, 'defUnit': _ctrUnit, 'defValue': _ctrValue, 'listProdID': _ctrLink }), onOK: (_) async { nav.pop(); }); } }, label: Text(widget.item != null ? AppLocalizations.of(context)!.editItemShort : AppLocalizations.of(context)!.createItemShort), icon: Icon(widget.item != null ? Icons.edit : Icons.add)), ); } }