beneficiary management

This commit is contained in:
Trina Bakshi 2025-05-16 14:51:05 +05:30
parent 33066e6e4f
commit 0781aeb4e1
15 changed files with 409 additions and 13 deletions

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen --> <!-- Modify this file to customize your launch splash screens -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="?android:colorBackground" /> <item android:drawable="?android:colorBackground" />

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen --> <!-- Modify this file to customize your launch splash screens -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" /> <item android:drawable="@android:color/white" />

View File

@ -2,7 +2,7 @@
<resources> <resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on --> <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is on -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screens on the activity. Automatically removed when
the Flutter engine draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>

View File

@ -2,7 +2,7 @@
<resources> <resources>
<!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off --> <!-- Theme applied to the Android Window while the process is starting when the OS's Dark Mode setting is off -->
<style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar"> <style name="LaunchTheme" parent="@android:style/Theme.Light.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when <!-- Show a splash screens on the activity. Automatically removed when
the Flutter engine draws its first frame --> the Flutter engine draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item> <item name="android:windowBackground">@drawable/launch_background</item>
</style> </style>

View File

@ -1,7 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart'; import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:kmobile/features/auth/screens/customer_info_screen.dart'; import 'package:kmobile/features/customer_info/screens/customer_info_screen.dart';
import 'package:kmobile/security/secure_storage.dart'; import 'package:kmobile/security/secure_storage.dart';
import 'api/services/auth_service.dart'; import 'api/services/auth_service.dart';
import 'config/themes.dart'; import 'config/themes.dart';
@ -10,9 +10,9 @@ import 'data/repositories/auth_repository.dart';
import 'di/injection.dart'; import 'di/injection.dart';
import 'features/auth/controllers/auth_cubit.dart'; import 'features/auth/controllers/auth_cubit.dart';
import 'features/auth/controllers/auth_state.dart'; import 'features/auth/controllers/auth_state.dart';
import 'features/auth/screens/Card_screen.dart'; import 'features/card/screens/Card_screen.dart';
import 'features/auth/screens/login_screen.dart'; import 'features/auth/screens/login_screen.dart';
import 'features/auth/screens/service_screen.dart'; import 'features/service/screens/service_screen.dart';
import 'features/dashboard/screens/dashboard_screen.dart'; import 'features/dashboard/screens/dashboard_screen.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart';
@ -75,7 +75,7 @@ class KMobile extends StatelessWidget {
} }
} }
// Simple splash screen component // Simple splash screens component
class _SplashScreen extends StatelessWidget { class _SplashScreen extends StatelessWidget {
const _SplashScreen(); const _SplashScreen();

View File

@ -1,5 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:kmobile/features/auth/screens/customer_info_screen.dart'; import 'package:kmobile/features/customer_info/screens/customer_info_screen.dart';
import 'package:kmobile/features/auth/screens/mpin_screen.dart'; import 'package:kmobile/features/auth/screens/mpin_screen.dart';
import '../app.dart'; import '../app.dart';
import '../features/auth/screens/login_screen.dart'; import '../features/auth/screens/login_screen.dart';

View File

@ -130,6 +130,7 @@ class LoginScreenState extends State<LoginScreen> {
}, },
), ),
), ),
textInputAction: TextInputAction.done,
obscureText: _obscurePassword, obscureText: _obscurePassword,
validator: (value) { validator: (value) {
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {

View File

@ -0,0 +1,299 @@
import 'package:flutter/material.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
class AddBeneficiaryScreen extends StatefulWidget {
const AddBeneficiaryScreen({super.key});
@override
State<AddBeneficiaryScreen> createState() => _AddBeneficiaryScreen();
}
class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen>{
final _formKey = GlobalKey<FormState>();
final TextEditingController accountNumberController = TextEditingController();
final TextEditingController nameController = TextEditingController();
final TextEditingController bankNameController = TextEditingController();
final TextEditingController branchNameController = TextEditingController();
final TextEditingController ifscController = TextEditingController();
final TextEditingController phoneController = TextEditingController();
String accountType = 'Savings';
void _submitForm() {
if (_formKey.currentState!.validate()) {
// Handle successful submission
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
backgroundColor: Colors.grey[900],
behavior: SnackBarBehavior.floating,
margin: const EdgeInsets.all(12),
duration: const Duration(seconds: 5),
content: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
const Expanded(
child: Text(
'Beneficiary added successfully',
style: TextStyle(color: Colors.white),
),
),
TextButton(
onPressed: () {
// Navigate to Payment Screen or do something
},
style: TextButton.styleFrom(
foregroundColor: Colors.blue[200],
),
child: const Text('Pay Now'),
),
IconButton(
icon: const Icon(Icons.close, color: Colors.white),
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
},
),
],
),
),
);
}
}
@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('Add Beneficiary', style: TextStyle(color: Colors.black,
fontWeight: FontWeight.w500),),
centerTitle: false,
actions: const [
Padding(
padding: EdgeInsets.only(right: 10.0),
child: CircleAvatar(
backgroundImage: AssetImage('assets/images/avatar.jpg'), // Replace with your image
radius: 20,
),
),
],
),
body: SafeArea(
child: Form(
key: _formKey,
child: Column(
children: [
Expanded(
child: SingleChildScrollView(
physics: const AlwaysScrollableScrollPhysics(),
child: Padding(
padding: const EdgeInsets.all(10.0),
child: Column(
children: [
TextFormField(
controller: accountNumberController,
decoration: const InputDecoration(
labelText: 'Account Number',
// prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
keyboardType: TextInputType.number,
textInputAction: TextInputAction.next,
validator: (value) {
if (value == null || value.length < 10) {
return "Enter a valid account number";
}
return null;
},
),
const SizedBox(height: 24),
TextFormField(
controller: nameController,
decoration: const InputDecoration(
labelText: 'Name',
// prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
textInputAction: TextInputAction.next,
validator: (value) =>
value == null || value.isEmpty ? "Name is required" : null,
),
const SizedBox(height: 24),
TextFormField(
controller: bankNameController,
decoration: const InputDecoration(
labelText: 'Beneficiary Bank Name',
// prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
textInputAction: TextInputAction.next,
validator: (value) =>
value == null || value.isEmpty ? "Bank name is required" : null,
),
const SizedBox(height: 24),
TextFormField(
controller: branchNameController,
decoration: const InputDecoration(
labelText: 'Branch Name',
// prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
textInputAction: TextInputAction.next,
validator: (value) =>
value == null || value.isEmpty ? "Branch name is required" : null,
),
const SizedBox(height: 24),
Row(
children: [
Expanded(
flex: 2,
child: TextFormField(
controller: ifscController,
decoration: const InputDecoration(
labelText: 'IFSC Code',
// prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
textInputAction: TextInputAction.next,
validator: (value) => value == null || value.length < 5
? "Enter a valid IFSC"
: null,
),
),
const SizedBox(width: 16),
Expanded(
flex: 2,
child: DropdownButtonFormField<String>(
value: accountType,
decoration: const InputDecoration(
labelText: 'Account Type',
// prefixIcon: Icon(Icons.person),
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
items: ['Savings', 'Current']
.map((type) => DropdownMenuItem(
value: type,
child: Text(type),
))
.toList(),
onChanged: (value) {
setState(() {
accountType = value!;
});
},
),
),
],
),
const SizedBox(height: 24),
TextFormField(
controller: phoneController,
keyboardType: TextInputType.phone,
decoration: const InputDecoration(
labelText: 'Phone',
prefixIcon: Icon(Icons.phone),
border: OutlineInputBorder(),
isDense: true,
filled: true,
fillColor: Colors.white,
enabledBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: OutlineInputBorder(
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
textInputAction: TextInputAction.done,
validator: (value) =>
value == null || value.length != 10 ? "Enter a valid phone" : null,
),
const SizedBox(height: 35),
],
),
),
),
),
Padding(
padding: const EdgeInsets.all(16.0),
child: SizedBox(
width: 250,
child: ElevatedButton(
onPressed: _submitForm,
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Colors.blue[900],
foregroundColor: Colors.white,
),
child: const Text("Add"),
),
),
),
],
),
),
),
);
}
}

View File

@ -0,0 +1,92 @@
import 'package:flutter/material.dart';
import 'package:kmobile/features/beneficiaries/screens/add_beneficiary_screen.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart';
class ManageBeneficiariesScreen extends StatefulWidget {
const ManageBeneficiariesScreen({super.key});
@override
State<ManageBeneficiariesScreen> createState() => _ManageBeneficiariesScreen();
}
class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen>{
final List<Map<String, String>> beneficiaries = [
{
'bank': 'State Bank Of India',
'name': 'Trina Bakshi',
},
{
'bank': 'State Bank Of India',
'name': 'Sheetal Rao',
},
{
'bank': 'Punjab National Bank',
'name': 'Manoj Kumar',
},
{
'bank': 'State Bank Of India',
'name': 'Rohit Mehra',
},
];
@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('Beneficiaries', style: TextStyle(color: Colors.black,
fontWeight: FontWeight.w500),),
centerTitle: false,
actions: const [
Padding(
padding: EdgeInsets.only(right: 10.0),
child: CircleAvatar(
backgroundImage: AssetImage('assets/images/avatar.jpg'), // Replace with your image
radius: 20,
),
),
],
),
body: Padding(
padding: const EdgeInsets.all(8.0),
child: ListView.builder(
itemCount: beneficiaries.length,
itemBuilder: (context, index) {
final beneficiary = beneficiaries[index];
return ListTile(
leading: const CircleAvatar(
backgroundColor: Colors.blue,
child: Text('A')),
title: Text(beneficiary['name']!),
subtitle: Text(beneficiary['bank']!),
trailing: IconButton(
icon: const Icon(Symbols.delete_forever, color: Colors.red),
onPressed: () {
// Delete action
},
),
);
},
),
),
floatingActionButton: Padding(
padding: const EdgeInsets.only(bottom: 8.0),
child: FloatingActionButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => const AddBeneficiaryScreen()));
},
backgroundColor: Colors.grey[300],
foregroundColor: Colors.blue[900],
elevation: 5,
child: const Icon(Icons.add),
),
),
);
}
}

View File

@ -1,7 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:kmobile/features/auth/screens/account_info_screen.dart'; import 'package:kmobile/features/accounts/screens/account_info_screen.dart';
import 'package:kmobile/features/auth/screens/account_statement_screen.dart'; import 'package:kmobile/features/accounts/screens/account_statement_screen.dart';
import 'package:kmobile/features/auth/screens/customer_info_screen.dart'; import 'package:kmobile/features/customer_info/screens/customer_info_screen.dart';
import 'package:kmobile/features/beneficiaries/screens/manage_beneficiaries_screen.dart';
import 'package:material_symbols_icons/material_symbols_icons.dart'; import 'package:material_symbols_icons/material_symbols_icons.dart';
class DashboardScreen extends StatefulWidget { class DashboardScreen extends StatefulWidget {
@ -126,7 +127,10 @@ class _DashboardScreenState extends State<DashboardScreen> {
_buildQuickLink(Symbols.checkbook, "Handle \n Cheque", _buildQuickLink(Symbols.checkbook, "Handle \n Cheque",
() => print("")), () => print("")),
_buildQuickLink(Icons.group, "Manage \n Beneficiary", _buildQuickLink(Icons.group, "Manage \n Beneficiary",
() => print("")), () {
Navigator.push(context, MaterialPageRoute(
builder: (context) => const ManageBeneficiariesScreen()));
}),
_buildQuickLink(Symbols.support_agent, "Contact \n Us", _buildQuickLink(Symbols.support_agent, "Contact \n Us",
() => print("")), () => print("")),
], ],