Toggle alignment Fixed - Registration Page

This commit is contained in:
VINISTAN 2025-02-08 00:49:23 +05:30
commit 6317d32b79
52 changed files with 4958 additions and 3062 deletions

View File

@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) {
def flutterVersionCode = localProperties.getProperty("flutter.versionCode") def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = "9" flutterVersionCode = "10"
} }
def flutterVersionName = localProperties.getProperty("flutter.versionName") def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) { if (flutterVersionName == null) {
flutterVersionName = "1.0.8" flutterVersionName = "1.0.9"
} }
def keystorePropertiesFile = rootProject.file("key.properties") def keystorePropertiesFile = rootProject.file("key.properties")

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

BIN
assets/feedback/errorfb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 716 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 832 B

BIN
assets/feedback/neutral.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 767 B

BIN
assets/feedback/smiling.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1004 B

BIN
assets/feedback/thumbfb.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 826 B

BIN
assets/user_guide/AboutFCSC.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

BIN
assets/user_guide/appFeatures.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
assets/user_guide/editProfile.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

BIN
assets/user_guide/getStarted.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
assets/user_guide/howUse.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

BIN
assets/user_guide/purpose.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

BIN
assets/user_guide/stayUpdate.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

BIN
assets/user_guide/whoUse.png Executable file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

View File

@ -293,6 +293,7 @@
// } // }
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import 'package:go_router/go_router.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/Bottom%20Navigation%20Pages/UAE_Numbers/Social/marriages.dart';
import 'package:uae_stat/presentation/Screens/auth_verification/registration.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/charts/screens/chart_screen.dart';
import 'package:uae_stat/presentation/Screens/demo_home2.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/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/AboutTheApp/AboutFCSC.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/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/routes/drawer_routes/custom_drawer_routes.dart';
import 'package:uae_stat/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.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/feedback.dart';
import '../presentation/routes/drawer_routes/Drawer Items/user_guide/faq_page.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/features.dart';
import '../presentation/routes/drawer_routes/Drawer Items/user_guide/user_guide.dart';
import '../presentation/routes/drawer_routes/Drawer Items/manage_users.dart'; import '../presentation/routes/drawer_routes/Drawer Items/manage_users.dart';
final pbService = PocketBaseService(); final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();
Future<String> getInitialRoute() async { Future<String?> _checkSession() async {
bool isLoggedIn = await pbService.loadSession(); print('_checkSession');
return isLoggedIn ? '/myhomepage' : '/login'; 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( final GoRouter router = GoRouter(
routes: [ routes: [
GoRoute(
path: '/',
builder: (context, state) => LoginRoute(),
),
// GoRoute( // GoRoute(
// path: '/', // path: '/',
// redirect: (context, state) async { // //builder: (context, state) => LoginRoute(),
// return await getInitialRoute(); // builder: (context, state) => LoginRoute(),
// },
// ), // ),
GoRoute(
path: '/',
redirect: (context, state) async => await _checkSession(),
),
GoRoute( GoRoute(
path: '/internetcheck', path: '/internetcheck',
builder: (context, state) => InternetCheck(), builder: (context, state) => InternetCheck(),
@ -455,23 +474,70 @@ final GoRouter router = GoRouter(
), ),
GoRoute( GoRoute(
path: '/user-guide', path: '/user-guide',
builder: (context, state) => UserGuide(), builder: (context, state) => Userguide(),
routes: <RouteBase>[ routes: <RouteBase>[
GoRoute( GoRoute(
path: '/features', path: '/features',
name: 'features', name: 'features',
builder: (context, state) => UsingFeatures(), builder: (context, state) => UsingFeatures(),
routes: <RouteBase>[
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: <RouteBase>[
GoRoute(
path: 'aboutFCSC',
name: 'aboutFCSC',
builder: (context, state) => aboutFCSC(),
),
GoRoute(
path: 'getStarted',
name: 'getStarted',
builder: (context, state) => GetStarted(),
),
]),
GoRoute( GoRoute(
path: '/faq', path: '/faq',
name: 'faq', name: 'faq',
builder: (context, state) => FAQPage(), builder: (context, state) => FAQPage(),
), ),
GoRoute(
path: '/gettingStarted',
name: 'gettingStarted',
builder: (context, state) => GettingStarted(),
),
], ],
), ),
// GoRoute( // GoRoute(

View File

@ -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';
}

View File

@ -1,8 +1,8 @@
{ {
"feedback_title": "FeedBack", "feedback_title": "Feedback",
"feedback_failed_msg": "Your feedback could not be submitted. Please try again", "feedback_failed_msg": "Your feedback could not be \n submitted. Please try again",
"register_title": "Register", "register_title": "Register",
"register_details": "Please enter your details", "register_details": "Please enter your details",

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; 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/presentation/routes/drawer_routes/custom_drawer_routes.dart';
class Competitiveness extends StatelessWidget { class Competitiveness extends StatelessWidget {
@ -8,16 +9,23 @@ class Competitiveness extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return BaseScaffold( return PopScope(
title: Center( onPopInvokedWithResult: (didPop, result) {
child: SizedBox( if (didPop) return;
height: myheight / 5, context.go('/myhomepage');
width: mywidth / 3, },
child: Image(image: AssetImage('assets/logos/uae_stat.png')))), child: BaseScaffold(
body: CompetitivenessState(context), 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"));
}
} }

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; 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/presentation/routes/drawer_routes/custom_drawer_routes.dart';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
@ -9,16 +10,23 @@ class CountryProfile extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return BaseScaffold( return PopScope(
title: Center( onPopInvokedWithResult: (didPop, result) {
child: SizedBox( if (didPop) return;
height: myheight / 5, context.go('/myhomepage');
width: mywidth / 3, },
child: Image(image: AssetImage('assets/logos/uae_stat.png')))), child: BaseScaffold(
body: CountryProfileWidget(), 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 { class CountryProfileWidget extends StatelessWidget {
const CountryProfileWidget({super.key}); const CountryProfileWidget({super.key});
@ -28,99 +36,20 @@ class CountryProfileWidget extends StatelessWidget {
} }
} }
class HorizontalBarChart extends StatelessWidget { class HorizontalBarChart extends StatelessWidget {
final List<String> xAxisData = ['2019', '2020', '2021', '2022', '2023']; final List<String> xAxisData = ['2019', '2020', '2021', '2022', '2023'];
final List<double> yAxisData = [2, 4, 1, 5, 3]; final List<double> yAxisData = [2, 4, 1, 5, 3];
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
return Scaffold( return Scaffold(
appBar: AppBar(title: Text('Horizontal Bar Chart')), // appBar: AppBar(title: Text('Horizontal Bar Chart')),
body: Padding( body: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: child: Center(
Container( child: Text('Coming Soon'),
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,
),
],
),
),
),
),
),
),
),
); );
} }
} }
@ -129,14 +58,6 @@ void main() {
runApp(MaterialApp(home: HorizontalBarChart())); runApp(MaterialApp(home: HorizontalBarChart()));
} }
// void main() { // void main() {
// runApp(MaterialApp(home: HorizontalBarChart())); // runApp(MaterialApp(home: HorizontalBarChart()));
// } // }

View File

@ -12,16 +12,33 @@ import 'package:http/http.dart' as http;
class UaeNumbers extends StatelessWidget { class UaeNumbers extends StatelessWidget {
const UaeNumbers({super.key}); 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 @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; 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"), title: Text("UAE Numbers"),
body: body: uaenumberWidget(),
//EconomicDashboard(), ),
//EconomyExpandTile() );
uaenumberWidget());
} }
} }
@ -81,15 +98,18 @@ class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
children: [ children: [
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.white, color: Colors.white,
borderRadius: BorderRadius.circular(30.0), borderRadius: BorderRadius.circular(30.0),
border: Border.all(width: 1,color: Color(0xFFAA8E83)),), border: Border.all(width: 1, color: Color(0xFFAA8E83)),
),
child: TextField( child: TextField(
decoration: InputDecoration( decoration: InputDecoration(
hintText: "Search", hintText: "Search",
prefixIcon: Icon(Icons.search, prefixIcon: Icon(
color: Color(0xFFAA8E83),), Icons.search,
border: InputBorder.none, color: Color(0xFFAA8E83),
),
border: InputBorder.none,
contentPadding: contentPadding:
EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0), EdgeInsets.symmetric(vertical: 15.0, horizontal: 20.0),
), ),
@ -109,7 +129,7 @@ class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
return CustomExpandableTile( return CustomExpandableTile(
index: index, index: index,
isExpanded: expandedIndex == index, // Compare with expandedIndex isExpanded: expandedIndex == index, // Compare with expandedIndex
onTap: (index) { onTap: (index) {
setState(() { setState(() {
expandedIndex = (expandedIndex == index) ? null : index; expandedIndex = (expandedIndex == index) ? null : index;
@ -297,7 +317,6 @@ class CustomExpandableTile extends StatefulWidget {
final bool isExpanded; final bool isExpanded;
final ValueChanged<int> onTap; final ValueChanged<int> onTap;
const CustomExpandableTile({ const CustomExpandableTile({
required this.title, required this.title,
required this.titleBackgroundColor, required this.titleBackgroundColor,
@ -305,7 +324,6 @@ class CustomExpandableTile extends StatefulWidget {
required this.index, required this.index,
required this.isExpanded, required this.isExpanded,
required this.onTap, required this.onTap,
}); });
@override @override
@ -329,8 +347,7 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
child: Column( child: Column(
children: [ children: [
GestureDetector( GestureDetector(
onTap: () => widget.onTap(widget.index), onTap: () => widget.onTap(widget.index),
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: widget.titleBackgroundColor, color: widget.titleBackgroundColor,

View File

@ -15,12 +15,12 @@ import 'package:uae_stat/presentation/components/indicators/locale_provider.dart
import '../../components/my_toggle.dart'; import '../../components/my_toggle.dart';
import '../../routes/auth_routes/login_route.dart'; import '../../routes/auth_routes/login_route.dart';
class RegisterScreen extends StatefulWidget { class RegisterScreen extends ConsumerStatefulWidget {
@override @override
_RegisterScreenState createState() => _RegisterScreenState(); _RegisterScreenState createState() => _RegisterScreenState();
} }
class _RegisterScreenState extends State<RegisterScreen> { class _RegisterScreenState extends ConsumerState<RegisterScreen> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
final _usernameController = TextEditingController(); final _usernameController = TextEditingController();
final _emailController = TextEditingController(); final _emailController = TextEditingController();
@ -311,6 +311,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
Widget build(BuildContext context) { Widget build(BuildContext context) {
double screenheight = MediaQuery.of(context).size.height; double screenheight = MediaQuery.of(context).size.height;
double screenwidth = MediaQuery.of(context).size.width; double screenwidth = MediaQuery.of(context).size.width;
final registerLocale = ref.watch(localeProvider);
Widget buildIconContainer(IconData icon, Color iconColor) { Widget buildIconContainer(IconData icon, Color iconColor) {
return Container( return Container(
@ -337,28 +338,35 @@ class _RegisterScreenState extends State<RegisterScreen> {
return Scaffold( return Scaffold(
body: body:
Column( Column(
children: [ children: [
Consumer( Align(
builder: (context, ref, _) { alignment: AlignmentDirectional.topEnd,
final locale = ref.watch(localeProvider); // Current locale child: Consumer(
return builder: (context, ref, _) {
Align( final locale = ref.watch(localeProvider); // Current locale
alignment: AlignmentDirectional.topEnd, return MyToggle(
child: MyToggle( isOn: locale?.languageCode == 'en',
isOn: locale?.languageCode == 'en', knobTextWhenOn: 'ع',
knobTextWhenOn: 'ع', knobTextWhenOff: 'EN',
knobTextWhenOff: 'EN', pathColorWhenOn: Colors.grey.shade300,
pathColorWhenOn: Colors.grey.shade300, pathColorWhenOff: Colors.grey.shade300,
pathColorWhenOff: Colors.grey.shade300, onTap: () {
onTap: () { ref.read(localeProvider.notifier).toggleLocale();
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( Container(
height: MediaQuery.of(context).size.height/1.2, height: MediaQuery.of(context).size.height/1.2,
@ -531,153 +539,157 @@ class _RegisterScreenState extends State<RegisterScreen> {
), ),
), ),
// prefixIcon: Icon( // prefixIcon: Icon(
// Icons.person, // Icons.person,
// color: Color(0xFF90B0D5), // color: Color(0xFF90B0D5),
// //
// ), // ),
// border: OutlineInputBorder(), // border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: MyTheme.topicColor( color: MyTheme.topicColor(
IndicatorTopic.economy) IndicatorTopic.economy)
.shade400, .shade400,
width: 1), // Enabled border width: 1), // Enabled border
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Colors.deepPurple, color: Colors.deepPurple,
width: 2), // Focused border width: 2), // Focused border
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Error border width: 1), // Error border
), ),
focusedErrorBorder: OutlineInputBorder( focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Match the error color width: 1), // Match the error color
), ),
counterText: '', counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB)), hintStyle: TextStyle(color: Color(0xFFC3C6CB),
), fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16,
validator: _validateUsername, ),
maxLength: ),
40, // Set the maximum length to 20 characters validator: _validateUsername,
maxLengthEnforcement: MaxLengthEnforcement.enforced, maxLength:
), 40, // Set the maximum length to 20 characters
), maxLengthEnforcement: MaxLengthEnforcement.enforced,
SizedBox(height: 15), ),
Padding( ),
padding: const EdgeInsets.only( SizedBox(height: 15),
top: 5.0, bottom: 10, left: 30, right: 30), Padding(
child: TextFormField( padding: const EdgeInsets.only(
controller: _emailController, top: 5.0, bottom: 10, left: 30, right: 30),
// focusNode: _focusNodes[1], child: TextFormField(
decoration: InputDecoration( controller: _emailController,
// hintText: 'Enter your email', // focusNode: _focusNodes[1],
hintText: _showHints[1] decoration: InputDecoration(
? AppLocalizations.of(context)! // hintText: 'Enter your email',
.enter_your_email hintText: _showHints[1]
: null, ? AppLocalizations.of(context)!
// _showHints[1] ? 'Enter your email' : null, .enter_your_email
prefixIconConstraints: const BoxConstraints( : null,
maxWidth: 25 + 16 + 10, // _showHints[1] ? 'Enter your email' : null,
maxHeight: 25 + (8 * 2), prefixIconConstraints: const BoxConstraints(
), maxWidth: 25 + 16 + 10,
prefixIcon: Padding( maxHeight: 25 + (8 * 2),
padding: const EdgeInsetsDirectional.only( ),
start: 16, prefixIcon: Padding(
end: 10, padding: const EdgeInsetsDirectional.only(
), start: 16,
child: Image.asset( end: 10,
MiscIconAssetPath.vector, ),
fit: BoxFit.fitHeight, child: Image.asset(
height: 20, MiscIconAssetPath.vector,
width: 25, fit: BoxFit.fitHeight,
color: height: 20,
MyTheme.topicColor(IndicatorTopic.economy) width: 25,
.shade100, color:
), MyTheme.topicColor(IndicatorTopic.economy)
), .shade100,
),
),
// border: OutlineInputBorder(), // border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: MyTheme.topicColor( color: MyTheme.topicColor(
IndicatorTopic.economy) IndicatorTopic.economy)
.shade400, .shade400,
width: 1), width: 1),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Colors.deepPurple, color: Colors.deepPurple,
width: 2), // Focused border width: 2), // Focused border
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Error border width: 1), // Error border
), ),
focusedErrorBorder: OutlineInputBorder( focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Match the error color width: 1), // Match the error color
), ),
counterText: '', counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB)), hintStyle: TextStyle(color: Color(0xFFC3C6CB),
), fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16,
validator: _validateEmail, ),
maxLength: 320, ),
maxLengthEnforcement: MaxLengthEnforcement.enforced, validator: _validateEmail,
inputFormatters: [ maxLength: 320,
LengthLimitingTextInputFormatter( maxLengthEnforcement: MaxLengthEnforcement.enforced,
320), // Limit to 320 characters inputFormatters: [
], LengthLimitingTextInputFormatter(
), 320), // Limit to 320 characters
), ],
SizedBox(height: 15), ),
Padding( ),
padding: const EdgeInsets.only( SizedBox(height: 15),
top: 5.0, bottom: 10, left: 30, right: 30), Padding(
child: TextFormField( padding: const EdgeInsets.only(
controller: _passwordController, top: 5.0, bottom: 10, left: 30, right: 30),
// focusNode: _focusNodes[2], child: TextFormField(
obscureText: _obscurePassword, controller: _passwordController,
decoration: InputDecoration( // focusNode: _focusNodes[2],
hintText: _showHints[2] obscureText: _obscurePassword,
? AppLocalizations.of(context)! decoration: InputDecoration(
.enter_your_password hintText: _showHints[2]
: null, ? AppLocalizations.of(context)!
// _showHints[2] ? 'Enter your password' : null, .enter_your_password
prefixIconConstraints: const BoxConstraints( : null,
maxWidth: 25 + 16 + 10, // _showHints[2] ? 'Enter your password' : null,
maxHeight: 25 + (8 * 2), prefixIconConstraints: const BoxConstraints(
), maxWidth: 25 + 16 + 10,
prefixIcon: Padding( maxHeight: 25 + (8 * 2),
padding: const EdgeInsetsDirectional.only( ),
start: 16, prefixIcon: Padding(
end: 10, padding: const EdgeInsetsDirectional.only(
), start: 16,
child: Image.asset( end: 10,
MiscIconAssetPath.lock, ),
fit: BoxFit.fitHeight, child: Image.asset(
height: 25, MiscIconAssetPath.lock,
width: 25, fit: BoxFit.fitHeight,
color: height: 25,
MyTheme.topicColor(IndicatorTopic.economy) width: 25,
.shade300, color:
), MyTheme.topicColor(IndicatorTopic.economy)
), .shade300,
),
),
// prefixIcon: Icon( // prefixIcon: Icon(
// Icons.lock, // Icons.lock,
@ -736,47 +748,49 @@ class _RegisterScreenState extends State<RegisterScreen> {
width: 1), // Match the error color width: 1), // Match the error color
), ),
counterText: '', counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB)), hintStyle: TextStyle(color: Color(0xFFC3C6CB),
), fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16,
validator: _validatePassword, ),
maxLength: 40, ),
maxLengthEnforcement: MaxLengthEnforcement.enforced, validator: _validatePassword,
), maxLength: 40,
), maxLengthEnforcement: MaxLengthEnforcement.enforced,
SizedBox(height: 15), ),
Padding( ),
padding: const EdgeInsets.only( SizedBox(height: 15),
top: 5.0, bottom: 10, left: 30, right: 30), Padding(
child: TextFormField( padding: const EdgeInsets.only(
controller: _confirmpasswordController, top: 5.0, bottom: 10, left: 30, right: 30),
// focusNode: _focusNodes[3], child: TextFormField(
obscureText: _obscureConfirmPassword, controller: _confirmpasswordController,
decoration: InputDecoration( // focusNode: _focusNodes[3],
hintText: _showHints[3] obscureText: _obscureConfirmPassword,
? AppLocalizations.of(context)! decoration: InputDecoration(
.register_Confirm_password hintText: _showHints[3]
: null, ? AppLocalizations.of(context)!
// _showHints[3] ? 'Confirm password' : null, .register_Confirm_password
prefixIconConstraints: const BoxConstraints( : null,
maxWidth: 25 + 16 + 10, // _showHints[3] ? 'Confirm password' : null,
maxHeight: 25 + (8 * 2), prefixIconConstraints: const BoxConstraints(
), maxWidth: 25 + 16 + 10,
prefixIcon: Padding( maxHeight: 25 + (8 * 2),
padding: const EdgeInsetsDirectional.only( ),
start: 16, prefixIcon: Padding(
end: 10, padding: const EdgeInsetsDirectional.only(
), start: 16,
child: Image.asset( end: 10,
MiscIconAssetPath.lock, ),
fit: BoxFit.fitHeight, child: Image.asset(
height: 25, MiscIconAssetPath.lock,
width: 25, fit: BoxFit.fitHeight,
color: height: 25,
MyTheme.topicColor(IndicatorTopic.economy) width: 25,
.shade300, color:
), MyTheme.topicColor(IndicatorTopic.economy)
), .shade300,
),
),
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Image.asset( icon: Image.asset(
@ -784,217 +798,222 @@ class _RegisterScreenState extends State<RegisterScreen> {
? MiscIconAssetPath.visibilityOff ? MiscIconAssetPath.visibilityOff
: MiscIconAssetPath.visibleOn, : MiscIconAssetPath.visibleOn,
color: Color( color: Color(
0xFF9EA2A9), // Apply color if needed, but keep in mind `Image.asset` might not support color directly. 0xFF9EA2A9), // Apply color if needed, but keep in mind `Image.asset` might not support color directly.
width: 24, width: 24,
height: 24, height: 24,
), ),
onPressed: () { onPressed: () {
setState(() { setState(() {
_obscureConfirmPassword = _obscureConfirmPassword =
!_obscureConfirmPassword; !_obscureConfirmPassword;
}); });
}, },
), ),
// border: OutlineInputBorder( // border: OutlineInputBorder(
// borderSide: BorderSide(color: Colors.blue, width: 2), // Default border color // borderSide: BorderSide(color: Colors.blue, width: 2), // Default border color
// ), // ),
enabledBorder: OutlineInputBorder( enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: MyTheme.topicColor( color: MyTheme.topicColor(
IndicatorTopic.economy) IndicatorTopic.economy)
.shade400, .shade400,
width: 1), width: 1),
), ),
focusedBorder: OutlineInputBorder( focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Colors.deepPurple, color: Colors.deepPurple,
width: 2), // Focused border width: 2), // Focused border
), ),
errorBorder: OutlineInputBorder( errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Error border width: 1), // Error border
), ),
focusedErrorBorder: OutlineInputBorder( focusedErrorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10), borderRadius: BorderRadius.circular(10),
borderSide: BorderSide( borderSide: BorderSide(
color: Color(0xFFb22222), color: Color(0xFFb22222),
width: 1), // Match the error color width: 1), // Match the error color
), ),
counterText: '', counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB)), 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, TextSpan(
maxLength: 40, text: AppLocalizations.of(context)!
maxLengthEnforcement: MaxLengthEnforcement.enforced, .t_and),
inputFormatters: [ TextSpan(
LengthLimitingTextInputFormatter( text: AppLocalizations.of(context)!
64), // Limit to 40 characters .privacy_policy,
], style: TextStyle(
), fontWeight: FontWeight.bold,
), fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14,
SizedBox(height: 10), fontFamily: 'Roboto',
Padding( color: Color(0xFF985400),
padding: const EdgeInsets.only( decoration:
top: 1.0, bottom: 10, left: 25, right: 30), TextDecoration.underline,
child: Row( decorationColor: Color(0xFF648CBA),
mainAxisAlignment: MainAxisAlignment.start, decorationThickness: 1),
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)!
.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( Text(
AppLocalizations.of(context)!.account_confirmation, // "Register",
AppLocalizations.of(context)!
.register_title,
style: TextStyle( style: TextStyle(
fontSize: 14, color: Colors.grey[600]), fontSize: registerLocale?.languageCode == 'ar' ? 14 : 16,
color: Colors.white),
), ),
SizedBox(height: 15), SizedBox(width: 8),
Padding( const Icon(
padding: const EdgeInsets.only( Icons.chevron_right_outlined,
top: 5.0, bottom: 10, left: 30, right: 30), color: Colors
child: SizedBox( .white, // Set your desired color here
width: screenwidth / 1, )
child: ElevatedButton( ],
onPressed: () { ),
context.go('/'); ),
}, ),
style: ElevatedButton.styleFrom( ),
backgroundColor: Color( SizedBox(height: 15),
0xFF82AFCB), // Blueish color for Login Text(
shape: RoundedRectangleBorder( AppLocalizations.of(context)!.account_confirmation,
borderRadius: BorderRadius.circular(10), style: TextStyle(
), fontSize: registerLocale?.languageCode == 'ar' ? 12 : 14,
), color: Colors.grey[600]),
child: Row( ),
mainAxisSize: MainAxisSize.min, SizedBox(height: 15),
children: [ Padding(
Text( padding: const EdgeInsets.only(
AppLocalizations.of(context)!.login_title, top: 5.0, bottom: 10, left: 30, right: 30),
style: TextStyle( child: SizedBox(
fontSize: 16, color: Colors.white), width: screenwidth / 1,
), child: ElevatedButton(
SizedBox(width: 8), onPressed: () {
const Icon( context.go('/');
Icons.chevron_right_outlined, },
color: Colors style: ElevatedButton.styleFrom(
.white, // Set your desired color here 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( // child: GestureDetector(
// onTap: () { // onTap: () {

View File

@ -12,6 +12,7 @@ import 'package:pocketbase/pocketbase.dart';
import 'package:uae_stat/domain/use_cases/language.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/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: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 '../components/my_bottom_nav_bar.dart';
import 'auth_verification/changepassword.dart'; import 'auth_verification/changepassword.dart';
@ -353,7 +354,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
}, },
), ),
title: Text( title: Text(
'My Profile', AppLocalizations.of(context)!.my_profile,
style: TextStyle(color: Color(0xFF985400)), style: TextStyle(color: Color(0xFF985400)),
), ),
actions: [ actions: [
@ -447,7 +448,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Text( Text(
"User Name", AppLocalizations.of(context)!.register_name,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -473,7 +474,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Text( Text(
"Email ID", AppLocalizations.of(context)!.email_id,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
fontWeight: FontWeight.w500, fontWeight: FontWeight.w500,
@ -500,7 +501,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Text( Text(
"Full Name*", AppLocalizations.of(context)!.full_name,
style: TextStyle( style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w500), fontSize: 16, fontWeight: FontWeight.w500),
), ),
@ -541,7 +542,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Text( Text(
"Date of Birth*", AppLocalizations.of(context)!.dob,
style: TextStyle( style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w500), fontSize: 16, fontWeight: FontWeight.w500),
), ),
@ -583,7 +584,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
mainAxisAlignment: MainAxisAlignment.start, mainAxisAlignment: MainAxisAlignment.start,
children: [ children: [
Text( Text(
"Country/Region*", AppLocalizations.of(context)!.region,
style: TextStyle( style: TextStyle(
fontSize: 16, fontWeight: FontWeight.w500), fontSize: 16, fontWeight: FontWeight.w500),
), ),
@ -645,12 +646,15 @@ class _ProfileScreenState extends State<ProfileScreen> {
), ),
Text.rich( Text.rich(
TextSpan( TextSpan(
text: 'I agree to the ', text: AppLocalizations.of(
style: TextStyle(color: Colors.black), context)!
.agree, style: TextStyle(color: Colors.black),
children: [ children: [
TextSpan( TextSpan(
text: 'Terms & Conditions', text: AppLocalizations.of(
style: TextStyle( context,
)!
.terms_conditions, style: TextStyle(
color: Color(0xFF648CBA), color: Color(0xFF648CBA),
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
fontWeight: FontWeight fontWeight: FontWeight
@ -664,12 +668,14 @@ class _ProfileScreenState extends State<ProfileScreen> {
}, },
), ),
TextSpan( TextSpan(
text: ' and ', text: AppLocalizations.of(
style: TextStyle(color: Colors.black), context,
)!.t_and, style: TextStyle(color: Colors.black),
), ),
TextSpan( TextSpan(
text: 'Privacy Policy', text: AppLocalizations.of(
style: TextStyle( context,
)!.privacy_policy, style: TextStyle(
color: Color(0xFF648CBA), color: Color(0xFF648CBA),
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
fontWeight: FontWeight fontWeight: FontWeight
@ -683,7 +689,10 @@ class _ProfileScreenState extends State<ProfileScreen> {
}, },
), ),
TextSpan( TextSpan(
text: ' of FCSC.', text: AppLocalizations.of(
context,
)!
.conditions,
style: TextStyle(color: Colors.black), style: TextStyle(color: Colors.black),
), ),
], ],
@ -724,7 +733,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
context.go('/createNewPw/$userId/$email'); context.go('/createNewPw/$userId/$email');
}, },
child: Text( child: Text(
'Change Password', AppLocalizations.of(context)!
.change_password,
style: TextStyle( style: TextStyle(
color: Color(0xFF648CBA), color: Color(0xFF648CBA),
fontSize: 14, fontSize: 14,
@ -762,7 +772,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
MainAxisAlignment.center, // Center the content MainAxisAlignment.center, // Center the content
children: [ children: [
Text( Text(
'Save', AppLocalizations.of(context)!.save,
style: TextStyle(color: Colors.white), style: TextStyle(color: Colors.white),
), ),
SizedBox(width: 8), // Add space between text and icon SizedBox(width: 8), // Add space between text and icon

View File

@ -1,7 +1,10 @@
import 'dart:convert';
import 'package:external_repos/external_repos.dart'; import 'package:external_repos/external_repos.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.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:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shared_preferences/shared_preferences.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/my_bottom_nav_bar.dart';
import 'package:uae_stat/presentation/components/space.dart'; import 'package:uae_stat/presentation/components/space.dart';
import 'package:uae_stat/presentation/components/themed_text_field.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:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import '../../Screens/auth_verification/registration.dart'; import '../../Screens/auth_verification/registration.dart';
@ -28,13 +30,14 @@ import '../../components/my_toggle.dart';
class LoginRoute extends HookConsumerWidget { class LoginRoute extends HookConsumerWidget {
final pb = PocketBase('https://pb.venbait.in'); 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 _pb = PocketBase('http://127.0.0.1:8090');
// final bool isLoginScreen; // Pass `true` if this is the login screen // final bool isLoginScreen; // Pass `true` if this is the login screen
// LoginRoute({Key? key, required this.isLoginScreen}) : super(key: key); // LoginRoute({Key? key, required this.isLoginScreen}) : super(key: key);
LoginRoute({super.key}); LoginRoute({super.key});
dynamic userData; dynamic userData;
String? role; String? role;
int? loginCount;
static final formKey = GlobalKey<FormState>(); static final formKey = GlobalKey<FormState>();
@ -83,11 +86,41 @@ class LoginRoute extends HookConsumerWidget {
} }
} }
Future<void> saveUserId(String userId) async { Future<void> saveUserId(String userId, count) async {
print(count);
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
await prefs.setString('userId', userId); // Save userId locally await prefs.setString('userId', userId); // Save userId locally
await prefs.setString('login_count', count.toString());
} }
// Future<void> 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 @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final locale = ref.watch(localeProvider); final locale = ref.watch(localeProvider);
@ -112,7 +145,7 @@ class LoginRoute extends HookConsumerWidget {
'إعادة تعيين كلمة المرور', 'إعادة تعيين كلمة المرور',
), ),
style: TextStyle( style: TextStyle(
fontSize: 20, fontSize: locale?.languageCode == 'ar' ? 18 : 20,
color: Color(0xFF898C81), color: Color(0xFF898C81),
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
), ),
@ -127,7 +160,7 @@ class LoginRoute extends HookConsumerWidget {
'عنوان البريد الإلكتروني', 'عنوان البريد الإلكتروني',
), ),
labelStyle: TextStyle( labelStyle: TextStyle(
fontSize: 16, fontSize: locale?.languageCode == 'ar' ? 13 : 16,
color: Color(0xFF898C81), // For label text color color: Color(0xFF898C81), // For label text color
// fontWeight: FontWeight.w600, // 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( child: Text(
context.translate( context.translate(
'Forgot Password?', 'Forgot Password?',
@ -214,10 +254,10 @@ class LoginRoute extends HookConsumerWidget {
style: TextStyle( style: TextStyle(
fontFamily: context.translate( fontFamily: context.translate(
'Roboto', 'Roboto',
'NotoKufi', 'Roboto',
), ),
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
fontSize: 14, fontSize: locale?.languageCode == 'ar' ? 12 : 14,
color: Color(0xFF985400), color: Color(0xFF985400),
), ),
), ),
@ -305,6 +345,10 @@ class LoginRoute extends HookConsumerWidget {
if (response.statusCode == 200) { if (response.statusCode == 200) {
print("Login success API call successful: ${response.body}"); 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 { } else {
print( print(
"Failed to call login success API. Status code: ${response.statusCode}"); "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"); print("Error calling login success API: $e");
} }
await saveUserId(userId); await saveUserId(userId, loginCount);
} }
try { try {
final bool isProfileComplete = await profileStatus(userId); final bool isProfileComplete = await profileStatus(userId);
@ -374,9 +418,9 @@ class LoginRoute extends HookConsumerWidget {
TextStyle( TextStyle(
fontFamily: context.translate( fontFamily: context.translate(
'Roboto', 'Roboto',
'NotoKufi', 'Roboto',
), ),
fontSize: 16, fontSize: locale?.languageCode == 'ar' ? 14 : 16,
fontWeight: FontWeight.w600, fontWeight: FontWeight.w600,
), ),
), ),
@ -398,6 +442,14 @@ class LoginRoute extends HookConsumerWidget {
'Login', 'Login',
'تسجيل الدخول', 'تسجيل الدخول',
), ),
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'Roboto',
),
fontSize: locale?.languageCode == 'ar' ? 16: 18,
fontWeight: FontWeight.bold,
)
), ),
6.horizontalSpace, 6.horizontalSpace,
const Icon( const Icon(
@ -467,9 +519,9 @@ class LoginRoute extends HookConsumerWidget {
style: TextStyle( style: TextStyle(
fontFamily: context.translate( fontFamily: context.translate(
'Roboto', 'Roboto',
'NotoKufi', 'Roboto',
), ),
fontSize: 40, fontSize: locale?.languageCode == 'ar' ? 38 : 40,
fontWeight: FontWeight.w300, fontWeight: FontWeight.w300,
), ),
), ),
@ -483,7 +535,7 @@ class LoginRoute extends HookConsumerWidget {
style: TextStyle( style: TextStyle(
fontFamily: context.translate( fontFamily: context.translate(
'Roboto', 'Roboto',
'NotoKufi', 'Roboto',
), ),
fontSize: context.translate(18.0, 14.0), fontSize: context.translate(18.0, 14.0),
color: const Color(0xff898C81), color: const Color(0xff898C81),
@ -500,15 +552,15 @@ class LoginRoute extends HookConsumerWidget {
style: TextStyle( style: TextStyle(
fontFamily: context.translate( fontFamily: context.translate(
'Roboto', 'Roboto',
'NotoKufi', 'Roboto',
), ),
fontSize: 14, fontSize: locale?.languageCode == 'ar' ? 12 : 14,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
children: [ children: [
TextSpan( TextSpan(
text: context.translate( text: context.translate(
'Don\'t have an account? ', 'Don\'t have an account?',
'ليس لديك حساب؟', 'ليس لديك حساب؟',
), ),
style: const TextStyle( style: const TextStyle(
@ -591,16 +643,14 @@ class LoginRoute extends HookConsumerWidget {
height: 40, height: 40,
); );
final screenWidth = MediaQuery.of(context).size.width; final screenWidth = MediaQuery.of(context).size.width;
final listViewHorizontalPadding = final listViewHorizontalPadding =
screenWidth < 700 ? 30 : 30 + (screenWidth - 700) / 2; screenWidth < 700 ? 30 : 30 + (screenWidth - 700) / 2;
final scaffoldBody = ListView( final scaffoldBody = ListView(
// padding: EdgeInsets.symmetric( padding: EdgeInsets.symmetric(
// horizontal: listViewHorizontalPadding.toDouble(), horizontal: listViewHorizontalPadding.toDouble(),
// ), ),
children: [ children: [
10.verticalSpace, 3.verticalSpace,
Align( Align(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
child: MyToggle( child: MyToggle(
@ -614,36 +664,16 @@ class LoginRoute extends HookConsumerWidget {
}, },
), ),
), ),
16.verticalSpace, 36.verticalSpace,
Padding( helloAndPleaseLoginTexts,
padding: EdgeInsets.symmetric(
horizontal: listViewHorizontalPadding.toDouble(),
),
child: helloAndPleaseLoginTexts,
),
42.verticalSpace, 42.verticalSpace,
Padding( form,
padding: EdgeInsets.symmetric(
horizontal: listViewHorizontalPadding.toDouble(),
),
child: form,
),
15.verticalSpace, 15.verticalSpace,
Padding( dontHaveAnAccountRegisterBtn,
padding: EdgeInsets.symmetric(
horizontal: listViewHorizontalPadding.toDouble(),
),
child: dontHaveAnAccountRegisterBtn,
),
20.verticalSpace, 20.verticalSpace,
// continueAsGuestBtn, // continueAsGuestBtn,
95.verticalSpace, 95.verticalSpace,
Padding( fcscBanner,
padding: EdgeInsets.symmetric(
horizontal: listViewHorizontalPadding.toDouble(),
),
child: fcscBanner,
),
], ],
); );
// final bgScaffold = Scaffold( // final bgScaffold = Scaffold(

View File

@ -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<void> 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<bool> 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<String, dynamic>));
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<bool> 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<void> logoutUser() async {
pb.authStore.clear();
await clearSession();
}
// Clear session from local storage
Future<void> clearSession() async {
final prefs = await SharedPreferences.getInstance();
await prefs.remove('pb_auth');
await prefs.remove('pb_user');
await prefs.remove('pb_auth_time');
}
}

View File

@ -233,6 +233,7 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
print('render finished'); print('render finished');
_showHomeTour(); _showHomeTour();
} else { } else {
print('render delayed');
Future.delayed(Duration(milliseconds: 100), _starTourRender); Future.delayed(Duration(milliseconds: 100), _starTourRender);
} }
} }
@ -804,7 +805,19 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
super.initState(); super.initState();
final locale = ref.read(localeProvider); final locale = ref.read(localeProvider);
fetchData(locale?.languageCode ?? 'en'); fetchData(locale?.languageCode ?? 'en');
_fetchUserData(); // _fetchUserData();
_loadLoginCount();
}
Future<void> _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 // @override
@ -820,33 +833,35 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
return prefs.getString('userId'); // Retrieve the userId return prefs.getString('userId'); // Retrieve the userId
} }
Future<void> _fetchUserData() async { // Future<void> _fetchUserData() async {
try { // try {
final userId = await getUserId(); // final userId = await getUserId();
print('EDIT PROFILE isPageLoad'); // print('EDIT PROFILE isPageLoad');
final adminAuth = await _pb.admins // final adminAuth = await _pb.admins
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com'); // .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
final adminToken = adminAuth.token; // final adminToken = adminAuth.token;
print('adminToken- $adminToken'); // print('adminToken- $adminToken');
final userDetailsResponse = await _pb.collection('users').getOne( // final userDetailsResponse = await _pb.collection('users').getOne(
userId!, // userId!,
headers: { // headers: {
'Authorization': 'Bearer $adminToken', // 'Authorization': 'Bearer $adminToken',
}, // },
); // );
final loginCount = userDetailsResponse.data['login_count']; // final loginCount = userDetailsResponse.data['login_count'];
print(loginCount); // print(loginCount);
if (loginCount == 1) { // if (loginCount == 1) {
setState(() { // print('_starTourRender count 1');
WidgetsBinding.instance.addPostFrameCallback((_) { // setState(() {
_starTourRender(); // print('_starTourRender');
}); // WidgetsBinding.instance.addPostFrameCallback((_) {
}); // _starTourRender();
} // });
} catch (e) { // });
print('Error fetching user details: $e'); // }
} // } catch (e) {
} // print('Error fetching user details: $e');
// }
// }
Future<void> fetchData(locale) async { Future<void> fetchData(locale) async {
const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; const baseUrl = 'https://pb.venbait.in/api/getHomePageData';

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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/custom_drawer_routes.dart';
class BookMark extends ConsumerStatefulWidget { class BookMark extends ConsumerStatefulWidget {
const BookMark({super.key}); const BookMark({super.key});
@ -59,23 +59,29 @@ class _BookMarkState extends ConsumerState<BookMark> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final filteredList = dataList.where((item) => item['isBookmark'] == true) final filteredList =
.toList(); dataList.where((item) => item['isBookmark'] == true).toList();
return BaseScaffold( return PopScope(
title: Text('Bookmark'), onPopInvokedWithResult: (didPop, result) {
body: Padding( if (didPop) return;
padding: const EdgeInsets.all(8.0), context.go('/myhomepage');
child: GridView.builder( },
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount( child: BaseScaffold(
crossAxisCount: 2, // Two columns title: Text('Bookmark'),
crossAxisSpacing: 10.0, body: Padding(
mainAxisSpacing: 10.0, padding: const EdgeInsets.all(8.0),
mainAxisExtent: 100, 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<BookMark> {
debugPrint("Box clicked: ${data['title']}"); debugPrint("Box clicked: ${data['title']}");
}, },
child: Container( child: Container(
width: MediaQuery width: MediaQuery.of(context).size.width * 0.4,
.of(context)
.size
.width * 0.4,
height: 100, height: 100,
padding: EdgeInsets.all(8.0), padding: EdgeInsets.all(8.0),
decoration: BoxDecoration( decoration: BoxDecoration(
@ -131,14 +134,16 @@ class _BookMarkState extends ConsumerState<BookMark> {
setState(() { setState(() {
// Change isOpen to false when icon is clicked // Change isOpen to false when icon is clicked
int index = dataList.indexWhere( int index = dataList.indexWhere(
(item) => item['title'] == data['title'],); (item) => item['title'] == data['title'],
);
if (index != -1) { if (index != -1) {
dataList[index]['isBookmark'] = false; dataList[index]['isBookmark'] = false;
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text( content: Text(
'Removed From Bookmark', 'Removed From Bookmark',
style: TextStyle(color: Color(0xFF2F692C), style: TextStyle(
color: Color(0xFF2F692C),
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
), ),
backgroundColor: Color(0xFFD6E9C6), backgroundColor: Color(0xFFD6E9C6),
@ -150,7 +155,8 @@ class _BookMarkState extends ConsumerState<BookMark> {
SnackBar( SnackBar(
content: Text( content: Text(
'Failed to Remove', 'Failed to Remove',
style: TextStyle(color: Color(0xFFEB5F24), style: TextStyle(
color: Color(0xFFEB5F24),
fontWeight: FontWeight.w600), fontWeight: FontWeight.w600),
), ),
backgroundColor: Color(0xFF544C4C), backgroundColor: Color(0xFF544C4C),
@ -191,4 +197,4 @@ class _BookMarkState extends ConsumerState<BookMark> {
), ),
); );
} }
} }

View File

@ -8,6 +8,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:pocketbase/pocketbase.dart'; import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:uae_stat/domain/use_cases/language.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/infrastructure/services/packages/go_router.dart';
import 'package:uae_stat/presentation/components/my_drawer.dart'; import 'package:uae_stat/presentation/components/my_drawer.dart';
import 'package:mailer/mailer.dart'; import 'package:mailer/mailer.dart';
@ -28,7 +30,7 @@ class FeedbackForm extends StatefulWidget {
class _FeedbackFormState extends State<FeedbackForm> class _FeedbackFormState extends State<FeedbackForm>
with WidgetsBindingObserver { with WidgetsBindingObserver {
final _pb = final _pb =
PocketBase('https://pb.venbait.in'); // Initialize PocketBase client PocketBase('https://pb.venbait.in'); // Initialize PocketBase client
// final _pb = // final _pb =
// PocketBase('http://127.0.0.1:8090'); // Initialize PocketBase client // PocketBase('http://127.0.0.1:8090'); // Initialize PocketBase client
@ -46,32 +48,55 @@ class _FeedbackFormState extends State<FeedbackForm>
dynamic userId; dynamic userId;
List<Map<String, dynamic>> get _emojiOptions => [ List<Map<String, dynamic>> get _emojiOptions => [
{ {
"icon": Icons.sentiment_very_dissatisfied, // "icon": Icons.emoji_emotions_rounded,
"label": context.translate("Terrible", "سئ جدا"), // Translate here 'icon': Image.asset(
"value": 1, FeedBackAssetPath.disappointedfb,
}, width: 25,
{ height: 25,
"icon": Icons.sentiment_dissatisfied, ),
"label": context.translate("Bad", "سيء"), // Translate here "label": context.translate("Terrible", "سئ جدا"), // Translate here
"value": 2, "value": 1,
}, },
{ {
"icon": Icons.sentiment_neutral, // "icon": Icons.sentiment_dissatisfied,
"label": context.translate("Okay", "مقبول"), // Translate here 'icon': Image.asset(
"value": 3, FeedBackAssetPath.frowningfb,
}, width: 25,
{ height: 25,
"icon": Icons.sentiment_satisfied, ),
"label": context.translate("Good", "جيد"), // Translate here "label": context.translate("Bad", "سيء"), // Translate here
"value": 4, "value": 2,
}, },
{ {
"icon": Icons.sentiment_very_satisfied, 'icon': Image.asset(
"label": context.translate("Amazing", "مذهل"), // Translate here FeedBackAssetPath.neutralfb,
"value": 5, 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; static const int _characterLimit = 1200;
final RegExp _allowedCharacters = RegExp(r'^[a-zA-Z0-9 .,!?-]*$'); final RegExp _allowedCharacters = RegExp(r'^[a-zA-Z0-9 .,!?-]*$');
@ -208,38 +233,54 @@ class _FeedbackFormState extends State<FeedbackForm>
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return BaseScaffold( // final uri = Uri.parse(GoRouterState.of(context).uri.toString());
// title: Text("Feedback"), // final userName = uri.queryParameters['userName'] ?? 'Guest User';
title: Text(AppLocalizations.of(context)!.feedback_title),
// appBar: AppBar( final userName = GoRouterState.of(context).extra as String? ?? 'Guest User';
// backgroundColor: const Color(0xFFf8f9ff), return PopScope(
// title: Text(AppLocalizations.of(context)!.feedback_title), onPopInvokedWithResult: (didPop, result) {
// actions: [ if (didPop) return;
// Align( context.go('/myhomepage');
// alignment: AlignmentDirectional.topEnd, },
// child: LangToggle( child: BaseScaffold(
// onSaveFeedback: _saveFeedbackText, // title: Text("Feedback"),
// onLoadFeedback: _loadFeedbackText, title: Text(
// selectedEmojiIndex: _selectedEmojiIndex ?? 0, AppLocalizations.of(context)!.feedback_title,
// easeOfUseRating: _easeOfUseRating, style: TextStyle(
// qualityRating: _qualityRating, fontSize: 24,
// designRating: _designRating, fontFamily: 'Roboto',
// redundancyRating: _redundancyRating, fontWeight: FontWeight.w500),
// ), ),
// ), // appBar: AppBar(
// ], // backgroundColor: const Color(0xFFf8f9ff),
// ), // title: Text(AppLocalizations.of(context)!.feedback_title),
body: Padding( // actions: [
padding: const EdgeInsets.all(16.0), // Align(
child: SingleChildScrollView( // alignment: AlignmentDirectional.topEnd,
child: _isFeedbackSubmitted // child: LangToggle(
? _buildThankYouMessage() // onSaveFeedback: _saveFeedbackText,
: _isFeedbackFailed // onLoadFeedback: _loadFeedbackText,
? _buildFailureMessage() // selectedEmojiIndex: _selectedEmojiIndex ?? 0,
: _buildFeedbackForm(), // 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() { Widget _buildFeedbackForm() {
@ -260,26 +301,34 @@ class _FeedbackFormState extends State<FeedbackForm>
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
const SizedBox(height: 20), const SizedBox(height: 20),
Text( Center(
context.translate('How was your experience with us today?', child: FittedBox(
'كيف كانت تجربتك معنا اليوم؟'), fit: BoxFit
style: const TextStyle( .scaleDown, // This will make the text smaller to fit within the available space
fontSize: 18, child: Text(
fontFamily: 'Roboto', context.translate('How was your experience with us today?',
fontWeight: FontWeight.w400, 'كيف كانت تجربتك معنا اليوم؟'),
color: Color(0xFF898C81), style: const TextStyle(
fontSize: 18,
fontFamily: 'Roboto',
fontWeight: FontWeight.w400,
color: Color(0xff898C81),
),
),
), ),
), ),
const SizedBox(height: 10), const SizedBox(height: 15),
Container( Container(
width: double.infinity,
decoration: BoxDecoration( decoration: BoxDecoration(
border: Border.all( border: Border.all(
color: _isSmileySelected ? Colors.transparent : Colors.red, color:
_isSmileySelected ? Colors.transparent : Colors.transparent,
width: 1.5, width: 1.5,
), ),
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
), ),
padding: const EdgeInsets.all(8), padding: const EdgeInsets.all(0.0),
child: Column( child: Column(
children: [ children: [
Row( Row(
@ -287,6 +336,8 @@ class _FeedbackFormState extends State<FeedbackForm>
children: List.generate(_emojiOptions.length, (index) { children: List.generate(_emojiOptions.length, (index) {
return _buildEmojiButton( return _buildEmojiButton(
icon: _emojiOptions[index]["icon"], icon: _emojiOptions[index]["icon"],
// icon: _emojiOptions[index]["icon"],
label: _emojiOptions[index]["label"], label: _emojiOptions[index]["label"],
index: index, index: index,
); );
@ -300,28 +351,31 @@ class _FeedbackFormState extends State<FeedbackForm>
'Please rate your experience before submitting your feedback.', '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), const SizedBox(height: 15),
Text( FittedBox(
context.translate('How good did we do in these aspects?', fit: BoxFit
'ما مدى جودة أدائنا في هذه الجوانب؟'), .scaleDown, // This will make the text smaller to fit within the available space
style: const TextStyle( child: Text(
fontSize: 18, context.translate('How good did we do in these aspects?',
fontFamily: 'Roboto', 'ما مدى جودة أدائنا في هذه الجوانب؟'),
fontWeight: FontWeight.w400, style: const TextStyle(
color: Color(0xFF898C81), fontSize: 18,
), fontFamily: 'Roboto',
), fontWeight: FontWeight.w400,
const SizedBox(height: 20), color: Color(0xFF898C81),
),
)),
const SizedBox(height: 15),
_buildRatingRow( _buildRatingRow(
context.translate('Ease of use', 'سهولة الاستخدام'), context.translate('Ease of use', 'سهولة الاستخدام'),
_easeOfUseRating, _easeOfUseRating,
(rating) { (rating) {
setState(() { setState(() {
_easeOfUseRating = rating; _easeOfUseRating = rating;
}); });
@ -330,7 +384,7 @@ class _FeedbackFormState extends State<FeedbackForm>
_buildRatingRow( _buildRatingRow(
context.translate('Quality', 'الجودة'), context.translate('Quality', 'الجودة'),
_qualityRating, _qualityRating,
(rating) { (rating) {
setState(() { setState(() {
_qualityRating = rating; _qualityRating = rating;
}); });
@ -339,7 +393,7 @@ class _FeedbackFormState extends State<FeedbackForm>
_buildRatingRow( _buildRatingRow(
context.translate('Design', 'التصميم'), context.translate('Design', 'التصميم'),
_designRating, _designRating,
(rating) { (rating) {
setState(() { setState(() {
_designRating = rating; _designRating = rating;
}); });
@ -348,7 +402,7 @@ class _FeedbackFormState extends State<FeedbackForm>
_buildRatingRow( _buildRatingRow(
context.translate('Redundant', 'مكرر'), context.translate('Redundant', 'مكرر'),
_redundancyRating, _redundancyRating,
(rating) { (rating) {
setState(() { setState(() {
_redundancyRating = rating; _redundancyRating = rating;
}); });
@ -360,23 +414,43 @@ class _FeedbackFormState extends State<FeedbackForm>
minLines: 5, // Start with 5 lines minLines: 5, // Start with 5 lines
maxLines: null, // Allows the field to expand automatically maxLines: null, // Allows the field to expand automatically
maxLength: _characterLimit, maxLength: _characterLimit,
style: TextStyle(color: Color(0xFF898C81)),
decoration: InputDecoration( decoration: InputDecoration(
hintText: context.translate( hintText: context.translate(
'Tell us how we can improve', 'أخبرنا كيف يمكننا التحسين'), 'Tell us how we can improve', 'أخبرنا كيف يمكننا التحسين'),
hintStyle: TextStyle(color: Color(0xFF898C81)),
border: OutlineInputBorder( border: OutlineInputBorder(
borderSide: BorderSide( borderRadius: BorderRadius.circular(10.0),
color: _hasError ? Colors.red : Color(0xFF7296BE), 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: errorText:
_hasError ? _errorMessage : null, // Show error below field _hasError ? _errorMessage : null, // Show error below field
), ),
onChanged: (text) { onChanged: (text) {
// Trigger re-validation and character limit on each change // Trigger re-validation and character limit on each change
_handleTextChange(); _handleTextChange();
}, },
), ),
const SizedBox(height: 20), const SizedBox(height: 15),
Center( Center(
child: ElevatedButton( child: ElevatedButton(
onPressed: _submitFeedback, onPressed: _submitFeedback,
@ -416,7 +490,10 @@ class _FeedbackFormState extends State<FeedbackForm>
), ),
), ),
6.horizontalSpace, 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<FeedbackForm>
); );
} }
Widget _buildThankYouMessage() { Widget _buildThankYouMessage(String userName) {
double screenHeight = MediaQuery.of(context).size.height;
return Center( return Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ 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), const SizedBox(height: 20),
Text( Text(
"Thank You", // "Thank you",
'Thank you $userName !',
style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold), style: const TextStyle(fontSize: 24, fontWeight: FontWeight.bold),
), ),
const SizedBox(height: 10), const SizedBox(height: 15),
const Text( const Text(
"For your valuable feedback, we truly appreciate your input!", "For your valuable feedback, we truly \n appreciate your input!",
style: TextStyle(fontSize: 16), style: TextStyle(fontSize: 16, color: Color(0xFF898C81)),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
const SizedBox(height: 30), // const SizedBox(height: 30),
ElevatedButton( // ElevatedButton(
onPressed: () => context.go('/myhomepage'), // onPressed: () => context.go('/myhomepage'),
//context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), // //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
child: const Text("Go to Home"), // child: const Text("Go to Home"),
), // ),
], ],
), ),
); );
@ -456,68 +569,143 @@ class _FeedbackFormState extends State<FeedbackForm>
// New widget for failure message // New widget for failure message
Widget _buildFailureMessage() { Widget _buildFailureMessage() {
double screenHeight = MediaQuery.of(context).size.height;
double screenWidth = MediaQuery.of(context).size.width;
return Center( return Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: [ 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 SizedBox(height: 20),
const Text("Failed to Share Feedback", const Text(
style: TextStyle(fontSize: 24, fontWeight: FontWeight.bold)), "Failed to Share Feedback",
style: TextStyle(
fontSize: 24,
fontWeight: FontWeight.bold,
color: Color(0xFF414042)),
),
const SizedBox(height: 10), const SizedBox(height: 10),
Text(AppLocalizations.of(context)!.feedback_failed_msg, Text(AppLocalizations.of(context)!.feedback_failed_msg,
style: const TextStyle(fontSize: 16), style: const TextStyle(fontSize: 16, color: Color(0xFF898C81)),
textAlign: TextAlign.center), textAlign: TextAlign.center),
const SizedBox(height: 30), // const SizedBox(height: 30),
ElevatedButton( // ElevatedButton(
onPressed: () { // onPressed: () {
setState(() { // setState(() {
_isFeedbackFailed = false; // Reset failure state // _isFeedbackFailed = false; // Reset failure state
}); // });
}, // },
child: const Text("Retry"), // child: const Text("Retry"),
), // ),
], ],
), ),
); );
} }
Widget _buildEmojiButton({ Widget _buildEmojiButton({
required IconData icon, // required IconData icon,
required Widget icon,
required String label, required String label,
required int index, required int index,
}) { }) {
bool isSelected = _selectedEmojiIndex == index; bool isSelected = _selectedEmojiIndex == index;
return GestureDetector(
return Column( onTap: () {
children: [ setState(() {
IconButton( _selectedEmojiIndex = index;
icon: Icon(icon, size: 40), _isSmileySelected = true; // Hide error when a smiley is selected
color: isSelected ? Colors.green : Colors.amber, });
onPressed: () { },
setState(() { child: Container(
_selectedEmojiIndex = index; padding: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
_isSmileySelected = true; // Hide error when a smiley is selected decoration: BoxDecoration(
}); border: Border.all(
}, color: isSelected ? Color(0xFF8E8E8E) : Colors.transparent,
), width: 2,
Text(
label,
style: TextStyle(
fontWeight: FontWeight.w400,
color: isSelected ? Colors.green : Color(0xFF000000),
), ),
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( Widget _buildRatingRow(
String label, String label,
double rating, double rating,
Function(double) onRatingUpdate, Function(double) onRatingUpdate,
) { ) {
return Row( return Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
@ -535,10 +723,14 @@ class _FeedbackFormState extends State<FeedbackForm>
allowHalfRating: true, allowHalfRating: true,
itemCount: 5, itemCount: 5,
itemSize: 30, itemSize: 30,
itemBuilder: (context, _) => const Icon( itemBuilder: (context, index) => Icon(
Icons.star, index < rating ? Icons.star : Icons.star_border,
color: Colors.amber, color: Colors.amber,
), ),
// itemBuilder: (context, _) => const Icon(
// Icons.star,
// color: Colors.amber,
// ),
onRatingUpdate: onRatingUpdate, onRatingUpdate: onRatingUpdate,
unratedColor: Color(0xFF8E8E8E), unratedColor: Color(0xFF8E8E8E),
), ),
@ -573,7 +765,7 @@ class _FeedbackFormState extends State<FeedbackForm>
"design": _designRating, "design": _designRating,
"redundancy": _redundancyRating, "redundancy": _redundancyRating,
"emoji_rating": _emojiOptions[_selectedEmojiIndex!] "emoji_rating": _emojiOptions[_selectedEmojiIndex!]
["label"], // Emoji rating ["label"], // Emoji rating
"feedback": _feedbackController.text, "feedback": _feedbackController.text,
}; };
@ -783,7 +975,7 @@ class LangToggle extends ConsumerWidget {
ref.read(preferencesUseCaseProvider.notifier).updatePreferences( ref.read(preferencesUseCaseProvider.notifier).updatePreferences(
(prefs) => prefs.copyWith(language: languageAfter), (prefs) => prefs.copyWith(language: languageAfter),
); );
await onLoadFeedback(); // Reload feedback text after toggling language await onLoadFeedback(); // Reload feedback text after toggling language
}, },

View File

@ -1,4 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart'; import 'package:intl/intl.dart';
import 'package:pocketbase/pocketbase.dart'; import 'package:pocketbase/pocketbase.dart';
import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart'; import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart';
@ -224,135 +225,148 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final Map<String, String> statusOptions = { final Map<String, String> statusOptions = {
'Approved': AppLocalizations.of(context)!.approved, 'Approved': AppLocalizations.of(context)!.approved,
'Denied': AppLocalizations.of(context)!.denied, 'Denied': AppLocalizations.of(context)!.denied,
'Pending': AppLocalizations.of(context)!.pending, 'Pending': AppLocalizations.of(context)!.pending,
}; };
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
return BaseScaffold(
// title: Text("Manage User"), return PopScope(
title: Text( onPopInvokedWithResult: (didPop, result) {
AppLocalizations.of(context)!.manage_user, if (didPop) return;
), context.go('/myhomepage');
body: SingleChildScrollView( },
child: Padding( child: BaseScaffold(
padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 3.0), // title: Text("Manage User"),
child: Column( title: Text(
children: [ AppLocalizations.of(context)!.manage_user,
TextField( ),
decoration: InputDecoration( body: SingleChildScrollView(
prefixIcon: const Icon(Icons.search), child: Padding(
hintText: 'Search', padding: const EdgeInsets.only(left: 10.0, right: 10.0, top: 3.0),
border: OutlineInputBorder( child: Column(
borderRadius: BorderRadius.all(Radius.circular(20)), 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(
SizedBox(height: myheight / 40), scrollDirection: Axis.horizontal,
SingleChildScrollView( child: ConstrainedBox(
scrollDirection: Axis.horizontal, constraints: BoxConstraints(
child: ConstrainedBox( minWidth: MediaQuery.of(context).size.width,
constraints: BoxConstraints( ),
minWidth: MediaQuery.of(context).size.width, child: DataTable(
), sortColumnIndex: _sortColumnIndex,
child: DataTable( sortAscending: _isAscending,
sortColumnIndex: _sortColumnIndex, columns: [
sortAscending: _isAscending, DataColumn(
columns: [ label: Text(
DataColumn( AppLocalizations.of(context)!.user_name,
label: Text( ),
AppLocalizations.of(context)!.user_name, onSort: (columnIndex, ascending) {
_sort((user) => user.userName.toLowerCase(),
columnIndex, ascending);
},
), ),
onSort: (columnIndex, ascending) { DataColumn(
_sort((user) => user.userName.toLowerCase(), label: Text(
columnIndex, ascending); AppLocalizations.of(context)!.email_id,
}, ),
), onSort: (columnIndex, ascending) {
DataColumn( _sort((user) => user.emailId.toLowerCase(),
label: Text( AppLocalizations.of(context)!.email_id,), columnIndex, ascending);
onSort: (columnIndex, ascending) { },
_sort((user) => user.emailId.toLowerCase(), ),
columnIndex, ascending); DataColumn(
}, label: Text(
), AppLocalizations.of(context)!.reg_date,
DataColumn( ),
label: Text(AppLocalizations.of(context)!.reg_date,), onSort: (columnIndex, ascending) {
onSort: (columnIndex, ascending) { _sort(
_sort( (user) => DateFormat('dd/MM/yyyy')
(user) => DateFormat('dd/MM/yyyy') .parse(user.registrationDate),
.parse(user.registrationDate), columnIndex,
columnIndex, ascending,
ascending, );
); },
}, ),
), DataColumn(
DataColumn( label: Text(
label: Text(AppLocalizations.of(context)!.status,), AppLocalizations.of(context)!.status,
onSort: (columnIndex, ascending) { ),
_sort((user) => user.status.toLowerCase(), onSort: (columnIndex, ascending) {
columnIndex, ascending); _sort((user) => user.status.toLowerCase(),
}, columnIndex, ascending);
), },
], ),
rows: filteredUserData.isEmpty ],
? [ rows: filteredUserData.isEmpty
DataRow( ? [
cells: List<DataCell>.generate( DataRow(
4, // Ensure it matches the number of DataColumns cells: List<DataCell>.generate(
(index) => DataCell( 4, // Ensure it matches the number of DataColumns
index == 0 (index) => DataCell(
? Text( index == 0
'No results found', ? Text(
style: TextStyle( 'No results found',
fontStyle: FontStyle.italic), style: TextStyle(
) fontStyle: FontStyle.italic),
: const Text( )
''), // Empty cells for other columns : const Text(
placeholder: true, ''), // 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<String>(
value: user.status,
items: statusOptions.entries.map((status) {
return DropdownMenuItem<String>(
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(), : filteredUserData.map((user) {
return DataRow(
cells: [
DataCell(Text(user.userName)),
DataCell(Text(user.emailId)),
DataCell(Text(user.registrationDate)),
DataCell(
DropdownButton<String>(
value: user.status,
items:
statusOptions.entries.map((status) {
return DropdownMenuItem<String>(
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(),
),
), ),
), ),
), ],
], ),
), ),
), ),
), ),

View File

@ -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>[
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,
),
]),
),
);
}
}

View File

@ -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,
),
],
),
),
),
),
);
}
}

View File

@ -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>[
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,
),
],
),
),
),
),
);
}
}

View File

@ -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>[
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>[
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,
),
],
),
),
),
),
);
}
}

View File

@ -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>[
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>[
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>[
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>[
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>[
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>[
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>[
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>[
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,
),
],
),
),
),
),
);
}
}

View File

@ -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,
),
],
),
),
),
),
);
}
}

View File

@ -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>[
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,
),
],
),
),
),
),
);
}
}

View File

@ -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,
),
],
),
),
),
),
);
}
}

View File

@ -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,
),
],
),
),
),
),
);
}
}

View File

@ -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,
),
],
),
),
);
}
}

View File

@ -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<TextSpan> 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,
),
);
}
}

View File

@ -1,360 +1,410 @@
import 'package:flutter/material.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/custom_drawer_routes.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; class FAQPage extends StatefulWidget {
const FAQPage({super.key});
import '../../../../components/indicators/locale_provider.dart';
import '../../../../components/my_toggle.dart'; @override
State<FAQPage> createState() => _FAQPageState();
class FAQPage extends StatefulWidget { }
const FAQPage({super.key});
class _FAQPageState extends State<FAQPage> {
@override @override
State<FAQPage> createState() => _FAQPageState(); Widget build(BuildContext context) {
} return BaseScaffold(
dividerColor: Colors.grey[300],
class _FAQPageState extends State<FAQPage> { appbarColor: Colors.white,
@override bottomColor: Colors.white,
Widget build(BuildContext context) { mycenterTitle: true,
return Scaffold( title: Padding(
appBar: AppBar( padding: EdgeInsets.only(bottom: 8.0),
elevation: 3, child: Text(
shadowColor: Colors.black, ' FAQs',
title: Text('Key Features',), style: TextStyle(
leading: IconButton( fontSize: 22,
onPressed: (){ color: Color(0xFF7DAFBC),
context.go('/user-guide'); fontWeight: FontWeight.w500,
}, // fontWeight: FontWeight.w500,
color: Colors.black, ),
icon: const Icon(Icons.arrow_back_ios_new),), ),
actions: [ ),
Consumer( body: SafeArea(
builder: (context, ref, _) { child: Container(
final locale = ref.watch(localeProvider); // Current locale height: double.infinity,
return MyToggle( color: Colors.white,
isOn: locale?.languageCode == 'en', child: Scrollbar(
knobTextWhenOn: 'ع', thumbVisibility: true,
knobTextWhenOff: 'EN', thickness: 8,
pathColorWhenOn: Colors.grey.shade300, radius: Radius.circular(10),
pathColorWhenOff: Colors.grey.shade300, interactive: true,
onTap: () { child: SingleChildScrollView(
ref.read(localeProvider.notifier).toggleLocale(); child: QuestionAnswerScrollView(),
}, ),
); ),
}, ),
), ),
], );
}
), }
body: SafeArea(
child: Scrollbar( class QuestionAnswerScrollView extends StatelessWidget {
thumbVisibility: true, const QuestionAnswerScrollView({super.key});
thickness: 6,
radius: Radius.circular(10), @override
interactive: true, Widget build(BuildContext context) {
child:SingleChildScrollView( final List<Map<String, dynamic>> questionsAndAnswers = [
child: Column( {
crossAxisAlignment: CrossAxisAlignment.start, 'question': 'What is the purpose of this app?',
children: [ 'answer':
Container '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.'
( },
color: Colors.white, {
padding: const EdgeInsets.all(16.0), 'question': 'Do I need to create an account to use the app?',
width: MediaQuery.of(context).size.width, 'answer': RichText(
child: Text.rich( text: TextSpan(
TextSpan( children: [
text: 'Here are some common questions about the ', TextSpan(
style: TextStyle( text:
fontSize: 19, 'Yes, the app is strictly for registered and approved users. To access the data:\n\n',
fontWeight: FontWeight.w600, style: TextStyle(
color: Colors.grey, color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
), ),
children: [ TextSpan(
TextSpan( text:
text:' Federal Competitiveness and Statistics Centre (FCSC),', ' 1. You need to sign up using the Register Now option on the login screen.\n',
style: TextStyle( style: TextStyle(
fontSize: 19, color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
fontWeight: FontWeight.w600, ),
color: Colors.black87, TextSpan(
), text: ' 2. Your registration must be approved by the admin.\n',
), style: TextStyle(
TextSpan( color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
text: 'mobile application:', ),
style: TextStyle( TextSpan(
fontSize: 19, text:
fontWeight: FontWeight.w600, " 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 ",
color: Colors.grey, style: TextStyle(
), color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
), ),
], ],
), ),
), ),
), },
Container( {
padding: const EdgeInsets.all(0.0), 'question': 'How can I navigate through the app?',
color: Colors.grey[50], 'answer':
child: QuestionAnswerScrollView(), '• 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',
class QuestionAnswerScrollView extends StatelessWidget { style: TextStyle(
const QuestionAnswerScrollView({super.key}); color: Color(0xFF414042),
fontWeight: FontWeight.w500,
fontSize: 16),
),
@override TextSpan(
Widget build(BuildContext context) { text: ' GDP, growth rates, and economic trends\n',
final List<Map<String, dynamic>> questionsAndAnswers = [ style: TextStyle(
{'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.'}, color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
{'question':'Do I need to create an account to use the app?', 'answer':RichText( ),
text: TextSpan( TextSpan(
children: [ text: ' • Environment:',
TextSpan( style: TextStyle(
text: 'Yes, the app is strictly for registered and approved users. To access the data:\n\n', color: Color(0xFF414042),
style: TextStyle(fontWeight: FontWeight.normal, color: Colors.grey), fontWeight: FontWeight.w500,
), fontSize: 16),
TextSpan( ),
text: ' 1. You need to sign up using the Register Now option on the login screen.\n', TextSpan(
style: TextStyle(color: Colors.grey), text: ' Electricity production, water consumption, and more.\n',
), style: TextStyle(
TextSpan( color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
text: ' 2. Your registration must be approved by the admin.\n', ),
style: TextStyle(color: Colors.grey), TextSpan(
), text: ' • Social:',
style: TextStyle(
TextSpan( color: Color(0xFF414042),
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 ", fontWeight: FontWeight.w500,
style: TextStyle(color: Colors.grey), fontSize: 16),
), ),
], TextSpan(
), text:
),}, ' Labor force distribution, participation rates, and demographic data.\n',
{'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'}, style: TextStyle(
{'question':'What types of data are available?', 'answer':RichText( color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
text: TextSpan( ),
children: [ ],
TextSpan( ),
text: 'The app offers data on:\n\n', ),
style: TextStyle(color: Colors.grey), },
), {
TextSpan( 'question': 'How do I bookmark a metric?',
text: ' • Economy', 'answer': RichText(
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), text: TextSpan(
), children: [
TextSpan( TextSpan(
text: ' GDP, growth rates, and economic trends\n', text: 'When viewing a metric, tap on the',
style: TextStyle(color: Colors.grey), style: TextStyle(
), color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
),
TextSpan( TextSpan(
text: ' • Environment:', text: ' Bookmark ',
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), style: TextStyle(
), color: Color(0xFF414042),
TextSpan( fontWeight: FontWeight.w500,
text: ' Electricity production, water consumption, and more.\n', fontSize: 16),
style: TextStyle(color: Colors.grey), ),
), TextSpan(
TextSpan( text: 'icon. Your bookmarks are accessible from the',
text: ' • Social:', style: TextStyle(
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
), ),
TextSpan( TextSpan(
text: ' Labor force distribution, participation rates, and demographic data.\n', text: 'My Bookmarks',
style: TextStyle(color: Colors.grey), style: TextStyle(
), color: Color(0xFF414042),
], fontWeight: FontWeight.w500,
), fontSize: 16),
),}, ),
{'question':'How do I bookmark a metric?', 'answer': RichText( TextSpan(
text: TextSpan( text: 'section in the navigation bar.\n',
children: [ style: TextStyle(
TextSpan( color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
text: 'When viewing a metric, tap on the', ),
style: TextStyle(color: Colors.grey), ],
), ),
TextSpan( ),
text: ' Bookmark ', },
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), {
), 'question': 'Can I view the app in another language?',
TextSpan( 'answer': RichText(
text: 'icon. Your bookmarks are accessible from the', text: TextSpan(
style: TextStyle(color: Colors.grey), children: [
), TextSpan(
text: 'Yes, the app supports both ',
TextSpan( style: TextStyle(
text: 'My Bookmarks', color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), ),
), TextSpan(
TextSpan( text: 'English ',
text: 'section in the navigation bar.\n', style: TextStyle(
style: TextStyle(color: Colors.grey), color: Color(0xFF414042),
), fontWeight: FontWeight.w500,
], fontSize: 16),
), ),
),}, TextSpan(
{'question':'Can I view the app in another language?', 'answer': RichText( text: 'and',
text: TextSpan( style: TextStyle(
children: [ color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
TextSpan( ),
text: 'Yes, the app supports both ', TextSpan(
style: TextStyle(color: Colors.grey), text: ' Arabic ',
), style: TextStyle(
TextSpan( color: Color(0xFF414042),
text: 'English ', fontWeight: FontWeight.w500,
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), fontSize: 16),
), ),
TextSpan( TextSpan(
text: 'and', text:
style: TextStyle(color: Colors.grey), '. 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'),
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':'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?',
{'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'}, 'answer':
{'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'}, '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':'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( 'question': 'How often is the data updated?',
children: [ 'answer':
TextSpan( 'The app updates its datasets regularly to ensure users have access to the latest statistics. Notifications are sent whenever significant updates are made.\n'
text: 'Yes, you can share data or charts directly from the app by tapping the ', },
style: TextStyle(color: Colors.grey), {
), 'question': 'What types of graphs and charts are available?',
TextSpan( 'answer':
text: 'Share ', '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'
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), },
), {
TextSpan( 'question': 'Can I share the data or charts?',
text: 'button available on most pages.\n', 'answer': RichText(
style: TextStyle(color: Colors.grey), text: TextSpan(
), children: [
], TextSpan(
), text:
),}, 'Yes, you can share data or charts directly from the app by tapping the ',
{'question':'What should I do if I encounter an issue?','answer':RichText( style: TextStyle(
text: TextSpan( color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
children: [ ),
TextSpan( TextSpan(
text: 'For technical support or feedback, navigate to the ', text: 'Share ',
style: TextStyle(color: Colors.grey), style: TextStyle(
), color: Color(0xFF414042),
TextSpan( fontWeight: FontWeight.w500,
text: 'Help ', fontSize: 16),
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), ),
), TextSpan(
TextSpan( text: 'button available on most pages.\n',
text: 'section in the app and contact the support team.\n', style: TextStyle(
style: TextStyle(color: Colors.grey), color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
), ),
], ],
), ),
),}, ),
{'question':'How do I log out of the app?','answer':RichText( },
text: TextSpan( {
children: [ 'question': 'What should I do if I encounter an issue?',
TextSpan( 'answer': RichText(
text: 'Go to the ', text: TextSpan(
style: TextStyle(color: Colors.grey), children: [
), TextSpan(
TextSpan( text: 'For technical support or feedback, navigate to the ',
text: 'Profile ', style: TextStyle(
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
), ),
TextSpan( TextSpan(
text: 'section and tap the ', text: 'Help ',
style: TextStyle(color: Colors.grey), style: TextStyle(
), color: Color(0xFF414042),
TextSpan( fontWeight: FontWeight.w500,
text: 'Logout ', fontSize: 16),
style: TextStyle(color: Colors.black87,fontWeight: FontWeight.w500), ),
), TextSpan(
TextSpan( text: 'section in the app and contact the support team.\n',
text: 'option in the top-right corner.\n', style: TextStyle(
style: TextStyle(color: Colors.grey), ), color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
], ),
), ],
),}, ),
]; ),
},
return SingleChildScrollView( {
child: Column( 'question': 'How do I log out of the app?',
children: questionsAndAnswers.map((qa) => QuestionAnswerCard(qa: qa)).toList(), 'answer': RichText(
), text: TextSpan(
); children: [
} TextSpan(
} text: 'Go to the ',
style: TextStyle(
class QuestionAnswerCard extends StatefulWidget { // Use dynamic to accommodate RichText color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
),
const QuestionAnswerCard({super.key, required this.qa}); TextSpan(
final Map<String, dynamic> qa; text: 'Profile ',
style: TextStyle(
@override color: Color(0xFF414042),
_QuestionAnswerCardState createState() => _QuestionAnswerCardState(); fontWeight: FontWeight.w500,
} fontSize: 16),
),
class _QuestionAnswerCardState extends State<QuestionAnswerCard> { TextSpan(
bool isExpanded = false; text: 'section and tap the ',
style: TextStyle(
@override color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
Widget build(BuildContext context) { ),
return Card( TextSpan(
color: Colors.grey[50], text: 'Logout ',
elevation: 1, style: TextStyle(
shape: RoundedRectangleBorder( color: Color(0xFF414042),
borderRadius: BorderRadius.zero, // No rounding, it's a rectangle fontWeight: FontWeight.w500,
), fontSize: 16),
margin: EdgeInsets.symmetric(vertical: 0), ),
child: Column( TextSpan(
crossAxisAlignment: CrossAxisAlignment.start, text: 'option in the top-right corner.\n',
children: [ style: TextStyle(
ListTile( color: Colors.grey, fontSize: 16, fontFamily: 'Roboto'),
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: () { return SingleChildScrollView(
setState(() { child: Column(
isExpanded = !isExpanded; children: questionsAndAnswers
}); .map((qa) => QuestionAnswerCard(qa: qa))
}, .toList(),
), ),
if (isExpanded) );
Padding( }
padding: const EdgeInsets.symmetric(horizontal: 16.0), }
child: widget.qa['answer'] is RichText
? widget.qa['answer'] class QuestionAnswerCard extends StatefulWidget {
: Text( // Use dynamic to accommodate RichText
widget.qa['answer'] ?? '',
style: TextStyle(color: Colors.grey), const QuestionAnswerCard({super.key, required this.qa});
), final Map<String, dynamic> qa;
),
], @override
), _QuestionAnswerCardState createState() => _QuestionAnswerCardState();
); }
}
} class _QuestionAnswerCardState extends State<QuestionAnswerCard> {
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'),
),
),
],
),
);
}
}

View File

@ -1,595 +1,254 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.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/custom_drawer_routes.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/custom_text.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart';
import '../../../../components/indicators/locale_provider.dart'; class UsingFeatures extends StatelessWidget {
import '../../../../components/my_toggle.dart'; const UsingFeatures({super.key});
@override
Widget build(BuildContext context) {
class UsingFeatures extends StatelessWidget { final fcscBanner = Image.asset(
const UsingFeatures({super.key}); BannerAssetPath.fcsc,
height: 56,
alignment: Alignment.center,
@override );
Widget build(BuildContext context) { return BaseScaffold(
showDivider: true,
List<TextSpan> textSpans = [ dividerColor: Colors.grey[300],
CustomTextRich.createTextSpan('1.Data-Driven Insights:', bottomColor: Colors.white,
fontSize: 15, appbarColor: Colors.white,
color: Colors.black87, mycenterTitle: true,
fontWeight: FontWeight.bold, title: Padding(
height: 2, padding: EdgeInsets.only(bottom: 8.0),
), child: Text(
CustomTextRich.createTextSpan( 'Key Features',
'Access detailed datasets across categories such as Economy, Environment, Social, ', style: TextStyle(
fontSize: 13, color:Color(0xFF898C81), fontSize: 22,
fontWeight: FontWeight.normal , fontFamily: 'Roboto',
spacingTop: 1.9,), color: Color(0xFF7DAFBC),
fontWeight: FontWeight.w500,
CustomTextRich.createTextSpan( // fontWeight: FontWeight.w500,
' Economy, Environment, Social ', ),
fontSize: 13, color:Colors.black, ),
fontWeight: FontWeight.w600 , ),
), body: Container(
CustomTextRich.createTextSpan( width: double.infinity,
'and more.Explore statistics presented as smart metrics, graphs, and charts for better understanding.', color: Colors.white,
fontSize: 13, color:Color(0xFF898C81), child: Column(
fontWeight: FontWeight.normal , children: [
), Container(
decoration: BoxDecoration(
CustomTextRich.createTextSpan('\n2.Drilldown Navigation:', fontSize: 15, border: Border(
color: Colors.black87, bottom: BorderSide(
fontWeight: FontWeight.w600, color: Colors.grey.shade300,
height: 2 width: 0.5), // Grey bottom line
), ),
),
CustomTextRich.createTextSpan( child: ListTile(
'\nStart with high-level categories and drill down to specific KPIs and metrics for deeper insights.', onTap: () {
fontSize: 13, color:Color(0xFF898C81), context.push('/user-guide/features/appFeatures');
fontWeight: FontWeight.normal , },
), tileColor: Colors.white,
CustomTextRich.createTextSpan('\n3.Interactive Visualizations:', fontSize: 15, title: Text(
color: Colors.black87, 'App Features',
fontWeight: FontWeight.w600, style: TextStyle(
height: 2 fontSize: 16,
), color: Color(0xFF414042),
fontWeight: FontWeight.w500,
CustomTextRich.createTextSpan( fontFamily: 'Roboto',
'\nStart with high-level categories and drill down to specific KPIs and metrics for deeper insights.', ),
fontSize: 13, color:Color(0xFF898C81), ),
fontWeight: FontWeight.normal , trailing: Icon(Icons.keyboard_arrow_right),
), ),
CustomTextRich.createTextSpan( ),
'View trends and relationships with interactive graphs and charts, including bar graphs, line charts, and more.', Container(
fontSize: 14.0, decoration: BoxDecoration(
color: Color(0xFF898C81), border: Border(
fontWeight: FontWeight.normal, bottom: BorderSide(
), color: Colors.grey.shade300,
CustomTextRich.createTextSpan( width: 0.5), // Grey bottom line
'\n4.Secure User Access:', ),
fontSize: 14.0, ),
color: Colors.black87, child: ListTile(
fontWeight: FontWeight.bold, onTap: () {
height: 2, context.push('/user-guide/features/whoUseApp');
), },
CustomTextRich.createTextSpan( // tileColor: Colors.white,
'\nAvailable only to registered users whose accounts have been approved by an admin. Login ensures secure access to sensitive statistical information.', title: Text(
fontSize: 14.0, 'Who can use The App',
color: Color(0xFF898C81), style: TextStyle(
fontWeight: FontWeight.normal, fontSize: 16,
), color: Color(0xFF414042),
CustomTextRich.createTextSpan( fontWeight: FontWeight.w500,
'\n5.Profile Customization:', fontFamily: 'Roboto',
fontSize: 14.0, ),
color: Color(0xFF414042), ),
fontWeight: FontWeight.bold, trailing: Icon(Icons.keyboard_arrow_right),
height: 2 shape: Border(
), bottom: BorderSide(
CustomTextRich.createTextSpan( color: Colors.black, width: 3), // Grey bottom line
'\nUpdate your profile details, such as name, password, and region, to personalize your experience.', ),
fontSize: 14.0, ),
color: Color(0xFF898C81), ),
fontWeight: FontWeight.normal, Container(
), decoration: BoxDecoration(
CustomTextRich.createTextSpan( border: Border(
'\n6.Bookmark:', bottom: BorderSide(
fontSize: 14.0, color: Colors.grey.shade300,
color: Color(0xFF414042), width: 0.5), // Grey bottom line
fontWeight: FontWeight.bold, ),
), ),
CustomTextRich.createTextSpan( child: ListTile(
'\nSave frequently accessed metrics and datasets for quick reference via the Bookmarks section.', onTap: () {
fontSize: 14.0, context.push('/user-guide/features/purpose');
color: Color(0xFF898C81), },
fontWeight: FontWeight.normal, // tileColor: Colors.white,
), title: Text(
CustomTextRich.createTextSpan( 'Purpose of the App ?',
'\n7.Bilingual Support:', style: TextStyle(
fontSize: 14.0, fontSize: 16,
color: Color(0xFF414042), color: Color(0xFF414042),
fontWeight: FontWeight.bold, fontWeight: FontWeight.w500,
height: 2 fontFamily: 'Roboto',
), ),
CustomTextRich.createTextSpan( ),
'\nToggle between English and Arabic for ease of use.', trailing: Icon(Icons.keyboard_arrow_right),
fontSize: 14.0, shape: Border(
color: Color(0xFF898C81), bottom: BorderSide(
fontWeight: FontWeight.normal, color: Colors.black, width: 3), // Grey bottom line
), ),
CustomTextRich.createTextSpan( ),
'\nWho Can Use the App?', ),
fontSize: 18.0, Container(
color: Color(0xFF414042), decoration: BoxDecoration(
fontWeight: FontWeight.w600, border: Border(
height: 2.5 bottom: BorderSide(
), color: Colors.grey.shade300,
CustomTextRich.createTextSpan( width: 0.5), // Grey bottom line
'\nThis app is intended for:', ),
fontSize: 14.0, ),
color: Color(0xFF898C81), child: ListTile(
fontWeight: FontWeight.normal, onTap: () {
), context.push('/user-guide/features/howUseApp');
CustomTextRich.createTextSpan( },
'\n\n • Government officials requiring UAE statistics for decision-making.', // tileColor: Colors.white,
fontSize: 14.0, title: Text(
color: Color(0xFF898C81), 'How to Use the App',
fontWeight: FontWeight.normal, style: TextStyle(
), fontSize: 16,
CustomTextRich.createTextSpan( color: Color(0xFF414042),
'\n •Business professionals and researchers analyzing market trends.', fontWeight: FontWeight.w500,
fontSize: 14.0, fontFamily: 'Roboto',
color: Color(0xFF898C81), ),
fontWeight: FontWeight.normal, ),
), trailing: Icon(Icons.keyboard_arrow_right),
CustomTextRich.createTextSpan( shape: Border(
'\n •Students and educators needing reliable data for study and teaching.\n\n', bottom: BorderSide(
fontSize: 14.0, color: Colors.black, width: 3), // Grey bottom line
color: Color(0xFF898C81), ),
fontWeight: FontWeight.normal, ),
), ),
CustomTextRich.createTextSpan( Container(
'Purpose of the App\n', decoration: BoxDecoration(
fontSize: 16.0, border: Border(
color: Color(0xFF414042), bottom: BorderSide(
fontWeight: FontWeight.w600, color: Colors.grey.shade300,
height: 2.0 width: 0.5), // Grey bottom line
), ),
CustomTextRich.createTextSpan( ),
' • Provide official statistics on the UAE in an accessible format.', child: ListTile(
fontSize: 14.0, onTap: () {
color: Color(0xFF898C81), context.push('/user-guide/features/stayUpdated');
fontWeight: FontWeight.normal, },
), // tileColor: Colors.white,
CustomTextRich.createTextSpan( title: Text(
'\n • Support decision-making and research with reliable, up-to-date data.', 'Stay Updated',
fontSize: 14.0, style: TextStyle(
color: Color(0xFF898C81), fontSize: 16,
fontWeight: FontWeight.normal, color: Color(0xFF414042),
), fontWeight: FontWeight.w500,
CustomTextRich.createTextSpan( fontFamily: 'Roboto',
'\n • Enable users to interact with data visually through graphs and metrics.', ),
fontSize: 14.0, ),
color: Color(0xFF898C81), trailing: Icon(Icons.keyboard_arrow_right),
fontWeight: FontWeight.normal, shape: Border(
), bottom: BorderSide(
CustomTextRich.createTextSpan( color: Colors.black, width: 3), // Grey bottom line
'\nHow to Use the App', ),
fontSize: 18.0, ),
color: Color(0xFF414042), ),
fontWeight: FontWeight.w600, Container(
height: 2.3 decoration: BoxDecoration(
), border: Border(
CustomTextRich.createTextSpan( bottom: BorderSide(
'\n1.Registration and Approval:', color: Colors.grey.shade300,
fontSize: 15.0, width: 0.5), // Grey bottom line
color: Colors.black87, ),
fontWeight: FontWeight.bold, ),
height: 2.0 child: ListTile(
), onTap: () {
CustomTextRich.createTextSpan( context.push('/user-guide/features/changeMyPassword');
'\nSign up for the app and wait for admin approval.', },
fontSize: 14.0, // tileColor: Colors.white,
color: Color(0xFF898C81), title: Text(
fontWeight: FontWeight.normal, 'How to Change My Password',
), style: TextStyle(
CustomTextRich.createTextSpan( fontSize: 16,
'\n2.Login and Navigation:', color: Color(0xFF414042),
fontSize: 15.0, fontWeight: FontWeight.w500,
color: Color(0xFF414042), fontFamily: 'Roboto',
fontWeight: FontWeight.bold, ),
height: 2.0, ),
), trailing: Icon(Icons.keyboard_arrow_right),
CustomTextRich.createTextSpan( shape: Border(
'\nOnce approved, log in to access the app. Navigate through the categories on the home screen.', bottom: BorderSide(
fontSize: 14.0, color: Colors.black, width: 3), // Grey bottom line
color: Color(0xFF898C81), ),
fontWeight: FontWeight.normal, ),
), ),
CustomTextRich.createTextSpan( Container(
'\n3.Access Data:', decoration: BoxDecoration(
fontSize: 15.0, border: Border(
color: Color(0xFF414042), bottom: BorderSide(
fontWeight: FontWeight.bold, color: Colors.grey.shade300,
height: 2.0, width: 0.5), // Grey bottom line
), ),
CustomTextRich.createTextSpan( ),
'\nDrill down into specific categories like "Economy" or "Environment" to view detailed KPIs and visual insights.', child: ListTile(
fontSize: 14.0, onTap: () {
color: Color(0xFF898C81), context.push('/user-guide/features/editMyProfile');
fontWeight: FontWeight.normal, },
), // tileColor: Colors.white,
CustomTextRich.createTextSpan( title: Text(
'\n4.Bookmark Metrics:', 'How to Edit My Profile',
fontSize: 15.0, style: TextStyle(
color: Color(0xFF414042), fontSize: 16,
fontWeight: FontWeight.bold, color: Color(0xFF414042),
height: 2.0, fontWeight: FontWeight.w500,
), fontFamily: 'Roboto',
CustomTextRich.createTextSpan( ),
'\nSave important statistics for easy reference.', ),
fontSize: 14.0, trailing: Icon(Icons.keyboard_arrow_right),
color: Color(0xFF898C81), shape: Border(
fontWeight: FontWeight.normal, bottom: BorderSide(
), color: Colors.black, width: 3), // Grey bottom line
CustomTextRich.createTextSpan( ),
'\nStay Updated', ),
fontSize: 18.0, ),
color: Color(0xFF414042), Spacer(),
fontWeight: FontWeight.w600, Align(
height: 3, alignment: Alignment.bottomCenter,
), child: fcscBanner,
CustomTextRich.createTextSpan( ),
'\nThe app is regularly updated with the latest datasets and features to ensure users have access to the most current information.', SizedBox(
fontSize: 14.0, height: 30,
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,
),
),
],
),
)
),
),
);
}
}

View File

@ -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<TextSpan> 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,
),
),
],
),
],
),
),
),
),
);
}
}

View File

@ -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<UserGuide> createState() => _UserGuideState();
}
class _UserGuideState extends State<UserGuide> {
@override
Widget build(BuildContext context) {
List<Widget> createRows(List<List<Map<String, dynamic>>> 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,
),
),
],
),
),
);
}
}

View File

@ -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<Userguide> createState() => _UserguideState();
}
class _UserguideState extends State<Userguide> {
final List<Map<String, dynamic>> 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<HoverContainer> {
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,
),
),
],
);
})
),
),
);
}
}

View File

@ -4,12 +4,15 @@ import 'dart:convert';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.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:go_router/go_router.dart';
import 'package:package_info_plus/package_info_plus.dart'; import 'package:package_info_plus/package_info_plus.dart';
import 'package:pocketbase/pocketbase.dart'; import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.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/bottom_bar_asset_icon_path.dart';
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/drawer_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.body,
required this.title, required this.title,
this.actions, this.actions,
this.showDivider = false,
this.dividerColor,
this.showBackButton = false, this.showBackButton = false,
this.mycenterTitle = false, this.mycenterTitle = false,
this.appbarColor, this.appbarColor,
this.mytitleColor, this.mytitleColor,
this.bottomColor = null,
}); });
final Widget body; final Widget body;
final Widget title; final Widget title;
final bool? showBackButton; final Color? dividerColor;
final bool showDivider;
final bool showBackButton;
final bool? mycenterTitle; final bool? mycenterTitle;
final List<Widget>? actions; final List<Widget>? actions;
final Color? bottomColor;
final Color? appbarColor, mytitleColor; final Color? appbarColor, mytitleColor;
@override @override
@ -63,6 +72,8 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
final GlobalKey drawerKey = GlobalKey(); final GlobalKey drawerKey = GlobalKey();
late double toggleHeight = 0; late double toggleHeight = 0;
bool isLoggedOut = false; bool isLoggedOut = false;
final FlutterSecureStorage _secureStorage = const FlutterSecureStorage();
static final _repo = getIt.call<TAuthRepo>();
@override @override
void initState() { void initState() {
@ -145,7 +156,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
Align( Align(
alignment: Alignment.bottomRight, alignment: Alignment.bottomRight,
child: Padding( child: Padding(
padding: const EdgeInsets.only(right:10.0), padding: const EdgeInsets.only(right: 10.0),
child: Text( child: Text(
'5/7', '5/7',
style: const TextStyle( style: const TextStyle(
@ -195,9 +206,10 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
.state = true; .state = true;
ref ref
.read(previousChartsTourProvider .read(previousChartsTourProvider
.notifier) .notifier)
.state = false; .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<BaseScaffold> {
children: [ children: [
Align( Align(
alignment: Alignment.bottomRight, alignment: Alignment.bottomRight,
child:Padding( child: Padding(
padding: const EdgeInsets.only(right:10.0), padding: const EdgeInsets.only(right: 10.0),
child: Text( child: Text(
'6/7', '6/7',
style: const TextStyle( style: const TextStyle(
@ -335,8 +347,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
), ),
TargetContent( TargetContent(
padding: EdgeInsets.only( padding: EdgeInsets.only(right: screenWidth * 0.7, top: 30),
right: screenWidth * 0.7, top: 30),
align: ContentAlign.right, align: ContentAlign.right,
child: Container( child: Container(
width: 200, width: 200,
@ -393,8 +404,8 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
children: [ children: [
Align( Align(
alignment: Alignment.bottomRight, alignment: Alignment.bottomRight,
child:Padding( child: Padding(
padding: const EdgeInsets.only(right:10.0), padding: const EdgeInsets.only(right: 10.0),
child: Text( child: Text(
'7/7', '7/7',
style: const TextStyle( style: const TextStyle(
@ -451,10 +462,10 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
.state = true; .state = true;
ref ref
.read( .read(
previousChartsTourProvider.notifier) previousChartsTourProvider.notifier)
.state = true; .state = true;
ref.read(homeTourProvider.notifier).state = ref.read(homeTourProvider.notifier).state =
true; true;
ref ref
.read(previousHomeTourProvider.notifier) .read(previousHomeTourProvider.notifier)
.state = true; .state = true;
@ -463,7 +474,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
.state = true; .state = true;
ref ref
.read(previousScaffoldTourProvider .read(previousScaffoldTourProvider
.notifier) .notifier)
.state = true; .state = true;
tutorialCoachMark.finish(); tutorialCoachMark.finish();
}, },
@ -496,7 +507,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
TargetContent( TargetContent(
padding: padding:
EdgeInsets.only(left: screenWidth * 0.7, top: toggleHeight), EdgeInsets.only(left: screenWidth * 0.7, top: toggleHeight),
align: ContentAlign.left, align: ContentAlign.left,
child: Container( child: Container(
width: 200, width: 200,
@ -593,8 +604,13 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
// setState(() { // setState(() {
// isLoggedOut = true; // isLoggedOut = true;
// }); // });
// prefs.clear();
await _repo.logout();
// state = const AsyncData(null);
// _pb.authStore.clear();
// await _secureStorage.delete(key: "FlutterSecureStorage.session");
prefs.clear(); prefs.clear();
context.go('/'); context.go('/login');
} }
@override @override
@ -606,9 +622,20 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
return Scaffold( return Scaffold(
backgroundColor: Colors.white,
appBar: AppBar( appBar: AppBar(
title: widget.title, 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 ?? actions: widget.actions ??
[ [
// IconButton( // IconButton(
@ -646,10 +673,8 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
builder: (BuildContext context) { builder: (BuildContext context) {
return IconButton( return IconButton(
key: drawerKey, key: drawerKey,
color: (widget.showBackButton == true) color: Colors.black,
? Colors.white icon: const Icon(Icons.menu, size: 30),
: Colors.black,
icon: const Icon(Icons.menu),
onPressed: () { onPressed: () {
Scaffold.of(context).openDrawer(); Scaffold.of(context).openDrawer();
}, },
@ -737,37 +762,37 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
ListTile( ListTile(
leading: Image.asset( leading: Image.asset(
DrawerAssetIconPath.feedback, DrawerAssetIconPath.feedback,
color: Colors.black , color: Colors.black,
width: 20, width: 20,
height: 20, height: 20,
), ),
// title: const Text('Feedback'), // title: const Text('Feedback'),
title: Text(AppLocalizations.of(context)!.feedback_title), title: Text(AppLocalizations.of(context)!.feedback_title),
onTap: () => context.go('/feedback'), onTap: () => context.go('/feedback', extra: userName),
), ),
if (role == 'admin') if (role == 'admin')
ListTile( ListTile(
leading: Image.asset( leading: Image.asset(
DrawerAssetIconPath.manageUser, DrawerAssetIconPath.manageUser,
color: Colors.black , color: Colors.black,
width: 20, width: 20,
height: 20, height: 20,
), ),
// title: Text('Manage User'), // title: Text('Manage User'),
title: Text( title: Text(
AppLocalizations.of(context)!.manage_user, AppLocalizations.of(context)!.manage_user,
), ),
onTap: () => context.go('/manageuser'), onTap: () => context.go('/manageuser'),
), ),
ListTile( ListTile(
leading: Icon(Icons.collections_bookmark_rounded), leading: Icon(Icons.bookmarks_outlined),
title: const Text('Bookmark'), title: const Text('Bookmark'),
onTap: () => context.go('/bookmark'), onTap: () => context.go('/bookmark'),
), ),
ListTile( ListTile(
leading: Image.asset( leading: Image.asset(
DrawerAssetIconPath.guide, DrawerAssetIconPath.guide,
color: Colors.black , color: Colors.black,
width: 20, width: 20,
height: 20, height: 20,
), ),
@ -828,57 +853,74 @@ leading: Image.asset(
), ),
])), ])),
bottomNavigationBar: BottomNavigationBar( bottomNavigationBar: BottomNavigationBar(
backgroundColor: Colors.white,
currentIndex: _getSelectedIndex(currentRoute), currentIndex: _getSelectedIndex(currentRoute),
onTap: (index) => _onItemTapped(context, index), onTap: (index) => _onItemTapped(context, index),
type: BottomNavigationBarType.fixed, type: BottomNavigationBarType.fixed,
items: [ items: [
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Padding( icon: Padding(
padding: const EdgeInsets.only(bottom: 4), // Adjust this for spacing padding:
child: Image.asset( const EdgeInsets.only(bottom: 4), // Adjust this for spacing
BottomBarAssetIconPath.home, child: Image.asset(
color: _getSelectedIndex(currentRoute) == 0 ? Colors.black : Color(0xFF989898), BottomBarAssetIconPath.home,
width: 20, color: _getSelectedIndex(currentRoute) == 0
height: 20, ? Colors.black
),), : Color(0xFF989898),
width: 20,
height: 20,
),
),
// label: 'Home', // label: 'Home',
label: AppLocalizations.of(context)!.nav_home, label: AppLocalizations.of(context)!.nav_home,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
// icon: Icon(Icons.map), // icon: Icon(Icons.map),
icon:Padding( icon: Padding(
padding: const EdgeInsets.only(bottom: 4), // Adjust this for spacing padding:
child: Image.asset( const EdgeInsets.only(bottom: 4), // Adjust this for spacing
BottomBarAssetIconPath.uaeMap, child: Image.asset(
color: _getSelectedIndex(currentRoute) == 1 ? Colors.black : Color(0xFF989898), BottomBarAssetIconPath.uaeMap,
width: 20, color: _getSelectedIndex(currentRoute) == 1
height: 20, ? Colors.black
),), : Color(0xFF989898),
width: 20,
height: 20,
),
),
// label: 'UAE Numbers' // label: 'UAE Numbers'
label: AppLocalizations.of(context)!.nav_uae, label: AppLocalizations.of(context)!.nav_uae,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Padding( icon: Padding(
padding: const EdgeInsets.only(bottom: 4), // Adjust this for spacing padding:
child: Image.asset( const EdgeInsets.only(bottom: 4), // Adjust this for spacing
BottomBarAssetIconPath.ranking, child: Image.asset(
color: _getSelectedIndex(currentRoute) == 2 ? Colors.black : Color(0xFF989898), BottomBarAssetIconPath.ranking,
width: 20, color: _getSelectedIndex(currentRoute) == 2
height: 20, ? Colors.black
),), : Color(0xFF989898),
// label: 'Competitiveness', width: 20,
height: 20,
),
),
// label: 'Competitiveness',
label: AppLocalizations.of(context)!.nav_competitiveness, label: AppLocalizations.of(context)!.nav_competitiveness,
), ),
BottomNavigationBarItem( BottomNavigationBarItem(
icon: Padding( icon: Padding(
padding: const EdgeInsets.only(bottom: 4), // Adjust this for spacing padding:
child: Image.asset( const EdgeInsets.only(bottom: 4), // Adjust this for spacing
BottomBarAssetIconPath.globe, child: Image.asset(
color: _getSelectedIndex(currentRoute) == 2 ? Colors.black : Color(0xFF989898), BottomBarAssetIconPath.globe,
width: 20, color: _getSelectedIndex(currentRoute) == 2
height: 20, ? Colors.black
),), : Color(0xFF989898),
// label: 'Country Profile', width: 20,
height: 20,
),
),
// label: 'Country Profile',
label: AppLocalizations.of(context)!.country_profile, label: AppLocalizations.of(context)!.country_profile,
), ),
], ],

View File

@ -26,5 +26,5 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin"))
UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin"))
FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin")) FVPVideoPlayerPlugin.register(with: registry.registrar(forPlugin: "FVPVideoPlayerPlugin"))
WebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "WebViewFlutterPlugin")) FLTWebViewFlutterPlugin.register(with: registry.registrar(forPlugin: "FLTWebViewFlutterPlugin"))
} }

View File

@ -5,10 +5,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _fe_analyzer_shared name: _fe_analyzer_shared
sha256: "88399e291da5f7e889359681a8f64b18c5123e03576b01f32a6a276611e511c3" sha256: "16e298750b6d0af7ce8a3ba7c18c69c3785d11b15ec83f6dcd0ad2a0009b3cab"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "78.0.0" version: "76.0.0"
_macros: _macros:
dependency: transitive dependency: transitive
description: dart description: dart
@ -18,18 +18,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: analyzer name: analyzer
sha256: "62899ef43d0b962b056ed2ebac6b47ec76ffd003d5f7c4e4dc870afe63188e33" sha256: "1f14db053a8c23e260789e9b0980fa27f2680dd640932cae5e1137cce0e46e1e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "7.1.0" version: "6.11.0"
analyzer_plugin: analyzer_plugin:
dependency: transitive dependency: transitive
description: description:
name: analyzer_plugin name: analyzer_plugin
sha256: "1d460d14e3c2ae36dc2b32cef847c4479198cf87704f63c3c3c8150ee50c3916" sha256: "9661b30b13a685efaee9f02e5d01ed9f2b423bd889d28a304d02d704aee69161"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.12.0" version: "0.11.3"
ansicolor: ansicolor:
dependency: transitive dependency: transitive
description: description:
@ -74,50 +74,50 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: build name: build
sha256: cef23f1eda9b57566c81e2133d196f8e3df48f244b317368d65c5943d91148f0 sha256: "80184af8b6cb3e5c1c4ec6d8544d27711700bc3e6d2efad04238c7b5290889f0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.2" version: "2.4.1"
build_config: build_config:
dependency: transitive dependency: transitive
description: description:
name: build_config name: build_config
sha256: "4ae2de3e1e67ea270081eaee972e1bd8f027d459f249e0f1186730784c2e7e33" sha256: bf80fcfb46a29945b423bd9aad884590fb1dc69b330a4d4700cac476af1708d1
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.1.2" version: "1.1.1"
build_daemon: build_daemon:
dependency: transitive dependency: transitive
description: description:
name: build_daemon name: build_daemon
sha256: "294a2edaf4814a378725bfe6358210196f5ea37af89ecd81bfa32960113d4948" sha256: "79b2aef6ac2ed00046867ed354c88778c9c0f029df8a20fe10b5436826721ef9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.3" version: "4.0.2"
build_resolvers: build_resolvers:
dependency: transitive dependency: transitive
description: description:
name: build_resolvers name: build_resolvers
sha256: "99d3980049739a985cf9b21f30881f46db3ebc62c5b8d5e60e27440876b1ba1e" sha256: "339086358431fa15d7eca8b6a36e5d783728cf025e559b834f4609a1fcfb7b0a"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.3" version: "2.4.2"
build_runner: build_runner:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: build_runner name: build_runner
sha256: "74691599a5bc750dc96a6b4bfd48f7d9d66453eab04c7f4063134800d6a5c573" sha256: "028819cfb90051c6b5440c7e574d1896f8037e3c96cf17aaeb054c9311cfbf4d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.14" version: "2.4.13"
build_runner_core: build_runner_core:
dependency: transitive dependency: transitive
description: description:
name: build_runner_core name: build_runner_core
sha256: "22e3aa1c80e0ada3722fe5b63fd43d9c8990759d0a2cf489c8c5d7b2bdebc021" sha256: f8126682b87a7282a339b871298cc12009cb67109cfa1614d6436fb0289193e0
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "8.0.0" version: "7.3.2"
built_collection: built_collection:
dependency: transitive dependency: transitive
description: description:
@ -258,42 +258,50 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: custom_lint name: custom_lint
sha256: "7e6a73e1722ad90b48f77918994c17a5b177b0869804ea3c4ce9c9199de019f6" sha256: "3486c470bb93313a9417f926c7dd694a2e349220992d7b9d14534dc49c15bba9"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.2" version: "0.7.0"
custom_lint_builder: custom_lint_builder:
dependency: transitive dependency: transitive
description: description:
name: custom_lint_builder name: custom_lint_builder
sha256: e26941131416b0bc81219dc8ddc68b34c6319e20abc001dd4855412749309d3b sha256: "42cdc41994eeeddab0d7a722c7093ec52bd0761921eeb2cbdbf33d192a234759"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.2" version: "0.7.0"
custom_lint_core: custom_lint_core:
dependency: transitive dependency: transitive
description: description:
name: custom_lint_core name: custom_lint_core
sha256: "6dcee8a017181941c51a110da7e267c1d104dc74bec8862eeb8c85b5c8759a9e" sha256: "02450c3e45e2a6e8b26c4d16687596ab3c4644dd5792e3313aa9ceba5a49b7f5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.1" version: "0.7.0"
custom_lint_visitor: custom_lint_visitor:
dependency: transitive dependency: transitive
description: description:
name: custom_lint_visitor name: custom_lint_visitor
sha256: "14df0760dfa81b7b0c398c876045f4e4a343eb2c9d200c66163671dd3e337c1b" sha256: bfe9b7a09c4775a587b58d10ebb871d4fe618237639b1e84d5ec62d7dfef25f9
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.0.0+7.1.0" version: "1.0.0+6.11.0"
dart_style: dart_style:
dependency: transitive dependency: transitive
description: description:
name: dart_style name: dart_style
sha256: "27eb0ae77836989a3bc541ce55595e8ceee0992807f14511552a898ddd0d88ac" sha256: "7856d364b589d1f08986e140938578ed36ed948581fbc3bc9aef1805039ac5ab"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted 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: dbus:
dependency: transitive dependency: transitive
description: description:
@ -302,6 +310,22 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.11" 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: equatable:
dependency: transitive dependency: transitive
description: description:
@ -543,6 +567,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.7.0" 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: flutter_test:
dependency: "direct dev" dependency: "direct dev"
description: flutter description: flutter
@ -565,10 +597,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: freezed name: freezed
sha256: "59a584c24b3acdc5250bb856d0d3e9c0b798ed14a4af1ddb7dc1c7b41df91c9c" sha256: "44c19278dd9d89292cf46e97dc0c1e52ce03275f40a97c5a348e802a924bf40e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.5.8" version: "2.5.7"
freezed_annotation: freezed_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@ -605,10 +637,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: go_router name: go_router
sha256: "9b736a9fa879d8ad6df7932cbdcc58237c173ab004ef90d8377923d7ad731eaa" sha256: daf3ff5570f55396b2d2c9bf8136d7db3a8acf208ac0cef92a3ae2beb9a81550
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "14.7.2" version: "14.7.1"
graphs: graphs:
dependency: transitive dependency: transitive
description: description:
@ -661,10 +693,18 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: http_parser name: http_parser
sha256: "178d74305e7866013777bab2c3d8726205dc5a4dd935297175b19a23a2e66571" sha256: "2aa08ce0341cc9b354a498388e30986515406668dbcc4f7c950c3e715496693b"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted 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: image:
dependency: transitive dependency: transitive
description: description:
@ -749,10 +789,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: injectable_generator name: injectable_generator
sha256: b04673a4c88b3a848c0c77bf58b8309f9b9e064d9fe1df5450c8ee1675eaea1a sha256: af403d76c7b18b4217335e0075e950cd0579fd7f8d7bd47ee7c85ada31680ba1
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.7.0" version: "2.6.2"
intl: intl:
dependency: "direct main" dependency: "direct main"
description: description:
@ -789,10 +829,10 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: json_serializable name: json_serializable
sha256: b0a98230538fe5d0b60a22fb6bf1b6cb03471b53e3324ff6069c591679dd59c9 sha256: c2fcb3920cf2b6ae6845954186420fca40bc0a8abcc84903b7801f17d7050d7c
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.9.3" version: "6.9.0"
jwt_decoder: jwt_decoder:
dependency: "direct main" dependency: "direct main"
description: description:
@ -829,10 +869,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: lints name: lints
sha256: c35bb79562d980e9a453fc715854e1ed39e24e7d0297a880ef54e17f9874a9d7 sha256: "3315600f3fb3b135be672bf4a178c55f274bebe368325ae18462c89ac1e3b413"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.1.1" version: "5.0.0"
logging: logging:
dependency: transitive dependency: transitive
description: description:
@ -953,6 +993,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.0" 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: path_provider:
dependency: transitive dependency: transitive
description: description:
@ -1061,10 +1109,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: pubspec_parse name: pubspec_parse
sha256: "0560ba233314abbed0a48a2956f7f022cce7c3e1e73df540277da7544cad4082" sha256: "81876843eb50dc2e1e5b151792c9a985c5ed2536914115ed04e9c8528f6647b0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.5.0" version: "1.4.0"
recase: recase:
dependency: transitive dependency: transitive
description: description:
@ -1093,10 +1141,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: riverpod_analyzer_utils name: riverpod_analyzer_utils
sha256: "837a6dc33f490706c7f4632c516bcd10804ee4d9ccc8046124ca56388715fdf3" sha256: c6b8222b2b483cb87ae77ad147d6408f400c64f060df7a225b127f4afef4f8c8
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.5.9" version: "0.5.8"
riverpod_annotation: riverpod_annotation:
dependency: "direct main" dependency: "direct main"
description: description:
@ -1109,18 +1157,18 @@ packages:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: riverpod_generator name: riverpod_generator
sha256: "120d3310f687f43e7011bb213b90a436f1bbc300f0e4b251a72c39bccb017a4f" sha256: "63546d70952015f0981361636bf8f356d9cfd9d7f6f0815e3c07789a41233188"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.4" version: "2.6.3"
riverpod_lint: riverpod_lint:
dependency: "direct dev" dependency: "direct dev"
description: description:
name: riverpod_lint name: riverpod_lint
sha256: b05408412b0f75dec954e032c855bc28349eeed2d2187f94519e1ddfdf8b3693 sha256: "83e4caa337a9840469b7b9bd8c2351ce85abad80f570d84146911b32086fbd99"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.6.4" version: "2.6.3"
rxdart: rxdart:
dependency: transitive dependency: transitive
description: description:
@ -1212,10 +1260,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shelf name: shelf
sha256: e7dd780a7ffb623c57850b33f43309312fc863fb6aa3d276a754bb299839ef12 sha256: ad29c505aee705f41a4d8963641f91ac4cee3c8fad5947e033390a7bd8180fa4
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.4.2" version: "1.4.1"
shelf_web_socket: shelf_web_socket:
dependency: transitive dependency: transitive
description: description:
@ -1240,10 +1288,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: source_gen name: source_gen
sha256: "35c8150ece9e8c8d263337a265153c3329667640850b9304861faea59fc98f6b" sha256: "14658ba5f669685cd3d63701d01b31ea748310f7ab854e471962670abcf57832"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.0.0" version: "1.5.0"
source_helper: source_helper:
dependency: transitive dependency: transitive
description: description:
@ -1432,10 +1480,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: url_launcher_web name: url_launcher_web
sha256: "3ba963161bd0fe395917ba881d320b9c4f6dd3c4a233da62ab18a5025c85f1e9" sha256: "772638d3b34c779ede05ba3d38af34657a05ac55b06279ea6edd409e323dca8e"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.0" version: "2.3.3"
url_launcher_windows: url_launcher_windows:
dependency: transitive dependency: transitive
description: description:
@ -1452,6 +1500,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.5.1" 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: vector_math:
dependency: transitive dependency: transitive
description: description:
@ -1472,10 +1544,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: video_player_android name: video_player_android
sha256: "7018dbcb395e2bca0b9a898e73989e67c0c4a5db269528e1b036ca38bcca0d0b" sha256: "391e092ba4abe2f93b3e625bd6b6a6ec7d7414279462c1c0ee42b5ab8d0a0898"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.7.17" version: "2.7.16"
video_player_avfoundation: video_player_avfoundation:
dependency: transitive dependency: transitive
description: description:
@ -1552,10 +1624,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_android name: webview_flutter_android
sha256: "5568f17a9c25c0fdd0737900fa1c2d1fee2d780bc212d9aec10c2d1f48ef0f59" sha256: d1ee28f44894cbabb1d94cc42f9980297f689ff844d067ec50ff88d86e27d63f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.3.1" version: "4.3.0"
webview_flutter_platform_interface: webview_flutter_platform_interface:
dependency: transitive dependency: transitive
description: description:
@ -1568,10 +1640,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: webview_flutter_wkwebview name: webview_flutter_wkwebview
sha256: "8e0593559bfecd35eb1757d6907ed6b995a41ef82607d6113df897c2805ce6be" sha256: "4adc14ea9a770cc9e2c8f1ac734536bd40e82615bd0fa6b94be10982de656cc7"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.18.0" version: "3.17.0"
win32: win32:
dependency: transitive dependency: transitive
description: description:
@ -1605,5 +1677,5 @@ packages:
source: hosted source: hosted
version: "3.1.3" version: "3.1.3"
sdks: sdks:
dart: ">=3.6.0 <4.0.0" dart: ">=3.5.2 <4.0.0"
flutter: ">=3.27.0" flutter: ">=3.24.0"

View File

@ -1,7 +1,7 @@
name: uae_stat name: uae_stat
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness." description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
publish_to: "none" publish_to: "none"
version: 0.5.10 version: 1.0.9+10
environment: environment:
sdk: ">=3.2.3 <4.0.0" sdk: ">=3.2.3 <4.0.0"
@ -22,7 +22,7 @@ dependencies:
cupertino_icons: ^1.0.6 cupertino_icons: ^1.0.6
fl_chart: ^0.70.2 fl_chart: ^0.70.2
iconify_design: ^1.0.1
marquee: ^2.2.3 marquee: ^2.2.3
url_launcher: ^6.3.1 url_launcher: ^6.3.1
# dynamic_layouts: # dynamic_layouts:
@ -112,6 +112,24 @@ flutter:
- assets/cached_responses/sharepoint/country_leader_imgs/ - assets/cached_responses/sharepoint/country_leader_imgs/
- assets/edit_profile/ - assets/edit_profile/
- assets/splash_screen/ - 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: fonts:
- family: Segoe - family: Segoe