App Tour Bug and Bookmark Frontend added

This commit is contained in:
Kalonkarthik 2025-02-03 15:13:38 +05:30
commit ceeb873797
17 changed files with 1153 additions and 636 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 = "3" flutterVersionCode = "6"
} }
def flutterVersionName = localProperties.getProperty("flutter.versionName") def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) { if (flutterVersionName == null) {
flutterVersionName = "1.0.2" flutterVersionName = "1.0.5"
} }
def keystorePropertiesFile = rootProject.file("key.properties") def keystorePropertiesFile = rootProject.file("key.properties")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 12 KiB

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 325 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 375 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 558 B

After

Width:  |  Height:  |  Size: 2.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 25 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

@ -414,7 +414,9 @@ final GoRouter router = GoRouter(
builder: (context, state) { builder: (context, state) {
final userId = state.pathParameters['userId']!; final userId = state.pathParameters['userId']!;
final email = state.pathParameters['email']!; final email = state.pathParameters['email']!;
return CreateNewPw(userId: userId, email: email); final key = state.uri.queryParameters['key'] ?? '';
return CreateNewPw(userId: userId, email: email, keyParam: key);
}, },
), ),
GoRoute( GoRoute(

View File

@ -0,0 +1,7 @@
import 'package:flutter/material.dart';
abstract class UaeNumbersAssetPath {
static const _basePath = 'assets/icons/uae_numbers';
static const bookmarksUae = '$_basePath/bookmarks.png';
static const shareUae = '$_basePath/share.png';
}

View File

@ -13,7 +13,9 @@ import '../../../config/my_theme.dart';
class CreateNewPw extends StatefulWidget { class CreateNewPw extends StatefulWidget {
final String userId; final String userId;
final String email; final String email;
const CreateNewPw({Key? key, required this.userId, required this.email}); final String? keyParam;
const CreateNewPw({Key? key, required this.userId, required this.email, required this.keyParam});
@override @override
State<CreateNewPw> createState() => _CreateNewPwState(); State<CreateNewPw> createState() => _CreateNewPwState();
@ -210,7 +212,14 @@ class _CreateNewPwState extends State<CreateNewPw> {
alignment: Alignment.topRight, alignment: Alignment.topRight,
child: GestureDetector( child: GestureDetector(
onTap: () { onTap: () {
context.go('/editProfile');
if (widget.keyParam == 'editProfile') {
context.go('/editProfile');
}else
{
context.go('/profile/${widget.userId}');
}
}, },
child: Container( child: Container(
margin: EdgeInsets.only(top: 16,left: 16,bottom: 16,right: 1), // Add margin for positioning margin: EdgeInsets.only(top: 16,left: 16,bottom: 16,right: 1), // Add margin for positioning
@ -351,8 +360,8 @@ class _CreateNewPwState extends State<CreateNewPw> {
SizedBox(height: screenHeight / 5), SizedBox(height: screenHeight / 5),
Center( Center(
child: Container( child: Container(
height: screenHeight / 8, height: screenHeight / 12,
width: screenWidth / 2, width: screenWidth / 2.5,
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage("assets/splash_screen/logo.png"), image: AssetImage("assets/splash_screen/logo.png"),

View File

@ -31,6 +31,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
String? _password; String? _password;
bool registrationSuccess = false; bool registrationSuccess = false;
bool registrationFailed = false; bool registrationFailed = false;
bool isRegistering = false;
dynamic userID; dynamic userID;
final pb = PocketBase('https://pb.venbait.in'); final pb = PocketBase('https://pb.venbait.in');
@ -144,6 +145,12 @@ class _RegisterScreenState extends State<RegisterScreen> {
final regex = RegExp( final regex = RegExp(
r'^[A-Za-z0-9~!@#$%^&*()_+=[\]{}|;:,.<>?/-àèìòùáéíóúÀÈÌÒÙÁÉÍÓÚ]*$'); r'^[A-Za-z0-9~!@#$%^&*()_+=[\]{}|;:,.<>?/-àèìòùáéíóúÀÈÌÒÙÁÉÍÓÚ]*$');
// Define regular expressions for password complexity requirements
final hasUppercase = RegExp(r'[A-Z]');
final hasLowercase = RegExp(r'[a-z]');
final hasDigit = RegExp(r'\d');
final hasSpecialCharacter = RegExp(r'[~!@#$%^&*()_+=[\]{}|;:,.<>?/-]');
if (value == null || value.isEmpty) { if (value == null || value.isEmpty) {
return 'Required'; return 'Required';
} else if (value.length < 8) { } else if (value.length < 8) {
@ -151,7 +158,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
} }
// Check the length constraint // Check the length constraint
if (value.length < 8 || value.length > 40) { if (value.length < 8 || value.length > 64) {
return 'Password must be between 8 and 64 characters'; return 'Password must be between 8 and 64 characters';
} }
@ -160,6 +167,27 @@ class _RegisterScreenState extends State<RegisterScreen> {
return 'Password contains invalid characters'; return 'Password contains invalid characters';
} }
// Track missing constraints
List<String> missingConstraints = [];
if (!hasUppercase.hasMatch(value)) {
missingConstraints.add('uppercase letter');
}
if (!hasLowercase.hasMatch(value)) {
missingConstraints.add('lowercase letter');
}
if (!hasDigit.hasMatch(value)) {
missingConstraints.add('numeric digit');
}
if (!hasSpecialCharacter.hasMatch(value)) {
missingConstraints.add('special character');
}
// If there are missing constraints, return a consolidated message
if (missingConstraints.isNotEmpty) {
return 'At least one ${missingConstraints.join(', ')}';
}
_password = value; // Store the password for confirm password validation _password = value; // Store the password for confirm password validation
return null; return null;
} }
@ -185,12 +213,15 @@ class _RegisterScreenState extends State<RegisterScreen> {
Future<void> _registerUser() async { Future<void> _registerUser() async {
if (_formKey.currentState?.validate() ?? false) { if (_formKey.currentState?.validate() ?? false) {
if (isChecked) { if (isChecked) {
setState(() {
isRegistering = true; // Disable the button
});
try { try {
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('adminTokenREgistration- ${adminToken}');
// Create user in PocketBase // Create user in PocketBase
final response = await pb.collection('users').create(body: { final response = await pb.collection('users').create(body: {
'uname': _usernameController.text, 'uname': _usernameController.text,
@ -211,6 +242,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
userID = response.id; userID = response.id;
registrationSuccess = true; registrationSuccess = true;
registrationFailed = false; // Show success message on success registrationFailed = false; // Show success message on success
isRegistering = false;
}); });
// Navigate to ProfileScreen after successful registration // Navigate to ProfileScreen after successful registration
@ -249,6 +281,9 @@ class _RegisterScreenState extends State<RegisterScreen> {
registrationFailed = true; registrationFailed = true;
registrationSuccess = false; registrationSuccess = false;
}); });
setState(() {
isRegistering = false; // Re-enable the button after error
});
} }
} }
} else { } else {
@ -330,7 +365,9 @@ class _RegisterScreenState extends State<RegisterScreen> {
buildIconContainer(Icons.report, Color(0xFF7DAFBC)), buildIconContainer(Icons.report, Color(0xFF7DAFBC)),
SizedBox(height: 20), SizedBox(height: 20),
Text( Text(
"Your registration is pending for verification.", context.translate(
'Your registration is pending for verification.',
'تسجيلك في انتظار التحقق.'),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
@ -339,7 +376,9 @@ class _RegisterScreenState extends State<RegisterScreen> {
), ),
SizedBox(height: 10), SizedBox(height: 10),
Text( Text(
"Kindly verify your mail to proceed further.", context.translate(
'Kindly verify your mail to proceed further.',
'يرجى التحقق من البريد الخاص بك للمضي قدما.'),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
@ -350,14 +389,14 @@ class _RegisterScreenState extends State<RegisterScreen> {
ElevatedButton( ElevatedButton(
onPressed: () => {context.go('/')}, onPressed: () => {context.go('/')},
child: Text( child: Text(
'Go to Login', context.translate('Go to Login', 'اذهب إلى تسجيل الدخول'),
), ),
), ),
SizedBox(height: screenheight / 5), SizedBox(height: screenheight / 5),
Center( Center(
child: Container( child: Container(
height: screenheight / 8, height: screenheight / 16,
width: screenwidth / 2, width: screenwidth / 2.5,
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage( image: AssetImage(
@ -379,7 +418,8 @@ class _RegisterScreenState extends State<RegisterScreen> {
buildIconContainer(Icons.report, Colors.red), buildIconContainer(Icons.report, Colors.red),
SizedBox(height: 20), SizedBox(height: 20),
Text( Text(
"Sorry ${_usernameController.text}!", context.translate('Sorry ${_usernameController.text}!',
'آسف ${_usernameController.text}!'),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 16, fontSize: 16,
@ -388,7 +428,9 @@ class _RegisterScreenState extends State<RegisterScreen> {
), ),
SizedBox(height: 10), SizedBox(height: 10),
Text( Text(
"Your registration process failed. For further assistance, please contact support.", context.translate(
'Your registration process failed. For further assistance, please contact support.',
'فشلت عملية التسجيل الخاصة بك. لمزيد من المساعدة، يرجى الاتصال بالدعم.'),
textAlign: TextAlign.center, textAlign: TextAlign.center,
style: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
@ -409,14 +451,14 @@ class _RegisterScreenState extends State<RegisterScreen> {
}) })
}, },
child: Text( child: Text(
'Retry', context.translate('Retry', 'أعد المحاولة'),
), ),
), ),
SizedBox(height: screenheight / 5), SizedBox(height: screenheight / 5),
Center( Center(
child: Container( child: Container(
height: screenheight / 8, height: screenheight / 16,
width: screenwidth / 2, width: screenwidth / 2.5,
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage( image: AssetImage(
@ -475,7 +517,8 @@ class _RegisterScreenState extends State<RegisterScreen> {
decoration: InputDecoration( decoration: InputDecoration(
// hintText: 'Enter your email', // hintText: 'Enter your email',
hintText: _showHints[1] hintText: _showHints[1]
? AppLocalizations.of(context)!.enter_your_email ? AppLocalizations.of(context)!
.enter_your_email
: null, : null,
// _showHints[1] ? 'Enter your email' : null, // _showHints[1] ? 'Enter your email' : null,
prefixIcon: Icon( prefixIcon: Icon(
@ -500,7 +543,8 @@ class _RegisterScreenState extends State<RegisterScreen> {
obscureText: _obscurePassword, obscureText: _obscurePassword,
decoration: InputDecoration( decoration: InputDecoration(
hintText: _showHints[2] hintText: _showHints[2]
? AppLocalizations.of(context)!.enter_your_password ? AppLocalizations.of(context)!
.enter_your_password
: null, : null,
// _showHints[2] ? 'Enter your password' : null, // _showHints[2] ? 'Enter your password' : null,
prefixIcon: Icon( prefixIcon: Icon(
@ -510,8 +554,8 @@ class _RegisterScreenState extends State<RegisterScreen> {
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon( icon: Icon(
_obscurePassword _obscurePassword
? Icons.visibility ? Icons.visibility_off
: Icons.visibility_off, : Icons.visibility,
color: Colors.blue, color: Colors.blue,
), ),
onPressed: () { onPressed: () {
@ -545,8 +589,8 @@ class _RegisterScreenState extends State<RegisterScreen> {
suffixIcon: IconButton( suffixIcon: IconButton(
icon: Icon( icon: Icon(
_obscureConfirmPassword _obscureConfirmPassword
? Icons.visibility ? Icons.visibility_off
: Icons.visibility_off, : Icons.visibility,
color: Colors.blue, color: Colors.blue,
), ),
onPressed: () { onPressed: () {
@ -632,7 +676,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
SizedBox( SizedBox(
width: screenwidth / 1.3, width: screenwidth / 1.3,
child: ElevatedButton( child: ElevatedButton(
onPressed: _registerUser, onPressed: isRegistering ? null : _registerUser,
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Color( backgroundColor: Color(
0xFFA7887A), // Brownish color for Register 0xFFA7887A), // Brownish color for Register
@ -719,8 +763,8 @@ class _RegisterScreenState extends State<RegisterScreen> {
), ),
Center( Center(
child: Container( child: Container(
height: screenheight / 8, height: screenheight / 16,
width: screenwidth / 2, width: screenwidth / 2.5,
decoration: BoxDecoration( decoration: BoxDecoration(
image: DecorationImage( image: DecorationImage(
image: AssetImage( image: AssetImage(

View File

@ -4,9 +4,11 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.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/uae_numbers_asset_path.dart';
import 'package:uae_stat/presentation/Screens/charts/services/api_service.dart'; import 'package:uae_stat/presentation/Screens/charts/services/api_service.dart';
import 'package:uae_stat/presentation/Screens/charts/widgets/chart_widget.dart'; import 'package:uae_stat/presentation/Screens/charts/widgets/chart_widget.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import 'package:uae_stat/presentation/components/my_toggle.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart'; import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart';
@ -761,8 +763,8 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
filterDataSet = filterData.entries filterDataSet = filterData.entries
.map((entry) => {'key': entry.key, 'value': entry.value}) .map((entry) => {'key': entry.key, 'value': entry.value})
.toList(); .toList();
// print("filterDataf1:- $filterData"); print("filterDataf1:- $filterData");
// print("filterDataf11:- $filterDataSet"); print("filterDataf11:- $filterDataSet");
} else { } else {
filterDataSet = data['filterData'] ?? []; filterDataSet = data['filterData'] ?? [];
print('filterData not found!'); print('filterData not found!');
@ -1081,53 +1083,139 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
), ),
), ),
// Button Section // Button Section
// Padding(
// padding: const EdgeInsets.all(16.0),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
// children: [
// ElevatedButton(
// onPressed: () {
// // Clear all selected filters
// selectedFilters.forEach((filter) {
// filter["filter_data"].clear();
// });
// setState(() {
// chartsData = List.from(originalTabChartsData);
// cardData = List.from(originalTabCardData);
// });
// // Reset the selectedFiltersStorage to empty when clearing
// selectedFiltersStorage.clear();
// Navigator.pop(context);
// },
// child: Text(context.translate(
// 'Clear',
// 'واضح',
// )),
// style: ElevatedButton.styleFrom(
// backgroundColor: Colors.grey,
// ),
// ),
// ElevatedButton(
// onPressed: () {
// print(
// "Selected Filters before applying: $selectedFilters");
// setState(() {
// chartsData = originalTabChartsData;
// cardData = originalTabCardData;
// });
//
// applyFilters(context, filters, chartsData, cardData,
// selectedFilters);
// // Save the selected filters to storage after applying
// selectedFiltersStorage = List.from(selectedFilters);
// },
// child: Text(context.translate(
// 'Apply Filter',
// 'تطبيق الفلتر',
// )),
// style: ElevatedButton.styleFrom(
// backgroundColor: Colors.blue,
// ),
// ),
// ],
// ),
// ),
Padding( Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Row( child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
ElevatedButton( Expanded(
onPressed: () { child: ElevatedButton(
// Clear all selected filters onPressed: () {
selectedFilters.forEach((filter) { selectedFilters.forEach((filter) {
filter["filter_data"].clear(); filter["filter_data"].clear();
}); });
setState(() { setState(() {
chartsData = List.from(originalTabChartsData); chartsData = List.from(originalTabChartsData);
cardData = List.from(originalTabCardData); cardData = List.from(originalTabCardData);
}); });
// Reset the selectedFiltersStorage to empty when clearing selectedFiltersStorage.clear();
selectedFiltersStorage.clear(); Navigator.pop(context);
Navigator.pop(context); },
}, child: Padding(
child: Text(context.translate( padding: const EdgeInsets.symmetric(
'Clear', vertical: 12), // Added padding
'واضح', child: Text(
)), context.translate('Clear', 'واضح'),
style: ElevatedButton.styleFrom( style: TextStyle(
backgroundColor: Colors.grey, color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
overflow:
TextOverflow.ellipsis, // Prevents wrapping
maxLines: 1, // Ensures single line
),
),
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF92722A),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
), ),
), ),
ElevatedButton( SizedBox(width: 16),
onPressed: () { Expanded(
print( child: ElevatedButton(
"Selected Filters before applying: $selectedFilters"); onPressed: () {
setState(() { print(
chartsData = originalTabChartsData; "Selected Filters before applying: $selectedFilters");
cardData = originalTabCardData; setState(() {
}); chartsData = originalTabChartsData;
cardData = originalTabCardData;
});
applyFilters(context, filters, chartsData, cardData, applyFilters(context, filters, chartsData, cardData,
selectedFilters); selectedFilters);
// Save the selected filters to storage after applying selectedFiltersStorage = List.from(selectedFilters);
selectedFiltersStorage = List.from(selectedFilters); },
}, child: Padding(
child: Text(context.translate( padding: const EdgeInsets.symmetric(
'Apply Filter', vertical: 12), // Added padding
'تطبيق الفلتر', child: FittedBox(
)), fit: BoxFit
style: ElevatedButton.styleFrom( .scaleDown, // Ensures text resizes if necessary
backgroundColor: Colors.blue, child: Text(
context.translate(
'Apply Filter', 'تطبيق الفلتر'),
style: TextStyle(
color: Colors.white,
fontSize: 16,
fontWeight: FontWeight.bold,
),
overflow:
TextOverflow.ellipsis, // Prevents wrapping
maxLines: 1, // Ensures single line
),
),
),
style: ElevatedButton.styleFrom(
backgroundColor: Color(0xFF92722A),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(8),
),
),
), ),
), ),
], ],
@ -1235,9 +1323,18 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final locale = ref.watch(localeProvider);
final localeNotifier = ref.read(localeProvider.notifier);
ref.listen<Locale?>(localeProvider, (previous, next) { ref.listen<Locale?>(localeProvider, (previous, next) {
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
fetchChartData(widget.dataSets, localeCode); // fetchChartData(widget.dataSets, localeCode);
fetchChartData(widget.dataSets, localeCode).then((_) {
if (_tabsData.isNotEmpty) {
// Call onTabSelected for the first tab
onTabSelected(_tabsData[0]['id']);
}
});
}); });
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;
@ -1249,6 +1346,23 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
appBar: AppBar( appBar: AppBar(
backgroundColor: color, backgroundColor: color,
elevation: 0, elevation: 0,
actions: [
// IconButton(
// onPressed: () {},
// icon: const Icon(Icons.toggle_off_outlined),
// ),
MyToggle(
// key: toggleKey,
isOn: locale?.languageCode == 'en',
knobTextWhenOn: 'ع',
knobTextWhenOff: 'EN',
pathColorWhenOn: Colors.grey.shade300,
pathColorWhenOff: Colors.grey.shade300,
onTap: () {
ref.read(localeProvider.notifier).toggleLocale();
},
),
],
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white), icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
onPressed: () { onPressed: () {
@ -1343,8 +1457,12 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
), ),
), ),
SizedBox(width: 5), SizedBox(width: 5),
Icon(Icons.bookmarks_outlined, Image.asset(
color: Colors.white, size: 18), UaeNumbersAssetPath.bookmarksUae,
color: Colors.white,
width: 24,
height: 24,
),
], ],
), ),
SizedBox(width: 10), SizedBox(width: 10),
@ -1361,8 +1479,12 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
), ),
), ),
SizedBox(width: 5), SizedBox(width: 5),
Icon(Icons.share_sharp, Image.asset(
color: Colors.white, size: 18), UaeNumbersAssetPath.shareUae,
color: Colors.white,
width: 24,
height: 24,
),
], ],
), ),
SizedBox( SizedBox(
@ -1492,10 +1614,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
Flexible( Flexible(
fit: FlexFit.loose, fit: FlexFit.loose,
child: FittedBox( child: FittedBox(
// fit: BoxFit.contain,
child: Text( child: Text(
'${chart_heading ?? 'NA'}', '${chart_heading ?? 'NA'}',
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 2, // Limit to 2 lines
softWrap:
true, // Enable soft wrapping
// overflow: TextOverflow.ellipsis, // Handle overflow gracefully
style: TextStyle( style: TextStyle(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
@ -1584,19 +1709,28 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
}, },
), ),
const SizedBox(height: 5), const SizedBox(height: 5),
Text( Flexible(
'${chart_heading ?? 'NA'}', fit: FlexFit.loose,
textAlign: TextAlign.center, child: FittedBox(
style: TextStyle( child: Text(
fontSize: 11, '${chart_heading ?? 'NA'}',
fontWeight: FontWeight.w400, textAlign: TextAlign.center,
color: Colors.black87, maxLines: 2, // Limit to 2 lines
softWrap:
true, // Enable soft wrapping
// overflow: TextOverflow.ellipsis, // Handle overflow gracefully
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
), ),
), ),
Text( Text(
'(${data['firstYear'] ?? 'NA'} - ${data['lastYear'] ?? 'NA'})', '(${data['firstYear'] ?? 'NA'} - ${data['lastYear'] ?? 'NA'})',
style: const TextStyle( style: const TextStyle(
fontSize: 11, color: Colors.grey), fontSize: 10, color: Colors.grey),
), ),
Flexible( Flexible(
fit: FlexFit.loose, fit: FlexFit.loose,
@ -1640,10 +1774,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
Flexible( Flexible(
fit: FlexFit.loose, fit: FlexFit.loose,
child: FittedBox( child: FittedBox(
// fit: BoxFit.contain,
child: Text( child: Text(
'${chart_heading ?? 'NA'}', '${chart_heading ?? 'NA'}',
textAlign: TextAlign.center, textAlign: TextAlign.center,
maxLines: 2, // Limit to 2 lines
softWrap:
true, // Enable soft wrapping
// overflow: TextOverflow.ellipsis, // Handle overflow gracefully
style: TextStyle( style: TextStyle(
fontSize: 11, fontSize: 11,
fontWeight: FontWeight.w400, fontWeight: FontWeight.w400,
@ -1715,14 +1852,17 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
Flexible( Flexible(
fit: FlexFit.loose, fit: FlexFit.loose,
child: FittedBox( child: FittedBox(
fit: BoxFit.contain,
child: Text( child: Text(
apiService.formatAmount( '${chart_heading ?? 'NA'}',
data['lastYearValue']), textAlign: TextAlign.center,
style: const TextStyle( maxLines: 2, // Limit to 2 lines
fontSize: 22, softWrap:
fontWeight: FontWeight.w900, true, // Enable soft wrapping
color: Color(0xFF90B0D5), // overflow: TextOverflow.ellipsis, // Handle overflow gracefully
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
), ),
), ),
), ),

View File

@ -72,27 +72,34 @@ class ChartWidget extends StatelessWidget {
}).toList(); }).toList();
} }
List<Widget> generateIndicators(dynamic chartData, groupByValue) { List<Widget> generateIndicators(dynamic chartData, String groupByValue) {
return chartData['response'].asMap().entries.map<Widget>((entry) { return chartData['response'].asMap().entries.map<Widget>((entry) {
int index = entry.key; int index = entry.key;
var data = entry.value; var data = entry.value;
Color color = Colors.primaries[index % Colors.primaries.length]; Color color = Colors.primaries[index % Colors.primaries.length];
String title = data['ObsKey'][groupByValue] ?? ''; String title = data['ObsKey'][groupByValue] ?? '';
String shortTitle =
title.length > 10 ? '${title.substring(0, 10)}' : title;
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
Container( Container(
width: 16, width: 10,
height: 16, height: 10,
decoration: BoxDecoration( decoration: BoxDecoration(
color: color, color: color,
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
), ),
SizedBox(width: 8), SizedBox(width: 8),
Text( Tooltip(
title, message: title, // Full text on hover
style: TextStyle(fontSize: 14), child: Text(
shortTitle,
style: TextStyle(fontSize: 12),
overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow
),
), ),
], ],
); );
@ -299,7 +306,7 @@ class ChartWidget extends StatelessWidget {
touchTooltipData: BarTouchTooltipData( touchTooltipData: BarTouchTooltipData(
// tooltipBgColor: Colors.black.withOpacity(0.8), // tooltipBgColor: Colors.black.withOpacity(0.8),
fitInsideHorizontally: true, fitInsideHorizontally: true,
fitInsideVertically: false, fitInsideVertically: true,
tooltipPadding: const EdgeInsets.all(8), tooltipPadding: const EdgeInsets.all(8),
tooltipMargin: 16, tooltipMargin: 16,
getTooltipItem: getTooltipItem:
@ -541,11 +548,21 @@ class ChartWidget extends StatelessWidget {
), ),
), ),
]); ]);
case 'line_trend_2': case 'line_trend_population':
final List<Color> uniqueColorsLine_trend_2 = [
Color(0xFF6097CD),
Color(0xFFD086A7),
Color(0xFF98BCE5),
Color(0xFFA7B5C5),
Color(0xFFBED3EC),
Color(0xFFD4E3F4),
];
Set<int> selectedYears = {1970, 1980, 1990, 2000, 2010, 2020};
Map<String, Color> groupColorMap = {}; Map<String, Color> groupColorMap = {};
int colorIndex = 0; int colorIndex = 0;
for (String group in groupByValues) { for (String group in groupByValues) {
groupColorMap[group] = uniqueColors[colorIndex % uniqueColors.length]; groupColorMap[group] = uniqueColorsLine_trend_2[
colorIndex % uniqueColorsLine_trend_2.length];
colorIndex++; colorIndex++;
} }
@ -565,15 +582,17 @@ class ChartWidget extends StatelessWidget {
); );
} }
// Find the maximum year and calculate the range for the last 5 years if (years.isNotEmpty) {
int maxYear = years.reduce((a, b) => a > b ? a : b); // Find the latest available year
int minYear = maxYear - 5; int latestYear = years.reduce((a, b) => a > b ? a : b);
selectedYears.add(latestYear); // Include the latest year in selection
}
// Filter chart data to only include entries within the last 5 years // Filter chart data to include only the selected years
List<dynamic> filteredData = List<dynamic> filteredData =
(chartData['response'] as List<dynamic>).where((entry) { (chartData['response'] as List<dynamic>).where((entry) {
int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0; int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0;
return year >= minYear && year <= maxYear; return selectedYears.contains(year);
}).toList(); }).toList();
Set<double> uniqueXValues = filteredData Set<double> uniqueXValues = filteredData
@ -583,7 +602,7 @@ class ChartWidget extends StatelessWidget {
// Generate line bars for the chart // Generate line bars for the chart
List<LineChartBarData> lineBars = List<LineChartBarData> lineBars =
lineBarsData2(filteredData, groupByValues, groupByKey); lineBarsData(filteredData, groupByValues, groupByKey);
return Column(children: [ return Column(children: [
Text( Text(
@ -600,12 +619,124 @@ class ChartWidget extends StatelessWidget {
child: LineChart(LineChartData( child: LineChart(LineChartData(
lineTouchData: lineTouchData1(), lineTouchData: lineTouchData1(),
gridData: gridData(), gridData: gridData(),
titlesData: titlesData2(uniqueXValues), titlesData: titlesData1(uniqueXValues),
borderData: borderData(), borderData: borderData(),
lineBarsData: lineBars, lineBarsData: lineBars,
minX: uniqueXValues.reduce((a, b) => a < b ? a : b), minX: uniqueXValues.reduce((a, b) => a < b ? a : b),
maxX: uniqueXValues.reduce((a, b) => a > b ? a : b), maxX: uniqueXValues.reduce((a, b) => a > b ? a : b),
))), ))),
Padding(
padding: const EdgeInsets.all(8.0),
child: Wrap(
spacing: 12,
runSpacing: 8,
children: groupByValues.map((group) {
return Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
width: 12,
height: 12,
color: groupColorMap[group],
),
SizedBox(width: 6),
Text(
group,
style: TextStyle(fontSize: 14),
),
],
);
}).toList(),
),
),
]);
case 'line_trend_2':
final List<Color> uniqueColorsLine_trend_2 = [
Color(0xFF6097CD),
Color(0xFFD086A7),
Color(0xFF98BCE5),
Color(0xFFA7B5C5),
Color(0xFFBED3EC),
Color(0xFFD4E3F4),
];
Set<int> selectedYears = {1970, 1980, 1990, 2000, 2010, 2020};
Map<String, Color> groupColorMap = {};
int colorIndex = 0;
for (String group in groupByValues) {
groupColorMap[group] = uniqueColorsLine_trend_2[
colorIndex % uniqueColorsLine_trend_2.length];
colorIndex++;
}
// Extract all years from the chart data
List<int> years = (chartData['response'] as List<dynamic>)
.map<int>((entry) =>
int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0)
.toList();
if (years.isEmpty) {
// Return an empty chart if no data
return LineChart(
LineChartData(
titlesData: FlTitlesData(show: false),
lineBarsData: [],
),
);
}
if (years.isNotEmpty) {
// Find the latest available year
int latestYear = years.reduce((a, b) => a > b ? a : b);
selectedYears.add(latestYear); // Include the latest year in selection
}
// Filter chart data to include only the selected years
List<dynamic> filteredData =
(chartData['response'] as List<dynamic>).where((entry) {
int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0;
return selectedYears.contains(year);
}).toList();
Set<double> uniqueXValues = filteredData
.map<double>(
(entry) => double.parse(entry['ObsKey']['TIME_PERIOD']))
.toSet();
// Generate line bars for the chart
List<LineChartBarData> lineBars = lineBarsData2(filteredData);
return Column(children: [
Text(
chartData['chart_heading'] ?? '', // Chart title from data
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10),
// Chart
Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.horizontal, // Enable horizontal scrolling
padding: const EdgeInsets.only(right: 40),
child: SizedBox(
width: (uniqueXValues.length * 80) +
80, // Adjust width dynamically
child: LineChart(
LineChartData(
lineTouchData: lineTouchData1(),
gridData: gridData(),
titlesData: titlesData1(uniqueXValues),
borderData: borderData(),
lineBarsData: lineBars,
minX: uniqueXValues.reduce((a, b) => a < b ? a : b),
maxX: uniqueXValues.reduce((a, b) => a > b ? a : b),
),
),
),
),
),
]); ]);
case 'bar_chart': case 'bar_chart':
// Extract groupBy values and their corresponding y-axis values // Extract groupBy values and their corresponding y-axis values
@ -697,6 +828,106 @@ class ChartWidget extends StatelessWidget {
), ),
)) ))
]); ]);
case 'bar_chart_horizontal':
// Extract groupBy values and their corresponding y-axis values
List<String> xAxisData = [];
List<double> yAxisData = [];
for (var entry in chartData['response']) {
var xValue = entry['ObsKey'][groupByKey];
var yValue = entry['ObsValue']['Value'];
if (xValue != null && yValue != null) {
xAxisData.add(xValue.toString());
yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0);
}
}
int rotationTurns = 1;
return Column(children: [
Text(
chartData['chart_heading'] ?? '', // Chart title from data
style: TextStyle(
fontSize: 14,
fontWeight: FontWeight.w400,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10),
// Chart
Expanded(
child: BarChart(
BarChartData(
alignment: BarChartAlignment.spaceAround,
maxY: yAxisData.isNotEmpty
? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2
: 10,
rotationQuarterTurns: rotationTurns,
barTouchData: BarTouchData(enabled: true),
titlesData: FlTitlesData(
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
interval: (yAxisData.isNotEmpty
? yAxisData.reduce((a, b) => a > b ? a : b) / 5
: 1),
getTitlesWidget: (value, meta) {
return Padding(
padding: const EdgeInsets.only(right: 8.0),
child: Text('${value.toInt()}'),
);
},
reservedSize: 60,
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
getTitlesWidget: (value, meta) {
if (value.toInt() < xAxisData.length) {
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Transform.rotate(
angle: -45 *
(3.1415927 / 180), // Rotating by -45 degrees
alignment: Alignment.center,
child: Text(
xAxisData[value.toInt()],
style: TextStyle(fontSize: 12),
),
),
);
}
return Container();
},
reservedSize: 60,
),
),
topTitles: AxisTitles(
sideTitles: SideTitles(showTitles: false), // Hide top titles
),
rightTitles: AxisTitles(
sideTitles:
SideTitles(showTitles: false), // Hide 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,
borderRadius: BorderRadius.circular(4),
width: 20,
),
],
),
),
),
))
]);
case 'fl_multi_bar': case 'fl_multi_bar':
double _calculateChartWidth(dynamic chartData) { double _calculateChartWidth(dynamic chartData) {
int totalBars = chartData['response']?.length ?? 0; int totalBars = chartData['response']?.length ?? 0;
@ -712,6 +943,15 @@ class ChartWidget extends StatelessWidget {
if (chartData['dataset'] == 'health_services') { if (chartData['dataset'] == 'health_services') {
crop = item['ObsKey']['SECTOR']; crop = item['ObsKey']['SECTOR'];
cropType = item['ObsKey'][groupByKey]; cropType = item['ObsKey'][groupByKey];
} else if (chartData['dataset'] == 'general_education') {
crop = item['ObsKey']['GENDER'];
cropType = item['ObsKey'][groupByKey];
} else if (chartData['dataset'] == 'higher_education') {
crop = item['ObsKey']['GENDER'];
cropType = item['ObsKey'][groupByKey];
} else if (chartData['dataset'] == 'labour_force') {
crop = item['ObsKey']['GENDER'];
cropType = item['ObsKey'][groupByKey];
} else { } else {
crop = item['ObsKey']['CROP']; crop = item['ObsKey']['CROP'];
cropType = item['ObsKey'][groupByKey]; cropType = item['ObsKey'][groupByKey];
@ -781,6 +1021,12 @@ class ChartWidget extends StatelessWidget {
barTouchData: BarTouchData( barTouchData: BarTouchData(
touchTooltipData: BarTouchTooltipData( touchTooltipData: BarTouchTooltipData(
tooltipHorizontalAlignment: FLHorizontalAlignment.center, tooltipHorizontalAlignment: FLHorizontalAlignment.center,
tooltipRoundedRadius: 8,
fitInsideHorizontally:
true, // Ensure it fits within the screen
fitInsideVertically: true,
tooltipPadding: EdgeInsets.all(8),
tooltipMargin: 16,
// Only show tooltip when touched // Only show tooltip when touched
getTooltipItem: (group, groupIndex, rod, rodIndex) { getTooltipItem: (group, groupIndex, rod, rodIndex) {
if (rod.toY == 0 || touchedGroupIndex == -1) { if (rod.toY == 0 || touchedGroupIndex == -1) {
@ -873,8 +1119,14 @@ class ChartWidget extends StatelessWidget {
// Iterate over the chartData to group crops by CROP_TYPE // Iterate over the chartData to group crops by CROP_TYPE
for (var item in chartData['response']) { for (var item in chartData['response']) {
String crop = item['ObsKey']['CROP']; String crop, cropType;
String cropType = item['ObsKey']['CROP_TYPE']; if (chartData['dataset'] == 'natural_reserves') {
crop = item['ObsKey']['NR_TYPE'];
cropType = item['ObsKey'][groupByKey];
} else {
crop = item['ObsKey']['CROP'];
cropType = item['ObsKey'][groupByKey];
}
if (groupedCrops.containsKey(cropType)) { if (groupedCrops.containsKey(cropType)) {
groupedCrops[cropType]!.add(crop); groupedCrops[cropType]!.add(crop);
@ -985,15 +1237,22 @@ class ChartWidget extends StatelessWidget {
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
reservedSize: 20, // Added space for rotated titles reservedSize: 80, // Added space for rotated titles
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
if (value < groupByValues.length) { if (value < groupByValues.length) {
String title = groupByValues.elementAt(value.toInt()); String title = groupByValues.elementAt(value.toInt());
return Transform.rotate( return Transform.rotate(
angle: -0.5, // Rotation in radians (~ -30 degrees) angle: -1.58, // Rotation in radians (~ -30 degrees)
child: Text( child: Center(
title, child: SizedBox(
style: const TextStyle(fontSize: 12), width: 80,
child: Text(
title,
style: const TextStyle(fontSize: 12),
softWrap: true,
maxLines: 2,
),
),
), ),
); );
} }
@ -1010,7 +1269,7 @@ class ChartWidget extends StatelessWidget {
show: true, show: true,
border: const Border( border: const Border(
// left: BorderSide(color: Colors.grey), // left: BorderSide(color: Colors.grey),
bottom: BorderSide(color: Colors.grey), bottom: BorderSide(color: Colors.white),
), ),
), ),
gridData: FlGridData( gridData: FlGridData(
@ -1084,47 +1343,25 @@ class ChartWidget extends StatelessWidget {
); );
} }
List<LineChartBarData> lineBarsData2(List<dynamic> filteredData, List<LineChartBarData> lineBarsData2(List<dynamic> filteredData) {
Set<String> groupByValues, String groupByKey) {
List<LineChartBarData> lineBars = []; List<LineChartBarData> lineBars = [];
print('filteredData $filteredData');
print('filteredData222 $groupByValues');
final List<Color> uniqueColors = [
Color(0xFF648CBA),
Color(0xFF90B0D5),
Color(0xFF98BCE5),
Color(0xFFA7B5C5),
Color(0xFFBED3EC),
Color(0xFFD4E3F4),
];
// Create a map to assign colors to each group in order // Create a map to store population values by year and gender
Map<String, Color> groupColorMap = {};
int colorIndex = 0;
for (String group in groupByValues) {
groupColorMap[group] = uniqueColors[colorIndex % uniqueColors.length];
colorIndex++;
}
print('Group-Color Map: $groupColorMap');
// Create a map to store the values by year and gender (M and F)
Map<int, Map<String, double>> yearGenderMap = {}; Map<int, Map<String, double>> yearGenderMap = {};
// Populate the yearGenderMap with male and female values
for (var entry in filteredData) { for (var entry in filteredData) {
int year = int.parse(entry['ObsKey']['TIME_PERIOD']); int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'].toString()) ?? 0;
String gender = entry['ObsKey']['GENDER']; String gender = entry['ObsKey']['GENDER'];
double value = double.parse(entry['ObsValue']['Value'].toString()); double value =
double.tryParse(entry['ObsValue']['Value'].toString()) ?? 0.0;
if (!yearGenderMap.containsKey(year)) { if (!yearGenderMap.containsKey(year)) {
yearGenderMap[year] = {'M': 0.0, 'F': 0.0}; yearGenderMap[year] = {'M': 0.0, 'F': 0.0};
} }
// Assign value based on gender if (gender == 'Male') {
if (gender == 'M') {
yearGenderMap[year]!['M'] = value; yearGenderMap[year]!['M'] = value;
} else if (gender == 'F') { } else if (gender == 'Female') {
yearGenderMap[year]!['F'] = value; yearGenderMap[year]!['F'] = value;
} }
} }
@ -1205,7 +1442,14 @@ class ChartWidget extends StatelessWidget {
// Helper functions for chart styles // Helper functions for chart styles
LineTouchData lineTouchData1() { LineTouchData lineTouchData1() {
return LineTouchData( return LineTouchData(
touchTooltipData: LineTouchTooltipData(), touchTooltipData: LineTouchTooltipData(
// tooltipBgColor: Colors.black.withOpacity(0.7), // Tooltip background
tooltipRoundedRadius: 8,
fitInsideHorizontally: true, // Ensure it fits within the screen
fitInsideVertically: true,
tooltipPadding: EdgeInsets.all(8),
tooltipMargin: 16, // Adds margin to prevent clipping
),
handleBuiltInTouches: true, handleBuiltInTouches: true,
); );
} }
@ -1534,6 +1778,12 @@ class ChartWidget extends StatelessWidget {
toY: value, // Use the parsed value toY: value, // Use the parsed value
color: barColor, // Dynamic color color: barColor, // Dynamic color
width: 20, width: 20,
// backDrawRodData: BackgroundBarChartRodData(
// show: true,
// toY: 400000,
// color: Colors.grey.shade300,
// ),
//
); );
}).toList(); }).toList();

View File

@ -451,7 +451,7 @@ class _ProfileScreenState extends State<ProfileScreen> {
controller: _usernameController, controller: _usernameController,
focusNode: _focusNodes[0], focusNode: _focusNodes[0],
decoration: InputDecoration( decoration: InputDecoration(
hintText: _showHints[0] ? 'Enter the User Name' : null, // hintText: _showHints[0] ? 'Enter the User Name' : null,
hintStyle: TextStyle(color: Colors.grey), hintStyle: TextStyle(color: Colors.grey),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),
@ -477,8 +477,8 @@ class _ProfileScreenState extends State<ProfileScreen> {
controller: _emailController, controller: _emailController,
focusNode: _focusNodes[1], focusNode: _focusNodes[1],
decoration: InputDecoration( decoration: InputDecoration(
hintText: // hintText:
_showHints[1] ? 'mohammad.hassan@fcsc.gov.ae' : null, // _showHints[1] ? 'mohammad.hassan@fcsc.gov.ae' : null,
hintStyle: TextStyle(color: Colors.grey), hintStyle: TextStyle(color: Colors.grey),
border: OutlineInputBorder( border: OutlineInputBorder(
borderRadius: BorderRadius.circular(8), borderRadius: BorderRadius.circular(8),

View File

@ -354,14 +354,22 @@ class LoginRoute extends HookConsumerWidget {
'Email', 'Email',
'بريد إلكتروني', 'بريد إلكتروني',
), ),
validator: FieldValidator.email(), validator: (value) {
if (value == null || value.isEmpty) {
return context.translate('Required', 'مطلوب');
}
return FieldValidator.email()(value);
},
imgPath: MiscIconAssetPath.person, imgPath: MiscIconAssetPath.person,
controller: emailCtl, controller: emailCtl,
), ),
15.verticalSpace, 15.verticalSpace,
ThemedFormField( ThemedFormField(
validator: (text) { validator: (text) {
if (text!.length < 8) { if (text == null || text.isEmpty) {
return context.translate('Required', 'مطلوب');
}
else if (text.length < 8) {
return 'The password must be at least 8 characters'; return 'The password must be at least 8 characters';
} }
return FieldValidator.password(minLength: 8)(text); return FieldValidator.password(minLength: 8)(text);
@ -462,16 +470,16 @@ class LoginRoute extends HookConsumerWidget {
width: double.infinity, width: double.infinity,
child: ElevatedButton( child: ElevatedButton(
onPressed: () async { onPressed: () async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
prefs.clear(); prefs.clear();
final userId = 'guest'; final userId = 'guest';
if (userId.isNotEmpty) { if (userId.isNotEmpty) {
await saveUserId(userId); await saveUserId(userId);
} }
context.go('/myhomepage'); context.go('/myhomepage');
//context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
}, },
//context.go('/${context.language}/${BottomNavBarItem.home.routePath}'), //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
style: ButtonStyle( style: ButtonStyle(
shape: WidgetStatePropertyAll( shape: WidgetStatePropertyAll(
RoundedRectangleBorder( RoundedRectangleBorder(
@ -515,7 +523,7 @@ class LoginRoute extends HookConsumerWidget {
); );
final fcscBanner = Image.asset( final fcscBanner = Image.asset(
BannerAssetPath.fcsc, BannerAssetPath.fcsc,
height: 56, height: 40,
); );
final screenWidth = MediaQuery.of(context).size.width; final screenWidth = MediaQuery.of(context).size.width;
final listViewHorizontalPadding = final listViewHorizontalPadding =
@ -528,14 +536,16 @@ class LoginRoute extends HookConsumerWidget {
36.verticalSpace, 36.verticalSpace,
Align( Align(
alignment: AlignmentDirectional.topEnd, alignment: AlignmentDirectional.topEnd,
child: MyToggle(isOn: locale?.languageCode == 'en', child: MyToggle(
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();
},), },
),
), ),
16.verticalSpace, 16.verticalSpace,
helloAndPleaseLoginTexts, helloAndPleaseLoginTexts,
@ -543,9 +553,9 @@ class LoginRoute extends HookConsumerWidget {
form, form,
20.verticalSpace, 20.verticalSpace,
dontHaveAnAccountRegisterBtn, dontHaveAnAccountRegisterBtn,
36.verticalSpace, 20.verticalSpace,
continueAsGuestBtn, continueAsGuestBtn,
72.verticalSpace, 25.verticalSpace,
fcscBanner, fcscBanner,
], ],
); );

View File

@ -753,14 +753,31 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
ListTile( ListTile(
leading: Icon(Icons.book), leading: Icon(Icons.book),
title: const Text('User Guide'), // title: const Text('User Guide'),
title: Text(AppLocalizations.of(context)!.guide_title),
onTap: () => context.go('/user-guide'), onTap: () => context.go('/user-guide'),
), ),
ListTile( if (userId != 'guest')
leading: Icon(Icons.logout), ListTile(
title: const Text('Logout'), leading: Icon(Icons.logout),
onTap: () => logout(), // title: const Text('Logout'),
), title: Text(AppLocalizations.of(context)!.logout),
onTap: () => logout(),
),
if (userId == 'guest')
ListTile(
leading: Icon(Icons.login),
// title: const Text('Login'),
title: Text(AppLocalizations.of(context)!.login_title),
onTap: () => context.go('/login'),
),
if (userId == 'guest')
ListTile(
leading: Icon(Icons.app_registration),
// title: const Text('Register'),
title: Text(AppLocalizations.of(context)!.register_title),
onTap: () => context.go('/register'),
),
], ],
), ),
), ),

View File

@ -2,7 +2,7 @@ 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: 0.5.10
version: 1.0.2+3 version: 1.0.5+6
environment: environment:
sdk: ">=3.2.3 <4.0.0" sdk: ">=3.2.3 <4.0.0"
@ -115,6 +115,8 @@ flutter:
- assets/edit_profile/ - assets/edit_profile/
- assets/splash_screen/ - assets/splash_screen/
- assets/app_tour/ - assets/app_tour/
- assets/icons/uae_numbers/bookmarks.png
- assets/icons/uae_numbers/share.png
fonts: fonts:
- family: Segoe - family: Segoe