Localization Changes #3

This commit is contained in:
2025-08-19 11:18:25 +05:30
58 changed files with 460 additions and 363 deletions

View File

@@ -4,7 +4,6 @@ import '../../features/auth/models/auth_token.dart';
import '../../features/auth/models/auth_credentials.dart';
import '../../core/errors/exceptions.dart';
class AuthService {
final Dio _dio;
AuthService(this._dio);
@@ -15,7 +14,7 @@ class AuthService {
'/api/auth/login',
data: credentials.toJson(),
);
if (response.statusCode == 200) {
return AuthToken.fromJson(response.data);
} else {
@@ -30,7 +29,8 @@ class AuthService {
}
throw NetworkException('Network error during login');
} catch (e) {
throw UnexpectedException('Unexpected error during login: ${e.toString()}');
throw UnexpectedException(
'Unexpected error during login: ${e.toString()}');
}
}
@@ -40,7 +40,7 @@ class AuthService {
'/auth/refresh',
data: {'refresh_token': refreshToken},
);
if (response.statusCode == 200) {
return AuthToken.fromJson(response.data);
} else {
@@ -54,7 +54,7 @@ class AuthService {
Future<bool> checkTpin() async {
try {
final response = await _dio.get('/api/auth/tpin');
if (response.statusCode == 200) {
return response.data['tpinSet'] as bool;
} else {
@@ -66,7 +66,8 @@ class AuthService {
}
throw NetworkException('Network error during TPIN check');
} catch (e) {
throw UnexpectedException('Unexpected error during TPIN check: ${e.toString()}');
throw UnexpectedException(
'Unexpected error during TPIN check: ${e.toString()}');
}
}
@@ -76,7 +77,7 @@ class AuthService {
'/api/auth/tpin',
data: {'tpin': tpin},
);
if (response.statusCode != 200) {
throw AuthException('Failed to set TPIN');
}
@@ -86,8 +87,8 @@ class AuthService {
}
throw NetworkException('Network error during TPIN setup');
} catch (e) {
throw UnexpectedException('Unexpected error during TPIN setup: ${e.toString()}');
throw UnexpectedException(
'Unexpected error during TPIN setup: ${e.toString()}');
}
}
}
}

View File

@@ -22,8 +22,8 @@ class ImpsService {
throw Exception(
'RTGS transaction failed with status code: ${response.statusCode}');
}
} on DioException {
rethrow ;
} on DioException {
rethrow;
} catch (e) {
throw Exception('An unexpected error occurred: ${e.toString()}');
}

View File

@@ -7,7 +7,8 @@ class NeftService {
NeftService(this._dio);
Future<NeftResponse> processNeftTransaction(NeftTransaction transaction) async {
Future<NeftResponse> processNeftTransaction(
NeftTransaction transaction) async {
try {
await Future.delayed(const Duration(seconds: 3));
final response = await _dio.post(

View File

@@ -10,7 +10,7 @@ class PaymentService {
Future<PaymentResponse> processQuickPayWithinBank(Transfer transfer) async {
try {
await Future.delayed(const Duration(seconds: 3)); // Simulate delay
await _dio.post('/api/payment/transfer', data: transfer.toJson());
return PaymentResponse(

View File

@@ -22,8 +22,8 @@ class RtgsService {
throw Exception(
'RTGS transaction failed with status code: ${response.statusCode}');
}
} on DioException {
rethrow ;
} on DioException {
rethrow;
} catch (e) {
throw Exception('An unexpected error occurred: ${e.toString()}');
}

View File

@@ -28,4 +28,4 @@ class UserService {
throw Exception('Unexpected error: ${e.toString()}');
}
}
}
}

View File

@@ -13,7 +13,7 @@ import '../features/dashboard/screens/dashboard_screen.dart';
class AppRoutes {
// Private constructor to prevent instantiation
AppRoutes._();
// Route names
static const String splash = '/';
static const String login = '/login';
@@ -25,7 +25,7 @@ class AppRoutes {
static const String accounts = '/accounts';
static const String transactions = '/transactions';
static const String payments = '/payments';
// Route generator
static Route<dynamic> generateRoute(RouteSettings settings) {
switch (settings.name) {
@@ -35,13 +35,16 @@ class AppRoutes {
return MaterialPageRoute(builder: (_) => const LoginScreen());
case mPin:
return MaterialPageRoute(builder: (_) => const MPinScreen(mode: MPinMode.enter,));
return MaterialPageRoute(
builder: (_) => const MPinScreen(
mode: MPinMode.enter,
));
case register:
// Placeholder - create the RegisterScreen class and uncomment
// return MaterialPageRoute(builder: (_) => const RegisterScreen());
return _errorRoute();
case forgotPassword:
// Placeholder - create the ForgotPasswordScreen class and uncomment
// return MaterialPageRoute(builder: (_) => const ForgotPasswordScreen());
@@ -49,31 +52,30 @@ class AppRoutes {
case navigationScaffold:
return MaterialPageRoute(builder: (_) => const NavigationScaffold());
case dashboard:
return MaterialPageRoute(builder: (_) => const DashboardScreen());
case accounts:
// Placeholder - create the AccountsScreen class and uncomment
// return MaterialPageRoute(builder: (_) => const AccountsScreen());
return _errorRoute();
case transactions:
// Placeholder - create the TransactionsScreen class and uncomment
// return MaterialPageRoute(builder: (_) => const TransactionsScreen());
return _errorRoute();
case payments:
// Placeholder - create the PaymentsScreen class and uncomment
// return MaterialPageRoute(builder: (_) => const PaymentsScreen());
return _errorRoute();
default:
return _errorRoute();
}
}
// Error route
static Route<dynamic> _errorRoute() {
return MaterialPageRoute(builder: (_) {
@@ -87,4 +89,4 @@ class AppRoutes {
);
});
}
}
}

View File

@@ -1,6 +1,6 @@
enum ThemeType {
violet,
green,
orange,
blue,
}
violet,
green,
orange,
blue,
}

View File

@@ -30,4 +30,3 @@ class AppThemes {
}
}
}

View File

@@ -1,8 +1,8 @@
class AppException implements Exception {
final String message;
AppException(this.message);
@override
String toString() => message;
}
@@ -11,7 +11,7 @@ class NetworkException extends AppException {
NetworkException(super.message);
}
class AuthException implements Exception{
class AuthException implements Exception {
final String message;
AuthException(this.message);
@@ -21,4 +21,4 @@ class AuthException implements Exception{
class UnexpectedException extends AppException {
UnexpectedException(super.message);
}
}

View File

@@ -62,4 +62,3 @@ class Beneficiary {
return 'Beneficiary(accountNo: $accountNo, accountType: $accountType, ifscCode: $ifscCode, name: $name)';
}
}

View File

@@ -30,4 +30,3 @@ class Ifsc {
return 'IFSC(ifscCode: $ifscCode, bankName: $bankName, branchName: $branchName)';
}
}

View File

@@ -32,7 +32,7 @@ class TransferResponse {
TransferResponse({
required this.status,
required this.message,
required this.error,
required this.error,
});
factory TransferResponse.fromJson(Map<String, dynamic> json) {
@@ -42,4 +42,4 @@ class TransferResponse {
error: json['error'] as String?,
);
}
}
}

View File

@@ -10,7 +10,7 @@ class AuthRepository {
final AuthService _authService;
final UserService _userService;
final SecureStorage _secureStorage;
static const _accessTokenKey = 'access_token';
static const _tokenExpiryKey = 'token_expiry';
@@ -18,35 +18,37 @@ class AuthRepository {
Future<List<User>> login(String customerNo, String password) async {
// Create credentials and call service
final credentials = AuthCredentials(customerNo: customerNo, password: password);
final credentials =
AuthCredentials(customerNo: customerNo, password: password);
final authToken = await _authService.login(credentials);
// Save token securely
await _saveAuthToken(authToken);
// Get and save user profile
final users = await _userService.getUserDetails();
return users;
}
Future<bool> isLoggedIn() async {
final token = await _getAuthToken();
return token != null && !token.isExpired;
}
Future<String?> getAccessToken() async {
final token = await _getAuthToken();
if (token == null) return null;
return token.accessToken;
}
// Private helper methods
Future<void> _saveAuthToken(AuthToken token) async {
await _secureStorage.write(_accessTokenKey, token.accessToken);
await _secureStorage.write(_tokenExpiryKey, token.expiresAt.toIso8601String());
await _secureStorage.write(
_tokenExpiryKey, token.expiresAt.toIso8601String());
}
Future<AuthToken?> _getAuthToken() async {
final accessToken = await _secureStorage.read(_accessTokenKey);
final expiryString = await _secureStorage.read(_tokenExpiryKey);
@@ -59,4 +61,4 @@ class AuthRepository {
}
return null;
}
}
}

View File

@@ -1,7 +1,6 @@
import 'package:kmobile/data/models/transfer.dart';
import 'package:dio/dio.dart';
abstract class TransferRepository {
Future<TransferResponse> transfer(Transfer transfer);
}
@@ -25,4 +24,4 @@ class TransferRepositoryImpl implements TransferRepository {
return TransferResponse.fromJson(resp.data as Map<String, dynamic>);
}
}
}

View File

@@ -60,7 +60,7 @@ Dio _createDioClient() {
BaseOptions(
baseUrl:
'http://lb-test-mobile-banking-app-192209417.ap-south-1.elb.amazonaws.com:8080',
//'http://localhost:8081',
//'http://localhost:8081',
connectTimeout: const Duration(seconds: 5),
receiveTimeout: const Duration(seconds: 10),
headers: {

View File

@@ -4,7 +4,7 @@ class Account {
final String accountType;
final double balance;
final String currency;
Account({
required this.id,
required this.accountNumber,
@@ -12,4 +12,4 @@ class Account {
required this.balance,
required this.currency,
});
}
}

View File

@@ -87,7 +87,7 @@ class _AccountInfoScreen extends State<AccountInfoScreen> {
);
}).toList(),
),
InfoRow(
title: AppLocalizations.of(context).customerNumber,
value: selectedUser.cifNumber ?? 'N/A',

View File

@@ -294,10 +294,10 @@ class _AccountStatementScreen extends State<AccountStatementScreen> {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
TransactionDetailsScreen(transaction: tx),
),
);
builder: (_) => TransactionDetailsScreen(
transaction: tx),
),
);
},
);
},

View File

@@ -3,7 +3,7 @@ import 'package:kmobile/l10n/app_localizations.dart';
import 'package:material_symbols_icons/symbols.dart';
class TransactionDetailsScreen extends StatelessWidget {
final dynamic transaction;
final dynamic transaction;
const TransactionDetailsScreen({super.key, required this.transaction});
@@ -22,29 +22,30 @@ class TransactionDetailsScreen extends StatelessWidget {
// final file = await File('${tempDir.path}/payment_result.png').create();
// await file.writeAsBytes(pngBytes);
// await Share.shareXFiles(
// [XFile(file.path)],
// text: AppLocalizations.of(context).paymentResult,
// );
// } catch (e) {
// if (!mounted) return;
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(
// '${AppLocalizations.of(context).failedToShareScreenshot}: $e',
// ),
// ),
// );
// }
// }
// await Share.shareXFiles(
// [XFile(file.path)],
// text: AppLocalizations.of(context).paymentResult,
// );
// } catch (e) {
// if (!mounted) return;
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(
// '${AppLocalizations.of(context).failedToShareScreenshot}: $e',
// ),
// ),
// );
// }
// }
return Scaffold(
appBar: AppBar(title: Text(AppLocalizations.of(context).transactionDetails)),
appBar:
AppBar(title: Text(AppLocalizations.of(context).transactionDetails)),
body: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: [
// Absolute center for amount + icon + date + details
// Absolute center for amount + icon + date + details
Expanded(
flex: 3,
child: Center(
@@ -93,39 +94,45 @@ class TransactionDetailsScreen extends StatelessWidget {
child: ListView(
children: [
// ignore: unnecessary_cast
_buildDetailRow(AppLocalizations.of(context).transactionType as String, transaction.type ?? ""),
_buildDetailRow(AppLocalizations.of(context).transferType, transaction.name.split("/").first ?? ""),
if(transaction.name.length> 12) ... [
_buildDetailRow(AppLocalizations.of(context).utrNo, transaction.name.split("= ")[1].split(" ")[0] ?? ""),
_buildDetailRow(AppLocalizations.of(context).beneficiaryAccountNo, transaction.name.split("A/C ").last ?? "")
_buildDetailRow(
AppLocalizations.of(context).transactionType as String,
transaction.type ?? ""),
_buildDetailRow(AppLocalizations.of(context).transferType,
transaction.name.split("/").first ?? ""),
if (transaction.name.length > 12) ...[
_buildDetailRow(AppLocalizations.of(context).utrNo,
transaction.name.split("= ")[1].split(" ")[0] ?? ""),
_buildDetailRow(
AppLocalizations.of(context).beneficiaryAccountNo,
transaction.name.split("A/C ").last ?? "")
]
],
),
),
// ElevatedButton.icon(
// onPressed: _shareScreenshot,
// icon: Icon(
// Icons.share_rounded,
// color: Theme.of(context).primaryColor,
// ),
// label: Text(
// AppLocalizations.of(context).share,
// style: TextStyle(color: Theme.of(context).primaryColor),
// ),
// style: ElevatedButton.styleFrom(
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
// padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
// shape: RoundedRectangleBorder(
// side: BorderSide(color: Theme.of(context).primaryColor, width: 1),
// borderRadius: BorderRadius.circular(30),
// ),
// textStyle: const TextStyle(
// fontSize: 18,
// fontWeight: FontWeight.w600,
// color: Colors.black,
// ),
// ),
// ),
// ElevatedButton.icon(
// onPressed: _shareScreenshot,
// icon: Icon(
// Icons.share_rounded,
// color: Theme.of(context).primaryColor,
// ),
// label: Text(
// AppLocalizations.of(context).share,
// style: TextStyle(color: Theme.of(context).primaryColor),
// ),
// style: ElevatedButton.styleFrom(
// backgroundColor: Theme.of(context).scaffoldBackgroundColor,
// padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
// shape: RoundedRectangleBorder(
// side: BorderSide(color: Theme.of(context).primaryColor, width: 1),
// borderRadius: BorderRadius.circular(30),
// ),
// textStyle: const TextStyle(
// fontSize: 18,
// fontWeight: FontWeight.w600,
// color: Colors.black,
// ),
// ),
// ),
],
),
),

View File

@@ -15,4 +15,3 @@ class ThemeState extends Equatable {
@override
List<Object?> get props => [themeType];
}

View File

@@ -6,12 +6,12 @@ import 'package:equatable/equatable.dart';
class AuthToken extends Equatable {
final String accessToken;
final DateTime expiresAt;
const AuthToken({
required this.accessToken,
required this.expiresAt,
});
factory AuthToken.fromJson(Map<String, dynamic> json) {
return AuthToken(
accessToken: json['token'],
@@ -29,7 +29,8 @@ class AuthToken extends Equatable {
// Pad the payload if necessary
String normalized = base64Url.normalize(payload);
final payloadMap = json.decode(utf8.decode(base64Url.decode(normalized)));
if (payloadMap is! Map<String, dynamic> || !payloadMap.containsKey('exp')) {
if (payloadMap is! Map<String, dynamic> ||
!payloadMap.containsKey('exp')) {
throw Exception('Invalid payload');
}
final exp = payloadMap['exp'];
@@ -40,9 +41,9 @@ class AuthToken extends Equatable {
return DateTime.now().add(const Duration(hours: 1));
}
}
bool get isExpired => DateTime.now().isAfter(expiresAt);
@override
List<Object> get props => [accessToken, expiresAt];
}

View File

@@ -48,9 +48,9 @@ class LoginScreenState extends State<LoginScreen>
void _submitForm() {
if (_formKey.currentState!.validate()) {
context.read<AuthCubit>().login(
_customerNumberController.text.trim(),
_passwordController.text,
);
_customerNumberController.text.trim(),
_passwordController.text,
);
}
}
@@ -204,7 +204,8 @@ class LoginScreenState extends State<LoginScreen>
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor: Theme.of(context).primaryColorDark,
side: const BorderSide(color: Colors.black, width: 1),
elevation: 0,

View File

@@ -198,7 +198,9 @@ class _MPinScreenState extends State<MPinScreen> {
key == '<' ? '' : key,
style: TextStyle(
fontSize: 20,
color: key == 'Enter' ? Theme.of(context).primaryColor : Colors.black,
color: key == 'Enter'
? Theme.of(context).primaryColor
: Colors.black,
),
),
),

View File

@@ -19,11 +19,8 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
// Automatically go to logizn after 4 seconds
Timer(const Duration(seconds: 4), () {
widget.onContinue();
}
);
});
}
@override
@@ -73,7 +70,8 @@ class _WelcomeScreenState extends State<WelcomeScreen> {
left: 0,
right: 0,
child: Center(
child: CircularProgressIndicator(color: Theme.of(context).scaffoldBackgroundColor),
child: CircularProgressIndicator(
color: Theme.of(context).scaffoldBackgroundColor),
),
),
],

View File

@@ -170,14 +170,16 @@ class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen> {
);
try {
final isSuccess = await service.sendForValidation(beneficiaryWithTpin);
final isSuccess =
await service.sendForValidation(beneficiaryWithTpin);
if (pinScreenContext.mounted) {
Navigator.pop(pinScreenContext); // Close the spinner
Navigator.pushReplacement(
pinScreenContext,
MaterialPageRoute(
builder: (ctx) => BeneficiaryResultPage(isSuccess: isSuccess),
builder: (ctx) =>
BeneficiaryResultPage(isSuccess: isSuccess),
),
);
}
@@ -196,7 +198,8 @@ class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen> {
Navigator.pop(pinScreenContext); // Close the spinner
ScaffoldMessenger.of(pinScreenContext).showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context).somethingWentWrong)),
content: Text(
AppLocalizations.of(context).somethingWentWrong)),
);
}
}
@@ -455,7 +458,8 @@ class _AddBeneficiaryScreen extends State<AddBeneficiaryScreen> {
child: CircularProgressIndicator(
strokeWidth: 2),
)
: Text(AppLocalizations.of(context).validateBeneficiary),
: Text(AppLocalizations.of(context)
.validateBeneficiary),
),
),
),

View File

@@ -66,34 +66,35 @@ class _BeneficiaryResultPageState extends State<BeneficiaryResultPage> {
),
],
),
Positioned(
bottom: 20, // keep it slightly above the very bottom
left: 16,
right: 16,
child: SizedBox(
height: 56, // larger button height
child: ElevatedButton(
onPressed: () {
Navigator.pushReplacement( // ensures back goes to ScaffoldScreen
context,
MaterialPageRoute(
builder: (context) => const NavigationScaffold(),
Positioned(
bottom: 20, // keep it slightly above the very bottom
left: 16,
right: 16,
child: SizedBox(
height: 56, // larger button height
child: ElevatedButton(
onPressed: () {
Navigator.pushReplacement(
// ensures back goes to ScaffoldScreen
context,
MaterialPageRoute(
builder: (context) => const NavigationScaffold(),
),
);
},
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 12),
backgroundColor: Theme.of(context).primaryColorDark,
foregroundColor: Theme.of(context).scaffoldBackgroundColor,
),
child: Text(
AppLocalizations.of(context).done,
style: const TextStyle(fontSize: 18), // slightly bigger text
),
),
),
),
);
},
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 12),
backgroundColor: Theme.of(context).primaryColorDark,
foregroundColor: Theme.of(context).scaffoldBackgroundColor,
),
child: Text(
AppLocalizations.of(context).done,
style: const TextStyle(fontSize: 18), // slightly bigger text
),
),
),
),
if (widget.isSuccess)
Align(
alignment: Alignment.topCenter,
@@ -112,4 +113,4 @@ Positioned(
),
);
}
}
}

View File

@@ -67,29 +67,30 @@ class _ManageBeneficiariesScreen extends State<ManageBeneficiariesScreen> {
width: 40,
height: 40,
);
}
}
if (bankName != null && bankName.toLowerCase().contains('kangra central')) {
return Image.asset(
'assets/images/icon.png',
width: 40,
height: 40,
);
}
}
if (bankName != null && bankName.toLowerCase().contains('hdfc bank ltd')) {
return Image.asset(
'assets/images/hdfc_logo.png',
width: 40,
height: 40,
);
}
if (bankName != null && bankName.toLowerCase().contains('icici bank ltd')) {
}
if (bankName != null && bankName.toLowerCase().contains('icici bank ltd')) {
return Image.asset(
'assets/images/icici_logo.png',
width: 40,
height: 40,
);
}
if (bankName != null && bankName.toLowerCase().contains('punjab national bank')) {
}
if (bankName != null &&
bankName.toLowerCase().contains('punjab national bank')) {
return Image.asset(
'assets/images/pnb_logo.png',
width: 40,

View File

@@ -20,7 +20,8 @@ class _CardManagementScreen extends State<CardManagementScreen> {
automaticallyImplyLeading: false,
title: Text(
AppLocalizations.of(context).cardManagement,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [

View File

@@ -54,7 +54,8 @@ class _CardPinChangeDetailsScreen extends State<CardPinChangeDetailsScreen> {
),
title: Text(
AppLocalizations.of(context).cardDetails,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [
@@ -189,7 +190,8 @@ class _CardPinChangeDetailsScreen extends State<CardPinChangeDetailsScreen> {
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor:
Theme.of(context).scaffoldBackgroundColor,
),
child: Text(AppLocalizations.of(context).next),
),

View File

@@ -54,7 +54,8 @@ class _CardPinSetScreen extends State<CardPinSetScreen> {
),
title: Text(
AppLocalizations.of(context).cardPin,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [
@@ -144,7 +145,8 @@ class _CardPinSetScreen extends State<CardPinSetScreen> {
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Theme.of(context).primaryColor,
foregroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor:
Theme.of(context).scaffoldBackgroundColor,
),
child: Text(AppLocalizations.of(context).submit),
),

View File

@@ -24,7 +24,8 @@ class _ChequeManagementScreen extends State<ChequeManagementScreen> {
),
title: Text(
AppLocalizations.of(context).chequeManagement,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [

View File

@@ -26,7 +26,8 @@ class _CustomerInfoScreenState extends State<CustomerInfoScreen> {
),
title: Text(
AppLocalizations.of(context).kMobile,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
actions: [
Padding(
@@ -89,8 +90,7 @@ class _CustomerInfoScreenState extends State<CustomerInfoScreen> {
),
InfoField(
label: AppLocalizations.of(context).dateOfBirth,
value:
(user.dateOfBirth != null &&
value: (user.dateOfBirth != null &&
user.dateOfBirth!.length == 8)
? '${user.dateOfBirth!.substring(0, 2)}-${user.dateOfBirth!.substring(2, 4)}-${user.dateOfBirth!.substring(4, 8)}'
: 'N/A',

View File

@@ -493,7 +493,13 @@ class _DashboardScreenState extends State<DashboardScreen> {
context,
MaterialPageRoute(
builder: (context) =>
FundTransferBeneficiaryScreen(creditAccountNo: users[selectedAccountIndex].accountNo!, remitterName: users[selectedAccountIndex].name!)));
FundTransferBeneficiaryScreen(
creditAccountNo:
users[selectedAccountIndex]
.accountNo!,
remitterName:
users[selectedAccountIndex]
.name!)));
}, disable: false),
_buildQuickLink(
Symbols.server_person,
@@ -582,14 +588,14 @@ class _DashboardScreenState extends State<DashboardScreen> {
style: const TextStyle(fontSize: 16),
),
onTap: () {
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
TransactionDetailsScreen(transaction: tx),
),
);
},
Navigator.push(
context,
MaterialPageRoute(
builder: (_) =>
TransactionDetailsScreen(transaction: tx),
),
);
},
),
)
else

View File

@@ -4,7 +4,7 @@ import '../../transactions/models/transaction.dart';
class TransactionListItem extends StatelessWidget {
final Transaction transaction;
const TransactionListItem({
super.key,
required this.transaction,
@@ -13,7 +13,7 @@ class TransactionListItem extends StatelessWidget {
@override
Widget build(BuildContext context) {
final bool isIncome = transaction.amount > 0;
return Card(
elevation: 0,
margin: const EdgeInsets.symmetric(vertical: 8),
@@ -25,7 +25,8 @@ class TransactionListItem extends StatelessWidget {
Container(
padding: const EdgeInsets.all(10),
decoration: BoxDecoration(
color: _getCategoryColor(transaction.category).withAlpha((0.1 * 255).toInt()),
color: _getCategoryColor(transaction.category)
.withAlpha((0.1 * 255).toInt()),
borderRadius: BorderRadius.circular(8),
),
child: Icon(
@@ -34,7 +35,7 @@ class TransactionListItem extends StatelessWidget {
),
),
const SizedBox(width: 12),
// Transaction details
Expanded(
child: Column(
@@ -48,7 +49,8 @@ class TransactionListItem extends StatelessWidget {
),
),
Text(
DateFormat('MMM dd, yyyy • h:mm a').format(transaction.date),
DateFormat('MMM dd, yyyy • h:mm a')
.format(transaction.date),
style: TextStyle(
color: Colors.grey[600],
fontSize: 12,
@@ -57,7 +59,7 @@ class TransactionListItem extends StatelessWidget {
],
),
),
// Amount
Text(
'${isIncome ? '+' : ''}${transaction.amount.toStringAsFixed(2)} USD',
@@ -106,4 +108,4 @@ class TransactionListItem extends StatelessWidget {
return Icons.category;
}
}
}
}

View File

@@ -40,12 +40,15 @@ class _EnquiryScreen extends State<EnquiryScreen> {
const SizedBox(height: 4),
GestureDetector(
onTap: () => _launchEmailAddress(email),
child: Text(email, style: TextStyle(color: Theme.of(context).primaryColor)),
child: Text(email,
style: TextStyle(color: Theme.of(context).primaryColor)),
),
const SizedBox(height: 4),
GestureDetector(
onTap: () => _launchPhoneNumber(phone),
child: Text(phone, style: TextStyle(color: Theme.of(context).scaffoldBackgroundColor)),
child: Text(phone,
style:
TextStyle(color: Theme.of(context).scaffoldBackgroundColor)),
),
],
);
@@ -63,7 +66,8 @@ class _EnquiryScreen extends State<EnquiryScreen> {
),
title: Text(
AppLocalizations.of(context).enquiry,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [

View File

@@ -45,7 +45,8 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
}
Widget _getBankLogo(String? bankName) {
if (bankName != null && bankName.toLowerCase().contains('state bank of india')) {
if (bankName != null &&
bankName.toLowerCase().contains('state bank of india')) {
return Image.asset(
'assets/images/sbi_logo.png',
width: 40,
@@ -69,8 +70,7 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
context: context,
builder: (ctx) => AlertDialog(
title: Text(AppLocalizations.of(context).invalidRtgs),
content: Text(
AppLocalizations.of(context).invalidRtgsPopUp),
content: Text(AppLocalizations.of(context).invalidRtgsPopUp),
actions: [
TextButton(
onPressed: () => Navigator.of(ctx).pop(),
@@ -120,18 +120,20 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
utr: neftResponse.utr,
);
completer.complete(paymentResponse);
} on DioException catch(e) {
} on DioException catch (e) {
print('dio exception');
print(e.toString());
final error = jsonDecode(e.response.toString())['error'];
var errorMessage =
{
"INCORRECT_TPIN" : AppLocalizations.of(context).correctTpin,
"INSUFFICIENT_FUNDS": AppLocalizations.of(context).insufficientFund
}[error] ?? AppLocalizations.of(context).somethingWentWrong;
final paymentResponse = PaymentResponse(
var errorMessage = {
"INCORRECT_TPIN":
AppLocalizations.of(context).correctTpin,
"INSUFFICIENT_FUNDS":
AppLocalizations.of(context).insufficientFund
}[error] ??
AppLocalizations.of(context).somethingWentWrong;
final paymentResponse = PaymentResponse(
isSuccess: false,
errorMessage: errorMessage,
);
@@ -141,7 +143,8 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
print(e.toString());
final paymentResponse = PaymentResponse(
isSuccess: false,
errorMessage: AppLocalizations.of(context).somethingWentWrong,
errorMessage:
AppLocalizations.of(context).somethingWentWrong,
);
completer.complete(paymentResponse);
}
@@ -181,14 +184,14 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
// } on DioException catch(e) {
// print('dio exception');
// print(e.toString());
// final error = jsonDecode(e.response.toString())['error'];
// var errorMessage =
// var errorMessage =
// {
// "INCORRECT_TPIN" : "Please Enter the correct TPIN",
// "INSUFFICIENT_FUNDS": "Your account does not have sufficient balance"
// }[error] ?? "Something Went Wrong";
// final paymentResponse = PaymentResponse(
// isSuccess: false,
// errorMessage: errorMessage,
@@ -236,19 +239,21 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
utr: rtgsResponse.utr,
);
completer.complete(paymentResponse);
} on DioException catch(e) {
} on DioException catch (e) {
print('dio exception');
print(e.toString());
final error = jsonDecode(e.response.toString())['error'];
var errorMessage =
{
"INCORRECT_TPIN" : AppLocalizations.of(context).correctTpin,
"INSUFFICIENT_FUNDS": AppLocalizations.of(context).insufficientFund
// ignore: use_build_context_synchronously
}[error] ?? AppLocalizations.of(context).somethingWentWrong;
final paymentResponse = PaymentResponse(
var errorMessage = {
"INCORRECT_TPIN":
AppLocalizations.of(context).correctTpin,
"INSUFFICIENT_FUNDS":
AppLocalizations.of(context).insufficientFund
// ignore: use_build_context_synchronously
}[error] ??
AppLocalizations.of(context).somethingWentWrong;
final paymentResponse = PaymentResponse(
isSuccess: false,
errorMessage: errorMessage,
);
@@ -258,7 +263,8 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
print(e.toString());
final paymentResponse = PaymentResponse(
isSuccess: false,
errorMessage: AppLocalizations.of(context).somethingWentWrong,
errorMessage:
AppLocalizations.of(context).somethingWentWrong,
);
completer.complete(paymentResponse);
}
@@ -349,14 +355,17 @@ class _FundTransferAmountScreenState extends State<FundTransferAmountScreen> {
borderColor: Colors.transparent,
selectedBorderColor: Colors.transparent,
splashColor: Theme.of(context).primaryColor.withOpacity(0.1),
highlightColor: Theme.of(context).primaryColor.withOpacity(0.05),
highlightColor:
Theme.of(context).primaryColor.withOpacity(0.05),
children: [
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 12.0),
child: Text(AppLocalizations.of(context).neft),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0, vertical: 12.0),
padding: const EdgeInsets.symmetric(
horizontal: 24.0, vertical: 12.0),
child: Text(AppLocalizations.of(context).rtgs),
),
// Padding(

View File

@@ -70,36 +70,36 @@ class _FundTransferBeneficiaryScreenState
width: 40,
height: 40,
);
}
if (bankName != null && bankName.toLowerCase().contains('kangra central')) {
}
if (bankName != null && bankName.toLowerCase().contains('kangra central')) {
return Image.asset(
'assets/images/icon.png',
width: 40,
height: 40,
);
}
}
if (bankName != null && bankName.toLowerCase().contains('hdfc bank ltd')) {
return Image.asset(
'assets/images/hdfc_logo.png',
width: 40,
height: 40,
);
}
if (bankName != null && bankName.toLowerCase().contains('icici bank ltd')) {
}
if (bankName != null && bankName.toLowerCase().contains('icici bank ltd')) {
return Image.asset(
'assets/images/icici_logo.png',
width: 40,
height: 40,
);
}
if (bankName != null && bankName.toLowerCase().contains('punjab national bank')) {
}
if (bankName != null &&
bankName.toLowerCase().contains('punjab national bank')) {
return Image.asset(
'assets/images/pnb_logo.png',
width: 40,
height: 40,
);
}
else {
} else {
return const Icon(
Icons.account_balance,
size: 40,
@@ -128,7 +128,8 @@ class _FundTransferBeneficiaryScreenState
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(beneficiary.accountNo),
if (beneficiary.bankName != null && beneficiary.bankName!.isNotEmpty)
if (beneficiary.bankName != null &&
beneficiary.bankName!.isNotEmpty)
Text(
beneficiary.bankName!,
style: TextStyle(fontSize: 12, color: Colors.grey[600]),

View File

@@ -87,7 +87,8 @@ class _FundTransferScreen extends State<FundTransferScreen> {
),
title: Text(
AppLocalizations.of(context).fundTransfer,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: const [

View File

@@ -27,7 +27,8 @@ class _PaymentAnimationScreenState extends State<PaymentAnimationScreen> {
@override
void initState() {
super.initState();
_confettiController = ConfettiController(duration: const Duration(seconds: 2));
_confettiController =
ConfettiController(duration: const Duration(seconds: 2));
}
@override
@@ -41,7 +42,8 @@ class _PaymentAnimationScreenState extends State<PaymentAnimationScreen> {
RenderRepaintBoundary boundary =
_shareKey.currentContext!.findRenderObject() as RenderRepaintBoundary;
ui.Image image = await boundary.toImage(pixelRatio: 3.0);
ByteData? byteData = await image.toByteData(format: ui.ImageByteFormat.png);
ByteData? byteData =
await image.toByteData(format: ui.ImageByteFormat.png);
Uint8List pngBytes = byteData!.buffer.asUint8List();
final tempDir = await getTemporaryDirectory();
@@ -129,7 +131,8 @@ class _PaymentAnimationScreenState extends State<PaymentAnimationScreen> {
? Column(
children: [
Text(
AppLocalizations.of(context).paymentSuccessful,
AppLocalizations.of(context)
.paymentSuccessful,
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.bold,
@@ -160,7 +163,8 @@ class _PaymentAnimationScreenState extends State<PaymentAnimationScreen> {
"Date: ${response.date!.toLocal().toIso8601String()}",
style: const TextStyle(fontSize: 16),
),
if (response.utr != null && response.utr!.isNotEmpty)
if (response.utr != null &&
response.utr!.isNotEmpty)
Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(
@@ -182,7 +186,8 @@ class _PaymentAnimationScreenState extends State<PaymentAnimationScreen> {
),
const SizedBox(height: 16),
if (response.errorMessage != null)
Text(response.errorMessage ?? '',
Text(
response.errorMessage ?? '',
style: const TextStyle(fontSize: 16),
),
],
@@ -211,10 +216,13 @@ class _PaymentAnimationScreenState extends State<PaymentAnimationScreen> {
style: TextStyle(color: Theme.of(context).primaryColor),
),
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
padding: const EdgeInsets.symmetric(horizontal: 32, vertical: 12),
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
padding: const EdgeInsets.symmetric(
horizontal: 32, vertical: 12),
shape: RoundedRectangleBorder(
side: BorderSide(color: Theme.of(context).primaryColor, width: 1),
side: BorderSide(
color: Theme.of(context).primaryColor, width: 1),
borderRadius: BorderRadius.circular(30),
),
textStyle: const TextStyle(
@@ -226,12 +234,14 @@ class _PaymentAnimationScreenState extends State<PaymentAnimationScreen> {
),
ElevatedButton.icon(
onPressed: () {
Navigator.of(context).popUntil((route) => route.isFirst);
Navigator.of(context)
.popUntil((route) => route.isFirst);
},
icon: const Icon(Icons.check),
label: Text(AppLocalizations.of(context).done),
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(horizontal: 45, vertical: 12),
padding: const EdgeInsets.symmetric(
horizontal: 45, vertical: 12),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(30),
),

View File

@@ -131,7 +131,8 @@ class _TpinOtpScreenState extends State<TpinOtpScreen> {
icon: const Icon(Icons.verified_user_rounded),
label: Text(
AppLocalizations.of(context).verifyOtp,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w600),
),
style: ElevatedButton.styleFrom(
backgroundColor: theme.colorScheme.primary,

View File

@@ -41,7 +41,8 @@ class TpinSetupPromptScreen extends StatelessWidget {
icon: const Icon(Icons.arrow_forward_rounded),
label: Text(
AppLocalizations.of(context).setTpin,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
style:
const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
),
style: ElevatedButton.styleFrom(
backgroundColor: theme.colorScheme.primary,

View File

@@ -173,7 +173,9 @@ class _TpinSetScreenState extends State<TpinSetScreen> {
key == '<' ? '' : key,
style: TextStyle(
fontSize: 20,
color: key == 'Enter' ? Theme.of(context).primaryColor : Colors.black,
color: key == 'Enter'
? Theme.of(context).primaryColor
: Colors.black,
),
),
),
@@ -202,7 +204,8 @@ class _TpinSetScreenState extends State<TpinSetScreen> {
child: Column(
children: [
const Spacer(),
Icon(Icons.lock_outline, size: 60, color: Theme.of(context).primaryColor),
Icon(Icons.lock_outline,
size: 60, color: Theme.of(context).primaryColor),
const SizedBox(height: 20),
Text(
getTitle(),

View File

@@ -151,7 +151,8 @@ class _TransactionPinScreenState extends State<TransactionPinScreen> {
),
title: Text(
AppLocalizations.of(context).tpin,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
),

View File

@@ -36,8 +36,8 @@ class _TransactionSuccessScreen extends State<TransactionSuccessScreen> {
@override
Widget build(BuildContext context) {
final String transactionDate = DateTime.now().toLocal().toString().split(
' ',
)[0];
' ',
)[0];
final String creditAccount = widget.creditAccount;
return Scaffold(
@@ -53,12 +53,15 @@ class _TransactionSuccessScreen extends State<TransactionSuccessScreen> {
CircleAvatar(
radius: 50,
backgroundColor: Theme.of(context).primaryColor,
child: Icon(Icons.check, color: Theme.of(context).scaffoldBackgroundColor, size: 60),
child: Icon(Icons.check,
color: Theme.of(context).scaffoldBackgroundColor,
size: 60),
),
const SizedBox(height: 24),
Text(
AppLocalizations.of(context).transactionSuccess,
style: const TextStyle(fontSize: 18, fontWeight: FontWeight.w600),
style: const TextStyle(
fontSize: 18, fontWeight: FontWeight.w600),
textAlign: TextAlign.center,
),
const SizedBox(height: 6),
@@ -92,7 +95,8 @@ class _TransactionSuccessScreen extends State<TransactionSuccessScreen> {
style: ElevatedButton.styleFrom(
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
backgroundColor:
Theme.of(context).scaffoldBackgroundColor,
foregroundColor: Theme.of(context).primaryColorLight,
side: const BorderSide(color: Colors.black, width: 1),
elevation: 0,
@@ -115,7 +119,8 @@ class _TransactionSuccessScreen extends State<TransactionSuccessScreen> {
shape: const StadiumBorder(),
padding: const EdgeInsets.symmetric(vertical: 16),
backgroundColor: Theme.of(context).primaryColorDark,
foregroundColor: Theme.of(context).scaffoldBackgroundColor,
foregroundColor:
Theme.of(context).scaffoldBackgroundColor,
),
child: Text(AppLocalizations.of(context).done),
),

View File

@@ -37,4 +37,4 @@ class LanguageDialog extends StatelessWidget {
),
);
}
}
}

View File

@@ -28,7 +28,8 @@ class PreferenceScreen extends StatelessWidget {
onTap: () {
showDialog(
context: context,
builder: (_) => const LanguageDialog(), // your custom language dialog
builder: (_) =>
const LanguageDialog(), // your custom language dialog
);
},
),
@@ -38,28 +39,27 @@ class PreferenceScreen extends StatelessWidget {
title: Text(AppLocalizations.of(context).themeMode),
enabled: false,
//trailing: Switch(
// value: state.isDarkMode,
// onChanged: (val) {
// context.read<ThemeCubit>().toggleDarkMode(val);
// },
// value: state.isDarkMode,
// onChanged: (val) {
// context.read<ThemeCubit>().toggleDarkMode(val);
// },
//),
),
//Color_Theme_Selection
//Color_Theme_Selection
ListTile(
leading: const Icon(Icons.color_lens),
title: Text(AppLocalizations.of(context).themeColor),
//enabled: false,
onTap: () {
showDialog(
context: context,
builder: (_) => const ColorThemeDialog(),
);
}
),
],
leading: const Icon(Icons.color_lens),
title: Text(AppLocalizations.of(context).themeColor),
//enabled: false,
onTap: () {
showDialog(
context: context,
builder: (_) => const ColorThemeDialog(),
);
}),
],
);
},
),
);
}
}
}

View File

@@ -21,7 +21,8 @@ class ProfileScreen extends StatelessWidget {
onTap: () {
Navigator.push(
context,
MaterialPageRoute(builder: (context) => const PreferenceScreen()),
MaterialPageRoute(
builder: (context) => const PreferenceScreen()),
);
},
),

View File

@@ -142,7 +142,8 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
if (!_isBeneficiaryValidated) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(AppLocalizations.of(context).plsValidateBeneficiary)),
content:
Text(AppLocalizations.of(context).plsValidateBeneficiary)),
);
return;
}
@@ -189,8 +190,8 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
Navigator.of(pinScreenContext).pushReplacement(
MaterialPageRoute(
builder: (_) =>
PaymentAnimationScreen(paymentResponse: completer.future),
builder: (_) => PaymentAnimationScreen(
paymentResponse: completer.future),
),
);
@@ -229,8 +230,8 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
Navigator.of(pinScreenContext).pushReplacement(
MaterialPageRoute(
builder: (_) =>
PaymentAnimationScreen(paymentResponse: completer.future),
builder: (_) => PaymentAnimationScreen(
paymentResponse: completer.future),
),
);
@@ -273,7 +274,8 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
),
title: Text(
AppLocalizations.of(context).quickPayOutsideBank,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [
@@ -385,9 +387,9 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
Expanded(
child: TextFormField(
maxLength: 11,
inputFormatters: [
LengthLimitingTextInputFormatter(11),
],
inputFormatters: [
LengthLimitingTextInputFormatter(11),
],
decoration: InputDecoration(
labelText: AppLocalizations.of(context).ifscCode,
border: const OutlineInputBorder(),
@@ -446,16 +448,14 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
items:
[
AppLocalizations.of(context).savings,
AppLocalizations.of(context).current,
]
.map(
(e) =>
DropdownMenuItem(value: e, child: Text(e)),
)
.toList(),
items: [
AppLocalizations.of(context).savings,
AppLocalizations.of(context).current,
]
.map(
(e) => DropdownMenuItem(value: e, child: Text(e)),
)
.toList(),
onChanged: (value) => setState(() {
accountType = value!;
}),
@@ -463,7 +463,6 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
),
],
),
const SizedBox(height: 25),
TextFormField(
controller: bankNameController,
@@ -516,14 +515,14 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
onPressed: _isValidating
? null
: () {
if (confirmAccountNumberController
.text ==
if (confirmAccountNumberController.text ==
accountNumberController.text) {
_validateBeneficiary();
} else {
setState(() {
_validationError =
AppLocalizations.of(context).accountMismatch;
AppLocalizations.of(context)
.accountMismatch;
});
}
},
@@ -531,10 +530,10 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
? const SizedBox(
width: 20,
height: 20,
child: CircularProgressIndicator(
strokeWidth: 2),
child: CircularProgressIndicator(strokeWidth: 2),
)
: Text(AppLocalizations.of(context).validateBeneficiary),
: Text(
AppLocalizations.of(context).validateBeneficiary),
),
),
),
@@ -559,8 +558,7 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
borderSide: BorderSide(color: Colors.black),
),
focusedBorder: const OutlineInputBorder(
borderSide:
BorderSide(color: Colors.black, width: 2),
borderSide: BorderSide(color: Colors.black, width: 2),
),
),
validator: (value) {
@@ -645,15 +643,18 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
Align(
alignment: Alignment.center,
child: SwipeButton.expand(
thumb: Icon(Icons.arrow_forward, color: Theme.of(context).dialogBackgroundColor),
thumb: Icon(Icons.arrow_forward,
color: Theme.of(context).dialogBackgroundColor),
activeThumbColor: Theme.of(context).primaryColor,
activeTrackColor: Theme.of(context).colorScheme.secondary.withAlpha(100),
activeTrackColor:
Theme.of(context).colorScheme.secondary.withAlpha(100),
borderRadius: BorderRadius.circular(30),
height: 56,
onSwipe: _onProceedToPay,
child: Text(
AppLocalizations.of(context).swipeToPay,
style: const TextStyle(fontSize: 16, fontWeight: FontWeight.bold),
style: const TextStyle(
fontSize: 16, fontWeight: FontWeight.bold),
),
),
),
@@ -679,10 +680,14 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
margin: const EdgeInsets.symmetric(horizontal: 4),
padding: const EdgeInsets.symmetric(vertical: 5),
decoration: BoxDecoration(
color: isSelected ? Theme.of(context).primaryColor : Theme.of(context).scaffoldBackgroundColor,
color: isSelected
? Theme.of(context).primaryColor
: Theme.of(context).scaffoldBackgroundColor,
borderRadius: BorderRadius.circular(5),
border: Border.all(
color: isSelected ? Theme.of(context).primaryColor : Theme.of(context).scaffoldBackgroundColor,
color: isSelected
? Theme.of(context).primaryColor
: Theme.of(context).scaffoldBackgroundColor,
width: isSelected ? 0 : 1.2,
),
),
@@ -698,4 +703,4 @@ class _QuickPayOutsideBankScreen extends State<QuickPayOutsideBankScreen> {
),
);
}
}
}

View File

@@ -212,7 +212,8 @@ class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
} else {
setState(() {
_validationError =
AppLocalizations.of(context).accountMismatch;
AppLocalizations.of(context)
.accountMismatch;
});
}
},
@@ -222,7 +223,8 @@ class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
height: 20,
child: CircularProgressIndicator(strokeWidth: 2),
)
: Text(AppLocalizations.of(context).validateBeneficiary),
: Text(
AppLocalizations.of(context).validateBeneficiary),
),
),
),
@@ -322,7 +324,8 @@ class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
Align(
alignment: Alignment.center,
child: SwipeButton.expand(
thumb: Icon(Icons.arrow_forward, color: Theme.of(context).dialogBackgroundColor),
thumb: Icon(Icons.arrow_forward,
color: Theme.of(context).dialogBackgroundColor),
activeThumbColor: Theme.of(context).primaryColor,
activeTrackColor: Theme.of(
context,
@@ -337,8 +340,8 @@ class _QuickPayWithinBankScreen extends State<QuickPayWithinBankScreen> {
if (_formKey.currentState!.validate()) {
if (!_isBeneficiaryValidated) {
setState(() {
_validationError =
AppLocalizations.of(context).validateBeneficiaryproceeding;
_validationError = AppLocalizations.of(context)
.validateBeneficiaryproceeding;
});
return;
}

View File

@@ -18,7 +18,8 @@ class _ServiceScreen extends State<ServiceScreen> {
automaticallyImplyLeading: false,
title: Text(
AppLocalizations.of(context).services,
style: const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
style:
const TextStyle(color: Colors.black, fontWeight: FontWeight.w500),
),
centerTitle: false,
actions: [

View File

@@ -4,7 +4,7 @@ class Transaction {
final double amount;
final DateTime date;
final String category;
Transaction({
required this.id,
required this.description,
@@ -12,4 +12,4 @@ class Transaction {
required this.date,
required this.category,
});
}
}

View File

@@ -62,7 +62,8 @@ import 'app_localizations_hi.dart';
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
/// property.
abstract class AppLocalizations {
AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString());
AppLocalizations(String locale)
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
final String localeName;
@@ -70,7 +71,8 @@ abstract class AppLocalizations {
return Localizations.of<AppLocalizations>(context, AppLocalizations)!;
}
static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();
static const LocalizationsDelegate<AppLocalizations> delegate =
_AppLocalizationsDelegate();
/// A list of this localizations delegate along with the default localizations
/// delegates.
@@ -82,7 +84,8 @@ abstract class AppLocalizations {
/// Additional delegates can be added by appending to this list in
/// MaterialApp. This list does not have to be used at all if a custom list
/// of delegates is preferred or required.
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
<LocalizationsDelegate<dynamic>>[
delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
@@ -1506,7 +1509,8 @@ abstract class AppLocalizations {
String get validateBeneficiaryproceeding;
}
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
class _AppLocalizationsDelegate
extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
@override
@@ -1515,25 +1519,25 @@ class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations>
}
@override
bool isSupported(Locale locale) => <String>['en', 'hi'].contains(locale.languageCode);
bool isSupported(Locale locale) =>
<String>['en', 'hi'].contains(locale.languageCode);
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
AppLocalizations lookupAppLocalizations(Locale locale) {
// Lookup logic when only language code is specified.
switch (locale.languageCode) {
case 'en': return AppLocalizationsEn();
case 'hi': return AppLocalizationsHi();
case 'en':
return AppLocalizationsEn();
case 'hi':
return AppLocalizationsHi();
}
throw FlutterError(
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.'
);
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.');
}

View File

@@ -486,7 +486,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get otpVerification => 'OTP Verification';
@override
String get otpSentMessage => 'Enter the 4-digit OTP sent to your mobile number';
String get otpSentMessage =>
'Enter the 4-digit OTP sent to your mobile number';
@override
String get verifyOtp => 'Verify OTP';
@@ -504,13 +505,15 @@ class AppLocalizationsEn extends AppLocalizations {
String get tpinRequired => 'TPIN Required';
@override
String get tpinRequiredMessage => 'You need to set your TPIN to continue with secure transactions';
String get tpinRequiredMessage =>
'You need to set your TPIN to continue with secure transactions';
@override
String get setTpinTitle => 'Set TPIN';
@override
String get tpinInfo => 'Your TPIN is a 6-digit code used to authorize transactions. Keep it safe and do not share it with anyone.';
String get tpinInfo =>
'Your TPIN is a 6-digit code used to authorize transactions. Keep it safe and do not share it with anyone.';
@override
String get tpinFailed => 'Failed to set TPIN. Please try again.';
@@ -564,7 +567,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get enableFingerprintLogin => 'Enable Fingerprint Login?';
@override
String get enableFingerprintMessage => 'Would you like to enable fingerprint authentication for faster login?';
String get enableFingerprintMessage =>
'Would you like to enable fingerprint authentication for faster login?';
@override
String get no => 'No';
@@ -585,7 +589,8 @@ class AppLocalizationsEn extends AppLocalizations {
String get loading => 'Loading......';
@override
String get enableFingerprintQuick => 'Enable fingerprint authentication for quick login?';
String get enableFingerprintQuick =>
'Enable fingerprint authentication for quick login?';
@override
String get kccb => 'KCCB';
@@ -687,13 +692,15 @@ class AppLocalizationsEn extends AppLocalizations {
String get invalidRtgs => 'Invalid Amount for RTGS';
@override
String get invalidRtgsPopUp => 'RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.';
String get invalidRtgsPopUp =>
'RTGS transactions require a minimum amount of 200,000. Please enter a higher amount or select NEFT as the transaction mode.';
@override
String get correctTpin => 'Please Enter the correct TPIN';
@override
String get insufficientFund => 'Your account does not have sufficient balance';
String get insufficientFund =>
'Your account does not have sufficient balance';
@override
String get creditedTo => 'Credited To';
@@ -705,11 +712,13 @@ class AppLocalizationsEn extends AppLocalizations {
String get proceed => 'Proceed';
@override
String get plsValidateBeneficiary => 'Please validate beneficiary details first';
String get plsValidateBeneficiary =>
'Please validate beneficiary details first';
@override
String get accno7to20 => 'Account number must be between 7 and 20 digits';
@override
String get validateBeneficiaryproceeding => 'Please validate beneficiary before proceeding';
String get validateBeneficiaryproceeding =>
'Please validate beneficiary before proceeding';
}

View File

@@ -52,7 +52,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get enableBiometric => 'बायोमेट्रिक प्रमाणीकरण सक्षम करें';
@override
String get useBiometricPrompt => 'तेज़ लॉगिन के लिए फिंगरप्रिंट/फेस आईडी का उपयोग करें?';
String get useBiometricPrompt =>
'तेज़ लॉगिन के लिए फिंगरप्रिंट/फेस आईडी का उपयोग करें?';
@override
String get later => 'बाद में';
@@ -486,7 +487,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get otpVerification => 'ओटीपी सत्यापन';
@override
String get otpSentMessage => 'अपने मोबाइल नंबर पर भेजा गया 4-अंकों का ओटीपी दर्ज करें';
String get otpSentMessage =>
'अपने मोबाइल नंबर पर भेजा गया 4-अंकों का ओटीपी दर्ज करें';
@override
String get verifyOtp => 'ओटीपी सत्यापित करें';
@@ -504,13 +506,15 @@ class AppLocalizationsHi extends AppLocalizations {
String get tpinRequired => 'टी-पिन आवश्यक है';
@override
String get tpinRequiredMessage => 'सुरक्षित लेनदेन के लिए टी-पिन सेट करना आवश्यक है';
String get tpinRequiredMessage =>
'सुरक्षित लेनदेन के लिए टी-पिन सेट करना आवश्यक है';
@override
String get setTpinTitle => 'टी-पिन सेट करें';
@override
String get tpinInfo => 'आपका टी-पिन 6 अंकों का कोड है जिसका उपयोग लेन-देन को प्रमाणित करने के लिए किया जाता है। इसे सुरक्षित रखें और किसी से साझा न करें।';
String get tpinInfo =>
'आपका टी-पिन 6 अंकों का कोड है जिसका उपयोग लेन-देन को प्रमाणित करने के लिए किया जाता है। इसे सुरक्षित रखें और किसी से साझा न करें।';
@override
String get tpinFailed => 'टी-पिन सेट करने में विफल। कृपया पुनः प्रयास करें।';
@@ -564,7 +568,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get enableFingerprintLogin => 'फिंगरप्रिंट लॉगिन सक्षम करें?';
@override
String get enableFingerprintMessage => 'क्या आप तेज लॉगिन के लिए फिंगरप्रिंट प्रमाणीकरण सक्षम करना चाहेंगे?';
String get enableFingerprintMessage =>
'क्या आप तेज लॉगिन के लिए फिंगरप्रिंट प्रमाणीकरण सक्षम करना चाहेंगे?';
@override
String get no => 'नहीं';
@@ -573,7 +578,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get yes => 'हाँ';
@override
String get authenticateToEnable => 'फिंगरप्रिंट लॉगिन सक्षम करने के लिए प्रमाणीकरण करें';
String get authenticateToEnable =>
'फिंगरप्रिंट लॉगिन सक्षम करने के लिए प्रमाणीकरण करें';
@override
String get exitApp => 'ऐप बंद करें';
@@ -585,7 +591,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get loading => 'लोड हो रहा है......';
@override
String get enableFingerprintQuick => 'तेज़ लॉगिन के लिए फिंगरप्रिंट प्रमाणीकरण सक्षम करें?';
String get enableFingerprintQuick =>
'तेज़ लॉगिन के लिए फिंगरप्रिंट प्रमाणीकरण सक्षम करें?';
@override
String get kccb => 'केसीसीबी';
@@ -687,7 +694,8 @@ class AppLocalizationsHi extends AppLocalizations {
String get invalidRtgs => 'RTGS के लिए अमान्य राशि';
@override
String get invalidRtgsPopUp => 'RTGS लेनदेन के लिए न्यूनतम 2,00,000 रुपये की राशि की आवश्यकता होती है। कृपया अधिक राशि दर्ज करें या लेनदेन मोड के रूप में NEFT चुनें';
String get invalidRtgsPopUp =>
'RTGS लेनदेन के लिए न्यूनतम 2,00,000 रुपये की राशि की आवश्यकता होती है। कृपया अधिक राशि दर्ज करें या लेनदेन मोड के रूप में NEFT चुनें';
@override
String get correctTpin => 'कृपया सही टी-पिन दर्ज करें';
@@ -705,11 +713,13 @@ class AppLocalizationsHi extends AppLocalizations {
String get proceed => 'आगे बढ़ना';
@override
String get plsValidateBeneficiary => 'कृपया पहले लाभार्थी विवरण सत्यापित करें';
String get plsValidateBeneficiary =>
'कृपया पहले लाभार्थी विवरण सत्यापित करें';
@override
String get accno7to20 => 'खाता संख्या सात से बीस अंकों के बीच होनी चाहिए';
@override
String get validateBeneficiaryproceeding => 'कृपया आगे बढ़ने से पहले लाभार्थी को पट्टे पर मान्य करें';
String get validateBeneficiaryproceeding =>
'कृपया आगे बढ़ने से पहले लाभार्थी को पट्टे पर मान्य करें';
}

View File

@@ -13,6 +13,6 @@ void main() async {
]);
// Initialize dependencies
await setupDependencies();
await setupDependencies();
runApp(const KMobile());
}

View File

@@ -3,33 +3,30 @@ import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class SecureStorage {
final FlutterSecureStorage _storage;
SecureStorage(): _storage = const FlutterSecureStorage();
SecureStorage() : _storage = const FlutterSecureStorage();
Future<void> write(String key, dynamic value) async {
final stringValue = value is String
? value
: json.encode(value);
final stringValue = value is String ? value : json.encode(value);
await _storage.write(key: key, value: stringValue);
}
Future<dynamic> read(String key) async {
final value = await _storage.read(key: key);
if (value == null) return null;
try {
return json.decode(value);
} catch (_) {
return value;
}
}
Future<void> delete(String key) async {
await _storage.delete(key: key);
}
Future<void> deleteAll() async {
await _storage.deleteAll();
}
}
}

View File

@@ -0,0 +1 @@