started with transaction view

This commit is contained in:
otsmr 2025-05-09 00:24:26 +02:00
parent f83cc4ace6
commit c1cc9dd3c5
2 changed files with 147 additions and 5 deletions

View file

@ -8,6 +8,7 @@ import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart';
import 'package:twonly/src/providers/connection_provider.dart'; import 'package:twonly/src/providers/connection_provider.dart';
import 'package:twonly/src/utils/misc.dart'; import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/views/components/better_list_title.dart'; import 'package:twonly/src/views/components/better_list_title.dart';
import 'package:twonly/src/views/settings/subscription/transaction_view.dart';
import 'package:twonly/src/views/settings/subscription/voucher_view.dart'; import 'package:twonly/src/views/settings/subscription/voucher_view.dart';
class SubscriptionView extends StatefulWidget { class SubscriptionView extends StatefulWidget {
@ -21,6 +22,7 @@ class _SubscriptionViewState extends State<SubscriptionView> {
bool loaded = false; bool loaded = false;
int ballanceInCents = 0; int ballanceInCents = 0;
DateTime? nextPayment; DateTime? nextPayment;
Response_PlanBallance? ballance;
@override @override
void initState() { void initState() {
@ -29,15 +31,15 @@ class _SubscriptionViewState extends State<SubscriptionView> {
} }
Future initAsync() async { Future initAsync() async {
Response_PlanBallance? ballance = await apiProvider.getPlanBallance(); ballance = await apiProvider.getPlanBallance();
if (ballance != null) { if (ballance != null) {
setState(() { setState(() {
DateTime lastPaymentDateTime = DateTime.fromMillisecondsSinceEpoch( DateTime lastPaymentDateTime = DateTime.fromMillisecondsSinceEpoch(
ballance.lastPaymentDoneUnixTimestamp.toInt() * 1000); ballance!.lastPaymentDoneUnixTimestamp.toInt() * 1000);
nextPayment = lastPaymentDateTime nextPayment = lastPaymentDateTime
.add(Duration(days: ballance.paymentPeriodDays.toInt())); .add(Duration(days: ballance!.paymentPeriodDays.toInt()));
ballanceInCents = ballanceInCents =
ballance.transactions.map((a) => a.depositCents.toInt()).sum; ballance!.transactions.map((a) => a.depositCents.toInt()).sum;
loaded = true; loaded = true;
}); });
return; return;
@ -163,7 +165,14 @@ class _SubscriptionViewState extends State<SubscriptionView> {
subtitle: (loaded) subtitle: (loaded)
? Text("${context.lang.currentBalance}: $formattedBalance") ? Text("${context.lang.currentBalance}: $formattedBalance")
: null, : null,
onTap: () {}, onTap: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return TransactionView(
transactions: ballance!.transactions,
formattedBalance: formattedBalance,
);
}));
},
), ),
if (currentPlan == "Family" || currentPlan == "Pro") if (currentPlan == "Family" || currentPlan == "Pro")
BetterListTile( BetterListTile(

View file

@ -0,0 +1,133 @@
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart';
import 'package:twonly/src/utils/misc.dart';
class TransactionView extends StatefulWidget {
const TransactionView(
{super.key, required this.transactions, required this.formattedBalance});
final List<Response_Transaction> transactions;
final String formattedBalance;
@override
State<TransactionView> createState() => _TransactionViewState();
}
class _TransactionViewState extends State<TransactionView> {
// String typeToText(String type) {
// switch (type) {
// case "VoucherCreated":
// break;
// default:
// }
// }
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(context.lang.transactionHistory),
),
body: ListView(
children: [
Padding(
padding: const EdgeInsets.all(32.0),
child: Center(
child: Container(
decoration: BoxDecoration(
color: context.color.primary,
borderRadius: BorderRadius.circular(15),
),
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 3),
child: Text(
widget.formattedBalance,
style: TextStyle(
fontSize: 32,
fontWeight: FontWeight.bold,
color: isDarkMode(context) ? Colors.black : Colors.white,
),
),
),
),
),
...widget.transactions.map((x) => TransactionCard(transaction: x))
],
),
);
}
}
class TransactionCard extends StatefulWidget {
final Response_Transaction transaction;
const TransactionCard({super.key, required this.transaction});
@override
State<TransactionCard> createState() => _TransactionCardState();
}
class _TransactionCardState extends State<TransactionCard> {
@override
Widget build(BuildContext context) {
final myLocale = Localizations.localeOf(context);
String formattedValue = NumberFormat.currency(
locale: myLocale.toString(),
symbol: '',
decimalDigits: 2,
).format(widget.transaction.depositCents.toInt() / 100);
DateTime timestamp = DateTime.fromMillisecondsSinceEpoch(
widget.transaction.createdAtUnixTimestamp.toInt() * 1000);
return Card(
margin: const EdgeInsets.all(10),
elevation: 5,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
widget.transaction.transactionType,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
),
),
Text(
DateFormat.yMMMMd(myLocale.toString()).format(timestamp),
style: TextStyle(
fontSize: 12,
color: Colors.grey,
),
),
],
),
Text(
formattedValue,
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: (widget.transaction.depositCents < 0)
? Colors.red
: context.color.primary,
),
),
],
),
],
),
),
);
}
}