APY integrated and Account UI done

This commit is contained in:
2026-03-19 13:23:34 +05:30
parent 8744e69ef7
commit fc495eca09
10 changed files with 617 additions and 492 deletions

View File

@@ -1,14 +1,15 @@
import 'package:flutter/material.dart'; // Keep if User model is generic
import 'package:kmobile/features/account_opening/screens/fd_screen.dart';
import 'package:kmobile/features/account_opening/screens/loan_screen.dart';
import 'package:kmobile/features/account_opening/screens/rd_screen.dart';
import 'package:kmobile/features/account_opening/screens/td_screen.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
import '../../../l10n/app_localizations.dart';
import 'package:flutter/material.dart';
import 'package:kmobile/data/models/user.dart';
import 'package:kmobile/l10n/app_localizations.dart';
import 'package:kmobile/features/account_opening/screens/create_deposit_screen.dart';
class AccountOpeningScreen extends StatefulWidget {
final List<User> users;
final int selectedIndex;
const AccountOpeningScreen({
super.key,
required this.users,
required this.selectedIndex,
});
@override
@@ -16,153 +17,154 @@ class AccountOpeningScreen extends StatefulWidget {
}
class _AccountOpeningScreenState extends State<AccountOpeningScreen> {
User? _selectedAccount;
List<User> _filteredUsers = [];
final _formKey = GlobalKey<FormState>();
bool _isLoading = false;
@override
void initState() {
super.initState();
_filteredUsers = widget.users
.where((user) => ['SA', 'SB', 'CA', 'CC'].contains(user.accountType))
.toList();
// Pre-fill the account number if possible
if (widget.users.isNotEmpty && widget.selectedIndex < widget.users.length) {
if (_filteredUsers.isNotEmpty) {
if (_filteredUsers.contains(widget.users[widget.selectedIndex])) {
_selectedAccount = widget.users[widget.selectedIndex];
} else {
_selectedAccount = _filteredUsers.first;
}
} else {
_selectedAccount = widget.users[widget.selectedIndex];
}
} else {
if (_filteredUsers.isNotEmpty) {
_selectedAccount = _filteredUsers.first;
}
}
}
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
return Scaffold(
appBar: AppBar(
title: const Text(
"Account Opening",
),
title: Text(l10n.accountOpeningDeposit),
centerTitle: false,
),
body: Stack(
children: [
Padding(
padding: const EdgeInsets.symmetric(vertical: 16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Expanded(
child: AccountOpeningCardTile(
icon: Symbols.savings,
label: "Fixed Deposit (FD)",
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const FdScreen(),
body: SingleChildScrollView(
padding: const EdgeInsets.all(16.0),
child: Form(
key: _formKey,
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
"Select your source account to proceed with opening a new FD, TD, or RD account. Your KYC details will be verified.",
style: Theme.of(context).textTheme.titleMedium,
),
),
),
const SizedBox(height: 16),
Card(
elevation: 2,
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
DropdownButtonFormField<User>(
value: _selectedAccount,
decoration: InputDecoration(
labelText: l10n.accountNumber,
border: const OutlineInputBorder(),
contentPadding: const EdgeInsets.symmetric(
vertical: 20, horizontal: 12),
),
);
},
),
),
Expanded(
child: AccountOpeningCardTile(
icon: Symbols.currency_rupee,
label: "Term Deposit",
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const TermDepositScreen()),
);
},
),
),
Expanded(
child: AccountOpeningCardTile(
icon: Symbols.account_balance,
label: AppLocalizations.of(context).recurringDeposit,
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) =>
const RecurringDepositScreen()),
);
},
),
),
Expanded(
child: AccountOpeningCardTile(
icon: Symbols.credit_card,
label: "Request Loan",
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => const LoanScreen()),
);
},
),
),
],
),
),
IgnorePointer(
child: Center(
child: Opacity(
opacity: 0.07,
child: ClipOval(
child: Image.asset(
'assets/images/logo.png',
width: 200,
height: 200,
items: _filteredUsers.map((user) {
return DropdownMenuItem<User>(
value: user,
child: Text(user.accountNo.toString()),
);
}).toList(),
onChanged: (User? newUser) {
setState(() {
_selectedAccount = newUser;
});
},
validator: (value) {
if (value == null) {
return l10n.accountNumberRequired;
}
return null;
},
),
],
),
),
),
),
),
],
),
);
}
}
const SizedBox(height: 24),
ElevatedButton(
onPressed: _isLoading
? null
: () async {
if (_formKey.currentState!.validate() &&
_selectedAccount != null) {
// Simulating API response
final mockResponse = {
"addressline1": "DATA CENTRE KCCB CIVIL BAZAR D/SHALA DHA",
"addressline2": "RAMSHALA KANGRA",
"cifNo": "30022497139",
"customername": "Mr. RAJAT KUMAR MAHARANA",
"idno": "536652226333 61",
"nationality": "IN",
"pincode": "176047"
};
class AccountOpeningCardTile extends StatelessWidget {
final IconData icon;
final String label;
final VoidCallback onTap;
final bool disable;
const AccountOpeningCardTile({
super.key,
required this.icon,
required this.label,
required this.onTap,
this.disable = false,
});
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
return Card(
margin: const EdgeInsets.symmetric(horizontal: 16.0, vertical: 8.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12.0),
),
elevation: 4,
child: InkWell(
onTap: disable ? null : onTap,
borderRadius: BorderRadius.circular(12.0),
child: Padding(
padding: const EdgeInsets.symmetric(vertical: 24.0, horizontal: 16.0),
child: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
icon,
size: 48,
color: disable
? theme.disabledColor
: theme.colorScheme.primary,
Navigator.push(
context,
MaterialPageRoute(
builder: (context) => CreateDepositScreen(
selectedAccount: _selectedAccount!,
initialData: mockResponse,
),
),
);
}
},
style: ElevatedButton.styleFrom(
backgroundColor:
Theme.of(context).colorScheme.primaryContainer,
foregroundColor:
Theme.of(context).colorScheme.onPrimaryContainer,
minimumSize: const Size(double.infinity, 50),
elevation: 4,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
const SizedBox(height: 12),
Text(
label,
textAlign: TextAlign.center,
style: theme.textTheme.titleLarge?.copyWith(
fontWeight: FontWeight.bold,
color: disable
? theme.disabledColor
: theme.colorScheme.onSurface,
),
),
],
),
child: _isLoading
? const SizedBox(
height: 20,
width: 20,
child: CircularProgressIndicator(
strokeWidth: 2,
),
)
: Text(
l10n.proceedButton,
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
),
),
],
),
),
),