From 0781aeb4e1b0438142fc602081854e94a2aa4b60 Mon Sep 17 00:00:00 2001 From: Trina Bakshi Date: Fri, 16 May 2025 14:51:05 +0530 Subject: [PATCH] beneficiary management --- .../res/drawable-v21/launch_background.xml | 2 +- .../main/res/drawable/launch_background.xml | 2 +- .../app/src/main/res/values-night/styles.xml | 2 +- android/app/src/main/res/values/styles.xml | 2 +- lib/app.dart | 8 +- lib/config/routes.dart | 2 +- .../screens/account_info_screen.dart | 0 .../screens/account_statement_screen.dart | 0 lib/features/auth/screens/login_screen.dart | 1 + .../screens/add_beneficiary_screen.dart | 299 ++++++++++++++++++ .../screens/manage_beneficiaries_screen.dart | 92 ++++++ .../{auth => card}/screens/Card_screen.dart | 0 .../screens/customer_info_screen.dart | 0 .../dashboard/screens/dashboard_screen.dart | 12 +- .../screens/service_screen.dart | 0 15 files changed, 409 insertions(+), 13 deletions(-) rename lib/features/{auth => accounts}/screens/account_info_screen.dart (100%) rename lib/features/{auth => accounts}/screens/account_statement_screen.dart (100%) create mode 100644 lib/features/beneficiaries/screens/add_beneficiary_screen.dart create mode 100644 lib/features/beneficiaries/screens/manage_beneficiaries_screen.dart rename lib/features/{auth => card}/screens/Card_screen.dart (100%) rename lib/features/{auth => customer_info}/screens/customer_info_screen.dart (100%) rename lib/features/{auth => service}/screens/service_screen.dart (100%) diff --git a/android/app/src/main/res/drawable-v21/launch_background.xml b/android/app/src/main/res/drawable-v21/launch_background.xml index f74085f..6ad68b1 100644 --- a/android/app/src/main/res/drawable-v21/launch_background.xml +++ b/android/app/src/main/res/drawable-v21/launch_background.xml @@ -1,5 +1,5 @@ - + diff --git a/android/app/src/main/res/drawable/launch_background.xml b/android/app/src/main/res/drawable/launch_background.xml index 304732f..3639e29 100644 --- a/android/app/src/main/res/drawable/launch_background.xml +++ b/android/app/src/main/res/drawable/launch_background.xml @@ -1,5 +1,5 @@ - + diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index 06952be..a28bd9a 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -2,7 +2,7 @@ diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index cb1ef88..05c0017 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -2,7 +2,7 @@ diff --git a/lib/app.dart b/lib/app.dart index bc628df..e6702f8 100644 --- a/lib/app.dart +++ b/lib/app.dart @@ -1,7 +1,7 @@ import 'package:flutter/material.dart'; import 'package:flutter/services.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 'api/services/auth_service.dart'; import 'config/themes.dart'; @@ -10,9 +10,9 @@ import 'data/repositories/auth_repository.dart'; import 'di/injection.dart'; import 'features/auth/controllers/auth_cubit.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/service_screen.dart'; +import 'features/service/screens/service_screen.dart'; import 'features/dashboard/screens/dashboard_screen.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 { const _SplashScreen(); diff --git a/lib/config/routes.dart b/lib/config/routes.dart index e7795f7..061e7f9 100644 --- a/lib/config/routes.dart +++ b/lib/config/routes.dart @@ -1,5 +1,5 @@ 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 '../app.dart'; import '../features/auth/screens/login_screen.dart'; diff --git a/lib/features/auth/screens/account_info_screen.dart b/lib/features/accounts/screens/account_info_screen.dart similarity index 100% rename from lib/features/auth/screens/account_info_screen.dart rename to lib/features/accounts/screens/account_info_screen.dart diff --git a/lib/features/auth/screens/account_statement_screen.dart b/lib/features/accounts/screens/account_statement_screen.dart similarity index 100% rename from lib/features/auth/screens/account_statement_screen.dart rename to lib/features/accounts/screens/account_statement_screen.dart diff --git a/lib/features/auth/screens/login_screen.dart b/lib/features/auth/screens/login_screen.dart index ed28161..5a6e9f3 100644 --- a/lib/features/auth/screens/login_screen.dart +++ b/lib/features/auth/screens/login_screen.dart @@ -130,6 +130,7 @@ class LoginScreenState extends State { }, ), ), + textInputAction: TextInputAction.done, obscureText: _obscurePassword, validator: (value) { if (value == null || value.isEmpty) { diff --git a/lib/features/beneficiaries/screens/add_beneficiary_screen.dart b/lib/features/beneficiaries/screens/add_beneficiary_screen.dart new file mode 100644 index 0000000..e97c22e --- /dev/null +++ b/lib/features/beneficiaries/screens/add_beneficiary_screen.dart @@ -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 createState() => _AddBeneficiaryScreen(); +} + +class _AddBeneficiaryScreen extends State{ + final _formKey = GlobalKey(); + + 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( + 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"), + ), + ), + ), + + ], + ), + ), + ), + ); + } + +} \ No newline at end of file diff --git a/lib/features/beneficiaries/screens/manage_beneficiaries_screen.dart b/lib/features/beneficiaries/screens/manage_beneficiaries_screen.dart new file mode 100644 index 0000000..9b0a546 --- /dev/null +++ b/lib/features/beneficiaries/screens/manage_beneficiaries_screen.dart @@ -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 createState() => _ManageBeneficiariesScreen(); +} + +class _ManageBeneficiariesScreen extends State{ + final List> 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), + ), + ), + ); + } + +} \ No newline at end of file diff --git a/lib/features/auth/screens/Card_screen.dart b/lib/features/card/screens/Card_screen.dart similarity index 100% rename from lib/features/auth/screens/Card_screen.dart rename to lib/features/card/screens/Card_screen.dart diff --git a/lib/features/auth/screens/customer_info_screen.dart b/lib/features/customer_info/screens/customer_info_screen.dart similarity index 100% rename from lib/features/auth/screens/customer_info_screen.dart rename to lib/features/customer_info/screens/customer_info_screen.dart diff --git a/lib/features/dashboard/screens/dashboard_screen.dart b/lib/features/dashboard/screens/dashboard_screen.dart index d54e846..2217617 100644 --- a/lib/features/dashboard/screens/dashboard_screen.dart +++ b/lib/features/dashboard/screens/dashboard_screen.dart @@ -1,7 +1,8 @@ import 'package:flutter/material.dart'; -import 'package:kmobile/features/auth/screens/account_info_screen.dart'; -import 'package:kmobile/features/auth/screens/account_statement_screen.dart'; -import 'package:kmobile/features/auth/screens/customer_info_screen.dart'; +import 'package:kmobile/features/accounts/screens/account_info_screen.dart'; +import 'package:kmobile/features/accounts/screens/account_statement_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'; class DashboardScreen extends StatefulWidget { @@ -126,7 +127,10 @@ class _DashboardScreenState extends State { _buildQuickLink(Symbols.checkbook, "Handle \n Cheque", () => print("")), _buildQuickLink(Icons.group, "Manage \n Beneficiary", - () => print("")), + () { + Navigator.push(context, MaterialPageRoute( + builder: (context) => const ManageBeneficiariesScreen())); + }), _buildQuickLink(Symbols.support_agent, "Contact \n Us", () => print("")), ], diff --git a/lib/features/auth/screens/service_screen.dart b/lib/features/service/screens/service_screen.dart similarity index 100% rename from lib/features/auth/screens/service_screen.dart rename to lib/features/service/screens/service_screen.dart