diff --git a/lib/api.dart b/lib/api.dart index 186e46f..e99b783 100644 --- a/lib/api.dart +++ b/lib/api.dart @@ -228,6 +228,10 @@ class API { return FlowInfo(jsonDecode(await getRequest("$instance/flow/$id/info"))); } + Future getFlow(String id) async { + return Flow(jsonDecode(await getRequest("$instance/flow/$id"))); + } + Future> getActiveFlowsOf(String id) async { var res = jsonDecode(await getRequest("$instance/flow/$id/active")) as List; diff --git a/lib/pages/flow.dart b/lib/pages/flow.dart index e42d4cb..344ee39 100644 --- a/lib/pages/flow.dart +++ b/lib/pages/flow.dart @@ -1,5 +1,6 @@ import 'package:cdb_ui/api.dart' as API; import 'package:cdb_ui/pages/expandable_list.dart'; +import 'package:cdb_ui/pages/transaction.dart'; import 'package:flutter/material.dart'; class FlowsPage extends StatefulWidget { @@ -160,38 +161,47 @@ class _FlowsPageState extends State { } } -class FlowInfoPage extends StatelessWidget { +class FlowInfoPage extends StatefulWidget { final API.FlowInfo info; const FlowInfoPage(this.info, {super.key}); + @override + State createState() => _FlowInfoPageState(); +} + +class _FlowInfoPageState extends State { + void refresh() { + setState(() {}); + } + @override Widget build(BuildContext context) { return Scaffold( - appBar: AppBar(title: Text(info.name)), + appBar: AppBar(title: Text(widget.info.name)), body: Column( children: [ // todo : ui improve - if (info.next != null) Text("Next: ${info.next}"), - if (info.depends.isNotEmpty) + if (widget.info.next != null) Text("Next: ${widget.info.next}"), + if (widget.info.depends.isNotEmpty) Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ const Text("Flow can use: "), - ...info.depends.map((x) => Text(x)).toList(), + ...widget.info.depends.map((x) => Text(x)).toList(), ], ), - if (info.produces?.isNotEmpty ?? false) + if (widget.info.produces?.isNotEmpty ?? false) Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ const Text("Flow can produce: "), - ...info.produces!.map((x) => Text(x)).toList(), + ...widget.info.produces!.map((x) => Text(x)).toList(), ], ), const Divider(), FutureBuilder( - future: API.API().getActiveFlowsOf(info.id), + future: API.API().getActiveFlowsOf(widget.info.id), builder: (context, snapshot) { if (!snapshot.hasData) { return const CircularProgressIndicator(); @@ -212,6 +222,96 @@ class FlowInfoPage extends StatelessWidget { ) ], ), + floatingActionButton: FloatingActionButton( + onPressed: () { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) => CreateFlowPage(widget.info, refresh))); + }, + child: const Icon(Icons.add)), + ); + } +} + +class CreateFlowPage extends StatelessWidget { + final API.FlowInfo info; + final Function refresh; + Map> depends = {}; + + CreateFlowPage(this.info, this.refresh, {super.key}); + + void _create(BuildContext context) { + // todo : input handling + API.API().startFlow(info.id, input: []).then((flowID) { + refresh(); + API.API().getFlow(flowID).then((flow) { + Navigator.of(context).pushReplacement( + MaterialPageRoute(builder: (context) => ActiveFlowPage(flow))); + }); + }); + } + + void selectDependItems(BuildContext context, String itemVariant) { + var (item, variant) = API.itemVariant(itemVariant); + + API.API().getInventoryOfVariant(item, variant).then((transactions) { + Navigator.of(context).push(MaterialPageRoute( + builder: (context) { + return TransactionSelectPage(transactions, onSelect: (t) { + depends.putIfAbsent(itemVariant, () { + return []; + }); + depends[itemVariant]!.add(t); + }, exclude: depends[itemVariant] ?? []); + }, + )); + }); + } + + @override + Widget build(BuildContext context) { + // todo : able to add transactions from depends + return Scaffold( + body: null, + ); + } +} + +class TransactionSelectPage extends StatelessWidget { + final Function(API.Transaction) onSelect; + final List selections; + final List? exclude; + + const TransactionSelectPage(this.selections, + {super.key, required this.onSelect, this.exclude}); + + @override + Widget build(BuildContext context) { + var selectionList = []; + + for (var s in selections) { + if (exclude?.any((x) => x.uuid == s.uuid) ?? false) { + continue; + } + + selectionList.add(s); + } + + return Scaffold( + appBar: AppBar( + title: const Text("Select a Transaction"), + ), + body: ListView( + children: selections + .map((x) => TransactionCard( + x, + () {}, + onLongPress: (x) {}, + onTap: (t) { + onSelect(t); + Navigator.of(context).pop(); + }, + )) + .toList()), ); } } diff --git a/lib/pages/stats.dart b/lib/pages/stats.dart index ba7e3ec..23e6189 100644 --- a/lib/pages/stats.dart +++ b/lib/pages/stats.dart @@ -19,7 +19,6 @@ class StatsPage extends StatelessWidget { // todo : add global statistics // todo : demand stat // todo : stat on origin + destination - // todo : add btn for scanning transaction return Scaffold( body: FutureBuilder( diff --git a/lib/pages/transaction.dart b/lib/pages/transaction.dart index 9a2375f..dfd7512 100644 --- a/lib/pages/transaction.dart +++ b/lib/pages/transaction.dart @@ -65,13 +65,21 @@ class TransactionPage extends StatelessWidget { class TransactionCard extends StatelessWidget { final Transaction t; final Function refresh; + final Function(Transaction)? onTap; + final Function(Transaction)? onLongPress; - const TransactionCard(this.t, this.refresh, {super.key}); + const TransactionCard(this.t, this.refresh, + {this.onTap, this.onLongPress, super.key}); @override Widget build(BuildContext context) { return InkWell( onTap: () { + if (onTap != null) { + onTap!(t); + return; + } + Navigator.of(context).push(MaterialPageRoute( builder: (context) { return ConsumePage(t, refresh); @@ -79,6 +87,11 @@ class TransactionCard extends StatelessWidget { )); }, onLongPress: () { + if (onLongPress != null) { + onLongPress!(t); + return; + } + Navigator.of(context).push(MaterialPageRoute( builder: (context) { return TransactionPage(t);