actions-test/lib/screens/room/items/edit.dart

279 lines
10 KiB
Dart
Raw Normal View History

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(
2023-12-22 20:14:36 +01:00
{super.key, required this.room, required this.server, this.item});
@override
State<StatefulWidget> createState() => _EditItemPageState();
}
class _EditItemPageState extends State<EditItemPage> {
// input controllers
final _ctrName = TextEditingController();
final _ctrDescription = TextEditingController();
int? _ctrCategory;
int _ctrUnit = 0;
String _ctrValue = '';
int? _ctrLink;
// data cache
List<RoomCategory> categories = [];
List<RoomProduct> products = [];
RoomItem? item;
void fetchCategories() {
final user = context.read<User>();
// TODO: load cached categories first
doNetworkRequest(ScaffoldMessenger.of(context),
2023-12-22 20:14:36 +01:00
req: () => postWithCreadentials(
credentials: user,
target: user.server,
path: 'getCategories',
body: {'room': widget.room, 'server': widget.server}),
onOK: (body) async {
final resp = body['data']
.map<RoomCategory>((raw) => RoomCategory.fromJSON(raw))
.toList();
2023-12-22 20:14:36 +01:00
setState(() {
categories = resp;
2023-12-22 20:14:36 +01:00
});
});
}
void fetchProducts() {
final user = context.read<User>();
// TODO: load cached products first
doNetworkRequest(ScaffoldMessenger.of(context),
2023-12-22 20:14:36 +01:00
req: () => postWithCreadentials(
credentials: user,
target: user.server,
path: 'getProducts',
body: {'room': widget.room, 'server': widget.server}),
onOK: (body) async {
final resp = body['data']
.map<RoomProduct>((raw) => RoomProduct.fromJSON(raw))
.toList();
2023-12-22 20:14:36 +01:00
setState(() {
products = resp;
2023-12-22 20:14:36 +01:00
});
});
}
void fetchItem() {
final user = context.read<User>();
// TODO: load cached item first
doNetworkRequest(ScaffoldMessenger.of(context),
2023-12-22 20:14:36 +01:00
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;
2023-12-22 20:14:36 +01:00
});
});
}
@override
void initState() {
super.initState();
WidgetsBinding.instance.addPostFrameCallback((_) {
2023-12-22 20:14:36 +01:00
fetchCategories();
fetchProducts();
2023-12-22 20:14:36 +01:00
if (widget.item != null) {
fetchItem();
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text((widget.item == null)
2023-12-22 20:14:36 +01:00
? AppLocalizations.of(context)!.createItem
: AppLocalizations.of(context)!.editItem),
),
body: SingleChildScrollView(
2023-12-22 20:14:36 +01:00
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(
2023-12-22 20:14:36 +01:00
onPressed: () async {
final scaffMgr = ScaffoldMessenger.of(context);
final trans = AppLocalizations.of(context);
final nav = Navigator.of(context);
2023-12-22 20:14:36 +01:00
if (_ctrName.text.isEmpty) {
showSimpleSnackbar(scaffMgr,
text: trans!.errorProductNameShouldNotBeEmpty,
action: trans.ok);
return;
}
2023-12-22 20:14:36 +01:00
final user = context.read<User>();
2023-12-22 20:14:36 +01:00
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)),
);
}
}