Files
velocity-pay-flutter/lib/screens/groups/batch_item_screen.dart
2026-06-05 20:25:20 +02:00

173 lines
5.5 KiB
Dart

import 'package:flutter/material.dart';
import 'package:qpay/screens/groups/models/group_batch_model.dart';
import 'package:qpay/models/responsive_policy.dart';
import 'package:qpay/widgets/status_chip_widget.dart';
class BatchItemScreen extends StatelessWidget {
final GroupBatchItem item;
const BatchItemScreen({super.key, required this.item});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(item.recipientName ?? 'Batch Item'),
centerTitle: true,
),
body: Center(
child: LayoutBuilder(
builder: (context, constraints) {
final width = constraints.maxWidth > ResponsivePolicy.md
? ResponsivePolicy.md.toDouble()
: constraints.maxWidth;
return SizedBox(
width: width,
child: SingleChildScrollView(
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
_buildHeaderCard(context),
const SizedBox(height: 16),
_buildDetailsCard(),
],
),
),
);
},
),
),
);
}
Widget _buildHeaderCard(BuildContext context) {
return Card(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(color: Colors.black12.withAlpha(30)),
),
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
children: [
CircleAvatar(
radius: 32,
backgroundColor: Theme.of(
context,
).colorScheme.primary.withAlpha(30),
child: Text(
item.recipientName?.isNotEmpty == true
? item.recipientName![0].toUpperCase()
: '?',
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Theme.of(context).colorScheme.primary,
),
),
),
const SizedBox(height: 12),
Text(
item.recipientName ?? '',
style: const TextStyle(fontSize: 20, fontWeight: FontWeight.bold),
),
const SizedBox(height: 4),
Text(
item.recipientPhone ?? '',
style: TextStyle(fontSize: 14, color: Colors.grey.shade600),
),
const SizedBox(height: 12),
StatusChip(status: item.status ?? 'PENDING'),
],
),
),
);
}
Widget _buildDetailsCard() {
return Card(
elevation: 0,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
side: BorderSide(color: Colors.black12.withAlpha(30)),
),
child: Padding(
padding: const EdgeInsets.all(16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Details',
style: TextStyle(fontSize: 15, fontWeight: FontWeight.w600),
),
const SizedBox(height: 12),
_detailRow('Amount', _formatAmount()),
_detailRow('Status', item.status ?? ''),
if (item.transactionId != null)
_detailRow('Transaction ID', item.transactionId!),
if (item.groupBatchId != null)
_detailRow('Batch ID', item.groupBatchId!),
if (item.createdAt != null) _detailRow('Created', item.createdAt!),
if (item.errorMessage != null && item.errorMessage!.isNotEmpty) ...[
const SizedBox(height: 8),
Container(
width: double.infinity,
padding: const EdgeInsets.all(12),
decoration: BoxDecoration(
color: Colors.red.withAlpha(20),
borderRadius: BorderRadius.circular(8),
border: Border.all(color: Colors.red.withAlpha(60)),
),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text(
'Error',
style: TextStyle(
fontWeight: FontWeight.w600,
color: Colors.red,
fontSize: 13,
),
),
const SizedBox(height: 4),
Text(
item.errorMessage!,
style: const TextStyle(fontSize: 13, color: Colors.red),
),
],
),
),
],
],
),
),
);
}
String _formatAmount() {
if (item.amount == null) return '';
return item.amount!.toStringAsFixed(2);
}
Widget _detailRow(String label, String value) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 6),
child: Row(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
width: 120,
child: Text(
label,
style: TextStyle(fontSize: 13, color: Colors.grey.shade600),
),
),
Expanded(child: Text(value, style: const TextStyle(fontSize: 13))),
],
),
);
}
}