206 lines
6.4 KiB
Dart
206 lines
6.4 KiB
Dart
import 'package:cdb_ui/api.dart';
|
|
import 'package:cdb_ui/pages/consume.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:intl/intl.dart';
|
|
import 'supply.dart';
|
|
|
|
class ItemView extends StatefulWidget {
|
|
final Item item;
|
|
|
|
@override
|
|
State<ItemView> createState() => _ItemViewState();
|
|
|
|
const ItemView({super.key, required this.item});
|
|
}
|
|
|
|
class _ItemViewState extends State<ItemView> {
|
|
void refresh() {
|
|
setState(() {});
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return Scaffold(
|
|
appBar: AppBar(
|
|
title: Text(widget.item.name),
|
|
),
|
|
body: Column(children: [
|
|
Padding(
|
|
padding: const EdgeInsets.symmetric(horizontal: 28),
|
|
child: Column(
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.start,
|
|
children: [
|
|
const Align(
|
|
alignment: Alignment.centerLeft,
|
|
child: Placeholder(
|
|
fallbackWidth: 100,
|
|
fallbackHeight: 100,
|
|
),
|
|
), // todo
|
|
const SizedBox(
|
|
width: 16.0,
|
|
),
|
|
Column(
|
|
children: [
|
|
Text(
|
|
widget.item.name,
|
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
Text(widget.item.category),
|
|
],
|
|
)
|
|
],
|
|
),
|
|
const SizedBox(height: 18),
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: widget.item.variants.entries.map((entry) {
|
|
return Column(children: [
|
|
Text(
|
|
entry.value.name,
|
|
style: const TextStyle(fontWeight: FontWeight.bold),
|
|
),
|
|
FutureBuilder(
|
|
future: API().getStat(widget.item.id, entry.key),
|
|
builder: (context, snapshot) {
|
|
if (!snapshot.hasData) {
|
|
return const CircularProgressIndicator();
|
|
}
|
|
|
|
var stat = snapshot.data!;
|
|
|
|
return Column(
|
|
children: [
|
|
Text("Amount: ${stat.amount}"),
|
|
Text(
|
|
"Total Cost: ${stat.total_price.toStringAsFixed(2)}")
|
|
],
|
|
);
|
|
},
|
|
)
|
|
]);
|
|
}).toList()),
|
|
const SizedBox(
|
|
height: 12,
|
|
)
|
|
],
|
|
),
|
|
),
|
|
FutureBuilder(
|
|
future: API().getInventory(widget.item.id),
|
|
builder: (context, snapshot) {
|
|
if (!snapshot.hasData) {
|
|
return const CircularProgressIndicator();
|
|
}
|
|
var data = snapshot.data!;
|
|
|
|
return Expanded(
|
|
child: ListView(
|
|
children:
|
|
data.map((x) => TransactionCard(x, refresh)).toList()));
|
|
},
|
|
)
|
|
]),
|
|
floatingActionButton: FloatingActionButton(
|
|
onPressed: () {
|
|
Navigator.of(context).push(MaterialPageRoute(
|
|
builder: (context) => SupplyPage(widget.item, refresh)));
|
|
},
|
|
child: const Icon(Icons.add)),
|
|
);
|
|
}
|
|
}
|
|
|
|
class TransactionCard extends StatelessWidget {
|
|
final Transaction t;
|
|
final Function refresh;
|
|
|
|
const TransactionCard(this.t, this.refresh, {super.key});
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return InkWell(
|
|
onTap: () {
|
|
Navigator.of(context).push(MaterialPageRoute(
|
|
builder: (context) {
|
|
return ConsumePage(t.uuid, t.item, t.variant, this.refresh);
|
|
},
|
|
));
|
|
},
|
|
child: Card(
|
|
color: t.expired ? Colors.red[100] : Colors.black,
|
|
margin: const EdgeInsets.symmetric(vertical: 8, horizontal: 16),
|
|
shape: RoundedRectangleBorder(
|
|
borderRadius: BorderRadius.circular(10),
|
|
),
|
|
elevation: 4,
|
|
child: Padding(
|
|
padding: const EdgeInsets.all(12),
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.start,
|
|
children: [
|
|
Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
Row(
|
|
children: [
|
|
Text(
|
|
t.item,
|
|
style: const TextStyle(fontSize: 16),
|
|
),
|
|
const SizedBox(
|
|
width: 4,
|
|
),
|
|
Text(
|
|
t.variant,
|
|
style: TextStyle(fontSize: 14, color: Colors.grey[400]),
|
|
),
|
|
],
|
|
),
|
|
Text(
|
|
tsFormat(t.timestamp),
|
|
style: TextStyle(fontSize: 14, color: Colors.grey[700]),
|
|
),
|
|
],
|
|
),
|
|
const SizedBox(
|
|
height: 10,
|
|
),
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.money, size: 18, color: Colors.green),
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
"${t.price.value.toStringAsFixed(2)} ${t.price.currency}",
|
|
style: const TextStyle(
|
|
fontSize: 16, fontWeight: FontWeight.bold),
|
|
),
|
|
],
|
|
),
|
|
if (t.origin != null) ...[
|
|
const SizedBox(height: 8),
|
|
Row(
|
|
children: [
|
|
const Icon(Icons.store, size: 18, color: Colors.blue),
|
|
const SizedBox(width: 6),
|
|
Text(
|
|
t.origin!,
|
|
style: TextStyle(fontSize: 14, color: Colors.grey[700]),
|
|
),
|
|
],
|
|
),
|
|
],
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
String tsFormat(int ts) {
|
|
DateTime dateTime = DateTime.fromMillisecondsSinceEpoch(ts * 1000);
|
|
return DateFormat('yyyy-MM-dd HH:mm:ss').format(dateTime);
|
|
}
|