Compare commits
No commits in common. "Animation" and "main" have entirely different histories.
@ -1,6 +1,4 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC"/>
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT"/>
|
||||
<application
|
||||
android:label="kmobile"
|
||||
android:name="${applicationName}"
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screens -->
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="?android:colorBackground" />
|
||||
|
||||
|
@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Modify this file to customize your launch splash screens -->
|
||||
<!-- Modify this file to customize your launch splash screen -->
|
||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:drawable="@android:color/white" />
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!-- 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">
|
||||
<!-- Show a splash screens on the activity. Automatically removed when
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
|
@ -2,7 +2,7 @@
|
||||
<resources>
|
||||
<!-- 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">
|
||||
<!-- Show a splash screens on the activity. Automatically removed when
|
||||
<!-- Show a splash screen on the activity. Automatically removed when
|
||||
the Flutter engine draws its first frame -->
|
||||
<item name="android:windowBackground">@drawable/launch_background</item>
|
||||
</style>
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 26 KiB |
Binary file not shown.
Before Width: | Height: | Size: 5.7 KiB |
File diff suppressed because one or more lines are too long
Before Width: | Height: | Size: 26 KiB |
@ -1,3 +0,0 @@
|
||||
description: This file stores settings for Dart & Flutter DevTools.
|
||||
documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states
|
||||
extensions:
|
@ -45,7 +45,5 @@
|
||||
<true/>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>We use Face ID to secure your data.</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
@ -1,3 +0,0 @@
|
||||
arb-dir: lib/l10n
|
||||
template-arb-file: app_en.arb
|
||||
output-localization-file: app_localizations.dart
|
@ -13,7 +13,7 @@ class AuthInterceptor extends Interceptor {
|
||||
RequestInterceptorHandler handler,
|
||||
) async {
|
||||
// Skip auth header for login and refresh endpoints
|
||||
if (options.path.contains('/login') ||
|
||||
if (options.path.contains('/auth/login') ||
|
||||
options.path.contains('/auth/refresh')) {
|
||||
return handler.next(options);
|
||||
}
|
||||
|
@ -1,26 +1,20 @@
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import '../../app.dart';
|
||||
import '../../features/auth/models/auth_token.dart';
|
||||
import '../../features/auth/models/auth_credentials.dart';
|
||||
import '../../data/models/user.dart';
|
||||
import '../../core/errors/exceptions.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
|
||||
import '../../features/dashboard/screens/dashboard_screen.dart';
|
||||
|
||||
class AuthService {
|
||||
final Dio _dio;
|
||||
|
||||
AuthService(this._dio);
|
||||
|
||||
Future<AuthToken> login(AuthCredentials credentials) async {
|
||||
try {
|
||||
final response = await _dio.post(
|
||||
'/login',
|
||||
'/auth/login',
|
||||
data: credentials.toJson(),
|
||||
);
|
||||
|
||||
@ -30,9 +24,6 @@ class AuthService {
|
||||
throw AuthException('Login failed');
|
||||
}
|
||||
} on DioException catch (e) {
|
||||
if (kDebugMode) {
|
||||
print(e.toString());
|
||||
}
|
||||
if (e.response?.statusCode == 401) {
|
||||
throw AuthException('Invalid credentials');
|
||||
}
|
||||
|
102
lib/app.dart
102
lib/app.dart
@ -1,17 +1,13 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:kmobile/features/customer_info/screens/customer_info_screen.dart';
|
||||
import 'config/themes.dart';
|
||||
import 'config/routes.dart';
|
||||
import 'di/injection.dart';
|
||||
import 'features/auth/controllers/auth_cubit.dart';
|
||||
import 'features/auth/controllers/auth_state.dart';
|
||||
import 'features/card/screens/card_management_screen.dart';
|
||||
import 'features/auth/screens/login_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';
|
||||
|
||||
class KMobile extends StatelessWidget {
|
||||
const KMobile({super.key});
|
||||
@ -56,12 +52,8 @@ class KMobile extends StatelessWidget {
|
||||
return const _SplashScreen();
|
||||
}
|
||||
|
||||
if(state is ShowBiometricPermission){
|
||||
return const BiometricPermissionScreen();
|
||||
}
|
||||
|
||||
if (state is Authenticated) {
|
||||
return const NavigationScaffold();
|
||||
return const DashboardScreen();
|
||||
}
|
||||
|
||||
return const LoginScreen();
|
||||
@ -72,7 +64,7 @@ class KMobile extends StatelessWidget {
|
||||
}
|
||||
}
|
||||
|
||||
// Simple splash screens component
|
||||
// Simple splash screen component
|
||||
class _SplashScreen extends StatelessWidget {
|
||||
const _SplashScreen();
|
||||
|
||||
@ -112,93 +104,3 @@ class _SplashScreen extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class NavigationScaffold extends StatefulWidget {
|
||||
const NavigationScaffold({super.key});
|
||||
|
||||
@override
|
||||
State<NavigationScaffold> createState() => _NavigationScaffoldState();
|
||||
}
|
||||
|
||||
class _NavigationScaffoldState extends State<NavigationScaffold> {
|
||||
final PageController _pageController = PageController();
|
||||
int _selectedIndex = 0;
|
||||
|
||||
final List<Widget> _pages = [
|
||||
DashboardScreen(),
|
||||
CardManagementScreen(),
|
||||
ServiceScreen(),
|
||||
CustomerInfoScreen()
|
||||
];
|
||||
|
||||
void _onItemTapped(int index) {
|
||||
setState(() {
|
||||
_selectedIndex = index;
|
||||
});
|
||||
_pageController.jumpToPage(index);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: PageView(
|
||||
controller: _pageController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: _pages,
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: _selectedIndex,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
items: const [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.home_filled),
|
||||
label: 'Home',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Symbols.credit_card),
|
||||
label: 'Card',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Symbols.concierge),
|
||||
label: 'Services',
|
||||
),
|
||||
],
|
||||
onTap: _onItemTapped,
|
||||
backgroundColor: const Color(0xFFE0F7FA), // Light blue background
|
||||
selectedItemColor: Colors.blue[800],
|
||||
unselectedItemColor: Colors.black54,
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class BiometricPermissionScreen extends StatelessWidget {
|
||||
const BiometricPermissionScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final cubit = context.read<AuthCubit>();
|
||||
|
||||
return Scaffold(
|
||||
body: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text('Would you like to enable biometric authentication?'),
|
||||
ElevatedButton(
|
||||
onPressed: () => cubit.handleBiometricChoice(true),
|
||||
child: const Text('Yes'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () => cubit.handleBiometricChoice(false),
|
||||
child: const Text('No, thanks'),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
@ -1,7 +1,4 @@
|
||||
import 'package:flutter/material.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';
|
||||
// import '../features/auth/screens/forgot_password_screen.dart';
|
||||
// import '../features/auth/screens/register_screen.dart';
|
||||
@ -18,24 +15,18 @@ class AppRoutes {
|
||||
// Route names
|
||||
static const String splash = '/';
|
||||
static const String login = '/login';
|
||||
static const String mPin = '/mPin';
|
||||
static const String register = '/register';
|
||||
static const String forgotPassword = '/forgot-password';
|
||||
static const String navigationScaffold = '/navigation-scaffold';
|
||||
static const String dashboard = '/dashboard';
|
||||
static const String accounts = '/accounts';
|
||||
static const String transactions = '/transactions';
|
||||
static const String payments = '/payments';
|
||||
static const String customer_info = '/customer-info';
|
||||
|
||||
// Route generator
|
||||
static Route<dynamic> generateRoute(RouteSettings settings) {
|
||||
switch (settings.name) {
|
||||
case login:
|
||||
return MaterialPageRoute(builder: (_) => const LoginScreen());
|
||||
|
||||
case mPin:
|
||||
return MaterialPageRoute(builder: (_) => const MPinScreen());
|
||||
|
||||
case register:
|
||||
// Placeholder - create the RegisterScreen class and uncomment
|
||||
@ -46,15 +37,9 @@ class AppRoutes {
|
||||
// Placeholder - create the ForgotPasswordScreen class and uncomment
|
||||
// return MaterialPageRoute(builder: (_) => const ForgotPasswordScreen());
|
||||
return _errorRoute();
|
||||
|
||||
case navigationScaffold:
|
||||
return MaterialPageRoute(builder: (_) => const NavigationScaffold());
|
||||
|
||||
case dashboard:
|
||||
return MaterialPageRoute(builder: (_) => const DashboardScreen());
|
||||
|
||||
case customer_info:
|
||||
return MaterialPageRoute(builder: (_) => const CustomerInfoScreen());
|
||||
|
||||
case accounts:
|
||||
// Placeholder - create the AccountsScreen class and uncomment
|
||||
|
@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||
class AppThemes {
|
||||
// Private constructor to prevent instantiation
|
||||
AppThemes._();
|
||||
|
||||
|
||||
// Light theme colors
|
||||
static const Color _primaryColorLight = Color(0xFF1E88E5); // Blue 600
|
||||
static const Color _secondaryColorLight = Color(0xFF26A69A); // Teal 400
|
||||
@ -22,61 +22,51 @@ class AppThemes {
|
||||
fontSize: 96,
|
||||
fontWeight: FontWeight.w300,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
displayMedium: TextStyle(
|
||||
fontSize: 60,
|
||||
fontWeight: FontWeight.w300,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
displaySmall: TextStyle(
|
||||
fontSize: 48,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
headlineMedium: TextStyle(
|
||||
fontSize: 34,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
headlineSmall: TextStyle(
|
||||
fontSize: 24,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
titleLarge: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
bodyLarge: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
bodyMedium: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
bodySmall: TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Color(0xFF757575),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
labelLarge: TextStyle(
|
||||
fontSize: 14,
|
||||
fontWeight: FontWeight.w500,
|
||||
color: Color(0xFF212121),
|
||||
fontFamily: 'Rubik',
|
||||
),
|
||||
);
|
||||
|
||||
@ -96,7 +86,6 @@ class AppThemes {
|
||||
// Light theme
|
||||
static final ThemeData lightTheme = ThemeData(
|
||||
useMaterial3: true,
|
||||
fontFamily: 'Rubik',
|
||||
colorScheme: const ColorScheme.light(
|
||||
primary: _primaryColorLight,
|
||||
secondary: _secondaryColorLight,
|
||||
@ -178,7 +167,6 @@ class AppThemes {
|
||||
|
||||
// Dark theme
|
||||
static final ThemeData darkTheme = ThemeData(
|
||||
fontFamily: 'Rubik',
|
||||
useMaterial3: true,
|
||||
colorScheme: const ColorScheme.dark(
|
||||
primary: _primaryColorDark,
|
||||
|
@ -35,7 +35,7 @@ Future<void> setupDependencies() async {
|
||||
Dio _createDioClient() {
|
||||
final dio = Dio(
|
||||
BaseOptions(
|
||||
baseUrl: 'http://localhost:3000',
|
||||
baseUrl: 'https://api.yourbank.com/v1',
|
||||
connectTimeout: const Duration(seconds: 5),
|
||||
receiveTimeout: const Duration(seconds: 3),
|
||||
headers: {
|
||||
|
@ -1,76 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class AccountInfoScreen extends StatefulWidget {
|
||||
const AccountInfoScreen({super.key});
|
||||
|
||||
@override
|
||||
State<AccountInfoScreen> createState() => _AccountInfoScreen();
|
||||
}
|
||||
|
||||
class _AccountInfoScreen extends State<AccountInfoScreen>{
|
||||
@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 Info', 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: ListView(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
children: const [
|
||||
InfoRow(title: 'Account Number', value: '700127638009871'),
|
||||
InfoRow(title: 'Nominee Customer No', value: '700127638009871'),
|
||||
InfoRow(title: 'SMS Service', value: 'Active'),
|
||||
InfoRow(title: 'Missed Call Service', value: 'Active'),
|
||||
InfoRow(title: 'Customer Number', value: '9000875272000212'),
|
||||
InfoRow(title: 'Product Name', value: 'SAVINGS-PERSONAL'),
|
||||
InfoRow(title: 'Account Opening Date', value: '12-09-2012'),
|
||||
InfoRow(title: 'Account Status', value: 'OPEN'),
|
||||
InfoRow(title: 'Available Balance', value: '12,000 CR'),
|
||||
InfoRow(title: 'Interest Rate', value: '12.00'),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
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 Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 6.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(title,
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.bold, fontSize: 14)),
|
||||
const SizedBox(height: 4),
|
||||
Text(value, style: const TextStyle(fontSize: 14)),
|
||||
const SizedBox(height: 10),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,220 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class AccountStatementScreen extends StatefulWidget {
|
||||
const AccountStatementScreen({super.key});
|
||||
|
||||
@override
|
||||
State<AccountStatementScreen> createState() => _AccountStatementScreen();
|
||||
}
|
||||
|
||||
class _AccountStatementScreen extends State<AccountStatementScreen>{
|
||||
DateTime? fromDate;
|
||||
DateTime? toDate;
|
||||
final _amountRangeController = TextEditingController(text: "");
|
||||
final transactions = [
|
||||
{"desc": "Transfer From ICICI Bank subsidy", "amount": "+₹133.98", "type": "Cr", "time": "21-02-2024 13:09:30"},
|
||||
{"desc": "Mobile recharge", "amount": "-₹299.00", "type": "Dr", "time": "21-02-2024 13:09:30"},
|
||||
{"desc": "NEFT received from Jaya Saha", "amount": "+₹987.80", "type": "Cr", "time": "21-02-2024 13:09:30"},
|
||||
{"desc": "Transfer From ICICI Bank subsidy", "amount": "+₹100.00", "type": "Cr", "time": "21-02-2024 13:09:30"},
|
||||
{"desc": "Transfer From ICICI Bank subsidy", "amount": "-₹100.00", "type": "Dr", "time": "21-02-2024 13:09:30"},
|
||||
{"desc": "Transfer From ICICI Bank subsidy", "amount": "+₹100.00", "type": "Cr", "time": "21-02-2024 13:09:30"},
|
||||
{"desc": "Transfer From ICICI Bank subsidy", "amount": "+₹100.00", "type": "Cr", "time": "21-02-2024 13:09:30"},
|
||||
];
|
||||
|
||||
void _selectDate({required bool isFromDate}) async {
|
||||
final DateTime initial = isFromDate ? fromDate ?? DateTime.now() : toDate ?? fromDate ?? DateTime.now();
|
||||
|
||||
final DateTime? picked = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: initial,
|
||||
firstDate: DateTime(2023),
|
||||
lastDate: DateTime(2030),
|
||||
);
|
||||
|
||||
if (picked != null) {
|
||||
setState(() {
|
||||
if (isFromDate) {
|
||||
fromDate = picked;
|
||||
if (toDate != null && toDate!.isBefore(fromDate!)) {
|
||||
toDate = null; // reset invalid toDate
|
||||
}
|
||||
} else {
|
||||
if (fromDate != null && picked.isBefore(fromDate!)) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(const SnackBar(
|
||||
content: Text("To Date cannot be before From Date"),
|
||||
));
|
||||
} else {
|
||||
toDate = picked;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
String _formatDate(DateTime date) {
|
||||
return "${date.day.toString().padLeft(2, '0')}-"
|
||||
"${date.month.toString().padLeft(2, '0')}-"
|
||||
"${date.year}";
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_amountRangeController.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: 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(12.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('Filters', style: TextStyle(fontSize: 17),),
|
||||
const SizedBox(height: 15,),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildFromDateSelector()),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(child: _buildToDateSelector()),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildFilterBox(""),
|
||||
const SizedBox(height: 35),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
itemCount: transactions.length,
|
||||
itemBuilder: (context, index) {
|
||||
final txn = transactions[index];
|
||||
return _buildTransactionTile(txn);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFromDateSelector() {
|
||||
return GestureDetector(
|
||||
onTap: () => _selectDate(isFromDate: true),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
fromDate != null ? _formatDate(fromDate!) : "From Date",
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
),
|
||||
const Icon(Icons.arrow_drop_down),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildToDateSelector() {
|
||||
return GestureDetector(
|
||||
onTap: () => _selectDate(isFromDate: false),
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 14),
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(color: Colors.grey),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
toDate != null ? _formatDate(toDate!) : "To Date",
|
||||
style: const TextStyle(fontSize: 16),
|
||||
),
|
||||
),
|
||||
const Icon(Icons.arrow_drop_down),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildFilterBox(String text) {
|
||||
return TextFormField(
|
||||
controller: _amountRangeController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Amount Range',
|
||||
// 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.isEmpty) {
|
||||
return 'Please enter amount range';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildTransactionTile(Map<String, String> txn) {
|
||||
final isCredit = txn['type'] == "Cr";
|
||||
final amountColor = isCredit ? Colors.green : Colors.red;
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(txn['time']!, style: const TextStyle(color: Colors.grey)),
|
||||
const SizedBox(height: 4),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Expanded(child: Text(txn['desc']!, style: const TextStyle(fontSize: 16))),
|
||||
Text(
|
||||
"${txn['amount']} ${txn['type']}",
|
||||
style: TextStyle(color: amountColor, fontWeight: FontWeight.bold),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -1,10 +1,4 @@
|
||||
import 'package:bloc/bloc.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import '../../../app.dart';
|
||||
import '../../../data/repositories/auth_repository.dart';
|
||||
import 'auth_state.dart';
|
||||
|
||||
@ -53,60 +47,4 @@ class AuthCubit extends Cubit<AuthState> {
|
||||
emit(AuthError(e.toString()));
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> checkFirstLaunch() async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
final isFirstLaunch = prefs.getBool('isFirstLaunch') ?? true;
|
||||
|
||||
if (isFirstLaunch) {
|
||||
emit(ShowBiometricPermission());
|
||||
} else {
|
||||
// Continue to authentication logic (e.g., check token)
|
||||
emit(AuthLoading()); // or Unauthenticated/Authenticated
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> handleBiometricChoice(bool enabled) async {
|
||||
SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
await prefs.setBool('biometric_opt_in', enabled);
|
||||
await prefs.setBool('isFirstLaunch', false);
|
||||
|
||||
// Then continue to auth logic or home
|
||||
if (enabled) {
|
||||
authenticateBiometric(); // implement biometric logic
|
||||
} else {
|
||||
emit(Unauthenticated());
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> authenticateBiometric() async {
|
||||
final LocalAuthentication auth = LocalAuthentication();
|
||||
|
||||
try {
|
||||
final isAvailable = await auth.canCheckBiometrics;
|
||||
final isDeviceSupported = await auth.isDeviceSupported();
|
||||
|
||||
if (isAvailable && isDeviceSupported) {
|
||||
final authenticated = await auth.authenticate(
|
||||
localizedReason: 'Touch the fingerprint sensor',
|
||||
options: const AuthenticationOptions(
|
||||
biometricOnly: true,
|
||||
stickyAuth: true,
|
||||
),
|
||||
);
|
||||
|
||||
if (authenticated) {
|
||||
// Continue to normal auth logic (e.g., auto login)
|
||||
emit(AuthLoading());
|
||||
await checkAuthStatus(); // Your existing method to verify token/session
|
||||
} else {
|
||||
emit(Unauthenticated());
|
||||
}
|
||||
} else {
|
||||
emit(Unauthenticated());
|
||||
}
|
||||
} catch (e) {
|
||||
emit(Unauthenticated());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,8 +10,6 @@ class AuthInitial extends AuthState {}
|
||||
|
||||
class AuthLoading extends AuthState {}
|
||||
|
||||
class ShowBiometricPermission extends AuthState {}
|
||||
|
||||
class Authenticated extends AuthState {
|
||||
final User user;
|
||||
|
||||
|
@ -5,7 +5,7 @@ class AuthCredentials {
|
||||
AuthCredentials({required this.username, required this.password});
|
||||
|
||||
Map<String, dynamic> toJson() => {
|
||||
'customer_no': username,
|
||||
'username': username,
|
||||
'password': password,
|
||||
};
|
||||
}
|
||||
|
@ -1,8 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:kmobile/features/auth/screens/mpin_screen.dart';
|
||||
import '../../../app.dart';
|
||||
import '../controllers/auth_cubit.dart';
|
||||
import '../controllers/auth_state.dart';
|
||||
import '../../dashboard/screens/dashboard_screen.dart';
|
||||
@ -16,39 +13,35 @@ class LoginScreen extends StatefulWidget {
|
||||
|
||||
class LoginScreenState extends State<LoginScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _customerNumberController = TextEditingController();
|
||||
final _usernameController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
bool _obscurePassword = true;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_customerNumberController.dispose();
|
||||
_usernameController.dispose();
|
||||
_passwordController.dispose();
|
||||
super.dispose();
|
||||
}
|
||||
|
||||
void _submitForm() {
|
||||
// if (_formKey.currentState!.validate()) {
|
||||
// context.read<AuthCubit>().login(
|
||||
// _customerNumberController.text.trim(),
|
||||
// _passwordController.text,
|
||||
// );
|
||||
// }
|
||||
|
||||
Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(builder: (context) => const MPinScreen()),
|
||||
);
|
||||
if (_formKey.currentState!.validate()) {
|
||||
context.read<AuthCubit>().login(
|
||||
_usernameController.text.trim(),
|
||||
_passwordController.text,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
// appBar: AppBar(title: const Text('Login')),
|
||||
appBar: AppBar(title: const Text('Login')),
|
||||
body: BlocConsumer<AuthCubit, AuthState>(
|
||||
listener: (context, state) {
|
||||
if (state is Authenticated) {
|
||||
Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(builder: (context) => const NavigationScaffold()),
|
||||
MaterialPageRoute(builder: (context) => const DashboardScreen()),
|
||||
);
|
||||
} else if (state is AuthError) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
@ -63,35 +56,19 @@ class LoginScreenState extends State<LoginScreen> {
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
// crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Bank logo or app branding
|
||||
SvgPicture.asset('assets/images/kccb_logo.svg', width: 100, height: 100,),
|
||||
const SizedBox(height: 16),
|
||||
// Title
|
||||
const Text(
|
||||
'KCCB',
|
||||
style: TextStyle(fontSize: 28, fontWeight: FontWeight.bold, color: Colors.blue),
|
||||
),
|
||||
const FlutterLogo(size: 80),
|
||||
const SizedBox(height: 48),
|
||||
|
||||
TextFormField(
|
||||
controller: _customerNumberController,
|
||||
controller: _usernameController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Customer Number',
|
||||
// prefixIcon: Icon(Icons.person),
|
||||
labelText: 'Username',
|
||||
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.isEmpty) {
|
||||
@ -106,17 +83,8 @@ class LoginScreenState extends State<LoginScreen> {
|
||||
controller: _passwordController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Password',
|
||||
// prefixIcon: const Icon(Icons.lock),
|
||||
prefixIcon: const Icon(Icons.lock),
|
||||
border: const OutlineInputBorder(),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.black),
|
||||
),
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.black, width: 2),
|
||||
),
|
||||
suffixIcon: IconButton(
|
||||
icon: Icon(
|
||||
_obscurePassword
|
||||
@ -130,7 +98,6 @@ class LoginScreenState extends State<LoginScreen> {
|
||||
},
|
||||
),
|
||||
),
|
||||
textInputAction: TextInputAction.done,
|
||||
obscureText: _obscurePassword,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
@ -140,72 +107,43 @@ class LoginScreenState extends State<LoginScreen> {
|
||||
},
|
||||
),
|
||||
|
||||
// Align(
|
||||
// alignment: Alignment.centerRight,
|
||||
// child: TextButton(
|
||||
// onPressed: () {
|
||||
// // Navigate to forgot password screen
|
||||
// },
|
||||
// child: const Text('Forgot Password?'),
|
||||
// ),
|
||||
// ),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
// Navigate to forgot password screen
|
||||
},
|
||||
child: const Text('Forgot Password?'),
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
SizedBox(
|
||||
width: 250,
|
||||
child: ElevatedButton(
|
||||
onPressed: state is AuthLoading ? null : _submitForm,
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const StadiumBorder(),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Colors.blueAccent,
|
||||
side: const BorderSide(color: Colors.black, width: 1),
|
||||
elevation: 0
|
||||
ElevatedButton(
|
||||
onPressed: state is AuthLoading ? null : _submitForm,
|
||||
style: ElevatedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
),
|
||||
child: state is AuthLoading
|
||||
? const CircularProgressIndicator()
|
||||
: const Text('LOGIN', style: TextStyle(fontSize: 16)),
|
||||
),
|
||||
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Registration option
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Text("Don't have an account?"),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// Navigate to registration screen
|
||||
},
|
||||
child: const Text('Register'),
|
||||
),
|
||||
child: state is AuthLoading
|
||||
? const CircularProgressIndicator()
|
||||
: const Text('Login', style: TextStyle(fontSize: 16),),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 15),
|
||||
|
||||
// OR Divider
|
||||
const Padding(
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(child: Divider()),
|
||||
Padding(
|
||||
padding: EdgeInsets.symmetric(horizontal: 8),
|
||||
child: Text('OR'),
|
||||
),
|
||||
Expanded(child: Divider()),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 25),
|
||||
|
||||
// Register Button
|
||||
SizedBox(
|
||||
width: 250,
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
// Handle register
|
||||
},
|
||||
style: OutlinedButton.styleFrom(
|
||||
shape: const StadiumBorder(),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
backgroundColor: Colors.lightBlue[100],
|
||||
foregroundColor: Colors.black
|
||||
),
|
||||
child: const Text('Register'),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
|
@ -1,146 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import 'package:kmobile/features/auth/controllers/auth_cubit.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
import '../../../app.dart';
|
||||
|
||||
class MPinScreen extends StatefulWidget {
|
||||
const MPinScreen({super.key});
|
||||
|
||||
@override
|
||||
MPinScreenState createState() => MPinScreenState();
|
||||
}
|
||||
|
||||
class MPinScreenState extends State<MPinScreen> {
|
||||
List<String> mPin = [];
|
||||
|
||||
void addDigit(String digit) {
|
||||
if (mPin.length < 4) {
|
||||
setState(() {
|
||||
mPin.add(digit);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void deleteDigit() {
|
||||
if (mPin.isNotEmpty) {
|
||||
setState(() {
|
||||
mPin.removeLast();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Widget buildMPinDots() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(4, (index) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.all(8),
|
||||
width: 15,
|
||||
height: 15,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: index < mPin.length ? Colors.black : Colors.grey[400],
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildNumberPad() {
|
||||
List<List<String>> keys = [
|
||||
['1', '2', '3'],
|
||||
['4', '5', '6'],
|
||||
['7', '8', '9'],
|
||||
['Enter', '0', '<']
|
||||
];
|
||||
|
||||
return Column(
|
||||
children: keys.map((row) {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: row.map((key) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
if (key == '<') {
|
||||
deleteDigit();
|
||||
} else if (key == 'Enter') {
|
||||
if (mPin.length == 4) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const NavigationScaffold()),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text("Please enter 4 digits")),
|
||||
);
|
||||
}
|
||||
} else if (key.isNotEmpty) {
|
||||
addDigit(key);
|
||||
}
|
||||
},
|
||||
child: Container(
|
||||
width: 70,
|
||||
height: 70,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Colors.grey[200],
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: key == 'Enter' ? const Icon(Symbols.check) : Text(
|
||||
key == '<' ? '⌫' : key,
|
||||
style: TextStyle(
|
||||
fontSize: 20,
|
||||
fontWeight: key == 'Enter' ?
|
||||
FontWeight.normal : FontWeight.normal,
|
||||
color: key == 'Enter' ? Colors.blue : Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}).toList(),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final cubit = context.read<AuthCubit>();
|
||||
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
// Logo
|
||||
const FlutterLogo(size: 100),
|
||||
const SizedBox(height: 20),
|
||||
const Text(
|
||||
"Enter your mPIN",
|
||||
style: TextStyle(fontSize: 20, fontWeight: FontWeight.w500),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
buildMPinDots(),
|
||||
const Spacer(),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
TextButton(onPressed: () {
|
||||
cubit.authenticateBiometric();
|
||||
}, child: const Text("Try another way")),
|
||||
TextButton(onPressed: () {}, child: const Text("Register?")),
|
||||
],
|
||||
),
|
||||
buildNumberPad(),
|
||||
const Spacer(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,299 +0,0 @@
|
||||
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"),
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,92 +0,0 @@
|
||||
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),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,200 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class BlockCardScreen extends StatefulWidget {
|
||||
const BlockCardScreen({super.key});
|
||||
|
||||
@override
|
||||
State<BlockCardScreen> createState() => _BlockCardScreen();
|
||||
}
|
||||
|
||||
class _BlockCardScreen extends State<BlockCardScreen>{
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _cardController = TextEditingController();
|
||||
final _cvvController = TextEditingController();
|
||||
final _expiryController = TextEditingController();
|
||||
final _phoneController = TextEditingController();
|
||||
|
||||
Future<void> _pickExpiryDate() async {
|
||||
final now = DateTime.now();
|
||||
final selectedDate = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: now,
|
||||
firstDate: now,
|
||||
lastDate: DateTime(now.year + 10),
|
||||
);
|
||||
if (selectedDate != null) {
|
||||
_expiryController.text = DateFormat('dd/MM/yyyy').format(selectedDate);
|
||||
}
|
||||
}
|
||||
|
||||
void _blockCard() {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
// Call your backend logic here
|
||||
|
||||
final snackBar = SnackBar(
|
||||
content: const Text('Card has been blocked'),
|
||||
action: SnackBarAction(
|
||||
label: 'X',
|
||||
onPressed: () {
|
||||
// Just close the SnackBar
|
||||
},
|
||||
textColor: Colors.white,
|
||||
),
|
||||
backgroundColor: Colors.black,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
}
|
||||
|
||||
@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('Block Card', 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(10.0),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ListView(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _cardController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Card Number',
|
||||
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) =>
|
||||
value != null && value.length == 16 ? null : 'Enter valid card number',
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: _cvvController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'CVV',
|
||||
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,
|
||||
obscureText: true,
|
||||
validator: (value) =>
|
||||
value != null && value.length == 3 ? null : 'CVV must be 3 digits',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: _expiryController,
|
||||
readOnly: true,
|
||||
onTap: _pickExpiryDate,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Expiry Date',
|
||||
suffixIcon: Icon(Icons.calendar_today),
|
||||
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),
|
||||
),
|
||||
),
|
||||
validator: (value) =>
|
||||
value != null && value.isNotEmpty ? null : 'Select expiry date',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
TextFormField(
|
||||
controller: _phoneController,
|
||||
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,
|
||||
keyboardType: TextInputType.phone,
|
||||
validator: (value) =>
|
||||
value != null && value.length >= 10 ? null : 'Enter valid phone number',
|
||||
),
|
||||
const SizedBox(height: 45),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
width: 250,
|
||||
child: ElevatedButton(
|
||||
onPressed: _blockCard,
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const StadiumBorder(),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
backgroundColor: Colors.blue[900],
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
child: const Text('Block'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/features/card/screens/block_card_screen.dart';
|
||||
import 'package:kmobile/features/card/screens/card_pin_change_details_screen.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class CardManagementScreen extends StatefulWidget {
|
||||
const CardManagementScreen({super.key});
|
||||
|
||||
@override
|
||||
State<CardManagementScreen> createState() => _CardManagementScreen();
|
||||
}
|
||||
|
||||
class _CardManagementScreen extends State<CardManagementScreen>{
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
title: const Text('Card Management', 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: ListView(
|
||||
children: [
|
||||
CardManagementTile(
|
||||
icon: Symbols.add,
|
||||
label: 'Apply Debit Card',
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
CardManagementTile(
|
||||
icon: Symbols.remove_moderator,
|
||||
label: 'Block / Unblock Card',
|
||||
onTap: () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const BlockCardScreen()));
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
CardManagementTile(
|
||||
icon: Symbols.password_2,
|
||||
label: 'Change Card PIN',
|
||||
onTap: () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const CardPinChangeDetailsScreen()));
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CardManagementTile extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String label;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const CardManagementTile({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.label,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Icon(icon),
|
||||
title: Text(label),
|
||||
trailing: const Icon(Symbols.arrow_right, size: 20),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -1,189 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:kmobile/features/card/screens/card_pin_set_screen.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class CardPinChangeDetailsScreen extends StatefulWidget {
|
||||
const CardPinChangeDetailsScreen({super.key});
|
||||
|
||||
@override
|
||||
State<CardPinChangeDetailsScreen> createState() => _CardPinChangeDetailsScreen();
|
||||
}
|
||||
|
||||
class _CardPinChangeDetailsScreen extends State<CardPinChangeDetailsScreen>{
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _cardController = TextEditingController();
|
||||
final _cvvController = TextEditingController();
|
||||
final _expiryController = TextEditingController();
|
||||
final _phoneController = TextEditingController();
|
||||
|
||||
Future<void> _pickExpiryDate() async {
|
||||
final now = DateTime.now();
|
||||
final selectedDate = await showDatePicker(
|
||||
context: context,
|
||||
initialDate: now,
|
||||
firstDate: now,
|
||||
lastDate: DateTime(now.year + 10),
|
||||
);
|
||||
if (selectedDate != null) {
|
||||
_expiryController.text = DateFormat('dd/MM/yyyy').format(selectedDate);
|
||||
}
|
||||
}
|
||||
|
||||
void _nextButton() {
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
// Call your backend logic here
|
||||
Navigator.of(context).pushReplacement(
|
||||
MaterialPageRoute(builder: (context) => const CardPinSetScreen()),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@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('Card Details', 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(10.0),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ListView(
|
||||
children: [
|
||||
const SizedBox(height: 10),
|
||||
TextFormField(
|
||||
controller: _cardController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Card Number',
|
||||
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) =>
|
||||
value != null && value.length == 16 ? null : 'Enter valid card number',
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: _cvvController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'CVV',
|
||||
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,
|
||||
obscureText: true,
|
||||
validator: (value) =>
|
||||
value != null && value.length == 3 ? null : 'CVV must be 3 digits',
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 16),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
controller: _expiryController,
|
||||
readOnly: true,
|
||||
onTap: _pickExpiryDate,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Expiry Date',
|
||||
suffixIcon: Icon(Icons.calendar_today),
|
||||
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),
|
||||
),
|
||||
),
|
||||
validator: (value) =>
|
||||
value != null && value.isNotEmpty ? null : 'Select expiry date',
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
TextFormField(
|
||||
controller: _phoneController,
|
||||
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,
|
||||
keyboardType: TextInputType.phone,
|
||||
validator: (value) =>
|
||||
value != null && value.length >= 10 ? null : 'Enter valid phone number',
|
||||
),
|
||||
const SizedBox(height: 45),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
width: 250,
|
||||
child: ElevatedButton(
|
||||
onPressed: _nextButton,
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const StadiumBorder(),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
backgroundColor: Colors.blue[900],
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
child: const Text('Next'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,148 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class CardPinSetScreen extends StatefulWidget {
|
||||
const CardPinSetScreen({super.key});
|
||||
|
||||
@override
|
||||
State<CardPinSetScreen> createState() => _CardPinSetScreen();
|
||||
}
|
||||
|
||||
class _CardPinSetScreen extends State<CardPinSetScreen>{
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _pinController = TextEditingController();
|
||||
final _confirmPinController = TextEditingController();
|
||||
|
||||
void _submit() {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
// Handle PIN submission logic here
|
||||
final snackBar = SnackBar(
|
||||
content: const Text('PIN set successfully'),
|
||||
action: SnackBarAction(
|
||||
label: 'X',
|
||||
onPressed: () {
|
||||
// Just close the SnackBar
|
||||
},
|
||||
textColor: Colors.white,
|
||||
),
|
||||
backgroundColor: Colors.black,
|
||||
behavior: SnackBarBehavior.floating,
|
||||
);
|
||||
|
||||
ScaffoldMessenger.of(context).showSnackBar(snackBar);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
_pinController.dispose();
|
||||
_confirmPinController.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('Card PIN', 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(16.0),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: _pinController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Enter new PIN',
|
||||
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.isEmpty) {
|
||||
return 'Please enter new PIN';
|
||||
}
|
||||
if (value.length < 4) {
|
||||
return 'PIN must be at least 4 digits';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
TextFormField(
|
||||
controller: _confirmPinController,
|
||||
obscureText: true,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Enter Again',
|
||||
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.done,
|
||||
validator: (value) {
|
||||
if (value != _pinController.text) {
|
||||
return 'PINs do not match';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 45),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: SizedBox(
|
||||
width: 250,
|
||||
child: ElevatedButton(
|
||||
onPressed: _submit,
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const StadiumBorder(),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
backgroundColor: Colors.blue[900],
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
child: const Text('Submit'),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,124 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/features/enquiry/screens/enquiry_screen.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class ChequeManagementScreen extends StatefulWidget {
|
||||
const ChequeManagementScreen({super.key});
|
||||
|
||||
@override
|
||||
State<ChequeManagementScreen> createState() => _ChequeManagementScreen();
|
||||
}
|
||||
|
||||
class _ChequeManagementScreen extends State<ChequeManagementScreen>{
|
||||
|
||||
@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('Cheque Management', 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: ListView(
|
||||
children: [
|
||||
const SizedBox(height: 15),
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.add,
|
||||
label: 'Request Checkbook',
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.data_alert,
|
||||
label: 'Enquiry',
|
||||
onTap: () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const EnquiryScreen()));
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.approval_delegation,
|
||||
label: 'Cheque Deposit',
|
||||
onTap: () {
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.front_hand,
|
||||
label: 'Stop Cheque',
|
||||
onTap: () {
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.cancel_presentation,
|
||||
label: 'Revoke Stop',
|
||||
onTap: () {
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
ChequeManagementTile(
|
||||
icon: Symbols.payments,
|
||||
label: 'Positive Pay',
|
||||
onTap: () {
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class ChequeManagementTile extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String label;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const ChequeManagementTile({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.label,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Icon(icon),
|
||||
title: Text(label),
|
||||
trailing: const Icon(Symbols.arrow_right, size: 20),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,104 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class CustomerInfoScreen extends StatefulWidget {
|
||||
const CustomerInfoScreen({super.key});
|
||||
|
||||
@override
|
||||
State<CustomerInfoScreen> createState() => _CustomerInfoScreen();
|
||||
}
|
||||
|
||||
class _CustomerInfoScreen extends State<CustomerInfoScreen>{
|
||||
@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('kMobile', style: TextStyle(color: Colors.black,
|
||||
fontWeight: FontWeight.w500),),
|
||||
actions: const [
|
||||
Padding(
|
||||
padding: EdgeInsets.only(right: 10.0),
|
||||
child: CircleAvatar(
|
||||
backgroundImage: AssetImage('assets/images/avatar.jpg'), // Replace with your image
|
||||
radius: 20,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
body: const SingleChildScrollView(
|
||||
physics: AlwaysScrollableScrollPhysics(),
|
||||
child: Padding(
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: SafeArea(
|
||||
child: Center(
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(height: 30),
|
||||
CircleAvatar(
|
||||
backgroundImage: AssetImage('assets/images/avatar.jpg'), // Replace with your image
|
||||
radius: 50,
|
||||
),
|
||||
|
||||
Padding(
|
||||
padding: EdgeInsets.only(top: 10.0),
|
||||
child: Text('Trina Bakshi', style: TextStyle(fontSize: 20,
|
||||
color: Colors.black, fontWeight: FontWeight.w500),),
|
||||
),
|
||||
|
||||
Text('CIF: 2553677487774', style: TextStyle(fontSize: 16, color: Colors.grey),),
|
||||
SizedBox(height: 30,),
|
||||
InfoField(label: 'Number of Active Accounts', value: '3'),
|
||||
InfoField(label: 'Mobile Number', value: '987XXXXX78'),
|
||||
InfoField(label: 'Date of Birth', value: '12-07-1984'),
|
||||
InfoField(label: 'Branch', value: 'Krishnapur'),
|
||||
InfoField(label: 'Aadhar Number', value: '7665 XXXX 1276'),
|
||||
InfoField(label: 'PAN Number', value: '700127638009871'),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
)),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class InfoField extends StatelessWidget {
|
||||
final String label;
|
||||
final String value;
|
||||
|
||||
const InfoField({Key? key, required this.label, required this.value}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Container(
|
||||
width: double.infinity,
|
||||
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
label,
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,14 +1,11 @@
|
||||
import 'package:flutter/material.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/cheque/screens/cheque_management_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:kmobile/features/enquiry/screens/enquiry_screen.dart';
|
||||
import 'package:kmobile/features/fund_transfer/screens/fund_transfer_beneficiary_screen.dart';
|
||||
import 'package:kmobile/features/quick_pay/screens/quick_pay_screen.dart';
|
||||
import 'package:kmobile/src/preferences/preference.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||
import '../../auth/controllers/auth_cubit.dart';
|
||||
import '../../auth/controllers/auth_state.dart';
|
||||
import '../widgets/account_card.dart';
|
||||
import '../widgets/transaction_list_item.dart';
|
||||
import '../../accounts/models/account.dart';
|
||||
import '../../transactions/models/transaction.dart';
|
||||
|
||||
class DashboardScreen extends StatefulWidget {
|
||||
const DashboardScreen({super.key});
|
||||
@ -18,173 +15,331 @@ class DashboardScreen extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _DashboardScreenState extends State<DashboardScreen> {
|
||||
// Mock data for transactions
|
||||
final List<Map<String, String>> transactions = [
|
||||
{'name': 'Raj Kumar', 'amount': '₹1,000', 'date': '09 March, 2025 16:04', 'type': 'in'},
|
||||
{'name': 'Sunita Joshi', 'amount': '₹1,45,000', 'date': '07 March, 2025 16:04', 'type': 'out'},
|
||||
{'name': 'Manoj Singh', 'amount': '₹2,400', 'date': '07 March, 2025 16:04', 'type': 'in'},
|
||||
{'name': 'Raj Kumar', 'amount': '₹11,500', 'date': '09 March, 2025 16:04', 'type': 'in'},
|
||||
{'name': 'Manoj Singh', 'amount': '₹1,000', 'date': '', 'type': 'in'},
|
||||
// Mock data for demonstration
|
||||
final List<Account> _accounts = [
|
||||
Account(
|
||||
id: '1',
|
||||
accountNumber: '**** 4589',
|
||||
accountType: 'Savings',
|
||||
balance: 12450.75,
|
||||
currency: 'USD',
|
||||
),
|
||||
Account(
|
||||
id: '2',
|
||||
accountNumber: '**** 7823',
|
||||
accountType: 'Checking',
|
||||
balance: 3840.50,
|
||||
currency: 'USD',
|
||||
),
|
||||
];
|
||||
|
||||
final List<Transaction> _recentTransactions = [
|
||||
Transaction(
|
||||
id: 't1',
|
||||
description: 'Coffee Shop',
|
||||
amount: -4.50,
|
||||
date: DateTime.now().subtract(const Duration(hours: 3)),
|
||||
category: 'Food & Drink',
|
||||
),
|
||||
Transaction(
|
||||
id: 't2',
|
||||
description: 'Salary Deposit',
|
||||
amount: 2500.00,
|
||||
date: DateTime.now().subtract(const Duration(days: 2)),
|
||||
category: 'Income',
|
||||
),
|
||||
Transaction(
|
||||
id: 't3',
|
||||
description: 'Electric Bill',
|
||||
amount: -85.75,
|
||||
date: DateTime.now().subtract(const Duration(days: 3)),
|
||||
category: 'Utilities',
|
||||
),
|
||||
Transaction(
|
||||
id: 't4',
|
||||
description: 'Amazon Purchase',
|
||||
amount: -32.50,
|
||||
date: DateTime.now().subtract(const Duration(days: 5)),
|
||||
category: 'Shopping',
|
||||
),
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
backgroundColor: const Color(0xfff5f9fc),
|
||||
appBar: AppBar(
|
||||
backgroundColor: const Color(0xfff5f9fc),
|
||||
automaticallyImplyLeading: false,
|
||||
title: const Text('kMobile', style: TextStyle(color: Colors.blueAccent,
|
||||
fontWeight: FontWeight.w500),),
|
||||
title: const Text('Dashboard'),
|
||||
actions: [
|
||||
// IconButton(
|
||||
// icon: const Icon(Icons.notifications_outlined),
|
||||
// onPressed: () {
|
||||
// // Navigate to notifications
|
||||
// },
|
||||
// ),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10.0),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
onTap: (){
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const Preference()));
|
||||
},
|
||||
child: const CircleAvatar(
|
||||
backgroundImage: AssetImage('assets/images/avatar.jpg'), // Replace with your image
|
||||
radius: 20,
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.notifications_outlined),
|
||||
onPressed: () {
|
||||
// Navigate to notifications
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Icons.logout),
|
||||
onPressed: () {
|
||||
_showLogoutConfirmation(context);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Account Info Card
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.blue[700],
|
||||
borderRadius: BorderRadius.circular(16),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: () async {
|
||||
// Implement refresh logic to fetch updated data
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
},
|
||||
child: SingleChildScrollView(
|
||||
physics: const AlwaysScrollableScrollPhysics(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Greeting section
|
||||
BlocBuilder<AuthCubit, AuthState>(
|
||||
builder: (context, state) {
|
||||
if (state is Authenticated) {
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Hello, ${state.user.username}',
|
||||
style: Theme.of(context).textTheme.headlineSmall,
|
||||
),
|
||||
const SizedBox(height: 4),
|
||||
Text(
|
||||
'Welcome back to your banking app',
|
||||
style: Theme.of(context).textTheme.bodyMedium?.copyWith(
|
||||
color: Colors.grey[600],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return Container();
|
||||
},
|
||||
),
|
||||
child: const Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
||||
const SizedBox(height: 24),
|
||||
|
||||
// Account cards section
|
||||
const Text(
|
||||
'Your Accounts',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
SizedBox(
|
||||
height: 180,
|
||||
child: ListView.builder(
|
||||
scrollDirection: Axis.horizontal,
|
||||
itemCount: _accounts.length + 1, // +1 for the "Add Account" card
|
||||
itemBuilder: (context, index) {
|
||||
if (index < _accounts.length) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(right: 16.0),
|
||||
child: AccountCard(account: _accounts[index]),
|
||||
);
|
||||
} else {
|
||||
// "Add Account" card
|
||||
return Container(
|
||||
width: 300,
|
||||
margin: const EdgeInsets.only(right: 16.0),
|
||||
decoration: BoxDecoration(
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
border: Border.all(color: Colors.grey[300]!),
|
||||
),
|
||||
child: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
Icons.add_circle_outline,
|
||||
size: 40,
|
||||
color: Theme.of(context).primaryColor,
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
'Add New Account',
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).primaryColor,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// Quick Actions section
|
||||
const Text(
|
||||
'Quick Actions',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
Text("Account Number: ", style:
|
||||
TextStyle(color: Colors.white, fontSize: 12)),
|
||||
Text("03000156789462302", style:
|
||||
TextStyle(color: Colors.white, fontSize: 14)),
|
||||
Padding(
|
||||
padding: EdgeInsets.only(left: 5.0),
|
||||
child: Icon(Symbols.keyboard_arrow_down, color: Colors.white),
|
||||
),
|
||||
],
|
||||
_buildQuickActionButton(
|
||||
icon: Icons.swap_horiz,
|
||||
label: 'Transfer',
|
||||
onTap: () {
|
||||
// Navigate to transfer screen
|
||||
},
|
||||
),
|
||||
SizedBox(height: 15),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text("₹ *****", style: TextStyle(color: Colors.white,
|
||||
fontSize: 24, fontWeight: FontWeight.w700)),
|
||||
Icon(Symbols.visibility_lock, color: Colors.white),
|
||||
],
|
||||
_buildQuickActionButton(
|
||||
icon: Icons.payment,
|
||||
label: 'Pay Bills',
|
||||
onTap: () {
|
||||
// Navigate to bill payment screen
|
||||
},
|
||||
),
|
||||
_buildQuickActionButton(
|
||||
icon: Icons.qr_code_scanner,
|
||||
label: 'Scan & Pay',
|
||||
onTap: () {
|
||||
// Navigate to QR code scanner
|
||||
},
|
||||
),
|
||||
_buildQuickActionButton(
|
||||
icon: Icons.more_horiz,
|
||||
label: 'More',
|
||||
onTap: () {
|
||||
// Show more options
|
||||
},
|
||||
),
|
||||
SizedBox(height: 20),
|
||||
],
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 18),
|
||||
const Text('Quick Links', style: TextStyle(fontSize: 15),),
|
||||
const SizedBox(height: 16),
|
||||
|
||||
// Quick Links
|
||||
GridView.count(
|
||||
crossAxisCount: 4,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
_buildQuickLink(Symbols.id_card, "Customer \n Info", () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const CustomerInfoScreen()));
|
||||
}),
|
||||
_buildQuickLink(Symbols.currency_rupee, "Quick \n Pay",
|
||||
() {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const QuickPayScreen()));
|
||||
}),
|
||||
_buildQuickLink(Symbols.send_money, "Fund \n Transfer",
|
||||
() {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const FundTransferBeneficiaryScreen()));
|
||||
}),
|
||||
_buildQuickLink(Symbols.server_person, "Account \n Info",
|
||||
(){
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const AccountInfoScreen()));
|
||||
}),
|
||||
_buildQuickLink(Symbols.receipt_long, "Account \n History",
|
||||
() {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const AccountStatementScreen()));
|
||||
}),
|
||||
_buildQuickLink(Symbols.checkbook, "Handle \n Cheque",
|
||||
() {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const ChequeManagementScreen()));
|
||||
}),
|
||||
_buildQuickLink(Icons.group, "Manage \n Beneficiary",
|
||||
() {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const ManageBeneficiariesScreen()));
|
||||
}),
|
||||
_buildQuickLink(Symbols.support_agent, "Contact \n Us",
|
||||
() {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const EnquiryScreen()));
|
||||
}),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 10),
|
||||
|
||||
// Recent Transactions
|
||||
const Align(
|
||||
alignment: Alignment.centerLeft,
|
||||
child: Text("Recent Transactions", style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold)),
|
||||
),
|
||||
...transactions.map((tx) => ListTile(
|
||||
leading: Icon(tx['type'] == 'in' ? Symbols.call_received : Symbols.call_made, color: tx['type'] == 'in' ? Colors.green : Colors.red),
|
||||
title: Text(tx['name']!),
|
||||
subtitle: Text(tx['date']!),
|
||||
trailing: Text(tx['amount']!),
|
||||
)),
|
||||
|
||||
|
||||
],
|
||||
|
||||
const SizedBox(height: 32),
|
||||
|
||||
// Recent Transactions section
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Recent Transactions',
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
// Navigate to all transactions
|
||||
},
|
||||
child: const Text('See All'),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
ListView.builder(
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
shrinkWrap: true,
|
||||
itemCount: _recentTransactions.length,
|
||||
itemBuilder: (context, index) {
|
||||
return TransactionListItem(
|
||||
transaction: _recentTransactions[index],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: 0,
|
||||
type: BottomNavigationBarType.fixed,
|
||||
items: const [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.dashboard),
|
||||
label: 'Home',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.account_balance_wallet),
|
||||
label: 'Accounts',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.show_chart),
|
||||
label: 'Insights',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.person),
|
||||
label: 'Profile',
|
||||
),
|
||||
],
|
||||
onTap: (index) {
|
||||
// Handle navigation
|
||||
},
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildQuickLink(IconData icon, String label, VoidCallback onTap) {
|
||||
return InkWell(
|
||||
Widget _buildQuickActionButton({
|
||||
required IconData icon,
|
||||
required String label,
|
||||
required VoidCallback onTap,
|
||||
}) {
|
||||
return GestureDetector(
|
||||
onTap: onTap,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Icon(icon, size: 30, color: Colors.blue[700]),
|
||||
const SizedBox(height: 4),
|
||||
Text(label, textAlign: TextAlign.center, style: const TextStyle(fontSize: 12)),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).primaryColor.withAlpha((0.1 * 255).toInt()),
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Icon(
|
||||
icon,
|
||||
color: Theme.of(context).primaryColor,
|
||||
size: 28,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Text(
|
||||
label,
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void _showLogoutConfirmation(BuildContext context) {
|
||||
showDialog(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Logout'),
|
||||
content: const Text('Are you sure you want to logout?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
child: const Text('CANCEL'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
context.read<AuthCubit>().logout();
|
||||
},
|
||||
child: const Text('LOGOUT'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
|
@ -1,93 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
import 'package:url_launcher/url_launcher.dart';
|
||||
|
||||
class EnquiryScreen extends StatefulWidget {
|
||||
const EnquiryScreen({super.key});
|
||||
|
||||
@override
|
||||
State<EnquiryScreen> createState() => _EnquiryScreen();
|
||||
}
|
||||
|
||||
class _EnquiryScreen extends State<EnquiryScreen>{
|
||||
Future<void> _launchEmail() async {
|
||||
final Uri emailUri = Uri(
|
||||
scheme: 'mailto',
|
||||
path: 'helpdesk@kccb.in',
|
||||
);
|
||||
if (await canLaunchUrl(emailUri)) {
|
||||
await launchUrl(emailUri);
|
||||
} else {
|
||||
debugPrint('Could not launch email client');
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _launchPhone() async {
|
||||
final Uri phoneUri = Uri(scheme: 'tel', path: '0651-312861');
|
||||
if (await canLaunchUrl(phoneUri)) {
|
||||
await launchUrl(phoneUri);
|
||||
} else {
|
||||
debugPrint('Could not launch phone dialer');
|
||||
}
|
||||
}
|
||||
|
||||
@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('Enquiry', 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(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text("Mail us at", style: TextStyle(color: Colors.grey)),
|
||||
const SizedBox(height: 4),
|
||||
GestureDetector(
|
||||
onTap: _launchEmail,
|
||||
child: const Text(
|
||||
"helpdesk@kccb.in",
|
||||
style: TextStyle(color: Colors.blue),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Text("Call us at", style: TextStyle(color: Colors.grey)),
|
||||
const SizedBox(height: 4),
|
||||
GestureDetector(
|
||||
onTap: _launchPhone,
|
||||
child: const Text(
|
||||
"0651-312861",
|
||||
style: TextStyle(color: Colors.blue),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
const Text("Write to us", style: TextStyle(color: Colors.grey)),
|
||||
const SizedBox(height: 4),
|
||||
const Text(
|
||||
"101 Street, Some Street, Some Address\nSome Address",
|
||||
style: TextStyle(color: Colors.blue),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,96 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/features/beneficiaries/screens/add_beneficiary_screen.dart';
|
||||
import 'package:kmobile/features/fund_transfer/screens/fund_transfer_screen.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class FundTransferBeneficiaryScreen extends StatefulWidget {
|
||||
const FundTransferBeneficiaryScreen({super.key});
|
||||
|
||||
@override
|
||||
State<FundTransferBeneficiaryScreen> createState() => _FundTransferBeneficiaryScreen();
|
||||
}
|
||||
|
||||
class _FundTransferBeneficiaryScreen extends State<FundTransferBeneficiaryScreen>{
|
||||
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('Fund Transfer - 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: 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.arrow_right, size: 20,),
|
||||
onPressed: () {
|
||||
// Delete action
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
Navigator.push(context, MaterialPageRoute(
|
||||
builder: (context) => const FundTransferScreen()));
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
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),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,133 +0,0 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/features/fund_transfer/screens/transaction_pin_screen.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class FundTransferScreen extends StatefulWidget {
|
||||
const FundTransferScreen({super.key});
|
||||
|
||||
@override
|
||||
State<FundTransferScreen> createState() => _FundTransferScreen();
|
||||
}
|
||||
|
||||
class _FundTransferScreen extends State<FundTransferScreen> {
|
||||
String amount = "";
|
||||
|
||||
void onKeyTap(String key) {
|
||||
setState(() {
|
||||
if (key == 'back') {
|
||||
if (amount.isNotEmpty) {
|
||||
amount = amount.substring(0, amount.length - 1);
|
||||
}
|
||||
} else if (key == 'done') {
|
||||
if (kDebugMode) {
|
||||
print('Amount entered: $amount');
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TransactionPinScreen()));
|
||||
}
|
||||
} else {
|
||||
amount += key;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget buildKey(String value) {
|
||||
if (value == 'done') {
|
||||
return GestureDetector(
|
||||
onTap: () => onKeyTap(value),
|
||||
child: const Icon(Symbols.check, size: 30),
|
||||
);
|
||||
} else if (value == 'back') {
|
||||
return GestureDetector(
|
||||
onTap: () => onKeyTap(value),
|
||||
child: const Icon(Symbols.backspace, size: 30));
|
||||
} else {
|
||||
return GestureDetector(
|
||||
onTap: () => onKeyTap(value),
|
||||
child: Center(
|
||||
child: Text(value,
|
||||
style: const TextStyle(fontSize: 24, color: Colors.black)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
final keys = [
|
||||
'1',
|
||||
'2',
|
||||
'3',
|
||||
'4',
|
||||
'5',
|
||||
'6',
|
||||
'7',
|
||||
'8',
|
||||
'9',
|
||||
'done',
|
||||
'0',
|
||||
'back',
|
||||
];
|
||||
|
||||
@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(
|
||||
'Fund Transfer',
|
||||
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: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
const Text('Enter Amount', style: TextStyle(fontSize: 20)),
|
||||
const SizedBox(height: 20),
|
||||
Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 24, vertical: 16),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.grey.shade200,
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
child: Text(
|
||||
amount.isEmpty ? "0" : amount,
|
||||
style: const TextStyle(fontSize: 32, fontWeight: FontWeight.bold),
|
||||
),
|
||||
),
|
||||
const Spacer(),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
color: Colors.white,
|
||||
child: GridView.count(
|
||||
crossAxisCount: 3,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
mainAxisSpacing: 12,
|
||||
crossAxisSpacing: 12,
|
||||
childAspectRatio: 1.2,
|
||||
children:
|
||||
keys.map((key) => buildKey(key)).toList(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,139 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/features/fund_transfer/screens/transaction_success_screen.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class TransactionPinScreen extends StatefulWidget {
|
||||
const TransactionPinScreen({super.key});
|
||||
|
||||
@override
|
||||
State<TransactionPinScreen> createState() => _TransactionPinScreen();
|
||||
}
|
||||
|
||||
class _TransactionPinScreen extends State<TransactionPinScreen> {
|
||||
final List<String> _pin = [];
|
||||
|
||||
void _onKeyPressed(String value) {
|
||||
setState(() {
|
||||
if (value == 'back') {
|
||||
if (_pin.isNotEmpty) _pin.removeLast();
|
||||
} else if (_pin.length < 6) {
|
||||
_pin.add(value);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
Widget _buildPinIndicators() {
|
||||
return Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: List.generate(6, (index) {
|
||||
return Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 8),
|
||||
width: 20,
|
||||
height: 20,
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.blue, width: 2),
|
||||
color: index < _pin.length ? Colors.blue : Colors.transparent,
|
||||
),
|
||||
);
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildKey(String label, {IconData? icon}) {
|
||||
return Expanded(
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
if (label == 'back') {
|
||||
_onKeyPressed('back');
|
||||
} else if (label == 'done') {
|
||||
// Handle submit if needed
|
||||
if (_pin.length == 6) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const TransactionSuccessScreen()));
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(content: Text("Please enter a 6-digit TPIN")),
|
||||
);
|
||||
}
|
||||
} else {
|
||||
_onKeyPressed(label);
|
||||
}
|
||||
},
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||
child: Center(
|
||||
child: icon != null
|
||||
? Icon(icon, size: 28)
|
||||
: Text(label, style: const TextStyle(fontSize: 24)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildKeypad() {
|
||||
return Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Row(children: [_buildKey('1'), _buildKey('2'), _buildKey('3')]),
|
||||
Row(children: [_buildKey('4'), _buildKey('5'), _buildKey('6')]),
|
||||
Row(children: [_buildKey('7'), _buildKey('8'), _buildKey('9')]),
|
||||
Row(children: [
|
||||
_buildKey('done', icon: Icons.check),
|
||||
_buildKey('0'),
|
||||
_buildKey('back', icon: Icons.backspace_outlined),
|
||||
]),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
@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(
|
||||
'TPIN',
|
||||
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.only(bottom: 20.0),
|
||||
child: Column(
|
||||
children: [
|
||||
const Spacer(),
|
||||
const Text(
|
||||
'Enter Your TPIN',
|
||||
style: TextStyle(fontSize: 18),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
_buildPinIndicators(),
|
||||
const Spacer(),
|
||||
_buildKeypad(),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,140 +0,0 @@
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:path_provider/path_provider.dart';
|
||||
import 'package:screenshot/screenshot.dart';
|
||||
import 'package:social_share/social_share.dart';
|
||||
|
||||
import '../../../app.dart';
|
||||
|
||||
class TransactionSuccessScreen extends StatefulWidget {
|
||||
const TransactionSuccessScreen({super.key});
|
||||
|
||||
@override
|
||||
State<TransactionSuccessScreen> createState() => _TransactionSuccessScreen();
|
||||
}
|
||||
|
||||
class _TransactionSuccessScreen extends State<TransactionSuccessScreen> {
|
||||
final String transactionDate = "18th March, 2025 04:30 PM";
|
||||
final String referenceNumber = "TXN32131093012931993";
|
||||
|
||||
final ScreenshotController _screenshotController = ScreenshotController();
|
||||
|
||||
Future<void> _shareScreenshot() async {
|
||||
final Uint8List? imageBytes = await _screenshotController.capture();
|
||||
if (imageBytes != null) {
|
||||
final directory = await getTemporaryDirectory();
|
||||
final imagePath = File('${directory.path}/transaction_success.png');
|
||||
await imagePath.writeAsBytes(imageBytes);
|
||||
|
||||
SocialShare.shareOptions(
|
||||
"Transaction Successful",
|
||||
imagePath: imagePath.path,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
body: SafeArea(
|
||||
child: Stack(
|
||||
children: [
|
||||
// Main content
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
const CircleAvatar(
|
||||
radius: 50,
|
||||
backgroundColor: Colors.blue,
|
||||
child: Icon(
|
||||
Icons.check,
|
||||
color: Colors.white,
|
||||
size: 60,
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 24),
|
||||
const Text(
|
||||
"Transaction Successful",
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.w600,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 6),
|
||||
Text(
|
||||
"On $transactionDate",
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Colors.black54,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
const SizedBox(height: 16),
|
||||
Text(
|
||||
"Reference No: $referenceNumber",
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
color: Colors.black87,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
|
||||
// Buttons at the bottom
|
||||
Align(
|
||||
alignment: Alignment.bottomCenter,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.fromLTRB(36, 0, 36, 25),
|
||||
child: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: OutlinedButton.icon(
|
||||
onPressed: _shareScreenshot,
|
||||
icon: const Icon(Icons.share, size: 18),
|
||||
label: const Text("Share"),
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const StadiumBorder(),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
backgroundColor: Colors.white,
|
||||
foregroundColor: Colors.blueAccent,
|
||||
side: const BorderSide(color: Colors.black, width: 1),
|
||||
elevation: 0
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
// Done action
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const NavigationScaffold()));
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
shape: const StadiumBorder(),
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
backgroundColor: Colors.blue[900],
|
||||
foregroundColor: Colors.white,
|
||||
),
|
||||
child: const Text("Done"),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@ -1,372 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_swipe_button/flutter_swipe_button.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class QuickPayOutsideBankScreen extends StatefulWidget {
|
||||
const QuickPayOutsideBankScreen({super.key});
|
||||
|
||||
@override
|
||||
State<QuickPayOutsideBankScreen> createState() =>
|
||||
_QuickPayOutsideBankScreen();
|
||||
}
|
||||
|
||||
class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
// Controllers
|
||||
final accountNumberController = TextEditingController();
|
||||
final nameController = TextEditingController();
|
||||
final bankNameController = TextEditingController();
|
||||
final branchNameController = TextEditingController();
|
||||
final ifscController = TextEditingController();
|
||||
final phoneController = TextEditingController();
|
||||
final amountController = TextEditingController();
|
||||
|
||||
String accountType = 'Savings';
|
||||
final List<String> transactionModes = ['NEFT', 'RTGS', 'IMPS'];
|
||||
int selectedTransactionIndex = 0;
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
// Dispose controllers
|
||||
accountNumberController.dispose();
|
||||
nameController.dispose();
|
||||
bankNameController.dispose();
|
||||
branchNameController.dispose();
|
||||
ifscController.dispose();
|
||||
phoneController.dispose();
|
||||
amountController.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(
|
||||
'Quick Pay - Other Bank',
|
||||
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(12),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: ListView(
|
||||
children: [
|
||||
const SizedBox(height: 25),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Account Number',
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: accountNumberController,
|
||||
keyboardType: TextInputType.number,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Account number is required';
|
||||
} else if (value.length != 16) {
|
||||
return 'Enter a valid account number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Name',
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: nameController,
|
||||
keyboardType: TextInputType.name,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Name is required';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Beneficiary Bank Name",
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: bankNameController,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Beneficiary Bank Name is required';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Branch Name",
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: branchNameController,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Branch Name is required';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: "IFSC Code",
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: ifscController,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'IFSC Code is required';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
)),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: DropdownButtonFormField<String>(
|
||||
value: accountType,
|
||||
decoration: const InputDecoration(
|
||||
labelText: "Account Type",
|
||||
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((e) => DropdownMenuItem(
|
||||
value: e,
|
||||
child: Text(e),
|
||||
))
|
||||
.toList(),
|
||||
onChanged: (value) => setState(() {
|
||||
accountType = value!;
|
||||
}),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 25),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: 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.next,
|
||||
validator: (value) => value == null || value.isEmpty
|
||||
? "Phone number is Required"
|
||||
: null,
|
||||
),
|
||||
),
|
||||
const SizedBox(width: 10),
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Amount',
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: amountController,
|
||||
keyboardType: TextInputType.number,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Amount is required';
|
||||
}
|
||||
final amount = double.tryParse(value);
|
||||
if (amount == null || amount <= 0) {
|
||||
return 'Enter a valid amount';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 30),
|
||||
Row(
|
||||
children: [
|
||||
const Text("Transaction Mode",
|
||||
style: TextStyle(fontWeight: FontWeight.w500)),
|
||||
const SizedBox(width: 12),
|
||||
Expanded(child: buildTransactionModeSelector()),
|
||||
],
|
||||
),
|
||||
|
||||
const SizedBox(height: 45),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: SwipeButton.expand(
|
||||
thumb: const Icon(
|
||||
Icons.arrow_forward,
|
||||
color: Colors.white,
|
||||
),
|
||||
activeThumbColor: Colors.blue[900],
|
||||
activeTrackColor: Colors.blue.shade100,
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
height: 56,
|
||||
child: const Text(
|
||||
"Swipe to Pay",
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
onSwipe: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
// Perform payment logic
|
||||
final selectedMode = transactionModes[selectedTransactionIndex];
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Paying via $selectedMode...')),
|
||||
);
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTransactionModeSelector() {
|
||||
return Container(
|
||||
padding: const EdgeInsets.all(4),
|
||||
child: Row(
|
||||
children: List.generate(transactionModes.length, (index) {
|
||||
bool isSelected = selectedTransactionIndex == index;
|
||||
return Expanded(
|
||||
child: GestureDetector(
|
||||
onTap: () {
|
||||
setState(() => selectedTransactionIndex = index);
|
||||
},
|
||||
child: Container(
|
||||
margin: const EdgeInsets.symmetric(horizontal: 4),
|
||||
padding: const EdgeInsets.symmetric(vertical: 5),
|
||||
decoration: BoxDecoration(
|
||||
color: isSelected ? Colors.blue[200] : Colors.white,
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
border: Border.all(
|
||||
color: isSelected? Colors.blue : Colors.grey,
|
||||
width: isSelected ? 0 : 1.2,
|
||||
),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
transactionModes[index],
|
||||
style: const TextStyle(
|
||||
color: Colors.black,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,95 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/features/quick_pay/screens/quick_pay_outside_bank_screen.dart';
|
||||
import 'package:kmobile/features/quick_pay/screens/quick_pay_within_bank_screen.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class QuickPayScreen extends StatefulWidget {
|
||||
const QuickPayScreen({super.key});
|
||||
|
||||
@override
|
||||
State<QuickPayScreen> createState() => _QuickPayScreen();
|
||||
}
|
||||
|
||||
class _QuickPayScreen extends State<QuickPayScreen> {
|
||||
@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(
|
||||
'Quick Pay',
|
||||
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: ListView(
|
||||
children: [
|
||||
QuickPayManagementTile(
|
||||
icon: Symbols.input_circle,
|
||||
label: 'Own Bank',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const QuickPayWithinBankScreen()));
|
||||
},
|
||||
),
|
||||
const Divider(
|
||||
height: 1,
|
||||
),
|
||||
QuickPayManagementTile(
|
||||
icon: Symbols.output_circle,
|
||||
label: 'Outside Bank',
|
||||
onTap: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
builder: (context) => const QuickPayOutsideBankScreen()));
|
||||
},
|
||||
),
|
||||
const Divider(
|
||||
height: 1,
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class QuickPayManagementTile extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String label;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const QuickPayManagementTile({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.label,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Icon(icon),
|
||||
title: Text(label),
|
||||
trailing: const Icon(Symbols.arrow_right, size: 20),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,209 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_swipe_button/flutter_swipe_button.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class QuickPayWithinBankScreen extends StatefulWidget {
|
||||
const QuickPayWithinBankScreen({super.key});
|
||||
|
||||
@override
|
||||
State<QuickPayWithinBankScreen> createState() => _QuickPayWithinBankScreen();
|
||||
}
|
||||
|
||||
class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
|
||||
final TextEditingController accountNumberController = TextEditingController();
|
||||
final TextEditingController nameController = TextEditingController();
|
||||
final TextEditingController amountController = TextEditingController();
|
||||
|
||||
@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(
|
||||
'Quick Pay - Own Bank',
|
||||
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(16.0),
|
||||
child: Form(
|
||||
key: _formKey,
|
||||
child: Column(
|
||||
children: [
|
||||
const SizedBox(height: 25),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Account Number',
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: accountNumberController,
|
||||
keyboardType: TextInputType.number,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Account number is required';
|
||||
} else if (value.length != 16) {
|
||||
return 'Enter a valid account number';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 15.0, top: 5),
|
||||
child: Text(
|
||||
'Beneficiary Account Number',
|
||||
style: TextStyle(color: Colors.black54),
|
||||
),
|
||||
)),
|
||||
const SizedBox(height: 25),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Name',
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: nameController,
|
||||
keyboardType: TextInputType.name,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Name is required';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const Align(
|
||||
alignment: Alignment.topLeft,
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(left: 15.0, top: 5),
|
||||
child: Text(
|
||||
'Beneficiary Name',
|
||||
style: TextStyle(color: Colors.black54),
|
||||
),
|
||||
)),
|
||||
const SizedBox(height: 25),
|
||||
TextFormField(
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Amount',
|
||||
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),
|
||||
),
|
||||
),
|
||||
controller: amountController,
|
||||
keyboardType: TextInputType.number,
|
||||
textInputAction: TextInputAction.next,
|
||||
validator: (value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return 'Amount is required';
|
||||
}
|
||||
final amount = double.tryParse(value);
|
||||
if (amount == null || amount <= 0) {
|
||||
return 'Enter a valid amount';
|
||||
}
|
||||
return null;
|
||||
},
|
||||
),
|
||||
const SizedBox(height: 45),
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: SwipeButton.expand(
|
||||
thumb: const Icon(
|
||||
Icons.arrow_forward,
|
||||
color: Colors.white,
|
||||
),
|
||||
activeThumbColor: Colors.blue[900],
|
||||
activeTrackColor: Colors.blue.shade100,
|
||||
borderRadius: BorderRadius.circular(30),
|
||||
height: 56,
|
||||
child: const Text(
|
||||
"Swipe to Pay",
|
||||
style: TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
|
||||
),
|
||||
onSwipe: () {
|
||||
if (_formKey.currentState!.validate()) {
|
||||
// Perform payment logic
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text('Processing Payment...')),
|
||||
);
|
||||
}
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget buildTextFormField({
|
||||
required String label,
|
||||
required TextEditingController controller,
|
||||
TextInputType keyboardType = TextInputType.text,
|
||||
String? Function(String?)? validator,
|
||||
}) {
|
||||
return TextFormField(
|
||||
controller: controller,
|
||||
keyboardType: keyboardType,
|
||||
validator: validator,
|
||||
decoration: InputDecoration(
|
||||
labelText: label,
|
||||
border: const OutlineInputBorder(),
|
||||
isDense: true,
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
enabledBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.black),
|
||||
),
|
||||
focusedBorder: const OutlineInputBorder(
|
||||
borderSide: BorderSide(color: Colors.black, width: 2),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,113 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
|
||||
class ServiceScreen extends StatefulWidget {
|
||||
const ServiceScreen({super.key});
|
||||
|
||||
@override
|
||||
State<ServiceScreen> createState() => _ServiceScreen();
|
||||
}
|
||||
|
||||
class _ServiceScreen extends State<ServiceScreen>{
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
automaticallyImplyLeading: false,
|
||||
title: const Text('Services', style: TextStyle(color: Colors.black,
|
||||
fontWeight: FontWeight.w500),),
|
||||
centerTitle: false,
|
||||
actions: [
|
||||
// IconButton(
|
||||
// icon: const Icon(Icons.notifications_outlined),
|
||||
// onPressed: () {
|
||||
// // Navigate to notifications
|
||||
// },
|
||||
// ),
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(right: 10.0),
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(20),
|
||||
onTap: (){
|
||||
// Navigator.push(context, MaterialPageRoute(
|
||||
// builder: (context) => const CustomerInfoScreen()));
|
||||
},
|
||||
child: const CircleAvatar(
|
||||
backgroundImage: AssetImage('assets/images/avatar.jpg'), // Replace with your image
|
||||
radius: 20,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
body: ListView(
|
||||
children: [
|
||||
ServiceManagementTile(
|
||||
icon: Symbols.add,
|
||||
label: 'Account Opening Request - Deposit',
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
ServiceManagementTile(
|
||||
icon: Symbols.add,
|
||||
label: 'Account Opening Request - Loan',
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
ServiceManagementTile(
|
||||
icon: Symbols.captive_portal,
|
||||
label: 'Quick Links',
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,),
|
||||
|
||||
ServiceManagementTile(
|
||||
icon: Symbols.missing_controller,
|
||||
label: 'Branch Locator',
|
||||
onTap: () {
|
||||
|
||||
},
|
||||
),
|
||||
|
||||
const Divider(height: 1,)
|
||||
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ServiceManagementTile extends StatelessWidget {
|
||||
final IconData icon;
|
||||
final String label;
|
||||
final VoidCallback onTap;
|
||||
|
||||
const ServiceManagementTile({
|
||||
super.key,
|
||||
required this.icon,
|
||||
required this.label,
|
||||
required this.onTap,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return ListTile(
|
||||
leading: Icon(icon),
|
||||
title: Text(label),
|
||||
trailing: const Icon(Symbols.arrow_right, size: 20),
|
||||
onTap: onTap,
|
||||
);
|
||||
}
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
{
|
||||
"@@locale": "bn",
|
||||
"app_title": "আইপিকেএস ম্যাপ",
|
||||
"ipks": "আইপিকেএস",
|
||||
"fingerprint_reason": "অ্যাপ শুরু করতে প্রমাণীকরণ করুন",
|
||||
"@fingerprint_reason": {},
|
||||
"m_pin_entry_prompt": "আপনার এমপিআইএন লিখুন",
|
||||
"register_prompt": "রেজিস্টার?",
|
||||
"try_another_way": "অন্য উপায় চেষ্টা করুন",
|
||||
"username": "ব্যবহারকারীর নাম",
|
||||
"password": "পাসওয়ার্ড",
|
||||
"login": "লগইন",
|
||||
"register": "রেজিস্টার",
|
||||
"mobile_number": "মোবাইল নম্বর",
|
||||
"aadhaar_number": "আধার নম্বর",
|
||||
"date_of_birth": "জন্ম তারিখ",
|
||||
"pacs_id": "প্যাকস আইডি",
|
||||
"view_full_kyc": "পূর্ণ কেওয়াইসি দেখুন",
|
||||
"account_summary": "হিসাবের সংক্ষিপ্ত সমূহ",
|
||||
"account_statement": "হিসাবের বিবৃতি",
|
||||
"customer_details": "গ্রাহকের বিবরণ",
|
||||
"home": "হোম",
|
||||
"details": "বিস্তারিত",
|
||||
"statement": "বিবৃতি",
|
||||
"no_of_active_accounts": "সক্রিয় হিসাবের সংখ্যা",
|
||||
"pan_number": "প্যান নম্বর",
|
||||
"mirror_acct_no": "মিরর হিসাব নম্বর",
|
||||
"cif": "সিআইএফ",
|
||||
"product_name": "পণ্যের নাম",
|
||||
"acct_opening_dt": "হিসাব খোলার তারিখ",
|
||||
"account_status": "হিসাবের অবস্থা",
|
||||
"available_bal": "উপলব্ধ ব্যালেন্স",
|
||||
"interest_rate": "সুদের হার",
|
||||
"acct_type": "হিসাবের ধরন",
|
||||
"acct_no": "হিসাব নম্বর",
|
||||
"date_range": "তারিখের পরিসীমা",
|
||||
"amount_range": "পরিমাণের পরিসীমা",
|
||||
"save": "সংরক্ষণ করুন",
|
||||
"min": "সর্বনিম্ন",
|
||||
"max": "সর্বোচ্চ",
|
||||
"min_amt": "ন্যূনতম পরিমাণ",
|
||||
"max_amt": "সর্বোচ্চ পরিমাণ",
|
||||
"customer_no_search_message": "আপনার আইপিকেএস গ্রাহক নম্বর লিখুন দয়া করে। আপনার গ্রাহক নম্বরটি আইপিকেএস ডেটাবেসে আপনার বিবরণ খুঁজে পেতে ব্যবহৃত হয়।",
|
||||
"search": "অনুসন্ধান",
|
||||
"details_verification_message": "দয়া করে আপনার বিবরণ যাচাই করুন।",
|
||||
"customer_no": "গ্রাহক নম্বর",
|
||||
"name": "নাম",
|
||||
"email": "ইমেল",
|
||||
"pacs_name": "প্যাকস নাম",
|
||||
"not_you_prompt": "না আপনি?",
|
||||
"next": "পরবর্তী",
|
||||
"otp_verification_message": "একটি ওটিপি মেসেজ আপনার নিবন্ধিত মোবাইল নম্বরে {masked_phone_number} প্রেরিত হয়েছে। এটি যাচাই করতে নিচে লিখুন।",
|
||||
"@otp_verification_message": {
|
||||
"placeholders": {
|
||||
"masked_phone_number": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"otp": "ওটিপি",
|
||||
"resend_otp_prompt": "পুনরায় ওটিপি প্রেরণ করুন?",
|
||||
"new_credentials_message": "দয়া করে এমঅ্যাপ এর জন্য আপনার নতুন ব্যবহারকারী নাম এবং পাসওয়ার্ড তৈরি করুন",
|
||||
"repeat_password": "পাসওয়ার্ড পুনরায় লিখুন",
|
||||
"registration_success_display": "রেজিস্ট্রেশন সফল",
|
||||
"goto_login_prompt": "লগইন পৃষ্ঠায় যান",
|
||||
"marital_status": "বৈবাহিক অবস্থা",
|
||||
"gender": "লিঙ্গ",
|
||||
"address": "ঠিকানা",
|
||||
"or": "অথবা",
|
||||
"district": "জেলা",
|
||||
"state": "রাজ্য",
|
||||
"city": "শহর",
|
||||
"pin_code": "পিন কোড",
|
||||
"linked_sb_no": "সংযুক্ত এসবি হিসাব নম্বর",
|
||||
"farmer_type": "কৃষকের ধরণ",
|
||||
"guardian_name": "অভিভাবকের নাম",
|
||||
"religion": "ধর্ম",
|
||||
"caste": "জাতি",
|
||||
"not_available": "পাওয়া যায়নি",
|
||||
"no_accounts_found": "কোনও হিসাব পাওয়া যায়নি",
|
||||
"account_holder": "হিসাব ধারক",
|
||||
"customer_name": "গ্রাহকের নাম",
|
||||
"sanction_amount": "অনুমোদিত পরিমাণ",
|
||||
"sanction_date": "অনুমোদনের তারিখ",
|
||||
"disbursed_amount": "বিতরণ করা পরিমাণ",
|
||||
"interest_outstanding": "সুদের বকেয়া",
|
||||
"principal_outstanding": "প্রধান বকেয়া",
|
||||
"interest_paid": "সুদ প্রদান",
|
||||
"principal_paid": "প্রধান প্রদান",
|
||||
"emi_amount": "ইএমআই পরিমাণ",
|
||||
"due_date": "নির্ধারিত তারিখ",
|
||||
"last_repayment_date": "সর্বশেষ পরিশোধের তারিখ",
|
||||
"interest_description": "সুদের বিবরণ",
|
||||
"total_interest_outstanding": "মোট সুদের বকেয়া",
|
||||
"total_interest_accrued": "মোট সুদ উত্থাপন",
|
||||
"total_interest_paid": "মোট সুদ প্রদান",
|
||||
"loan_type": "ঋণের ধরণ",
|
||||
"old_account_number": "পুরাতন হিসাব নম্বর",
|
||||
"penal_interest_rate": "জরিমানা সুদের হার",
|
||||
"cbs_account_number": "সিবিএস হিসাব নম্বর",
|
||||
"nominee_name": "নোমিনির নাম",
|
||||
"open_date": "খোলার তারিখ",
|
||||
"interest_available": "সুদ উপলব্ধ",
|
||||
"interest_from_date": "সুদ শুরুর তারিখ",
|
||||
"interest_to_date": "সুদ শেষের তারিখ",
|
||||
"term_value": "মেয়াদ মান",
|
||||
"maturity_value": "পরিপ্রেক্ষিত মূল্য",
|
||||
"maturity_date": "পরিপ্রেক্ষিত তারিখ",
|
||||
"term_start_date": "মেয়াদ শুরুর তারিখ",
|
||||
"term_end_date": "মেয়াদ শেষের তারিখ",
|
||||
"interest_projected": "সুদ প্রকাশ্য",
|
||||
"interest_capitalized": "সুদ পুঁজিবদ্ধ",
|
||||
"no_of_installments_paid": "পরিশোধিত কিস্তির সংখ্যা",
|
||||
"next_due_date": "পরবর্তী মেয়াদ শেষের তারিখ",
|
||||
"rd_penal_count": "আরডি জরিমানা গণনা",
|
||||
"hold_value": "ধার মান",
|
||||
"term_length": "মেয়াদের দৈর্ঘ্য",
|
||||
"interest_repayment_method": "সুদ পরিশোধের পদ্ধতি",
|
||||
"mode_of_account": "হিসাবের মোড",
|
||||
"secondary_cif_number": "দ্বিতীয় সিআইএফ নম্বর",
|
||||
"secondary_cif_name": "দ্বিতীয় সিআইএফ নাম",
|
||||
"no_statements_found": "কোনও বিবৃতি পাওয়া যায়নি",
|
||||
"date_range_exceeds_10_days": "10 দিনের বেশি সময়কাল নির্বাচন করুন না",
|
||||
"last_10_transactions": "সর্বশেষ 10 লেনদেন প্রদর্শিত হচ্ছে",
|
||||
"select_account_type": "হিসাবের ধরন নির্বাচন করুন",
|
||||
"select_account_number": "হিসাব নম্বর নির্বাচন করুন",
|
||||
"select_date_range": "তারিখের পরিসীমা নির্বাচন করুন",
|
||||
"please_wait": "অপেক্ষা করুন...",
|
||||
"preferences": "পছন্দসমূহ",
|
||||
"everforest": "এভারফরেস্ট",
|
||||
"rosy": "রোসি",
|
||||
"skypeia": "স্কাইপিয়া",
|
||||
"marigold": "গাঁদা ফুল",
|
||||
"select_language": "ভাষা নির্বাচন করুন",
|
||||
"english": "ইংরেজি",
|
||||
"hindi": "হিন্দি",
|
||||
"bengali": "বাংলা",
|
||||
"malayalam": "মালায়ালম",
|
||||
"dark_theme": "গা থিম",
|
||||
"color_theme": "রঙের থিম",
|
||||
"language": "ভাষা",
|
||||
"deposit": "জমা",
|
||||
"loan": "ঋণ",
|
||||
"export": "রপ্তানি",
|
||||
"invalid_credentials": "অবৈধ পরিচয়পত্র",
|
||||
"logout": "লগআউট",
|
||||
"backend_ip": "ব্যাকএন্ড আইপি",
|
||||
"bank_branch_no": "ব্যাংক শাখা নম্বর",
|
||||
"ifsc_code": "আইএফএসসি কোড",
|
||||
"bank_branch_name": "ব্যাংক শাখার নাম",
|
||||
"search_customer_paragraph": "অনুগ্রহ করে আপনার আইপিকেএস গ্রাহক নম্বর দিন। আপনার গ্রাহক নম্বর আইপিকেএস ডাটাবেসে আপনার বিবরণ খুঁজতে ব্যবহৃত হয়",
|
||||
"invalid_customer_no": "অবৈধ গ্রাহক নম্বর",
|
||||
"searching": "অনুসন্ধান করা হচ্ছে",
|
||||
"invalid_otp": "অবৈধ ওটিপি",
|
||||
"register_customer_message": "অনুগ্রহ করে এমঅ্যাপের জন্য আপনার নতুন ব্যবহারকারী নাম এবং পাসওয়ার্ড প্রবেশ করান",
|
||||
"username_criteria": "৬টি অক্ষর, শুধুমাত্র অক্ষর এবং সংখ্যা",
|
||||
"password_criteria": "একটি বড় হাতের অক্ষর, একটি ছোট হাতের অক্ষর, একটি সংখ্যা (৮টি অক্ষর)",
|
||||
"passowrd_mismatch_msg": "পাসওয়ার্ডগুলি মেলে না",
|
||||
"password_confirm": "পাসওয়ার্ড নিশ্চিত করুন",
|
||||
"registration_successful": "নিবন্ধন সফল হয়েছে",
|
||||
"registration_successful_message": "অনুগ্রহ করে আপনার নতুন পরিচয়পত্র দিয়ে লগইন করুন",
|
||||
"goto_login": "লগইন পৃষ্ঠায় যান",
|
||||
"socket_exception": "অনুগ্রহ করে আপনার ইন্টারনেট সংযোগ পরীক্ষা করুন",
|
||||
"mpin_setup": "৪-সংখ্যার এমপিন সেট করুন",
|
||||
"mpin_confirm": "আপনার এমপিন নিশ্চিত করুন",
|
||||
"storage_permission_denied": "স্টোরেজ অনুমতি অস্বীকৃত হয়েছে",
|
||||
"forgot_password": "পাসওয়ার্ড ভুলে গেছেন",
|
||||
"forgot_password_search_user": "আপনার সিআইএফ নম্বর লিখুন",
|
||||
"forgot_password_success": "রিসেট সফল হয়েছে",
|
||||
"forgot_password_create": "আপনার নতুন পাসওয়ার্ড লিখুন",
|
||||
"new_password": "নতুন পাসওয়ার্ড",
|
||||
"security": "নিরাপত্তা",
|
||||
"verify_mpin": "আপনার এমপিন যাচাই করুন"
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
{
|
||||
"@@locale": "en",
|
||||
"app_title": "mApp",
|
||||
"ipks": "IPKS",
|
||||
"fingerprint_reason": "Authenticate to start app",
|
||||
"@fingerprint_reason": {},
|
||||
"m_pin_entry_prompt": "Enter your mPIN",
|
||||
"register_prompt": "Register?",
|
||||
"try_another_way": "Try another way",
|
||||
"username": "Username",
|
||||
"password": "Password",
|
||||
"login": "Login",
|
||||
"register": "Register",
|
||||
"mobile_number": "Mobile Number",
|
||||
"aadhaar_number": "Aadhaar Number",
|
||||
"date_of_birth": "Date of Birth",
|
||||
"pacs_id": "PACS id",
|
||||
"view_full_kyc": "View full KYC",
|
||||
"account_summary": "Account Summary",
|
||||
"account_statement": "Account Statement",
|
||||
"customer_details": "Customer Details",
|
||||
"home": "Home",
|
||||
"details": "Details",
|
||||
"statement": "Statement",
|
||||
"no_of_active_accounts": "Number of active accounts",
|
||||
"pan_number": "PAN Number",
|
||||
"mirror_acct_no": "Mirror Account Number",
|
||||
"cif": "CIF",
|
||||
"product_name": "Product Name",
|
||||
"acct_opening_dt": "Account Opening Date",
|
||||
"account_status": "Account Status",
|
||||
"available_bal": "Available Balance",
|
||||
"interest_rate": "Interest Rate",
|
||||
"acct_type": "Account Type",
|
||||
"acct_no": "Account Number",
|
||||
"date_range": "Date Range",
|
||||
"amount_range": "Amount Range",
|
||||
"save": "Save",
|
||||
"min": "Min",
|
||||
"max": "Max",
|
||||
"min_amt": "Min Amount",
|
||||
"max_amt": "Max Amount",
|
||||
"customer_no_search_message": "Please enter your IPKS customer number. Your customer number is used to search your details in the IPKS database.",
|
||||
"search": "Search",
|
||||
"details_verification_message": "Please verify your details.",
|
||||
"customer_no": "Customer Number",
|
||||
"name": "Name",
|
||||
"email": "Email",
|
||||
"pacs_name": "PACS Name",
|
||||
"not_you_prompt": "Not You?",
|
||||
"next": "Next",
|
||||
"otp_verification_message": "An OTP message has been sent to your registered mobile number {masked_phone_number}. Enter it below to verify your phone number.",
|
||||
"@otp_verification_message": {
|
||||
"placeholders": {
|
||||
"masked_phone_number": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"otp": "OTP",
|
||||
"resend_otp_prompt": "Resend OTP?",
|
||||
"new_credentials_message": "Please create your new username and password for mApp",
|
||||
"repeat_password": "Repeat Password",
|
||||
"registration_success_display": "Registration success",
|
||||
"goto_login_prompt": "Go to Login Page",
|
||||
"marital_status": "Marital Status",
|
||||
"gender": "Gender",
|
||||
"address": "Address",
|
||||
"or": "OR",
|
||||
"district": "District",
|
||||
"state": "State",
|
||||
"city": "City",
|
||||
"pin_code": "Pin code",
|
||||
"linked_sb_no": "Linked SB Account Number",
|
||||
"farmer_type": "Farmer Type",
|
||||
"guardian_name": "Guardian Name",
|
||||
"religion": "Religion",
|
||||
"caste": "Caste",
|
||||
"not_available": "Not Available",
|
||||
"no_accounts_found": "No Accounts Found",
|
||||
"account_holder": "Account Holder",
|
||||
"customer_name": "Customer Name",
|
||||
"sanction_amount": "Sanction Amount",
|
||||
"sanction_date": "Sanction Date",
|
||||
"disbursed_amount": "Disbursed Amount",
|
||||
"interest_outstanding": "Interest Outstanding",
|
||||
"principal_outstanding": "Principal Outstanding",
|
||||
"interest_paid": "Interest Paid",
|
||||
"principal_paid": "Principal Paid",
|
||||
"emi_amount": "EMI Amount",
|
||||
"due_date": "Due Date",
|
||||
"last_repayment_date": "Last Repayment Date",
|
||||
"interest_description": "Interest Description",
|
||||
"total_interest_outstanding": "Total Interest Outstanding",
|
||||
"total_interest_accrued": "Total Interest Accrued",
|
||||
"total_interest_paid": "Total Interest Paid",
|
||||
"loan_type": "Loan Type",
|
||||
"old_account_number": "Old Account Number",
|
||||
"penal_interest_rate": "Penal Interest Rate",
|
||||
"cbs_account_number": "CBS Account Number",
|
||||
"nominee_name": "Nominee Name",
|
||||
"open_date": "Open Date",
|
||||
"interest_available": "Interest Available",
|
||||
"interest_from_date": "Interest From Date",
|
||||
"interest_to_date": "Interest To Date",
|
||||
"term_value": "Term Value",
|
||||
"maturity_value": "Maturity Value",
|
||||
"maturity_date": "Maturity Date",
|
||||
"term_start_date": "Term Start Date",
|
||||
"term_end_date": "Term End Date",
|
||||
"interest_projected": "Interest Projected",
|
||||
"interest_capitalized": "Interest Capitalized",
|
||||
"no_of_installments_paid": "Number of Installments Paid",
|
||||
"next_due_date": "Next Due Date",
|
||||
"rd_penal_count": "RD Penal Count",
|
||||
"hold_value": "Hold Value",
|
||||
"term_length": "Term Length",
|
||||
"interest_repayment_method": "Interest Repayment Method",
|
||||
"mode_of_account": "Mode of Account",
|
||||
"secondary_cif_number": "Secondary CIF Number",
|
||||
"secondary_cif_name": "Secondary CIF Name",
|
||||
"no_statements_found": "No Statements Found",
|
||||
"date_range_exceeds_10_days": "Select duration of 10 days or less",
|
||||
"last_10_transactions": "Displaying last 10 transactions",
|
||||
"select_account_type": "Select Account Type",
|
||||
"select_account_number": "Select Account Number",
|
||||
"select_date_range": "Select Date Range",
|
||||
"please_wait": "Please wait...",
|
||||
"preferences": "Preferences",
|
||||
"everforest": "Everforest",
|
||||
"rosy": "Rosy",
|
||||
"skypeia": "Skypeia",
|
||||
"marigold": "Marigold",
|
||||
"select_language": "Select Language",
|
||||
"english": "English",
|
||||
"hindi": "Hindi",
|
||||
"bengali": "Bengali",
|
||||
"malayalam": "Malayalam",
|
||||
"dark_theme": "Dark Theme",
|
||||
"color_theme": "Color Theme",
|
||||
"language": "Language",
|
||||
"deposit": "Deposit",
|
||||
"loan": "Loan",
|
||||
"export": "Export",
|
||||
"invalid_credentials": "Invalid credentials",
|
||||
"logout": "Logout",
|
||||
"backend_ip": "Backend IP",
|
||||
"bank_branch_no": "Bank Branch Number",
|
||||
"ifsc_code": "IFSC code",
|
||||
"bank_branch_name": "Bank Branch Name",
|
||||
"search_customer_paragraph": "Please enter your IPKS customer number. Your customer number is used to search your details in the IPKS database",
|
||||
"invalid_customer_no": "Invalid customer number",
|
||||
"searching": "Searching",
|
||||
"invalid_otp": "Invalid OTP",
|
||||
"register_customer_message": "Please enter your new username and password for mApp",
|
||||
"username_criteria": "6 characters, only letters and digits",
|
||||
"password_criteria": "one uppercase, one lowercase, one number (8 characters)",
|
||||
"passowrd_mismatch_msg": "The passwords doesn't match",
|
||||
"password_confirm": "Confirm Password",
|
||||
"registration_successful": "Registration Successful",
|
||||
"registration_successful_message": "Please login with your new credentails",
|
||||
"goto_login": "Got to Login Page",
|
||||
"socket_exception": "Please check your internet connection",
|
||||
"mpin_setup": "Setup 4-digit MPIN",
|
||||
"mpin_confirm": "Confirm your MPIN",
|
||||
"storage_permission_denied": "Storage Persmission denied",
|
||||
"forgot_password": "Forgot Password",
|
||||
"forgot_password_search_user": "Enter your CIF number",
|
||||
"forgot_password_success": "Reset Successful",
|
||||
"forgot_password_create": "Enter your new password",
|
||||
"new_password": "New Password",
|
||||
"security": "Security",
|
||||
"verify_mpin": "Verify your MPIN"
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
{
|
||||
"@@locale": "hi",
|
||||
"app_title": "आईपीकेएस ऐप",
|
||||
"ipks": "आईपीकेएस",
|
||||
"fingerprint_reason": "ऐप शुरू करने के लिए प्रमाणित करें",
|
||||
"@fingerprint_reason": {},
|
||||
"m_pin_entry_prompt": "अपना एम पिन दर्ज करें",
|
||||
"register_prompt": "रजिस्टर करें?",
|
||||
"try_another_way": "किसी अन्य तरीके की कोशिश करें",
|
||||
"username": "उपयोगकर्ता नाम",
|
||||
"password": "पासवर्ड",
|
||||
"login": "लॉगिन",
|
||||
"register": "रजिस्टर",
|
||||
"mobile_number": "मोबाइल नंबर",
|
||||
"aadhaar_number": "आधार नंबर",
|
||||
"date_of_birth": "जन्म तिथि",
|
||||
"pacs_id": "पैक्स आईडी",
|
||||
"view_full_kyc": "पूरा केवाईसी देखें",
|
||||
"account_summary": "हिसाब सारांश",
|
||||
"account_statement": "हिसाब की बयान",
|
||||
"customer_details": "ग्राहक विवरण",
|
||||
"home": "होम",
|
||||
"details": "विवरण",
|
||||
"statement": "बयान",
|
||||
"no_of_active_accounts": "सक्रिय खातों की संख्या",
|
||||
"pan_number": "पैन नंबर",
|
||||
"mirror_acct_no": "मिरर खाता नंबर",
|
||||
"cif": "सीआईएफ",
|
||||
"product_name": "उत्पाद का नाम",
|
||||
"acct_opening_dt": "खाता खोलने की तिथि",
|
||||
"account_status": "खाता की स्थिति",
|
||||
"available_bal": "उपलब्ध शेष",
|
||||
"interest_rate": "ब्याज दर",
|
||||
"acct_type": "खाते का प्रकार",
|
||||
"acct_no": "खाता संख्या",
|
||||
"date_range": "तिथि सीमा",
|
||||
"amount_range": "राशि सीमा",
|
||||
"save": "सहेजें",
|
||||
"min": "न्यूनतम",
|
||||
"max": "अधिकतम",
|
||||
"min_amt": "न्यूनतम राशि",
|
||||
"max_amt": "अधिकतम राशि",
|
||||
"customer_no_search_message": "कृपया अपना आईपीकेएस ग्राहक संख्या दर्ज करें। आपका ग्राहक संख्या आईपीकेएस डेटाबेस में आपका विवरण खोजने के लिए उपयोग किया जाता है।",
|
||||
"search": "खोज",
|
||||
"details_verification_message": "कृपया अपना विवरण सत्यापित करें।",
|
||||
"customer_no": "ग्राहक संख्या",
|
||||
"name": "नाम",
|
||||
"email": "ईमेल",
|
||||
"pacs_name": "पैक्स का नाम",
|
||||
"not_you_prompt": "तुम नहीं?",
|
||||
"next": "अगला",
|
||||
"otp_verification_message": "एक ओटीपी संदेश आपके पंजीकृत मोबाइल नंबर {masked_phone_number} पर भेजा गया है। इसे नीचे दिए गए बॉक्स में दर्ज करके अपने फोन नंबर को सत्यापित करें।",
|
||||
"@otp_verification_message": {
|
||||
"placeholders": {
|
||||
"masked_phone_number": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"otp": "ओटीपी",
|
||||
"resend_otp_prompt": "ओटीपी पुनः भेजें?",
|
||||
"new_credentials_message": "कृपया एमएपी के लिए अपना नया उपयोगकर्ता नाम और पासवर्ड बनाएं",
|
||||
"repeat_password": "पासवर्ड दोहराएं",
|
||||
"registration_success_display": "रजिस्ट्रेशन सफलता",
|
||||
"goto_login_prompt": "लॉगिन पेज पर जाएं",
|
||||
"marital_status": "वैवाहिक स्थिति",
|
||||
"gender": "लिंग",
|
||||
"address": "पता",
|
||||
"or": "या",
|
||||
"district": "जिला",
|
||||
"state": "राज्य",
|
||||
"city": "शहर",
|
||||
"pin_code": "पिन कोड",
|
||||
"linked_sb_no": "लिंक्ड एसबी खाता नंबर",
|
||||
"farmer_type": "किसान प्रकार",
|
||||
"guardian_name": "संरक्षक का नाम",
|
||||
"religion": "धर्म",
|
||||
"caste": "जाति",
|
||||
"not_available": "उपलब्ध नहीं है",
|
||||
"no_accounts_found": "कोई खाते नहीं मिला",
|
||||
"account_holder": "खाता धारक",
|
||||
"customer_name": "ग्राहक का नाम",
|
||||
"sanction_amount": "स्वीकृत राशि",
|
||||
"sanction_date": "स्वीकृति तिथि",
|
||||
"disbursed_amount": "वितरित राशि",
|
||||
"interest_outstanding": "बकाया ब्याज",
|
||||
"principal_outstanding": "मुख्य बकाया",
|
||||
"interest_paid": "ब्याज दिया",
|
||||
"principal_paid": "मुख्य दिया",
|
||||
"emi_amount": "ईएमआई राशि",
|
||||
"due_date": "निर्धारित तिथि",
|
||||
"last_repayment_date": "अंतिम प्रतिपूर्ति तिथि",
|
||||
"interest_description": "ब्याज विवरण",
|
||||
"total_interest_outstanding": "कुल बकाया ब्याज",
|
||||
"total_interest_accrued": "कुल ब्याज बनाया गया",
|
||||
"total_interest_paid": "कुल ब्याज दिया",
|
||||
"loan_type": "ऋण प्रकार",
|
||||
"old_account_number": "पुराना खाता नंबर",
|
||||
"penal_interest_rate": "जुर्माना ब्याज दर",
|
||||
"cbs_account_number": "सीबीएस खाता नंबर",
|
||||
"nominee_name": "नामांकित नाम",
|
||||
"open_date": "खोलने की तारीख",
|
||||
"interest_available": "ब्याज उपलब्ध",
|
||||
"interest_from_date": "ब्याज तिथि से",
|
||||
"interest_to_date": "ब्याज तारीख तक",
|
||||
"term_value": "मुद्रा मूल्य",
|
||||
"maturity_value": "परिपक्ष्य मूल्य",
|
||||
"maturity_date": "परिपक्ष्य तिथि",
|
||||
"term_start_date": "अवधि प्रारंभ तिथि",
|
||||
"term_end_date": "अवधि समाप्ति तिथि",
|
||||
"interest_projected": "ब्याज परियोजित",
|
||||
"interest_capitalized": "ब्याज पुँजीबद्ध",
|
||||
"no_of_installments_paid": "भुगतान की गई किस्तों की संख्या",
|
||||
"next_due_date": "अगली निर्धारित तिथि",
|
||||
"rd_penal_count": "आरडी जुर्माना गणना",
|
||||
"hold_value": "होल्ड मूल्य",
|
||||
"term_length": "अवधि लंबाई",
|
||||
"interest_repayment_method": "ब्याज प्रतिपूर्ति विधि",
|
||||
"mode_of_account": "खाते का मोड",
|
||||
"secondary_cif_number": "द्वितीय सीआईएफ नंबर",
|
||||
"secondary_cif_name": "द्वितीय सीआईएफ नाम",
|
||||
"no_statements_found": "कोई बयान नहीं मिला",
|
||||
"date_range_exceeds_10_days": "10 दिनों से अधिक अवधि का चयन नहीं करें",
|
||||
"last_10_transactions": "अंतिम 10 लेनदेन दिखा रहा है",
|
||||
"select_account_type": "खाता प्रकार चुनें",
|
||||
"select_account_number": "खाता संख्या चुनें",
|
||||
"select_date_range": "तिथि सीमा चुनें",
|
||||
"please_wait": "कृपया प्रतीक्षा करें...",
|
||||
"preferences": "प्राथमिकताएँ",
|
||||
"everforest": "एवरफॉरेस्ट",
|
||||
"rosy": "रोसी",
|
||||
"skypeia": "स्काइपिया",
|
||||
"marigold": "मैरीगोल्ड",
|
||||
"select_language": "भाषा चुनें",
|
||||
"english": "अंग्रेज़ी",
|
||||
"hindi": "हिंदी",
|
||||
"bengali": "बंगाली",
|
||||
"malayalam": "मलयालम",
|
||||
"dark_theme": "डार्क थीम",
|
||||
"color_theme": "रंग थीम",
|
||||
"language": "भाषा",
|
||||
"deposit": "जमा",
|
||||
"loan": "ऋण",
|
||||
"export": "निर्यात",
|
||||
"invalid_credentials": "अमान्य प्रमाण पत्र",
|
||||
"logout": "लॉगआउट",
|
||||
"backend_ip": "बैकएंड आईपी",
|
||||
"bank_branch_no": "बैंक शाखा संख्या",
|
||||
"ifsc_code": "आईएफएससी कोड",
|
||||
"bank_branch_name": "बैंक शाखा का नाम",
|
||||
"search_customer_paragraph": "कृपया अपना आईपीकेएस ग्राहक नंबर दर्ज करें। आपका ग्राहक नंबर आईपीकेएस डेटाबेस में आपके विवरण खोजने के लिए उपयोग किया जाता है",
|
||||
"invalid_customer_no": "अमान्य ग्राहक संख्या",
|
||||
"searching": "खोज रहे हैं",
|
||||
"invalid_otp": "अमान्य ओटीपी",
|
||||
"register_customer_message": "कृपया एमऐप के लिए अपना नया उपयोगकर्ता नाम और पासवर्ड दर्ज करें",
|
||||
"username_criteria": "6 अक्षर, केवल अक्षर और अंक",
|
||||
"password_criteria": "एक अपरकेस, एक लोअरकेस, एक अंक (8 अक्षर)",
|
||||
"passowrd_mismatch_msg": "पासवर्ड मेल नहीं खाते",
|
||||
"password_confirm": "पासवर्ड की पुष्टि करें",
|
||||
"registration_successful": "पंजीकरण सफल",
|
||||
"registration_successful_message": "कृपया अपने नए प्रमाण पत्रों से लॉगिन करें",
|
||||
"goto_login": "लॉगिन पेज पर जाएं",
|
||||
"socket_exception": "कृपया अपना इंटरनेट कनेक्शन जांचें",
|
||||
"mpin_setup": "4-अंकों का एम-पिन सेट करें",
|
||||
"mpin_confirm": "अपने एम-पिन की पुष्टि करें",
|
||||
"storage_permission_denied": "स्टोरेज अनुमति अस्वीकृत",
|
||||
"forgot_password": "पासवर्ड भूल गए",
|
||||
"forgot_password_search_user": "अपना सीआईएफ नंबर दर्ज करें",
|
||||
"forgot_password_success": "रीसेट सफल",
|
||||
"forgot_password_create": "अपना नया पासवर्ड दर्ज करें",
|
||||
"new_password": "नया पासवर्ड",
|
||||
"security": "सुरक्षा",
|
||||
"verify_mpin": "अपना एम-पिन सत्यापित करें"
|
||||
}
|
@ -1,174 +0,0 @@
|
||||
{
|
||||
"@@locale": "ml",
|
||||
"app_title": "ഐപികെഎസ് ആപ്പ്",
|
||||
"ipks": "ഐപികെഎസ്",
|
||||
"fingerprint_reason": "ആപ്പ് ആരംഭിക്കുകയാണ് പ്രമാണിക്കുക",
|
||||
"@fingerprint_reason": {},
|
||||
"m_pin_entry_prompt": "നിങ്ങളുടെ എം പിൻ നൽകുക",
|
||||
"register_prompt": "രജിസ്റ്റർ ചെയ്യുക?",
|
||||
"try_another_way": "മറ്റൊരു വഴി പരീക്ഷിക്കുക",
|
||||
"username": "ഉപയോക്തൃനാമം",
|
||||
"password": "പാസ്വേഡ്",
|
||||
"login": "ലോഗിൻ",
|
||||
"register": "രജിസ്റ്റർ",
|
||||
"mobile_number": "മൊബൈൽ നമ്പർ",
|
||||
"aadhaar_number": "ആധാർ നമ്പർ",
|
||||
"date_of_birth": "ജനന തീയതി",
|
||||
"pacs_id": "പക്സ് ഐഡി",
|
||||
"view_full_kyc": "പൂർണ്ണമായി KYC കാണുക",
|
||||
"account_summary": "അക്കൗണ്ട് സംഗ്രഹം",
|
||||
"account_statement": "അക്കൗണ്ട് സ്റ്റേറ്റ്മെന്റ്",
|
||||
"customer_details": "ഗ്രാഹക വിവരങ്ങൾ",
|
||||
"home": "ഹോം",
|
||||
"details": "വിശദങ്ങൾ",
|
||||
"statement": "സ്റ്റേറ്റ്മെന്റ്",
|
||||
"no_of_active_accounts": "സജീവ അക്കൗണ്ടുകൾക്കായി നിലവിലെ അക്കൗണ്ടുകൾ",
|
||||
"pan_number": "പാൻ നമ്പർ",
|
||||
"mirror_acct_no": "മിറർ അക്കൗണ്ട് നമ്പർ",
|
||||
"cif": "സിഐഎഫ്",
|
||||
"product_name": "ഉൽപ്പന്നത്തിന്റെ പേര്",
|
||||
"acct_opening_dt": "അക്കൗണ്ട് തുറക്കിയ തീയതി",
|
||||
"account_status": "അക്കൗണ്ട് സ്റ്റാറ്റസ്",
|
||||
"available_bal": "ലഭ്യമായ ബാലൻസ്",
|
||||
"interest_rate": "ബായാജ് വരുമാനം",
|
||||
"acct_type": "അക്കൗണ്ട് തരം",
|
||||
"acct_no": "അക്കൗണ്ട് നമ്പർ",
|
||||
"date_range": "തീയതി ശ്രേണി",
|
||||
"amount_range": "രൂപ ശ്രേണി",
|
||||
"save": "സേവ്",
|
||||
"min": "അതിന്റെ",
|
||||
"max": "പരമാവധി",
|
||||
"min_amt": "അതിന്റെ തിരഞ്ഞെടുക്കണം",
|
||||
"max_amt": "പരമാവധി തിരഞ്ഞെടുക്കണം",
|
||||
"customer_no_search_message": "ദയവായി നിങ്ങളുടെ ഐപികെഎസ് ഗ്രാഹക നമ്പർ നൽകുക. ആപ്പ് ഡാറ്റാബേസിൽ നിങ്ങളുടെ വിവരങ്ങൾ തിരയുന്നതിനായി നിങ്ങളുടെ ഗ്രാഹക നമ്പർ ഉപയോഗിക്കുന്നു.",
|
||||
"search": "തിരയുക",
|
||||
"details_verification_message": "ദയവായി നിങ്ങളുടെ വിശദങ്ങൾ പരിശോധിക്കുക.",
|
||||
"customer_no": "ഗ്രാഹക നമ്പർ",
|
||||
"name": "പേര്",
|
||||
"email": "ഇമെയിൽ",
|
||||
"pacs_name": "പക്സ് പേര്",
|
||||
"not_you_prompt": "നിന്ന് അല്ല?",
|
||||
"next": "അടുത്തത്",
|
||||
"otp_verification_message": "ഒരു OTP സന്ദേശം നിങ്ങളുടെ രജിസ്റ്റർ ചെയ്യപ്പെട്ട മൊബൈൽ നമ്പറിലേക്ക് {masked_phone_number} അയച്ചിരിക്കുന്നു. നിങ്ങൾക്ക് ഫോൺ നമ്പറിനെ പരിശോധിക്കാൻ അതിനു താഴെ നൽകുന്ന ബോക്സിൽ അതിൽ നൽകുക.",
|
||||
"@otp_verification_message": {
|
||||
"placeholders": {
|
||||
"masked_phone_number": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"otp": "ഓടിപി",
|
||||
"resend_otp_prompt": "OTP പുനഃക്രമീകരിക്കുക?",
|
||||
"new_credentials_message": "ഐപികെഎസ് ആപ്പിനായി നിങ്ങളുടെ പുതിയ ഉപയോക്തൃനാമം മറികടക്കുക",
|
||||
"repeat_password": "പാസ്വേഡ് പുനരാക്ഷരിക്കുക",
|
||||
"registration_success_display": "രജിസ്ട്രേഷൻ വിജയം",
|
||||
"goto_login_prompt": "ലോഗിൻ പേജിലേക്ക് പോകുക",
|
||||
"marital_status": "വിവാഹിത സ്ഥിതി",
|
||||
"gender": "ലിംഗം",
|
||||
"address": "വിലാസം",
|
||||
"or": "അഥവാ",
|
||||
"district": "ജില്ല",
|
||||
"state": "സംസ്ഥാനം",
|
||||
"city": "നഗരം",
|
||||
"pin_code": "പിൻ കോഡ്",
|
||||
"linked_sb_no": "ലിങ്ക്ഡ് എസ്ബി അക്കൗണ്ട് നമ്പർ",
|
||||
"farmer_type": "കൃഷിക്കാർ തരം",
|
||||
"guardian_name": "ഗാർഡിയൻ പേര്",
|
||||
"religion": "മതം",
|
||||
"caste": "ജാതി",
|
||||
"not_available": "ലഭ്യമല്ല",
|
||||
"no_accounts_found": "അക്കൗണ്ടുകൾ കണ്ടെത്തിയില്ല",
|
||||
"account_holder": "അക്കൗണ്ട് ഹോൾഡർ",
|
||||
"customer_name": "ഗ്രാഹകനാമം",
|
||||
"sanction_amount": "അനുവദിച്ച തുക",
|
||||
"sanction_date": "അനുവദിച്ച തീയതി",
|
||||
"disbursed_amount": "പിന്നീട് പിഴച്ച തുക",
|
||||
"interest_outstanding": "ബായാജ് അടുപ്പുകൾ",
|
||||
"principal_outstanding": "പ്രധാന അടുപ്പ്",
|
||||
"interest_paid": "ബായാജ് ചെലവ്",
|
||||
"principal_paid": "പ്രധാന ചെലവ്",
|
||||
"emi_amount": "EMI തുക",
|
||||
"due_date": "നിർബന്ധമായ തീയതി",
|
||||
"last_repayment_date": "അവസാന തുക തീയതി",
|
||||
"interest_description": "ബായാജ് വിവരണം",
|
||||
"total_interest_outstanding": "മൊത്ത ബായാജ് അടുപ്പുകൾ",
|
||||
"total_interest_accrued": "മൊത്ത ബായാജ് അക്ക്രൂട്ട്",
|
||||
"total_interest_paid": "മൊത്ത ബായാജ് ചെലവ്",
|
||||
"loan_type": "വായ്പ തരം",
|
||||
"old_account_number": "പഴയ അക്കൗണ്ട് നമ്പർ",
|
||||
"penal_interest_rate": "ശിക്ഷാ ബായാജ് വരുമാനം",
|
||||
"cbs_account_number": "സിബിഎസ് അക്കൗണ്ട് നമ്പർ",
|
||||
"nominee_name": "നോമിനീ പേര്",
|
||||
"open_date": "തുറന്ന തീയതി",
|
||||
"interest_available": "ബായാജ് ലഭ്യമാണ്",
|
||||
"interest_from_date": "ബായാജ് തീയതി മുതൽ",
|
||||
"interest_to_date": "ബായാജ് തീയതി വരെ",
|
||||
"term_value": "അവധി മൂല്യം",
|
||||
"maturity_value": "പരിപാലന മൂല്യം",
|
||||
"maturity_date": "പരിപാലന തീയതി",
|
||||
"term_start_date": "അവധി തുടക്കം തീയതി",
|
||||
"term_end_date": "അവധി അവസാനം തീയതി",
|
||||
"interest_projected": "ബായാജ് പ്രൊജക്ടുചെയ്യൽ",
|
||||
"interest_capitalized": "ബായാജ് ക്യാപിറ്റലൈസ്ഡ്",
|
||||
"no_of_installments_paid": "പിന്നീട് നടത്തിയ കിസ്തുകൾക്കായി നിരക്കുകൾ",
|
||||
"next_due_date": "അടുത്ത നിർബന്ധ തീയതി",
|
||||
"rd_penal_count": "ആർഡി പെനല് എണ്ണം",
|
||||
"hold_value": "ഹോൾഡ് മൂല്യം",
|
||||
"term_length": "അവധി നീളം",
|
||||
"interest_repayment_method": "ബായാജ് തിരിച്ചറിയൽ രീതി",
|
||||
"mode_of_account": "അക്കൗണ്ട് മോഡ്",
|
||||
"secondary_cif_number": "സെക്കന്ററി സിഐഎഫ് നമ്പർ",
|
||||
"secondary_cif_name": "സെക്കന്ററി സിഐഎഫ് പേര്",
|
||||
"no_statements_found": "സ്റ്റേറ്റ്മെന്റുകൾ കണ്ടെത്തിയില്ല",
|
||||
"date_range_exceeds_10_days": "10 ദിവസങ്ങൾക്ക് അധികം തീയതി ശ്രേണി തിരഞ്ഞെടുക്കരുത്",
|
||||
"last_10_transactions": "അവസാന 10 ലിങ്കുകൾ പ്രദർശിപ്പിക്കുന്നു",
|
||||
"select_account_type": "അക്കൗണ്ട് തരം തിരഞ്ഞെടുക്കുക",
|
||||
"select_account_number": "അക്കൗണ്ട് നമ്പർ തിരഞ്ഞെടുക്കുക",
|
||||
"select_date_range": "തീയതി ശ്രേണി തിരഞ്ഞെടുക്കുക",
|
||||
"please_wait": "ദയവായി കാത്തിരിക്കുക...",
|
||||
"preferences": "മൊത്തത്തിന്റെ അഭിരുചികൾ",
|
||||
"everforest": "എവർഫോറസ്റ്റ്",
|
||||
"rosy": "റോസി",
|
||||
"skypeia": "സ്കൈപ്പിയ",
|
||||
"marigold": "മാരിഗോൾഡ്",
|
||||
"select_language": "ഭാഷ തിരഞ്ഞെടുക്കുക",
|
||||
"english": "ഇംഗ്ലീഷ്",
|
||||
"hindi": "ഹിന്ദി",
|
||||
"bengali": "ബംഗാളി",
|
||||
"malayalam": "മലയാളം",
|
||||
"dark_theme": "കറുത്ത തീം",
|
||||
"color_theme": "നിറ തീം",
|
||||
"language": "ഭാഷ",
|
||||
"deposit": "ഡപ്പോസിറ്റ്",
|
||||
"loan": "വായ്പ",
|
||||
"export": "കയറ്റുമതി ചെയ്യുക",
|
||||
"invalid_credentials": "അസാധുവായ ക്രെഡൻഷ്യലുകൾ",
|
||||
"logout": "ലോഗ്ഔട്ട്",
|
||||
"backend_ip": "ബാക്ക്എൻഡ് ഐപി",
|
||||
"bank_branch_no": "ബാങ്ക് ശാഖ നമ്പർ",
|
||||
"ifsc_code": "ഐഎഫ്എസ്സി കോഡ്",
|
||||
"bank_branch_name": "ബാങ്ക് ശാഖയുടെ പേര്",
|
||||
"search_customer_paragraph": "ദയവായി നിങ്ങളുടെ ഐപികെഎസ് ഉപഭോക്താവ് നമ്പർ നൽകുക. ഐപികെഎസ് ഡാറ്റാബേസിൽ നിങ്ങളുടെ വിശദാംശങ്ങൾ തിരയാൻ ഉപഭോക്താവ് നമ്പർ ഉപയോഗിക്കുന്നു",
|
||||
"invalid_customer_no": "അസാധുവായ ഉപഭോക്താവ് നമ്പർ",
|
||||
"searching": "തിരയുന്നു",
|
||||
"invalid_otp": "അസാധുവായ ഒറ്റത്തവണ പാസ്വേഡ്",
|
||||
"register_customer_message": "ദയവായി mApp-നായി നിങ്ങളുടെ പുതിയ ഉപയോക്തൃനാമവും പാസ്വേഡും നൽകുക",
|
||||
"username_criteria": "6 അക്ഷരങ്ങൾ, അക്ഷരങ്ങളും അക്കങ്ങളും മാത്രം",
|
||||
"password_criteria": "ഒരു അപ്പർകേസ്, ഒരു ലോവർകേസ്, ഒരു നമ്പർ (8 അക്ഷരങ്ങൾ)",
|
||||
"passowrd_mismatch_msg": "പാസ്വേഡുകൾ പൊരുത്തപ്പെടുന്നില്ല",
|
||||
"password_confirm": "പാസ്വേഡ് സ്ഥിരീകരിക്കുക",
|
||||
"registration_successful": "രജിസ്ട്രേഷൻ വിജയകരമായി",
|
||||
"registration_successful_message": "ദയവായി നിങ്ങളുടെ പുതിയ ക്രെഡൻഷ്യലുകൾ ഉപയോഗിച്ച് ലോഗിൻ ചെയ്യുക",
|
||||
"goto_login": "ലോഗിൻ പേജിലേക്ക് പോകുക",
|
||||
"socket_exception": "ദയവായി നിങ്ങളുടെ ഇന്റർനെറ്റ് കണക്ഷൻ പരിശോധിക്കുക",
|
||||
"mpin_setup": "4-അക്ക എംപിൻ സജ്ജമാക്കുക",
|
||||
"mpin_confirm": "നിങ്ങളുടെ എംപിൻ സ്ഥിരീകരിക്കുക",
|
||||
"storage_permission_denied": "സ്റ്റോറേജ് അനുമതി നിഷേധിച്ചു",
|
||||
"forgot_password": "പാസ്വേഡ് മറന്നോ",
|
||||
"forgot_password_search_user": "നിങ്ങളുടെ സിഐഎഫ് നമ്പർ നൽകുക",
|
||||
"forgot_password_success": "പുനഃസജ്ജീകരണം വിജയകരമായി",
|
||||
"forgot_password_create": "നിങ്ങളുടെ പുതിയ പാസ്വേഡ് നൽകുക",
|
||||
"new_password": "പുതിയ പാസ്വേഡ്",
|
||||
"security": "സുരക്ഷ",
|
||||
"verify_mpin": "നിങ്ങളുടെ എംപിൻ പരിശോധിക്കുക"
|
||||
}
|
@ -1,7 +1,5 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:kmobile/src/preferences/preferences_provider.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'di/injection.dart';
|
||||
import 'app.dart';
|
||||
|
||||
@ -17,7 +15,5 @@ void main() async {
|
||||
// Initialize dependencies
|
||||
await setupDependencies();
|
||||
|
||||
runApp(MultiProvider(providers: [
|
||||
ChangeNotifierProvider(create: (_) => PreferencesProvider()),
|
||||
], child: const KMobile()));
|
||||
runApp(const KMobile());
|
||||
}
|
||||
|
@ -1,70 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:kmobile/utils/theme/color/color_scheme.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
class ColorDialog extends StatelessWidget {
|
||||
const ColorDialog({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SimpleDialog(
|
||||
title: const Text('Select Theme'),
|
||||
children: <Widget>[
|
||||
SimpleDialogOption(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, KMobileColorScheme.everforest);
|
||||
},
|
||||
child: ListTile(
|
||||
leading: const Icon(
|
||||
Symbols.circle,
|
||||
color: Colors.greenAccent,
|
||||
fill: 1.0,
|
||||
),
|
||||
title: Text(AppLocalizations.of(context)!.everforest),
|
||||
),
|
||||
),
|
||||
SimpleDialogOption(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, KMobileColorScheme.rosy);
|
||||
},
|
||||
child: ListTile(
|
||||
leading: const Icon(
|
||||
Symbols.circle,
|
||||
color: Colors.pinkAccent,
|
||||
fill: 1.0,
|
||||
),
|
||||
title: Text(AppLocalizations.of(context)!.rosy),
|
||||
),
|
||||
),
|
||||
SimpleDialogOption(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, KMobileColorScheme.skypeia);
|
||||
},
|
||||
child: ListTile(
|
||||
leading: const Icon(
|
||||
Symbols.circle,
|
||||
color: Colors.lightBlueAccent,
|
||||
fill: 1.0,
|
||||
),
|
||||
title: Text(AppLocalizations.of(context)!.skypeia),
|
||||
),
|
||||
),
|
||||
SimpleDialogOption(
|
||||
onPressed: () {
|
||||
Navigator.pop(context, KMobileColorScheme.marigold);
|
||||
},
|
||||
child: ListTile(
|
||||
leading: const Icon(
|
||||
Symbols.circle,
|
||||
color: Colors.amberAccent,
|
||||
fill: 1.0,
|
||||
),
|
||||
title: Text(AppLocalizations.of(context)!.marigold),
|
||||
),
|
||||
),
|
||||
// const Divider(height: 0),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
@ -1,31 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
class LanguageDialog extends StatelessWidget {
|
||||
const LanguageDialog({super.key});
|
||||
|
||||
String getLocaleName(BuildContext context, String code) {
|
||||
Map<String, String> localeCodeMap = {
|
||||
'en': AppLocalizations.of(context)!.english,
|
||||
'bn': AppLocalizations.of(context)!.bengali,
|
||||
'ml': AppLocalizations.of(context)!.malayalam,
|
||||
'hi': AppLocalizations.of(context)!.hindi,
|
||||
};
|
||||
return localeCodeMap[code] ?? 'Unknown';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SimpleDialog(
|
||||
title: Text(AppLocalizations.of(context)!.select_language),
|
||||
children: AppLocalizations.supportedLocales.map(
|
||||
(locale) {
|
||||
return SimpleDialogOption(
|
||||
onPressed: () => Navigator.pop(context, locale),
|
||||
child: ListTile(title: Text(getLocaleName(context, locale.languageCode))),
|
||||
);
|
||||
},
|
||||
).toList(),
|
||||
);
|
||||
}
|
||||
}
|
@ -1,73 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:kmobile/src/preferences/color_dialog.dart';
|
||||
import 'package:kmobile/src/preferences/language_dialog.dart';
|
||||
import 'package:kmobile/src/preferences/preferences_provider.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
class Preference extends StatelessWidget {
|
||||
const Preference({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
PreferencesProvider preferencesProvider =
|
||||
Provider.of<PreferencesProvider>(context);
|
||||
return Scaffold(
|
||||
backgroundColor: Theme.of(context).colorScheme.background,
|
||||
appBar: AppBar(
|
||||
title: Text(AppLocalizations.of(context)!.preferences),
|
||||
),
|
||||
body: ListView(
|
||||
children: [
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context)!.dark_theme),
|
||||
trailing: Switch(
|
||||
value: preferencesProvider.themeMode == ThemeMode.dark,
|
||||
onChanged: (value) {
|
||||
preferencesProvider.themeMode =
|
||||
value ? ThemeMode.dark : ThemeMode.light;
|
||||
}),
|
||||
),
|
||||
const Divider(height: 0),
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context)!.color_theme),
|
||||
onTap: () => _changeCurrentTheme(context),
|
||||
),
|
||||
const Divider(height: 0),
|
||||
ListTile(
|
||||
title: Text(AppLocalizations.of(context)!.language),
|
||||
onTap: () => _changeCurrentLocale(context),
|
||||
)
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> _changeCurrentTheme(BuildContext context) async {
|
||||
Map<ThemeMode, ColorScheme> selectedColorScheme = await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return const ColorDialog();
|
||||
},
|
||||
);
|
||||
if (context.mounted) {
|
||||
PreferencesProvider provider =
|
||||
Provider.of<PreferencesProvider>(context, listen: false);
|
||||
provider.colorScheme = selectedColorScheme;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _changeCurrentLocale(BuildContext context) async {
|
||||
Locale selectedLocale = await showDialog(
|
||||
context: context,
|
||||
builder: (BuildContext context) {
|
||||
return const LanguageDialog();
|
||||
},
|
||||
);
|
||||
if (context.mounted) {
|
||||
PreferencesProvider provider =
|
||||
Provider.of<PreferencesProvider>(context, listen: false);
|
||||
provider.locale = selectedLocale;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,25 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:kmobile/utils/theme/color/color_scheme.dart';
|
||||
|
||||
class PreferencesProvider with ChangeNotifier {
|
||||
ThemeMode _themeMode = ThemeMode.light;
|
||||
ThemeMode get themeMode => _themeMode;
|
||||
set themeMode(ThemeMode currentMode) {
|
||||
_themeMode = currentMode;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Map<ThemeMode, ColorScheme> _colorScheme = KMobileColorScheme.everforest;
|
||||
Map<ThemeMode, ColorScheme> get colorScheme => _colorScheme;
|
||||
set colorScheme(Map<ThemeMode, ColorScheme> currentColorScheme) {
|
||||
_colorScheme = currentColorScheme;
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
Locale _locale = const Locale.fromSubtags(languageCode: 'en');
|
||||
Locale get locale => _locale;
|
||||
set locale(Locale currentLocale) {
|
||||
_locale = currentLocale;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
@ -1,67 +0,0 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class KMobileColorScheme {
|
||||
KMobileColorScheme._();
|
||||
|
||||
static Map<ThemeMode, ColorScheme> everforest = {
|
||||
ThemeMode.light: ColorScheme.fromSeed(
|
||||
seedColor: const Color(0xFF008442),
|
||||
brightness: Brightness.light,
|
||||
primary: const Color(0xff2C6A45),
|
||||
onPrimary: const Color(0xffffffff),
|
||||
primaryContainer: const Color(0xffB0F1C3),
|
||||
onPrimaryContainer: const Color(0xFF00210F),
|
||||
secondary: const Color(0xFF4F6354),
|
||||
onSecondary: const Color(0xFFFFFFFF),
|
||||
error: const Color(0xFFBA1A1A),
|
||||
onError: const Color(0xFFFFFFFF),
|
||||
background: const Color(0xFFF6FBF3),
|
||||
onBackground: const Color(0xFF181D19),
|
||||
surface: const Color(0xFFF6FBF3),
|
||||
onSurface: const Color(0xFF181D19),
|
||||
),
|
||||
ThemeMode.dark: ColorScheme.fromSeed(
|
||||
seedColor: const Color(0xFF008442),
|
||||
brightness: Brightness.dark,
|
||||
primary: const Color(0xff95D5A8),
|
||||
onPrimary: const Color(0xff00391E),
|
||||
primaryContainer: const Color(0xff0E512F),
|
||||
onPrimaryContainer: const Color(0xFFB0F1C3),
|
||||
secondary: const Color(0xFFB6CCB9),
|
||||
onSecondary: const Color(0xFF213527),
|
||||
error: const Color(0xFFFFB4AB),
|
||||
onError: const Color(0xFF690005),
|
||||
background: const Color(0xFF0F1511),
|
||||
onBackground: const Color(0xFFDFE4DD),
|
||||
surface: const Color(0xFF0F1511),
|
||||
onSurface: const Color(0xFFDFE4DD),
|
||||
),
|
||||
};
|
||||
|
||||
static Map<ThemeMode, ColorScheme> rosy = {
|
||||
ThemeMode.light: ColorScheme.fromSeed(
|
||||
seedColor: const Color.fromARGB(255, 132, 0, 66),
|
||||
),
|
||||
ThemeMode.dark: ColorScheme.fromSeed(
|
||||
seedColor: const Color.fromARGB(255, 132, 0, 66),
|
||||
brightness: Brightness.dark),
|
||||
};
|
||||
|
||||
static Map<ThemeMode, ColorScheme> skypeia = {
|
||||
ThemeMode.light: ColorScheme.fromSeed(
|
||||
seedColor: const Color.fromARGB(255, 0, 62, 132),
|
||||
),
|
||||
ThemeMode.dark: ColorScheme.fromSeed(
|
||||
seedColor: const Color.fromARGB(255, 0, 62, 132),
|
||||
brightness: Brightness.dark),
|
||||
};
|
||||
|
||||
static Map<ThemeMode, ColorScheme> marigold = {
|
||||
ThemeMode.light: ColorScheme.fromSeed(
|
||||
seedColor: const Color.fromARGB(255, 123, 132, 0),
|
||||
),
|
||||
ThemeMode.dark: ColorScheme.fromSeed(
|
||||
seedColor: const Color.fromARGB(255, 123, 132, 0),
|
||||
brightness: Brightness.dark),
|
||||
};
|
||||
}
|
329
pubspec.lock
329
pubspec.lock
@ -1,14 +1,6 @@
|
||||
# Generated by pub
|
||||
# See https://dart.dev/tools/pub/glossary#lockfile
|
||||
packages:
|
||||
args:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: args
|
||||
sha256: d0481093c50b1da8910eb0bb301626d4d8eb7284aa739614d2b394ee09e3ea04
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.7.0"
|
||||
async:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -33,14 +25,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.2"
|
||||
chalkdart:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: chalkdart
|
||||
sha256: "7ffc6bd39c81453fb9ba8dbce042a9c960219b75ea1c07196a7fa41c2fab9e86"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.5"
|
||||
characters:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -113,14 +97,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.4"
|
||||
file:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: file
|
||||
sha256: a3b4f84adafef897088c160faf7dfffb7696046cb13ae90b508c2cbc95d3b8d4
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "7.0.1"
|
||||
flutter:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
@ -130,10 +106,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_bloc
|
||||
sha256: cf51747952201a455a1c840f8171d273be009b932c75093020f9af64f2123e38
|
||||
sha256: "1046d719fbdf230330d3443187cc33cc11963d15c9089f6cc56faa42a4c5f0cc"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "9.1.1"
|
||||
version: "9.1.0"
|
||||
flutter_lints:
|
||||
dependency: "direct dev"
|
||||
description:
|
||||
@ -142,19 +118,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.2"
|
||||
flutter_localizations:
|
||||
dependency: "direct main"
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
flutter_plugin_android_lifecycle:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_plugin_android_lifecycle
|
||||
sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.0.28"
|
||||
flutter_secure_storage:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
@ -167,10 +130,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: flutter_secure_storage_linux
|
||||
sha256: be76c1d24a97d0b98f8b54bce6b481a380a6590df992d0098f868ad54dc8f688
|
||||
sha256: bf7404619d7ab5c0a1151d7c4e802edad8f33535abfbeff2f9e1fe1274e2d705
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.2.3"
|
||||
version: "1.2.2"
|
||||
flutter_secure_storage_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -203,22 +166,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.2"
|
||||
flutter_svg:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_svg
|
||||
sha256: d44bf546b13025ec7353091516f6881f1d4c633993cb109c3916c3a0159dadf1
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.0"
|
||||
flutter_swipe_button:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: flutter_swipe_button
|
||||
sha256: "67df9f1121ad10429b900a723366403441634ebb2c064fd4babb7de274366a36"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
flutter_test:
|
||||
dependency: "direct dev"
|
||||
description: flutter
|
||||
@ -237,22 +184,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "8.0.3"
|
||||
glob:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: glob
|
||||
sha256: c3f1ee72c96f8f78935e18aa8cecced9ab132419e8625dc187e1c2408efc20de
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.1.3"
|
||||
http:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: http
|
||||
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
http_parser:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -265,10 +196,10 @@ packages:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: intl
|
||||
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
|
||||
sha256: "3df61194eb431efc39c4ceba583b95633a403f46c9fd341e550ce0bfa50e9aa5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.19.0"
|
||||
version: "0.20.2"
|
||||
js:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -309,46 +240,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
local_auth:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: local_auth
|
||||
sha256: "434d854cf478f17f12ab29a76a02b3067f86a63a6d6c4eb8fbfdcfe4879c1b7b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
local_auth_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: local_auth_android
|
||||
sha256: "63ad7ca6396290626dc0cb34725a939e4cfe965d80d36112f08d49cf13a8136e"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.49"
|
||||
local_auth_darwin:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: local_auth_darwin
|
||||
sha256: "630996cd7b7f28f5ab92432c4b35d055dd03a747bc319e5ffbb3c4806a3e50d2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.3"
|
||||
local_auth_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: local_auth_platform_interface
|
||||
sha256: "1b842ff177a7068442eae093b64abe3592f816afd2a533c0ebcdbe40f9d2075a"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.10"
|
||||
local_auth_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: local_auth_windows
|
||||
sha256: bc4e66a29b0fdf751aafbec923b5bed7ad6ed3614875d8151afe2578520b2ab5
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.0.11"
|
||||
matcher:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -365,14 +256,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "0.11.1"
|
||||
material_symbols_icons:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: material_symbols_icons
|
||||
sha256: "7c50901b39d1ad645ee25d920aed008061e1fd541a897b4ebf2c01d966dbf16b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "4.2815.1"
|
||||
meta:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -397,16 +280,8 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.9.1"
|
||||
path_parsing:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_parsing
|
||||
sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
path_provider:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider
|
||||
sha256: "50c5dd5b6e1aaf6fb3a78b33f6aa3afca52bf903a8a5298f53101fdaee55bbcd"
|
||||
@ -417,10 +292,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: path_provider_android
|
||||
sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
|
||||
sha256: "0ca7359dad67fd7063cb2892ab0c0737b2daafd807cf1acecd62374c8fae6c12"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.2.17"
|
||||
version: "2.2.16"
|
||||
path_provider_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -453,14 +328,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.0"
|
||||
petitparser:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: petitparser
|
||||
sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.0"
|
||||
platform:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -478,90 +345,18 @@ packages:
|
||||
source: hosted
|
||||
version: "2.1.8"
|
||||
provider:
|
||||
dependency: "direct main"
|
||||
dependency: transitive
|
||||
description:
|
||||
name: provider
|
||||
sha256: "4abbd070a04e9ddc287673bf5a030c7ca8b685ff70218720abab8b092f53dd84"
|
||||
sha256: "489024f942069c2920c844ee18bb3d467c69e48955a4f32d1677f71be103e310"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.1.5"
|
||||
screenshot:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: screenshot
|
||||
sha256: "63817697a7835e6ce82add4228e15d233b74d42975c143ad8cfe07009fab866b"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.0.0"
|
||||
shared_preferences:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: shared_preferences
|
||||
sha256: "6e8bf70b7fef813df4e9a36f658ac46d107db4b4cfe1048b477d4e453a8159f5"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.3"
|
||||
shared_preferences_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_android
|
||||
sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.10"
|
||||
shared_preferences_foundation:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_foundation
|
||||
sha256: "6a52cfcdaeac77cad8c97b539ff688ccfc458c007b4db12be584fbe5c0e49e03"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.5.4"
|
||||
shared_preferences_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_linux
|
||||
sha256: "580abfd40f415611503cae30adf626e6656dfb2f0cee8f465ece7b6defb40f2f"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_platform_interface
|
||||
sha256: "57cbf196c486bc2cf1f02b85784932c6094376284b3ad5779d1b1c6c6a816b80"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
shared_preferences_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_web
|
||||
sha256: c49bd060261c9a3f0ff445892695d6212ff603ef3115edbb448509d407600019
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.3"
|
||||
shared_preferences_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: shared_preferences_windows
|
||||
sha256: "94ef0f72b2d71bc3e700e025db3710911bd51a71cefb65cc609dd0d9a982e3c1"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
version: "6.1.4"
|
||||
sky_engine:
|
||||
dependency: transitive
|
||||
description: flutter
|
||||
source: sdk
|
||||
version: "0.0.0"
|
||||
social_share:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: social_share
|
||||
sha256: eb19a0f6f5a29c7bb71e5bb1991145eb52472184363b6e2da70695befd8be041
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.1"
|
||||
source_span:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -618,94 +413,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.4.0"
|
||||
url_launcher:
|
||||
dependency: "direct main"
|
||||
description:
|
||||
name: url_launcher
|
||||
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.1"
|
||||
url_launcher_android:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_android
|
||||
sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.16"
|
||||
url_launcher_ios:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_ios
|
||||
sha256: "7f2022359d4c099eea7df3fdf739f7d3d3b9faf3166fb1dd390775176e0b76cb"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.3.3"
|
||||
url_launcher_linux:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_linux
|
||||
sha256: "4e9ba368772369e3e08f231d2301b4ef72b9ff87c31192ef471b380ef29a4935"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.1"
|
||||
url_launcher_macos:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_macos
|
||||
sha256: "17ba2000b847f334f16626a574c702b196723af2a289e7a93ffcb79acff855c2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.2.2"
|
||||
url_launcher_platform_interface:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_platform_interface
|
||||
sha256: "552f8a1e663569be95a8190206a38187b531910283c3e982193e4f2733f01029"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.3.2"
|
||||
url_launcher_web:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_web
|
||||
sha256: "4bd2b7b4dc4d4d0b94e5babfffbca8eac1a126c7f3d6ecbc1a11013faa3abba2"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "2.4.1"
|
||||
url_launcher_windows:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: url_launcher_windows
|
||||
sha256: "3284b6d2ac454cf34f114e1d3319866fdd1e19cdc329999057e44ffe936cfa77"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "3.1.4"
|
||||
vector_graphics:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics
|
||||
sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.18"
|
||||
vector_graphics_codec:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_codec
|
||||
sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.13"
|
||||
vector_graphics_compiler:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: vector_graphics_compiler
|
||||
sha256: "557a315b7d2a6dbb0aaaff84d857967ce6bdc96a63dc6ee2a57ce5a6ee5d3331"
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.17"
|
||||
vector_math:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -734,10 +441,10 @@ packages:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: win32
|
||||
sha256: "329edf97fdd893e0f1e3b9e88d6a0e627128cc17cc316a8d67fda8f1451178ba"
|
||||
sha256: dc6ecaa00a7c708e5b4d10ee7bec8c270e9276dfcab1783f57e9962d7884305f
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "5.13.0"
|
||||
version: "5.12.0"
|
||||
xdg_directories:
|
||||
dependency: transitive
|
||||
description:
|
||||
@ -746,14 +453,6 @@ packages:
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "1.1.0"
|
||||
xml:
|
||||
dependency: transitive
|
||||
description:
|
||||
name: xml
|
||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
||||
url: "https://pub.dev"
|
||||
source: hosted
|
||||
version: "6.5.0"
|
||||
sdks:
|
||||
dart: ">=3.7.0 <4.0.0"
|
||||
flutter: ">=3.27.0"
|
||||
|
32
pubspec.yaml
32
pubspec.yaml
@ -41,21 +41,7 @@ dependencies:
|
||||
bloc: ^9.0.0
|
||||
flutter_bloc: ^9.1.0
|
||||
get_it: ^8.0.3
|
||||
flutter_localizations:
|
||||
sdk: flutter
|
||||
intl: any
|
||||
flutter_svg: ^2.1.0
|
||||
local_auth: ^2.3.0
|
||||
material_symbols_icons: ^4.2815.0
|
||||
shared_preferences: ^2.5.3
|
||||
url_launcher: ^6.3.1
|
||||
social_share: ^2.3.1
|
||||
screenshot: ^3.0.0
|
||||
path_provider: ^2.1.5
|
||||
flutter_swipe_button: ^2.1.3
|
||||
provider: ^6.1.5
|
||||
|
||||
|
||||
|
||||
dev_dependencies:
|
||||
flutter_test:
|
||||
@ -78,12 +64,11 @@ flutter:
|
||||
# included with your application, so that you can use the icons in
|
||||
# the material Icons class.
|
||||
uses-material-design: true
|
||||
generate: true
|
||||
|
||||
# To add assets to your application, add an assets section, like this:
|
||||
assets:
|
||||
- assets/images/kccb_logo.svg
|
||||
- assets/images/avatar.jpg
|
||||
# assets:
|
||||
# - images/a_dot_burr.jpeg
|
||||
# - images/a_dot_ham.jpeg
|
||||
|
||||
# An image asset can refer to one or more resolution-specific "variants", see
|
||||
# https://flutter.dev/assets-and-images/#resolution-aware
|
||||
@ -96,12 +81,11 @@ flutter:
|
||||
# "family" key with the font family name, and a "fonts" key with a
|
||||
# list giving the asset and other descriptors for the font. For
|
||||
# example:
|
||||
fonts:
|
||||
- family: Rubik
|
||||
fonts:
|
||||
- asset: assets/fonts/Rubik-Regular.ttf
|
||||
- asset: assets/fonts/Rubik-Bold.ttf
|
||||
weight: 700
|
||||
# fonts:
|
||||
# - family: Schyler
|
||||
# fonts:
|
||||
# - asset: fonts/Schyler-Regular.ttf
|
||||
# - asset: fonts/Schyler-Italic.ttf
|
||||
# style: italic
|
||||
# - family: Trajan Pro
|
||||
# fonts:
|
||||
|
Loading…
x
Reference in New Issue
Block a user