Transaction details

This commit is contained in:
2025-10-04 20:33:34 +08:00
parent 6c91093198
commit 5dbe7371cb
4 changed files with 222 additions and 24 deletions

View File

@@ -1176,5 +1176,14 @@
"noRecipientsSelected": "No recipients selected",
"selectRecipientsToSendFund": "Select recipients to send the fund to",
"addRecipient": "Add Recipient",
"addMoreRecipients": "Add More Recipients"
"addMoreRecipients": "Add More Recipients",
"transactionDetails": "Transaction Details",
"remarks": "Remarks",
"payer": "Payer",
"payee": "Payee",
"transactionType": "Transaction Type",
"transfer": "Transfer",
"payment": "Payment",
"systemWallet": "System Wallet",
"date": "Date"
}

View File

@@ -1075,5 +1075,6 @@
"deleteRecycledFiles": "删除被回收的文件",
"recycledFilesDeleted": "被回收文件成功删除",
"failedToDeleteRecycledFiles": "删除被回收文件失败",
"upload": "上传"
"upload": "上传",
"systemWallet": "中央统筹"
}

View File

@@ -8,6 +8,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/account.dart';
import 'package:island/models/wallet.dart';
import 'package:island/pods/network.dart';
import 'package:island/widgets/account/account_pfc.dart';
import 'package:island/widgets/account/account_picker.dart';
import 'package:island/widgets/app_scaffold.dart';
import 'package:island/widgets/content/cloud_files.dart';
@@ -659,6 +660,173 @@ Future<SnWalletFund> walletFund(Ref ref, String fundId) async {
return SnWalletFund.fromJson(resp.data);
}
class TransactionDetailSheet extends StatelessWidget {
final SnTransaction transaction;
const TransactionDetailSheet({super.key, required this.transaction});
@override
Widget build(BuildContext context) {
final isIncome =
transaction.payeeWalletId == null ||
transaction.payeeWallet?.accountId == null;
return SheetScaffold(
titleText: 'transactionDetails'.tr(),
heightFactor: 0.75,
child: SingleChildScrollView(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Amount
Text(
'amount'.tr(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.primary,
),
),
const Gap(4),
Text(
'${transaction.amount.toStringAsFixed(2)} ${transaction.currency}',
style: TextStyle(
fontSize: 18,
fontWeight: FontWeight.bold,
color: isIncome ? Colors.green : Colors.red,
),
),
const Gap(16),
// Remarks
if (transaction.remarks != null &&
transaction.remarks!.isNotEmpty) ...[
Text(
'remarks'.tr(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.primary,
),
),
const Gap(4),
Text(
transaction.remarks!,
style: Theme.of(context).textTheme.bodyMedium,
),
const Gap(16),
],
// Date
Text(
'date'.tr(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.primary,
),
),
const Gap(4),
Text(
DateFormat.yMd().add_Hm().format(transaction.createdAt),
style: Theme.of(context).textTheme.bodyMedium,
),
const Gap(16),
// Payer
Text(
'payer'.tr(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.primary,
),
),
const Gap(4),
AccountPfcGestureDetector(
uname: transaction.payerWallet?.account?.name,
child: Row(
spacing: 8,
children: [
if (transaction.payerWallet?.account != null)
ProfilePictureWidget(
file: transaction.payerWallet!.account!.profile.picture,
radius: 12,
),
Text(
transaction.payerWallet?.account?.nick ??
'systemWallet'.tr(),
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
const Gap(16),
// Payee
Text(
'payee'.tr(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.primary,
),
),
const Gap(4),
AccountPfcGestureDetector(
uname: transaction.payeeWallet?.account?.name,
child: Row(
spacing: 8,
children: [
if (transaction.payeeWallet?.account != null)
ProfilePictureWidget(
file: transaction.payeeWallet!.account!.profile.picture,
radius: 12,
),
Text(
transaction.payeeWallet?.account?.nick ??
'systemWallet'.tr(),
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
const Gap(16),
// Transaction Type
Text(
'transactionType'.tr(),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Theme.of(context).colorScheme.primary,
),
),
const Gap(4),
Text(
_getTransactionTypeText(transaction.type),
style: Theme.of(context).textTheme.bodyMedium,
),
],
),
),
);
}
String _getTransactionTypeText(int type) {
// Assuming types: 0: transfer, 1: payment, etc. Adjust based on actual types
switch (type) {
case 0:
return 'transfer'.tr();
case 1:
return 'payment'.tr();
default:
return 'unknown'.tr();
}
}
}
class WalletScreen extends HookConsumerWidget {
const WalletScreen({super.key});
@@ -802,7 +970,19 @@ class WalletScreen extends HookConsumerWidget {
final isIncome =
transaction.payeeWalletId == wallet.value?.id;
return ListTile(
return InkWell(
onTap: () {
showModalBottomSheet(
context: context,
useRootNavigator: true,
isScrollControlled: true,
builder:
(context) => TransactionDetailSheet(
transaction: transaction,
),
);
},
child: ListTile(
key: ValueKey(transaction.id),
leading: Icon(
isIncome
@@ -822,7 +1002,9 @@ class WalletScreen extends HookConsumerWidget {
trailing: Text(
'${isIncome ? '+' : '-'}${transaction.amount.toStringAsFixed(2)} ${transaction.currency}',
style: TextStyle(
color: isIncome ? Colors.green : Colors.red,
color:
isIncome ? Colors.green : Colors.red,
),
),
),
);

View File

@@ -189,7 +189,7 @@ class AccountProfileCard extends HookConsumerWidget {
}
class AccountPfcGestureDetector extends StatelessWidget {
final String uname;
final String? uname;
final Widget child;
const AccountPfcGestureDetector({
super.key,
@@ -202,7 +202,13 @@ class AccountPfcGestureDetector extends StatelessWidget {
return GestureDetector(
child: child,
onTapDown: (details) {
showAccountProfileCard(context, uname, offset: details.localPosition);
if (uname != null) {
showAccountProfileCard(
context,
uname!,
offset: details.localPosition,
);
}
},
);
}