add produce flows

This commit is contained in:
JMARyA 2024-09-25 18:14:42 +02:00
parent 3da48add7e
commit 70b798f65f
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 192 additions and 48 deletions

View file

@ -1,4 +1,5 @@
import 'dart:convert'; import 'dart:convert';
import 'package:cdb_ui/pages/supply.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
@ -249,7 +250,9 @@ class API {
} }
// /flow/<id>/end // /flow/<id>/end
Future<List<String>?> endFlow(String id, {Map<String, int>? produced}) async { Future<List<String>?> endFlow(String id, {List<SupplyForm>? produced}) async {
// todo : update api for supplyform
var resp = jsonDecode( var resp = jsonDecode(
await postRequest("$instance/$id/end", {"produced": produced})); await postRequest("$instance/$id/end", {"produced": produced}));
@ -365,6 +368,12 @@ class Price {
currency = json["currency"]; currency = json["currency"];
} }
Price.fromString(String value) {
var priceSplit = value.split(" ");
this.value = double.parse(priceSplit[0]);
currency = priceSplit[1];
}
String format() { String format() {
return "${value.toStringAsFixed(2)} $currency"; return "${value.toStringAsFixed(2)} $currency";
} }
@ -394,6 +403,20 @@ class Transaction {
consumed = json["consumed"] != null ? ConsumeInfo(json["consumed"]) : null; consumed = json["consumed"] != null ? ConsumeInfo(json["consumed"]) : null;
location = json["location"] != null ? Location(json["location"]) : null; location = json["location"] != null ? Location(json["location"]) : null;
} }
Transaction.inMemory(String itemID, String variant, String price,
String? origin, Location? location, String? note) {
uuid = "";
item = itemID;
variant = variant;
this.price = Price.fromString(price);
origin = origin;
timestamp = 0;
consumed = null;
expired = false;
note = note;
location = location;
}
} }
class ConsumeInfo { class ConsumeInfo {

View file

@ -85,6 +85,7 @@ class _ActiveFlowPageState extends State<ActiveFlowPage> {
children: [ children: [
Text("ID: ${widget.flow.id}"), Text("ID: ${widget.flow.id}"),
Text("Started since: ${tsFormat(widget.flow.started)}"), Text("Started since: ${tsFormat(widget.flow.started)}"),
if (widget.flow.input != null)
...widget.flow.input!.map((x) => Text("Input: $x")).toList(), ...widget.flow.input!.map((x) => Text("Input: $x")).toList(),
if (widget.flow.done != null) ...[ if (widget.flow.done != null) ...[
Text("Ended: ${tsFormat(widget.flow.done!.ended)}"), Text("Ended: ${tsFormat(widget.flow.done!.ended)}"),

View file

@ -1,5 +1,8 @@
import 'dart:js_interop_unsafe';
import 'package:cdb_ui/api.dart' as API; import 'package:cdb_ui/api.dart' as API;
import 'package:cdb_ui/api.dart'; import 'package:cdb_ui/api.dart';
import 'package:cdb_ui/pages/supply.dart';
import 'package:cdb_ui/pages/transaction.dart'; import 'package:cdb_ui/pages/transaction.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
@ -14,7 +17,30 @@ class EndFlowWithProduce extends StatefulWidget {
} }
class _EndFlowWithProduceState extends State<EndFlowWithProduce> { class _EndFlowWithProduceState extends State<EndFlowWithProduce> {
Map<String, int> produces = {}; List<SupplyForm> produces = [];
late Map<String, Location> locations;
@override
void initState() {
super.initState();
API.API().getLocations().then(
(value) {
setState(() {
locations = value;
});
},
);
}
refresh() {
setState(() {});
}
void addProduced(SupplyForm t) {
setState(() {
produces.add(t);
});
}
List<Widget> addProduceButtons() { List<Widget> addProduceButtons() {
List<Widget> ret = []; List<Widget> ret = [];
@ -22,7 +48,21 @@ class _EndFlowWithProduceState extends State<EndFlowWithProduce> {
for (var i in widget.info.produces!) { for (var i in widget.info.produces!) {
ret.add(ElevatedButton( ret.add(ElevatedButton(
onPressed: () { onPressed: () {
// todo : implement adding var (itemID, variant) = API.itemVariant(i);
API.API().getItem(itemID).then((item) {
Navigator.of(context).push(MaterialPageRoute(
builder: (context) {
return SupplyPage(
item,
refresh,
onlyVariants: [variant],
forcePrice: "0.00",
forceOrigin: "flow::${widget.flow.kind}::${widget.flow.id}",
onCreate: addProduced,
);
},
));
});
}, },
child: Text("Produced $i"))); child: Text("Produced $i")));
} }
@ -48,6 +88,14 @@ class _EndFlowWithProduceState extends State<EndFlowWithProduce> {
...addProduceButtons(), ...addProduceButtons(),
const Divider(), const Divider(),
// todo : add produced list // todo : add produced list
...produces.map((x) {
return TransactionCard(
x.transaction(locations),
() {},
onLongPress: (x) {},
onTap: (x) {},
);
}).toList(),
const SizedBox( const SizedBox(
height: 10, height: 10,
), ),

View file

@ -9,7 +9,7 @@ class AddNotePage extends StatelessWidget {
AddNotePage(this.flow, this.refresh, {super.key}); AddNotePage(this.flow, this.refresh, {super.key});
_submit(BuildContext context) { void _submit(BuildContext context) {
API.API().addNoteToFlow(flow.id, _noteController.text).then((x) { API.API().addNoteToFlow(flow.id, _noteController.text).then((x) {
refresh(); refresh();
Navigator.of(context).pop(); Navigator.of(context).pop();
@ -32,7 +32,7 @@ class AddNotePage extends StatelessWidget {
height: 14, height: 14,
), ),
ElevatedButton( ElevatedButton(
onPressed: _submit(context), child: const Text("Add Note")) onPressed: () => _submit(context), child: const Text("Add Note"))
], ],
), ),
); );

View file

@ -5,14 +5,26 @@ import 'package:qr_bar_code_scanner_dialog/qr_bar_code_scanner_dialog.dart';
class SupplyPage extends StatefulWidget { class SupplyPage extends StatefulWidget {
final Item item; final Item item;
final Function refresh; final Function refresh;
final List<String>? onlyVariants;
final String? forcePrice;
final String? forceOrigin;
const SupplyPage(this.item, this.refresh, {super.key}); // callback function for receiving a transaction without creating on the API
final Function(SupplyForm)? onCreate;
const SupplyPage(this.item, this.refresh,
{this.onlyVariants,
this.onCreate,
this.forceOrigin,
this.forcePrice,
super.key});
@override @override
State<SupplyPage> createState() => _SupplyPageState(); State<SupplyPage> createState() => _SupplyPageState();
} }
class _SupplyPageState extends State<SupplyPage> { class _SupplyPageState extends State<SupplyPage> {
late List<String> availableVariants;
late String variant; late String variant;
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
String _selectedOrigin = ""; String _selectedOrigin = "";
@ -23,8 +35,13 @@ class _SupplyPageState extends State<SupplyPage> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
availableVariants =
widget.onlyVariants ?? widget.item.variants.keys.toList();
variant = widget.item.variants.keys.first; variant = widget.item.variants.keys.first;
_priceController = TextEditingController(text: "");
_selectedOrigin = widget.forceOrigin ?? "";
_priceController = TextEditingController(text: widget.forcePrice ?? "");
_noteController = TextEditingController(text: ""); _noteController = TextEditingController(text: "");
} }
@ -32,6 +49,23 @@ class _SupplyPageState extends State<SupplyPage> {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
_formKey.currentState!.save(); _formKey.currentState!.save();
if (widget.onCreate != null) {
// todo : create shadow transaction
var t = SupplyForm(
itemID: widget.item.id,
variant: variant,
price: "${_priceController.text}",
origin: _selectedOrigin,
location: _selectedLocation,
note: _noteController.text);
widget.onCreate!(t);
Navigator.of(context).pop();
widget.refresh();
return;
}
API() API()
.supplyItem(widget.item.id, variant, "${_priceController.text}", .supplyItem(widget.item.id, variant, "${_priceController.text}",
_selectedOrigin, _selectedLocation, _noteController.text) _selectedOrigin, _selectedLocation, _noteController.text)
@ -78,10 +112,11 @@ class _SupplyPageState extends State<SupplyPage> {
variant = value!; variant = value!;
}); });
}, },
items: widget.item.variants.entries.map((entry) { items: availableVariants.map((entryKey) {
var entry = widget.item.variants[entryKey]!;
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
value: entry.key, value: entryKey,
child: Text(entry.value.name), child: Text(entry.name),
); );
}).toList(), }).toList(),
onSaved: (value) { onSaved: (value) {
@ -92,6 +127,7 @@ class _SupplyPageState extends State<SupplyPage> {
const SizedBox(height: 16), const SizedBox(height: 16),
// Origin Field with Dropdown and Text Input // Origin Field with Dropdown and Text Input
if (widget.forceOrigin == null)
AutocompletedTextField( AutocompletedTextField(
options: origins, options: origins,
getValue: () => _selectedOrigin, getValue: () => _selectedOrigin,
@ -115,6 +151,7 @@ class _SupplyPageState extends State<SupplyPage> {
const SizedBox(height: 16), const SizedBox(height: 16),
// Price Field // Price Field
if (widget.forcePrice == null)
TextFormField( TextFormField(
decoration: const InputDecoration(labelText: 'Price'), decoration: const InputDecoration(labelText: 'Price'),
keyboardType: TextInputType.number, keyboardType: TextInputType.number,
@ -253,3 +290,37 @@ class AutocompletedTextField extends StatelessWidget {
); );
} }
} }
class SupplyForm {
final String itemID;
final String variant;
final String price;
final String? origin;
final String? location;
final String note;
factory SupplyForm.fromJson(Map<String, dynamic> json) {
return SupplyForm(
itemID: json['item'],
variant: json['variant'],
price: json['price'],
origin: json['origin'],
location: json['location'],
note: json['note'],
);
}
SupplyForm({
required this.itemID,
required this.variant,
required this.price,
required this.origin,
required this.location,
required this.note,
});
Transaction transaction(Map<String, Location> locations) {
return Transaction.inMemory(itemID, variant, price, origin,
location != null ? locations[location!] : null, note);
}
}

View file

@ -222,6 +222,7 @@ class TransactionCard extends StatelessWidget {
), ),
], ],
), ),
if (t.timestamp != 0)
Text( Text(
tsFormat(t.timestamp), tsFormat(t.timestamp),
style: TextStyle(fontSize: 14, color: Colors.grey[700]), style: TextStyle(fontSize: 14, color: Colors.grey[700]),