From 04a1ce26ecd06522714d4499cba94e8f7da75eac Mon Sep 17 00:00:00 2001 From: asif Date: Fri, 28 Nov 2025 11:28:01 +0530 Subject: [PATCH] Profile Changed and Customer Info --- assets/images/profile.svg | Bin 0 -> 4314 bytes lib/di/injection.dart | 4 +- .../screens/customer_info_screen.dart | 218 +++++++++++------- .../preferences/preference_screen.dart | 68 +++--- lib/features/profile/profile_screen.dart | 25 +- .../profile/security_settings_screen.dart | 178 +++++++------- pubspec.yaml | 1 + 7 files changed, 274 insertions(+), 220 deletions(-) create mode 100644 assets/images/profile.svg diff --git a/assets/images/profile.svg b/assets/images/profile.svg new file mode 100644 index 0000000000000000000000000000000000000000..56de2bdd492fbac20020aa660c05d3d9a3fe8cfd GIT binary patch literal 4314 zcmZuy2|Sct`+jE3SchgX80*XklVz-Bc`=3=>#Ih{QiL>?2qn=*wiuG7nylHX$(uxE z3uTvGNXV9Ci!8}f{AaxH_x-=`_xsLsp8Gk!v)%W(uIoO}-q79z05>-_GX_8)001!` zU~dG71i08a`1$#ftQQFvMk0ln6^?`>g_vz&VIdJDQbYoW77>+^Kni13F)|7YcsyQI zN?l7`NfW1pR{(KybMx}@BAHbIg_KZGQeYM(mQ`YXm<^WM?`4g!iYD_>&}6>*y?bu} z1Sc>FOtOKn02l#cLxA=g0WoHPU^Z5$|1KbQFa*lR!5q|w10XOM!p+GJ1~VryXMg|% z7{jJYw1PnS)eMij=DhvRE`U`JxS7;z!cv3po`a<%`#gr03=6WRPzcyxhVEGh8 z{HMEpzk9;~jOhT3U_$@|Uz*A3z~s2PG%=tD_rqI@bgRIe0XSp-8ZOvZ zwYLFZ2KdcnI&x9D>yYaB9oLErtwd=2l=kCkpc=Mg`T0J@Amygk(SS-$SmTBwZLK{U z&&40<~~JXgxJ@Q2*47YcuY4w((ReD#^}e4B1` z()(%8I_-g73cS3ed$vl1VCEw86s^+WuTA_ZDDnPC2qL{aRhoWX&nfOSw1F|Feg+`{ zUvynzzpNCE9~U_32BegZ|KXud+21Qk)9c8MF=|c&pRu~nH&$8TS$hPP$; zrM^s+7WRuREC$Sm{W4#sGF&=y3d>B>OVbH{>XgZclk?w*vOcRmpI*0#SI^Ba8p(!4 zr2lITyOXbMkv=2SN%qCpHnX(0K!%7k7iww~{#lpx!^N zv(8#i3{0r^tDm4uCGYvx(Wr(Zka zrT{y1@^I4yIH#K!!y{Hyrqih9>3tLH>tTclTb?FJX z7%UkmiF6&&RE*#!p}UJuSxF#mTkNO%LM2e%7++(8Saf4c#mF-~CviqpsJ75%=VFPV9=Sx0z?LXTH%;2?;VwkM}n7( z@#FkEVwo{&3upRC^K*x9>6=FIo8gT}^3m&%@CjYxit~m`EdpYxZ@JGnb~!Ofhu<5x3 z(8P*AcUO!8Vx9WOA&fry&ZWF4H=3ucOTaa~oGS1682w<{m-u2m35ASdOBaPbz}4@I z&G*-$@>=nTXz8A~x25P65(z>wAdw`x63z%=Y3d*4ic6&PCPMY)d%m!QQ5*F9LCS%J zY=K=@Y$!)Z0I`R^z%O%k?J!JCW=HfLxe%+qvFXRk%1`GCqzfXP1fJy$=x*h50bJnk zX;YP)?4(jGqsYKWtD{dS%l-9>ssJb|;m{k9%I#O^!oY{Ts(tP@=p-rCqP`;AW@~Zx z7%rp$^+xodn{4$EW!cfbVYJ)#~r+908y(%UwdmlX| zMc=q44c^CcTos=tPRygX7Ac9Qm>5NJnQ%zczE_IWnNb1j7GH8+vu^b+7w9n&Sz`4+{Up0JasAB;qUj}W`hg#(d zy_jnx zA@<-diUVaH$po8uv=jJP;uv{1Z}k||>BQ04tWNX@*AI@59D&cm0ak1=F+BVwI53~4 zx#u1bDV8VpR`OjzVU1kersL+MRLWbML<9nafSXcc!W()O(Ge12f7}#~id^Py99I4~ zXwyNoNI3>=n$(9}Eval{k+W6?xkOo5CcVq6*nSvjW1(@={~Ya$c}swv-oY`SU4V~! z9`z_SUuotMsaa;uOZ0ikk?-#mvp@W!59rWrEh5F-RmXoh`pm`WI`3$S4R9I?PL#xO z^jHPEXxV7I;GBF_98jtp_z!bYdbn@_L2?f09Uq6qp*7quH^R*(JNhfJ$TZWb_+jq~ zdp%(qOZP1C|9C6imcaR(CNN91`$crcHcj7LrBCLT5-IMs-D02 zZ1C-Z$p}|?pCLA^;+GG$o}n-TtjiDgVNj;fJ^8_|TExvXA*%EQ&QGPVsE#@ZYvwK!8_Wke0 zADlIouayqjaI82lVP@{Em0=Ibkp!LlC(T*M4X=$ER#v*feKW#frCynam^Z9rvNWs| z$j1mx3H>H`)@tL5(NE)UTuhbdZ+%*F64&ojEF%Z49|Z&{I(GOu@pC9Q()6^{jQZ!CYL1o&bw`HK`CAG zrTPF%*rhk1TFJIgj-OpKC26SMjN$@&@`BZ9M0A|IDd#~FC-#LAy!da8lQD+8zf8#Y zj(fgJLTrd>*}?vLmrhLGww&lWZ1v-dBEk4vbh47&_-|anf z;07{YrRiM*i(&r~qaX;u{#+`|>OFh>(bmXZ$!kapl-tm(1zGE;k73?okU~{`RB^ngY$0ju=mFsp!b?4^yb%yo{hnpc1D~YG<^SQ zh5lX3*(%=L)ejTlqiO4Vz{!5I+N_@j^S8D%cY94%zKzl1Q}dU$?WA=x(~s^3{AMp0wZ3E`ghx^o2MFOG9~fBp!Zu}S6%mxegJDgOE0?#G+CqwEvMX)RP`Hme`>2gH*k64Y;Ymu;Z8 z@@_z}s&^b_=124FuA)Zq*+xPFm}~g_iI1A^$7W?~ZvWnzx|2WdA!!&vwRM!Lc}HcE z-=0cYxRJHor&vd)PE%Z#k5GFCzlPJjUe-p9ZaPMdg=}kHbmR!RoMw0NIGaZ1xP|Q* zK``1yaj?-l#;NW?V&}(>z8W5looeM9PEd7mxA#T@VOL77DpTt#7iLAs@OTj~wqy|= zq%$4S#H*p=Vf7$#3G7ZT3+G|Sz1^W%_)fh(jnoLiQsQTyMP3~hHsWbq>2p<$F(TqREYaAa#_BeE z|35{!wIC{Yrb_1oLWr4Am`Xh+(!Bw8t9!Y&EPYP%V@qOmN72ill@|2v^i*(R(Qob5 zr$(N2;|n|cRdgowMsVIg2o#hOt|t5aP^`R%82qg_p6^g2+u54UyaC>LjwQVJxGq*X z^}i&5nqD-{{PmrJs@6`k%b`BJe0I6LfNzcJD{)r&oK}CepJvYGZyvMRm+2wCo$Y9K zvrp?~R;5k}H9Ojs2CVaAm}^|iwgUN=b<#~7h=bniZeP&NS4f)=10tu$8y(}eoY0^VHi!0sXF-mQJ9s5ypaQtZdINjju zZjpu5r2@-T+gbnXZOlJd9E!#5wUA;l^4Frb(8|MJyXB0O>wkO;6mV|d{k3A!=j9z> zM78_4Gnx|m^in*-wrmf0qFlK@-Jo1<`L~~$=KIkn&~o73%E zk-njG-4I{ltU8F$^oJ+gW4V^=%Vj;sY(m@WHsXZxUN4g*@77G~j@@;dc9v|V9ncYP zO{Q1hYWak)%EVuj_uOfHt(PPy8K|8kBNwE5y%&jk?_uzm@B8LeEKYa!;u$NcAl=}5 zI7U~x&H+5P>+*qHKumUhG~?GMBd%If*BqNC?>({lD=P6nM>d_WSs_u@o+17Y*G}U( tX)w { .replaceFirst(RegExp('\n'), ''), ), ), - body: Stack( - children: [ - SingleChildScrollView( - physics: const AlwaysScrollableScrollPhysics(), - child: Padding( - padding: const EdgeInsets.all(16.0), - child: SafeArea( - child: Center( - child: Column( - children: [ - const SizedBox(height: 30), - CircleAvatar( - radius: 50, - child: SvgPicture.asset( - 'assets/images/avatar_male.svg', - width: 150, - height: 150, - fit: BoxFit.cover, + body: SafeArea( + child: Stack( + children: [ + SingleChildScrollView( + physics: const AlwaysScrollableScrollPhysics(), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + children: [ + Card( + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: theme.colorScheme.outline.withOpacity(0.2), + width: 1, + ), + ), + child: Padding( padding: const EdgeInsets.all(16.0), + child: Row( + children: [ + SizedBox( + width: 56, + height: 56, + child: CircleAvatar( + radius: 50, + child: SvgPicture.asset( + 'assets/images/avatar_male.svg', + fit: BoxFit.cover, + ), + ), + ), + const SizedBox(width: 12), + // Name + mobile + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + // If you want to show the user's name instead, replace below. + user.name ?? '', + style: + theme.textTheme.titleLarge?.copyWith( + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 4), + Text( + user.cifNumber ?? '', + style: theme.textTheme.bodyMedium?.copyWith( + color: theme.colorScheme.onSurface + .withOpacity(0.7), + ), + ), + ], + ), + ), + ], ), ), - Padding( - padding: const EdgeInsets.only(top: 10.0), - child: Text( - user.name ?? '', - style: TextStyle( - fontSize: 20, - color: theme.colorScheme.onSurface, - fontWeight: FontWeight.w500, - ), + ), + const SizedBox(height: 16), + Card( + elevation: 0, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(12), + side: BorderSide( + color: theme.colorScheme.outline.withOpacity(0.2), + width: 1, ), ), - Text( - '${AppLocalizations.of(context).cif}: ${user.cifNumber ?? 'N/A'}', - style: TextStyle( - fontSize: 16, - color: theme.colorScheme.onSurfaceVariant), + child: Padding( + padding: const EdgeInsets.all(16.0), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Personal Information', + style: theme.textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 16), + InfoField( + label: AppLocalizations.of(context).activeAccounts, + value: user.activeAccounts?.toString() ?? 'N/A', + ), + InfoField( + label: AppLocalizations.of(context).mobileNumber, + value: user.mobileNo ?? 'N/A', + ), + InfoField( + label: AppLocalizations.of(context).dateOfBirth, + 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', + ), // Replace with DOB if available + InfoField( + label: AppLocalizations.of(context).branchCode, + value: user.branchId ?? 'N/A', + ), + InfoField( + label: AppLocalizations.of(context).address, + value: user.address ?? 'N/A', + ), // Replace with Aadhar if available + InfoField( + label: AppLocalizations.of(context).primaryId, + value: _maskPrimaryId(user.primaryId), + ), + ], + ), ), - const SizedBox(height: 30), - InfoField( - label: AppLocalizations.of(context).activeAccounts, - value: user.activeAccounts?.toString() ?? 'N/A', - ), - InfoField( - label: AppLocalizations.of(context).mobileNumber, - value: user.mobileNo ?? 'N/A', - ), - InfoField( - label: AppLocalizations.of(context).dateOfBirth, - 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', - ), // Replace with DOB if available - InfoField( - label: AppLocalizations.of(context).branchCode, - value: user.branchId ?? 'N/A', - ), - InfoField( - label: AppLocalizations.of(context).address, - value: user.address ?? 'N/A', - ), // Replace with Aadhar if available - InfoField( - label: AppLocalizations.of(context).primaryId, - value: _maskPrimaryId(user.primaryId), - ), // Replace with PAN if available - ], + ), + ], + ), + ), + ), + IgnorePointer( + child: Center( + child: Opacity( + opacity: 0.07, // Reduced opacity + child: ClipOval( + child: Image.asset( + 'assets/images/logo.png', + width: 200, // Adjust size as needed + height: 200, // Adjust size as needed + ), ), ), ), ), - ), - IgnorePointer( - child: Center( - child: Opacity( - opacity: 0.07, // Reduced opacity - child: ClipOval( - child: Image.asset( - 'assets/images/logo.png', - width: 200, // Adjust size as needed - height: 200, // Adjust size as needed - ), - ), - ), - ), - ), - ], - ), + ], + ), + ) ); } } @@ -141,16 +189,16 @@ class InfoField extends StatelessWidget { children: [ Text( label, - style: TextStyle( - fontSize: 15, - fontWeight: FontWeight.w500, - color: theme.colorScheme.onSurfaceVariant, + style: theme.textTheme.bodySmall?.copyWith( + color: theme.colorScheme.onSurface.withOpacity(0.6), ), ), - const SizedBox(height: 3), + const SizedBox(height: 4), Text( - value, - style: TextStyle(fontSize: 16, color: theme.colorScheme.onSurface), + value.isEmpty ? 'N/A' : value, + style: theme.textTheme.titleMedium?.copyWith( + fontWeight: FontWeight.w600, + ), ), ], ), diff --git a/lib/features/profile/preferences/preference_screen.dart b/lib/features/profile/preferences/preference_screen.dart index e852133..3204ba2 100644 --- a/lib/features/profile/preferences/preference_screen.dart +++ b/lib/features/profile/preferences/preference_screen.dart @@ -23,42 +23,50 @@ class PreferenceScreen extends StatelessWidget { return Stack( children: [ ListView( + padding: + const EdgeInsets.symmetric(horizontal: 16, vertical: 12), children: [ - //Set Prefered Username - // ListTile( - // leading: const Icon(Icons.person), - // title: const Text("Set Prefered Username"), - // onTap: () { - // }), // Language Selection - ListTile( - leading: const Icon(Icons.language), - title: Text(loc.language), - onTap: () { - showDialog( - context: context, - builder: (_) => const LanguageDialog(), - ); - }, - ), - //Theme Mode Switch (Light/Dark) - ListTile( - leading: const Icon(Icons.brightness_6), - title: Text(AppLocalizations.of(context).themeMode), - onTap: () { - showThemeModeDialog(context); - }, - ), - //Color_Theme_Selection - ListTile( - leading: const Icon(Icons.color_lens), - title: Text(AppLocalizations.of(context).themeColor), + Card( + margin: const EdgeInsets.only(bottom: 10), + child: ListTile( + leading: const Icon(Icons.language), + title: Text(loc.language), + trailing: const Icon(Icons.chevron_right), onTap: () { showDialog( context: context, - builder: (_) => const ColorThemeDialog(), + builder: (_) => const LanguageDialog(), ); - }), + }, + ), + ), + //Theme Mode Switch (Light/Dark) + Card( + margin: const EdgeInsets.only(bottom: 10), + child: ListTile( + leading: const Icon(Icons.brightness_6), + title: Text(AppLocalizations.of(context).themeMode), + trailing: const Icon(Icons.chevron_right), + onTap: () { + showThemeModeDialog(context); + }, + ), + ), + //Color_Theme_Selection + Card( + margin: const EdgeInsets.only(bottom: 10), + child: ListTile( + leading: const Icon(Icons.color_lens), + title: Text(AppLocalizations.of(context).themeColor), + trailing: const Icon(Icons.chevron_right), + onTap: () { + showDialog( + context: context, + builder: (_) => const ColorThemeDialog(), + ); + }), + ), ], ), IgnorePointer( diff --git a/lib/features/profile/profile_screen.dart b/lib/features/profile/profile_screen.dart index 378332a..5e08d9f 100644 --- a/lib/features/profile/profile_screen.dart +++ b/lib/features/profile/profile_screen.dart @@ -1,6 +1,7 @@ import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_svg/svg.dart'; import 'package:kmobile/data/repositories/auth_repository.dart'; import 'package:kmobile/features/profile/daily_transaction_limit.dart'; import 'package:kmobile/features/profile/logout_dialog.dart'; @@ -188,15 +189,14 @@ class _ProfileScreenState extends State { Container( width: 56, height: 56, - decoration: BoxDecoration( - shape: BoxShape.circle, - color: theme.colorScheme.surface, - image: const DecorationImage( - image: AssetImage('assets/images/logo.png'), - fit: BoxFit.cover, - ), +child: CircleAvatar( + radius: 50, + child: SvgPicture.asset( + 'assets/images/avatar_male.svg', + fit: BoxFit.cover, ), ), + ), const SizedBox(width: 12), // Name + mobile Expanded( @@ -221,17 +221,6 @@ class _ProfileScreenState extends State { ], ), ), - // Edit/Profile button (optional) - TextButton.icon( - onPressed: () { - // TODO: Navigate to edit profile if required - }, - icon: const Icon(Icons.edit, size: 18), - label: const Text("Edit"), - style: TextButton.styleFrom( - foregroundColor: theme.colorScheme.onSurface, - ), - ), ], ), ), diff --git a/lib/features/profile/security_settings_screen.dart b/lib/features/profile/security_settings_screen.dart index 5e194cf..a620cc3 100644 --- a/lib/features/profile/security_settings_screen.dart +++ b/lib/features/profile/security_settings_screen.dart @@ -24,99 +24,107 @@ class SecuritySettingsScreen extends StatelessWidget { body: Stack( children: [ ListView( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), children: [ - ListTile( - leading: const Icon(Icons.lock_outline), - title: Text(loc.changeLoginPassword), - trailing: const Icon(Icons.chevron_right), - onTap: () { - Navigator.push( - context, - MaterialPageRoute( - builder: (context) => ChangePasswordScreen( - mobileNumber: mobileNumber, - ), - ), - ); - }, - ), - Divider(height: 1, color: Theme.of(context).dividerColor), - ListTile( - leading: const Icon(Icons.pin), - title: Text(loc.changeMpin), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - final result = await Navigator.push( - context, - MaterialPageRoute( - builder: (context) => const ChangeMpinScreen(), - ), - ); - - if (result == true && context.mounted) { - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text(loc.mpinChangedSuccessfully), - backgroundColor: - Theme.of(context).colorScheme.secondary, + Card( + margin: const EdgeInsets.only(bottom: 10), + child: ListTile( + leading: const Icon(Icons.lock_outline), + title: Text(loc.changeLoginPassword), + trailing: const Icon(Icons.chevron_right), + onTap: () { + Navigator.push( + context, + MaterialPageRoute( + builder: (context) => ChangePasswordScreen( + mobileNumber: mobileNumber, + ), ), ); - } - }, + }, + ), ), - Divider(height: 1, color: Theme.of(context).dividerColor), - ListTile( - leading: const Icon(Icons.password), - title: const Text('Change TPIN'), - trailing: const Icon(Icons.chevron_right), - onTap: () async { - final authService = getIt(); - final isTpinSet = await authService.checkTpin(); + Card( + margin: const EdgeInsets.only(bottom: 10), + child: ListTile( + leading: const Icon(Icons.pin), + title: Text(loc.changeMpin), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + final result = await Navigator.push( + context, + MaterialPageRoute( + builder: (context) => const ChangeMpinScreen(), + ), + ); - if (!isTpinSet) { - if (context.mounted) { - showDialog( - context: context, - builder: (BuildContext context) { - return AlertDialog( - title: const Text('TPIN Not Set'), - content: const Text( - 'You have not set a TPIN yet. Please set a TPIN to proceed.'), - actions: [ - TextButton( - child: const Text('Back'), - onPressed: () { - Navigator.of(context).pop(); - }, - ), - TextButton( - child: const Text('Proceed'), - onPressed: () { - Navigator.of(context).pop(); - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => - const TpinSetScreen(), - ), - ); - }, - ), - ], - ); - }, - ); - } - } else { - if (context.mounted) { - Navigator.of(context).push( - MaterialPageRoute( - builder: (context) => - ChangeTpinScreen(mobileNumber: mobileNumber), + if (result == true && context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar( + content: Text(loc.mpinChangedSuccessfully), + backgroundColor: + Theme.of(context).colorScheme.secondary, ), ); } - } - }, + }, + ), + ), + Card( + margin: const EdgeInsets.only(bottom: 10), + child: ListTile( + leading: const Icon(Icons.password), + title: const Text('Change TPIN'), + trailing: const Icon(Icons.chevron_right), + onTap: () async { + final authService = getIt(); + final isTpinSet = await authService.checkTpin(); + + if (!isTpinSet) { + if (context.mounted) { + showDialog( + context: context, + builder: (BuildContext context) { + return AlertDialog( + title: const Text('TPIN Not Set'), + content: const Text( + 'You have not set a TPIN yet. Please set a TPIN to proceed.'), + actions: [ + TextButton( + child: const Text('Back'), + onPressed: () { + Navigator.of(context).pop(); + }, + ), + TextButton( + child: const Text('Proceed'), + onPressed: () { + Navigator.of(context).pop(); + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + const TpinSetScreen(), + ), + ); + }, + ), + ], + ); + }, + ); + } + } else { + if (context.mounted) { + Navigator.of(context).push( + MaterialPageRoute( + builder: (context) => + ChangeTpinScreen(mobileNumber: mobileNumber), + ), + ); + } + } + }, + ), ), ], ), diff --git a/pubspec.yaml b/pubspec.yaml index bdd1e8d..194aad6 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -114,6 +114,7 @@ flutter: - assets/images/yes_bank_logo.png - assets/images/uco_logo.png - assets/images/ipos_logo.png + - assets/images/profile.svg - assets/animations/rupee.json - assets/animations/error.json - assets/animations/done.json