This commit is contained in:
JMARyA 2024-09-20 09:18:06 +02:00
parent 7155aaf6b9
commit e9b0e93f43
Signed by: jmarya
GPG key ID: 901B2ADDF27C2263
6 changed files with 226 additions and 123 deletions

View file

@ -1,7 +1,9 @@
import 'package:cdb_ui/api.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/stats.dart';
import 'package:flutter/material.dart';
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 {
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
View 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
View 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}")
],
),
),
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
View 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(),
],
);
},
),
);
}
}

View file

@ -73,6 +73,14 @@ packages:
url: "https://pub.dev"
source: hosted
version: "4.0.1"
equatable:
dependency: transitive
description:
name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
url: "https://pub.dev"
source: hosted
version: "2.0.5"
fake_async:
dependency: transitive
description:
@ -105,6 +113,14 @@ packages:
url: "https://pub.dev"
source: hosted
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:
dependency: "direct main"
description: flutter

View file

@ -35,6 +35,7 @@ dependencies:
qr_bar_code_scanner_dialog: ^0.0.5
intl: ^0.18.0
shared_preferences: ^2.1.0
fl_chart: ^0.69.0
# The following adds the Cupertino Icons font to your application.