2024-02-22 20:36:59 +01:00
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
|
|
|
import 'package:go_router/go_router.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_chip.dart';
|
|
|
|
import 'package:outbag_app/tools/fetch_wrapper.dart';
|
|
|
|
import 'package:provider/provider.dart';
|
|
|
|
|
|
|
|
class NewItemPage extends StatefulWidget {
|
|
|
|
final String room;
|
|
|
|
final String server;
|
|
|
|
|
|
|
|
final int? item;
|
|
|
|
|
|
|
|
const NewItemPage(
|
|
|
|
{super.key, required this.room, required this.server, this.item});
|
|
|
|
|
|
|
|
@override
|
|
|
|
State<StatefulWidget> createState() => _NewItemPageState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _NewItemPageState extends State<NewItemPage> {
|
|
|
|
// input controllers
|
|
|
|
final _ctrInput = TextEditingController();
|
|
|
|
|
|
|
|
// 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']
|
2024-02-23 16:13:15 +01:00
|
|
|
.map<RoomCategory>((raw) =>
|
|
|
|
RoomCategory.fromJSON(widget.server, widget.room, raw))
|
2024-02-22 20:36:59 +01:00
|
|
|
.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(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;
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@override
|
|
|
|
void initState() {
|
|
|
|
super.initState();
|
|
|
|
|
|
|
|
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
|
|
fetchCategories();
|
|
|
|
fetchProducts();
|
|
|
|
|
|
|
|
if (widget.item != null) {
|
|
|
|
fetchItem();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
String _query = "";
|
|
|
|
|
|
|
|
void createItem(BuildContext ctx, String name, int? productID) {
|
|
|
|
final scaffMgr = ScaffoldMessenger.of(context);
|
|
|
|
final router = GoRouter.of(context);
|
|
|
|
final user = context.read<User>();
|
|
|
|
|
|
|
|
doNetworkRequest(scaffMgr,
|
|
|
|
req: () => postWithCreadentials(
|
|
|
|
target: user.server,
|
|
|
|
credentials: user,
|
|
|
|
path: 'addItem',
|
|
|
|
body: {
|
|
|
|
'room': widget.room,
|
|
|
|
'server': widget.server,
|
|
|
|
'state': 0,
|
|
|
|
'title': name,
|
|
|
|
'description': '',
|
|
|
|
'listCatID': null,
|
|
|
|
'unit': 0,
|
|
|
|
'value': '',
|
|
|
|
'listProdID': productID
|
|
|
|
}),
|
|
|
|
onOK: (body) async {
|
|
|
|
final id = body["data"]["listItemID"];
|
|
|
|
// TODO cache item
|
|
|
|
// launch edit item screen
|
|
|
|
router.pushReplacementNamed('edit-item', params: {
|
|
|
|
'server': widget.server,
|
|
|
|
'id': widget.room,
|
|
|
|
'item': id.toString()
|
|
|
|
});
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
void createProduct(BuildContext ctx, String name, Function(int) cb) {
|
|
|
|
final scaffMgr = ScaffoldMessenger.of(context);
|
|
|
|
final user = context.read<User>();
|
|
|
|
|
|
|
|
doNetworkRequest(scaffMgr,
|
|
|
|
req: () => postWithCreadentials(
|
|
|
|
target: user.server,
|
|
|
|
credentials: user,
|
|
|
|
path: 'addProduct',
|
|
|
|
body: {
|
|
|
|
'room': widget.room,
|
|
|
|
'server': widget.server,
|
|
|
|
'title': name,
|
|
|
|
'description': '',
|
|
|
|
'listCatID': null,
|
|
|
|
'defUnit': 0,
|
|
|
|
'defValue': '',
|
|
|
|
'ean': '',
|
|
|
|
'parent': null
|
|
|
|
}),
|
|
|
|
onOK: (body) async {
|
|
|
|
final id = body["data"]["listProdID"];
|
|
|
|
// TODO: cache product
|
|
|
|
cb(id);
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
@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: [
|
|
|
|
SearchBar(
|
|
|
|
controller: _ctrInput,
|
|
|
|
leading: const Icon(Icons.search),
|
|
|
|
hintText:
|
|
|
|
AppLocalizations.of(context)!.newItemQueryHint,
|
|
|
|
onChanged: (text) {
|
|
|
|
setState(() {
|
|
|
|
_query = text;
|
|
|
|
});
|
|
|
|
},
|
|
|
|
),
|
|
|
|
const Divider(),
|
|
|
|
// button bar
|
|
|
|
...((_query == "")
|
|
|
|
? ([
|
|
|
|
Text(AppLocalizations.of(context)!
|
|
|
|
.newItemQueryEmpty)
|
|
|
|
])
|
|
|
|
: ([
|
|
|
|
Wrap(
|
|
|
|
spacing: 20,
|
|
|
|
runSpacing: 10,
|
|
|
|
alignment: WrapAlignment.center,
|
|
|
|
crossAxisAlignment:
|
|
|
|
WrapCrossAlignment.center,
|
|
|
|
children: [
|
|
|
|
Text(AppLocalizations.of(context)!
|
|
|
|
.newItemQuickAccessPrefix),
|
|
|
|
// new item
|
|
|
|
FilledButton.icon(
|
|
|
|
onPressed: () {
|
|
|
|
// create new named item
|
|
|
|
// launch edit item screen once done
|
|
|
|
createItem(context, _query, null);
|
|
|
|
},
|
|
|
|
icon: const Icon(Icons.add),
|
|
|
|
label: Text(_query)),
|
|
|
|
// new product
|
|
|
|
FilledButton.icon(
|
|
|
|
onPressed: () {
|
|
|
|
// create new product with name,
|
|
|
|
// create new item with name
|
|
|
|
// and link to the created product
|
|
|
|
// launch edit item screen once done
|
|
|
|
createProduct(
|
|
|
|
context,
|
|
|
|
_query,
|
|
|
|
(p0) => createItem(
|
|
|
|
context, _query, p0));
|
|
|
|
},
|
|
|
|
icon: const Icon(Icons.add),
|
|
|
|
label: Text(AppLocalizations.of(
|
|
|
|
context)!
|
|
|
|
.newItemQuickProduct(_query))),
|
|
|
|
])
|
|
|
|
])),
|
|
|
|
const Divider(),
|
|
|
|
// link products search
|
|
|
|
...((products
|
|
|
|
// show all products if query is empty
|
|
|
|
// when query isn't empty show products
|
|
|
|
// that contain the query in the title
|
|
|
|
// or description
|
|
|
|
.where((element) =>
|
|
|
|
(_query == "") ||
|
|
|
|
element.name.contains(_query) ||
|
|
|
|
element.description.contains(_query))
|
|
|
|
.map((e) => ListTile(
|
|
|
|
title: Text(e.name),
|
|
|
|
subtitle: Text(e.description),
|
|
|
|
trailing: CategoryChip(
|
2024-02-23 16:13:15 +01:00
|
|
|
server: widget.server,
|
|
|
|
room: widget.room,
|
2024-02-22 20:36:59 +01:00
|
|
|
category: categories
|
|
|
|
.where((element) =>
|
|
|
|
element.id == e.category)
|
|
|
|
.firstOrNull ??
|
2024-02-23 16:13:15 +01:00
|
|
|
RoomCategory.other(widget.server,
|
|
|
|
widget.room, context),
|
2024-02-22 20:36:59 +01:00
|
|
|
),
|
|
|
|
onTap: () {
|
|
|
|
// create new item and link it to the product
|
|
|
|
// launch edit item screen once done
|
|
|
|
createItem(
|
|
|
|
context,
|
|
|
|
// use productname as item name
|
|
|
|
e.name,
|
|
|
|
e.id);
|
|
|
|
},
|
|
|
|
))))
|
|
|
|
],
|
|
|
|
))))),
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|