diff --git a/.firebaserc b/.firebaserc index 8c804c3e..f4483484 100644 --- a/.firebaserc +++ b/.firebaserc @@ -1,5 +1,5 @@ { "projects": { - "default": "uae-stats-demo" + "default": "fcsc-da580" } } diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 6c6699ac..a570820b 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,5 +1,6 @@ + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/java/ae/gov/fcsc/frontend/MainActivity.java b/android/app/src/main/java/ae/gov/fcsc/frontend/MainActivity.java new file mode 100644 index 00000000..f4c43bb3 --- /dev/null +++ b/android/app/src/main/java/ae/gov/fcsc/frontend/MainActivity.java @@ -0,0 +1,6 @@ +package ae.gov.fcsc.frontend; + +import io.flutter.embedding.android.FlutterActivity; + +public class MainActivity extends FlutterActivity { +} diff --git a/android/app/src/main/kotlin/ae/gov/fcsc/frontend/MainActivity.kt b/android/app/src/main/kotlin/ae/gov/fcsc/frontend/MainActivity.kt deleted file mode 100644 index 09aad86f..00000000 --- a/android/app/src/main/kotlin/ae/gov/fcsc/frontend/MainActivity.kt +++ /dev/null @@ -1,5 +0,0 @@ -package ae.gov.fcsc.frontend - -import io.flutter.embedding.android.FlutterActivity - -class MainActivity: FlutterActivity() diff --git a/assets/edit_profile/profile.jpg b/assets/edit_profile/profile.jpg new file mode 100644 index 00000000..392d42d2 Binary files /dev/null and b/assets/edit_profile/profile.jpg differ diff --git a/assets/edit_profile/profile.png b/assets/edit_profile/profile.png deleted file mode 100644 index c37fb456..00000000 Binary files a/assets/edit_profile/profile.png and /dev/null differ diff --git a/firebase.json b/firebase.json index 08b57089..ebf22e80 100644 --- a/firebase.json +++ b/firebase.json @@ -1,18 +1,6 @@ { - "flutter": { - "platforms": { - "dart": { - "lib/firebase_options.dart": { - "projectId": "uae-stats-demo", - "configurations": { - "web": "1:225888316715:web:b96ad37877684cd2dd296e" - } - } - } - } - }, "hosting": { - "public": "build/web", + "public": "p", "ignore": [ "firebase.json", "**/.*", diff --git a/lib/l10n/intl_ar.arb b/lib/l10n/intl_ar.arb index 2f586571..c272b10e 100644 --- a/lib/l10n/intl_ar.arb +++ b/lib/l10n/intl_ar.arb @@ -98,7 +98,7 @@ "failed_to_update_password": "", "password_update_successfully": "تم تحديث كلمة المرور بنجاح.", "new_password_not_same_as_old": "كلمة المرور الجديدة يجب ألا تكون نفس كلمة المرور القديمة", - "password_between_8_to_40": "يجب أن تتراوح كلمة المرور بين 8 و64 حرفًا", + "password_between_8_to_40": "يجب أن تتراوح كلمة المرور بين 8 و40 حرفًا", "new_password_required": "كلمة المرور الجديدة مطلوبة", "old_password_is_required": "كلمة المرور القديمة مطلوبة", "confirm_password_is_required": "تأكيد كلمة المرور مطلوب", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index f6217299..8f5fba5a 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -99,7 +99,7 @@ "failed_to_update_password": "", "password_update_successfully": "Password updated successfully.", "new_password_not_same_as_old": "New password must not be the same as the old password", - "password_between_8_to_40": "Password must be between 8 and 64 characters", + "password_between_8_to_40": "Password must be between 8 and 40 characters", "new_password_required": "New password is required", "old_password_is_required": "Old password is required", "confirm_password_is_required": "Confirm password is required", diff --git a/lib/presentation/Screens/auth_verification/create_new_pw.dart b/lib/presentation/Screens/auth_verification/create_new_pw.dart index be8a8564..0b8de8da 100644 --- a/lib/presentation/Screens/auth_verification/create_new_pw.dart +++ b/lib/presentation/Screens/auth_verification/create_new_pw.dart @@ -220,14 +220,7 @@ class _CreateNewPwState extends ConsumerState { children: [ GestureDetector( onTap: () { - - if (widget.keyParam == 'editProfile') { - context.go('/editProfile'); - }else - { - context.go('/profile/${widget.userId}'); - } - + context.pop(); }, child: Container( margin: EdgeInsets.only(top: 10,left: 1,bottom: 16,right: 1), // Add margin for positioning @@ -249,7 +242,13 @@ class _CreateNewPwState extends ConsumerState { pathColorWhenOn: Colors.grey.shade300, pathColorWhenOff: Colors.grey.shade300, onTap: () { + final formState = _formKey.currentState; ref.read(localeProvider.notifier).toggleLocale(); + Future.delayed(Duration(milliseconds: 100), () { + if (formState?.validate() == false) { + formState?.validate(); + } + }); }, ); }, @@ -658,7 +657,7 @@ class _CreateNewPwState extends ConsumerState { SizedBox(height: 10), ElevatedButton( onPressed: () async { - context.go('/'); + context.go('/login'); }, style: ButtonStyle( shape: WidgetStatePropertyAll( @@ -697,6 +696,14 @@ class _CreateNewPwState extends ConsumerState { 'Login', 'تسجيل الدخول', ), + style: TextStyle( + fontFamily: context.translate( + 'Roboto', + 'Roboto', + ), + fontSize: 17, + fontWeight: FontWeight.w500, + ), ), 6.horizontalSpace, const Icon(Icons.chevron_right_outlined,color:Colors.white), diff --git a/lib/presentation/Screens/auth_verification/registration.dart b/lib/presentation/Screens/auth_verification/registration.dart index 36eb6a9a..aa9166d0 100644 --- a/lib/presentation/Screens/auth_verification/registration.dart +++ b/lib/presentation/Screens/auth_verification/registration.dart @@ -7,12 +7,13 @@ 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/banner_asset_path.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'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; -import '../../components/my_toggle.dart'; +import 'package:uae_stat/presentation/components/my_toggle.dart'; import '../../routes/auth_routes/login_route.dart'; class RegisterScreen extends ConsumerStatefulWidget { @@ -120,10 +121,10 @@ class _RegisterScreenState extends ConsumerState { if (value == null || value.isEmpty) { return context.translate('Required', 'مطلوب'); } else if (value.length > 40) { - return 'Must not exceed 40 characters'; + return AppLocalizations.of(context)!.only40charac; } else if (!RegExp(r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF]+$") .hasMatch(value)) { - return 'Invalid Characters'; + return AppLocalizations.of(context)!.invalid_characters; } return null; } @@ -138,7 +139,7 @@ class _RegisterScreenState extends ConsumerState { if (value == null || value.isEmpty) { return context.translate('Required', 'مطلوب'); } else if (!RegExp(emailRegex).hasMatch(value)) { - return 'Invalid Email'; + return AppLocalizations.of(context)!.invalid_email; } return null; } @@ -157,38 +158,38 @@ class _RegisterScreenState extends ConsumerState { if (value == null || value.isEmpty) { return context.translate('Required', 'مطلوب'); } else if (value.length < 8) { - return 'Password must be at least 8characters'; + return AppLocalizations.of(context)!.only8charac; } // Check the length constraint - if (value.length < 8 || value.length > 64) { - return 'Password must be between 8 and 64 characters'; + if (value.length < 8 || value.length > 40) { + return AppLocalizations.of(context)!.password_between_8_to_40; } // Check the regular expression if (!regex.hasMatch(value)) { - return 'Password contains invalid characters'; + return AppLocalizations.of(context)!.password_invalid; } // Track missing constraints List missingConstraints = []; if (!hasUppercase.hasMatch(value)) { - missingConstraints.add('uppercase letter'); + missingConstraints.add(context.translate('uppercase letter','حرف كبير')); } if (!hasLowercase.hasMatch(value)) { - missingConstraints.add('lowercase letter'); + missingConstraints.add(context.translate('lowercase letter','حرف صغير')); } if (!hasDigit.hasMatch(value)) { - missingConstraints.add('numeric digit'); + missingConstraints.add(context.translate('numeric digit','رقم')); } if (!hasSpecialCharacter.hasMatch(value)) { - missingConstraints.add('special character'); + missingConstraints.add(context.translate('special character','رمز خاص')); } // If there are missing constraints, return a consolidated message if (missingConstraints.isNotEmpty) { - return 'At least one ${missingConstraints.join(', ')}'; + return context.translate('At least one ${missingConstraints.join(', ')}','${missingConstraints.join(', ')}على الأقل واحد '); } _password = value; // Store the password for confirm password validation @@ -203,11 +204,12 @@ class _RegisterScreenState extends ConsumerState { if (value == null || value.isEmpty) { return context.translate('Required', 'مطلوب'); } else if (value.length < 8 || value.length > 40) { - return 'Password must be at least 8characters'; + return AppLocalizations.of(context)!.password_between_8_to_40; } else if (!regex.hasMatch(value)) { - return 'Password contains invalid characters'; + return AppLocalizations.of(context)!.password_invalid; } else if (value != _password) { - return 'Passwords do not match'; + return AppLocalizations.of(context)!.password_match; + ; } return null; @@ -261,7 +263,7 @@ class _RegisterScreenState extends ConsumerState { // Check if the error is due to an invalid or already used email if (e .toString() - .contains('The email is invalid or already in use.')) { + .contains(AppLocalizations.of(context)!.email_invalid)) { showDialog( context: context, builder: (context) { @@ -321,6 +323,11 @@ class _RegisterScreenState extends ConsumerState { } } + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 40, + ); + @override Widget build(BuildContext context) { double screenheight = MediaQuery.of(context).size.height; @@ -376,7 +383,13 @@ class _RegisterScreenState extends ConsumerState { pathColorWhenOn: Colors.grey.shade300, pathColorWhenOff: Colors.grey.shade300, onTap: () { + final formState = _formKey.currentState; ref.read(localeProvider.notifier).toggleLocale(); + Future.delayed(Duration(milliseconds: 100), () { + if (formState?.validate() == false) { + formState?.validate(); + } + }); }, ); }, @@ -1224,17 +1237,19 @@ class _RegisterScreenState extends ConsumerState { height: 10, ), Center( - child: Container( - height: screenheight / 16, - width: screenwidth / 3, - decoration: BoxDecoration( - image: DecorationImage( - image: AssetImage( - "assets/splash_screen/logo.png"), // Background image asset - fit: BoxFit.fill, - ), - ), - )), + // child: Container( + // height: screenheight / 16, + // width: screenwidth / 3, + // decoration: BoxDecoration( + // image: DecorationImage( + // image: AssetImage( + // "assets/splash_screen/logo.png"), // Background image asset + // fit: BoxFit.fill, + // ), + // ), + // ) + child: fcscBanner, + ), SizedBox( height: 20, ), diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index e8a10522..2111236f 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -3,7 +3,9 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_svg/svg.dart'; import 'package:go_router/go_router.dart'; +import 'package:path_provider/path_provider.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:screenshot/screenshot.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; import 'package:uae_stat/config/toast_util.dart'; @@ -17,6 +19,11 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart'; import '../filters/search_filter_helper.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:share_plus/share_plus.dart'; +import 'package:path_provider/path_provider.dart'; +import 'dart:io'; class ChartScreen1 extends ConsumerStatefulWidget { final String dataSets; @@ -148,17 +155,17 @@ class _ChartScreen1State extends ConsumerState { }); // ToastUtil.showSuccessToast("Added to Bookmark."); - ScaffoldMessenger.of(context).showSnackBar( - SnackBar( - content: Text( - AppLocalizations.of(context)!.added_to_Bookmark, - style: TextStyle( - color: Color(0xFF2F692C), fontWeight: FontWeight.w600), - ), - backgroundColor: Color(0xFFD6E9C6), - duration: Duration(seconds: 2), - ), - ); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text( + // AppLocalizations.of(context)!.added_to_Bookmark, + // style: TextStyle( + // color: Color(0xFF2F692C), fontWeight: FontWeight.w600), + // ), + // backgroundColor: Color(0xFFD6E9C6), + // duration: Duration(seconds: 2), + // ), + // ); print("Bookmark added: ${response.id}"); } catch (e) { @@ -2066,7 +2073,7 @@ class _ChartScreen1State extends ConsumerState { GestureDetector( onTap: () { if (isBookmarked) { - showRemoveBookmarkDialog(); + showRemoveBookmarkDialog(); } else { showAddBookmarkDialog(); } @@ -2127,30 +2134,68 @@ class _ChartScreen1State extends ConsumerState { color: Colors.white, ), ), - SizedBox(width: 6), - Stack( - children: [ - // Image.asset( - // UaeNumbersAssetPath.shareUae, - // color: Colors.white, // Outline color - // width: 24, // Slightly larger - // height: 24, - // ), - // Image.asset( - // UaeNumbersAssetPath.shareUae, - // color: Colors.white, - // width: 24, - // height: 24, - // ), + SizedBox(width: 5), + GestureDetector( + onTap: () async { + try { + // Define share content + final String shareLink = 'https://fcsc-da580.web.app'; // Your link + final String shareText = 'Check this out!'; + final String svgAssetPath = 'assets/logos/fcsc.png'; // Your SVG asset path - SvgPicture.asset( - UaeNumbersAssetPath.share, - semanticsLabel: 'share', - width: 24, - height: 24, + // Create a controller to capture the SVG as an image + final screenshotController = ScreenshotController(); + + // Render the SVG off-screen and capture it as PNG + final svgWidget = SvgPicture.asset( + svgAssetPath, + width: 200, // Adjust size as needed + height: 200, + ); + + // Capture the SVG as a PNG + final Uint8List? capturedImage = await screenshotController.captureFromWidget( + Material( + child: svgWidget, + ), + ); + + if (capturedImage == null) { + throw Exception('Failed to capture SVG as image'); + } + + // Save the captured PNG to a temporary file + final directory = await getTemporaryDirectory(); + final file = File('${directory.path}/shared_image.png'); + await file.writeAsBytes(capturedImage); + + // Share the PNG file with text and link + await Share.shareXFiles( + [XFile(file.path)], + text: '$shareText\n$shareLink', + subject: 'Shared Content', + ); + + // Clean up temporary file + await file.delete(); + } catch (e) { + print("Error sharing file: $e"); + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Error sharing: $e')), + ); + } + }, + child: Container( + width: 24, + height: 24, + child: Icon( + Icons.share, + color: Colors.white, + size: 24, + semanticLabel: 'Share', ), - ], - ) + ), + ), ], ), SizedBox( diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index 6a1ec4a6..c93f003f 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -273,7 +273,7 @@ class _ProfileScreenState extends ConsumerState { // Function to validate the DOB field String? _validateDob(String? value) { if (value == null || value.isEmpty) { - return 'Required'; + return context.translate('Required', 'مطلوب'); } final DateTime selectedDate = _selectedDate!; @@ -281,14 +281,14 @@ class _ProfileScreenState extends ConsumerState { // Check if the selected date is in the future if (selectedDate.isAfter(today)) { - return 'Date of birth cannot be in the future'; + return context.translate('Date of birth cannot be in the future','لا يمكن أن يكون تاريخ الميلاد في المستقبل'); } return null; } String? _validateDropdown(String? value) { if (value == null || value.isEmpty) { - return 'Required'; + return context.translate('Required', 'مطلوب'); } return null; } @@ -657,7 +657,7 @@ class _ProfileScreenState extends ConsumerState { enabled: true, validator: (value) { if (value == null || value.isEmpty) { - return 'Required'; + return context.translate('Required', 'مطلوب'); } //RegExp(r"^[a-zA-Z\s]+$"); @@ -665,7 +665,7 @@ class _ProfileScreenState extends ConsumerState { r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF\s]+$"); if (!nameRegex.hasMatch(value)) { - return 'Invalid Characters'; + return AppLocalizations.of(context)!.invalid_characters; } return null; }, @@ -912,7 +912,7 @@ class _ProfileScreenState extends ConsumerState { Padding( padding: const EdgeInsets.only(left: 10.0), child: Text( - 'Required', + context.translate('Required', 'مطلوب'), style: TextStyle( color: Color(0xFFb22222), fontSize: 12, @@ -928,7 +928,7 @@ class _ProfileScreenState extends ConsumerState { final userId = widget.userId; final email = _emailController.text; - context.go('/createNewPw/$userId/$email'); + context.push('/createNewPw/$userId/$email'); }, child: Text( AppLocalizations.of(context)!.change_password, diff --git a/lib/presentation/routes/auth_routes/login_route.dart b/lib/presentation/routes/auth_routes/login_route.dart index df4ecb23..53bbf143 100644 --- a/lib/presentation/routes/auth_routes/login_route.dart +++ b/lib/presentation/routes/auth_routes/login_route.dart @@ -24,6 +24,8 @@ import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_r import 'package:http/http.dart' as http; import '../../Screens/auth_verification/registration.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + import '../../components/indicators/locale_provider.dart'; import '../../components/my_toggle.dart'; @@ -451,7 +453,7 @@ class LoginRoute extends HookConsumerWidget { ), fontSize: locale?.languageCode == 'ar' ? 12: 18, fontWeight: FontWeight.w500, - ) + ), ), 6.horizontalSpace, const Icon( @@ -473,10 +475,14 @@ class LoginRoute extends HookConsumerWidget { ), validator: (value) { + final emailRegex = + r'^[a-zA-Z0-9àèìòùÀÈÌÒÙéàç~!#$%^&*()_+=-{}|;,.?<>]+@[a-zA-Z0-9àèìòùÀÈÌÒÙéàç~!#$%^&*()_+=-{}|;,.?<>]+\.[a-zA-Z]{2,}$'; if (value == null || value.isEmpty) { return context.translate('Required', 'مطلوب'); } - return FieldValidator.email()(value); + else if (!RegExp(emailRegex).hasMatch(value)) { + return AppLocalizations.of(context)!.invalid_email; + } return null; }, imgPath: MiscIconAssetPath.person, controller: emailCtl, @@ -487,7 +493,7 @@ class LoginRoute extends HookConsumerWidget { if (text == null || text.isEmpty) { return context.translate('Required', 'مطلوب'); } else if (text.length < 8) { - return 'The password must be at least 8 characters'; + return AppLocalizations.of(context)!.only8charac; } return FieldValidator.password(minLength: 8)(text); }, @@ -668,7 +674,13 @@ class LoginRoute extends HookConsumerWidget { pathColorWhenOn: Colors.grey.shade300, pathColorWhenOff: Colors.grey.shade300, onTap: () { + final formState = formKey.currentState; ref.read(localeProvider.notifier).toggleLocale(); + Future.delayed(Duration(milliseconds: 100), () { + if (formState?.validate() == false) { + formState?.validate(); + } + }); }, ), ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart index cf44f52a..4a192cac 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart @@ -109,17 +109,17 @@ class _BookMarkState extends ConsumerState { 'Authorization': adminToken, }); // Show success SnackBar - ScaffoldMessenger.of(context).showSnackBar( - const SnackBar( - content: Text( - 'Removed from Bookmark.', - style: TextStyle( - color: Color(0xFF2F692C), fontWeight: FontWeight.w600), - ), - backgroundColor: Color(0xFFD6E9C6), - duration: Duration(seconds: 2), - ), - ); + // ScaffoldMessenger.of(context).showSnackBar( + // const SnackBar( + // content: Text( + // 'Removed from Bookmark.', + // style: TextStyle( + // color: Color(0xFF2F692C), fontWeight: FontWeight.w600), + // ), + // backgroundColor: Color(0xFFD6E9C6), + // duration: Duration(seconds: 2), + // ), + // ); final locale = ref.read(localeProvider); fetchBookmarks(locale?.languageCode ?? 'en'); // ToastUtil.showSuccessToast("Removed from Bookmark."); @@ -140,90 +140,96 @@ class _BookMarkState extends ConsumerState { } /// Show confirmation dialog before removing bookmark - // void showRemoveBookmarkDialog(id) { - // double myheight = MediaQuery.of(context).size.height; - // showDialog( - // context: context, - // barrierDismissible: false, // User must tap button to dismiss dialog - // builder: (context) => AlertDialog( - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(5.0), // Rounded corners - // ), - // contentPadding: EdgeInsets.zero, - // content: Stack( - // children: [ - // Padding( - // padding: const EdgeInsets.all(10.0), - // child: Column( - // mainAxisSize: MainAxisSize.min, - // children: [ - // SizedBox( - // height: myheight / 30, - // ), - // Text( - // context.translate( - // 'Are you sure you want to remove this bookmark?', - // 'هل أنت متأكد أنك تريد إزالة هذه الإشارة المرجعية؟'), - // textAlign: TextAlign.center, - // style: TextStyle( - // fontSize: 18, - // color: Color(0xFF898C81), - // ), - // ) - // ], - // ), - // ), - // ], - // ), - // actions: [ - // SizedBox(height: 20), - // SizedBox( - // width: 100, // Set the desired width - // child: TextButton( - // onPressed: () => Navigator.pop(context), - // style: TextButton.styleFrom( - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular( - // 10.0), // Adjust the radius as needed - // ), - // side: BorderSide( - // color: Color(0xFFAA8E83), // Set the outline color - // width: 1, // Set the border width - // ), - // ), - // child: Text( - // context.translate('No', 'لا'), - // style: TextStyle( - // color: Color(0xFFAA8E83), - // fontSize: 16, - // ), - // ), - // ), - // ), - // SizedBox( - // width: 100, // Set the desired width - // child: TextButton( - // onPressed: () { - // Navigator.pop(context); - // removeBookmark(id); // Close dialog - // }, - // style: TextButton.styleFrom( - // backgroundColor: Color(0xFFAA8E83), // Set background color - // foregroundColor: Colors.white, - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(10.0), // Set text color - // ), - // ), - // child: Text( - // context.translate('Yes', 'نعم'), - // style: TextStyle(color: Colors.white, fontSize: 16), - // ), - // ), - // ), - // ], - // ), - // ); - // } + void showRemoveBookmarkDialog(id) { + double myheight = MediaQuery.of(context).size.height; + showDialog( + context: context, + barrierDismissible: false, // User must tap button to dismiss dialog + builder: (context) => AlertDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), // Rounded corners + ), + contentPadding: EdgeInsets.zero, + content: Stack( + children: [ + Padding( + padding: const EdgeInsets.all(10.0), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + SizedBox( + height: myheight / 30, + ), + Text( + context.translate( + 'Are you sure you want to remove this bookmark?', + 'هل أنت متأكد أنك تريد إزالة هذه الإشارة المرجعية؟'), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Color(0xFF898C81), + ), + ) + ], + ), + ), + ], + ), + actions: [ + SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + SizedBox( + width: 100, // Set the desired width + child: TextButton( + onPressed: () => Navigator.pop(context), + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular( + 10.0), // Adjust the radius as needed + ), + side: BorderSide( + color: Color(0xFFAA8E83), // Set the outline color + width: 1, // Set the border width + ), + ), + child: Text( + context.translate('No', 'لا'), + style: TextStyle( + color: Color(0xFFAA8E83), + fontSize: 16, + ), + ), + ), + ), + SizedBox( + width: 100, // Set the desired width + child: TextButton( + onPressed: () { + Navigator.pop(context); + removeBookmark(id); // Close dialog + }, + style: TextButton.styleFrom( + backgroundColor: Color(0xFFAA8E83), // Set background color + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), // Set text color + ), + ), + child: Text( + context.translate('Yes', 'نعم'), + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ), + ], + ) + + ], + ), + ); + } String colorToHex(Color color) { return '0xFF${color.red.toRadixString(16).padLeft(2, '0').toUpperCase()}' @@ -329,9 +335,9 @@ class _BookMarkState extends ConsumerState { ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( - 'The bookmark is removed successfully', + 'Removed from BookMark', ), - backgroundColor: Colors.green, + backgroundColor: Colors.black, duration: Duration(seconds: 2), ), ); @@ -346,14 +352,35 @@ class _BookMarkState extends ConsumerState { // GestureDetector( // onTap: () { // debugPrint("Icon clicked in: ${data['title']}"); - // // showRemoveBookmarkDialog(data['id']); + // removeBookmark(data['id']); + // ScaffoldMessenger.of(context).showSnackBar( + // SnackBar( + // content: Text( + // 'The bookmark is removed successfully', + // ), + // backgroundColor: Colors.green, + // duration: Duration(seconds: 2), + // ), + // ); // }, // child: const Icon( - // Icons.bookmarks_rounded, + // Icons.delete, // color: Colors.black, // size: 20, // ), // ), + + GestureDetector( + onTap: () { + debugPrint("Icon clicked in: ${data['title']}"); + showRemoveBookmarkDialog(data['id']); + }, + child: const Icon( + Icons.bookmarks_rounded, + color: Colors.black, + size: 20, + ), + ), ], ), Text( diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart b/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart index 42280b3b..7b291815 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart @@ -13,6 +13,7 @@ import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.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/routes/drawer_routes/custom_drawer_routes.dart'; @@ -298,7 +299,7 @@ class _EditProfileState extends State { // Function to validate the DOB field String? _validateDob(String? value) { if (value == null || value.isEmpty) { - return 'Required'; + return context.translate('Required', 'مطلوب'); } final DateTime selectedDate = _selectedDate!; @@ -306,14 +307,14 @@ class _EditProfileState extends State { // Check if the selected date is in the future if (selectedDate.isAfter(today)) { - return 'Date of birth cannot be in the future'; + return context.translate('Date of birth cannot be in the future','لا يمكن أن يكون تاريخ الميلاد في المستقبل'); } return null; } String? _validateDropdown(String? value) { if (value == null || value.isEmpty) { - return 'Required'; + return context.translate('Required', 'مطلوب'); } return null; } @@ -544,7 +545,7 @@ class _EditProfileState extends State { ? NetworkImage( _avatarUrl) // Load from URL : AssetImage( - 'assets/edit_profile/profile.png') + 'assets/edit_profile/profile.jpg') as ImageProvider, child: _avatarUrl.isNotEmpty ? FutureBuilder( @@ -689,7 +690,7 @@ class _EditProfileState extends State { enabled: false, validator: (value) { if (value == null || value.isEmpty) { - return 'Required'; + return context.translate('Required', 'مطلوب'); } //RegExp(r"^[a-zA-Z\s]+$"); @@ -697,7 +698,7 @@ class _EditProfileState extends State { r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF\s]+$", ); if (!nameRegex.hasMatch(value)) { - return 'Invalid Characters'; + return AppLocalizations.of(context)!.invalid_characters; } return null; }, @@ -956,7 +957,7 @@ class _EditProfileState extends State { child: GestureDetector( onTap: () { final email = _emailController.text; - context.go( + context.push( '/createNewPw/$userId/$email?key=editProfile'); }, child: Text( diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/AboutFCSC.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/AboutFCSC.dart index 8f5a8543..5c63feb8 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/AboutFCSC.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/AboutFCSC.dart @@ -3,18 +3,11 @@ import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; -import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart'; - class aboutFCSC extends StatelessWidget { const aboutFCSC({super.key}); @override Widget build(BuildContext context) { - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); return BaseScaffold( showDivider: true, showBackButton: true, @@ -86,15 +79,10 @@ class aboutFCSC extends StatelessWidget { ], ), ), - SizedBox(height: MediaQuery.of(context).size.height*0.15), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), SizedBox( - height: 25, + height: 20, ), - ]), + ],), ), ), ); diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/getStarted.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/getStarted.dart index 78835c9d..e6b1e33c 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/getStarted.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/getStarted.dart @@ -3,18 +3,12 @@ import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; -import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart'; class GetStarted extends StatelessWidget { const GetStarted({super.key}); @override Widget build(BuildContext context) { - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); return Theme( data: ThemeData( fontFamily: 'Roboto', // Set default font family for this page @@ -84,12 +78,7 @@ class GetStarted extends StatelessWidget { SizedBox( height:MediaQuery.of(context).size.height * 0.12, ), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox(height: 25,), - + SizedBox(height: 20,), ], ), ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/AppFeatures.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/AppFeatures.dart index 3b834f03..a58e852c 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/AppFeatures.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/AppFeatures.dart @@ -6,11 +6,7 @@ import '../../../custom_drawer_routes.dart'; class AppFeatures extends StatelessWidget { AppFeatures({super.key}); - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + @override Widget build(BuildContext context) { return Theme( @@ -205,12 +201,7 @@ class AppFeatures extends StatelessWidget { ], ), ), - SizedBox(height: 25,), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox(height: 25,), + SizedBox(height: 20,), ], ), ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/ChangeMyPassword.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/ChangeMyPassword.dart index 64d20ad8..a6b2a8ad 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/ChangeMyPassword.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/ChangeMyPassword.dart @@ -1,16 +1,9 @@ import 'package:flutter/material.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; - -import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; -import '../../../custom_drawer_routes.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class ChangeMyPassword extends StatelessWidget { - ChangeMyPassword({super.key}); - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + const ChangeMyPassword({super.key}); @override Widget build(BuildContext context) { return Theme( @@ -116,7 +109,7 @@ class ChangeMyPassword extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.w600, color: Color(0xFF414042), - fontFamily: 'Roboto' + fontFamily: 'Roboto', ),), TextSpan(text:context.translate( ' link at the bottom.', @@ -295,9 +288,9 @@ class ChangeMyPassword extends StatelessWidget { style: TextStyle( fontWeight: FontWeight.w600, color: Color(0xFF414042), - fontFamily: 'Roboto' + fontFamily: 'Roboto', ),), - TextSpan(text: context.translate('button',''),) + TextSpan(text: context.translate('button',''),), ], ), ), @@ -360,14 +353,7 @@ class ChangeMyPassword extends StatelessWidget { ], ), ), - - SizedBox(height: 25,), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox(height: 25,), - + SizedBox(height: 20,), ], ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/EditMyProfile.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/EditMyProfile.dart index 3a8ff898..ac52029a 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/EditMyProfile.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/EditMyProfile.dart @@ -1,16 +1,12 @@ import 'package:flutter/material.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; -import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; -import '../../../custom_drawer_routes.dart'; + +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class EditMyProfile extends StatelessWidget { - EditMyProfile({super.key}); - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + const EditMyProfile({super.key}); + @override Widget build(BuildContext context) { return Theme( @@ -457,14 +453,7 @@ class EditMyProfile extends StatelessWidget { ], ), ), - - SizedBox(height: 25,), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox(height: 25,), - + SizedBox(height: 20,), ], ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/howUseTheApp.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/howUseTheApp.dart index 1d61194e..ed84871f 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/howUseTheApp.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/howUseTheApp.dart @@ -1,16 +1,12 @@ import 'package:flutter/material.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; -import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; -import '../../../custom_drawer_routes.dart'; + +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class HowUseTheApp extends StatelessWidget { - HowUseTheApp({super.key}); - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + const HowUseTheApp({super.key}); + @override Widget build(BuildContext context) { return Theme( @@ -203,14 +199,7 @@ class HowUseTheApp extends StatelessWidget { ], ), SizedBox( - height: 25, - ), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox( - height: 25, + height: 20, ), ], ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/purpose.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/purpose.dart index eae4c7cb..99e08a72 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/purpose.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/purpose.dart @@ -1,16 +1,10 @@ import 'package:flutter/material.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; -import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; -import '../../../custom_drawer_routes.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class Purpose extends StatelessWidget { - Purpose({super.key}); - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + const Purpose({super.key}); @override Widget build(BuildContext context) { return Theme( @@ -151,14 +145,7 @@ class Purpose extends StatelessWidget { ], ), SizedBox( - height: 40, - ), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox( - height: 25, + height: 20, ), ], ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/stayUpdate.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/stayUpdate.dart index 85ec7ce7..78b8f8ca 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/stayUpdate.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/stayUpdate.dart @@ -1,16 +1,11 @@ import 'package:flutter/material.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; -import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; -import '../../../custom_drawer_routes.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class StayUpdate extends StatelessWidget { - StayUpdate({super.key}); - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + const StayUpdate({super.key}); + @override Widget build(BuildContext context) { return Theme( @@ -91,14 +86,7 @@ class StayUpdate extends StatelessWidget { ], ), SizedBox( - height: 150, - ), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox( - height: 25, + height: 20, ), ], ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/useTheApp.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/useTheApp.dart index b2720689..ad2f41dc 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/useTheApp.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/useTheApp.dart @@ -1,16 +1,10 @@ import 'package:flutter/material.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; - -import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; -import '../../../custom_drawer_routes.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class WhoUseTheApp extends StatelessWidget { - WhoUseTheApp({super.key}); - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + const WhoUseTheApp({super.key}); + @override Widget build(BuildContext context) { return Theme( @@ -141,15 +135,9 @@ class WhoUseTheApp extends StatelessWidget { ), ], ), + SizedBox( - height: 50, - ), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox( - height: 25, + height: 20, ), ], ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/aboutApp.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/aboutApp.dart index fa53a0b8..8454db74 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/aboutApp.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/aboutApp.dart @@ -3,18 +3,12 @@ import 'package:go_router/go_router.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; -import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart'; class aboutTheApp extends StatelessWidget { const aboutTheApp({super.key}); @override Widget build(BuildContext context) { - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); return BaseScaffold( showDivider: true, showBackButton: true, @@ -67,7 +61,7 @@ class aboutTheApp extends StatelessWidget { border: Border( bottom: BorderSide( color: Colors.grey.shade300, - width: 0.5), // Grey bottom line + width: 0.5,), // Grey bottom line ), ), child: ListTile( @@ -87,17 +81,12 @@ class aboutTheApp extends StatelessWidget { trailing: Icon(Icons.keyboard_arrow_right), shape: Border( bottom: BorderSide( - color: Colors.black, width: 3), // Grey bottom line + color: Colors.black, width: 3,), // Grey bottom line ), ), ), - Spacer(), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), SizedBox( - height: 25, + height: 20, ), ], ), diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/faq_page.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/faq_page.dart index 6511c91a..4b354932 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/faq_page.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/faq_page.dart @@ -1,7 +1,5 @@ import 'package:flutter/material.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; -import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart'; - import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class FAQPage extends StatefulWidget { @@ -12,11 +10,7 @@ class FAQPage extends StatefulWidget { } class _FAQPageState extends State { - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + @override Widget build(BuildContext context) { return BaseScaffold( @@ -44,14 +38,7 @@ class _FAQPageState extends State { radius: Radius.circular(10), interactive: true, child: SingleChildScrollView( - child: Column( - children: [ - QuestionAnswerScrollView(), - SizedBox(height: 25,), - fcscBanner, - SizedBox(height: 25,), - ], - ), + child: QuestionAnswerScrollView(), ), ), ), @@ -83,24 +70,24 @@ class QuestionAnswerScrollView extends StatelessWidget { text: 'Yes, the app is strictly for registered and approved users. To access the data:\n\n', style: TextStyle( - color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto',), ), TextSpan( text: ' 1. You need to sign up using the Register Now option on the login screen.\n', style: TextStyle( - color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto',), ), TextSpan( text: ' 2. Your registration must be approved by the admin.\n', style: TextStyle( - color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto',), ), TextSpan( text: " 3. Once approved, you can log in to access the app's features and datasets.\n\nGuest access is not available for this application.\n ", style: TextStyle( - color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto',), ), ], ), @@ -112,24 +99,24 @@ class QuestionAnswerScrollView extends StatelessWidget { text: 'نعم، التطبيق مخصص فقط للمستخدمين المسجلين والمعتمدين. للوصول إلى البيانات:\n\n', style: TextStyle( - color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto',), ), TextSpan( text: ' 1. يجب عليك التسجيل باستخدام خيار "التسجيل الآن" في شاشة تسجيل الدخول.\n', style: TextStyle( - color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto',), ), TextSpan( text: ' 2. يجب أن يتم الموافقة على تسجيلك من قبل المسؤول.\n', style: TextStyle( - color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto',), ), TextSpan( text: - " بعد الموافقة، يمكنك تسجيل الدخول للوصول إلى ميزات التطبيق وبياناته.\n\n لا يتوفر الوصول للزوار في هذا التطبيق.\n", + ' بعد الموافقة، يمكنك تسجيل الدخول للوصول إلى ميزات التطبيق وبياناته.\n\n لا يتوفر الوصول للزوار في هذا التطبيق.\n', style: TextStyle( - color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto',), ), ], ), @@ -140,7 +127,7 @@ class QuestionAnswerScrollView extends StatelessWidget { 'question-ar': 'كيف يمكنني التنقل عبر التطبيق؟', 'answer': '• Use the main categories on the homepage (e.g., Economy, Environment) to access subcategories and detailed KPIs.\n• Drill down into specific metrics or graphical views by tapping on a KPI.\n• Access additional features like Bookmarks or Profile through the navigation bar.\n', - 'answer-ar': '•استخدم الفئات الرئيسية الموجودة على الصفحة الرئيسية (مثل: الاقتصاد، البيئة) للوصول إلى الفئات الفرعية ومؤشرات الأداء الرئيسية التفصيلية •\n\ قم بالتعمق في مؤشرات معينة أو عرض الرسوم البيانية من خلال النقر على مؤشر الأداء الرئيسي (KPI). \n • للوصول إلى ميزات إضافية مثل الإشارات المرجعية أو الملف الشخصي، استخدم شريط التنقل.\n', + 'answer-ar': '•استخدم الفئات الرئيسية الموجودة على الصفحة الرئيسية (مثل: الاقتصاد، البيئة) للوصول إلى الفئات الفرعية ومؤشرات الأداء الرئيسية التفصيلية •\n قم بالتعمق في مؤشرات معينة أو عرض الرسوم البيانية من خلال النقر على مؤشر الأداء الرئيسي (KPI). \n • للوصول إلى ميزات إضافية مثل الإشارات المرجعية أو الملف الشخصي، استخدم شريط التنقل.\n', }, { 'question': 'What types of data are available?', diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/features.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/features.dart index 216d3bb8..d0207db1 100755 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/features.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/features.dart @@ -11,11 +11,7 @@ class UsingFeatures extends StatelessWidget { @override Widget build(BuildContext context) { - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment: Alignment.center, - ); + return BaseScaffold( showDivider: true, showBackButton: true, @@ -237,14 +233,6 @@ class UsingFeatures extends StatelessWidget { ), ), ), - Spacer(), - Align( - alignment: Alignment.bottomCenter, - child: fcscBanner, - ), - SizedBox( - height: 30, - ), ], ), ), diff --git a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart index 0055d82b..28f1152c 100644 --- a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart +++ b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart @@ -14,6 +14,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; import 'package:uae_stat/config/injector.dart'; import 'package:uae_stat/domain/repos/t_auth_repo.dart'; +import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/data/p_auth_repo.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/bottom_bar_asset_icon_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/drawer_asset_icon_path.dart'; @@ -780,7 +781,7 @@ class _BaseScaffoldState extends ConsumerState { ) : Image( image: AssetImage( - 'assets/edit_profile/profile.png', + 'assets/edit_profile/profile.jpg', ), fit: BoxFit.cover, width: double.infinity, @@ -792,23 +793,53 @@ class _BaseScaffoldState extends ConsumerState { SizedBox( width: mywidth / 20, ), - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - // Text(userId ?? 'Loading user...'), // Display userId here - // Text('Mohammad@fcsc.com') - if (userId == "guest") ...[ - Text(userName ?? 'Guest User'), - ] else ...[ - Text(userName ?? 'Loading...'), - Text( - userEmail ?? 'Loading...', - style: TextStyle(fontSize: 12), - // maxLines: 2, // Allow the text to wrap to the next line - overflow: TextOverflow.ellipsis, - ), - ] - ], + // Column( + // crossAxisAlignment: CrossAxisAlignment.start, + // children: [ + // // Text(userId ?? 'Loading user...'), // Display userId here + // // Text('Mohammad@fcsc.com') + // if (userId == "guest") ...[ + // Text(userName ?? 'Guest User'), + // ] else ...[ + // Text(userName ?? 'Loading...'), + // Tooltip( + // message: userEmail ?? 'Loading...', + // child: Text( + // userEmail ?? 'Loading...', + // style: TextStyle(fontSize: 12), + // softWrap: true, + // maxLines: 1, + // overflow: TextOverflow.ellipsis, + // ), + // ), + // + // ] + // ], + // ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (userId == "guest") ...[ + Text(userName ?? 'Guest User'), + ] else ...[ + Text(userName ?? 'Loading...'), + Tooltip( + message: userEmail ?? 'Loading...', // Shows full email on hover + child: SizedBox( + width: MediaQuery.of(context).size.width * 0.6, // Adjust width as needed + child: Text( + userEmail ?? 'Loading...', + style: TextStyle(fontSize: 12), + // softWrap: true, + overflow: TextOverflow.ellipsis, + maxLines: 1, + ), + ), + ), + ], + ], + ), ), ], ), @@ -875,7 +906,7 @@ class _BaseScaffoldState extends ConsumerState { leading: Icon(Icons.logout), // title: const Text('Logout'), title: Text(AppLocalizations.of(context)!.logout), - onTap: () => logout(context), + onTap: () => _showLogoutConfirmationDialog(context), ), if (userId == 'guest') ListTile( @@ -1047,3 +1078,85 @@ class _BaseScaffoldState extends ConsumerState { } } } +void _showLogoutConfirmationDialog(context) { + double myheight = MediaQuery.of(context).size.height; + showDialog( + context: context, + barrierDismissible: false, // User must tap a button to dismiss dialog + builder: (context) => AlertDialog( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(5.0), // Rounded corners + ), + contentPadding: EdgeInsets.zero, + title: Text( + context.translate('Log Out Confirmation', 'تأكيد تسجيل الخروج'), + textAlign: TextAlign.center, + style: TextStyle(fontSize: 20, fontWeight: FontWeight.bold), + ), + content: Padding( + padding: const EdgeInsets.all(20.0), + child: Text( + context.translate( + 'Are you sure you want to log out?', + 'هل أنت متأكد أنك تريد تسجيل الخروج؟'), + textAlign: TextAlign.center, + style: TextStyle( + fontSize: 18, + color: Color(0xFF898C81), + ), + ), + ), + actions: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, // Space buttons evenly + children: [ + SizedBox( + width: 120, // Set button width + child: TextButton( + onPressed: () => Navigator.pop(context), + style: TextButton.styleFrom( + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + side: BorderSide( + color: Color(0xFFAA8E83), // Border color + width: 1, + ), + ), + child: Text( + context.translate('Cancel', 'إلغاء'), + style: TextStyle( + color: Color(0xFFAA8E83), + fontSize: 16, + ), + ), + ), + ), + SizedBox( + width: 120, // Set button width + child: TextButton( + onPressed: () { + Navigator.pop(context); + // Add logout function here + }, + style: TextButton.styleFrom( + backgroundColor: Color(0xFFAA8E83), // Background color + foregroundColor: Colors.white, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10.0), + ), + ), + child: Text( + context.translate('Log Out', 'تسجيل الخروج'), + style: TextStyle(color: Colors.white, fontSize: 16), + ), + ), + ), + ], + ), + SizedBox(height: 10), // Add spacing below buttons + ], + ), + ); +} + diff --git a/p/404.html b/p/404.html new file mode 100644 index 00000000..829eda8f --- /dev/null +++ b/p/404.html @@ -0,0 +1,33 @@ + + + + + + Page Not Found + + + + +
+

404

+

Page Not Found

+

The specified file was not found on this website. Please check the URL for mistakes and try again.

+

Why am I seeing this?

+

This page was generated by the Firebase Command-Line Interface. To modify it, edit the 404.html file in your project's configured public directory.

+
+ + diff --git a/p/index.html b/p/index.html new file mode 100644 index 00000000..c78755d8 --- /dev/null +++ b/p/index.html @@ -0,0 +1,89 @@ + + + + + + Welcome to Firebase Hosting + + + + + + + + + + + + + + + + + + + +
+

Welcome

+

Firebase Hosting Setup Complete

+

You're seeing this because you've successfully setup Firebase Hosting. Now it's time to go build something extraordinary!

+ Open Hosting Documentation +
+

Firebase SDK Loading…

+ + + + diff --git a/public/.well-known/assetlinks.json b/public/.well-known/assetlinks.json new file mode 100644 index 00000000..af8eb41b --- /dev/null +++ b/public/.well-known/assetlinks.json @@ -0,0 +1,12 @@ +[ + { + "relation": ["delegate_permission/common.handle_all_urls"], + "target": { + "namespace": "android_app", + "package_name": "ae.gov.fcsc.frontend", + "sha256_cert_fingerprints": [ + "3D:BB:9E:B6:3E:80:50:6F:52:EB:73:B8:AD:F9:5F:5A:0A:05:BE:E4:CA:D1:AF:F7:26:2C:56:3F:35:1D:4E:81" + ] + } + } +] diff --git a/pubspec.lock b/pubspec.lock index 1bdd3452..a90e1d09 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -1177,6 +1177,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.28.0" + screenshot: + dependency: "direct main" + description: + name: screenshot + sha256: "63817697a7835e6ce82add4228e15d233b74d42975c143ad8cfe07009fab866b" + url: "https://pub.dev" + source: hosted + version: "3.0.0" sdmx: dependency: "direct main" description: diff --git a/pubspec.yaml b/pubspec.yaml index 0425154b..76c44216 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -26,6 +26,7 @@ dependencies: marquee: ^2.2.3 url_launcher: ^6.3.1 path_provider: ^2.1.5 + screenshot: ^3.0.0 # dynamic_layouts: # git: # url: https://github.com/flutter/packages.git