9ff6d97c90
BUG: when deleting a product the product list won't update
266 lines
9.5 KiB
Dart
266 lines
9.5 KiB
Dart
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,
|
|
required 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;
|
|
int _ctrState = 0;
|
|
|
|
// 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),
|
|
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(widget.server, widget.room, raw))
|
|
.toList();
|
|
|
|
setState(() {
|
|
categories = resp;
|
|
});
|
|
});
|
|
}
|
|
|
|
void fetchProducts() {
|
|
final user = context.read<User>();
|
|
|
|
// 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<RoomProduct>((raw) =>
|
|
RoomProduct.fromJSON(widget.server, widget.room, raw))
|
|
.toList();
|
|
|
|
setState(() {
|
|
products = resp;
|
|
});
|
|
});
|
|
}
|
|
|
|
void fetchItem() {
|
|
final user = context.read<User>();
|
|
|
|
// 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;
|
|
_ctrName.text = resp.name;
|
|
_ctrDescription.text = resp.description;
|
|
_ctrValue = resp.value;
|
|
_ctrCategory = resp.category;
|
|
_ctrLink = resp.link;
|
|
_ctrUnit = resp.unit;
|
|
_ctrState = resp.state;
|
|
});
|
|
});
|
|
}
|
|
|
|
@override
|
|
void initState() {
|
|
super.initState();
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
fetchCategories();
|
|
fetchProducts();
|
|
|
|
fetchItem();
|
|
});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(AppLocalizations.of(context)!.editItem),
|
|
),
|
|
body: SingleChildScrollView(
|
|
child: Center(
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(14),
|
|
child: ConstrainedBox(
|
|
constraints: const BoxConstraints(maxWidth: 600),
|
|
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(
|
|
server: widget.server,
|
|
room: widget.room,
|
|
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<User>();
|
|
|
|
doNetworkRequest(scaffMgr,
|
|
req: () => postWithCreadentials(
|
|
credentials: user,
|
|
target: user.server,
|
|
path: 'changeItem',
|
|
body: {
|
|
'listItemID': widget.item,
|
|
'room': widget.room,
|
|
'server': widget.server,
|
|
'title': _ctrName.text,
|
|
'state': _ctrState,
|
|
'description': _ctrDescription.text,
|
|
'listCatID': _ctrCategory,
|
|
'unit': _ctrUnit,
|
|
'value': _ctrValue,
|
|
'listProdID': _ctrLink
|
|
}),
|
|
onOK: (_) async {
|
|
nav.pop();
|
|
});
|
|
},
|
|
label: Text(AppLocalizations.of(context)!.editItemShort),
|
|
icon: const Icon(Icons.edit)),
|
|
);
|
|
}
|
|
}
|