diff --git a/android/app/build.gradle b/android/app/build.gradle index 374c1b19..7798729d 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 = "9" + flutterVersionCode = "10" } def flutterVersionName = localProperties.getProperty("flutter.versionName") if (flutterVersionName == null) { - flutterVersionName = "1.0.8" + flutterVersionName = "1.0.9" } def keystorePropertiesFile = rootProject.file("key.properties") diff --git a/assets/feedback/disappointed.png b/assets/feedback/disappointed.png new file mode 100644 index 00000000..07335f6f Binary files /dev/null and b/assets/feedback/disappointed.png differ diff --git a/assets/feedback/errorfb.png b/assets/feedback/errorfb.png new file mode 100644 index 00000000..290702c8 Binary files /dev/null and b/assets/feedback/errorfb.png differ diff --git a/assets/feedback/frowning.png b/assets/feedback/frowning.png new file mode 100644 index 00000000..dbca69c0 Binary files /dev/null and b/assets/feedback/frowning.png differ diff --git a/assets/feedback/neutral.png b/assets/feedback/neutral.png new file mode 100644 index 00000000..860ec117 Binary files /dev/null and b/assets/feedback/neutral.png differ diff --git a/assets/feedback/smiling.png b/assets/feedback/smiling.png new file mode 100644 index 00000000..3686209b Binary files /dev/null and b/assets/feedback/smiling.png differ diff --git a/assets/feedback/smilingopenface.png b/assets/feedback/smilingopenface.png new file mode 100644 index 00000000..371acca5 Binary files /dev/null and b/assets/feedback/smilingopenface.png differ diff --git a/assets/feedback/thumbfb.png b/assets/feedback/thumbfb.png new file mode 100644 index 00000000..b5e1afe9 Binary files /dev/null and b/assets/feedback/thumbfb.png differ diff --git a/assets/user_guide/AboutFCSC.png b/assets/user_guide/AboutFCSC.png new file mode 100755 index 00000000..c5017acf Binary files /dev/null and b/assets/user_guide/AboutFCSC.png differ diff --git a/assets/user_guide/appFeatures.png b/assets/user_guide/appFeatures.png new file mode 100755 index 00000000..db30b794 Binary files /dev/null and b/assets/user_guide/appFeatures.png differ diff --git a/assets/user_guide/changePassword.png b/assets/user_guide/changePassword.png new file mode 100755 index 00000000..1838615a Binary files /dev/null and b/assets/user_guide/changePassword.png differ diff --git a/assets/user_guide/editProfile.png b/assets/user_guide/editProfile.png new file mode 100755 index 00000000..890c50c5 Binary files /dev/null and b/assets/user_guide/editProfile.png differ diff --git a/assets/user_guide/getStarted.png b/assets/user_guide/getStarted.png new file mode 100755 index 00000000..a4756317 Binary files /dev/null and b/assets/user_guide/getStarted.png differ diff --git a/assets/user_guide/howUse.png b/assets/user_guide/howUse.png new file mode 100755 index 00000000..e76fa0cc Binary files /dev/null and b/assets/user_guide/howUse.png differ diff --git a/assets/user_guide/purpose.png b/assets/user_guide/purpose.png new file mode 100755 index 00000000..02b31a5a Binary files /dev/null and b/assets/user_guide/purpose.png differ diff --git a/assets/user_guide/stayUpdate.png b/assets/user_guide/stayUpdate.png new file mode 100755 index 00000000..afe141d1 Binary files /dev/null and b/assets/user_guide/stayUpdate.png differ diff --git a/assets/user_guide/whoUse.png b/assets/user_guide/whoUse.png new file mode 100755 index 00000000..fa920d90 Binary files /dev/null and b/assets/user_guide/whoUse.png differ diff --git a/lib/config/my_router.dart b/lib/config/my_router.dart index aa7bfb5b..731091d5 100644 --- a/lib/config/my_router.dart +++ b/lib/config/my_router.dart @@ -293,6 +293,7 @@ // } import 'package:flutter/material.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:uae_stat/presentation/Screens/Bottom%20Navigation%20Pages/UAE_Numbers/Social/marriages.dart'; import 'package:uae_stat/presentation/Screens/auth_verification/registration.dart'; @@ -300,8 +301,17 @@ import 'package:uae_stat/presentation/Screens/charts/chart.dart'; import 'package:uae_stat/presentation/Screens/charts/screens/chart_screen.dart'; import 'package:uae_stat/presentation/Screens/demo_home2.dart'; import 'package:uae_stat/presentation/Screens/online_offline_verification/internet_check.dart'; -import 'package:uae_stat/presentation/routes/auth_routes/pocketbase_service.dart'; -import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/getting_started.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/AboutTheApp/AboutFCSC.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/AboutTheApp/getStarted.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/KeyFeatures/AppFeatures.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/KeyFeatures/ChangeMyPassword.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/KeyFeatures/EditMyProfile.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/KeyFeatures/howUseTheApp.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/KeyFeatures/purpose.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/KeyFeatures/stayUpdate.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/KeyFeatures/useTheApp.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/aboutApp.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/userguide.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; import 'package:uae_stat/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart'; @@ -322,29 +332,38 @@ import '../presentation/routes/drawer_routes/Drawer Items/edit_profile.dart'; import '../presentation/routes/drawer_routes/Drawer Items/feedback.dart'; import '../presentation/routes/drawer_routes/Drawer Items/user_guide/faq_page.dart'; import '../presentation/routes/drawer_routes/Drawer Items/user_guide/features.dart'; -import '../presentation/routes/drawer_routes/Drawer Items/user_guide/user_guide.dart'; import '../presentation/routes/drawer_routes/Drawer Items/manage_users.dart'; -final pbService = PocketBaseService(); +final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(); -Future getInitialRoute() async { - bool isLoggedIn = await pbService.loadSession(); - return isLoggedIn ? '/myhomepage' : '/login'; +Future _checkSession() async { + print('_checkSession'); + await Future.delayed(Duration(seconds: 2)); // Optional splash effect + + String? sessionToken = + await _secureStorage.read(key: "FlutterSecureStorage.session"); + print('sessionToken $sessionToken'); + + if (sessionToken != null && sessionToken.isNotEmpty) { + print('_checkSession home'); + return "/myhomepage"; // Redirect to home page if session is valid + } else { + print('_checkSession login'); + return "/login"; // Redirect to login page if session is invalid + } } final GoRouter router = GoRouter( routes: [ - GoRoute( - path: '/', - builder: (context, state) => LoginRoute(), - - ), // GoRoute( // path: '/', - // redirect: (context, state) async { - // return await getInitialRoute(); - // }, + // //builder: (context, state) => LoginRoute(), + // builder: (context, state) => LoginRoute(), // ), + GoRoute( + path: '/', + redirect: (context, state) async => await _checkSession(), + ), GoRoute( path: '/internetcheck', builder: (context, state) => InternetCheck(), @@ -455,23 +474,70 @@ final GoRouter router = GoRouter( ), GoRoute( path: '/user-guide', - builder: (context, state) => UserGuide(), + builder: (context, state) => Userguide(), routes: [ GoRoute( path: '/features', name: 'features', builder: (context, state) => UsingFeatures(), + routes: [ + GoRoute( + path: 'whoUseApp', + name: 'whoUseApp', + builder: (context, state) => WhoUseTheApp(), + ), + GoRoute( + path: 'howUseApp', + name: 'howUseApp', + builder: (context, state) => HowUseTheApp(), + ), + GoRoute( + path: 'purpose', + name: 'purpose', + builder: (context, state) => Purpose(), + ), + GoRoute( + path: 'stayUpdated', + name: 'stayUpdated', + builder: (context, state) => StayUpdate(), + ), + GoRoute( + path: 'changeMyPassword', + name: 'changeMyPassword', + builder: (context, state) => ChangeMyPassword(), + ), + GoRoute( + path: 'appFeatures', + name: 'appFeatures', + builder: (context, state) => AppFeatures(), + ), + GoRoute( + path: 'editMyProfile', + name: 'editMyProfile', + builder: (context, state) => EditMyProfile(), + ), + ], ), + GoRoute( + path: 'aboutApp', + builder: (context, state) => aboutTheApp(), + routes: [ + GoRoute( + path: 'aboutFCSC', + name: 'aboutFCSC', + builder: (context, state) => aboutFCSC(), + ), + GoRoute( + path: 'getStarted', + name: 'getStarted', + builder: (context, state) => GetStarted(), + ), + ]), GoRoute( path: '/faq', name: 'faq', builder: (context, state) => FAQPage(), ), - GoRoute( - path: '/gettingStarted', - name: 'gettingStarted', - builder: (context, state) => GettingStarted(), - ), ], ), // GoRoute( diff --git a/lib/infrastructure/services/img_asset_paths/feedback_asset_path.dart b/lib/infrastructure/services/img_asset_paths/feedback_asset_path.dart new file mode 100644 index 00000000..9b73196b --- /dev/null +++ b/lib/infrastructure/services/img_asset_paths/feedback_asset_path.dart @@ -0,0 +1,14 @@ +import 'package:flutter/material.dart'; + +abstract class FeedBackAssetPath { + static const _basePath = 'assets/feedback'; + + static const disappointedfb = '$_basePath/disappointed.png'; + static const frowningfb = '$_basePath/frowning.png'; + static const neutralfb = '$_basePath/neutral.png'; + static const smilingfb = '$_basePath/smiling.png'; + static const smilingFacefb = '$_basePath/smilingopenface.png'; + static const thumbfb = '$_basePath/thumbfb.png'; + static const errorfb = '$_basePath/errorfb.png'; + +} \ No newline at end of file diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index f99002cb..0e9f3c2d 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,8 +1,8 @@ { - "feedback_title": "FeedBack", - "feedback_failed_msg": "Your feedback could not be submitted. Please try again", + "feedback_title": "Feedback", + "feedback_failed_msg": "Your feedback could not be \n submitted. Please try again", "register_title": "Register", "register_details": "Please enter your details", diff --git a/lib/presentation/Screens/Bottom Navigation Pages/Competitiveness/competitiveness.dart b/lib/presentation/Screens/Bottom Navigation Pages/Competitiveness/competitiveness.dart index 1ba3fb58..57ec518d 100644 --- a/lib/presentation/Screens/Bottom Navigation Pages/Competitiveness/competitiveness.dart +++ b/lib/presentation/Screens/Bottom Navigation Pages/Competitiveness/competitiveness.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class Competitiveness extends StatelessWidget { @@ -8,16 +9,23 @@ class Competitiveness extends StatelessWidget { Widget build(BuildContext context) { double myheight = MediaQuery.of(context).size.height; double mywidth = MediaQuery.of(context).size.width; - return BaseScaffold( - title: Center( - child: SizedBox( - height: myheight / 5, - width: mywidth / 3, - child: Image(image: AssetImage('assets/logos/uae_stat.png')))), - body: CompetitivenessState(context), + return PopScope( + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + context.go('/myhomepage'); + }, + child: BaseScaffold( + title: Center( + child: SizedBox( + height: myheight / 5, + width: mywidth / 3, + child: Image(image: AssetImage('assets/logos/uae_stat.png')))), + body: CompetitivenessState(context), + ), ); } - Widget CompetitivenessState(BuildContext context) {return Center(child: Text("Competitiveness"));} + + Widget CompetitivenessState(BuildContext context) { + return Center(child: Text("Competitiveness")); + } } - - diff --git a/lib/presentation/Screens/Bottom Navigation Pages/Country_Profile/country_profile.dart b/lib/presentation/Screens/Bottom Navigation Pages/Country_Profile/country_profile.dart index 58a1c5ae..a08720a0 100644 --- a/lib/presentation/Screens/Bottom Navigation Pages/Country_Profile/country_profile.dart +++ b/lib/presentation/Screens/Bottom Navigation Pages/Country_Profile/country_profile.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; import 'package:fl_chart/fl_chart.dart'; @@ -9,16 +10,23 @@ class CountryProfile extends StatelessWidget { Widget build(BuildContext context) { double myheight = MediaQuery.of(context).size.height; double mywidth = MediaQuery.of(context).size.width; - return BaseScaffold( - title: Center( - child: SizedBox( - height: myheight / 5, - width: mywidth / 3, - child: Image(image: AssetImage('assets/logos/uae_stat.png')))), - body: CountryProfileWidget(), + return PopScope( + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + context.go('/myhomepage'); + }, + child: BaseScaffold( + title: Center( + child: SizedBox( + height: myheight / 5, + width: mywidth / 3, + child: Image(image: AssetImage('assets/logos/uae_stat.png')))), + body: CountryProfileWidget(), + ), ); } } + class CountryProfileWidget extends StatelessWidget { const CountryProfileWidget({super.key}); @@ -28,99 +36,20 @@ class CountryProfileWidget extends StatelessWidget { } } - - - - class HorizontalBarChart extends StatelessWidget { final List xAxisData = ['2019', '2020', '2021', '2022', '2023']; final List yAxisData = [2, 4, 1, 5, 3]; - @override Widget build(BuildContext context) { double myheight = MediaQuery.of(context).size.height; return Scaffold( - appBar: AppBar(title: Text('Horizontal Bar Chart')), + // appBar: AppBar(title: Text('Horizontal Bar Chart')), body: Padding( - padding: const EdgeInsets.all(16.0), - child: - Container( - height: myheight/4, - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(12), - boxShadow: [ - BoxShadow( - color: Colors.black12, - blurRadius: 8, - offset: Offset(0, 4), - ), - ], - ), - child: - Padding( - padding: const EdgeInsets.only(top: 16,left: 8.0,right: 8.0,bottom: 8.0), - child: BarChart( - BarChartData( - alignment: BarChartAlignment.spaceAround, - maxY: 8, - barTouchData: BarTouchData(enabled: false), - titlesData: FlTitlesData( - leftTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - interval: 2, - getTitlesWidget: (value, meta) { - return Padding( - padding: const EdgeInsets.only(right: 8.0), - child: Text('${value.toInt()}K'), - ); - }, - reservedSize: 60, - ), - ), - bottomTitles: AxisTitles( - sideTitles: SideTitles( - showTitles: true, - getTitlesWidget: (value, meta) { - return Padding( - padding: const EdgeInsets.only(top: 8.0), - child: Text(xAxisData[value.toInt()]), - ); - }, - reservedSize: 40, - ), - ), - topTitles: AxisTitles( - sideTitles: SideTitles(showTitles: false), // Hides top titles - ), - rightTitles: AxisTitles( - sideTitles: SideTitles(showTitles: false), // Hides right titles - ), - ), - gridData: FlGridData(show: false), - borderData: FlBorderData(show: false), - barGroups: List.generate( - xAxisData.length, - (index) => BarChartGroupData( - x: index, - barRods: [ - BarChartRodData( - toY: yAxisData[index], - color: Colors.blueAccent, - //colors: [Colors.blueAccent], - borderRadius: BorderRadius.circular(4), - width: 20, - ), - ], - ), - ), - ), - ), - ), - ), - ), + padding: const EdgeInsets.all(16.0), + child: Center( + child: Text('Coming Soon'), + )), ); } } @@ -129,14 +58,6 @@ void main() { runApp(MaterialApp(home: HorizontalBarChart())); } - // void main() { // runApp(MaterialApp(home: HorizontalBarChart())); // } - - - - - - - diff --git a/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart b/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart index c5bd1e8a..989d5a05 100644 --- a/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart +++ b/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart @@ -12,16 +12,33 @@ import 'package:http/http.dart' as http; class UaeNumbers extends StatelessWidget { const UaeNumbers({super.key}); + @override + // Widget build(BuildContext context) { + // double myheight = MediaQuery.of(context).size.height; + // double mywidth = MediaQuery.of(context).size.width; + // return BaseScaffold( + // title: Text("UAE Numbers"), + // body: + // //EconomicDashboard(), + // //EconomyExpandTile() + // uaenumberWidget()); + // } + @override Widget build(BuildContext context) { double myheight = MediaQuery.of(context).size.height; double mywidth = MediaQuery.of(context).size.width; - return BaseScaffold( + + return PopScope( + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + context.go('/myhomepage'); + }, + child: BaseScaffold( title: Text("UAE Numbers"), - body: - //EconomicDashboard(), - //EconomyExpandTile() - uaenumberWidget()); + body: uaenumberWidget(), + ), + ); } } @@ -81,15 +98,18 @@ class _UaenumberWidgetState extends ConsumerState { children: [ Container( decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(30.0), - border: Border.all(width: 1,color: Color(0xFFAA8E83)),), + color: Colors.white, + borderRadius: BorderRadius.circular(30.0), + border: Border.all(width: 1, color: Color(0xFFAA8E83)), + ), child: TextField( decoration: InputDecoration( hintText: "Search", - prefixIcon: Icon(Icons.search, - color: Color(0xFFAA8E83),), - border: InputBorder.none, + prefixIcon: Icon( + Icons.search, + color: Color(0xFFAA8E83), + ), + border: InputBorder.none, contentPadding: EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0), ), @@ -109,7 +129,7 @@ class _UaenumberWidgetState extends ConsumerState { return CustomExpandableTile( index: index, -isExpanded: expandedIndex == index, // Compare with expandedIndex + isExpanded: expandedIndex == index, // Compare with expandedIndex onTap: (index) { setState(() { expandedIndex = (expandedIndex == index) ? null : index; @@ -297,7 +317,6 @@ class CustomExpandableTile extends StatefulWidget { final bool isExpanded; final ValueChanged onTap; - const CustomExpandableTile({ required this.title, required this.titleBackgroundColor, @@ -305,7 +324,6 @@ class CustomExpandableTile extends StatefulWidget { required this.index, required this.isExpanded, required this.onTap, - }); @override @@ -329,8 +347,7 @@ class _CustomExpandableTileState extends State { child: Column( children: [ GestureDetector( - onTap: () => widget.onTap(widget.index), - + onTap: () => widget.onTap(widget.index), child: Container( decoration: BoxDecoration( color: widget.titleBackgroundColor, diff --git a/lib/presentation/Screens/auth_verification/registration.dart b/lib/presentation/Screens/auth_verification/registration.dart index 31e17ba4..7e445ccc 100644 --- a/lib/presentation/Screens/auth_verification/registration.dart +++ b/lib/presentation/Screens/auth_verification/registration.dart @@ -15,12 +15,12 @@ import 'package:uae_stat/presentation/components/indicators/locale_provider.dart import '../../components/my_toggle.dart'; import '../../routes/auth_routes/login_route.dart'; -class RegisterScreen extends StatefulWidget { +class RegisterScreen extends ConsumerStatefulWidget { @override _RegisterScreenState createState() => _RegisterScreenState(); } -class _RegisterScreenState extends State { +class _RegisterScreenState extends ConsumerState { final _formKey = GlobalKey(); final _usernameController = TextEditingController(); final _emailController = TextEditingController(); @@ -311,6 +311,7 @@ class _RegisterScreenState extends State { Widget build(BuildContext context) { double screenheight = MediaQuery.of(context).size.height; double screenwidth = MediaQuery.of(context).size.width; + final registerLocale = ref.watch(localeProvider); Widget buildIconContainer(IconData icon, Color iconColor) { return Container( @@ -337,28 +338,35 @@ class _RegisterScreenState extends State { return Scaffold( - body: - + body: + Column( children: [ - Consumer( - builder: (context, ref, _) { - final locale = ref.watch(localeProvider); // Current locale - return - Align( - alignment: AlignmentDirectional.topEnd, - child: MyToggle( - isOn: locale?.languageCode == 'en', - knobTextWhenOn: 'ع', - knobTextWhenOff: 'EN', - pathColorWhenOn: Colors.grey.shade300, - pathColorWhenOff: Colors.grey.shade300, - onTap: () { - ref.read(localeProvider.notifier).toggleLocale(); - }, - ), + Align( + alignment: AlignmentDirectional.topEnd, + child: Consumer( + builder: (context, ref, _) { + final locale = ref.watch(localeProvider); // Current locale + return MyToggle( + isOn: locale?.languageCode == 'en', + knobTextWhenOn: 'ع', + knobTextWhenOff: 'EN', + pathColorWhenOn: Colors.grey.shade300, + pathColorWhenOff: Colors.grey.shade300, + onTap: () { + ref.read(localeProvider.notifier).toggleLocale(); + }, ); - }, + // IconButton( + // icon: Icon(locale?.languageCode == 'en' + // ? Icons.toggle_off_outlined + // : Icons.toggle_on_outlined,), + // onPressed: () { + // ref.read(localeProvider.notifier).toggleLocale(); + // }, + // ); + }, + ), ), Container( height: MediaQuery.of(context).size.height/1.2, @@ -531,153 +539,157 @@ class _RegisterScreenState extends State { ), ), - // prefixIcon: Icon( - // Icons.person, - // color: Color(0xFF90B0D5), - // - // ), - // border: OutlineInputBorder(), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: MyTheme.topicColor( - IndicatorTopic.economy) - .shade400, - width: 1), // 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(0xFFb22222), - width: 1), // Error border - ), - focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: Color(0xFFb22222), - width: 1), // Match the error color - ), - counterText: '', - hintStyle: TextStyle(color: Color(0xFFC3C6CB)), - ), - validator: _validateUsername, - maxLength: - 40, // Set the maximum length to 20 characters - maxLengthEnforcement: MaxLengthEnforcement.enforced, - ), - ), - SizedBox(height: 15), - Padding( - padding: const EdgeInsets.only( - top: 5.0, bottom: 10, left: 30, right: 30), - child: TextFormField( - controller: _emailController, - // focusNode: _focusNodes[1], - decoration: InputDecoration( - // hintText: 'Enter your email', - hintText: _showHints[1] - ? AppLocalizations.of(context)! - .enter_your_email - : null, - // _showHints[1] ? 'Enter your email' : null, - prefixIconConstraints: const BoxConstraints( - maxWidth: 25 + 16 + 10, - maxHeight: 25 + (8 * 2), - ), - prefixIcon: Padding( - padding: const EdgeInsetsDirectional.only( - start: 16, - end: 10, - ), - child: Image.asset( - MiscIconAssetPath.vector, - fit: BoxFit.fitHeight, - height: 20, - width: 25, - color: - MyTheme.topicColor(IndicatorTopic.economy) - .shade100, - ), - ), + // prefixIcon: Icon( + // Icons.person, + // color: Color(0xFF90B0D5), + // + // ), + // border: OutlineInputBorder(), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: MyTheme.topicColor( + IndicatorTopic.economy) + .shade400, + width: 1), // 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(0xFFb22222), + width: 1), // Error border + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Color(0xFFb22222), + width: 1), // Match the error color + ), + counterText: '', + hintStyle: TextStyle(color: Color(0xFFC3C6CB), + fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, + ), + ), + validator: _validateUsername, + maxLength: + 40, // Set the maximum length to 20 characters + maxLengthEnforcement: MaxLengthEnforcement.enforced, + ), + ), + SizedBox(height: 15), + Padding( + padding: const EdgeInsets.only( + top: 5.0, bottom: 10, left: 30, right: 30), + child: TextFormField( + controller: _emailController, + // focusNode: _focusNodes[1], + decoration: InputDecoration( + // hintText: 'Enter your email', + hintText: _showHints[1] + ? AppLocalizations.of(context)! + .enter_your_email + : null, + // _showHints[1] ? 'Enter your email' : null, + prefixIconConstraints: const BoxConstraints( + maxWidth: 25 + 16 + 10, + maxHeight: 25 + (8 * 2), + ), + prefixIcon: Padding( + padding: const EdgeInsetsDirectional.only( + start: 16, + end: 10, + ), + child: Image.asset( + MiscIconAssetPath.vector, + fit: BoxFit.fitHeight, + height: 20, + width: 25, + color: + MyTheme.topicColor(IndicatorTopic.economy) + .shade100, + ), + ), - // border: OutlineInputBorder(), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: MyTheme.topicColor( - IndicatorTopic.economy) - .shade400, - width: 1), - ), - 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(0xFFb22222), - width: 1), // Error border - ), - focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: Color(0xFFb22222), - width: 1), // Match the error color - ), - counterText: '', - hintStyle: TextStyle(color: Color(0xFFC3C6CB)), - ), - validator: _validateEmail, - maxLength: 320, - maxLengthEnforcement: MaxLengthEnforcement.enforced, - inputFormatters: [ - LengthLimitingTextInputFormatter( - 320), // Limit to 320 characters - ], - ), - ), - SizedBox(height: 15), - Padding( - padding: const EdgeInsets.only( - top: 5.0, bottom: 10, left: 30, right: 30), - child: TextFormField( - controller: _passwordController, - // focusNode: _focusNodes[2], - obscureText: _obscurePassword, - decoration: InputDecoration( - hintText: _showHints[2] - ? AppLocalizations.of(context)! - .enter_your_password - : null, - // _showHints[2] ? 'Enter your password' : null, - prefixIconConstraints: const BoxConstraints( - maxWidth: 25 + 16 + 10, - maxHeight: 25 + (8 * 2), - ), - prefixIcon: Padding( - padding: const EdgeInsetsDirectional.only( - start: 16, - end: 10, - ), - child: Image.asset( - MiscIconAssetPath.lock, - fit: BoxFit.fitHeight, - height: 25, - width: 25, - color: - MyTheme.topicColor(IndicatorTopic.economy) - .shade300, - ), - ), + // border: OutlineInputBorder(), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: MyTheme.topicColor( + IndicatorTopic.economy) + .shade400, + width: 1), + ), + 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(0xFFb22222), + width: 1), // Error border + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Color(0xFFb22222), + width: 1), // Match the error color + ), + counterText: '', + hintStyle: TextStyle(color: Color(0xFFC3C6CB), + fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, + ), + ), + validator: _validateEmail, + maxLength: 320, + maxLengthEnforcement: MaxLengthEnforcement.enforced, + inputFormatters: [ + LengthLimitingTextInputFormatter( + 320), // Limit to 320 characters + ], + ), + ), + SizedBox(height: 15), + Padding( + padding: const EdgeInsets.only( + top: 5.0, bottom: 10, left: 30, right: 30), + child: TextFormField( + controller: _passwordController, + // focusNode: _focusNodes[2], + obscureText: _obscurePassword, + decoration: InputDecoration( + hintText: _showHints[2] + ? AppLocalizations.of(context)! + .enter_your_password + : null, + // _showHints[2] ? 'Enter your password' : null, + prefixIconConstraints: const BoxConstraints( + maxWidth: 25 + 16 + 10, + maxHeight: 25 + (8 * 2), + ), + prefixIcon: Padding( + padding: const EdgeInsetsDirectional.only( + start: 16, + end: 10, + ), + child: Image.asset( + MiscIconAssetPath.lock, + fit: BoxFit.fitHeight, + height: 25, + width: 25, + color: + MyTheme.topicColor(IndicatorTopic.economy) + .shade300, + ), + ), // prefixIcon: Icon( // Icons.lock, @@ -736,47 +748,49 @@ class _RegisterScreenState extends State { width: 1), // Match the error color ), - counterText: '', - hintStyle: TextStyle(color: Color(0xFFC3C6CB)), - ), - validator: _validatePassword, - maxLength: 40, - maxLengthEnforcement: MaxLengthEnforcement.enforced, - ), - ), - SizedBox(height: 15), - Padding( - padding: const EdgeInsets.only( - top: 5.0, bottom: 10, left: 30, right: 30), - child: TextFormField( - controller: _confirmpasswordController, - // focusNode: _focusNodes[3], - obscureText: _obscureConfirmPassword, - decoration: InputDecoration( - hintText: _showHints[3] - ? AppLocalizations.of(context)! - .register_Confirm_password - : null, - // _showHints[3] ? 'Confirm password' : null, - prefixIconConstraints: const BoxConstraints( - maxWidth: 25 + 16 + 10, - maxHeight: 25 + (8 * 2), - ), - prefixIcon: Padding( - padding: const EdgeInsetsDirectional.only( - start: 16, - end: 10, - ), - child: Image.asset( - MiscIconAssetPath.lock, - fit: BoxFit.fitHeight, - height: 25, - width: 25, - color: - MyTheme.topicColor(IndicatorTopic.economy) - .shade300, - ), - ), + counterText: '', + hintStyle: TextStyle(color: Color(0xFFC3C6CB), + fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, + ), + ), + validator: _validatePassword, + maxLength: 40, + maxLengthEnforcement: MaxLengthEnforcement.enforced, + ), + ), + SizedBox(height: 15), + Padding( + padding: const EdgeInsets.only( + top: 5.0, bottom: 10, left: 30, right: 30), + child: TextFormField( + controller: _confirmpasswordController, + // focusNode: _focusNodes[3], + obscureText: _obscureConfirmPassword, + decoration: InputDecoration( + hintText: _showHints[3] + ? AppLocalizations.of(context)! + .register_Confirm_password + : null, + // _showHints[3] ? 'Confirm password' : null, + prefixIconConstraints: const BoxConstraints( + maxWidth: 25 + 16 + 10, + maxHeight: 25 + (8 * 2), + ), + prefixIcon: Padding( + padding: const EdgeInsetsDirectional.only( + start: 16, + end: 10, + ), + child: Image.asset( + MiscIconAssetPath.lock, + fit: BoxFit.fitHeight, + height: 25, + width: 25, + color: + MyTheme.topicColor(IndicatorTopic.economy) + .shade300, + ), + ), suffixIcon: IconButton( icon: Image.asset( @@ -784,217 +798,222 @@ class _RegisterScreenState extends State { ? 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(() { - _obscureConfirmPassword = - !_obscureConfirmPassword; - }); - }, - ), - // border: OutlineInputBorder( - // borderSide: BorderSide(color: Colors.blue, width: 2), // Default border color - // ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: MyTheme.topicColor( - IndicatorTopic.economy) - .shade400, - width: 1), - ), - 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(0xFFb22222), - width: 1), // Error border - ), - focusedErrorBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(10), - borderSide: BorderSide( - color: Color(0xFFb22222), - width: 1), // Match the error color - ), - counterText: '', - hintStyle: TextStyle(color: Color(0xFFC3C6CB)), + color: Color( + 0xFF9EA2A9), // Apply color if needed, but keep in mind `Image.asset` might not support color directly. + width: 24, + height: 24, + ), + onPressed: () { + setState(() { + _obscureConfirmPassword = + !_obscureConfirmPassword; + }); + }, + ), + // border: OutlineInputBorder( + // borderSide: BorderSide(color: Colors.blue, width: 2), // Default border color + // ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: MyTheme.topicColor( + IndicatorTopic.economy) + .shade400, + width: 1), + ), + 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(0xFFb22222), + width: 1), // Error border + ), + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10), + borderSide: BorderSide( + color: Color(0xFFb22222), + width: 1), // Match the error color + ), + counterText: '', + hintStyle: TextStyle(color: Color(0xFFC3C6CB), + fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, + ), + ), + validator: _validateConfirmPassword, + maxLength: 40, + maxLengthEnforcement: MaxLengthEnforcement.enforced, + inputFormatters: [ + LengthLimitingTextInputFormatter( + 64), // Limit to 40 characters + ], + ), + ), + SizedBox(height: 10), + Padding( + padding: const EdgeInsets.only( + top: 1.0, bottom: 10, left: 25, right: 30), + child: Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Checkbox( + value: isChecked, + onChanged: (value) { + setState(() { + isChecked = value ?? false; + showError = false; + }); + }, + side: BorderSide( + color: showError + ? Color(0xFFD83731) + : Color(0xFF7DAFBC), + width: 1, + ), + ), + Expanded( + child: Text.rich( + TextSpan( + text: AppLocalizations.of(context)!.agree, + // text: 'I agree to ', + children: [ + TextSpan( + text: AppLocalizations.of(context)! + .terms_conditions, + // text: 'Terms & Conditions', + style: TextStyle( + fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14, + fontWeight: FontWeight.bold, + color: Color(0xFF985400), + // Makes the text bold + decoration: + TextDecoration.underline, + decorationColor: Color(0xFF985400), + decorationThickness: 1), ), - validator: _validateConfirmPassword, - maxLength: 40, - maxLengthEnforcement: MaxLengthEnforcement.enforced, - inputFormatters: [ - LengthLimitingTextInputFormatter( - 64), // Limit to 40 characters - ], - ), - ), - SizedBox(height: 10), - Padding( - padding: const EdgeInsets.only( - top: 1.0, bottom: 10, left: 25, right: 30), - child: Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Checkbox( - value: isChecked, - onChanged: (value) { - setState(() { - isChecked = value ?? false; - showError = false; - }); - }, - side: BorderSide( - color: showError - ? Color(0xFFD83731) - : Color(0xFF7DAFBC), - width: 1, - ), - ), - Expanded( - child: Text.rich( - TextSpan( - text: AppLocalizations.of(context)!.agree, - // text: 'I agree to ', - children: [ - TextSpan( - text: AppLocalizations.of(context)! - .terms_conditions, - // text: 'Terms & Conditions', - style: TextStyle( - fontWeight: FontWeight.bold, - color: Color(0xFF985400), - // Makes the text bold - decoration: - TextDecoration.underline, - decorationColor: Color(0xFF985400), - decorationThickness: 1), - ), - TextSpan( - text: AppLocalizations.of(context)! - .t_and), - TextSpan( - text: AppLocalizations.of(context)! - .privacy_policy, - style: TextStyle( - fontWeight: FontWeight.bold, - fontSize: 14, - fontFamily: 'Roboto', - color: Color(0xFF985400), - decoration: - TextDecoration.underline, - decorationColor: Color(0xFF648CBA), - decorationThickness: 1), - ), - TextSpan( - text: AppLocalizations.of(context)! - .conditions), - ], - ), - ), - ), - ], - ), - ), - if (showError) - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only(left: 30.0), - child: Text( - 'Required', - style: TextStyle( - color: Color(0xFFb22222), - fontSize: 12, - ), - ), - ), - ], - ), - SizedBox(height: 20), - Padding( - padding: const EdgeInsets.only( - top: 5.0, bottom: 10, left: 30, right: 30), - child: SizedBox( - width: screenwidth / 1, - child: ElevatedButton( - onPressed: isRegistering ? null : _registerUser, - style: ElevatedButton.styleFrom( - backgroundColor: Color( - 0xFFA7887A), // Brownish color for Register - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - // "Register", - AppLocalizations.of(context)! - .register_title, - style: TextStyle( - fontSize: 16, color: Colors.white), - ), - SizedBox(width: 8), - const Icon( - Icons.chevron_right_outlined, - color: Colors - .white, // Set your desired color here - ) - ], - ), + TextSpan( + text: AppLocalizations.of(context)! + .t_and), + TextSpan( + text: AppLocalizations.of(context)! + .privacy_policy, + style: TextStyle( + fontWeight: FontWeight.bold, + fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14, + fontFamily: 'Roboto', + color: Color(0xFF985400), + decoration: + TextDecoration.underline, + decorationColor: Color(0xFF648CBA), + decorationThickness: 1), ), - ), + TextSpan( + text: AppLocalizations.of(context)! + .conditions), + ], ), - SizedBox(height: 15), + ), + ), + ], + ), + ), + if (showError) + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(left: 30.0), + child: Text( + 'Required', + style: TextStyle( + color: Color(0xFFb22222), + fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14, + ), + ), + ), + ], + ), + SizedBox(height: 20), + Padding( + padding: const EdgeInsets.only( + top: 5.0, bottom: 10, left: 30, right: 30), + child: SizedBox( + width: screenwidth / 1, + child: ElevatedButton( + onPressed: isRegistering ? null : _registerUser, + style: ElevatedButton.styleFrom( + backgroundColor: Color( + 0xFFA7887A), // Brownish color for Register + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ Text( - AppLocalizations.of(context)!.account_confirmation, + // "Register", + AppLocalizations.of(context)! + .register_title, style: TextStyle( - fontSize: 14, color: Colors.grey[600]), + fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16, + color: Colors.white), ), - SizedBox(height: 15), - Padding( - padding: const EdgeInsets.only( - top: 5.0, bottom: 10, left: 30, right: 30), - child: SizedBox( - width: screenwidth / 1, - child: ElevatedButton( - onPressed: () { - context.go('/'); - }, - style: ElevatedButton.styleFrom( - backgroundColor: Color( - 0xFF82AFCB), // Blueish color for Login - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(10), - ), - ), - child: Row( - mainAxisSize: MainAxisSize.min, - children: [ - Text( - AppLocalizations.of(context)!.login_title, - style: TextStyle( - fontSize: 16, color: Colors.white), - ), - SizedBox(width: 8), - const Icon( - Icons.chevron_right_outlined, - color: Colors - .white, // Set your desired color here - ) - ], - ), + SizedBox(width: 8), + const Icon( + Icons.chevron_right_outlined, + color: Colors + .white, // Set your desired color here + ) + ], + ), + ), + ), + ), + SizedBox(height: 15), + Text( + AppLocalizations.of(context)!.account_confirmation, + style: TextStyle( + fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14, + color: Colors.grey[600]), + ), + SizedBox(height: 15), + Padding( + padding: const EdgeInsets.only( + top: 5.0, bottom: 10, left: 30, right: 30), + child: SizedBox( + width: screenwidth / 1, + child: ElevatedButton( + onPressed: () { + context.go('/'); + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color( + 0xFF82AFCB), // Blueish color for Login + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + AppLocalizations.of(context)!.login_title, + style: TextStyle( + fontSize: 16, color: Colors.white), + ), + SizedBox(width: 8), + const Icon( + Icons.chevron_right_outlined, + color: Colors + .white, // Set your desired color here + ) + ], + ), // child: GestureDetector( // onTap: () { diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index f9667d3b..6b43a080 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -12,6 +12,7 @@ import 'package:pocketbase/pocketbase.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/bottom_bar_routes/tab_routes/home_route.dart'; +import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import '../components/my_bottom_nav_bar.dart'; import 'auth_verification/changepassword.dart'; @@ -353,7 +354,7 @@ class _ProfileScreenState extends State { }, ), title: Text( - 'My Profile', + AppLocalizations.of(context)!.my_profile, style: TextStyle(color: Color(0xFF985400)), ), actions: [ @@ -447,7 +448,7 @@ class _ProfileScreenState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - "User Name", + AppLocalizations.of(context)!.register_name, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, @@ -473,7 +474,7 @@ class _ProfileScreenState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - "Email ID", + AppLocalizations.of(context)!.email_id, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500, @@ -500,7 +501,7 @@ class _ProfileScreenState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - "Full Name*", + AppLocalizations.of(context)!.full_name, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500), ), @@ -541,7 +542,7 @@ class _ProfileScreenState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - "Date of Birth*", + AppLocalizations.of(context)!.dob, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500), ), @@ -583,7 +584,7 @@ class _ProfileScreenState extends State { mainAxisAlignment: MainAxisAlignment.start, children: [ Text( - "Country/Region*", + AppLocalizations.of(context)!.region, style: TextStyle( fontSize: 16, fontWeight: FontWeight.w500), ), @@ -645,12 +646,15 @@ class _ProfileScreenState extends State { ), Text.rich( TextSpan( - text: 'I agree to the ', - style: TextStyle(color: Colors.black), + text: AppLocalizations.of( + context)! + .agree, style: TextStyle(color: Colors.black), children: [ TextSpan( - text: 'Terms & Conditions', - style: TextStyle( + text: AppLocalizations.of( + context, + )! + .terms_conditions, style: TextStyle( color: Color(0xFF648CBA), decoration: TextDecoration.underline, fontWeight: FontWeight @@ -664,12 +668,14 @@ class _ProfileScreenState extends State { }, ), TextSpan( - text: ' and ', - style: TextStyle(color: Colors.black), + text: AppLocalizations.of( + context, + )!.t_and, style: TextStyle(color: Colors.black), ), TextSpan( - text: 'Privacy Policy', - style: TextStyle( + text: AppLocalizations.of( + context, + )!.privacy_policy, style: TextStyle( color: Color(0xFF648CBA), decoration: TextDecoration.underline, fontWeight: FontWeight @@ -683,7 +689,10 @@ class _ProfileScreenState extends State { }, ), TextSpan( - text: ' of FCSC.', + text: AppLocalizations.of( + context, + )! + .conditions, style: TextStyle(color: Colors.black), ), ], @@ -724,7 +733,8 @@ class _ProfileScreenState extends State { context.go('/createNewPw/$userId/$email'); }, child: Text( - 'Change Password', + AppLocalizations.of(context)! + .change_password, style: TextStyle( color: Color(0xFF648CBA), fontSize: 14, @@ -762,7 +772,7 @@ class _ProfileScreenState extends State { MainAxisAlignment.center, // Center the content children: [ Text( - 'Save', + AppLocalizations.of(context)!.save, style: TextStyle(color: Colors.white), ), SizedBox(width: 8), // Add space between text and icon diff --git a/lib/presentation/routes/auth_routes/login_route.dart b/lib/presentation/routes/auth_routes/login_route.dart index 54a4e143..9f956b3d 100644 --- a/lib/presentation/routes/auth_routes/login_route.dart +++ b/lib/presentation/routes/auth_routes/login_route.dart @@ -1,7 +1,10 @@ +import 'dart:convert'; + 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:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -17,7 +20,6 @@ import 'package:uae_stat/presentation/components/lang_toggle.dart'; 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/auth_routes/pocketbase_service.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'; @@ -28,13 +30,14 @@ import '../../components/my_toggle.dart'; class LoginRoute extends HookConsumerWidget { final pb = PocketBase('https://pb.venbait.in'); - final _pbService = PocketBaseService(); + final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(); // final _pb = PocketBase('http://127.0.0.1:8090'); // 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; + int? loginCount; static final formKey = GlobalKey(); @@ -83,11 +86,41 @@ class LoginRoute extends HookConsumerWidget { } } - Future saveUserId(String userId) async { + Future saveUserId(String userId, count) async { + print(count); final prefs = await SharedPreferences.getInstance(); await prefs.setString('userId', userId); // Save userId locally + await prefs.setString('login_count', count.toString()); } + // Future authenticateAndStoreData() async { + // try { + // // Perform authentication + // final authData = await pb + // .collection("users") + // .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); + // + // // Check if authentication is successful + // if (pb.authStore.isValid) { + // print("Authentication successful!"); + // print("Token: ${pb.authStore.token}"); + // // print("User ID: ${pb.authStore.record.id}"); + // + // // Store the token and user ID in local storage + // await _secureStorage.write( + // key: "FlutterSecureStorage.session", value: pb.authStore.token); + // // await _secureStorage.write( + // // key: "FlutterSecureStorage.userId", value: pb.authStore.record.id); + // + // print("Session and User ID stored in local storage."); + // } else { + // print("Authentication failed."); + // } + // } catch (e) { + // print("Error during authentication: $e"); + // } + // } + @override Widget build(BuildContext context, WidgetRef ref) { final locale = ref.watch(localeProvider); @@ -112,7 +145,7 @@ class LoginRoute extends HookConsumerWidget { 'إعادة تعيين كلمة المرور', ), style: TextStyle( - fontSize: 20, + fontSize: locale?.languageCode == 'ar' ? 18 : 20, color: Color(0xFF898C81), fontWeight: FontWeight.w600), ), @@ -127,7 +160,7 @@ class LoginRoute extends HookConsumerWidget { 'عنوان البريد الإلكتروني', ), labelStyle: TextStyle( - fontSize: 16, + fontSize: locale?.languageCode == 'ar' ? 13 : 16, color: Color(0xFF898C81), // For label text color // fontWeight: FontWeight.w600, ), @@ -206,6 +239,13 @@ class LoginRoute extends HookConsumerWidget { ), ); }, + style: TextButton.styleFrom( + padding: EdgeInsets.zero, + // maximumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + visualDensity: VisualDensity.compact, + overlayColor: Colors.white + ), child: Text( context.translate( 'Forgot Password?', @@ -214,10 +254,10 @@ class LoginRoute extends HookConsumerWidget { style: TextStyle( fontFamily: context.translate( 'Roboto', - 'NotoKufi', + 'Roboto', ), fontWeight: FontWeight.bold, - fontSize: 14, + fontSize: locale?.languageCode == 'ar' ? 12 : 14, color: Color(0xFF985400), ), ), @@ -305,6 +345,10 @@ class LoginRoute extends HookConsumerWidget { if (response.statusCode == 200) { print("Login success API call successful: ${response.body}"); + final count = jsonDecode(response.body); + loginCount = + count["login_count"]; // Directly assign it as an int + print(loginCount); } else { print( "Failed to call login success API. Status code: ${response.statusCode}"); @@ -313,7 +357,7 @@ class LoginRoute extends HookConsumerWidget { print("Error calling login success API: $e"); } - await saveUserId(userId); + await saveUserId(userId, loginCount); } try { final bool isProfileComplete = await profileStatus(userId); @@ -374,9 +418,9 @@ class LoginRoute extends HookConsumerWidget { TextStyle( fontFamily: context.translate( 'Roboto', - 'NotoKufi', + 'Roboto', ), - fontSize: 16, + fontSize: locale?.languageCode == 'ar' ? 14 : 16, fontWeight: FontWeight.w600, ), ), @@ -398,6 +442,14 @@ class LoginRoute extends HookConsumerWidget { 'Login', 'تسجيل الدخول', ), + style: TextStyle( + fontFamily: context.translate( + 'Roboto', + 'Roboto', + ), + fontSize: locale?.languageCode == 'ar' ? 16: 18, + fontWeight: FontWeight.bold, + ) ), 6.horizontalSpace, const Icon( @@ -467,9 +519,9 @@ class LoginRoute extends HookConsumerWidget { style: TextStyle( fontFamily: context.translate( 'Roboto', - 'NotoKufi', + 'Roboto', ), - fontSize: 40, + fontSize: locale?.languageCode == 'ar' ? 38 : 40, fontWeight: FontWeight.w300, ), ), @@ -483,7 +535,7 @@ class LoginRoute extends HookConsumerWidget { style: TextStyle( fontFamily: context.translate( 'Roboto', - 'NotoKufi', + 'Roboto', ), fontSize: context.translate(18.0, 14.0), color: const Color(0xff898C81), @@ -500,15 +552,15 @@ class LoginRoute extends HookConsumerWidget { style: TextStyle( fontFamily: context.translate( 'Roboto', - 'NotoKufi', + 'Roboto', ), - fontSize: 14, + fontSize: locale?.languageCode == 'ar' ? 12 : 14, fontWeight: FontWeight.bold, ), children: [ TextSpan( text: context.translate( - 'Don\'t have an account? ', + 'Don\'t have an account?', 'ليس لديك حساب؟', ), style: const TextStyle( @@ -591,16 +643,14 @@ class LoginRoute extends HookConsumerWidget { height: 40, ); final screenWidth = MediaQuery.of(context).size.width; - final listViewHorizontalPadding = screenWidth < 700 ? 30 : 30 + (screenWidth - 700) / 2; final scaffoldBody = ListView( - // padding: EdgeInsets.symmetric( - // horizontal: listViewHorizontalPadding.toDouble(), - // ), + padding: EdgeInsets.symmetric( + horizontal: listViewHorizontalPadding.toDouble(), + ), children: [ - 10.verticalSpace, - + 3.verticalSpace, Align( alignment: AlignmentDirectional.topEnd, child: MyToggle( @@ -614,36 +664,16 @@ class LoginRoute extends HookConsumerWidget { }, ), ), - 16.verticalSpace, - Padding( - padding: EdgeInsets.symmetric( - horizontal: listViewHorizontalPadding.toDouble(), - ), - child: helloAndPleaseLoginTexts, - ), + 36.verticalSpace, + helloAndPleaseLoginTexts, 42.verticalSpace, - Padding( - padding: EdgeInsets.symmetric( - horizontal: listViewHorizontalPadding.toDouble(), - ), - child: form, - ), + form, 15.verticalSpace, - Padding( - padding: EdgeInsets.symmetric( - horizontal: listViewHorizontalPadding.toDouble(), - ), - child: dontHaveAnAccountRegisterBtn, - ), + dontHaveAnAccountRegisterBtn, 20.verticalSpace, // continueAsGuestBtn, 95.verticalSpace, - Padding( - padding: EdgeInsets.symmetric( - horizontal: listViewHorizontalPadding.toDouble(), - ), - child: fcscBanner, - ), + fcscBanner, ], ); // final bgScaffold = Scaffold( diff --git a/lib/presentation/routes/auth_routes/pocketbase_service.dart b/lib/presentation/routes/auth_routes/pocketbase_service.dart deleted file mode 100644 index 8e5cc2c8..00000000 --- a/lib/presentation/routes/auth_routes/pocketbase_service.dart +++ /dev/null @@ -1,66 +0,0 @@ -import 'package:pocketbase/pocketbase.dart'; -import 'package:shared_preferences/shared_preferences.dart'; - -class PocketBaseService { - final PocketBase pb = PocketBase('https://pb.venbait.in'); - - // Save session to local storage - Future saveSession() async { - final prefs = await SharedPreferences.getInstance(); - await prefs.setString('pb_auth', pb.authStore.token); - await prefs.setString('pb_user', pb.authStore.model.toJson()); - await prefs.setInt('pb_auth_time', DateTime.now().millisecondsSinceEpoch); - } - - // Load session from local storage - Future loadSession() async { - final prefs = await SharedPreferences.getInstance(); - final token = prefs.getString('pb_auth'); - final userJson = prefs.getString('pb_user'); - - if (token != null && userJson != null) { - pb.authStore - .save(token, RecordModel.fromJson(userJson as Map)); - - if (!pb.authStore.isValid || isSessionExpired(prefs)) { - await clearSession(); - return false; - } - return true; - } - return false; - } - - // Check if the session is expired (4 days) - bool isSessionExpired(SharedPreferences prefs) { - final savedTime = prefs.getInt('pb_auth_time') ?? 0; - final currentTime = DateTime.now().millisecondsSinceEpoch; - const sessionDuration = Duration(days: 4); - return (currentTime - savedTime) > sessionDuration.inMilliseconds; - } - - // User login - Future loginUser(String email, String password) async { - try { - await pb.collection('users').authWithPassword(email, password); - await saveSession(); - return true; - } catch (e) { - return false; - } - } - - // User logout - Future logoutUser() async { - pb.authStore.clear(); - await clearSession(); - } - - // Clear session from local storage - Future clearSession() async { - final prefs = await SharedPreferences.getInstance(); - await prefs.remove('pb_auth'); - await prefs.remove('pb_user'); - await prefs.remove('pb_auth_time'); - } -} 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 e4d22b45..6d7b850e 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 @@ -233,6 +233,7 @@ class EconomyStatsState extends ConsumerState { print('render finished'); _showHomeTour(); } else { + print('render delayed'); Future.delayed(Duration(milliseconds: 100), _starTourRender); } } @@ -804,7 +805,19 @@ class EconomyStatsState extends ConsumerState { super.initState(); final locale = ref.read(localeProvider); fetchData(locale?.languageCode ?? 'en'); - _fetchUserData(); + // _fetchUserData(); + _loadLoginCount(); + } + + Future _loadLoginCount() async { + final prefs = await SharedPreferences.getInstance(); + String? loginCount = prefs.getString('login_count'); + print('Login Count: $loginCount'); // Debugging + if (loginCount == '1') { + WidgetsBinding.instance.addPostFrameCallback((_) { + _starTourRender(); + }); + } } // @override @@ -820,33 +833,35 @@ class EconomyStatsState extends ConsumerState { 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) { - setState(() { - WidgetsBinding.instance.addPostFrameCallback((_) { - _starTourRender(); - }); - }); - } - } catch (e) { - print('Error fetching user details: $e'); - } - } + // 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) { + // print('_starTourRender count 1'); + // setState(() { + // print('_starTourRender'); + // WidgetsBinding.instance.addPostFrameCallback((_) { + // _starTourRender(); + // }); + // }); + // } + // } catch (e) { + // print('Error fetching user details: $e'); + // } + // } Future fetchData(locale) async { const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart index 75e2ccbd..395a8363 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart @@ -1,8 +1,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; - class BookMark extends ConsumerStatefulWidget { const BookMark({super.key}); @@ -59,23 +59,29 @@ class _BookMarkState extends ConsumerState { @override Widget build(BuildContext context) { - final filteredList = dataList.where((item) => item['isBookmark'] == true) - .toList(); - return BaseScaffold( - title: Text('Bookmark'), - body: Padding( - padding: const EdgeInsets.all(8.0), - child: GridView.builder( - gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( - crossAxisCount: 2, // Two columns - crossAxisSpacing: 10.0, - mainAxisSpacing: 10.0, - mainAxisExtent: 100, + final filteredList = + dataList.where((item) => item['isBookmark'] == true).toList(); + return PopScope( + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + context.go('/myhomepage'); + }, + child: BaseScaffold( + title: Text('Bookmark'), + body: Padding( + padding: const EdgeInsets.all(8.0), + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, // Two columns + crossAxisSpacing: 10.0, + mainAxisSpacing: 10.0, + mainAxisExtent: 100, + ), + itemCount: filteredList.length, + itemBuilder: (context, index) { + return _buildBox(filteredList[index], context); + }, ), - itemCount: filteredList.length, - itemBuilder: (context, index) { - return _buildBox(filteredList[index], context); - }, ), ), ); @@ -88,10 +94,7 @@ class _BookMarkState extends ConsumerState { debugPrint("Box clicked: ${data['title']}"); }, child: Container( - width: MediaQuery - .of(context) - .size - .width * 0.4, + width: MediaQuery.of(context).size.width * 0.4, height: 100, padding: EdgeInsets.all(8.0), decoration: BoxDecoration( @@ -131,14 +134,16 @@ class _BookMarkState extends ConsumerState { setState(() { // Change isOpen to false when icon is clicked int index = dataList.indexWhere( - (item) => item['title'] == data['title'],); + (item) => item['title'] == data['title'], + ); if (index != -1) { dataList[index]['isBookmark'] = false; ScaffoldMessenger.of(context).showSnackBar( SnackBar( content: Text( 'Removed From Bookmark', - style: TextStyle(color: Color(0xFF2F692C), + style: TextStyle( + color: Color(0xFF2F692C), fontWeight: FontWeight.w600), ), backgroundColor: Color(0xFFD6E9C6), @@ -150,7 +155,8 @@ class _BookMarkState extends ConsumerState { SnackBar( content: Text( 'Failed to Remove', - style: TextStyle(color: Color(0xFFEB5F24), + style: TextStyle( + color: Color(0xFFEB5F24), fontWeight: FontWeight.w600), ), backgroundColor: Color(0xFF544C4C), @@ -191,4 +197,4 @@ class _BookMarkState extends ConsumerState { ), ); } -} \ No newline at end of file +} 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 55d92b96..0e4b8d51 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart @@ -77,7 +77,7 @@ class _EditProfileState extends State { dynamic collectionId; dynamic role; - bool _isHoveringDropdown = false; + bool _isHoveringDropdown = false; @override void initState() { @@ -424,585 +424,608 @@ class _EditProfileState extends State { @override Widget build(BuildContext context) { - return BaseScaffold( - title: Text(AppLocalizations.of(context)!.my_profile, - style: TextStyle(color: Color(0xFF985400)),), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 3.0), - child: Column( - children: [ - SingleChildScrollView( - child: Form( - key: _formKey, - child: Padding( - // padding: const EdgeInsets.all(20.0), -padding: const EdgeInsets.only( - top: 20.0, bottom: 20.0, left: 25, right: 25), - child: isPageLoad - ? Center( - child: CircularProgressIndicator(), - ) - : Column( - children: [ - // CircleAvatar( - // radius: 50, - // backgroundImage: _profileImage != null - // ? FileImage( - // _profileImage!) // If a local file is selected - // : _avatarUrl.isNotEmpty - // ? NetworkImage(_avatarUrl) // Load from URL - // : AssetImage( - // "assets/edit_profile/profile.png") - // as ImageProvider, - // - // //backgroundImage: NetworkImage(_avatarUrl) as ImageProvider, - // - // child: - // Align( - // alignment: Alignment.bottomRight, - // child: GestureDetector( - // onTap: _pickImage, // Call `_pickImage` on tap - // child: CircleAvatar( - // radius: 15, - // backgroundColor: Colors.white, - // child: Icon( - // Icons.camera_alt, - // size: 15, - // color: Colors.grey, - // ), - // ), - // ), - // ), - // ), - - // Stack( - // alignment: Alignment.center, - // children: [ - // // FutureBuilder to load the image - // FutureBuilder( - // future: _loadProfileImage(), - // builder: (context, snapshot) { - // if (snapshot.connectionState == ConnectionState.waiting) { - // // While the image is loading, show a progress indicator - // return CircleAvatar( - // radius: 50, - // child: CircularProgressIndicator(), - // ); - // } else if (snapshot.hasError || snapshot.data == null) { - // // If there's an error or no image, show an error icon - // return CircleAvatar( - // radius: 50, - // child: CircularProgressIndicator(), - // ); - // } else { - // // Display the loaded image - // return CircleAvatar( - // radius: 50, - // backgroundImage: snapshot.data, - // child: Align( - // alignment: Alignment.bottomRight, - // child: GestureDetector( - // onTap: _pickImage, - // child: CircleAvatar( - // radius: 15, - // backgroundColor: Colors.white, - // child: Icon( - // Icons.camera_alt, - // size: 15, - // color: Colors.grey, - // ), - // ), - // ), - // ), - // ); - // } - // }, - // ), - // ], - // ), - - Stack( - alignment: Alignment.center, + return PopScope( + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + context.go('/myhomepage'); + }, + child: BaseScaffold( + title: Text( + AppLocalizations.of(context)!.my_profile, + style: TextStyle(color: Color(0xFF985400)), + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 3.0), + child: Column( + children: [ + SingleChildScrollView( + child: Form( + key: _formKey, + child: Padding( + // padding: const EdgeInsets.all(20.0), + padding: const EdgeInsets.only( + top: 20.0, bottom: 20.0, left: 25, right: 25), + child: isPageLoad + ? Center( + child: CircularProgressIndicator(), + ) + : Column( children: [ - CircleAvatar( - radius: 50, - backgroundImage: _profileImage != null - ? FileImage( - _profileImage!) // If a local file is selected - : _avatarUrl.isNotEmpty - ? NetworkImage( - _avatarUrl) // Load from URL - : AssetImage( - 'assets/edit_profile/profile.png') - as ImageProvider, - child: _avatarUrl.isNotEmpty - ? FutureBuilder( - future: _loadImage(_avatarUrl), - builder: (context, snapshot) { - if (snapshot.connectionState == - ConnectionState.waiting) { - return Center( - child: - CircularProgressIndicator(), - ); - } else if (snapshot.hasError) { - return Center( - child: Icon(Icons.error), - ); - } else { - return Align( - alignment: - Alignment.bottomRight, - child: GestureDetector( - onTap: - _pickImage, // Call `_pickImage` on tap - child: CircleAvatar( - radius: 15, - backgroundColor: - Colors.white, - child: Icon( - Icons.camera_alt, - size: 15, - color: Colors.grey, + // CircleAvatar( + // radius: 50, + // backgroundImage: _profileImage != null + // ? FileImage( + // _profileImage!) // If a local file is selected + // : _avatarUrl.isNotEmpty + // ? NetworkImage(_avatarUrl) // Load from URL + // : AssetImage( + // "assets/edit_profile/profile.png") + // as ImageProvider, + // + // //backgroundImage: NetworkImage(_avatarUrl) as ImageProvider, + // + // child: + // Align( + // alignment: Alignment.bottomRight, + // child: GestureDetector( + // onTap: _pickImage, // Call `_pickImage` on tap + // child: CircleAvatar( + // radius: 15, + // backgroundColor: Colors.white, + // child: Icon( + // Icons.camera_alt, + // size: 15, + // color: Colors.grey, + // ), + // ), + // ), + // ), + // ), + + // Stack( + // alignment: Alignment.center, + // children: [ + // // FutureBuilder to load the image + // FutureBuilder( + // future: _loadProfileImage(), + // builder: (context, snapshot) { + // if (snapshot.connectionState == ConnectionState.waiting) { + // // While the image is loading, show a progress indicator + // return CircleAvatar( + // radius: 50, + // child: CircularProgressIndicator(), + // ); + // } else if (snapshot.hasError || snapshot.data == null) { + // // If there's an error or no image, show an error icon + // return CircleAvatar( + // radius: 50, + // child: CircularProgressIndicator(), + // ); + // } else { + // // Display the loaded image + // return CircleAvatar( + // radius: 50, + // backgroundImage: snapshot.data, + // child: Align( + // alignment: Alignment.bottomRight, + // child: GestureDetector( + // onTap: _pickImage, + // child: CircleAvatar( + // radius: 15, + // backgroundColor: Colors.white, + // child: Icon( + // Icons.camera_alt, + // size: 15, + // color: Colors.grey, + // ), + // ), + // ), + // ), + // ); + // } + // }, + // ), + // ], + // ), + + Stack( + alignment: Alignment.center, + children: [ + CircleAvatar( + radius: 50, + backgroundImage: _profileImage != null + ? FileImage( + _profileImage!) // If a local file is selected + : _avatarUrl.isNotEmpty + ? NetworkImage( + _avatarUrl) // Load from URL + : AssetImage( + 'assets/edit_profile/profile.png') + as ImageProvider, + child: _avatarUrl.isNotEmpty + ? FutureBuilder( + future: _loadImage(_avatarUrl), + builder: (context, snapshot) { + if (snapshot + .connectionState == + ConnectionState.waiting) { + return Center( + child: + CircularProgressIndicator(), + ); + } else if (snapshot + .hasError) { + return Center( + child: Icon(Icons.error), + ); + } else { + return Align( + alignment: + Alignment.bottomRight, + child: GestureDetector( + onTap: + _pickImage, // Call `_pickImage` on tap + child: CircleAvatar( + radius: 15, + backgroundColor: + Colors.white, + child: Icon( + Icons.camera_alt, + size: 15, + color: Colors.grey, + ), + ), ), + ); + } + }, + ) + : Align( + alignment: + Alignment.bottomRight, + child: GestureDetector( + onTap: + _pickImage, // Call `_pickImage` on tap + child: CircleAvatar( + radius: 15, + backgroundColor: + Colors.white, + child: Icon( + Icons.camera_alt, + size: 15, + color: Colors.grey, ), ), - ); - } - }, - ) - : Align( - alignment: Alignment.bottomRight, - child: GestureDetector( - onTap: - _pickImage, // Call `_pickImage` on tap - child: CircleAvatar( - radius: 15, - backgroundColor: Colors.white, - child: Icon( - Icons.camera_alt, - size: 15, - color: Colors.grey, ), ), + ), + if (_isLoading) + Positioned( + child: CircularProgressIndicator( + strokeWidth: 2, + valueColor: + AlwaysStoppedAnimation( + Colors.grey, ), ), + ), + ], ), - if (_isLoading) - Positioned( - child: CircularProgressIndicator( - strokeWidth: 2, - valueColor: - AlwaysStoppedAnimation( - Colors.grey, + + SizedBox(height: 20), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)! + .register_name, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.grey, ), ), - ), - ], - ), - - SizedBox(height: 20), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.register_name, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.grey, - ), + ], ), - ], - ), - SizedBox(height: 10), - TextFormField( - controller: _usernameController, - focusNode: _focusNodes[0], - decoration: InputDecoration( - // hintText: _showHints[0] ? 'Mohammad Hassan' : null, - hintStyle: TextStyle(color: Colors.grey), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - enabled: false, - ), - ), - SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.email_id, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.grey, - ), - ), - ], - ), - SizedBox(height: 10), - TextFormField( - controller: _emailController, - focusNode: _focusNodes[1], - decoration: InputDecoration( - // hintText: _showHints[1]? 'mohammad.hassan@fcsc.gov.ae': null, - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - enabled: false, - ), - ), - SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.full_name, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.grey, - ), - ), - ], - ), - SizedBox(height: 10), - TextFormField( - enabled: false, - validator: (value) { - if (value == null || value.isEmpty) { - return 'Required'; - } - - //RegExp(r"^[a-zA-Z\s]+$"); - final nameRegex = RegExp( - r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF\s]+$", - ); - if (!nameRegex.hasMatch(value)) { - return 'Invalid Characters'; - } - return null; - }, - controller: _fullNameController, - focusNode: _focusNodes[2], - decoration: InputDecoration( - // hintText: _showHints[2] ? 'Mohammad' : null, - hintStyle: TextStyle(color: Colors.grey), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - // counterText: '', - enabled: !_isProfileCompleted, - ), - maxLength: - 40, // Set the maximum length to 20 characters - maxLengthEnforcement: - MaxLengthEnforcement.enforced, - ), - SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.dob, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - color: Colors.grey, - ), - ), - ], - ), - SizedBox(height: 10), - TextFormField( - controller: _dateController, - focusNode: _focusNodes[3], - decoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - // hintText: _showHints[3] ? 'Select your Date of Birth' : null, - hintStyle: TextStyle(color: Colors.grey), - suffixIcon: Container( - width: 45, - padding: EdgeInsets.only(right: 1), - alignment: Alignment - .center, // Center the icon vertically - child: Icon( - Icons.keyboard_arrow_down_sharp, - color: Colors.grey, - ), - ), - enabled: !_isProfileCompleted, - ), - readOnly: true, - onTap: _pickDate, - validator: _validateDob, - ), - SizedBox(height: 10), - Row( - mainAxisAlignment: MainAxisAlignment.start, - children: [ - Text( - AppLocalizations.of(context)!.region, - style: TextStyle( - fontSize: 16, - fontWeight: FontWeight.w500, - ), - ), - ], - ), - SizedBox(height: 10), - MouseRegion( - onEnter: (_) => - setState(() => _isHoveringDropdown = true), - onExit: (_) => - setState(() => _isHoveringDropdown = false), - child: DropdownButtonFormField( - value: _selectedCountry, - decoration: InputDecoration( - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(8), - ), - labelText: 'Select', - ), - icon: Icon(Icons.keyboard_arrow_down_sharp, - color: _isHoveringDropdown - ? Colors.black - : Colors.grey), - items: _countries - .map( - (item) => DropdownMenuItem( - value: item, - child: Text(item), + SizedBox(height: 10), + TextFormField( + controller: _usernameController, + focusNode: _focusNodes[0], + decoration: InputDecoration( + // hintText: _showHints[0] ? 'Mohammad Hassan' : null, + hintStyle: TextStyle(color: Colors.grey), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), ), - ) - .toList(), - onChanged: (String? newValue) { - setState(() { - _selectedCountry = newValue; - }); - }, - validator: _validateDropdown, - ), - ), - SizedBox(height: 20), - if (!_isProfileCompleted) // Conditional rendering - Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Row( + enabled: false, + ), + ), + SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.email_id, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.grey, + ), + ), + ], + ), + SizedBox(height: 10), + TextFormField( + controller: _emailController, + focusNode: _focusNodes[1], + decoration: InputDecoration( + // hintText: _showHints[1]? 'mohammad.hassan@fcsc.gov.ae': null, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + enabled: false, + ), + ), + SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.full_name, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.grey, + ), + ), + ], + ), + SizedBox(height: 10), + TextFormField( + enabled: false, + validator: (value) { + if (value == null || value.isEmpty) { + return 'Required'; + } + + //RegExp(r"^[a-zA-Z\s]+$"); + final nameRegex = RegExp( + r"^[a-zA-Z0-9'\-\u0627\u0639~\u00C0-\u00FF\s]+$", + ); + if (!nameRegex.hasMatch(value)) { + return 'Invalid Characters'; + } + return null; + }, + controller: _fullNameController, + focusNode: _focusNodes[2], + decoration: InputDecoration( + // hintText: _showHints[2] ? 'Mohammad' : null, + hintStyle: TextStyle(color: Colors.grey), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + // counterText: '', + enabled: !_isProfileCompleted, + ), + maxLength: + 40, // Set the maximum length to 20 characters + maxLengthEnforcement: + MaxLengthEnforcement.enforced, + ), + SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.dob, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + color: Colors.grey, + ), + ), + ], + ), + SizedBox(height: 10), + TextFormField( + controller: _dateController, + focusNode: _focusNodes[3], + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + ), + // hintText: _showHints[3] ? 'Select your Date of Birth' : null, + hintStyle: TextStyle(color: Colors.grey), + suffixIcon: Container( + width: 45, + padding: EdgeInsets.only(right: 1), + alignment: Alignment + .center, // Center the icon vertically + child: Icon( + Icons.keyboard_arrow_down_sharp, + color: Colors.grey, + ), + ), + enabled: !_isProfileCompleted, + ), + readOnly: true, + onTap: _pickDate, + validator: _validateDob, + ), + SizedBox(height: 10), + Row( + mainAxisAlignment: MainAxisAlignment.start, + children: [ + Text( + AppLocalizations.of(context)!.region, + style: TextStyle( + fontSize: 16, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + SizedBox(height: 10), + MouseRegion( + onEnter: (_) => setState( + () => _isHoveringDropdown = true), + onExit: (_) => setState( + () => _isHoveringDropdown = false), + child: DropdownButtonFormField( + value: _selectedCountry, + decoration: InputDecoration( + border: OutlineInputBorder( + borderRadius: + BorderRadius.circular(8), + ), + labelText: 'Select', + ), + icon: Icon( + Icons.keyboard_arrow_down_sharp, + color: _isHoveringDropdown + ? Colors.black + : Colors.grey), + items: _countries + .map( + (item) => DropdownMenuItem( + value: item, + child: Text(item), + ), + ) + .toList(), + onChanged: (String? newValue) { + setState(() { + _selectedCountry = newValue; + }); + }, + validator: _validateDropdown, + ), + ), + SizedBox(height: 20), + if (!_isProfileCompleted) // Conditional rendering + Column( + crossAxisAlignment: + CrossAxisAlignment.start, children: [ - Checkbox( - value: isChecked, - onChanged: (value) { - setState(() { - isChecked = value ?? false; - showError = false; - }); - }, - side: BorderSide( - color: showError - ? Colors.red - : Colors.grey, - width: 1.5, - ), + Row( + children: [ + Checkbox( + value: isChecked, + onChanged: (value) { + setState(() { + isChecked = value ?? false; + showError = false; + }); + }, + side: BorderSide( + color: showError + ? Colors.red + : Colors.grey, + width: 1.5, + ), + ), + Expanded( + child: Column( + mainAxisAlignment: + MainAxisAlignment.start, + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + SizedBox(height: 10), + Text.rich( + TextSpan( + text: AppLocalizations.of( + context)! + .agree, + style: TextStyle( + color: Colors.black), + children: [ + TextSpan( + text: AppLocalizations + .of( + context, + )! + .terms_conditions, + style: TextStyle( + // color: Colors.blue, + color: Color( + 0xFF648CBA), + decoration: + TextDecoration + .underline, + ), + recognizer: + TapGestureRecognizer() + ..onTap = () { + // Add action for Terms & Conditions tap + }, + ), + TextSpan( + text: AppLocalizations + .of( + context, + )! + .t_and, + style: TextStyle( + color: Colors.black, + ), + ), + TextSpan( + text: AppLocalizations + .of( + context, + )! + .privacy_policy, + style: TextStyle( + // color: Colors.blue, + color: Color( + 0xFF648CBA), + decoration: + TextDecoration + .underline, + ), + recognizer: + TapGestureRecognizer() + ..onTap = () { + // Add action for Privacy Policy tap + }, + ), + TextSpan( + text: AppLocalizations + .of( + context, + )! + .conditions, + style: TextStyle( + color: Colors.black, + ), + ), + ], + ), + textAlign: TextAlign.start, + maxLines: 2, + overflow: + TextOverflow.visible, + softWrap: true, + ), + ], + ), + ), + ], ), - Expanded( - child: Column( + if (showError) + Row( mainAxisAlignment: MainAxisAlignment.start, - crossAxisAlignment: - CrossAxisAlignment.start, children: [ - SizedBox(height: 10), - Text.rich( - TextSpan( - text: AppLocalizations.of( - context)! - .agree, + Padding( + padding: const EdgeInsets.only( + left: 10.0), + child: Text( + 'Please agree to terms and conditions', style: TextStyle( - color: Colors.black), - children: [ - TextSpan( - text: AppLocalizations.of( - context, - )! - .terms_conditions, - style: TextStyle( - // color: Colors.blue, - color: - Color(0xFF648CBA), - decoration: - TextDecoration - .underline, - ), - recognizer: - TapGestureRecognizer() - ..onTap = () { - // Add action for Terms & Conditions tap - }, - ), - TextSpan( - text: AppLocalizations.of( - context, - )! - .t_and, - style: TextStyle( - color: Colors.black, - ), - ), - TextSpan( - text: AppLocalizations.of( - context, - )! - .privacy_policy, - style: TextStyle( - // color: Colors.blue, - color: Color(0xFF648CBA), - decoration: - TextDecoration - .underline, - ), - recognizer: - TapGestureRecognizer() - ..onTap = () { - // Add action for Privacy Policy tap - }, - ), - TextSpan( - text: AppLocalizations.of( - context, - )! - .conditions, - style: TextStyle( - color: Colors.black, - ), - ), - ], + color: Colors.red[700], + fontSize: 12, + ), ), - textAlign: TextAlign.start, - maxLines: 2, - overflow: TextOverflow.visible, - softWrap: true, ), ], ), + ], + ), + SizedBox(height: 20), + Center( + child: GestureDetector( + onTap: () { + final email = _emailController.text; + context.go( + '/createNewPw/$userId/$email?key=editProfile'); + }, + child: Text( + AppLocalizations.of(context)! + .change_password, + style: TextStyle( + color: Color(0xFF648CBA), + fontSize: 14, + fontWeight: FontWeight.w700, + fontFamily: 'Roboto', + // decoration: TextDecoration.underline + ), + ), + ), + ), + SizedBox(height: 20), + // ElevatedButton.icon( + // onPressed: () { + // showConfirmationDialog(context); + // }, + // icon: Icon( + // Icons.save, + // color: Colors.white, + // ), + // label: Text( + // AppLocalizations.of(context)!.save, + // style: TextStyle(color: Colors.white), + // ), + // style: ElevatedButton.styleFrom( + // backgroundColor: Color(0xFF92722A), + // minimumSize: Size(double.infinity, 50), + // shape: RoundedRectangleBorder( + // borderRadius: BorderRadius.circular(8), + // ), + // ), + // ), + ElevatedButton( + onPressed: () { + // if ((_formKey.currentState?.validate() ?? false) && (isChecked)) { + // _formKey.currentState?.save(); + showConfirmationDialog(context); + // } else { + // setState(() { + // showError = !isChecked; // Show error if the checkbox is not checked + // }); + // } + }, + style: ElevatedButton.styleFrom( + backgroundColor: Color(0xFF92722A), + minimumSize: Size(double.infinity, 50), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment + .center, // Center the content + children: [ + Text( + AppLocalizations.of(context)!.save, + style: TextStyle(color: Colors.white), + ), + SizedBox( + width: + 8), // Add space between text and icon + Image.asset( + MiscIconAssetPath.save, + color: Colors.white, + width: 20, + height: 20, ), ], ), - if (showError) - Row( - mainAxisAlignment: - MainAxisAlignment.start, - children: [ - Padding( - padding: const EdgeInsets.only( - left: 10.0), - child: Text( - 'Please agree to terms and conditions', - style: TextStyle( - color: Colors.red[700], - fontSize: 12, - ), - ), - ), - ], - ), - ], - ), - SizedBox(height: 20), - Center( - child: GestureDetector( - onTap: () { - final email = _emailController.text; - context.go( - '/createNewPw/$userId/$email?key=editProfile'); - }, - child: Text( - AppLocalizations.of(context)! - .change_password, - style: TextStyle( - color: Color(0xFF648CBA), - fontSize: 14, - fontWeight: FontWeight.w700, - fontFamily: 'Roboto', - // decoration: TextDecoration.underline - ), - ), - ), + ) + ], ), - SizedBox(height: 20), - // ElevatedButton.icon( - // onPressed: () { - // showConfirmationDialog(context); - // }, - // icon: Icon( - // Icons.save, - // color: Colors.white, - // ), - // label: Text( - // AppLocalizations.of(context)!.save, - // style: TextStyle(color: Colors.white), - // ), - // style: ElevatedButton.styleFrom( - // backgroundColor: Color(0xFF92722A), - // minimumSize: Size(double.infinity, 50), - // shape: RoundedRectangleBorder( - // borderRadius: BorderRadius.circular(8), - // ), - // ), - // ), - ElevatedButton( - onPressed: () { - // if ((_formKey.currentState?.validate() ?? false) && (isChecked)) { - // _formKey.currentState?.save(); - showConfirmationDialog(context); - // } else { - // setState(() { - // showError = !isChecked; // Show error if the checkbox is not checked - // }); - // } - }, - style: ElevatedButton.styleFrom( - backgroundColor: Color(0xFF92722A), - minimumSize: Size(double.infinity, 50), - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.circular(8), - ), - ), - child: Row( - mainAxisAlignment: MainAxisAlignment.center, // Center the content - children: [ - Text( - AppLocalizations.of(context)!.save, - style: TextStyle(color: Colors.white), - ), - SizedBox(width: 8), // Add space between text and icon - Image.asset( - MiscIconAssetPath.save, - color: Colors.white, - width: 20, - height: 20, - ), - ], - ), - ) - - ], - ), + ), + ), ), - ), + ], ), - ], + ), ), - ), - ), - //bottomNavigationBar: MyBottomNavBar(), - ); + //bottomNavigationBar: MyBottomNavBar(), + )); } } diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart b/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart index 2c701b8a..83beb9bc 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart @@ -8,6 +8,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; +import 'package:uae_stat/infrastructure/services/img_asset_paths/feedback_asset_path.dart'; + import 'package:uae_stat/infrastructure/services/packages/go_router.dart'; import 'package:uae_stat/presentation/components/my_drawer.dart'; import 'package:mailer/mailer.dart'; @@ -28,7 +30,7 @@ class FeedbackForm extends StatefulWidget { class _FeedbackFormState extends State with WidgetsBindingObserver { final _pb = - PocketBase('https://pb.venbait.in'); // Initialize PocketBase client + PocketBase('https://pb.venbait.in'); // Initialize PocketBase client // final _pb = // PocketBase('http://127.0.0.1:8090'); // Initialize PocketBase client @@ -46,32 +48,55 @@ class _FeedbackFormState extends State dynamic userId; List> get _emojiOptions => [ - { - "icon": Icons.sentiment_very_dissatisfied, - "label": context.translate("Terrible", "سئ جدا"), // Translate here - "value": 1, - }, - { - "icon": Icons.sentiment_dissatisfied, - "label": context.translate("Bad", "سيء"), // Translate here - "value": 2, - }, - { - "icon": Icons.sentiment_neutral, - "label": context.translate("Okay", "مقبول"), // Translate here - "value": 3, - }, - { - "icon": Icons.sentiment_satisfied, - "label": context.translate("Good", "جيد"), // Translate here - "value": 4, - }, - { - "icon": Icons.sentiment_very_satisfied, - "label": context.translate("Amazing", "مذهل"), // Translate here - "value": 5, - }, - ]; + { + // "icon": Icons.emoji_emotions_rounded, + 'icon': Image.asset( + FeedBackAssetPath.disappointedfb, + width: 25, + height: 25, + ), + "label": context.translate("Terrible", "سئ جدا"), // Translate here + "value": 1, + }, + { + // "icon": Icons.sentiment_dissatisfied, + 'icon': Image.asset( + FeedBackAssetPath.frowningfb, + width: 25, + height: 25, + ), + "label": context.translate("Bad", "سيء"), // Translate here + "value": 2, + }, + { + 'icon': Image.asset( + FeedBackAssetPath.neutralfb, + width: 25, + height: 25, + ), + "label": context.translate("Okay", "مقبول"), // Translate here + "value": 3, + }, + { + 'icon': Image.asset( + FeedBackAssetPath.smilingfb, + width: 25, + height: 25, + ), + "label": context.translate("Good", "جيد"), // Translate here + "value": 4, + }, + { + // "icon": Icons.sentiment_very_satisfied, + 'icon': Image.asset( + FeedBackAssetPath.smilingFacefb, + width: 25, + height: 25, + ), + "label": context.translate("Amazing", "مذهل"), // Translate here + "value": 5, + }, + ]; static const int _characterLimit = 1200; final RegExp _allowedCharacters = RegExp(r'^[a-zA-Z0-9 .,!?-]*$'); @@ -208,38 +233,54 @@ class _FeedbackFormState extends State @override Widget build(BuildContext context) { - return BaseScaffold( - // title: Text("Feedback"), - title: Text(AppLocalizations.of(context)!.feedback_title), - // appBar: AppBar( - // backgroundColor: const Color(0xFFf8f9ff), - // title: Text(AppLocalizations.of(context)!.feedback_title), - // actions: [ - // Align( - // alignment: AlignmentDirectional.topEnd, - // child: LangToggle( - // onSaveFeedback: _saveFeedbackText, - // onLoadFeedback: _loadFeedbackText, - // selectedEmojiIndex: _selectedEmojiIndex ?? 0, - // easeOfUseRating: _easeOfUseRating, - // qualityRating: _qualityRating, - // designRating: _designRating, - // redundancyRating: _redundancyRating, - // ), - // ), - // ], - // ), - body: Padding( - padding: const EdgeInsets.all(16.0), - child: SingleChildScrollView( - child: _isFeedbackSubmitted - ? _buildThankYouMessage() - : _isFeedbackFailed - ? _buildFailureMessage() - : _buildFeedbackForm(), - ), - ), - ); + // final uri = Uri.parse(GoRouterState.of(context).uri.toString()); + // final userName = uri.queryParameters['userName'] ?? 'Guest User'; + + final userName = GoRouterState.of(context).extra as String? ?? 'Guest User'; + return PopScope( + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + context.go('/myhomepage'); + }, + child: BaseScaffold( + // title: Text("Feedback"), + title: Text( + AppLocalizations.of(context)!.feedback_title, + style: TextStyle( + fontSize: 24, + fontFamily: 'Roboto', + fontWeight: FontWeight.w500), + ), + // appBar: AppBar( + // backgroundColor: const Color(0xFFf8f9ff), + // title: Text(AppLocalizations.of(context)!.feedback_title), + // actions: [ + // Align( + // alignment: AlignmentDirectional.topEnd, + // child: LangToggle( + // onSaveFeedback: _saveFeedbackText, + // onLoadFeedback: _loadFeedbackText, + // selectedEmojiIndex: _selectedEmojiIndex ?? 0, + // easeOfUseRating: _easeOfUseRating, + // qualityRating: _qualityRating, + // designRating: _designRating, + // redundancyRating: _redundancyRating, + // ), + // ), + // ], + // ), + body: Padding( + padding: const EdgeInsets.only( + top: 8.0, bottom: 16.0, left: 23.0, right: 23.0), + child: SingleChildScrollView( + child: _isFeedbackSubmitted + ? _buildThankYouMessage(userName) + : _isFeedbackFailed + ? _buildFailureMessage() + : _buildFeedbackForm(), + ), + ), + )); } Widget _buildFeedbackForm() { @@ -260,26 +301,34 @@ class _FeedbackFormState extends State textAlign: TextAlign.center, ), const SizedBox(height: 20), - Text( - context.translate('How was your experience with us today?', - 'كيف كانت تجربتك معنا اليوم؟'), - style: const TextStyle( - fontSize: 18, - fontFamily: 'Roboto', - fontWeight: FontWeight.w400, - color: Color(0xFF898C81), + Center( + child: FittedBox( + fit: BoxFit + .scaleDown, // This will make the text smaller to fit within the available space + child: Text( + context.translate('How was your experience with us today?', + 'كيف كانت تجربتك معنا اليوم؟'), + style: const TextStyle( + fontSize: 18, + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + color: Color(0xff898C81), + ), + ), ), ), - const SizedBox(height: 10), + const SizedBox(height: 15), Container( + width: double.infinity, decoration: BoxDecoration( border: Border.all( - color: _isSmileySelected ? Colors.transparent : Colors.red, + color: + _isSmileySelected ? Colors.transparent : Colors.transparent, width: 1.5, ), borderRadius: BorderRadius.circular(8), ), - padding: const EdgeInsets.all(8), + padding: const EdgeInsets.all(0.0), child: Column( children: [ Row( @@ -287,6 +336,8 @@ class _FeedbackFormState extends State children: List.generate(_emojiOptions.length, (index) { return _buildEmojiButton( icon: _emojiOptions[index]["icon"], + + // icon: _emojiOptions[index]["icon"], label: _emojiOptions[index]["label"], index: index, ); @@ -300,28 +351,31 @@ class _FeedbackFormState extends State 'Please rate your experience before submitting your feedback.', 'يرجى تقييم تجربتك قبل تقديم ملاحظاتك.', ), - style: TextStyle(color: Colors.red, fontSize: 14), + style: TextStyle(color: Color(0xFFD83731), fontSize: 14), ), ), ], ), ), - const SizedBox(height: 30), - Text( - context.translate('How good did we do in these aspects?', - 'ما مدى جودة أدائنا في هذه الجوانب؟'), - style: const TextStyle( - fontSize: 18, - fontFamily: 'Roboto', - fontWeight: FontWeight.w400, - color: Color(0xFF898C81), - ), - ), - const SizedBox(height: 20), + const SizedBox(height: 15), + FittedBox( + fit: BoxFit + .scaleDown, // This will make the text smaller to fit within the available space + child: Text( + context.translate('How good did we do in these aspects?', + 'ما مدى جودة أدائنا في هذه الجوانب؟'), + style: const TextStyle( + fontSize: 18, + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + color: Color(0xFF898C81), + ), + )), + const SizedBox(height: 15), _buildRatingRow( context.translate('Ease of use', 'سهولة الاستخدام'), _easeOfUseRating, - (rating) { + (rating) { setState(() { _easeOfUseRating = rating; }); @@ -330,7 +384,7 @@ class _FeedbackFormState extends State _buildRatingRow( context.translate('Quality', 'الجودة'), _qualityRating, - (rating) { + (rating) { setState(() { _qualityRating = rating; }); @@ -339,7 +393,7 @@ class _FeedbackFormState extends State _buildRatingRow( context.translate('Design', 'التصميم'), _designRating, - (rating) { + (rating) { setState(() { _designRating = rating; }); @@ -348,7 +402,7 @@ class _FeedbackFormState extends State _buildRatingRow( context.translate('Redundant', 'مكرر'), _redundancyRating, - (rating) { + (rating) { setState(() { _redundancyRating = rating; }); @@ -360,23 +414,43 @@ class _FeedbackFormState extends State minLines: 5, // Start with 5 lines maxLines: null, // Allows the field to expand automatically maxLength: _characterLimit, + style: TextStyle(color: Color(0xFF898C81)), decoration: InputDecoration( hintText: context.translate( 'Tell us how we can improve', 'أخبرنا كيف يمكننا التحسين'), + hintStyle: TextStyle(color: Color(0xFF898C81)), border: OutlineInputBorder( - borderSide: BorderSide( - color: _hasError ? Colors.red : Color(0xFF7296BE), - ), + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide(color: Color(0xFF7296BE), width: 1), ), + + // Border when the TextField is enabled but not focused + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide(color: Color(0xFF7296BE), width: 1), + ), + + // Border when there is an error + errorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide(color: Color(0xFFD83731), width: 1), + ), + + // Border when focused and there is an error + focusedErrorBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(10.0), + borderSide: BorderSide(color: Color(0xFFD83731), width: 1), + ), + errorText: - _hasError ? _errorMessage : null, // Show error below field + _hasError ? _errorMessage : null, // Show error below field ), onChanged: (text) { // Trigger re-validation and character limit on each change _handleTextChange(); }, ), - const SizedBox(height: 20), + const SizedBox(height: 15), Center( child: ElevatedButton( onPressed: _submitFeedback, @@ -416,7 +490,10 @@ class _FeedbackFormState extends State ), ), 6.horizontalSpace, - const Icon(Icons.chevron_right_outlined), + const Icon( + Icons.chevron_right_outlined, + color: Colors.white, + ), ], ), ), @@ -425,30 +502,66 @@ class _FeedbackFormState extends State ); } - Widget _buildThankYouMessage() { + Widget _buildThankYouMessage(String userName) { + double screenHeight = MediaQuery.of(context).size.height; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(Icons.thumb_up, size: 80, color: Color(0xFF7DAFBC)), + SizedBox(height: screenHeight / 5), + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Color(0xFFF9F9F9), // Circle background color + shape: BoxShape.circle, // Make it a circle + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.2), + blurRadius: 5, + spreadRadius: 2, + offset: Offset(0, 3), // Shadow position + ), + ], + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + FeedBackAssetPath.thumbfb, + width: 40, + height: 40, + ) + // Icon( + // Icons.thumb, + // size: 80, + // color: Color(0xFF7DAFBC), // Icon color + // ), + // const SizedBox(height: 20), + ], + ), + ), + + // Icon(Icons.thumb_up, size: 80, color: Color(0xFF7DAFBC)), const SizedBox(height: 20), Text( - "Thank You", + // "Thank you", + + 'Thank you $userName !', style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), ), - const SizedBox(height: 10), + const SizedBox(height: 15), const Text( - "For your valuable feedback, we truly appreciate your input!", - style: TextStyle(fontSize: 16), + "For your valuable feedback, we truly \n appreciate your input!", + style: TextStyle(fontSize: 16, color: Color(0xFF898C81)), textAlign: TextAlign.center, ), - const SizedBox(height: 30), - ElevatedButton( - onPressed: () => context.go('/myhomepage'), - //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), - child: const Text("Go to Home"), - ), + // const SizedBox(height: 30), + // ElevatedButton( + // onPressed: () => context.go('/myhomepage'), + // //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), + // child: const Text("Go to Home"), + // ), ], ), ); @@ -456,68 +569,143 @@ class _FeedbackFormState extends State // New widget for failure message Widget _buildFailureMessage() { + double screenHeight = MediaQuery.of(context).size.height; + double screenWidth = MediaQuery.of(context).size.width; return Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center, children: [ - Icon(Icons.error, size: 80, color: Colors.red), + SizedBox(height: screenHeight / 5), + Container( + padding: EdgeInsets.all(20), + decoration: BoxDecoration( + color: Color(0xFFF9F9F9), // Circle background color + shape: BoxShape.circle, // Make it a circle + boxShadow: [ + BoxShadow( + color: Color.fromRGBO(0, 0, 0, 0.2), + blurRadius: 5, + spreadRadius: 2, + offset: Offset(0, 3), // Shadow position + ), + ], + ), + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Image.asset( + FeedBackAssetPath.errorfb, + width: 40, + height: 40, + ), + ])), + + // Icon(Icons.error, size: 80, color: Colors.red), const SizedBox(height: 20), - const Text("Failed to Share Feedback", - style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), + const Text( + "Failed to Share Feedback", + style: TextStyle( + fontSize: 24, + fontWeight: FontWeight.bold, + color: Color(0xFF414042)), + ), const SizedBox(height: 10), Text(AppLocalizations.of(context)!.feedback_failed_msg, - style: const TextStyle(fontSize: 16), + style: const TextStyle(fontSize: 16, color: Color(0xFF898C81)), textAlign: TextAlign.center), - const SizedBox(height: 30), - ElevatedButton( - onPressed: () { - setState(() { - _isFeedbackFailed = false; // Reset failure state - }); - }, - child: const Text("Retry"), - ), + // const SizedBox(height: 30), + // ElevatedButton( + // onPressed: () { + // setState(() { + // _isFeedbackFailed = false; // Reset failure state + // }); + // }, + // child: const Text("Retry"), + // ), ], ), ); } Widget _buildEmojiButton({ - required IconData icon, + // required IconData icon, + required Widget icon, required String label, required int index, }) { bool isSelected = _selectedEmojiIndex == index; - - return Column( - children: [ - IconButton( - icon: Icon(icon, size: 40), - color: isSelected ? Colors.green : Colors.amber, - onPressed: () { - setState(() { - _selectedEmojiIndex = index; - _isSmileySelected = true; // Hide error when a smiley is selected - }); - }, - ), - Text( - label, - style: TextStyle( - fontWeight: FontWeight.w400, - color: isSelected ? Colors.green : Color(0xFF000000), + return GestureDetector( + onTap: () { + setState(() { + _selectedEmojiIndex = index; + _isSmileySelected = true; // Hide error when a smiley is selected + }); + }, + child: Container( + padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8), + decoration: BoxDecoration( + border: Border.all( + color: isSelected ? Color(0xFF8E8E8E) : Colors.transparent, + width: 2, ), + borderRadius: BorderRadius.circular(12), // Rounded corners ), - ], + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + icon, // Assuming `icon` is an Icon widget + SizedBox(height: 3), + + FittedBox( + fit: BoxFit + .scaleDown, // This will make the text smaller to fit within the available space + child: Text( + label, + style: TextStyle( + fontFamily: 'Roboto', + fontWeight: FontWeight.w400, + fontSize: 14, + color: Colors.black, + // color: isSelected ? Colors.green : Colors.black, + ), + ), + ), + ], + ), + ), ); + + // return Column( + // children: [ + // + // IconButton( + // // icon: Icon(icon, size: 40), + // icon: icon, + // color: isSelected ? Colors.green : Colors.amber, + // onPressed: () { + // setState(() { + // _selectedEmojiIndex = index; + // _isSmileySelected = true; // Hide error when a smiley is selected + // }); + // }, + // ), + // Text( + // label, + // style: TextStyle( + // fontWeight: FontWeight.w400, + // color: isSelected ? Colors.green : Color(0xFF000000), + // ), + // ), + // ], + // ); } Widget _buildRatingRow( - String label, - double rating, - Function(double) onRatingUpdate, - ) { + String label, + double rating, + Function(double) onRatingUpdate, + ) { return Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -535,10 +723,14 @@ class _FeedbackFormState extends State allowHalfRating: true, itemCount: 5, itemSize: 30, - itemBuilder: (context, _) => const Icon( - Icons.star, + itemBuilder: (context, index) => Icon( + index < rating ? Icons.star : Icons.star_border, color: Colors.amber, ), + // itemBuilder: (context, _) => const Icon( + // Icons.star, + // color: Colors.amber, + // ), onRatingUpdate: onRatingUpdate, unratedColor: Color(0xFF8E8E8E), ), @@ -573,7 +765,7 @@ class _FeedbackFormState extends State "design": _designRating, "redundancy": _redundancyRating, "emoji_rating": _emojiOptions[_selectedEmojiIndex!] - ["label"], // Emoji rating + ["label"], // Emoji rating "feedback": _feedbackController.text, }; @@ -783,7 +975,7 @@ class LangToggle extends ConsumerWidget { ref.read(preferencesUseCaseProvider.notifier).updatePreferences( (prefs) => prefs.copyWith(language: languageAfter), - ); + ); await onLoadFeedback(); // Reload feedback text after toggling language }, diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart b/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart index 2406f9a8..37655d7c 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart @@ -1,4 +1,5 @@ import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart'; @@ -224,135 +225,148 @@ class _ManageUserRouterState extends State { @override Widget build(BuildContext context) { - final Map statusOptions = { 'Approved': AppLocalizations.of(context)!.approved, 'Denied': AppLocalizations.of(context)!.denied, 'Pending': AppLocalizations.of(context)!.pending, }; - double myheight = MediaQuery.of(context).size.height; - return BaseScaffold( - // title: Text("Manage User"), - title: Text( - AppLocalizations.of(context)!.manage_user, - ), - body: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 3.0), - child: Column( - children: [ - TextField( - decoration: InputDecoration( - prefixIcon: const Icon(Icons.search), - hintText: 'Search', - border: OutlineInputBorder( - borderRadius: BorderRadius.all(Radius.circular(20)), + + return PopScope( + onPopInvokedWithResult: (didPop, result) { + if (didPop) return; + context.go('/myhomepage'); + }, + child: BaseScaffold( + // title: Text("Manage User"), + title: Text( + AppLocalizations.of(context)!.manage_user, + ), + body: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 3.0), + child: Column( + children: [ + TextField( + decoration: InputDecoration( + prefixIcon: const Icon(Icons.search), + hintText: 'Search', + border: OutlineInputBorder( + borderRadius: BorderRadius.all(Radius.circular(20)), + ), ), + onChanged: filterUsers, ), - onChanged: filterUsers, - ), - SizedBox(height: myheight / 40), - SingleChildScrollView( - scrollDirection: Axis.horizontal, - child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: MediaQuery.of(context).size.width, - ), - child: DataTable( - sortColumnIndex: _sortColumnIndex, - sortAscending: _isAscending, - columns: [ - DataColumn( - label: Text( - AppLocalizations.of(context)!.user_name, + SizedBox(height: myheight / 40), + SingleChildScrollView( + scrollDirection: Axis.horizontal, + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: MediaQuery.of(context).size.width, + ), + child: DataTable( + sortColumnIndex: _sortColumnIndex, + sortAscending: _isAscending, + columns: [ + DataColumn( + label: Text( + AppLocalizations.of(context)!.user_name, + ), + onSort: (columnIndex, ascending) { + _sort((user) => user.userName.toLowerCase(), + columnIndex, ascending); + }, ), - onSort: (columnIndex, ascending) { - _sort((user) => user.userName.toLowerCase(), - columnIndex, ascending); - }, - ), - DataColumn( - label: Text( AppLocalizations.of(context)!.email_id,), - onSort: (columnIndex, ascending) { - _sort((user) => user.emailId.toLowerCase(), - columnIndex, ascending); - }, - ), - DataColumn( - label: Text(AppLocalizations.of(context)!.reg_date,), - onSort: (columnIndex, ascending) { - _sort( - (user) => DateFormat('dd/MM/yyyy') - .parse(user.registrationDate), - columnIndex, - ascending, - ); - }, - ), - DataColumn( - label: Text(AppLocalizations.of(context)!.status,), - onSort: (columnIndex, ascending) { - _sort((user) => user.status.toLowerCase(), - columnIndex, ascending); - }, - ), - ], - rows: filteredUserData.isEmpty - ? [ - DataRow( - cells: List.generate( - 4, // Ensure it matches the number of DataColumns - (index) => DataCell( - index == 0 - ? Text( - 'No results found', - style: TextStyle( - fontStyle: FontStyle.italic), - ) - : const Text( - ''), // Empty cells for other columns - placeholder: true, - ), - ), - ), - ] - : filteredUserData.map((user) { - return DataRow( - cells: [ - DataCell(Text(user.userName)), - DataCell(Text(user.emailId)), - DataCell(Text(user.registrationDate)), - DataCell( - DropdownButton( - value: user.status, - items: statusOptions.entries.map((status) { - return DropdownMenuItem( - value: status.key, - child: Text( - status.value, - style: TextStyle( - color: getStatusColor(status.key),), - ), - ); - }).toList(), - onChanged: (newStatus) { - print(user); - if (newStatus != null) { - _showConfirmationDialog( - user, newStatus); - } - }, + DataColumn( + label: Text( + AppLocalizations.of(context)!.email_id, + ), + onSort: (columnIndex, ascending) { + _sort((user) => user.emailId.toLowerCase(), + columnIndex, ascending); + }, + ), + DataColumn( + label: Text( + AppLocalizations.of(context)!.reg_date, + ), + onSort: (columnIndex, ascending) { + _sort( + (user) => DateFormat('dd/MM/yyyy') + .parse(user.registrationDate), + columnIndex, + ascending, + ); + }, + ), + DataColumn( + label: Text( + AppLocalizations.of(context)!.status, + ), + onSort: (columnIndex, ascending) { + _sort((user) => user.status.toLowerCase(), + columnIndex, ascending); + }, + ), + ], + rows: filteredUserData.isEmpty + ? [ + DataRow( + cells: List.generate( + 4, // Ensure it matches the number of DataColumns + (index) => DataCell( + index == 0 + ? Text( + 'No results found', + style: TextStyle( + fontStyle: FontStyle.italic), + ) + : const Text( + ''), // Empty cells for other columns + placeholder: true, ), ), - ], - ); - }).toList(), + ), + ] + : filteredUserData.map((user) { + return DataRow( + cells: [ + DataCell(Text(user.userName)), + DataCell(Text(user.emailId)), + DataCell(Text(user.registrationDate)), + DataCell( + DropdownButton( + value: user.status, + items: + statusOptions.entries.map((status) { + return DropdownMenuItem( + value: status.key, + child: Text( + status.value, + style: TextStyle( + color: getStatusColor(status.key), + ), + ), + ); + }).toList(), + onChanged: (newStatus) { + print(user); + if (newStatus != null) { + _showConfirmationDialog( + user, newStatus); + } + }, + ), + ), + ], + ); + }).toList(), + ), ), ), - ), - ], + ], + ), ), ), ), 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 new file mode 100755 index 00000000..616912c4 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/AboutFCSC.dart @@ -0,0 +1,96 @@ +import 'package:flutter/material.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, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + bottomColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Getting Started', + style: TextStyle( + fontFamily: 'Roboto', + fontSize: 22, + color: Color(0xFF7DAFBC), + // fontWeight: FontWeight.normal, + fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + width: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: Column(children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'About FCSC', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + fontFamily: 'Roboto', + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/AboutFCSC.png', + fit: BoxFit.contain, + ), + ), + SizedBox( + height: 5, + ), + RichText( + text: TextSpan( + text: 'The ', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: + ' Federal Competitiveness and Statistics Centre (FCSC),', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: + ' in your App is designed to provide registered and approved users with access to accurate and comprehensive statistics about the UAE. The app serves as a centralized platform for exploring key datasets, trends, and insights across various sectors.'), + ], + ), + ), + Spacer(), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ]), + ), + ); + } +} 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 new file mode 100755 index 00000000..82bbfa55 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/AboutTheApp/getStarted.dart @@ -0,0 +1,149 @@ +import 'package:flutter/material.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 + textTheme: TextTheme( + bodyMedium: TextStyle(fontSize: 16, color: Color(0xFF898C81)), + ), + ), + child: BaseScaffold( + showDivider: true, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + bottomColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Getting Started', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + height: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'How to Get Started', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/getStarted.png', + fit: BoxFit.contain, + ), + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + '1. Download the app from the App Store or Google Play Store.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + '2. Log in to unlock advanced features or continue as a guest.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + '3. Log in to unlock advanced features or continue as a guest.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox( + height: MediaQuery.of(context).size.height * 0.1, + ), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ), + ), + ); + } +} 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 new file mode 100755 index 00000000..0fbeba15 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/AppFeatures.dart @@ -0,0 +1,208 @@ +import 'package:flutter/material.dart'; + +import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; +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( + data: ThemeData( + fontFamily: 'Roboto', // Set default font family for this page + textTheme: TextTheme( + bodyMedium: TextStyle(fontSize: 16, color: Color(0xFF898C81)), + ), + ), + child: BaseScaffold( + showDivider: true, + bottomColor: Colors.white, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Key Features', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + width: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'App Features', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/appFeatures.png', + fit: BoxFit.contain, + ), + ), + Text( + '1.Comprehensive Statistics:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 6.0), + child: Icon(Icons.brightness_1, size: 5), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + text: + 'Access detailed datasets across categories such as Economy, Environment, Social, ', + style: TextStyle( + color: Color(0xFF898C81), + fontSize: 16, + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'Economy, Environment, Social, ', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan(text: 'and more.'), + ], + ), + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Explore statistics presented as smart metrics, graphs, and charts for better understanding.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + ' 2. Drilldown Navigation:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Start with high-level categories and drill down to specific KPIs and metrics for deeper insights.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '3. Interactive Visualizations:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'View trends and relationships with interactive graphs and charts, including bar graphs, line charts, and more.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox( + height: 25, + ), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ), + ), + ); + } +} 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 new file mode 100755 index 00000000..0db02f39 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/ChangeMyPassword.dart @@ -0,0 +1,352 @@ +import 'package:flutter/material.dart'; + +import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; +import '../../../custom_drawer_routes.dart'; + +class ChangeMyPassword extends StatelessWidget { + ChangeMyPassword({super.key}); + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 56, + alignment: Alignment.center, + ); + @override + Widget build(BuildContext context) { + return Theme( + data: ThemeData( + fontFamily: 'Roboto', // Set default font family for this page + textTheme: TextTheme( + bodyMedium: TextStyle(fontSize: 16, color: Color(0xFF898C81)), + ), + ), + child: BaseScaffold( + showDivider: true, + bottomColor: Colors.white, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'App Features', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + width: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'How to Change My Password', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/changePassword.png', + fit: BoxFit.contain, + ), + ), + Text( + 'Changing your password helps keep your account secure. Follow these steps to update your password:', + ), + SizedBox(height: 12), + Text( + 'Steps to Change Password', + style: TextStyle( + fontSize: 22, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Text( + '1. Access the Change Password Page:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + text: 'From the Profile page, tap on the ', + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: '"Change Password"', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: ' link at the bottom.', + ) + ], + ), + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '2. Enter Old Password:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon(Icons.brightness_1, size: 5), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Enter your current password in the first field.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '3. Set a New Password:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Enter your new password in the second field.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Re-enter the new password in the third field for confirmation.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '4. Password Requirements:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Your new password must be different from the previously used password.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '5. Save Your Password:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + text: 'Tap the ', + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'Save ', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: 'button', + ) + ], + ), + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'A confirmation message will appear: “Password has been successfully updated.”', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '6. Re-Login:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Log in again using your new password to continue using the app', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox( + height: 25, + ), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ), + ), + ); + } +} 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 new file mode 100755 index 00000000..32d26816 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/EditMyProfile.dart @@ -0,0 +1,484 @@ +import 'package:flutter/material.dart'; + +import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; +import '../../../custom_drawer_routes.dart'; + +class EditMyProfile extends StatelessWidget { + EditMyProfile({super.key}); + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 56, + alignment: Alignment.center, + ); + @override + Widget build(BuildContext context) { + return Theme( + data: ThemeData( + fontFamily: 'Roboto', // Set default font family for this page + textTheme: TextTheme( + bodyMedium: TextStyle(fontSize: 16, color: Color(0xFF898C81)), + ), + ), + child: BaseScaffold( + showDivider: true, + bottomColor: Colors.white, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'App Features', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + width: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'How to Edit My Profile', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/editProfile.png', + fit: BoxFit.contain, + ), + ), + Text( + 'Editing your profile allows you to update specific information while ensuring that critical details remain secure. Follow the steps below to update your profile:', + ), + SizedBox(height: 12), + Text( + 'Steps to Edit Profile', + style: TextStyle( + fontSize: 22, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Text( + '1. Access the Profile Page:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + text: 'Tap on the ', + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: '"Profile"', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: + ' option from the navigation bar at the top left corner of the screen.', + ) + ], + ), + )), + ], + ), + SizedBox(height: 8), + Text( + '2. Editable Fields:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon(Icons.brightness_1, size: 5), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'Full Name:', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: + ' Tap the text box to enter your name (up to 40 alphanumeric characters).', + ) + ], + ), + )), + ], + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon(Icons.brightness_1, size: 5), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'Date of Birth: ', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: + ' Use the calendar dropdown to select your date of birth.', + ) + ], + ), + )), + ], + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon(Icons.brightness_1, size: 5), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'Country/Region: ', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: + ' Choose your current location from the dropdown menu.', + ), + ], + ), + )), + ], + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon(Icons.brightness_1, size: 5), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'User Image: ', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: + 'Tap on the avatar icon to upload or change your profile picture.', + ), + ], + ), + )), + ], + ), + SizedBox(height: 8), + Text( + '3. Non-Editable Fields:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon(Icons.brightness_1, size: 5), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'Username ', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: 'and ', + ), + TextSpan( + text: 'Email Id: ', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: + 'These fields cannot be edited to ensure the integrity of your account.', + ), + ], + ), + )), + ], + ), + SizedBox(height: 8), + Text( + '4. Agree to Terms and Conditions:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Ensure that the checkbox for "I agree to Terms & Conditions and Privacy Policy" is selected before saving changes.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '4. Save Your Changes:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + text: 'Tap the ', + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'Save', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: ' button at the bottom of the screen.', + ) + ], + ), + ), + ), + ], + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'A confirmation dialog will appear with the message: “Are you sure you want to save this page? Once saved, you will not be able to change your name or date of birth.”', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + text: 'Select ', + style: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'Confirm', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: ' to save the changes', + ), + TextSpan( + text: ' Cancel', + style: TextStyle( + fontWeight: FontWeight.w600, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: ' to go back.', + ), + ], + ), + ), + ), + ], + ), + SizedBox( + height: 25, + ), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ), + ), + ); + } +} 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 new file mode 100755 index 00000000..e6ad832c --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/howUseTheApp.dart @@ -0,0 +1,207 @@ +import 'package:flutter/material.dart'; + +import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; +import '../../../custom_drawer_routes.dart'; + +class HowUseTheApp extends StatelessWidget { + HowUseTheApp({super.key}); + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 56, + alignment: Alignment.center, + ); + @override + Widget build(BuildContext context) { + return Theme( + data: ThemeData( + fontFamily: 'Roboto', // Set default font family for this page + textTheme: TextTheme( + bodyMedium: TextStyle(fontSize: 16, color: Color(0xFF898C81)), + ), + ), + child: BaseScaffold( + showDivider: true, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + bottomColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Key Features', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + width: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'How to Use the App', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/howUse.png', + fit: BoxFit.contain, + ), + ), + Text( + '1. Registration and Approval:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Sign up for the app and wait for admin approval.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '2. Login and Navigation:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Once approved, log in to access the app. Navigate through the categories on the home screen.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '3. Access Data:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Drill down into specific categories like "Economy" or "Environment" to view detailed KPIs and visual insights.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox(height: 8), + Text( + '4. Bookmark Metrics:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Drill down into specific categories like "Economy" or "Environment" to view detailed KPIs and visual insights.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox( + height: 25, + ), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ), + ), + ); + } +} 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 new file mode 100755 index 00000000..d61602a3 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/purpose.dart @@ -0,0 +1,166 @@ +import 'package:flutter/material.dart'; + +import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; +import '../../../custom_drawer_routes.dart'; + +class Purpose extends StatelessWidget { + Purpose({super.key}); + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 56, + alignment: Alignment.center, + ); + @override + Widget build(BuildContext context) { + return Theme( + data: ThemeData( + fontFamily: 'Roboto', // Set default font family for this page + textTheme: TextTheme( + bodyMedium: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + ), + ), + ), + child: BaseScaffold( + showDivider: true, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + bottomColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Key Features', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + height: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'Purpose of the App', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/purpose.png', + fit: BoxFit.contain, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: RichText( + text: TextSpan( + text: 'Provide ', + style: TextStyle( + color: Color(0xFF898C81), + fontSize: 16, + fontFamily: 'Roboto'), + children: const [ + TextSpan( + text: 'official statistics ', + style: TextStyle( + fontWeight: FontWeight.bold, + color: Color(0xFF414042), + fontFamily: 'Roboto'), + ), + TextSpan( + text: 'on the UAE in an accessible format.'), + ], + ), + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Support decision-making and research with reliable, up-to-date data.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Enable users to interact with data visually through graphs and metrics.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox( + height: 40, + ), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ), + ), + ); + } +} 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 new file mode 100755 index 00000000..3c2bbe37 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/stayUpdate.dart @@ -0,0 +1,109 @@ +import 'package:flutter/material.dart'; + +import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; +import '../../../custom_drawer_routes.dart'; + +class StayUpdate extends StatelessWidget { + StayUpdate({super.key}); + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 56, + alignment: Alignment.center, + ); + @override + Widget build(BuildContext context) { + return Theme( + data: ThemeData( + fontFamily: 'Roboto', // Set default font family for this page + textTheme: TextTheme( + bodyMedium: TextStyle( + fontSize: 16, + color: Color(0xFF898C81), + ), + ), + ), + child: BaseScaffold( + showDivider: true, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + bottomColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Key Features', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + height: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'Stay Updated', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/stayUpdate.png', + fit: BoxFit.contain, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'The app regularly updates datasets and features to reflect the latest information. Notifications will alertyou about new data or improvements.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox( + height: 150, + ), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ), + ), + ); + } +} 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 new file mode 100755 index 00000000..2b76c420 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/KeyFeatures/useTheApp.dart @@ -0,0 +1,156 @@ +import 'package:flutter/material.dart'; + +import '../../../../../../infrastructure/services/img_asset_paths/banner_asset_path.dart'; +import '../../../custom_drawer_routes.dart'; + +class WhoUseTheApp extends StatelessWidget { + WhoUseTheApp({super.key}); + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 56, + alignment: Alignment.center, + ); + @override + Widget build(BuildContext context) { + return Theme( + data: ThemeData( + fontFamily: 'Roboto', // Set default font family for this page + textTheme: TextTheme( + bodyMedium: TextStyle(fontSize: 16, color: Color(0xFF898C81)), + ), + ), + child: BaseScaffold( + showDivider: true, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + bottomColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Key Features', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + height: double.infinity, + color: Colors.white, + padding: EdgeInsets.all(16), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Align( + alignment: Alignment.topLeft, + child: Text( + 'Who Use the App', + style: TextStyle( + fontSize: 20, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + ), + SizedBox( + width: MediaQuery.of(context).size.width, + height: MediaQuery.of(context).size.height * 0.36, + child: Image.asset( + 'assets/user_guide/whoUse.png', + fit: BoxFit.contain, + ), + ), + Text( + 'This app is intended for:', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w600, + ), + ), + SizedBox(height: 8), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Government officials requiring UAE statistics for decision-making.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Business professionals and researchers analyzing market trends.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Padding( + padding: const EdgeInsets.only(top: 8.0), + child: Icon( + Icons.brightness_1, + size: 5, + color: Color(0xFF414042), + ), + ), // Bullet point + SizedBox(width: 8), // Space between bullet and text + Expanded( + child: Text( + 'Students and educators needing reliable data for study and teaching.', + textAlign: TextAlign.justify, // Align the text + softWrap: true, + ), + ), + ], + ), + SizedBox( + height: 50, + ), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ), + ), + ); + } +} 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 new file mode 100755 index 00000000..70a5c6d4 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/aboutApp.dart @@ -0,0 +1,108 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.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, + bottomColor: Colors.white, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Getting Started', + style: TextStyle( + fontSize: 22, + fontFamily: 'Roboto', + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + width: double.infinity, + color: Colors.white, + child: Column( + children: [ + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/aboutApp/aboutFCSC'); + }, + tileColor: Colors.white, + title: Text( + 'About FCSC', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/aboutApp/getStarted'); + }, + // tileColor: Colors.white, + title: Text( + 'How to Get Started?', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + shape: Border( + bottom: BorderSide( + color: Colors.black, width: 3), // Grey bottom line + ), + ), + ), + Spacer(), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 25, + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/custom_text.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/custom_text.dart deleted file mode 100644 index a20db95f..00000000 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/custom_text.dart +++ /dev/null @@ -1,57 +0,0 @@ -import 'package:flutter/material.dart'; - -class CustomTextRich extends StatelessWidget { - - const CustomTextRich({ - super.key, - required this.textSpans, - this.padding = const EdgeInsets.all(8.0), - this.textAlign = TextAlign.left, - }); - final List textSpans; - final EdgeInsetsGeometry padding; - final TextAlign textAlign; - - @override - Widget build(BuildContext context) { - return SingleChildScrollView( - child :Padding( - padding: padding, - child: Text.rich( - TextSpan(children: textSpans), - textAlign: textAlign, - ), - ), - ); - - - } - - static TextSpan createTextSpan( - String text, { - double? fontSize, - Color color = const Color(0xFF898C81), - FontWeight fontWeight = FontWeight.w500, - double? height, - double defaultFontSize = 14, - TextDecoration textDecoration = TextDecoration.none, - Color? decorationColor, - double spacingTop = 0.0, - double spacingBottom = 0.0, - }) { - String spacedText = (spacingTop > 0.0 || spacingBottom > 0.0) - ? '${'\n' * spacingTop.toInt()}$text${'\n' * spacingBottom.toInt()}' - : text; - return TextSpan( - text: spacedText, - style: TextStyle( - fontSize: fontSize ?? defaultFontSize, - color: color, - fontWeight: fontWeight, - height: height, - decoration: textDecoration, - decorationColor: decorationColor ?? color, - ), - ); - } -} 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 old mode 100644 new mode 100755 index f9aceff7..26fd1f1d --- 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,360 +1,410 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; - -import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; - -import '../../../../components/indicators/locale_provider.dart'; -import '../../../../components/my_toggle.dart'; - -class FAQPage extends StatefulWidget { - const FAQPage({super.key}); - - @override - State createState() => _FAQPageState(); -} - -class _FAQPageState extends State { - @override - Widget build(BuildContext context) { - return Scaffold( - appBar: AppBar( - elevation: 3, - shadowColor: Colors.black, - title: Text('Key Features',), - leading: IconButton( - onPressed: (){ - context.go('/user-guide'); - }, - color: Colors.black, - icon: const Icon(Icons.arrow_back_ios_new),), - actions: [ - Consumer( - builder: (context, ref, _) { - final locale = ref.watch(localeProvider); // Current locale - return MyToggle( - isOn: locale?.languageCode == 'en', - knobTextWhenOn: 'ع', - knobTextWhenOff: 'EN', - pathColorWhenOn: Colors.grey.shade300, - pathColorWhenOff: Colors.grey.shade300, - onTap: () { - ref.read(localeProvider.notifier).toggleLocale(); - }, - ); - }, - ), - ], - - ), - body: SafeArea( - child: Scrollbar( - thumbVisibility: true, - thickness: 6, - radius: Radius.circular(10), - interactive: true, - child:SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container - ( - color: Colors.white, - padding: const EdgeInsets.all(16.0), - width: MediaQuery.of(context).size.width, - child: Text.rich( - TextSpan( - text: 'Here are some common questions about the ', - style: TextStyle( - fontSize: 19, - fontWeight: FontWeight.w600, - color: Colors.grey, - ), - children: [ - TextSpan( - text:' Federal Competitiveness and Statistics Centre (FCSC),', - style: TextStyle( - fontSize: 19, - fontWeight: FontWeight.w600, - color: Colors.black87, - ), - ), - TextSpan( - text: 'mobile application:', - style: TextStyle( - fontSize: 19, - fontWeight: FontWeight.w600, - color: Colors.grey, - ), - ), - ], - ), - ), - ), - Container( - padding: const EdgeInsets.all(0.0), - color: Colors.grey[50], - child: QuestionAnswerScrollView(), - ), - ], - ), - ), - ), - - ), - ); - } - - - -} -class QuestionAnswerScrollView extends StatelessWidget { - const QuestionAnswerScrollView({super.key}); - - - - @override - Widget build(BuildContext context) { - final List> questionsAndAnswers = [ - {'question':'What is the purpose of this app?', 'answer': 'The app provides official UAE statistics across categories like Economy, Environment, and Social. It allows users to explore datasets, view trends, and access detailed metrics to make informed decisions.'}, - {'question':'Do I need to create an account to use the app?', 'answer':RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'Yes, the app is strictly for registered and approved users. To access the data:\n\n', - style: TextStyle(fontWeight: FontWeight.normal, color: Colors.grey), - ), - TextSpan( - text: ' 1. You need to sign up using the Register Now option on the login screen.\n', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: ' 2. Your registration must be approved by the admin.\n', - style: TextStyle(color: Colors.grey), - ), - - 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), - ), - ], - ), - ),}, - {'question':'How can I navigate through the app?','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'}, - {'question':'What types of data are available?', 'answer':RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'The app offers data on:\n\n', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: ' • Economy', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: ' GDP, growth rates, and economic trends\n', - style: TextStyle(color: Colors.grey), - ), - - TextSpan( - text: ' • Environment:', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: ' Electricity production, water consumption, and more.\n', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: ' • Social:', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: ' Labor force distribution, participation rates, and demographic data.\n', - style: TextStyle(color: Colors.grey), - ), - ], - ), - ),}, - {'question':'How do I bookmark a metric?', 'answer': RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'When viewing a metric, tap on the', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: ' Bookmark ', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: 'icon. Your bookmarks are accessible from the', - style: TextStyle(color: Colors.grey), - ), - - TextSpan( - text: 'My Bookmarks', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: 'section in the navigation bar.\n', - style: TextStyle(color: Colors.grey), - ), - ], - ), - ),}, - {'question':'Can I view the app in another language?', 'answer': RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'Yes, the app supports both ', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: 'English ', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: 'and', - style: TextStyle(color: Colors.grey), - ), - - TextSpan( - text: ' Arabic ', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: '. You can toggle the language using the switch in the top-right corner of the app.\n', - style: TextStyle(color: Colors.grey), - ), - ], - ), - ),}, - {'question':'What happens if I forget my password?','answer':'Tap on the Forgot Password? link on the login page. Follow the steps to reset your password via your registered email address.\n'}, - {'question':'Can I edit my profile details?','answer': 'Yes, you can edit specific fields such as Date of Birth and User Image. However, certain fields like Username and Email are non-editable for security reasons.\n'}, - {'question':'How often is the data updated?','answer':'The app updates its datasets regularly to ensure users have access to the latest statistics. Notifications are sent whenever significant updates are made.\n'}, - {'question':'What types of graphs and charts are available?','answer':'The app provides a variety of visualizations, including:\n • Line charts for trends.\n • Bar and column charts for comparisons.\n • Stacked charts for multi-layered data views.\n'}, - {'question':'Can I share the data or charts?','answer':RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'Yes, you can share data or charts directly from the app by tapping the ', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: 'Share ', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: 'button available on most pages.\n', - style: TextStyle(color: Colors.grey), - ), - ], - ), - ),}, - {'question':'What should I do if I encounter an issue?','answer':RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'For technical support or feedback, navigate to the ', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: 'Help ', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: 'section in the app and contact the support team.\n', - style: TextStyle(color: Colors.grey), - ), - ], - ), - ),}, - {'question':'How do I log out of the app?','answer':RichText( - text: TextSpan( - children: [ - TextSpan( - text: 'Go to the ', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: 'Profile ', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: 'section and tap the ', - style: TextStyle(color: Colors.grey), - ), - TextSpan( - text: 'Logout ', - style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), - ), - TextSpan( - text: 'option in the top-right corner.\n', - style: TextStyle(color: Colors.grey), ), - ], - ), - ),}, - ]; - - return SingleChildScrollView( - child: Column( - children: questionsAndAnswers.map((qa) => QuestionAnswerCard(qa: qa)).toList(), - ), - ); - } -} - -class QuestionAnswerCard extends StatefulWidget { // Use dynamic to accommodate RichText - - const QuestionAnswerCard({super.key, required this.qa}); - final Map qa; - - @override - _QuestionAnswerCardState createState() => _QuestionAnswerCardState(); -} - -class _QuestionAnswerCardState extends State { - bool isExpanded = false; - - @override - Widget build(BuildContext context) { - return Card( - color: Colors.grey[50], - elevation: 1, - shape: RoundedRectangleBorder( - borderRadius: BorderRadius.zero, // No rounding, it's a rectangle - ), - margin: EdgeInsets.symmetric(vertical: 0), - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - ListTile( - dense: true, - textColor: Color(0xFF414042), - title: Text( - widget.qa['question']!, - style: TextStyle(fontWeight: FontWeight.w600, fontSize: 15), - ), - trailing: Icon(isExpanded ? Icons.remove : Icons.add), - onTap: () { - setState(() { - isExpanded = !isExpanded; - }); - }, - ), - if (isExpanded) - Padding( - padding: const EdgeInsets.symmetric(horizontal: 16.0), - child: widget.qa['answer'] is RichText - ? widget.qa['answer'] - : Text( - widget.qa['answer'] ?? '', - style: TextStyle(color: Colors.grey), - ), - ), - ], - ), - ); - } -} \ No newline at end of file +import 'package:flutter/material.dart'; + +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; + +class FAQPage extends StatefulWidget { + const FAQPage({super.key}); + + @override + State createState() => _FAQPageState(); +} + +class _FAQPageState extends State { + @override + Widget build(BuildContext context) { + return BaseScaffold( + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + bottomColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + ' FAQs', + style: TextStyle( + fontSize: 22, + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: SafeArea( + child: Container( + height: double.infinity, + color: Colors.white, + child: Scrollbar( + thumbVisibility: true, + thickness: 8, + radius: Radius.circular(10), + interactive: true, + child: SingleChildScrollView( + child: QuestionAnswerScrollView(), + ), + ), + ), + ), + ); + } +} + +class QuestionAnswerScrollView extends StatelessWidget { + const QuestionAnswerScrollView({super.key}); + + @override + Widget build(BuildContext context) { + final List> questionsAndAnswers = [ + { + 'question': 'What is the purpose of this app?', + 'answer': + 'The app provides official UAE statistics across categories like Economy, Environment, and Social. It allows users to explore datasets, view trends, and access detailed metrics to make informed decisions.' + }, + { + 'question': 'Do I need to create an account to use the app?', + 'answer': RichText( + text: TextSpan( + children: [ + TextSpan( + 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'), + ), + 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'), + ), + TextSpan( + text: ' 2. Your registration must be approved by the admin.\n', + style: TextStyle( + 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'), + ), + ], + ), + ), + }, + { + 'question': 'How can I navigate through the app?', + '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' + }, + { + 'question': 'What types of data are available?', + 'answer': RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'The app offers data on:\n\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: ' • Economy', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: ' GDP, growth rates, and economic trends\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: ' • Environment:', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: ' Electricity production, water consumption, and more.\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: ' • Social:', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: + ' Labor force distribution, participation rates, and demographic data.\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + ], + ), + ), + }, + { + 'question': 'How do I bookmark a metric?', + 'answer': RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'When viewing a metric, tap on the', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: ' Bookmark ', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: 'icon. Your bookmarks are accessible from the', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: 'My Bookmarks', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: 'section in the navigation bar.\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + ], + ), + ), + }, + { + 'question': 'Can I view the app in another language?', + 'answer': RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Yes, the app supports both ', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: 'English ', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: 'and', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: ' Arabic ', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: + '. You can toggle the language using the switch in the top-right corner of the app.\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + ], + ), + ), + }, + { + 'question': 'What happens if I forget my password?', + 'answer': + 'Tap on the Forgot Password? link on the login page. Follow the steps to reset your password via your registered email address.\n' + }, + { + 'question': 'Can I edit my profile details?', + 'answer': + 'Yes, you can edit specific fields such as Date of Birth and User Image. However, certain fields like Username and Email are non-editable for security reasons.\n' + }, + { + 'question': 'How often is the data updated?', + 'answer': + 'The app updates its datasets regularly to ensure users have access to the latest statistics. Notifications are sent whenever significant updates are made.\n' + }, + { + 'question': 'What types of graphs and charts are available?', + 'answer': + 'The app provides a variety of visualizations, including:\n • Line charts for trends.\n • Bar and column charts for comparisons.\n • Stacked charts for multi-layered data views.\n' + }, + { + 'question': 'Can I share the data or charts?', + 'answer': RichText( + text: TextSpan( + children: [ + TextSpan( + text: + 'Yes, you can share data or charts directly from the app by tapping the ', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: 'Share ', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: 'button available on most pages.\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + ], + ), + ), + }, + { + 'question': 'What should I do if I encounter an issue?', + 'answer': RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'For technical support or feedback, navigate to the ', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: 'Help ', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: 'section in the app and contact the support team.\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + ], + ), + ), + }, + { + 'question': 'How do I log out of the app?', + 'answer': RichText( + text: TextSpan( + children: [ + TextSpan( + text: 'Go to the ', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: 'Profile ', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: 'section and tap the ', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ), + TextSpan( + text: 'Logout ', + style: TextStyle( + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontSize: 16), + ), + TextSpan( + text: 'option in the top-right corner.\n', + style: TextStyle( + color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'), + ) + ], + ), + ), + }, + ]; + + return SingleChildScrollView( + child: Column( + children: questionsAndAnswers + .map((qa) => QuestionAnswerCard(qa: qa)) + .toList(), + ), + ); + } +} + +class QuestionAnswerCard extends StatefulWidget { + // Use dynamic to accommodate RichText + + const QuestionAnswerCard({super.key, required this.qa}); + final Map qa; + + @override + _QuestionAnswerCardState createState() => _QuestionAnswerCardState(); +} + +class _QuestionAnswerCardState extends State { + bool isExpanded = false; + + @override + Widget build(BuildContext context) { + return Card( + color: Colors.white, + shape: Border( + bottom: BorderSide(width: 0.5, color: Colors.grey.shade300), + ), + margin: EdgeInsets.symmetric( + vertical: 0, + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ListTile( + dense: true, + textColor: Color(0xFF414042), + title: Text( + widget.qa['question']!, + style: TextStyle(fontWeight: FontWeight.w500, fontSize: 16), + ), + trailing: Icon(isExpanded + ? Icons.keyboard_arrow_up + : Icons.keyboard_arrow_down), + onTap: () { + setState(() { + isExpanded = !isExpanded; + }); + }, + ), + if (isExpanded) + Padding( + padding: const EdgeInsets.only( + left: 16, right: 16, bottom: 16, top: 0), + child: widget.qa['answer'] is RichText + ? widget.qa['answer'] + : Text( + widget.qa['answer'] ?? '', + style: TextStyle( + color: Colors.grey, + fontSize: 16, + fontFamily: 'Roboto'), + ), + ), + ], + ), + ); + } +} 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 old mode 100644 new mode 100755 index 0f54ed28..ddb2c774 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/features.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/features.dart @@ -1,595 +1,254 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; -import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; - -import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/custom_text.dart'; - -import '../../../../components/indicators/locale_provider.dart'; -import '../../../../components/my_toggle.dart'; - - - -class UsingFeatures extends StatelessWidget { - const UsingFeatures({super.key}); - - - @override - Widget build(BuildContext context) { - - List textSpans = [ - CustomTextRich.createTextSpan('1.Data-Driven Insights:', - fontSize: 15, - color: Colors.black87, - fontWeight: FontWeight.bold, - height: 2, - ), - CustomTextRich.createTextSpan( - 'Access detailed datasets across categories such as Economy, Environment, Social, ', - fontSize: 13, color:Color(0xFF898C81), - fontWeight: FontWeight.normal , - spacingTop: 1.9,), - - CustomTextRich.createTextSpan( - ' Economy, Environment, Social ', - fontSize: 13, color:Colors.black, - fontWeight: FontWeight.w600 , - ), - CustomTextRich.createTextSpan( - 'and more.Explore statistics presented as smart metrics, graphs, and charts for better understanding.', - fontSize: 13, color:Color(0xFF898C81), - fontWeight: FontWeight.normal , - ), - - CustomTextRich.createTextSpan('\n2.Drilldown Navigation:', fontSize: 15, - color: Colors.black87, - fontWeight: FontWeight.w600, - height: 2 - ), - - CustomTextRich.createTextSpan( - '\nStart with high-level categories and drill down to specific KPIs and metrics for deeper insights.', - fontSize: 13, color:Color(0xFF898C81), - fontWeight: FontWeight.normal , - ), - CustomTextRich.createTextSpan('\n3.Interactive Visualizations:', fontSize: 15, - color: Colors.black87, - fontWeight: FontWeight.w600, - height: 2 - ), - - CustomTextRich.createTextSpan( - '\nStart with high-level categories and drill down to specific KPIs and metrics for deeper insights.', - fontSize: 13, color:Color(0xFF898C81), - fontWeight: FontWeight.normal , - ), - CustomTextRich.createTextSpan( - 'View trends and relationships with interactive graphs and charts, including bar graphs, line charts, and more.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n4.Secure User Access:', - fontSize: 14.0, - color: Colors.black87, - fontWeight: FontWeight.bold, - height: 2, - ), - CustomTextRich.createTextSpan( - '\nAvailable only to registered users whose accounts have been approved by an admin. Login ensures secure access to sensitive statistical information.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n5.Profile Customization:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 2 - ), - CustomTextRich.createTextSpan( - '\nUpdate your profile details, such as name, password, and region, to personalize your experience.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n6.Bookmark:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - ), - CustomTextRich.createTextSpan( - '\nSave frequently accessed metrics and datasets for quick reference via the Bookmarks section.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n7.Bilingual Support:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 2 - ), - CustomTextRich.createTextSpan( - '\nToggle between English and Arabic for ease of use.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\nWho Can Use the App?', - fontSize: 18.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w600, - height: 2.5 - ), - CustomTextRich.createTextSpan( - '\nThis app is intended for:', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n\n • Government officials requiring UAE statistics for decision-making.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n •Business professionals and researchers analyzing market trends.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n •Students and educators needing reliable data for study and teaching.\n\n', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - 'Purpose of the App\n', - fontSize: 16.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w600, - height: 2.0 - ), - CustomTextRich.createTextSpan( - ' • Provide official statistics on the UAE in an accessible format.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n • Support decision-making and research with reliable, up-to-date data.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n • Enable users to interact with data visually through graphs and metrics.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\nHow to Use the App', - fontSize: 18.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w600, - height: 2.3 - ), - CustomTextRich.createTextSpan( - '\n1.Registration and Approval:', - fontSize: 15.0, - color: Colors.black87, - fontWeight: FontWeight.bold, - height: 2.0 - ), - CustomTextRich.createTextSpan( - '\nSign up for the app and wait for admin approval.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n2.Login and Navigation:', - fontSize: 15.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 2.0, - ), - CustomTextRich.createTextSpan( - '\nOnce approved, log in to access the app. Navigate through the categories on the home screen.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n3.Access Data:', - fontSize: 15.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 2.0, - ), - CustomTextRich.createTextSpan( - '\nDrill down into specific categories like "Economy" or "Environment" to view detailed KPIs and visual insights.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n4.Bookmark Metrics:', - fontSize: 15.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 2.0, - ), - CustomTextRich.createTextSpan( - '\nSave important statistics for easy reference.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\nStay Updated', - fontSize: 18.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w600, - height: 3, - ), - CustomTextRich.createTextSpan( - '\nThe app is regularly updated with the latest datasets and features to ensure users have access to the most current information.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\nHow to Change My Password', - fontSize: 18.0, - color: Colors.black87, - fontWeight: FontWeight.w600, - height: 3, - ), - CustomTextRich.createTextSpan( - '\nChanging your password helps keep your account secure. Follow these steps to update your password:\n \n', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - 'Steps to Change Password', - fontSize: 16.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 2.5 - ), - CustomTextRich.createTextSpan( - '\n1.Access the Change Password Page:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 1.5, - ), - CustomTextRich.createTextSpan( - '\nFrom the Profile page, tap on the "Change Password" link at the bottom.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n2.Enter Old Password:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 1.5, - ), - CustomTextRich.createTextSpan( - '\nEnter your current password in the first field.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n3.Set a New Password:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 1.5, - ), - CustomTextRich.createTextSpan( - '\n• Enter your new password in the second field.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n• Re-enter the new password in the third field for confirmation.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n4.Password Requirements:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - ), - CustomTextRich.createTextSpan( - '\nYour new password must be different from the previously used password.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n5.Save Your Password:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - ), - CustomTextRich.createTextSpan( - '\n• Tap the Save button.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n• A confirmation message will appear: “Password has been successfully updated.”', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n6.Re-Login:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - ), - CustomTextRich.createTextSpan( - '\nLog in again using your new password to continue using the app.\n\n', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - 'How to Edit My Profile', - fontSize: 18.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w600, - height: 2.5, - ), - CustomTextRich.createTextSpan( - '\nEditing your profile allows you to update specific information while ensuring that critical details remain secure. Follow the steps below to update your profile:\n', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\nSteps to Edit Profile', - fontSize: 17.0, - color: Color(0xFF414042), - fontWeight: FontWeight.bold, - height: 2, - ), - CustomTextRich.createTextSpan( - '\n 1.Access the Profile Page:', - fontSize: 14.0, - color: Colors.black87, - fontWeight: FontWeight.w600, - height: 2, - ), - CustomTextRich.createTextSpan( - '\nTap on the "Profile" option from the navigation bar at the top left corner of the screen.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n 2. Editable Fields:', - fontSize: 14.0, - color: Colors.black87, - fontWeight: FontWeight.w600, - height: 2, - ), - CustomTextRich.createTextSpan( - '\n • Full Name:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w500, - ), - CustomTextRich.createTextSpan( - ' Tap the text box to enter your name (up to 40 alphanumeric characters).', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n • Date of Birth:', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w500, - ), - CustomTextRich.createTextSpan( - ' Use the calendar dropdown to select your date of birth.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n • Country/Region: ', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w500, - ), - CustomTextRich.createTextSpan( - 'Choose your current location from the dropdown menu.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n •User Image: ', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w500, - ), - CustomTextRich.createTextSpan( - 'Tap on the avatar icon to upload or change your profile picture.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n 3. Non-Editable Fields:', - fontSize: 14.0, - color: Colors.black87, - fontWeight: FontWeight.w600, - height: 2, - ), - CustomTextRich.createTextSpan( - '\nUsername ', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w500, - ), - CustomTextRich.createTextSpan( - 'and ', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - 'Email ID: ', - fontSize: 14.0, - color: Color(0xFF414042), - fontWeight: FontWeight.w500, - ), - CustomTextRich.createTextSpan( - 'These fields cannot be edited to ensure the integrity of your account.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n 4.Agree to Terms and Conditions:', - fontSize: 14.0, - color: Colors.black87, - fontWeight: FontWeight.w600, - height: 2, - ), - - CustomTextRich.createTextSpan( - '\nEnsure that the checkbox for "I agree to Terms & Conditions and Privacy Policy" is selected before saving changes.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n 5. Save Your Changes:', - fontSize: 15.0, - color: Colors.black87, - fontWeight: FontWeight.bold, - height: 2, - ), - CustomTextRich.createTextSpan( - '\n • Tap the Save button at the bottom of the screen.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n • A confirmation dialog will appear with the message:', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '“Are you sure you want to save this page? Once saved, you will not be able to change your name or date of birth.”', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - CustomTextRich.createTextSpan( - '\n • Select Confirm to save the changes or Cancel to go back.', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - - ]; - return - Scaffold( - appBar: AppBar( - elevation: 3, - shadowColor: Colors.black, - title: Text('Key Features',), - leading: IconButton( - onPressed: (){ - context.go('/user-guide'); - }, - color: Colors.black, - icon: const Icon(Icons.arrow_back_ios_new),), - actions: [ - Consumer( - builder: (context, ref, _) { - final locale = ref.watch(localeProvider); // Current locale - return MyToggle( - isOn: locale?.languageCode == 'en', - knobTextWhenOn: 'ع', - knobTextWhenOff: 'EN', - pathColorWhenOn: Colors.grey.shade300, - pathColorWhenOff: Colors.grey.shade300, - onTap: () { - ref.read(localeProvider.notifier).toggleLocale(); - }, - ); - }, - ), - ], - - ), - body:SafeArea( - - child: Scrollbar( - thumbVisibility: true, - thickness: 6, - radius: Radius.circular(10), - interactive: true, - child: SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - color: Colors.white, - padding: const EdgeInsets.all(16.0), - width: MediaQuery.of(context).size.width, - child: Text( - 'FEATURES', - style: TextStyle( - color: Colors.black,// Text color - fontSize: 18, - fontWeight: FontWeight.w500, - ), - ), - ), - Container( - color: Colors.grey[50], // Set the background color here - // child: SingleChildScrollView( - child: CustomTextRich( - textSpans: textSpans, - padding: const EdgeInsets.all(16.0), - textAlign: TextAlign.start, - ), - ), - ], - ), - ) - ), - ), - ); - } -} +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:go_router/go_router.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 UsingFeatures extends StatelessWidget { + const UsingFeatures({super.key}); + + @override + Widget build(BuildContext context) { + final fcscBanner = Image.asset( + BannerAssetPath.fcsc, + height: 56, + alignment: Alignment.center, + ); + return BaseScaffold( + showDivider: true, + dividerColor: Colors.grey[300], + bottomColor: Colors.white, + appbarColor: Colors.white, + mycenterTitle: true, + title: Padding( + padding: EdgeInsets.only(bottom: 8.0), + child: Text( + 'Key Features', + style: TextStyle( + fontSize: 22, + fontFamily: 'Roboto', + color: Color(0xFF7DAFBC), + fontWeight: FontWeight.w500, + // fontWeight: FontWeight.w500, + ), + ), + ), + body: Container( + width: double.infinity, + color: Colors.white, + child: Column( + children: [ + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/features/appFeatures'); + }, + tileColor: Colors.white, + title: Text( + 'App Features', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/features/whoUseApp'); + }, + // tileColor: Colors.white, + title: Text( + 'Who can use The App', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + shape: Border( + bottom: BorderSide( + color: Colors.black, width: 3), // Grey bottom line + ), + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/features/purpose'); + }, + // tileColor: Colors.white, + title: Text( + 'Purpose of the App ?', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + shape: Border( + bottom: BorderSide( + color: Colors.black, width: 3), // Grey bottom line + ), + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/features/howUseApp'); + }, + // tileColor: Colors.white, + title: Text( + 'How to Use the App', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + shape: Border( + bottom: BorderSide( + color: Colors.black, width: 3), // Grey bottom line + ), + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/features/stayUpdated'); + }, + // tileColor: Colors.white, + title: Text( + 'Stay Updated', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + shape: Border( + bottom: BorderSide( + color: Colors.black, width: 3), // Grey bottom line + ), + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/features/changeMyPassword'); + }, + // tileColor: Colors.white, + title: Text( + 'How to Change My Password', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + shape: Border( + bottom: BorderSide( + color: Colors.black, width: 3), // Grey bottom line + ), + ), + ), + Container( + decoration: BoxDecoration( + border: Border( + bottom: BorderSide( + color: Colors.grey.shade300, + width: 0.5), // Grey bottom line + ), + ), + child: ListTile( + onTap: () { + context.push('/user-guide/features/editMyProfile'); + }, + // tileColor: Colors.white, + title: Text( + 'How to Edit My Profile', + style: TextStyle( + fontSize: 16, + color: Color(0xFF414042), + fontWeight: FontWeight.w500, + fontFamily: 'Roboto', + ), + ), + trailing: Icon(Icons.keyboard_arrow_right), + shape: Border( + bottom: BorderSide( + color: Colors.black, width: 3), // Grey bottom line + ), + ), + ), + Spacer(), + Align( + alignment: Alignment.bottomCenter, + child: fcscBanner, + ), + SizedBox( + height: 30, + ), + ], + ), + ), + ); + } +} diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/getting_started.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/getting_started.dart deleted file mode 100644 index a0e575a9..00000000 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/getting_started.dart +++ /dev/null @@ -1,219 +0,0 @@ -import 'package:flutter/gestures.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; - - -import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/custom_text.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'; -import 'package:url_launcher/url_launcher.dart'; - -import '../../../../components/indicators/locale_provider.dart'; -import '../../../../components/my_toggle.dart'; -class GettingStarted extends StatelessWidget { - GettingStarted({super.key}); - - final String url = 'https://fcsc.gov.ae/en-us/Pages/home.aspx'; - final fcscBanner = Image.asset( - BannerAssetPath.fcsc, - height: 56, - alignment:Alignment.center, - ); - - - - - @override - Widget build(BuildContext context) { - List textSpans = [ - - CustomTextRich.createTextSpan('How to Get Started\n', fontSize: 17, - color: Colors.black87, - fontWeight: FontWeight.bold, - ), - CustomTextRich.createTextSpan('1.Download the app from the App Store or Google Play Store.', - fontSize: 13, color:Color(0xFF898C81), - fontWeight: FontWeight.normal , - spacingTop: 1.9, - ), - CustomTextRich.createTextSpan( - '2.Log in to unlock advanced features or continue as a guest.\n', - fontSize: 13, color:Color(0xFF898C81), - fontWeight: FontWeight.normal , - spacingTop: 1.9,), - - CustomTextRich.createTextSpan( - '3.Navigate through categories, explore metrics, and bookmark essential information.\n', - fontSize: 13, color:Color(0xFF898C81), - fontWeight: FontWeight.normal , - ), - - CustomTextRich.createTextSpan('\nStay Updated', fontSize: 15, - color: Colors.black87, - fontWeight: FontWeight.w600, - height: 2, - ), - - CustomTextRich.createTextSpan( - '\nThe app regularly updates datasets and features to reflect the latest information. Notifications will alert you about new data or improvements.', - fontSize: 13, color:Color(0xFF898C81), - fontWeight: FontWeight.normal , - ), - - CustomTextRich.createTextSpan( - 'Support decision-making and research with reliable, up-to-date data.\n \n ', - fontSize: 14.0, - color: Color(0xFF898C81), - fontWeight: FontWeight.normal, - ), - - - ]; - return Scaffold( - appBar: AppBar( - elevation: 3, - shadowColor: Colors.black, - title: Text('About the App',), - leading: IconButton( - onPressed: (){ - context.go('/user-guide'); - }, - color: Colors.black, - icon: const Icon(Icons.arrow_back_ios_new),), - actions: [ - Consumer( - builder: (context, ref, _) { - final locale = ref.watch(localeProvider); // Current locale - return MyToggle( - isOn: locale?.languageCode == 'en', - knobTextWhenOn: 'ع', - knobTextWhenOff: 'EN', - pathColorWhenOn: Colors.grey.shade300, - pathColorWhenOff: Colors.grey.shade300, - onTap: () { - ref.read(localeProvider.notifier).toggleLocale(); - }, - ); - // IconButton( - // icon: Icon(locale?.languageCode == 'en' - // ? Icons.toggle_off_outlined - // : Icons.toggle_on_outlined,), - // onPressed: () { - // ref.read(localeProvider.notifier).toggleLocale(); - // }, - // ); - }, - ), - ], - ), - // title: Text('About the App',), - // showBackButton: true, - body:SafeArea( - child: Scrollbar( - thumbVisibility: true, - thickness: 6, - radius: Radius.circular(10), - interactive: true, - child:SingleChildScrollView( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Container( - color: Colors.white, - padding: const EdgeInsets.all(16.0), - width: MediaQuery.of(context).size.width, - child: Text.rich( - TextSpan( - text: 'The', - style: TextStyle( - fontSize: 19, - fontWeight: FontWeight.w600, - color: Colors.grey, - ), - children: [ - TextSpan( - text:' Federal Competitiveness and Statistics Centre (FCSC),', - style: TextStyle( - fontSize: 19, - fontWeight: FontWeight.w600, - color: Colors.black87, - ), - ), - TextSpan( - text:' in your App is designed to provide registered and approved users with access to accurate and comprehensive statistics about the UAE. The app serves as a centralized platform for exploring key datasets, trends, and insights across various sectors.', - style: TextStyle( - fontSize: 19, - fontWeight: FontWeight.w600, - color: Colors.grey, - ), - ), - ], - ), - ), - ), - - Column( - children: [ - Container( - color: Colors.grey[50], // Set the background color here - // child: SingleChildScrollView( - child: CustomTextRich( - textSpans: textSpans, - padding: const EdgeInsets.all(16.0), - textAlign: TextAlign.start, - ), - ), - Container( - color: Colors.grey[50], - padding: EdgeInsets.only(bottom: 26.0), - child:Text.rich( - TextSpan( - text: 'For more information please visit ', - style: TextStyle( - fontSize: 16.0, - color: Color(0xFF265E84), - fontWeight: FontWeight.normal,), - children: [ - TextSpan( - text: 'www.fcsc.gov.ae', - style: TextStyle( - fontSize: 16.0, - color: Color(0xFF568898), - fontWeight: FontWeight.normal, - decoration: TextDecoration.underline, - decorationColor:Color(0xFF568898), - ), - recognizer: TapGestureRecognizer() - ..onTap = () async { - final Uri uri = Uri.parse(url); - if (await launchUrl(uri)) { - await launchUrl(uri, mode: LaunchMode.externalApplication); - } else { - throw 'Could not launch $url'; - } - }, - ), - ], - ), - ), - ), - Container( - color: Colors.grey[50], - padding: EdgeInsets.only(bottom: 26.0), - width: MediaQuery.of(context).size.width, - child: Center( - child: fcscBanner, - ), - ), - ], - ), - ], - ), - ), - ), - ), - ); - } -} diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/user_guide.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/user_guide.dart deleted file mode 100644 index 2455932a..00000000 --- a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/user_guide.dart +++ /dev/null @@ -1,148 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:go_router/go_router.dart'; -import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; -class UserGuide extends StatefulWidget { - const UserGuide({super.key}); - - @override - State createState() => _UserGuideState(); -} - -class _UserGuideState extends State { - @override - Widget build(BuildContext context) { - - List createRows(List>> items) { - return items.map((pair) { - return Padding( - padding: const EdgeInsets.only(bottom: 20), - child: Row( - mainAxisAlignment: pair.length == 1 - ? MainAxisAlignment.center - : MainAxisAlignment.spaceEvenly, - children: pair.map((item) { - return userGuides( - color: item['color'] as Color, - text: item['text'] as String, - dynamicIcon: item['icon'], - routePath:item['routePath']as String, - ); - }).toList(), - ), - ); - }).toList(); - } - - return BaseScaffold( - title: Text('User Guide'), - body: SingleChildScrollView( - child: Container( - padding: const EdgeInsets.all(16.0), // Padding around content - child: Column( - children: createRows([ - // Each pair defines a row of (Color, Text) pairs - [ - {'routePath':'gettingStarted','color': Color(0xFF90B0D5), 'text': 'Getting Started', 'icon': 'START',}, - {'routePath':'features','color': Color(0xFFAA8E83), 'text': 'Using Features', 'icon': Icons.stars_outlined,}, - ], - [ - {'routePath':'faq','color': Color(0xFF7296BE), 'text': 'FAQs', 'icon': Icons.question_answer_sharp,}, - // {'routePath':'features','color': Color(0xFF7DAFBC), 'text': 'Advanced Settings', 'icon': Icons.settings_outlined, 'index': '6'}, - ], - ]), - ), - ), - ), ); - } -} - -class userGuides extends StatelessWidget { - - const userGuides({super.key, required this.routePath ,required this.color, required this.text,required this.dynamicIcon}); - final Color color; - final String text; - final dynamic dynamicIcon; - final String routePath; - - - Widget buildDynamicWidget(dynamic icons, Color iconColor) { - if (dynamicIcon is IconData) { - - return Icon( - icons, - size: 38, - color: iconColor, - ); - } else if (dynamicIcon is String) { - // Create a Text widget if variable is a String - return Text( - icons, - style: TextStyle( - fontWeight: FontWeight.w600, - fontSize: 20, - color: iconColor, - ), - ); - } else { - // Handle unsupported types - return Text( - 'Unsupported type', - style: TextStyle(color: Colors.red), - ); - } - } - - - @override - Widget build(BuildContext context) { - final double screenWidth= MediaQuery.of(context).size.width; - final double screenHeight= MediaQuery.of(context).size.height; - return InkWell( - onTap: (){ - context.push('/user-guide/$routePath'); - }, - child: Container( - padding: EdgeInsets.symmetric(horizontal: 4), - height: 110, - width: screenWidth * 0.40, - margin: EdgeInsets.all(1), - decoration: BoxDecoration( - color: Colors.white, - borderRadius: BorderRadius.circular(10), - border: Border.all(color: color, - width: 2.0) - ), - child: Column( - mainAxisAlignment: MainAxisAlignment.center, - children: [ - // Icon( - // size:38, - // icons, // Home icon - // color: Colors.white, - // ), - buildDynamicWidget(dynamicIcon, color), - - SizedBox(width: 10,height: 10,), // Space between icon and text - Container( - width: double.infinity, - padding: EdgeInsets.symmetric(horizontal: 4, vertical: 5), // Padding inside the text background - decoration: BoxDecoration( - color: color, // Background color for text - borderRadius: BorderRadius.circular(5), - ), - child: Text( - text, - style: TextStyle( - color: Colors.white, // Text color - fontWeight: FontWeight.bold, - ), - textAlign: TextAlign.center, - ), - ), - ], - ), - ), - ); - } -} - diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/userguide.dart b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/userguide.dart new file mode 100755 index 00000000..65aaf812 --- /dev/null +++ b/lib/presentation/routes/drawer_routes/Drawer Items/user_guide/userguide.dart @@ -0,0 +1,175 @@ +import 'package:flutter/material.dart'; +import 'package:go_router/go_router.dart'; +import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; +import 'package:iconify_design/iconify_design.dart'; + +class Userguide extends StatefulWidget { + Userguide({super.key}); + + @override + State createState() => _UserguideState(); +} + +class _UserguideState extends State { + final List> guideList = [ + {'routePath':'aboutApp','color': Color(0xFF90B0D5), 'text': 'Getting Started', 'icon': 'cbi:start-tv', }, + {'routePath':'features','color': Color(0xFFAA8E83), 'text': 'Using Features', 'icon': 'pajamas:issue-type-feature',}, + {'routePath':'faq','color': Color(0xFF7296BE), 'text': 'FAQs', 'icon': 'mdi:faq',}, + ]; + + @override + Widget buildDynamicWidget(dynamic icons, Color color) { + if (icons is IconData) { + return Icon( + icons, + size: 38, + color: color, // Apply color dynamically + ); + } else if (icons is String) { + return Text( + icons, + style: TextStyle( + // fontFamily: 'Handel', + fontWeight: FontWeight.w700, + fontSize: 20, + letterSpacing: 1.6, + color: color, // Apply color dynamically + ), + ); + } else { + return Text( + 'Unsupported type', + style: TextStyle(color: Colors.red), + ); + } + } + + Widget build(BuildContext context) { + return BaseScaffold( + showDivider: true, + bottomColor: Colors.white, + dividerColor: Colors.grey[300], + appbarColor: Colors.white, + title: Padding( + padding:EdgeInsets.only(bottom:8.0), + child: Text('User Guide'), + ) , + body: Container( + color: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 16 , vertical: 20), + child: GridView.builder( + gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, // Two columns + crossAxisSpacing: 10.0, + mainAxisSpacing: 10.0, + mainAxisExtent:MediaQuery.of(context).size.height* 0.15 , + ), + itemCount: guideList.length, + itemBuilder: (context, index) { + return HoverContainer( + iconName: guideList[index]['icon'], + title: guideList[index]['text'], + routePath: guideList[index]['routePath'], + ); + }, + ), + ), + ); + } + +} + + +class HoverContainer extends StatefulWidget { + final String iconName; + final String title; + final String routePath; + + + const HoverContainer({Key? key, required this.iconName, required this.title, required this.routePath}) : super(key: key); + + @override + _HoverContainerState createState() => _HoverContainerState(); +} + +class _HoverContainerState extends State { + bool isHovered = true; + @override + Widget build(BuildContext context) { + final double screenWidth= MediaQuery.of(context).size.width; + final double screenHeight= MediaQuery.of(context).size.height; + return GestureDetector( + onTap: () { context.push('/user-guide/${widget.routePath}');}, + child: MouseRegion( + onEnter: (_) => setState(() => isHovered = true), + onExit: (_) => setState(() => isHovered = true), + child : Container( + padding: EdgeInsets.only(top: 4, right: 4, left: 4, bottom: 6), + height: screenHeight* 0.23 , + width: screenWidth*0.30, + margin: EdgeInsets.all(1), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(10), + boxShadow: isHovered + ? [ + BoxShadow( + color: Colors.black.withOpacity(0.2), + blurRadius:2, + spreadRadius: 1, + offset: Offset(0, 4), + ), + ] + : [], + border: Border.all( + color: Color(0xFF7DAFBC), + width: 1.0 + ), + ), + alignment: Alignment.center, + // duration: Duration(milliseconds: 200), + + child: LayoutBuilder(builder: (context, constraints){ + double containerWidth = constraints.maxWidth; + // double containerHeight = constraints.maxHeight; + return Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + IconifyIcon(icon: widget.iconName, + color: Color((0xFF7DAFBC)), + size: containerWidth * 0.25,), + // buildDynamicWidget(data['icon'], Color(0xFF7DAFBC)), + SizedBox(width: 10,height: containerWidth * 0.04,), // Space between icon and text + Container( + width: containerWidth* 0.85, + padding: EdgeInsets.symmetric(horizontal: 4, vertical: 4), + margin: EdgeInsets.only(bottom: 3), + decoration: BoxDecoration( + color: Color(0xFF7DAFBC), + borderRadius: BorderRadius.circular(5), + border: Border.all(color: Color(0xFF7DAFBC)) + ), + child: Text( + widget.title, + style: TextStyle( + color: Colors.white, // Text color + fontWeight: FontWeight.bold, + ), + textAlign: TextAlign.center, + ), + ), + ], + ); + }) + + + ), + ), + + + + ); + + + } +} \ No newline at end of file diff --git a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart index 5067f8da..9f95fbbf 100644 --- a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart +++ b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart @@ -4,12 +4,15 @@ import 'dart:convert'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; 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/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'; @@ -25,16 +28,22 @@ class BaseScaffold extends ConsumerStatefulWidget { required this.body, required this.title, this.actions, + this.showDivider = false, + this.dividerColor, this.showBackButton = false, this.mycenterTitle = false, this.appbarColor, this.mytitleColor, + this.bottomColor = null, }); final Widget body; final Widget title; - final bool? showBackButton; + final Color? dividerColor; + final bool showDivider; + final bool showBackButton; final bool? mycenterTitle; final List? actions; + final Color? bottomColor; final Color? appbarColor, mytitleColor; @override @@ -63,6 +72,8 @@ class _BaseScaffoldState extends ConsumerState { final GlobalKey drawerKey = GlobalKey(); late double toggleHeight = 0; bool isLoggedOut = false; + final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(); + static final _repo = getIt.call(); @override void initState() { @@ -145,7 +156,7 @@ class _BaseScaffoldState extends ConsumerState { Align( alignment: Alignment.bottomRight, child: Padding( - padding: const EdgeInsets.only(right:10.0), + padding: const EdgeInsets.only(right: 10.0), child: Text( '5/7', style: const TextStyle( @@ -195,9 +206,10 @@ class _BaseScaffoldState extends ConsumerState { .state = true; ref .read(previousChartsTourProvider - .notifier) + .notifier) .state = false; - context.go('/chartScreen/hotels?bgColor=0xFF90B0D5&mainTopic=ECONOMY&title=Hotel+Establishments'); + context.go( + '/chartScreen/hotels?bgColor=0xFF90B0D5&mainTopic=ECONOMY&title=Hotel+Establishments'); }, ), ), @@ -258,8 +270,8 @@ class _BaseScaffoldState extends ConsumerState { children: [ Align( alignment: Alignment.bottomRight, - child:Padding( - padding: const EdgeInsets.only(right:10.0), + child: Padding( + padding: const EdgeInsets.only(right: 10.0), child: Text( '6/7', style: const TextStyle( @@ -335,8 +347,7 @@ class _BaseScaffoldState extends ConsumerState { ), ), TargetContent( - padding: EdgeInsets.only( - right: screenWidth * 0.7, top: 30), + padding: EdgeInsets.only(right: screenWidth * 0.7, top: 30), align: ContentAlign.right, child: Container( width: 200, @@ -393,8 +404,8 @@ class _BaseScaffoldState extends ConsumerState { children: [ Align( alignment: Alignment.bottomRight, - child:Padding( - padding: const EdgeInsets.only(right:10.0), + child: Padding( + padding: const EdgeInsets.only(right: 10.0), child: Text( '7/7', style: const TextStyle( @@ -451,10 +462,10 @@ class _BaseScaffoldState extends ConsumerState { .state = true; ref .read( - previousChartsTourProvider.notifier) + previousChartsTourProvider.notifier) .state = true; ref.read(homeTourProvider.notifier).state = - true; + true; ref .read(previousHomeTourProvider.notifier) .state = true; @@ -463,7 +474,7 @@ class _BaseScaffoldState extends ConsumerState { .state = true; ref .read(previousScaffoldTourProvider - .notifier) + .notifier) .state = true; tutorialCoachMark.finish(); }, @@ -496,7 +507,7 @@ class _BaseScaffoldState extends ConsumerState { ), TargetContent( padding: - EdgeInsets.only(left: screenWidth * 0.7, top: toggleHeight), + EdgeInsets.only(left: screenWidth * 0.7, top: toggleHeight), align: ContentAlign.left, child: Container( width: 200, @@ -593,8 +604,13 @@ class _BaseScaffoldState extends ConsumerState { // setState(() { // isLoggedOut = true; // }); + // prefs.clear(); + await _repo.logout(); + // state = const AsyncData(null); + // _pb.authStore.clear(); + // await _secureStorage.delete(key: "FlutterSecureStorage.session"); prefs.clear(); - context.go('/'); + context.go('/login'); } @override @@ -606,9 +622,20 @@ class _BaseScaffoldState extends ConsumerState { double mywidth = MediaQuery.of(context).size.width; return Scaffold( + backgroundColor: Colors.white, appBar: AppBar( title: widget.title, - backgroundColor: widget.appbarColor, + backgroundColor: Colors.white, + leadingWidth: widget.showBackButton ? mywidth * 0.25 : null, + bottom: widget.showDivider + ? PreferredSize( + preferredSize: Size.fromHeight(1), // Height of the line + child: Container( + color: widget.dividerColor, // Line color + height: 1, // Line thickness + ), + ) + : null, actions: widget.actions ?? [ // IconButton( @@ -646,10 +673,8 @@ class _BaseScaffoldState extends ConsumerState { builder: (BuildContext context) { return IconButton( key: drawerKey, - color: (widget.showBackButton == true) - ? Colors.white - : Colors.black, - icon: const Icon(Icons.menu), + color: Colors.black, + icon: const Icon(Icons.menu, size: 30), onPressed: () { Scaffold.of(context).openDrawer(); }, @@ -737,37 +762,37 @@ class _BaseScaffoldState extends ConsumerState { ListTile( leading: Image.asset( DrawerAssetIconPath.feedback, - color: Colors.black , + color: Colors.black, width: 20, height: 20, ), // title: const Text('Feedback'), title: Text(AppLocalizations.of(context)!.feedback_title), - onTap: () => context.go('/feedback'), + onTap: () => context.go('/feedback', extra: userName), ), if (role == 'admin') ListTile( -leading: Image.asset( + leading: Image.asset( DrawerAssetIconPath.manageUser, - color: Colors.black , + color: Colors.black, width: 20, height: 20, ), - // title: Text('Manage User'), + // title: Text('Manage User'), title: Text( AppLocalizations.of(context)!.manage_user, ), onTap: () => context.go('/manageuser'), ), ListTile( - leading: Icon(Icons.collections_bookmark_rounded), + leading: Icon(Icons.bookmarks_outlined), title: const Text('Bookmark'), onTap: () => context.go('/bookmark'), ), ListTile( leading: Image.asset( DrawerAssetIconPath.guide, - color: Colors.black , + color: Colors.black, width: 20, height: 20, ), @@ -828,57 +853,74 @@ leading: Image.asset( ), ])), bottomNavigationBar: BottomNavigationBar( + backgroundColor: Colors.white, currentIndex: _getSelectedIndex(currentRoute), onTap: (index) => _onItemTapped(context, index), type: BottomNavigationBarType.fixed, items: [ BottomNavigationBarItem( - icon: Padding( - padding: const EdgeInsets.only(bottom: 4), // Adjust this for spacing - child: Image.asset( - BottomBarAssetIconPath.home, - color: _getSelectedIndex(currentRoute) == 0 ? Colors.black : Color(0xFF989898), - width: 20, - height: 20, - ),), + icon: Padding( + padding: + const EdgeInsets.only(bottom: 4), // Adjust this for spacing + child: Image.asset( + BottomBarAssetIconPath.home, + color: _getSelectedIndex(currentRoute) == 0 + ? Colors.black + : Color(0xFF989898), + width: 20, + height: 20, + ), + ), // label: 'Home', label: AppLocalizations.of(context)!.nav_home, ), BottomNavigationBarItem( // icon: Icon(Icons.map), - icon:Padding( - padding: const EdgeInsets.only(bottom: 4), // Adjust this for spacing - child: Image.asset( - BottomBarAssetIconPath.uaeMap, - color: _getSelectedIndex(currentRoute) == 1 ? Colors.black : Color(0xFF989898), - width: 20, - height: 20, - ),), + icon: Padding( + padding: + const EdgeInsets.only(bottom: 4), // Adjust this for spacing + child: Image.asset( + BottomBarAssetIconPath.uaeMap, + color: _getSelectedIndex(currentRoute) == 1 + ? Colors.black + : Color(0xFF989898), + width: 20, + height: 20, + ), + ), // label: 'UAE Numbers' label: AppLocalizations.of(context)!.nav_uae, ), BottomNavigationBarItem( -icon: Padding( - padding: const EdgeInsets.only(bottom: 4), // Adjust this for spacing - child: Image.asset( - BottomBarAssetIconPath.ranking, - color: _getSelectedIndex(currentRoute) == 2 ? Colors.black : Color(0xFF989898), - width: 20, - height: 20, - ),), - // label: 'Competitiveness', + icon: Padding( + padding: + const EdgeInsets.only(bottom: 4), // Adjust this for spacing + child: Image.asset( + BottomBarAssetIconPath.ranking, + color: _getSelectedIndex(currentRoute) == 2 + ? Colors.black + : Color(0xFF989898), + width: 20, + height: 20, + ), + ), + // label: 'Competitiveness', label: AppLocalizations.of(context)!.nav_competitiveness, ), BottomNavigationBarItem( - icon: Padding( - padding: const EdgeInsets.only(bottom: 4), // Adjust this for spacing - child: Image.asset( - BottomBarAssetIconPath.globe, - color: _getSelectedIndex(currentRoute) == 2 ? Colors.black : Color(0xFF989898), - width: 20, - height: 20, - ),), - // label: 'Country Profile', + icon: Padding( + padding: + const EdgeInsets.only(bottom: 4), // Adjust this for spacing + child: Image.asset( + BottomBarAssetIconPath.globe, + color: _getSelectedIndex(currentRoute) == 2 + ? Colors.black + : Color(0xFF989898), + width: 20, + height: 20, + ), + ), + // label: 'Country Profile', label: AppLocalizations.of(context)!.country_profile, ), ], diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index cee82ebe..761e0b22 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -26,5 +26,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin")) - WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin")) + FLTWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "FLTWebViewFlutterPlugin")) } diff --git a/pubspec.lock b/pubspec.lock index 10d21d20..c8b9ce43 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -5,10 +5,10 @@ packages: dependency: transitive description: name: _fe_analyzer_shared - sha256: "88399e291da5f7e889359681a8f64b18c5123e03576b01f32a6a276611e511c3" + sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab" url: "https://pub.dev" source: hosted - version: "78.0.0" + version: "76.0.0" _macros: dependency: transitive description: dart @@ -18,18 +18,18 @@ packages: dependency: transitive description: name: analyzer - sha256: "62899ef43d0b962b056ed2ebac6b47ec76ffd003d5f7c4e4dc870afe63188e33" + sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e" url: "https://pub.dev" source: hosted - version: "7.1.0" + version: "6.11.0" analyzer_plugin: dependency: transitive description: name: analyzer_plugin - sha256: "1d460d14e3c2ae36dc2b32cef847c4479198cf87704f63c3c3c8150ee50c3916" + sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161" url: "https://pub.dev" source: hosted - version: "0.12.0" + version: "0.11.3" ansicolor: dependency: transitive description: @@ -74,50 +74,50 @@ packages: dependency: transitive description: name: build - sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 + sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0" url: "https://pub.dev" source: hosted - version: "2.4.2" + version: "2.4.1" build_config: dependency: transitive description: name: build_config - sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" + sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1 url: "https://pub.dev" source: hosted - version: "1.1.2" + version: "1.1.1" build_daemon: dependency: transitive description: name: build_daemon - sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948" + sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9" url: "https://pub.dev" source: hosted - version: "4.0.3" + version: "4.0.2" build_resolvers: dependency: transitive description: name: build_resolvers - sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e" + sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a" url: "https://pub.dev" source: hosted - version: "2.4.3" + version: "2.4.2" build_runner: dependency: "direct dev" description: name: build_runner - sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573" + sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d" url: "https://pub.dev" source: hosted - version: "2.4.14" + version: "2.4.13" build_runner_core: dependency: transitive description: name: build_runner_core - sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" + sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0 url: "https://pub.dev" source: hosted - version: "8.0.0" + version: "7.3.2" built_collection: dependency: transitive description: @@ -258,42 +258,50 @@ packages: dependency: "direct dev" description: name: custom_lint - sha256: "7e6a73e1722ad90b48f77918994c17a5b177b0869804ea3c4ce9c9199de019f6" + sha256: "3486c470bb93313a9417f926c7dd694a2e349220992d7b9d14534dc49c15bba9" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.0" custom_lint_builder: dependency: transitive description: name: custom_lint_builder - sha256: e26941131416b0bc81219dc8ddc68b34c6319e20abc001dd4855412749309d3b + sha256: "42cdc41994eeeddab0d7a722c7093ec52bd0761921eeb2cbdbf33d192a234759" url: "https://pub.dev" source: hosted - version: "0.7.2" + version: "0.7.0" custom_lint_core: dependency: transitive description: name: custom_lint_core - sha256: "6dcee8a017181941c51a110da7e267c1d104dc74bec8862eeb8c85b5c8759a9e" + sha256: "02450c3e45e2a6e8b26c4d16687596ab3c4644dd5792e3313aa9ceba5a49b7f5" url: "https://pub.dev" source: hosted - version: "0.7.1" + version: "0.7.0" custom_lint_visitor: dependency: transitive description: name: custom_lint_visitor - sha256: "14df0760dfa81b7b0c398c876045f4e4a343eb2c9d200c66163671dd3e337c1b" + sha256: bfe9b7a09c4775a587b58d10ebb871d4fe618237639b1e84d5ec62d7dfef25f9 url: "https://pub.dev" source: hosted - version: "1.0.0+7.1.0" + version: "1.0.0+6.11.0" dart_style: dependency: transitive description: name: dart_style - sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac" + sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab" url: "https://pub.dev" source: hosted - version: "3.0.1" + version: "2.3.7" + dartz: + dependency: transitive + description: + name: dartz + sha256: e6acf34ad2e31b1eb00948692468c30ab48ac8250e0f0df661e29f12dd252168 + url: "https://pub.dev" + source: hosted + version: "0.10.1" dbus: dependency: transitive description: @@ -302,6 +310,22 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.11" + dio: + dependency: transitive + description: + name: dio + sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9" + url: "https://pub.dev" + source: hosted + version: "5.8.0+1" + dio_web_adapter: + dependency: transitive + description: + name: dio_web_adapter + sha256: e485c7a39ff2b384fa1d7e09b4e25f755804de8384358049124830b04fc4f93a + url: "https://pub.dev" + source: hosted + version: "2.1.0" equatable: dependency: transitive description: @@ -543,6 +567,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.7.0" + flutter_svg: + dependency: transitive + description: + name: flutter_svg + sha256: c200fd79c918a40c5cd50ea0877fa13f81bdaf6f0a5d3dbcc2a13e3285d6aa1b + url: "https://pub.dev" + source: hosted + version: "2.0.17" flutter_test: dependency: "direct dev" description: flutter @@ -565,10 +597,10 @@ packages: dependency: "direct dev" description: name: freezed - sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c" + sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e" url: "https://pub.dev" source: hosted - version: "2.5.8" + version: "2.5.7" freezed_annotation: dependency: "direct main" description: @@ -605,10 +637,10 @@ packages: dependency: "direct main" description: name: go_router - sha256: "9b736a9fa879d8ad6df7932cbdcc58237c173ab004ef90d8377923d7ad731eaa" + sha256: daf3ff5570f55396b2d2c9bf8136d7db3a8acf208ac0cef92a3ae2beb9a81550 url: "https://pub.dev" source: hosted - version: "14.7.2" + version: "14.7.1" graphs: dependency: transitive description: @@ -661,10 +693,18 @@ packages: dependency: transitive description: name: http_parser - sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" + sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b" url: "https://pub.dev" source: hosted - version: "4.1.2" + version: "4.0.2" + iconify_design: + dependency: "direct main" + description: + name: iconify_design + sha256: "4e8593d994b94f2be6942fafa7392042df457a970763b5bed1bc0eb37ca6e776" + url: "https://pub.dev" + source: hosted + version: "1.0.1" image: dependency: transitive description: @@ -749,10 +789,10 @@ packages: dependency: "direct dev" description: name: injectable_generator - sha256: b04673a4c88b3a848c0c77bf58b8309f9b9e064d9fe1df5450c8ee1675eaea1a + sha256: af403d76c7b18b4217335e0075e950cd0579fd7f8d7bd47ee7c85ada31680ba1 url: "https://pub.dev" source: hosted - version: "2.7.0" + version: "2.6.2" intl: dependency: "direct main" description: @@ -789,10 +829,10 @@ packages: dependency: "direct dev" description: name: json_serializable - sha256: b0a98230538fe5d0b60a22fb6bf1b6cb03471b53e3324ff6069c591679dd59c9 + sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c url: "https://pub.dev" source: hosted - version: "6.9.3" + version: "6.9.0" jwt_decoder: dependency: "direct main" description: @@ -829,10 +869,10 @@ packages: dependency: transitive description: name: lints - sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 + sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413" url: "https://pub.dev" source: hosted - version: "5.1.1" + version: "5.0.0" logging: dependency: transitive description: @@ -953,6 +993,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.9.0" + path_parsing: + dependency: transitive + description: + name: path_parsing + sha256: "883402936929eac138ee0a45da5b0f2c80f89913e6dc3bf77eb65b84b409c6ca" + url: "https://pub.dev" + source: hosted + version: "1.1.0" path_provider: dependency: transitive description: @@ -1061,10 +1109,10 @@ packages: dependency: transitive description: name: pubspec_parse - sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" + sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0" url: "https://pub.dev" source: hosted - version: "1.5.0" + version: "1.4.0" recase: dependency: transitive description: @@ -1093,10 +1141,10 @@ packages: dependency: transitive description: name: riverpod_analyzer_utils - sha256: "837a6dc33f490706c7f4632c516bcd10804ee4d9ccc8046124ca56388715fdf3" + sha256: c6b8222b2b483cb87ae77ad147d6408f400c64f060df7a225b127f4afef4f8c8 url: "https://pub.dev" source: hosted - version: "0.5.9" + version: "0.5.8" riverpod_annotation: dependency: "direct main" description: @@ -1109,18 +1157,18 @@ packages: dependency: "direct dev" description: name: riverpod_generator - sha256: "120d3310f687f43e7011bb213b90a436f1bbc300f0e4b251a72c39bccb017a4f" + sha256: "63546d70952015f0981361636bf8f356d9cfd9d7f6f0815e3c07789a41233188" url: "https://pub.dev" source: hosted - version: "2.6.4" + version: "2.6.3" riverpod_lint: dependency: "direct dev" description: name: riverpod_lint - sha256: b05408412b0f75dec954e032c855bc28349eeed2d2187f94519e1ddfdf8b3693 + sha256: "83e4caa337a9840469b7b9bd8c2351ce85abad80f570d84146911b32086fbd99" url: "https://pub.dev" source: hosted - version: "2.6.4" + version: "2.6.3" rxdart: dependency: transitive description: @@ -1212,10 +1260,10 @@ packages: dependency: transitive description: name: shelf - sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 + sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4 url: "https://pub.dev" source: hosted - version: "1.4.2" + version: "1.4.1" shelf_web_socket: dependency: transitive description: @@ -1240,10 +1288,10 @@ packages: dependency: transitive description: name: source_gen - sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" + sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832" url: "https://pub.dev" source: hosted - version: "2.0.0" + version: "1.5.0" source_helper: dependency: transitive description: @@ -1432,10 +1480,10 @@ packages: dependency: transitive description: name: url_launcher_web - sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" + sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e" url: "https://pub.dev" source: hosted - version: "2.4.0" + version: "2.3.3" url_launcher_windows: dependency: transitive description: @@ -1452,6 +1500,30 @@ packages: url: "https://pub.dev" source: hosted version: "4.5.1" + vector_graphics: + dependency: transitive + description: + name: vector_graphics + sha256: "44cc7104ff32563122a929e4620cf3efd584194eec6d1d913eb5ba593dbcf6de" + url: "https://pub.dev" + source: hosted + version: "1.1.18" + vector_graphics_codec: + dependency: transitive + description: + name: vector_graphics_codec + sha256: "99fd9fbd34d9f9a32efd7b6a6aae14125d8237b10403b422a6a6dfeac2806146" + url: "https://pub.dev" + source: hosted + version: "1.1.13" + vector_graphics_compiler: + dependency: transitive + description: + name: vector_graphics_compiler + sha256: "1b4b9e706a10294258727674a340ae0d6e64a7231980f9f9a3d12e4b42407aad" + url: "https://pub.dev" + source: hosted + version: "1.1.16" vector_math: dependency: transitive description: @@ -1472,10 +1544,10 @@ packages: dependency: transitive description: name: video_player_android - sha256: "7018dbcb395e2bca0b9a898e73989e67c0c4a5db269528e1b036ca38bcca0d0b" + sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898" url: "https://pub.dev" source: hosted - version: "2.7.17" + version: "2.7.16" video_player_avfoundation: dependency: transitive description: @@ -1552,10 +1624,10 @@ packages: dependency: transitive description: name: webview_flutter_android - sha256: "5568f17a9c25c0fdd0737900fa1c2d1fee2d780bc212d9aec10c2d1f48ef0f59" + sha256: d1ee28f44894cbabb1d94cc42f9980297f689ff844d067ec50ff88d86e27d63f url: "https://pub.dev" source: hosted - version: "4.3.1" + version: "4.3.0" webview_flutter_platform_interface: dependency: transitive description: @@ -1568,10 +1640,10 @@ packages: dependency: transitive description: name: webview_flutter_wkwebview - sha256: "8e0593559bfecd35eb1757d6907ed6b995a41ef82607d6113df897c2805ce6be" + sha256: "4adc14ea9a770cc9e2c8f1ac734536bd40e82615bd0fa6b94be10982de656cc7" url: "https://pub.dev" source: hosted - version: "3.18.0" + version: "3.17.0" win32: dependency: transitive description: @@ -1605,5 +1677,5 @@ packages: source: hosted version: "3.1.3" sdks: - dart: ">=3.6.0 <4.0.0" - flutter: ">=3.27.0" + dart: ">=3.5.2 <4.0.0" + flutter: ">=3.24.0" diff --git a/pubspec.yaml b/pubspec.yaml index 48939a6f..75073021 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,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.9+10 environment: sdk: ">=3.2.3 <4.0.0" @@ -22,7 +22,7 @@ dependencies: cupertino_icons: ^1.0.6 fl_chart: ^0.70.2 - + iconify_design: ^1.0.1 marquee: ^2.2.3 url_launcher: ^6.3.1 # dynamic_layouts: @@ -112,6 +112,24 @@ flutter: - assets/cached_responses/sharepoint/country_leader_imgs/ - assets/edit_profile/ - assets/splash_screen/ + - 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 + - assets/icons/misc/save.png + - assets/icons/drawer/guide.png + - assets/icons/drawer/feedback.png + - assets/icons/drawer/manageusr.png + - assets/feedback/disappointed.png + - assets/feedback/frowning.png + - assets/feedback/neutral.png + - assets/feedback/smiling.png + - assets/feedback/smilingopenface.png + - assets/feedback/errorfb.png + - assets/feedback/thumbfb.png + - assets/user_guide/ + - assets/app_tour/ fonts: - family: Segoe