Language Changes

This commit is contained in:
Nilanjan Chakrabarti
2025-07-09 12:46:51 +05:30
commit 5e72baf1d3
458 changed files with 52259 additions and 0 deletions

View File

@@ -0,0 +1,109 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:kmobile/data/models/user.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
class AccountInfoScreen extends StatefulWidget {
final User user;
const AccountInfoScreen({super.key, required this.user});
@override
State<AccountInfoScreen> createState() => _AccountInfoScreen();
}
class _AccountInfoScreen extends State<AccountInfoScreen> {
@override
Widget build(BuildContext context) {
final user = widget.user;
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Symbols.arrow_back_ios_new),
onPressed: () {
Navigator.pop(context);
},
),
title: const Text(
'Account Info',
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: CircleAvatar(
backgroundColor: Colors.grey[200],
radius: 20,
child: SvgPicture.asset(
'assets/images/avatar_male.svg',
width: 40,
height: 40,
fit: BoxFit.cover,
),
),
),
],
),
body: ListView(
padding: const EdgeInsets.all(16.0),
children: [
InfoRow(title: 'Account Number', value: user.accountNo ?? 'N/A'),
// InfoRow(title: 'Nominee Customer No', value: user.nomineeCustomerNo),
// InfoRow(title: 'SMS Service', value: user.smsService),
// InfoRow(title: 'Missed Call Service', value: user.missedCallService),
InfoRow(title: 'Customer Number', value: user.cifNumber ?? 'N/A'),
InfoRow(title: 'Product Name', value: user.productType ?? 'N/A'),
// InfoRow(title: 'Account Opening Date', value: user.accountOpeningDate ?? 'N/A'),
const InfoRow(title: 'Account Status', value: 'OPEN'),
InfoRow(
title: 'Available Balance',
value: user.availableBalance ?? 'N/A'),
InfoRow(
title: 'Current Balance', value: user.currentBalance ?? 'N/A'),
user.approvedAmount != null
? InfoRow(
title: 'Approved Amount', value: user.approvedAmount ?? 'N/A')
: const SizedBox.shrink(),
],
),
);
}
}
class InfoRow extends StatelessWidget {
final String title;
final String value;
const InfoRow({required this.title, required this.value, super.key});
@override
Widget build(BuildContext context) {
return Container(
width: double.infinity,
margin: const EdgeInsets.symmetric(vertical: 8),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
title,
style: const TextStyle(
fontSize: 15,
fontWeight: FontWeight.w500,
color: Colors.black87,
),
),
const SizedBox(height: 3),
Text(
value,
style: const TextStyle(
fontSize: 16,
color: Colors.black,
),
),
],
),
);
}
}

View File

@@ -0,0 +1,319 @@
import 'package:flutter/material.dart';
import 'package:flutter_svg/svg.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import 'package:shimmer/shimmer.dart';
import 'package:kmobile/data/models/transaction.dart';
import 'package:kmobile/data/repositories/transaction_repository.dart';
import 'package:kmobile/di/injection.dart';
class AccountStatementScreen extends StatefulWidget {
final String accountNo;
const AccountStatementScreen({
super.key,
required this.accountNo,
});
@override
State<AccountStatementScreen> createState() => _AccountStatementScreen();
}
class _AccountStatementScreen extends State<AccountStatementScreen> {
DateTime? fromDate;
DateTime? toDate;
bool _txLoading = true;
List<Transaction> _transactions = [];
final _minAmountController = TextEditingController();
final _maxAmountController = TextEditingController();
@override
void initState() {
super.initState();
_loadTransactions();
}
Future<void> _loadTransactions() async {
setState(() {
_txLoading = true;
_transactions = [];
});
try {
final repo = getIt<TransactionRepository>();
final txs = await repo.fetchTransactions(widget.accountNo);
setState(() => _transactions = txs);
} catch (e) {
if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Failed to load transactions: $e')),
);
} finally {
setState(() => _txLoading = false);
}
}
Future<void> _selectFromDate(BuildContext context) async {
final now = DateTime.now();
final picked = await showDatePicker(
context: context,
initialDate: fromDate ?? now,
firstDate: DateTime(2020),
lastDate: now,
);
if (picked != null) {
setState(() {
fromDate = picked;
toDate = null;
});
}
}
Future<void> _selectToDate(BuildContext context) async {
if (fromDate == null) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Please select From Date first')),
);
return;
}
final now = DateTime.now();
final maxToDate = fromDate!.add(const Duration(days: 31)).isBefore(now)
? fromDate!.add(const Duration(days: 31))
: now;
final picked = await showDatePicker(
context: context,
initialDate: toDate ?? fromDate!,
firstDate: fromDate!,
lastDate: maxToDate,
);
if (picked != null) {
setState(() => toDate = picked);
}
}
String _formatDate(DateTime date) {
return "${date.day.toString().padLeft(2, '0')}-"
"${date.month.toString().padLeft(2, '0')}-"
"${date.year}";
}
@override
void dispose() {
_minAmountController.dispose();
_maxAmountController.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: const Icon(Symbols.arrow_back_ios_new),
onPressed: () => Navigator.pop(context),
),
title: const Text(
'Account Statement',
style: TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [
Padding(
padding: const EdgeInsets.only(right: 10.0),
child: CircleAvatar(
backgroundColor: Colors.grey[200],
radius: 20,
child: SvgPicture.asset(
'assets/images/avatar_male.svg',
width: 40,
height: 40,
fit: BoxFit.cover,
),
),
),
],
),
body: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Text('Filters', style: TextStyle(fontSize: 17)),
const SizedBox(height: 15),
Row(
children: [
Expanded(
child: GestureDetector(
onTap: () => _selectFromDate(context),
child: buildDateBox("From Date", fromDate),
),
),
const SizedBox(width: 10),
Expanded(
child: GestureDetector(
onTap: () => _selectToDate(context),
child: buildDateBox("To Date", toDate),
),
),
],
),
const SizedBox(height: 20),
Row(
children: [
Expanded(
child: TextFormField(
controller: _minAmountController,
decoration: const InputDecoration(
labelText: 'Min Amount',
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
),
keyboardType: TextInputType.number,
textInputAction: TextInputAction.next,
),
),
const SizedBox(width: 8),
Expanded(
child: TextFormField(
controller: _maxAmountController,
decoration: const InputDecoration(
labelText: 'Max Amount',
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
),
keyboardType: TextInputType.number,
textInputAction: TextInputAction.done,
),
),
const SizedBox(width: 8),
SizedBox(
width: 70,
child: ElevatedButton(
onPressed: _loadTransactions,
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).primaryColor,
),
child: const Icon(
Symbols.arrow_forward,
color: Colors.white,
size: 30,
),
),
),
],
),
const SizedBox(height: 35),
if (!_txLoading && _transactions.isNotEmpty)
Padding(
padding: const EdgeInsets.only(bottom: 12.0),
child: Text(
'Showing last 10 transactions.',
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
color: Colors.grey[700],
),
),
),
Expanded(
child: _txLoading
? ListView.builder(
itemCount: 3,
itemBuilder: (_, __) => ListTile(
leading: Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: const CircleAvatar(
radius: 12, backgroundColor: Colors.white),
),
title: Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: Container(
height: 10, width: 100, color: Colors.white),
),
subtitle: Shimmer.fromColors(
baseColor: Colors.grey[300]!,
highlightColor: Colors.grey[100]!,
child: Container(
height: 8, width: 60, color: Colors.white),
),
),
)
: _transactions.isEmpty
? Center(
child: Text(
'No transactions found for this account.',
style: TextStyle(
fontSize: 16,
color: Colors.grey[600],
),
),
)
: ListView.builder(
itemCount: _transactions.length,
itemBuilder: (context, index) {
final txn = _transactions[index];
final isCredit = txn.type == 'CR';
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(txn.date ?? '',
style: const TextStyle(color: Colors.grey)),
const SizedBox(height: 4),
Row(
mainAxisAlignment:
MainAxisAlignment.spaceBetween,
children: [
Expanded(
child: Text(txn.name ?? '',
style: const TextStyle(fontSize: 16)),
),
Text(
"${isCredit ? '+' : '-'}${txn.amount}",
style: TextStyle(
color: isCredit
? Colors.green
: Colors.red,
// fontWeight: FontWeight.bold,
fontSize: 16,
),
),
],
),
const SizedBox(height: 25),
],
);
},
),
),
],
),
),
);
}
Widget buildDateBox(String label, DateTime? date) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 16),
decoration: BoxDecoration(
border: Border.all(color: Colors.grey),
borderRadius: BorderRadius.circular(6),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Text(
date != null ? _formatDate(date) : label,
style: TextStyle(
fontSize: 16,
color: date != null ? Colors.black : Colors.grey,
),
),
const Icon(Icons.arrow_drop_down),
],
),
);
}
}