From 3ba3650e92d93b0c7095c84d57ca86de4d76013d Mon Sep 17 00:00:00 2001 From: venbaittech Date: Tue, 4 Feb 2025 18:35:02 +0530 Subject: [PATCH] App Tour first time login and fiter change --- ...kotlin-compiler-3932177861650478103.salive | 0 android/app/build.gradle | 4 +- assets/icons/misc/vector.png | Bin 0 -> 557 bytes assets/icons/misc/visibility_off.png | Bin 0 -> 1584 bytes assets/icons/misc/visible_on.png | Bin 0 -> 818 bytes lib/config/my_router.dart | 5 +- .../icons/misc_icon_asset_path.dart | 3 + lib/l10n/intl_en.arb | 12 +- .../auth_verification/registration.dart | 188 +++++-- .../Screens/charts/screens/chart_screen.dart | 103 ++-- .../Screens/charts/widgets/chart_widget.dart | 516 +++++++++++++----- .../routes/auth_routes/login_route.dart | 186 ++++--- .../tab_routes/home_route.dart | 257 +++++---- pubspec.yaml | 5 +- 14 files changed, 863 insertions(+), 416 deletions(-) create mode 100644 android/.kotlin/sessions/kotlin-compiler-3932177861650478103.salive create mode 100644 assets/icons/misc/vector.png create mode 100644 assets/icons/misc/visibility_off.png create mode 100644 assets/icons/misc/visible_on.png diff --git a/android/.kotlin/sessions/kotlin-compiler-3932177861650478103.salive b/android/.kotlin/sessions/kotlin-compiler-3932177861650478103.salive new file mode 100644 index 00000000..e69de29b diff --git a/android/app/build.gradle b/android/app/build.gradle index 02d9a058..6891a8ad 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) { def flutterVersionCode = localProperties.getProperty("flutter.versionCode") if (flutterVersionCode == null) { - flutterVersionCode = "6" + flutterVersionCode = "7" } def flutterVersionName = localProperties.getProperty("flutter.versionName") if (flutterVersionName == null) { - flutterVersionName = "1.0.5" + flutterVersionName = "1.0.6" } def keystorePropertiesFile = rootProject.file("key.properties") diff --git a/assets/icons/misc/vector.png b/assets/icons/misc/vector.png new file mode 100644 index 0000000000000000000000000000000000000000..d3783e75655e5e06d23e3f015bb9579f97dccb26 GIT binary patch literal 557 zcmV+|0@D47P)ZlHai=;sq#OCQBj8Vk=J9NOL(?O>Tj^u1>=DP<&O zvA}*tRIIz$Qa39)Ncrn{_UlIZa+64|g^*?&Te@ad0F3&~N{FYxv!9RGLB9eb!^ai@ z1we;!4X}$z)Llj0n0ED=W;F&-f~~3E1B}Sk4C#m>%%Oq9b%Lh*XqEeIV9_dbRY3%FC)=|} zbH=z#S#bGrVG8F4jU0q&mT)!Cta1})YcLA&bc;;hJo_cBV)QPf>r|(xUdR%Fi3M4- zw>bR*&_nRBfqe7msU9=lwH(YK)+;Twsxt3n$oinM1J+XMQ%^~?2>Dv)!2K93s(xK% zfkPukdMLk~C=JPJtF)ey@@|T|9^~L&^mSv?1_xusN@9dYjrv>zpQnUJmIG8Lg>9?X v9mcavlk#7WzjHbY+gPtV?Eiyx1XlD1{<|5N|I58000000NkvXXu0mjfm9O+S literal 0 HcmV?d00001 diff --git a/assets/icons/misc/visibility_off.png b/assets/icons/misc/visibility_off.png new file mode 100644 index 0000000000000000000000000000000000000000..f01af5ba31a5f0f2afc1a5191a5c28da03906bea GIT binary patch literal 1584 zcmV-02G9A4P)Px)>PbXFRCr$PoLg4aFcgMQabVyiWceU2aUjA##3eqsa1!9aq^>lC_LMaF|GjfL za5isx+V154_ATjU*x6rK1%|HH&G^m$bany*U;sKR(Am62fC1>NKxgw70S2J60-eoU z1Q>wM3UoFPN5GF?zt0{YPtLx6KELWb<~L;?0^r0S$CG@crlA)iCV7Atp-J1ZQ^&P0%(nK7Y*c5TG0qkYo{V0U@-v z-m{k;jY}&#a(Ebqf7iWXWV@hR5STP46PP)xAB-#jH;tRyKliA2GUU@Hoy_|{u6>Nvh}1mgAoO)X1%MTQE|B<5oq4MQ+n1V! z=EaeMxV$(Q>nJ`^D!v4QZpF-l;O)uNkqCfR{Pqy|)W=7I3<3?Hl=wX$xGe^@a5B*# zsc#ejW-$H+3D$En1LwvNE4_yW0S3TKJP67}%dtX$05E&^YawevSZ_VJ+m_5t9R_%a zBgP4b;qg7Pl7|4GB5q9zJzu*{U>8?)Az-O43jn2_n@mdx4g@-GNe_=+JEuu@C5)yX z#88iI3uOH0*w^J8g^)`{$q2x_77Mj70qmOoXsI|$vGPK3<6mAIn@jrost2>C5CV%0 zC(3+u3kZ@lG}jyd%xvl}HHS?A2wjahdCx2dA!n<_JhmV!o{W=+E?W;uq@xrB4FGg5 zTQ;Hq5bu|y9zK8W2ewA2bQI{EDHmZW2YLYj=^P|`D(f71b9*=Da%b#!DTJIz(mKE_ z(qdzO0icEV`>>S(kfx)YV`%{(bAkZmJjEGmG1y#mu#r$3K<@f}J}*<%bL7zpVu5NkK90Fa9#1K~TG z@cQZWuf5OJxYt>0Js%o}pc7w}f|f+tbTpsKgFyV78ILp)nDbI&R;8fjh0$CYA53`= zH6fJzdSo#GY>T?>6&{BB9eKPvJ8c-VA$7$JZD9 z?M+nR+;PPL1cSPilpA)v-&;ed2B1zf)DwPr<(3et0tl0mx2tUgk6CF2p$UN33Zeys zrT|_eh}sak09b~6zw}h+J!Up(b_cMA!M<*aPS|;}J9haYs6$vM929`Hn9JUN|C7a2 z*S^>XnpO(WpC=BVI9m%IgVh_tK?6X&TYFqj2nOJZUM~m+U=cn&AQ*sE{%Q@u07ME% zO9%#Fqk^}BU;q*=R0{|OAk)LvhF}1IMMO;q1^@uy4nZNX&j%R*5P&-@cbAV9f7(DH z?AxIU2omuPfY7DZksuY{00;pr(~(Ae1E2s<>Qt)%rIZw2#{dY0D|MOyD5a$EItD-} iT&dFxKq)1K*ZB{M(x=P9 literal 0 HcmV?d00001 diff --git a/assets/icons/misc/visible_on.png b/assets/icons/misc/visible_on.png new file mode 100644 index 0000000000000000000000000000000000000000..b25be6b4595c3657912cbd9901669a6d0e2a107a GIT binary patch literal 818 zcmV-21I_%2P);00009a7bBm000XU z000XU0RWnu7ytkO0drDELIAGL9O(c600d`2O+f$vv5yP?>2K~#7Fl~vtw z+CUKAJz?ybI5Tt*TtP?$mMgIR;KV$DIlBNu1&9h_3P{Ay1B3HGQh{*?qyu#jGI27F zK)2pIfe?}~_P)T}?tR~V`zM4Km^&I3;K8>6;SdxS__r8(Xv+URAh?J9{8*lzPPbv< zvqb%GHjug|K%2n}unkOL2dtna%VqCXghtUHzexaf6NETcD!3N{#xMs@$`H_XIWG5D zQiLT0yyl}~NDMddCf~|ZoFa4wgCfnuow_;-GGSU=s;< zLG0mud1F(xEZf2gYZx;V4q*_HJtgl2Wj}+B3_EojqF-eHL^FV?nxcJK9K#-NQsGg{H9d4Xs?fcpr z)_9YAHxAw~d}c#N{S6t%8=uBrVyy+aJa5)=-h>k;H9jF6zHza-fxNs`7w5Z9n2AMf zZ}@q!7Cj7j24%+JXOWr<$YrjajaU9~fAVZG!H%~^#LJ#ltyWutER%2vO5#7OF$-Cn z$D`90Xieh#ljDj!HX8hp>wLmJupFUwQuVWhYid(z++^IzNMj~$$Cv%92v@{9jlRtt wXLHBBW98wz5i2M4n-@5Lw)g`qw|{`205$lR?3`b$$N&HU07*qoM6N<$g4_&n+yDRo literal 0 HcmV?d00001 diff --git a/lib/config/my_router.dart b/lib/config/my_router.dart index c02c0097..b4ef5ea0 100644 --- a/lib/config/my_router.dart +++ b/lib/config/my_router.dart @@ -328,16 +328,15 @@ final GoRouter router = GoRouter( GoRoute( path: '/', //builder: (context, state) => LoginRoute(), - builder: (context, state) => LoginRoute(), + builder: (context, state) => LoginRoute(isLoginScreen: true), ), GoRoute( path: '/internetcheck', builder: (context, state) => InternetCheck(), - ), GoRoute( path: '/login', - builder: (context, state) => LoginRoute(), + builder: (context, state) => LoginRoute(isLoginScreen: true), //builder: (context, state) => LoginRoute(), ), GoRoute( diff --git a/lib/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart b/lib/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart index 7b4cebd1..55f0bdcd 100644 --- a/lib/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart +++ b/lib/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart @@ -6,4 +6,7 @@ abstract class MiscIconAssetPath { static const menu = '$_basePath/menu.png'; static const person = '$_basePath/person.png'; static const back = '$_basePath/back.png'; + static const vector = '$_basePath/vector.png'; + static const visibleOn = '$_basePath/visible_on.png'; + static const visibilityOff = '$_basePath/visibility_off.png'; } diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index dac0f961..fc0ec46f 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -12,14 +12,16 @@ "enter_your_email": "Enter your email", "enter_your_password": "Enter your password", "register_Confirm_password": "Confirm password", - "agree": "I agree to ", + "agree": "I agree to the", "t_and": " and ", - "conditions": " of Fcsc", - "terms_conditions": "terms & conditions", - "privacy_policy":"privacy policy", - "account_confirmation": "Already have an account? Login", + "conditions": " of FCSC", + "terms_conditions": "Terms & Conditions", + "privacy_policy":"Privacy Policy", + "account_confirmation": "Already have an account?", "login_title": "Login", + + "profile_title": "Edit Profile", "my_profile": "My Profile", "logout": "Logout", diff --git a/lib/presentation/Screens/auth_verification/registration.dart b/lib/presentation/Screens/auth_verification/registration.dart index a4650aad..ab0e9586 100644 --- a/lib/presentation/Screens/auth_verification/registration.dart +++ b/lib/presentation/Screens/auth_verification/registration.dart @@ -1,10 +1,13 @@ +import 'package:external_repos/external_repos.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/my_theme.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; +import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; import 'package:uae_stat/presentation/Screens/profilepage.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; @@ -471,14 +474,15 @@ class _RegisterScreenState extends State { ), ) : Padding( - padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.only(top: 5.0,bottom: 20, left: 20,right: 20), + child: Form( key: _formKey, child: SingleChildScrollView( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: [ - SizedBox(height: screenheight / 15), + SizedBox(height: screenheight / 60), Text( // 'Register', AppLocalizations.of(context)!.register_title, @@ -492,18 +496,42 @@ class _RegisterScreenState extends State { // Display this if registration is pending approval TextFormField( controller: _usernameController, - focusNode: _focusNodes[0], + // focusNode: _focusNodes[0], decoration: InputDecoration( // hintText: _showHints[0] ? 'Username' : null, hintText: _showHints[0] ? AppLocalizations.of(context)!.register_name : null, - prefixIcon: Icon( - Icons.person, - color: Colors.blue, + prefixIcon: Padding( + padding: const EdgeInsets.all(8.0), // Adjust the padding as needed + child: Image.asset( + MiscIconAssetPath.person, + color: Color(0xFF90B0D5), + width: 24, + height: 24, + ), + ), + + // prefixIcon: Icon( + // Icons.person, + // color: Color(0xFF90B0D5), + // + // ), + // border: OutlineInputBorder(), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Color(0xFF90B0D5), width: 2), // Enabled border + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Colors.deepPurple, width: 2), // Focused border + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Color(0xFFD83731), width: 1), // Error border ), - border: OutlineInputBorder(), counterText: '', + hintStyle: TextStyle(color: Color(0xFFC3C6CB)), ), validator: _validateUsername, maxLength: @@ -513,7 +541,7 @@ class _RegisterScreenState extends State { SizedBox(height: 15), TextFormField( controller: _emailController, - focusNode: _focusNodes[1], + // focusNode: _focusNodes[1], decoration: InputDecoration( // hintText: 'Enter your email', hintText: _showHints[1] @@ -521,12 +549,30 @@ class _RegisterScreenState extends State { .enter_your_email : null, // _showHints[1] ? 'Enter your email' : null, - prefixIcon: Icon( - Icons.email, - color: Colors.blue, + prefixIcon: Padding( + padding: const EdgeInsets.all(8.0), // Adjust the padding as needed + child: Image.asset( + MiscIconAssetPath.vector, + color: Color(0xFF90B0D5), + width: 24, + height: 24, + ), + ), + // border: OutlineInputBorder(), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Color(0xFF90B0D5), width: 2), // Enabled border + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Colors.deepPurple, width: 2), // Focused border + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Color(0xFFD83731), width: 1), // Error border ), - border: OutlineInputBorder(), counterText: '', + hintStyle: TextStyle(color: Color(0xFFC3C6CB)), ), validator: _validateEmail, maxLength: 320, @@ -539,7 +585,7 @@ class _RegisterScreenState extends State { SizedBox(height: 15), TextFormField( controller: _passwordController, - focusNode: _focusNodes[2], + // focusNode: _focusNodes[2], obscureText: _obscurePassword, decoration: InputDecoration( hintText: _showHints[2] @@ -547,25 +593,59 @@ class _RegisterScreenState extends State { .enter_your_password : null, // _showHints[2] ? 'Enter your password' : null, - prefixIcon: Icon( - Icons.lock, - color: Colors.blue, - ), - suffixIcon: IconButton( - icon: Icon( - _obscurePassword - ? Icons.visibility_off - : Icons.visibility, - color: Colors.blue, + prefixIcon: Padding( + padding: const EdgeInsets.all(8.0), // Adjust the padding as needed + child: Image.asset( + MiscIconAssetPath.lock, + color: Color(0xFF90B0D5), + width: 24, + height: 24, ), + ), + // prefixIcon: Icon( + // Icons.lock, + // color: Color(0xFF90B0D5), + // ), + suffixIcon: IconButton( + // icon: Icon( + // _obscurePassword + // ? Icons.visibility_off + // : Icons.visibility, + // color: Color(0xFF9EA2A9), + // ), + + icon: Image.asset( + _obscurePassword + ?MiscIconAssetPath.visibilityOff + :MiscIconAssetPath.visibleOn, + + color: Color(0xFF9EA2A9), // Apply color if needed, but keep in mind `Image.asset` might not support color directly. + width: 24, + height: 24, + ), + + onPressed: () { setState(() { _obscurePassword = !_obscurePassword; }); }, ), - border: OutlineInputBorder(), + // border: OutlineInputBorder(), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Color(0xFF90B0D5), width: 2), // Enabled border + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Colors.deepPurple, width: 2), // Focused border + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Color(0xFFD83731), width: 1), // Error border + ), counterText: '', + hintStyle: TextStyle(color: Color(0xFFC3C6CB)), ), validator: _validatePassword, maxLength: 40, @@ -574,7 +654,7 @@ class _RegisterScreenState extends State { SizedBox(height: 15), TextFormField( controller: _confirmpasswordController, - focusNode: _focusNodes[3], + // focusNode: _focusNodes[3], obscureText: _obscureConfirmPassword, decoration: InputDecoration( hintText: _showHints[3] @@ -582,16 +662,25 @@ class _RegisterScreenState extends State { .register_Confirm_password : null, // _showHints[3] ? 'Confirm password' : null, - prefixIcon: Icon( - Icons.lock, - color: Colors.blue, + prefixIcon: Padding( + padding: const EdgeInsets.all(8.0), // Adjust the padding as needed + child: Image.asset( + MiscIconAssetPath.lock, + color: Color(0xFF90B0D5), + width: 24, + height: 24, + ), ), suffixIcon: IconButton( - icon: Icon( + + icon: Image.asset( _obscureConfirmPassword - ? Icons.visibility_off - : Icons.visibility, - color: Colors.blue, + ?MiscIconAssetPath.visibilityOff + :MiscIconAssetPath.visibleOn, + + color: Color(0xFF9EA2A9), // Apply color if needed, but keep in mind `Image.asset` might not support color directly. + width: 24, + height: 24, ), onPressed: () { setState(() { @@ -600,8 +689,23 @@ class _RegisterScreenState extends State { }); }, ), - border: OutlineInputBorder(), + // border: OutlineInputBorder( + // borderSide: BorderSide(color: Colors.blue, width: 2), // Default border color + // ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Color(0xFF90B0D5), width: 2), // Enabled border + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Colors.deepPurple, width: 2), // Focused border + ), + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide(color: Color(0xFFD83731), width: 1), // Error border + ), counterText: '', + hintStyle: TextStyle(color: Color(0xFFC3C6CB)), ), validator: _validateConfirmPassword, maxLength: 40, @@ -623,7 +727,7 @@ class _RegisterScreenState extends State { }); }, side: BorderSide( - color: showError ? Colors.red : Colors.grey, + color: showError ? Colors.red : Color(0xFF92722A), width: 1.5, ), ), @@ -637,7 +741,7 @@ class _RegisterScreenState extends State { text: AppLocalizations.of(context)! .terms_conditions, // text: 'Terms & Conditions', - style: TextStyle(color: Colors.blue), + style: TextStyle( color: MyTheme.topicColor(IndicatorTopic.economy).shade600,), ), TextSpan( text: AppLocalizations.of(context)! @@ -645,7 +749,7 @@ class _RegisterScreenState extends State { TextSpan( text: AppLocalizations.of(context)! .privacy_policy, - style: TextStyle(color: Colors.blue), + style: TextStyle( color: MyTheme.topicColor(IndicatorTopic.economy).shade600,), ), TextSpan( text: AppLocalizations.of(context)! @@ -695,8 +799,10 @@ class _RegisterScreenState extends State { fontSize: 16, color: Colors.white), ), SizedBox(width: 8), - Icon(Icons.arrow_forward, - color: Colors.white), + const Icon( + Icons.chevron_right_outlined, + color: Colors.white, // Set your desired color here + ) ], ), ), @@ -730,8 +836,10 @@ class _RegisterScreenState extends State { fontSize: 16, color: Colors.white), ), SizedBox(width: 8), - Icon(Icons.arrow_forward, - color: Colors.white), + const Icon( + Icons.chevron_right_outlined, + color: Colors.white, // Set your desired color here + ) ], ), diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index c962a673..87d07f82 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -369,9 +369,15 @@ class _ChartScreen1State extends ConsumerState { child: ListView.builder( itemCount: filters.length, itemBuilder: (context, index) { + filters.sort((a, b) => a["filter_text_and_order"]["order"] + .compareTo(b["filter_text_and_order"]["order"])); + final filter = filters[index]; final filterKey = filter["filter_key"]; final filterData = filter["filter_data"]; + final filter_text_and_order = + filter["filter_text_and_order"]; + final fieldOrder = filter_text_and_order['order']; return StatefulBuilder( builder: (context, setState) { @@ -386,7 +392,9 @@ class _ChartScreen1State extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( - capitalizeAndSplit(filterKey), + context.translate(filter_text_and_order['en'], + filter_text_and_order['ar']), + // capitalizeAndSplit(filterKey), style: TextStyle( fontSize: 16, fontWeight: FontWeight.bold, @@ -399,8 +407,13 @@ class _ChartScreen1State extends ConsumerState { builder: (BuildContext context) { return StatefulBuilder( builder: (context, dialogSetState) { + final locale = + ref.watch(localeProvider); + print('localelocale $locale'); return AlertDialog( - title: Text('Select $filterKey'), + title: Text( + // "${locale == 'ar' ? 'يختار ' : 'Select '}" + "${context.translate(filter_text_and_order['en'], filter_text_and_order['ar'])}"), content: SingleChildScrollView( child: ListBody( children: filterData @@ -465,7 +478,9 @@ class _ChartScreen1State extends ConsumerState { children: selectedFilter["filter_data"].isEmpty ? [ - Text('Select $filterKey', + Text( + // "${locale == 'ar' ? 'يختار ' : 'Select '}" + "${context.translate(filter_text_and_order['en'], filter_text_and_order['ar'])}", style: TextStyle( color: Colors.grey)) ] @@ -1023,26 +1038,31 @@ class _ChartScreen1State extends ConsumerState { Flexible( fit: FlexFit.loose, child: FittedBox( - child: Text( - '${chart_heading ?? 'NA'}', - textAlign: TextAlign.center, - maxLines: 2, // Limit to 2 lines - softWrap: - true, // Enable soft wrapping - // overflow: TextOverflow.ellipsis, // Handle overflow gracefully - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.w400, - color: Colors.black87, + child: SizedBox( + // height: 70.0, + child: Text( + '${chart_heading ?? 'NA'}', + textAlign: TextAlign.center, + maxLines: 2, // Limit to 2 lines + softWrap: + true, // Enable soft wrapping + // overflow: TextOverflow.ellipsis, // Handle overflow gracefully + style: TextStyle( + fontSize: 8, + fontWeight: FontWeight.w400, + color: Colors.black87, + ), ), ), ), ), + const SizedBox(height: 1), Text( '(${data['lastYear'] ?? 'NA'})', style: const TextStyle( - fontSize: 11, color: Colors.grey), + fontSize: 10, color: Colors.grey), ), + const SizedBox(height: 1), Flexible( fit: FlexFit.loose, child: FittedBox( @@ -1051,7 +1071,7 @@ class _ChartScreen1State extends ConsumerState { apiService.formatAmount( data['lastYearValue']), style: const TextStyle( - fontSize: 26, + fontSize: 18, fontWeight: FontWeight.w900, color: Color(0xFF90B0D5), ), @@ -1074,7 +1094,7 @@ class _ChartScreen1State extends ConsumerState { apiService.formatAmount( data['secondLastYearValue']), style: const TextStyle( - fontSize: 16, + fontSize: 14, fontWeight: FontWeight.w600, color: Color(0xFFD83731), ), @@ -1084,7 +1104,7 @@ class _ChartScreen1State extends ConsumerState { Text( '(${data['secondLastYear'] ?? 'NA'})', style: const TextStyle( - fontSize: 8, + fontSize: 9, fontWeight: FontWeight.w500, color: Colors.grey), ), @@ -1120,37 +1140,42 @@ class _ChartScreen1State extends ConsumerState { const SizedBox(height: 5), Flexible( fit: FlexFit.loose, - child: FittedBox( - child: Text( - '${chart_heading ?? 'NA'}', - textAlign: TextAlign.center, - maxLines: 2, // Limit to 2 lines - softWrap: - true, // Enable soft wrapping - // overflow: TextOverflow.ellipsis, // Handle overflow gracefully - style: TextStyle( - fontSize: 11, - fontWeight: FontWeight.w400, - color: Colors.black87, - ), + // child: FittedBox( + child: Text( + '${chart_heading ?? 'NA'}', + textAlign: TextAlign.center, + maxLines: 2, // Limit to 2 lines + softWrap: + true, // Enable soft wrapping + // overflow: TextOverflow.ellipsis, // Handle overflow gracefully + style: TextStyle( + fontSize: 9, + fontWeight: FontWeight.w400, + color: Colors.black87, ), ), + // ), ), + const SizedBox(height: 1), Text( '(${data['firstYear'] ?? 'NA'} - ${data['lastYear'] ?? 'NA'})', style: const TextStyle( fontSize: 10, color: Colors.grey), ), + const SizedBox(height: 1), Flexible( fit: FlexFit.loose, - child: FittedBox( - fit: BoxFit.contain, - child: Text( - '${data['roundedAverage'] ?? 'NA'}', - style: const TextStyle( - fontSize: 26, - fontWeight: FontWeight.w900, - color: Color(0xFF90B0D5), + child: SizedBox( + height: 50.0, + child: FittedBox( + fit: BoxFit.contain, + child: Text( + '${data['roundedAverage'] ?? 'NA'}', + style: const TextStyle( + fontSize: 20, + fontWeight: FontWeight.w900, + color: Color(0xFF90B0D5), + ), ), ), ), diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index ca303309..59321013 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -538,6 +538,7 @@ class ChartWidget extends StatelessWidget { color: groupColorMap[group], ), SizedBox(width: 6), + Text( group, style: TextStyle(fontSize: 14), @@ -789,12 +790,26 @@ class ChartWidget extends StatelessWidget { bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, + interval: 1, getTitlesWidget: (value, meta) { if (value.toInt() < xAxisData.length) { + String title = xAxisData[value.toInt()]; + String displayTitle = title.length > 10 ? title.substring(0, 10) + '...' : title; + return Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text(xAxisData[value.toInt()]), - ); + padding: const EdgeInsets.only(top: 8.0), + child: SizedBox( + width: 60, // Limit width to force wrapping + child: Transform.rotate( + angle: -0.5, + child:Tooltip( + message: title, + child: Text( + displayTitle, + softWrap: true, + overflow: TextOverflow.ellipsis, + )),) + )); } return Container(); }, @@ -994,19 +1009,36 @@ class ChartWidget extends StatelessWidget { bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, - reservedSize: 20, // Added space for rotated titles + reservedSize: 40, // Added space for rotated titles getTitlesWidget: (value, meta) { if (value < groupByValues.length) { String title = groupByValues.elementAt(value.toInt()); - return Transform.rotate( - angle: - -0.5, // Rotation in radians (~ -30 degrees) - child: Text( - title, - style: const TextStyle(fontSize: 12), - ), - ); + + String displayTitle = title.length > 10 ? title.substring(0, 10) + '...' : title; + + return Padding( + padding: const EdgeInsets.only(top: 8.0), + child: SizedBox( + width: 60, // Limit width to force wrapping + child: Transform.rotate( + angle: -0.5, + child:Tooltip( + message: title, + child: Text( + displayTitle, + softWrap: true, + overflow: TextOverflow.ellipsis, + )),) + )); + // return Transform.rotate( + // angle: + // -0.5, // Rotation in radians (~ -30 degrees) + // child: Text( + // title, + // style: const TextStyle(fontSize: 12), + // ), + // ); } return const SizedBox.shrink(); }, @@ -1150,152 +1182,341 @@ class ChartWidget extends StatelessWidget { SizedBox(height: 10), // Chart Expanded( - child: BarChart( - BarChartData( - maxY: 400000, - rotationQuarterTurns: rotationTurns, - barTouchData: BarTouchData( - touchTooltipData: BarTouchTooltipData( - tooltipHorizontalAlignment: FLHorizontalAlignment.center, - // Only show tooltip when touched - getTooltipItem: (group, groupIndex, rod, rodIndex) { - if (rod.toY == 0 || touchedGroupIndex == -1) { - return null; // Don't show the tooltip if the value is 0 or there's no touch - } - - if (groupIndex == touchedGroupIndex) { - // print('Group Index: $groupIndex, Group : $group'); - - // Get the group label dynamically - String groupLabel = groupByValues.elementAt(groupIndex); - - // Fetch the crop for the current group from groupedCrops - String cropType = groupByValues.elementAt(groupIndex); - String crop = groupedCrops[cropType]![rodIndex]; - double value = rod.toY; - - String formattedValue; - if (value >= 1000000) { - formattedValue = - (value / 1000000).toStringAsFixed(1) + 'M'; - } else if (value >= 1000) { - formattedValue = - (value / 1000).toStringAsFixed(1) + 'K'; - } else { - formattedValue = value - .toStringAsFixed(0); // for values smaller than 1000 + child: BarChart( + BarChartData( + maxY: 400000, + rotationQuarterTurns: rotationTurns, + barTouchData: BarTouchData( + touchTooltipData: BarTouchTooltipData( + tooltipHorizontalAlignment: FLHorizontalAlignment.center, + tooltipRoundedRadius: 8, + fitInsideHorizontally: true, // Ensure it fits within the screen + fitInsideVertically: true, + tooltipPadding: EdgeInsets.all(8), + tooltipMargin: 16, + // Only show tooltip when touched + getTooltipItem: (group, groupIndex, rod, rodIndex) { + if (rod.toY == 0 || touchedGroupIndex == -1) { + return null; // Don't show the tooltip if the value is 0 or there's no touch } - return BarTooltipItem( - '$groupLabel\n$crop', - const TextStyle( - color: Colors.white, - fontWeight: FontWeight.bold, - ), - children: [ - TextSpan( - text: ' Value: $formattedValue', - style: const TextStyle( - color: Colors.yellow, - fontWeight: FontWeight.w500, + if (groupIndex == touchedGroupIndex) { + // print('Group Index: $groupIndex, Group : $group'); + + // Get the group label dynamically + String groupLabel = groupByValues.elementAt(groupIndex); + + // Fetch the crop for the current group from groupedCrops + String cropType = groupByValues.elementAt(groupIndex); + String crop = groupedCrops[cropType]![rodIndex]; + double value = rod.toY; + + String formattedValue; + if (value >= 1000000) { + formattedValue = + (value / 1000000).toStringAsFixed(1) + 'M'; + } else if (value >= 1000) { + formattedValue = + (value / 1000).toStringAsFixed(1) + 'K'; + } else { + formattedValue = value.toStringAsFixed( + 0); // for values smaller than 1000 + } + + return BarTooltipItem( + '$groupLabel\n$crop', + const TextStyle( + color: Colors.white, + fontWeight: FontWeight.bold, + ), + children: [ + TextSpan( + text: ' Value: $formattedValue', + style: const TextStyle( + color: Colors.yellow, + fontWeight: FontWeight.w500, + ), ), - ), - ], - ); - } - return null; - }, - ), - touchCallback: (event, response) { - if (event.isInterestedForInteractions && - response != null && - response.spot != null) { - // setState(() { - touchedGroupIndex = response.spot!.touchedBarGroupIndex; - // }); - } else { - // setState(() { - touchedGroupIndex = -1; // Reset if no interaction - // }); - } - }, - ), - titlesData: FlTitlesData( - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: false, - reservedSize: 20, - interval: 100000, - getTitlesWidget: (value, meta) { - return Text( - value.toInt().toString(), - style: const TextStyle(fontSize: 12), - ); - }, - ), - ), - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - reservedSize: 80, // Added space for rotated titles - getTitlesWidget: (value, meta) { - if (value < groupByValues.length) { - String title = groupByValues.elementAt(value.toInt()); - return Transform.rotate( - angle: -1.58, // Rotation in radians (~ -30 degrees) - child: Center( - child: SizedBox( - width: 80, - child: Text( - title, - style: const TextStyle(fontSize: 12), - softWrap: true, - maxLines: 2, - ), - ), - ), + ], ); } - return const SizedBox.shrink(); + return null; }, ), + touchCallback: (event, response) { + if (event.isInterestedForInteractions && + response != null && + response.spot != null) { + // setState(() { + touchedGroupIndex = response.spot!.touchedBarGroupIndex; + // }); + } else { + // setState(() { + touchedGroupIndex = -1; // Reset if no interaction + // }); + } + }, ), - rightTitles: - AxisTitles(sideTitles: SideTitles(showTitles: false)), - topTitles: - AxisTitles(sideTitles: SideTitles(showTitles: false)), - ), - borderData: FlBorderData( - show: true, - border: const Border( - // left: BorderSide(color: Colors.grey), - bottom: BorderSide(color: Colors.white), + titlesData: FlTitlesData( + leftTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: false, + reservedSize: 20, + interval: 100000, + getTitlesWidget: (value, meta) { + return Text( + value.toInt().toString(), + style: const TextStyle(fontSize: 12), + ); + }, + ), + ), + bottomTitles: AxisTitles( + sideTitles: SideTitles( + showTitles: true, + reservedSize: 80, // Added space for rotated titles + getTitlesWidget: (value, meta) { + if (value < groupByValues.length) { + String title = groupByValues.elementAt(value.toInt()); + return Transform.rotate( + angle: -1.58, // Rotation in radians (~ -30 degrees) + child: Center( + child: SizedBox( + width: 80, + child: Text( + title, + style: const TextStyle(fontSize: 12), + softWrap: true, + maxLines: 2, + ), + ), + ), + ); + } + return const SizedBox.shrink(); + }, + ), + ), + rightTitles: + AxisTitles(sideTitles: SideTitles(showTitles: false)), + topTitles: + AxisTitles(sideTitles: SideTitles(showTitles: false)), ), + borderData: FlBorderData( + show: true, + border: const Border( + // left: BorderSide(color: Colors.grey), + bottom: BorderSide(color: Colors.white), + ), + ), + gridData: FlGridData( + show: false, + drawVerticalLine: true, + verticalInterval: 1, + horizontalInterval: 100000, + getDrawingHorizontalLine: (value) { + return FlLine( + color: Colors.grey.withOpacity(0.5), + strokeWidth: 1, + ); + }, + getDrawingVerticalLine: (value) { + return FlLine( + color: Colors.grey.withOpacity(0.5), + strokeWidth: 1, + ); + }, + ), + barGroups: + _buildHorizontalRotateBarGroups(chartData, groupByValues), + alignment: BarChartAlignment.spaceAround, ), - gridData: FlGridData( - show: false, - drawVerticalLine: true, - verticalInterval: 1, - horizontalInterval: 100000, - getDrawingHorizontalLine: (value) { - return FlLine( - color: Colors.grey.withOpacity(0.5), - strokeWidth: 1, - ); - }, - getDrawingVerticalLine: (value) { - return FlLine( - color: Colors.grey.withOpacity(0.5), - strokeWidth: 1, - ); - }, - ), - barGroups: - _buildHorizontalRotateBarGroups(chartData, groupByValues), - alignment: BarChartAlignment.spaceAround, ), - )) + ) + // Expanded( + // child: Stack( + // children:[ + // BarChart( + // BarChartData( + // maxY: 400000, + // rotationQuarterTurns: rotationTurns, + // barTouchData: BarTouchData( + // touchTooltipData: BarTouchTooltipData( + // tooltipHorizontalAlignment: FLHorizontalAlignment.center, + // // Only show tooltip when touched + // getTooltipItem: (group, groupIndex, rod, rodIndex) { + // if (rod.toY == 0 || touchedGroupIndex == -1) { + // return null; // Don't show the tooltip if the value is 0 or there's no touch + // } + // + // if (groupIndex == touchedGroupIndex) { + // // print('Group Index: $groupIndex, Group : $group'); + // + // // Get the group label dynamically + // String groupLabel = groupByValues.elementAt(groupIndex); + // + // // Fetch the crop for the current group from groupedCrops + // String cropType = groupByValues.elementAt(groupIndex); + // String crop = groupedCrops[cropType]![rodIndex]; + // double value = rod.toY; + // + // String formattedValue; + // if (value >= 1000000) { + // formattedValue = + // (value / 1000000).toStringAsFixed(1) + 'M'; + // } else if (value >= 1000) { + // formattedValue = + // (value / 1000).toStringAsFixed(1) + 'K'; + // } else { + // formattedValue = value + // .toStringAsFixed(0); // for values smaller than 1000 + // } + // + // return BarTooltipItem( + // '$groupLabel\n$crop', + // const TextStyle( + // color: Colors.white, + // fontWeight: FontWeight.bold, + // ), + // children: [ + // TextSpan( + // text: ' Value: $formattedValue', + // style: const TextStyle( + // color: Colors.yellow, + // fontWeight: FontWeight.w500, + // ), + // ), + // ], + // ); + // } + // return null; + // }, + // ), + // touchCallback: (event, response) { + // if (event.isInterestedForInteractions && + // response != null && + // response.spot != null) { + // // setState(() { + // touchedGroupIndex = response.spot!.touchedBarGroupIndex; + // // }); + // } else { + // // setState(() { + // touchedGroupIndex = -1; // Reset if no interaction + // // }); + // } + // }, + // ), + // titlesData: FlTitlesData( + // leftTitles: AxisTitles( + // sideTitles: SideTitles( + // showTitles: false, + // reservedSize: 20, + // interval: 100000, + // getTitlesWidget: (value, meta) { + // return Text( + // value.toInt().toString(), + // style: const TextStyle(fontSize: 12), + // ); + // }, + // ), + // ), + // bottomTitles: AxisTitles( + // sideTitles: SideTitles( + // showTitles: true, + // reservedSize: 80, // Added space for rotated titles + // getTitlesWidget: (value, meta) { + // if (value < groupByValues.length) { + // String title = groupByValues.elementAt(value.toInt()); + // return Transform.rotate( + // angle: -1.58, // Rotation in radians (~ -30 degrees) + // child: Center( + // child: SizedBox( + // width: 80, + // child: Text( + // title, + // style: const TextStyle(fontSize: 12), + // softWrap: true, + // maxLines: 2, + // ), + // ), + // ), + // ); + // } + // return const SizedBox.shrink(); + // }, + // ), + // ), + // rightTitles: + // AxisTitles(sideTitles: SideTitles(showTitles: false)), + // topTitles: + // AxisTitles(sideTitles: SideTitles(showTitles: false)), + // ), + // borderData: FlBorderData( + // show: true, + // border: const Border( + // // left: BorderSide(color: Colors.grey), + // bottom: BorderSide(color: Colors.white), + // ), + // ), + // gridData: FlGridData( + // show: false, + // drawVerticalLine: true, + // verticalInterval: 1, + // horizontalInterval: 100000, + // getDrawingHorizontalLine: (value) { + // return FlLine( + // color: Colors.grey.withOpacity(0.5), + // strokeWidth: 1, + // ); + // }, + // getDrawingVerticalLine: (value) { + // return FlLine( + // color: Colors.grey.withOpacity(0.5), + // strokeWidth: 1, + // ); + // }, + // ), + // barGroups: + // _buildHorizontalRotateBarGroups(chartData, groupByValues), + // alignment: BarChartAlignment.spaceAround, + // ), + // + // ), + // // Overlay Texts + // ..._buildHorizontalRotateBarGroups(chartData, groupByValues) + // .asMap() + // .entries + // .expand((entry) { + // int groupIndex = entry.key; + // BarChartGroupData groupData = entry.value; + // return groupData.barRods.asMap().entries.map((rodEntry) { + // int rodIndex = rodEntry.key; + // BarChartRodData rodData = rodEntry.value; + // + // // Position calculation + // double barHeight = rodData.toY / 400000 * MediaQuery.of(context).size.height; + // + // return Positioned( + // left: (groupIndex * 80).toDouble() + 20, // Adjust based on spacing + // bottom: barHeight / 2, // Centered inside the bar + // child: Transform.rotate( + // angle: -0.1, + // child: Text( + // // '${rodData.toY.toInt()}', + // "123", + // style: TextStyle( + // color: Colors.black, + // fontWeight: FontWeight.bold, + // fontSize: 12, + // ), + // ), + // ), + // ); + // }).toList(); + // }).toList(), + // ])) ]); + default: return Center(child: Text('Unknown chart type')); } @@ -1778,12 +1999,11 @@ class ChartWidget extends StatelessWidget { toY: value, // Use the parsed value color: barColor, // Dynamic color width: 20, - // backDrawRodData: BackgroundBarChartRodData( + // backDrawRodData: BackgroundBarChartRodData( // show: true, // toY: 400000, // color: Colors.grey.shade300, // ), - // ); }).toList(); diff --git a/lib/presentation/routes/auth_routes/login_route.dart b/lib/presentation/routes/auth_routes/login_route.dart index b74d62f2..5a43b9ee 100644 --- a/lib/presentation/routes/auth_routes/login_route.dart +++ b/lib/presentation/routes/auth_routes/login_route.dart @@ -1,5 +1,6 @@ import 'package:external_repos/external_repos.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; @@ -17,7 +18,7 @@ import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart'; import 'package:uae_stat/presentation/components/space.dart'; import 'package:uae_stat/presentation/components/themed_text_field.dart'; import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart'; - +import 'package:http/http.dart' as http; import '../../Screens/auth_verification/registration.dart'; import 'package:pocketbase/pocketbase.dart'; @@ -27,7 +28,9 @@ import '../../components/my_toggle.dart'; class LoginRoute extends HookConsumerWidget { final pb = PocketBase('https://pb.venbait.in'); // final _pb = PocketBase('http://127.0.0.1:8090'); - LoginRoute({super.key}); + final bool isLoginScreen; // Pass `true` if this is the login screen + LoginRoute({Key? key, required this.isLoginScreen}) : super(key: key); + // LoginRoute({super.key}); dynamic userData; String? role; @@ -253,6 +256,22 @@ class LoginRoute extends HookConsumerWidget { if (!context.mounted || session == null) return; final userId = session.id; if (userId.isNotEmpty) { + final url = + Uri.parse("https://pb.venbait.in/api/login_success?id=$userId"); + + try { + final response = await http.get(url); + + if (response.statusCode == 200) { + print("Login success API call successful: ${response.body}"); + } else { + print( + "Failed to call login success API. Status code: ${response.statusCode}"); + } + } catch (e) { + print("Error calling login success API: $e"); + } + await saveUserId(userId); } try { @@ -340,7 +359,10 @@ class LoginRoute extends HookConsumerWidget { ), ), 6.horizontalSpace, - const Icon(Icons.chevron_right_outlined), + const Icon( + Icons.chevron_right_outlined, + color: Colors.white, // Set your desired color here + ) ], ), ), @@ -368,8 +390,7 @@ class LoginRoute extends HookConsumerWidget { validator: (text) { if (text == null || text.isEmpty) { return context.translate('Required', 'مطلوب'); - } - else if (text.length < 8) { + } else if (text.length < 8) { return 'The password must be at least 8 characters'; } return FieldValidator.password(minLength: 8)(text); @@ -411,7 +432,7 @@ class LoginRoute extends HookConsumerWidget { 10.verticalSpace, Text( context.translate( - 'Please login to access UAE’s key official statistics', + 'Please login to access \n UAE’s key official statistics', 'يرجى تسجيل الدخول للوصول إلى الإحصاءات الرسمية الرئيسية لدولة الإمارات العربية المتحدة', ), textAlign: TextAlign.center, @@ -422,7 +443,7 @@ class LoginRoute extends HookConsumerWidget { ), fontSize: 18, color: const Color(0xff898C81), - fontWeight: FontWeight.w700, + fontWeight: FontWeight.w600, ), ), ], @@ -466,61 +487,61 @@ class LoginRoute extends HookConsumerWidget { ), ), ); - final continueAsGuestBtn = SizedBox( - width: double.infinity, - child: ElevatedButton( - onPressed: () async { - final prefs = await SharedPreferences.getInstance(); - prefs.clear(); - final userId = 'guest'; - if (userId.isNotEmpty) { - await saveUserId(userId); - } - context.go('/myhomepage'); - //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), - }, - //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), - style: ButtonStyle( - shape: WidgetStatePropertyAll( - RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - padding: const WidgetStatePropertyAll( - EdgeInsets.symmetric(vertical: 10.5), - ), - textStyle: WidgetStatePropertyAll( - TextStyle( - fontFamily: context.translate( - 'Roboto', - 'NotoKufi', - ), - fontSize: 16, - fontWeight: FontWeight.w600, - ), - ), - backgroundColor: WidgetStatePropertyAll( - MyTheme.topicColor(IndicatorTopic.environment), - ), - foregroundColor: const WidgetStatePropertyAll( - Colors.white, - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - Text( - context.translate( - 'Continue as Guest', - 'استمر كضيف', - ), - ), - 6.horizontalSpace, - const Icon(Icons.chevron_right_outlined), - ], - ), - ), - ); + // final continueAsGuestBtn = SizedBox( + // width: double.infinity, + // child: ElevatedButton( + // onPressed: () async { + // final prefs = await SharedPreferences.getInstance(); + // prefs.clear(); + // final userId = 'guest'; + // if (userId.isNotEmpty) { + // await saveUserId(userId); + // } + // context.go('/myhomepage'); + // //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), + // }, + // //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), + // style: ButtonStyle( + // shape: WidgetStatePropertyAll( + // RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(10), + // ), + // ), + // padding: const WidgetStatePropertyAll( + // EdgeInsets.symmetric(vertical: 10.5), + // ), + // textStyle: WidgetStatePropertyAll( + // TextStyle( + // fontFamily: context.translate( + // 'Roboto', + // 'NotoKufi', + // ), + // fontSize: 16, + // fontWeight: FontWeight.w600, + // ), + // ), + // backgroundColor: WidgetStatePropertyAll( + // MyTheme.topicColor(IndicatorTopic.environment), + // ), + // foregroundColor: const WidgetStatePropertyAll( + // Colors.white, + // ), + // ), + // child: Row( + // mainAxisAlignment: MainAxisAlignment.center, + // children: [ + // Text( + // context.translate( + // 'Continue as Guest', + // 'استمر كضيف', + // ), + // ), + // 6.horizontalSpace, + // const Icon(Icons.chevron_right_outlined), + // ], + // ), + // ), + // ); final fcscBanner = Image.asset( BannerAssetPath.fcsc, height: 40, @@ -554,15 +575,46 @@ class LoginRoute extends HookConsumerWidget { 20.verticalSpace, dontHaveAnAccountRegisterBtn, 20.verticalSpace, - continueAsGuestBtn, + // continueAsGuestBtn, 25.verticalSpace, fcscBanner, ], ); - final bgScaffold = Scaffold( - backgroundColor: Colors.white, - body: SafeArea(child: scaffoldBody), + // final bgScaffold = Scaffold( + // backgroundColor: Colors.white, + // body: SafeArea(child: scaffoldBody), + // ); + // return bgScaffold; + return PopScope( + canPop: !isLoginScreen, // Allow back navigation only if not login screen + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + _showExitConfirmation(context); // Show exit confirmation dialog + }, + child: Scaffold( + backgroundColor: Colors.white, + body: SafeArea(child: scaffoldBody), + ), + ); + } + + void _showExitConfirmation(BuildContext context) { + showDialog( + context: context, + builder: (context) => AlertDialog( + title: Text("Exit App"), + content: Text("Are you sure you want to exit?"), + actions: [ + TextButton( + onPressed: () => Navigator.of(context).pop(), // Close dialog + child: Text("Cancel"), + ), + TextButton( + onPressed: () => SystemNavigator.pop(), // Exit the app + child: Text("Exit"), + ), + ], + ), ); - return bgScaffold; } } diff --git a/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart b/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart index ab7cc0f0..176146f2 100644 --- a/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart +++ b/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart @@ -165,6 +165,8 @@ import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; +import 'package:pocketbase/pocketbase.dart'; +import 'package:shared_preferences/shared_preferences.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart'; @@ -205,7 +207,7 @@ class EconomyStatsWidget extends ConsumerStatefulWidget { class EconomyStatsState extends ConsumerState { List data = []; - + final _pb = PocketBase('https://pb.venbait.in'); bool isLoading = true; final GlobalKey cardTopicKey = GlobalKey(); @@ -213,11 +215,12 @@ class EconomyStatsState extends ConsumerState { late TutorialCoachMark tutorialCoachMark; late List homeTargets; late List previousHomeTargets; - Offset _imageCardPosition =Offset.zero; - Offset _imageTopicPosition =Offset.zero; + Offset _imageCardPosition = Offset.zero; + Offset _imageTopicPosition = Offset.zero; void _calculateCardPosition() { - final RenderBox cardRenderBox = cardsKey.currentContext!.findRenderObject() as RenderBox; + final RenderBox cardRenderBox = + cardsKey.currentContext!.findRenderObject() as RenderBox; final Offset cardPosition = cardRenderBox.localToGlobal(Offset.zero); final Size cardSize = cardRenderBox.size; @@ -233,10 +236,10 @@ class EconomyStatsState extends ConsumerState { void handleSkip() { tutorialCoachMark.skip(); debugPrint('Skip clicked'); - ref.read(chartsTourProvider.notifier).state = true; - ref.read(previousChartsTourProvider.notifier).state = true; - ref.read(homeTourProvider.notifier).state = true; - ref.read( previousHomeTourProvider.notifier).state = true; + ref.read(chartsTourProvider.notifier).state = true; + ref.read(previousChartsTourProvider.notifier).state = true; + ref.read(homeTourProvider.notifier).state = true; + ref.read(previousHomeTourProvider.notifier).state = true; ref.read(scaffoldTourProvider.notifier).state = true; ref.read(previousScaffoldTourProvider.notifier).state = true; } @@ -288,11 +291,10 @@ class EconomyStatsState extends ConsumerState { }, )..show(context: context); } - } - void _initTarget(){ - homeTargets=[ + void _initTarget() { + homeTargets = [ TargetFocus( identify: 'cardTopicKey', keyTarget: cardTopicKey, @@ -308,7 +310,7 @@ class EconomyStatsState extends ConsumerState { align: ContentAlign.bottom, child: SizedBox( width: double.infinity, - height: MediaQuery.of(context).size.height*0.69, + height: MediaQuery.of(context).size.height * 0.69, child: Stack( children: [ Positioned( @@ -353,12 +355,14 @@ class EconomyStatsState extends ConsumerState { decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFF7DAFBC), - border: Border.all(color: Color(0xFF7DAFBC), width: 1), + border: Border.all( + color: Color(0xFF7DAFBC), width: 1), ), child: IconButton( padding: EdgeInsets.zero, iconSize: 20, - icon: const Icon(Icons.arrow_forward, color: Colors.white), + icon: const Icon(Icons.arrow_forward, + color: Colors.white), onPressed: () { tutorialCoachMark.next(); }, @@ -379,21 +383,18 @@ class EconomyStatsState extends ConsumerState { align: ContentAlign.bottom, child: SizedBox( width: MediaQuery.of(context).size.width, - height:MediaQuery.of(context).size.height*0.69 , - child: Stack( - children: [ - Positioned( - left: MediaQuery.of(context).size.width*0.4, - top: _imageCardPosition.dy-29, - child: Image.asset( - 'assets/app_tour/down_right.png', - width: 40, - height: 90, - ), - ), - ] - ), - + height: MediaQuery.of(context).size.height * 0.69, + child: Stack(children: [ + Positioned( + left: MediaQuery.of(context).size.width * 0.4, + top: _imageCardPosition.dy - 29, + child: Image.asset( + 'assets/app_tour/down_right.png', + width: 40, + height: 90, + ), + ), + ]), ), ), ], @@ -404,17 +405,17 @@ class EconomyStatsState extends ConsumerState { shape: ShapeLightFocus.RRect, contents: [ createTargetContent( - text:AppLocalizations.of(context)!.economy, + text: AppLocalizations.of(context)!.economy, alignment: ContentAlign.bottom, gap: 0, - space: 40,), - + space: 40, + ), TargetContent( align: ContentAlign.bottom, - child: - SizedBox( + child: SizedBox( width: double.infinity, - height: MediaQuery.of(context).size.height *0.5, // Set an appropriate height for the Stack + height: MediaQuery.of(context).size.height * + 0.5, // Set an appropriate height for the Stack child: Stack( children: [ Positioned( @@ -425,7 +426,7 @@ class EconomyStatsState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ElevatedButton( - onPressed: () =>handleSkip, + onPressed: () => handleSkip, style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), @@ -457,11 +458,13 @@ class EconomyStatsState extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - border: Border.all(color: Colors.white, width: 2.0), + border: Border.all( + color: Colors.white, width: 2.0), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_back, color: Colors.white), + icon: const Icon(Icons.arrow_back, + color: Colors.white), onPressed: () { tutorialCoachMark.previous(); }, @@ -472,11 +475,13 @@ class EconomyStatsState extends ConsumerState { decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFF7DAFBC), - border: Border.all(color: Color(0xFF7DAFBC), width: 1), + border: Border.all( + color: Color(0xFF7DAFBC), width: 1), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_forward, color: Colors.white), + icon: const Icon(Icons.arrow_forward, + color: Colors.white), onPressed: () { tutorialCoachMark.next(); }, @@ -496,22 +501,19 @@ class EconomyStatsState extends ConsumerState { TargetContent( align: ContentAlign.bottom, child: SizedBox( - width: MediaQuery.of(context).size.width , - height:MediaQuery.of(context).size.height*0.69 , - child: Stack( - children: [ - Positioned( - left: MediaQuery.of(context).size.width*0.40, - top: _imageTopicPosition.dy-29, - child: Image.asset( - 'assets/app_tour/down_right.png', - width: 40, - height: 90, - ), - ), - ] - ), - + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.69, + child: Stack(children: [ + Positioned( + left: MediaQuery.of(context).size.width * 0.40, + top: _imageTopicPosition.dy - 29, + child: Image.asset( + 'assets/app_tour/down_right.png', + width: 40, + height: 90, + ), + ), + ]), ), ), ], @@ -519,24 +521,25 @@ class EconomyStatsState extends ConsumerState { ]; } - void _initPreviousTarget(){ - previousHomeTargets=[ + void _initPreviousTarget() { + previousHomeTargets = [ TargetFocus( identify: 'cardsKey', keyTarget: cardsKey, shape: ShapeLightFocus.RRect, contents: [ createTargetContent( - text:AppLocalizations.of(context)!.economy, + text: AppLocalizations.of(context)!.economy, alignment: ContentAlign.bottom, gap: 0, - space: 40,), + space: 40, + ), TargetContent( align: ContentAlign.bottom, - child: - SizedBox( + child: SizedBox( width: double.infinity, - height: MediaQuery.of(context).size.height *0.5, // Set an appropriate height for the Stack + height: MediaQuery.of(context).size.height * + 0.5, // Set an appropriate height for the Stack child: Stack( children: [ Positioned( @@ -547,7 +550,7 @@ class EconomyStatsState extends ConsumerState { mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ ElevatedButton( - onPressed: () =>handleSkip(), + onPressed: () => handleSkip(), style: ElevatedButton.styleFrom( shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(12), @@ -579,10 +582,12 @@ class EconomyStatsState extends ConsumerState { Container( decoration: BoxDecoration( shape: BoxShape.circle, - border: Border.all(color: Colors.white, width: 2.0), + border: Border.all( + color: Colors.white, width: 2.0), ), child: IconButton( - icon: const Icon(Icons.arrow_back, color: Colors.white), + icon: const Icon(Icons.arrow_back, + color: Colors.white), onPressed: () { tutorialCoachMark.next(); }, @@ -593,14 +598,21 @@ class EconomyStatsState extends ConsumerState { decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFF7DAFBC), - border: Border.all(color: Color(0xFF7DAFBC), width: 1.5), + border: Border.all( + color: Color(0xFF7DAFBC), width: 1.5), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_forward, color: Colors.white), + icon: const Icon(Icons.arrow_forward, + color: Colors.white), onPressed: () { - ref.read(previousHomeTourProvider.notifier).state=true; - ref.read(chartsTourProvider.notifier).state=false; + ref + .read( + previousHomeTourProvider.notifier) + .state = true; + ref + .read(chartsTourProvider.notifier) + .state = false; tutorialCoachMark.finish(); }, ), @@ -620,21 +632,18 @@ class EconomyStatsState extends ConsumerState { align: ContentAlign.bottom, child: SizedBox( width: MediaQuery.of(context).size.width, - height:MediaQuery.of(context).size.height*0.69 , - child: Stack( - children: [ - Positioned( - left: MediaQuery.of(context).size.width*0.40, - top: _imageTopicPosition.dy-29, - child: Image.asset( - 'assets/app_tour/down_right.png', - width: 40, - height: 90, - ), - ), - ] - ), - + height: MediaQuery.of(context).size.height * 0.69, + child: Stack(children: [ + Positioned( + left: MediaQuery.of(context).size.width * 0.40, + top: _imageTopicPosition.dy - 29, + child: Image.asset( + 'assets/app_tour/down_right.png', + width: 40, + height: 90, + ), + ), + ]), ), ), ], @@ -645,7 +654,7 @@ class EconomyStatsState extends ConsumerState { shape: ShapeLightFocus.RRect, contents: [ createTargetContent( - text:AppLocalizations.of(context)!.home_topic, + text: AppLocalizations.of(context)!.home_topic, alignment: ContentAlign.bottom, gap: 45, space: 40, @@ -654,7 +663,7 @@ class EconomyStatsState extends ConsumerState { align: ContentAlign.bottom, child: SizedBox( width: double.infinity, - height: MediaQuery.of(context).size.height*0.69, + height: MediaQuery.of(context).size.height * 0.69, child: Stack( children: [ Positioned( @@ -702,11 +711,13 @@ class EconomyStatsState extends ConsumerState { decoration: BoxDecoration( shape: BoxShape.circle, color: Color(0xFF7DAFBC), - border: Border.all(color: Color(0xFF7DAFBC), width: 1.5), + border: Border.all( + color: Color(0xFF7DAFBC), width: 1.5), ), child: IconButton( iconSize: 20, - icon: const Icon(Icons.arrow_forward, color: Colors.white), + icon: const Icon(Icons.arrow_forward, + color: Colors.white), onPressed: () { tutorialCoachMark.previous(); }, @@ -727,21 +738,18 @@ class EconomyStatsState extends ConsumerState { align: ContentAlign.bottom, child: SizedBox( width: MediaQuery.of(context).size.width, - height:MediaQuery.of(context).size.height*0.69 , - child: Stack( - children: [ - Positioned( - left: MediaQuery.of(context).size.width*0.4, - top: _imageCardPosition.dy-29, - child: Image.asset( - 'assets/app_tour/down_right.png', - width: 40, - height: 90, - ), - ), - ] - ), - + height: MediaQuery.of(context).size.height * 0.69, + child: Stack(children: [ + Positioned( + left: MediaQuery.of(context).size.width * 0.4, + top: _imageCardPosition.dy - 29, + child: Image.asset( + 'assets/app_tour/down_right.png', + width: 40, + height: 90, + ), + ), + ]), ), ), ], @@ -749,15 +757,12 @@ class EconomyStatsState extends ConsumerState { ]; } - @override void initState() { super.initState(); final locale = ref.read(localeProvider); fetchData(locale?.languageCode ?? 'en'); - WidgetsBinding.instance.addPostFrameCallback((_) { - _starTourRender(); - }); + _fetchUserData(); } // @override @@ -768,6 +773,37 @@ class EconomyStatsState extends ConsumerState { // fetchData(locale); // Pass the locale to the fetchData method // } + Future getUserId() async { + final prefs = await SharedPreferences.getInstance(); + return prefs.getString('userId'); // Retrieve the userId + } + + Future _fetchUserData() async { + try { + final userId = await getUserId(); + print('EDIT PROFILE isPageLoad'); + final adminAuth = await _pb.admins + .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); + final adminToken = adminAuth.token; + print('adminToken- $adminToken'); + final userDetailsResponse = await _pb.collection('users').getOne( + userId!, + headers: { + 'Authorization': 'Bearer $adminToken', + }, + ); + final loginCount = userDetailsResponse.data['login_count']; + print(loginCount); + if (loginCount == 1) { + WidgetsBinding.instance.addPostFrameCallback((_) { + _starTourRender(); + }); + } + } catch (e) { + print('Error fetching user details: $e'); + } + } + Future fetchData(locale) async { const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; try { @@ -875,7 +911,7 @@ class EconomyStatsState extends ConsumerState { crossAxisAlignment: CrossAxisAlignment.start, children: [ RoundedCornerContainer( - key: mainTopic['main_topic'] =='ECONOMY' + key: mainTopic['main_topic'] == 'ECONOMY' ? cardTopicKey : null, text: mainTopic['main_topic'], @@ -889,7 +925,7 @@ class EconomyStatsState extends ConsumerState { SizedBox( height: myheight / 4.8, // Set dynamic height child: Container( - key:mainTopic['main_topic'] == 'ECONOMY' + key: mainTopic['main_topic'] == 'ECONOMY' ? cardsKey : null, // color: Colors.grey[200], // Set a background color for the scrollable container @@ -1111,7 +1147,6 @@ class InfoCard extends StatelessWidget { final encodedTitle = Uri.encodeComponent(title); final encodedKey = Uri.encodeQueryComponent('home'); - return GestureDetector( onTap: () { context.go( diff --git a/pubspec.yaml b/pubspec.yaml index 073fd01c..907eb18d 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -2,7 +2,7 @@ name: uae_stat description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness." publish_to: "none" #version: 0.5.10 -version: 1.0.5+6 +version: 1.0.6+7 environment: sdk: ">=3.2.3 <4.0.0" @@ -117,6 +117,9 @@ flutter: - assets/app_tour/ - assets/icons/uae_numbers/bookmarks.png - assets/icons/uae_numbers/share.png + - assets/icons/misc/vector.png + - assets/icons/misc/visible_on.png + - assets/icons/misc/visibility_off.png fonts: - family: Segoe