mirror of
https://github.com/Mercantec-GHC/h4-projekt-gruppe-0-sm.git
synced 2025-04-27 08:24:05 +02:00
receipt/all and receipt/one for frontend
This commit is contained in:
parent
c729175a28
commit
fd288dafee
@ -1,85 +1,16 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/models/cart_item.dart';
|
||||
import 'package:mobile/models/product.dart';
|
||||
import 'package:mobile/controllers/session.dart';
|
||||
import 'package:mobile/models/receipt.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/server/server.dart';
|
||||
|
||||
class ReceiptController extends ChangeNotifier {
|
||||
int nextId = 0;
|
||||
final List<Receipt> receipts = [];
|
||||
class ReceiptController {
|
||||
final Server server;
|
||||
final SessionController sessionController;
|
||||
|
||||
List<Receipt> allReceipts() {
|
||||
return receipts;
|
||||
}
|
||||
ReceiptController({required this.server, required this.sessionController});
|
||||
|
||||
List<Receipt> sortedReceiptsByDate() {
|
||||
List<Receipt> clonedReceipts = [];
|
||||
for (var i = 0; i < receipts.length; i++) {
|
||||
clonedReceipts.add(receipts[i]);
|
||||
}
|
||||
clonedReceipts.sort((a, b) => b.date.compareTo(a.date));
|
||||
return clonedReceipts;
|
||||
}
|
||||
|
||||
Receipt? receiptWithId(int id) {
|
||||
for (var i = 0; i < receipts.length; i++) {
|
||||
if (receipts[i].id == id) {
|
||||
return receipts[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
void createReceipt(List<CartItem> cartItems) {
|
||||
List<ReceiptItem> receiptItems = [];
|
||||
for (var i = 0; i < cartItems.length; i++) {
|
||||
final ReceiptItem receiptItem = ReceiptItem(
|
||||
amount: cartItems[i].amount, product: cartItems[i].product);
|
||||
receiptItems.add(receiptItem);
|
||||
}
|
||||
receipts.add(Receipt(
|
||||
date: DateTime.now(), receiptItems: receiptItems, id: nextId++));
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
||||
|
||||
class Receipt {
|
||||
final int id;
|
||||
final DateTime date;
|
||||
final List<ReceiptItem> receiptItems;
|
||||
|
||||
Receipt({required this.date, required this.receiptItems, required this.id});
|
||||
|
||||
List<ReceiptItem> allReceiptItems() {
|
||||
return receiptItems;
|
||||
}
|
||||
|
||||
ReceiptItem? withProductId(int productId) {
|
||||
for (var i = 0; i < receiptItems.length; i++) {
|
||||
if (receiptItems[i].product.id == productId) {
|
||||
return receiptItems[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int totalPrice() {
|
||||
var result = 0;
|
||||
for (var i = 0; i < receiptItems.length; i++) {
|
||||
result += receiptItems[i].totalPrice();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
String dateFormatted() {
|
||||
return "${date.day}-${date.month}-${date.year}";
|
||||
}
|
||||
}
|
||||
|
||||
class ReceiptItem {
|
||||
final Product product;
|
||||
final int amount;
|
||||
ReceiptItem({required this.product, required this.amount});
|
||||
|
||||
int totalPrice() {
|
||||
return product.priceDkkCent * amount;
|
||||
Future<Result<Receipt, String>> receiptWithId(int id) async {
|
||||
return await sessionController.requestWithSession(
|
||||
(Server server, String token) => server.oneReceipt(token, id));
|
||||
}
|
||||
}
|
||||
|
40
mobile/lib/controllers/receipt_header.dart
Normal file
40
mobile/lib/controllers/receipt_header.dart
Normal file
@ -0,0 +1,40 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/controllers/session.dart';
|
||||
import 'package:mobile/models/receipt.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/server/server.dart';
|
||||
|
||||
class ReceiptHeaderController extends ChangeNotifier {
|
||||
List<ReceiptHeader> _receiptHeaders = [];
|
||||
|
||||
final Server server;
|
||||
|
||||
final SessionController sessionController;
|
||||
|
||||
ReceiptHeaderController(
|
||||
{required this.server, required this.sessionController}) {
|
||||
fetchReceiptsFromServer();
|
||||
}
|
||||
|
||||
Future<void> fetchReceiptsFromServer() async {
|
||||
final res = await sessionController.requestWithSession(
|
||||
(Server server, String token) => server.allReceipts(token));
|
||||
|
||||
switch (res) {
|
||||
case Ok<List<ReceiptHeader>, String>(value: final receiptHeaders):
|
||||
_receiptHeaders = receiptHeaders;
|
||||
case Err<List<ReceiptHeader>, String>():
|
||||
break;
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
List<ReceiptHeader> receiptHeadersSortedByDate() {
|
||||
List<ReceiptHeader> clonedReceiptHeaders = [];
|
||||
for (var i = 0; i < _receiptHeaders.length; i++) {
|
||||
clonedReceiptHeaders.add(_receiptHeaders[i]);
|
||||
}
|
||||
clonedReceiptHeaders.sort((a, b) => b.timestamp.compareTo(a.timestamp));
|
||||
return clonedReceiptHeaders;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:mobile/controllers/receipt_header.dart';
|
||||
import 'package:mobile/controllers/session.dart';
|
||||
import 'package:mobile/pages/dashboard.dart';
|
||||
import 'package:mobile/pages/log_in_page.dart';
|
||||
@ -56,7 +57,12 @@ class MyApp extends StatelessWidget {
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => CartControllerCache(
|
||||
server: server, sessionController: sessionController)),
|
||||
ChangeNotifierProvider(create: (_) => ReceiptController()),
|
||||
Provider(
|
||||
create: (_) => ReceiptController(
|
||||
server: server, sessionController: sessionController)),
|
||||
ChangeNotifierProvider(
|
||||
create: (_) => ReceiptHeaderController(
|
||||
server: server, sessionController: sessionController)),
|
||||
ChangeNotifierProvider(create: (_) => PayingStateController()),
|
||||
ChangeNotifierProvider(create: (_) => AddToCartStateController()),
|
||||
ChangeNotifierProvider(create: (_) => LocationImageController()),
|
||||
|
72
mobile/lib/models/receipt.dart
Normal file
72
mobile/lib/models/receipt.dart
Normal file
@ -0,0 +1,72 @@
|
||||
class Receipt {
|
||||
final int id;
|
||||
final DateTime timestamp;
|
||||
final List<ReceiptItem> receiptItems;
|
||||
|
||||
Receipt(
|
||||
{required this.timestamp, required this.receiptItems, required this.id});
|
||||
|
||||
List<ReceiptItem> allReceiptItems() {
|
||||
return receiptItems;
|
||||
}
|
||||
|
||||
ReceiptItem? withProductId(int productId) {
|
||||
for (var i = 0; i < receiptItems.length; i++) {
|
||||
if (receiptItems[i].productId == productId) {
|
||||
return receiptItems[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
int totalPrice() {
|
||||
var result = 0;
|
||||
for (var i = 0; i < receiptItems.length; i++) {
|
||||
result += receiptItems[i].totalPrice();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Receipt.fromJson(Map<String, dynamic> json)
|
||||
: id = json["receipt_id"],
|
||||
timestamp = DateTime.parse(json["timestamp"]),
|
||||
receiptItems = (json["products"] as List<dynamic>)
|
||||
.map(((receiptItem) => ReceiptItem.fromJson(receiptItem)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
class ReceiptItem {
|
||||
final int productId;
|
||||
final String name;
|
||||
final int priceDkkCent;
|
||||
final int amount;
|
||||
ReceiptItem(
|
||||
{required this.productId,
|
||||
required this.name,
|
||||
required this.priceDkkCent,
|
||||
required this.amount});
|
||||
|
||||
int totalPrice() {
|
||||
return priceDkkCent * amount;
|
||||
}
|
||||
|
||||
ReceiptItem.fromJson(Map<String, dynamic> json)
|
||||
: productId = json["product_id"],
|
||||
name = json["name"],
|
||||
priceDkkCent = json["price_dkk_cent"],
|
||||
amount = json["amount"];
|
||||
}
|
||||
|
||||
class ReceiptHeader {
|
||||
final int id;
|
||||
final DateTime timestamp;
|
||||
final int totalDkkCent;
|
||||
|
||||
ReceiptHeader(
|
||||
{required this.timestamp, required this.id, required this.totalDkkCent});
|
||||
|
||||
ReceiptHeader.fromJson(Map<String, dynamic> json)
|
||||
: id = json["id"],
|
||||
totalDkkCent = json["total_dkk_cent"],
|
||||
timestamp = DateTime.parse(json["timestamp"]);
|
||||
}
|
@ -1,18 +1,14 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/controllers/receipt_header.dart';
|
||||
import 'package:mobile/models/receipt.dart';
|
||||
import 'package:mobile/pages/receipt_page.dart';
|
||||
import 'package:mobile/controllers/receipt.dart';
|
||||
import 'package:mobile/utils/date.dart';
|
||||
import 'package:mobile/utils/price.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ReceiptsListItem extends StatelessWidget {
|
||||
final String dateFormatted;
|
||||
final int totalPrice;
|
||||
final ReceiptPage receiptPage;
|
||||
const ReceiptsListItem(
|
||||
{super.key,
|
||||
required this.dateFormatted,
|
||||
required this.totalPrice,
|
||||
required this.receiptPage});
|
||||
final ReceiptHeader receiptHeader;
|
||||
const ReceiptsListItem({super.key, required this.receiptHeader});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
@ -21,14 +17,19 @@ class ReceiptsListItem extends StatelessWidget {
|
||||
child: InkWell(
|
||||
borderRadius: const BorderRadius.all(Radius.circular(10)),
|
||||
onTap: () {
|
||||
Navigator.of(context)
|
||||
.push(MaterialPageRoute(builder: (context) => receiptPage));
|
||||
Navigator.of(context).push(MaterialPageRoute(
|
||||
builder: (context) => ReceiptPage(
|
||||
receiptId: receiptHeader.id,
|
||||
)));
|
||||
},
|
||||
child: Container(
|
||||
padding: const EdgeInsets.all(20),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [Text(dateFormatted), Text(formatDkkCents(totalPrice))],
|
||||
children: [
|
||||
Text(dateFormatted(receiptHeader.timestamp)),
|
||||
Text(formatDkkCents(receiptHeader.totalDkkCent))
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -41,20 +42,21 @@ class AllReceiptsPage extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
context.read<ReceiptHeaderController>().fetchReceiptsFromServer();
|
||||
return Column(
|
||||
children: [
|
||||
Expanded(child: Consumer<ReceiptController>(
|
||||
builder: (_, receiptRepo, __) {
|
||||
final allReceipts = receiptRepo.sortedReceiptsByDate();
|
||||
Expanded(child: Consumer<ReceiptHeaderController>(
|
||||
builder: (_, receiptHeaderController, __) {
|
||||
final allReceiptHeaders =
|
||||
receiptHeaderController.receiptHeadersSortedByDate();
|
||||
return ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (_, idx) {
|
||||
return ReceiptsListItem(
|
||||
dateFormatted: allReceipts[idx].dateFormatted(),
|
||||
totalPrice: allReceipts[idx].totalPrice(),
|
||||
receiptPage: ReceiptPage(receipt: allReceipts[idx]));
|
||||
receiptHeader: allReceiptHeaders[idx],
|
||||
);
|
||||
},
|
||||
itemCount: allReceipts.length,
|
||||
itemCount: allReceiptHeaders.length,
|
||||
);
|
||||
},
|
||||
)),
|
||||
|
@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:mobile/controllers/routing.dart';
|
||||
import 'package:mobile/controllers/cart.dart';
|
||||
import 'package:mobile/controllers/paying_state.dart';
|
||||
import 'package:mobile/controllers/receipt.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/utils/price.dart';
|
||||
import 'package:mobile/widgets/primary_button.dart';
|
||||
@ -16,7 +15,6 @@ class FinishShoppingPage extends StatelessWidget {
|
||||
Widget build(BuildContext context) {
|
||||
final CartControllerCache cartController =
|
||||
context.read<CartControllerCache>();
|
||||
final ReceiptController receiptRepo = context.read<ReceiptController>();
|
||||
final PayingStateController payingStateRepo =
|
||||
context.watch<PayingStateController>();
|
||||
final cart = cartController.allCartItems();
|
||||
@ -70,8 +68,8 @@ class FinishShoppingPage extends StatelessWidget {
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () =>
|
||||
Navigator.pop(context, 'OK'),
|
||||
child: const Text('OK'),
|
||||
Navigator.pop(context, 'Ok'),
|
||||
child: const Text('Ok'),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -80,7 +78,6 @@ class FinishShoppingPage extends StatelessWidget {
|
||||
payingStateRepo.reset();
|
||||
return;
|
||||
}
|
||||
receiptRepo.createReceipt(cart);
|
||||
payingStateRepo.next();
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
cartController.clearCart();
|
||||
|
@ -1,15 +1,19 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:mobile/controllers/receipt.dart';
|
||||
import 'package:mobile/models/receipt.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/utils/date.dart';
|
||||
import 'package:mobile/utils/price.dart';
|
||||
import 'package:mobile/widgets/receipt_item.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
|
||||
class ReceiptView extends StatelessWidget {
|
||||
final Receipt receipt;
|
||||
const ReceiptView({super.key, required this.receipt});
|
||||
final int receiptId;
|
||||
const ReceiptView({super.key, required this.receiptId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final receiptItems = receipt.allReceiptItems();
|
||||
final receiptController = context.read<ReceiptController>();
|
||||
|
||||
return SafeArea(
|
||||
child: Column(
|
||||
@ -19,34 +23,65 @@ class ReceiptView extends StatelessWidget {
|
||||
Expanded(
|
||||
child: Container(
|
||||
margin: const EdgeInsets.all(20),
|
||||
child: Column(
|
||||
children: [
|
||||
Text(receipt.dateFormatted()),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (_, idx) => ReceiptItemView(
|
||||
pricePerAmount:
|
||||
receiptItems[idx].product.priceDkkCent,
|
||||
name: receiptItems[idx].product.name,
|
||||
amount: receiptItems[idx].amount),
|
||||
itemCount: receiptItems.length),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
"Total:",
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
child: FutureBuilder(
|
||||
future: receiptController.receiptWithId(receiptId),
|
||||
builder: (context, snapshot) {
|
||||
final error = snapshot.error;
|
||||
if (error != null) {
|
||||
throw error;
|
||||
}
|
||||
final receipt = snapshot.data;
|
||||
switch (receipt) {
|
||||
case null:
|
||||
return const CircularProgressIndicator();
|
||||
case Err<Receipt, String>(value: final message):
|
||||
showDialog<String>(
|
||||
context: context,
|
||||
builder: (BuildContext context) => AlertDialog(
|
||||
content: Text(message),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, 'Ok'),
|
||||
child: const Text('Ok'),
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(formatDkkCents(receipt.totalPrice())),
|
||||
],
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
),
|
||||
);
|
||||
return Container();
|
||||
case Ok<Receipt, String>(value: final receipt):
|
||||
return Column(
|
||||
children: [
|
||||
Text(dateFormatted(receipt.timestamp)),
|
||||
Expanded(
|
||||
child: Column(
|
||||
children: [
|
||||
ListView.builder(
|
||||
shrinkWrap: true,
|
||||
itemBuilder: (_, idx) => ReceiptItemView(
|
||||
pricePerAmount: receipt
|
||||
.receiptItems[idx].priceDkkCent,
|
||||
name: receipt.receiptItems[idx].name,
|
||||
amount:
|
||||
receipt.receiptItems[idx].amount),
|
||||
itemCount: receipt.receiptItems.length),
|
||||
Row(
|
||||
mainAxisAlignment:
|
||||
MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
"Total:",
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(formatDkkCents(receipt.totalPrice())),
|
||||
],
|
||||
),
|
||||
],
|
||||
)),
|
||||
],
|
||||
);
|
||||
}
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -56,12 +91,12 @@ class ReceiptView extends StatelessWidget {
|
||||
}
|
||||
|
||||
class ReceiptPage extends StatelessWidget {
|
||||
final Receipt receipt;
|
||||
final int receiptId;
|
||||
|
||||
const ReceiptPage({super.key, required this.receipt});
|
||||
const ReceiptPage({super.key, required this.receiptId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(body: ReceiptView(receipt: receipt));
|
||||
return Scaffold(body: ReceiptView(receiptId: receiptId));
|
||||
}
|
||||
}
|
||||
|
@ -42,8 +42,8 @@ class SaldoSettingsPage extends StatelessWidget {
|
||||
content: Text('Serverfejl: $message'),
|
||||
actions: <Widget>[
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context, 'OK'),
|
||||
child: const Text('OK'),
|
||||
onPressed: () => Navigator.pop(context, 'Ok'),
|
||||
child: const Text('Ok'),
|
||||
),
|
||||
],
|
||||
));
|
||||
|
@ -3,6 +3,7 @@ import 'dart:convert';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:mobile/models/cart_item.dart';
|
||||
import 'package:mobile/models/product.dart';
|
||||
import 'package:mobile/models/receipt.dart';
|
||||
import 'package:mobile/models/user.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/server/server.dart';
|
||||
@ -30,7 +31,7 @@ class BackendServer implements Server {
|
||||
.then((res) => json.decode(res.body));
|
||||
if (res["ok"]) {
|
||||
return Ok((res["products"] as List<dynamic>)
|
||||
.map(((product) => Product.fromJson(product)))
|
||||
.map(((productJson) => Product.fromJson(productJson)))
|
||||
.toList());
|
||||
} else {
|
||||
return Err(res["msg"]);
|
||||
@ -149,4 +150,43 @@ class BackendServer implements Server {
|
||||
return Err(res["msg"]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<ReceiptHeader>, String>> allReceipts(String token) async {
|
||||
final res = await http.get(
|
||||
Uri.parse("$_apiUrl/receipts/all"),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"Session-Token": token
|
||||
},
|
||||
).then((res) => json.decode(res.body));
|
||||
|
||||
if (res["ok"]) {
|
||||
return Ok((res["receipts"] as List<dynamic>)
|
||||
.map(((receiptHeaderJson) =>
|
||||
ReceiptHeader.fromJson(receiptHeaderJson)))
|
||||
.toList());
|
||||
} else {
|
||||
return Err(res["msg"]);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Receipt, String>> oneReceipt(String token, int id) async {
|
||||
final res = await http.get(
|
||||
Uri.parse("$_apiUrl/receipts/one?receipt_id=$id"),
|
||||
headers: {
|
||||
"Content-Type": "application/json",
|
||||
"Accept": "application/json",
|
||||
"Session-Token": token
|
||||
},
|
||||
).then((res) => json.decode(res.body));
|
||||
|
||||
if (res["ok"]) {
|
||||
return Ok((Receipt.fromJson(res["receipt"] as Map<String, dynamic>)));
|
||||
} else {
|
||||
return Err(res["msg"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import 'package:mobile/models/cart_item.dart';
|
||||
import 'package:mobile/models/coordinate.dart';
|
||||
import 'package:mobile/models/product.dart';
|
||||
import 'package:mobile/models/receipt.dart';
|
||||
import 'package:mobile/models/user.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
import 'package:mobile/server/server.dart';
|
||||
@ -132,4 +133,17 @@ class MockServer implements Server {
|
||||
Future<Result<Null, String>> addBalance(String token) async {
|
||||
return const Ok(null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<List<ReceiptHeader>, String>> allReceipts(String token) async {
|
||||
return Ok([
|
||||
ReceiptHeader(timestamp: DateTime.now(), id: 0, totalDkkCent: 1242431)
|
||||
]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<Result<Receipt, String>> oneReceipt(String token, int id) async {
|
||||
return Ok(Receipt(
|
||||
timestamp: DateTime.now(), id: id, receiptItems: <ReceiptItem>[]));
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
import 'package:mobile/models/cart_item.dart';
|
||||
import 'package:mobile/models/product.dart';
|
||||
import 'package:mobile/models/receipt.dart';
|
||||
import 'package:mobile/models/user.dart';
|
||||
import 'package:mobile/results.dart';
|
||||
|
||||
@ -24,4 +25,7 @@ abstract class Server {
|
||||
String token, List<CartItem> cartItems);
|
||||
|
||||
Future<Result<Null, String>> addBalance(String token);
|
||||
|
||||
Future<Result<List<ReceiptHeader>, String>> allReceipts(String token);
|
||||
Future<Result<Receipt, String>> oneReceipt(String token, int id);
|
||||
}
|
||||
|
3
mobile/lib/utils/date.dart
Normal file
3
mobile/lib/utils/date.dart
Normal file
@ -0,0 +1,3 @@
|
||||
String dateFormatted(DateTime date) {
|
||||
return "${date.day}-${date.month}-${date.year} ${date.hour}:${date.minute}";
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user