update
This commit is contained in:
parent
7155aaf6b9
commit
e9b0e93f43
6 changed files with 226 additions and 123 deletions
126
lib/main.dart
126
lib/main.dart
|
@ -1,7 +1,9 @@
|
||||||
import 'package:cdb_ui/api.dart';
|
import 'package:cdb_ui/api.dart';
|
||||||
import 'package:cdb_ui/pages/flow.dart';
|
import 'package:cdb_ui/pages/flow.dart';
|
||||||
import 'package:cdb_ui/pages/itemview.dart';
|
import 'package:cdb_ui/pages/items.dart';
|
||||||
|
import 'package:cdb_ui/pages/locations.dart';
|
||||||
import 'package:cdb_ui/pages/setup.dart';
|
import 'package:cdb_ui/pages/setup.dart';
|
||||||
|
import 'package:cdb_ui/pages/stats.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
|
@ -26,111 +28,6 @@ class MyApp extends StatelessWidget {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class StatsPage extends StatelessWidget {
|
|
||||||
const StatsPage({super.key});
|
|
||||||
|
|
||||||
Future<(List<MinItem>, List<Transaction>, GlobalItemStat)>
|
|
||||||
_fetchData() async {
|
|
||||||
return (
|
|
||||||
await API().getItemsUnderMin(),
|
|
||||||
await API().getExpiredItems(),
|
|
||||||
await API().getGlobalItemStat()
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// todo : add global statistics
|
|
||||||
// todo : demand stat
|
|
||||||
// todo : stat on origin + destination
|
|
||||||
|
|
||||||
return Scaffold(
|
|
||||||
body: FutureBuilder(
|
|
||||||
future: _fetchData(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return const CircularProgressIndicator();
|
|
||||||
}
|
|
||||||
|
|
||||||
var data = snapshot.data!;
|
|
||||||
var min = data.$1;
|
|
||||||
var expired = data.$2;
|
|
||||||
var global_stat = data.$3;
|
|
||||||
|
|
||||||
return Column(
|
|
||||||
children: [
|
|
||||||
Card(
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
Text("Items: ${global_stat.item_count}"),
|
|
||||||
Text("Inventory: ${global_stat.total_transactions}"),
|
|
||||||
Text("Price: ${global_stat.total_price} €")
|
|
||||||
],
|
|
||||||
)),
|
|
||||||
|
|
||||||
if (min.isNotEmpty)
|
|
||||||
const ListTile(title: Text("Items under Minimum")),
|
|
||||||
...min.map((item) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text(
|
|
||||||
"Item ${item.itemVariant} under minimum. Needs ${item.need} more."),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
|
|
||||||
if (expired.isNotEmpty)
|
|
||||||
const ListTile(title: Text("Expired Items")),
|
|
||||||
|
|
||||||
// Mapping expired list to widgets
|
|
||||||
...expired.map((item) {
|
|
||||||
return ListTile(
|
|
||||||
title: TransactionCard(item, () {}),
|
|
||||||
);
|
|
||||||
}).toList(),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class LocationsPage extends StatelessWidget {
|
|
||||||
const LocationsPage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
// todo : add locations tree view
|
|
||||||
return const Scaffold();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ItemsPage extends StatelessWidget {
|
|
||||||
const ItemsPage({super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Scaffold(
|
|
||||||
appBar: AppBar(
|
|
||||||
title: const Text("Items"),
|
|
||||||
),
|
|
||||||
body: FutureBuilder(
|
|
||||||
future: API().getItems(),
|
|
||||||
builder: (context, snapshot) {
|
|
||||||
if (!snapshot.hasData) {
|
|
||||||
return const CircularProgressIndicator();
|
|
||||||
}
|
|
||||||
|
|
||||||
var items = snapshot.data!;
|
|
||||||
|
|
||||||
return ListView(
|
|
||||||
children: items.map((x) {
|
|
||||||
return ItemTile(x);
|
|
||||||
}).toList());
|
|
||||||
}),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class MyHomePage extends StatefulWidget {
|
class MyHomePage extends StatefulWidget {
|
||||||
const MyHomePage({super.key});
|
const MyHomePage({super.key});
|
||||||
|
|
||||||
|
@ -173,20 +70,3 @@ class _MyHomePageState extends State<MyHomePage> {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ItemTile extends StatelessWidget {
|
|
||||||
final String item;
|
|
||||||
|
|
||||||
const ItemTile(this.item, {super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ListTile(
|
|
||||||
onTap: () {
|
|
||||||
API().getItem(item).then((itemInfo) => Navigator.push(context,
|
|
||||||
MaterialPageRoute(builder: (context) => ItemView(item: itemInfo))));
|
|
||||||
},
|
|
||||||
title: Text(item),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
47
lib/pages/items.dart
Normal file
47
lib/pages/items.dart
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
import 'package:cdb_ui/api.dart';
|
||||||
|
import 'package:cdb_ui/pages/itemview.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class ItemsPage extends StatelessWidget {
|
||||||
|
const ItemsPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text("Items"),
|
||||||
|
),
|
||||||
|
body: FutureBuilder(
|
||||||
|
future: API().getItems(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
|
var items = snapshot.data!;
|
||||||
|
|
||||||
|
return ListView(
|
||||||
|
children: items.map((x) {
|
||||||
|
return ItemTile(x);
|
||||||
|
}).toList());
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class ItemTile extends StatelessWidget {
|
||||||
|
final String item;
|
||||||
|
|
||||||
|
const ItemTile(this.item, {super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return ListTile(
|
||||||
|
onTap: () {
|
||||||
|
API().getItem(item).then((itemInfo) => Navigator.push(context,
|
||||||
|
MaterialPageRoute(builder: (context) => ItemView(item: itemInfo))));
|
||||||
|
},
|
||||||
|
title: Text(item),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
87
lib/pages/locations.dart
Normal file
87
lib/pages/locations.dart
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
import 'package:cdb_ui/api.dart';
|
||||||
|
import 'package:cdb_ui/pages/itemview.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class LocationsPage extends StatelessWidget {
|
||||||
|
const LocationsPage({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// todo : add locations tree view
|
||||||
|
return const Scaffold();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class LocationView extends StatefulWidget {
|
||||||
|
final Location location;
|
||||||
|
|
||||||
|
const LocationView(this.location, {super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<LocationView> createState() => _LocationViewState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _LocationViewState extends State<LocationView> {
|
||||||
|
bool recursive = true;
|
||||||
|
|
||||||
|
void refresh() {
|
||||||
|
setState(() {});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: Text(widget.location.name),
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Card(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
if (widget.location.parent != null)
|
||||||
|
Text("Inside: ${widget.location.parent!}"),
|
||||||
|
if (widget.location.conditions?.temperature != null)
|
||||||
|
Text(
|
||||||
|
"Temperature: ${widget.location.conditions!.temperature} C°")
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: !recursive,
|
||||||
|
onChanged: (bool? newValue) {
|
||||||
|
setState(() {
|
||||||
|
recursive = !(newValue ?? false);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Expanded(
|
||||||
|
child: Text(
|
||||||
|
'Show only exact matches with location',
|
||||||
|
style: TextStyle(fontSize: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
FutureBuilder(
|
||||||
|
future: API().getTransactionsOfLocation(widget.location.id,
|
||||||
|
recursive: recursive),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = snapshot.data!;
|
||||||
|
|
||||||
|
return ListView(
|
||||||
|
children:
|
||||||
|
data.map((x) => TransactionCard(x, refresh)).toList());
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
72
lib/pages/stats.dart
Normal file
72
lib/pages/stats.dart
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import 'package:cdb_ui/api.dart';
|
||||||
|
import 'package:cdb_ui/pages/itemview.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class StatsPage extends StatelessWidget {
|
||||||
|
const StatsPage({super.key});
|
||||||
|
|
||||||
|
Future<(List<MinItem>, List<Transaction>, GlobalItemStat)>
|
||||||
|
_fetchData() async {
|
||||||
|
return (
|
||||||
|
await API().getItemsUnderMin(),
|
||||||
|
await API().getExpiredItems(),
|
||||||
|
await API().getGlobalItemStat()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
// todo : add global statistics
|
||||||
|
// todo : demand stat
|
||||||
|
// todo : stat on origin + destination
|
||||||
|
// todo : add btn for scanning transaction
|
||||||
|
|
||||||
|
return Scaffold(
|
||||||
|
body: FutureBuilder(
|
||||||
|
future: _fetchData(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (!snapshot.hasData) {
|
||||||
|
return const CircularProgressIndicator();
|
||||||
|
}
|
||||||
|
|
||||||
|
var data = snapshot.data!;
|
||||||
|
var min = data.$1;
|
||||||
|
var expired = data.$2;
|
||||||
|
var globalStat = data.$3;
|
||||||
|
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Card(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text("Items: ${globalStat.item_count}"),
|
||||||
|
Text("Inventory: ${globalStat.total_transactions}"),
|
||||||
|
Text("Price: ${globalStat.total_price} €")
|
||||||
|
],
|
||||||
|
)),
|
||||||
|
|
||||||
|
if (min.isNotEmpty)
|
||||||
|
const ListTile(title: Text("Items under Minimum")),
|
||||||
|
...min.map((item) {
|
||||||
|
return ListTile(
|
||||||
|
title: Text(
|
||||||
|
"Item ${item.itemVariant} under minimum. Needs ${item.need} more."),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
|
||||||
|
if (expired.isNotEmpty)
|
||||||
|
const ListTile(title: Text("Expired Items")),
|
||||||
|
|
||||||
|
// Mapping expired list to widgets
|
||||||
|
...expired.map((item) {
|
||||||
|
return ListTile(
|
||||||
|
title: TransactionCard(item, () {}),
|
||||||
|
);
|
||||||
|
}).toList(),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
16
pubspec.lock
16
pubspec.lock
|
@ -73,6 +73,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.1"
|
version: "4.0.1"
|
||||||
|
equatable:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: equatable
|
||||||
|
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.0.5"
|
||||||
fake_async:
|
fake_async:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
@ -105,6 +113,14 @@ packages:
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.0"
|
version: "1.1.0"
|
||||||
|
fl_chart:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: fl_chart
|
||||||
|
sha256: "94307bef3a324a0d329d3ab77b2f0c6e5ed739185ffc029ed28c0f9b019ea7ef"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.69.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
|
|
@ -35,6 +35,7 @@ dependencies:
|
||||||
qr_bar_code_scanner_dialog: ^0.0.5
|
qr_bar_code_scanner_dialog: ^0.0.5
|
||||||
intl: ^0.18.0
|
intl: ^0.18.0
|
||||||
shared_preferences: ^2.1.0
|
shared_preferences: ^2.1.0
|
||||||
|
fl_chart: ^0.69.0
|
||||||
|
|
||||||
|
|
||||||
# The following adds the Cupertino Icons font to your application.
|
# The following adds the Cupertino Icons font to your application.
|
||||||
|
|
Loading…
Reference in a new issue