App Tour first time login and fiter change

This commit is contained in:
venbaittech 2025-02-04 18:35:02 +05:30
parent b5d4df493e
commit 3ba3650e92
14 changed files with 863 additions and 416 deletions

View File

@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) {
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) {
flutterVersionCode = "6"
flutterVersionCode = "7"
}
def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) {
flutterVersionName = "1.0.5"
flutterVersionName = "1.0.6"
}
def keystorePropertiesFile = rootProject.file("key.properties")

Binary file not shown.

After

Width:  |  Height:  |  Size: 557 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 818 B

View File

@ -328,16 +328,15 @@ final GoRouter router = GoRouter(
GoRoute(
path: '/',
//builder: (context, state) => LoginRoute(),
builder: (context, state) => LoginRoute(),
builder: (context, state) => LoginRoute(isLoginScreen: true),
),
GoRoute(
path: '/internetcheck',
builder: (context, state) => InternetCheck(),
),
GoRoute(
path: '/login',
builder: (context, state) => LoginRoute(),
builder: (context, state) => LoginRoute(isLoginScreen: true),
//builder: (context, state) => LoginRoute(),
),
GoRoute(

View File

@ -6,4 +6,7 @@ abstract class MiscIconAssetPath {
static const menu = '$_basePath/menu.png';
static const person = '$_basePath/person.png';
static const back = '$_basePath/back.png';
static const vector = '$_basePath/vector.png';
static const visibleOn = '$_basePath/visible_on.png';
static const visibilityOff = '$_basePath/visibility_off.png';
}

View File

@ -12,14 +12,16 @@
"enter_your_email": "Enter your email",
"enter_your_password": "Enter your password",
"register_Confirm_password": "Confirm password",
"agree": "I agree to ",
"agree": "I agree to the",
"t_and": " and ",
"conditions": " of Fcsc",
"terms_conditions": "terms & conditions",
"privacy_policy":"privacy policy",
"account_confirmation": "Already have an account? Login",
"conditions": " of FCSC",
"terms_conditions": "Terms & Conditions",
"privacy_policy":"Privacy Policy",
"account_confirmation": "Already have an account?",
"login_title": "Login",
"profile_title": "Edit Profile",
"my_profile": "My Profile",
"logout": "Logout",

View File

@ -1,10 +1,13 @@
import 'package:external_repos/external_repos.dart';
import 'package:flutter/gestures.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:uae_stat/config/my_theme.dart';
import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart';
import 'package:uae_stat/presentation/Screens/profilepage.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -471,14 +474,15 @@ class _RegisterScreenState extends State<RegisterScreen> {
),
)
: Padding(
padding: const EdgeInsets.all(20.0),
padding: const EdgeInsets.only(top: 5.0,bottom: 20, left: 20,right: 20),
child: Form(
key: _formKey,
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
SizedBox(height: screenheight / 15),
SizedBox(height: screenheight / 60),
Text(
// 'Register',
AppLocalizations.of(context)!.register_title,
@ -492,18 +496,42 @@ class _RegisterScreenState extends State<RegisterScreen> {
// Display this if registration is pending approval
TextFormField(
controller: _usernameController,
focusNode: _focusNodes[0],
// focusNode: _focusNodes[0],
decoration: InputDecoration(
// hintText: _showHints[0] ? 'Username' : null,
hintText: _showHints[0]
? AppLocalizations.of(context)!.register_name
: null,
prefixIcon: Icon(
Icons.person,
color: Colors.blue,
prefixIcon: Padding(
padding: const EdgeInsets.all(8.0), // Adjust the padding as needed
child: Image.asset(
MiscIconAssetPath.person,
color: Color(0xFF90B0D5),
width: 24,
height: 24,
),
),
// prefixIcon: Icon(
// Icons.person,
// color: Color(0xFF90B0D5),
//
// ),
// border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFF90B0D5), width: 2), // Enabled border
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.deepPurple, width: 2), // Focused border
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFFD83731), width: 1), // Error border
),
border: OutlineInputBorder(),
counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB)),
),
validator: _validateUsername,
maxLength:
@ -513,7 +541,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
SizedBox(height: 15),
TextFormField(
controller: _emailController,
focusNode: _focusNodes[1],
// focusNode: _focusNodes[1],
decoration: InputDecoration(
// hintText: 'Enter your email',
hintText: _showHints[1]
@ -521,12 +549,30 @@ class _RegisterScreenState extends State<RegisterScreen> {
.enter_your_email
: null,
// _showHints[1] ? 'Enter your email' : null,
prefixIcon: Icon(
Icons.email,
color: Colors.blue,
prefixIcon: Padding(
padding: const EdgeInsets.all(8.0), // Adjust the padding as needed
child: Image.asset(
MiscIconAssetPath.vector,
color: Color(0xFF90B0D5),
width: 24,
height: 24,
),
),
// border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFF90B0D5), width: 2), // Enabled border
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.deepPurple, width: 2), // Focused border
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFFD83731), width: 1), // Error border
),
border: OutlineInputBorder(),
counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB)),
),
validator: _validateEmail,
maxLength: 320,
@ -539,7 +585,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
SizedBox(height: 15),
TextFormField(
controller: _passwordController,
focusNode: _focusNodes[2],
// focusNode: _focusNodes[2],
obscureText: _obscurePassword,
decoration: InputDecoration(
hintText: _showHints[2]
@ -547,25 +593,59 @@ class _RegisterScreenState extends State<RegisterScreen> {
.enter_your_password
: null,
// _showHints[2] ? 'Enter your password' : null,
prefixIcon: Icon(
Icons.lock,
color: Colors.blue,
),
suffixIcon: IconButton(
icon: Icon(
_obscurePassword
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
prefixIcon: Padding(
padding: const EdgeInsets.all(8.0), // Adjust the padding as needed
child: Image.asset(
MiscIconAssetPath.lock,
color: Color(0xFF90B0D5),
width: 24,
height: 24,
),
),
// prefixIcon: Icon(
// Icons.lock,
// color: Color(0xFF90B0D5),
// ),
suffixIcon: IconButton(
// icon: Icon(
// _obscurePassword
// ? Icons.visibility_off
// : Icons.visibility,
// color: Color(0xFF9EA2A9),
// ),
icon: Image.asset(
_obscurePassword
?MiscIconAssetPath.visibilityOff
:MiscIconAssetPath.visibleOn,
color: Color(0xFF9EA2A9), // Apply color if needed, but keep in mind `Image.asset` might not support color directly.
width: 24,
height: 24,
),
onPressed: () {
setState(() {
_obscurePassword = !_obscurePassword;
});
},
),
border: OutlineInputBorder(),
// border: OutlineInputBorder(),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFF90B0D5), width: 2), // Enabled border
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.deepPurple, width: 2), // Focused border
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFFD83731), width: 1), // Error border
),
counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB)),
),
validator: _validatePassword,
maxLength: 40,
@ -574,7 +654,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
SizedBox(height: 15),
TextFormField(
controller: _confirmpasswordController,
focusNode: _focusNodes[3],
// focusNode: _focusNodes[3],
obscureText: _obscureConfirmPassword,
decoration: InputDecoration(
hintText: _showHints[3]
@ -582,16 +662,25 @@ class _RegisterScreenState extends State<RegisterScreen> {
.register_Confirm_password
: null,
// _showHints[3] ? 'Confirm password' : null,
prefixIcon: Icon(
Icons.lock,
color: Colors.blue,
prefixIcon: Padding(
padding: const EdgeInsets.all(8.0), // Adjust the padding as needed
child: Image.asset(
MiscIconAssetPath.lock,
color: Color(0xFF90B0D5),
width: 24,
height: 24,
),
),
suffixIcon: IconButton(
icon: Icon(
icon: Image.asset(
_obscureConfirmPassword
? Icons.visibility_off
: Icons.visibility,
color: Colors.blue,
?MiscIconAssetPath.visibilityOff
:MiscIconAssetPath.visibleOn,
color: Color(0xFF9EA2A9), // Apply color if needed, but keep in mind `Image.asset` might not support color directly.
width: 24,
height: 24,
),
onPressed: () {
setState(() {
@ -600,8 +689,23 @@ class _RegisterScreenState extends State<RegisterScreen> {
});
},
),
border: OutlineInputBorder(),
// border: OutlineInputBorder(
// borderSide: BorderSide(color: Colors.blue, width: 2), // Default border color
// ),
enabledBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFF90B0D5), width: 2), // Enabled border
),
focusedBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Colors.deepPurple, width: 2), // Focused border
),
errorBorder: OutlineInputBorder(
borderRadius: BorderRadius.circular(10),
borderSide: BorderSide(color: Color(0xFFD83731), width: 1), // Error border
),
counterText: '',
hintStyle: TextStyle(color: Color(0xFFC3C6CB)),
),
validator: _validateConfirmPassword,
maxLength: 40,
@ -623,7 +727,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
});
},
side: BorderSide(
color: showError ? Colors.red : Colors.grey,
color: showError ? Colors.red : Color(0xFF92722A),
width: 1.5,
),
),
@ -637,7 +741,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
text: AppLocalizations.of(context)!
.terms_conditions,
// text: 'Terms & Conditions',
style: TextStyle(color: Colors.blue),
style: TextStyle( color: MyTheme.topicColor(IndicatorTopic.economy).shade600,),
),
TextSpan(
text: AppLocalizations.of(context)!
@ -645,7 +749,7 @@ class _RegisterScreenState extends State<RegisterScreen> {
TextSpan(
text: AppLocalizations.of(context)!
.privacy_policy,
style: TextStyle(color: Colors.blue),
style: TextStyle( color: MyTheme.topicColor(IndicatorTopic.economy).shade600,),
),
TextSpan(
text: AppLocalizations.of(context)!
@ -695,8 +799,10 @@ class _RegisterScreenState extends State<RegisterScreen> {
fontSize: 16, color: Colors.white),
),
SizedBox(width: 8),
Icon(Icons.arrow_forward,
color: Colors.white),
const Icon(
Icons.chevron_right_outlined,
color: Colors.white, // Set your desired color here
)
],
),
),
@ -730,8 +836,10 @@ class _RegisterScreenState extends State<RegisterScreen> {
fontSize: 16, color: Colors.white),
),
SizedBox(width: 8),
Icon(Icons.arrow_forward,
color: Colors.white),
const Icon(
Icons.chevron_right_outlined,
color: Colors.white, // Set your desired color here
)
],
),

View File

@ -369,9 +369,15 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
child: ListView.builder(
itemCount: filters.length,
itemBuilder: (context, index) {
filters.sort((a, b) => a["filter_text_and_order"]["order"]
.compareTo(b["filter_text_and_order"]["order"]));
final filter = filters[index];
final filterKey = filter["filter_key"];
final filterData = filter["filter_data"];
final filter_text_and_order =
filter["filter_text_and_order"];
final fieldOrder = filter_text_and_order['order'];
return StatefulBuilder(
builder: (context, setState) {
@ -386,7 +392,9 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(
capitalizeAndSplit(filterKey),
context.translate(filter_text_and_order['en'],
filter_text_and_order['ar']),
// capitalizeAndSplit(filterKey),
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
@ -399,8 +407,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
builder: (BuildContext context) {
return StatefulBuilder(
builder: (context, dialogSetState) {
final locale =
ref.watch(localeProvider);
print('localelocale $locale');
return AlertDialog(
title: Text('Select $filterKey'),
title: Text(
// "${locale == 'ar' ? 'يختار ' : 'Select '}"
"${context.translate(filter_text_and_order['en'], filter_text_and_order['ar'])}"),
content: SingleChildScrollView(
child: ListBody(
children: filterData
@ -465,7 +478,9 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
children:
selectedFilter["filter_data"].isEmpty
? [
Text('Select $filterKey',
Text(
// "${locale == 'ar' ? 'يختار ' : 'Select '}"
"${context.translate(filter_text_and_order['en'], filter_text_and_order['ar'])}",
style: TextStyle(
color: Colors.grey))
]
@ -1023,26 +1038,31 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
Flexible(
fit: FlexFit.loose,
child: FittedBox(
child: Text(
'${chart_heading ?? 'NA'}',
textAlign: TextAlign.center,
maxLines: 2, // Limit to 2 lines
softWrap:
true, // Enable soft wrapping
// overflow: TextOverflow.ellipsis, // Handle overflow gracefully
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
child: SizedBox(
// height: 70.0,
child: Text(
'${chart_heading ?? 'NA'}',
textAlign: TextAlign.center,
maxLines: 2, // Limit to 2 lines
softWrap:
true, // Enable soft wrapping
// overflow: TextOverflow.ellipsis, // Handle overflow gracefully
style: TextStyle(
fontSize: 8,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
),
),
),
const SizedBox(height: 1),
Text(
'(${data['lastYear'] ?? 'NA'})',
style: const TextStyle(
fontSize: 11, color: Colors.grey),
fontSize: 10, color: Colors.grey),
),
const SizedBox(height: 1),
Flexible(
fit: FlexFit.loose,
child: FittedBox(
@ -1051,7 +1071,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
apiService.formatAmount(
data['lastYearValue']),
style: const TextStyle(
fontSize: 26,
fontSize: 18,
fontWeight: FontWeight.w900,
color: Color(0xFF90B0D5),
),
@ -1074,7 +1094,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
apiService.formatAmount(
data['secondLastYearValue']),
style: const TextStyle(
fontSize: 16,
fontSize: 14,
fontWeight: FontWeight.w600,
color: Color(0xFFD83731),
),
@ -1084,7 +1104,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
Text(
'(${data['secondLastYear'] ?? 'NA'})',
style: const TextStyle(
fontSize: 8,
fontSize: 9,
fontWeight: FontWeight.w500,
color: Colors.grey),
),
@ -1120,37 +1140,42 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
const SizedBox(height: 5),
Flexible(
fit: FlexFit.loose,
child: FittedBox(
child: Text(
'${chart_heading ?? 'NA'}',
textAlign: TextAlign.center,
maxLines: 2, // Limit to 2 lines
softWrap:
true, // Enable soft wrapping
// overflow: TextOverflow.ellipsis, // Handle overflow gracefully
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
// child: FittedBox(
child: Text(
'${chart_heading ?? 'NA'}',
textAlign: TextAlign.center,
maxLines: 2, // Limit to 2 lines
softWrap:
true, // Enable soft wrapping
// overflow: TextOverflow.ellipsis, // Handle overflow gracefully
style: TextStyle(
fontSize: 9,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
// ),
),
const SizedBox(height: 1),
Text(
'(${data['firstYear'] ?? 'NA'} - ${data['lastYear'] ?? 'NA'})',
style: const TextStyle(
fontSize: 10, color: Colors.grey),
),
const SizedBox(height: 1),
Flexible(
fit: FlexFit.loose,
child: FittedBox(
fit: BoxFit.contain,
child: Text(
'${data['roundedAverage'] ?? 'NA'}',
style: const TextStyle(
fontSize: 26,
fontWeight: FontWeight.w900,
color: Color(0xFF90B0D5),
child: SizedBox(
height: 50.0,
child: FittedBox(
fit: BoxFit.contain,
child: Text(
'${data['roundedAverage'] ?? 'NA'}',
style: const TextStyle(
fontSize: 20,
fontWeight: FontWeight.w900,
color: Color(0xFF90B0D5),
),
),
),
),

View File

@ -538,6 +538,7 @@ class ChartWidget extends StatelessWidget {
color: groupColorMap[group],
),
SizedBox(width: 6),
Text(
group,
style: TextStyle(fontSize: 14),
@ -789,12 +790,26 @@ class ChartWidget extends StatelessWidget {
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
interval: 1,
getTitlesWidget: (value, meta) {
if (value.toInt() < xAxisData.length) {
String title = xAxisData[value.toInt()];
String displayTitle = title.length > 10 ? title.substring(0, 10) + '...' : title;
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: Text(xAxisData[value.toInt()]),
);
padding: const EdgeInsets.only(top: 8.0),
child: SizedBox(
width: 60, // Limit width to force wrapping
child: Transform.rotate(
angle: -0.5,
child:Tooltip(
message: title,
child: Text(
displayTitle,
softWrap: true,
overflow: TextOverflow.ellipsis,
)),)
));
}
return Container();
},
@ -994,19 +1009,36 @@ class ChartWidget extends StatelessWidget {
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 20, // Added space for rotated titles
reservedSize: 40, // Added space for rotated titles
getTitlesWidget: (value, meta) {
if (value < groupByValues.length) {
String title =
groupByValues.elementAt(value.toInt());
return Transform.rotate(
angle:
-0.5, // Rotation in radians (~ -30 degrees)
child: Text(
title,
style: const TextStyle(fontSize: 12),
),
);
String displayTitle = title.length > 10 ? title.substring(0, 10) + '...' : title;
return Padding(
padding: const EdgeInsets.only(top: 8.0),
child: SizedBox(
width: 60, // Limit width to force wrapping
child: Transform.rotate(
angle: -0.5,
child:Tooltip(
message: title,
child: Text(
displayTitle,
softWrap: true,
overflow: TextOverflow.ellipsis,
)),)
));
// return Transform.rotate(
// angle:
// -0.5, // Rotation in radians (~ -30 degrees)
// child: Text(
// title,
// style: const TextStyle(fontSize: 12),
// ),
// );
}
return const SizedBox.shrink();
},
@ -1150,152 +1182,341 @@ class ChartWidget extends StatelessWidget {
SizedBox(height: 10),
// Chart
Expanded(
child: BarChart(
BarChartData(
maxY: 400000,
rotationQuarterTurns: rotationTurns,
barTouchData: BarTouchData(
touchTooltipData: BarTouchTooltipData(
tooltipHorizontalAlignment: FLHorizontalAlignment.center,
// Only show tooltip when touched
getTooltipItem: (group, groupIndex, rod, rodIndex) {
if (rod.toY == 0 || touchedGroupIndex == -1) {
return null; // Don't show the tooltip if the value is 0 or there's no touch
}
if (groupIndex == touchedGroupIndex) {
// print('Group Index: $groupIndex, Group : $group');
// Get the group label dynamically
String groupLabel = groupByValues.elementAt(groupIndex);
// Fetch the crop for the current group from groupedCrops
String cropType = groupByValues.elementAt(groupIndex);
String crop = groupedCrops[cropType]![rodIndex];
double value = rod.toY;
String formattedValue;
if (value >= 1000000) {
formattedValue =
(value / 1000000).toStringAsFixed(1) + 'M';
} else if (value >= 1000) {
formattedValue =
(value / 1000).toStringAsFixed(1) + 'K';
} else {
formattedValue = value
.toStringAsFixed(0); // for values smaller than 1000
child: BarChart(
BarChartData(
maxY: 400000,
rotationQuarterTurns: rotationTurns,
barTouchData: BarTouchData(
touchTooltipData: BarTouchTooltipData(
tooltipHorizontalAlignment: FLHorizontalAlignment.center,
tooltipRoundedRadius: 8,
fitInsideHorizontally: true, // Ensure it fits within the screen
fitInsideVertically: true,
tooltipPadding: EdgeInsets.all(8),
tooltipMargin: 16,
// Only show tooltip when touched
getTooltipItem: (group, groupIndex, rod, rodIndex) {
if (rod.toY == 0 || touchedGroupIndex == -1) {
return null; // Don't show the tooltip if the value is 0 or there's no touch
}
return BarTooltipItem(
'$groupLabel\n$crop',
const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
children: [
TextSpan(
text: ' Value: $formattedValue',
style: const TextStyle(
color: Colors.yellow,
fontWeight: FontWeight.w500,
if (groupIndex == touchedGroupIndex) {
// print('Group Index: $groupIndex, Group : $group');
// Get the group label dynamically
String groupLabel = groupByValues.elementAt(groupIndex);
// Fetch the crop for the current group from groupedCrops
String cropType = groupByValues.elementAt(groupIndex);
String crop = groupedCrops[cropType]![rodIndex];
double value = rod.toY;
String formattedValue;
if (value >= 1000000) {
formattedValue =
(value / 1000000).toStringAsFixed(1) + 'M';
} else if (value >= 1000) {
formattedValue =
(value / 1000).toStringAsFixed(1) + 'K';
} else {
formattedValue = value.toStringAsFixed(
0); // for values smaller than 1000
}
return BarTooltipItem(
'$groupLabel\n$crop',
const TextStyle(
color: Colors.white,
fontWeight: FontWeight.bold,
),
children: [
TextSpan(
text: ' Value: $formattedValue',
style: const TextStyle(
color: Colors.yellow,
fontWeight: FontWeight.w500,
),
),
),
],
);
}
return null;
},
),
touchCallback: (event, response) {
if (event.isInterestedForInteractions &&
response != null &&
response.spot != null) {
// setState(() {
touchedGroupIndex = response.spot!.touchedBarGroupIndex;
// });
} else {
// setState(() {
touchedGroupIndex = -1; // Reset if no interaction
// });
}
},
),
titlesData: FlTitlesData(
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
reservedSize: 20,
interval: 100000,
getTitlesWidget: (value, meta) {
return Text(
value.toInt().toString(),
style: const TextStyle(fontSize: 12),
);
},
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 80, // Added space for rotated titles
getTitlesWidget: (value, meta) {
if (value < groupByValues.length) {
String title = groupByValues.elementAt(value.toInt());
return Transform.rotate(
angle: -1.58, // Rotation in radians (~ -30 degrees)
child: Center(
child: SizedBox(
width: 80,
child: Text(
title,
style: const TextStyle(fontSize: 12),
softWrap: true,
maxLines: 2,
),
),
),
],
);
}
return const SizedBox.shrink();
return null;
},
),
touchCallback: (event, response) {
if (event.isInterestedForInteractions &&
response != null &&
response.spot != null) {
// setState(() {
touchedGroupIndex = response.spot!.touchedBarGroupIndex;
// });
} else {
// setState(() {
touchedGroupIndex = -1; // Reset if no interaction
// });
}
},
),
rightTitles:
AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles:
AxisTitles(sideTitles: SideTitles(showTitles: false)),
),
borderData: FlBorderData(
show: true,
border: const Border(
// left: BorderSide(color: Colors.grey),
bottom: BorderSide(color: Colors.white),
titlesData: FlTitlesData(
leftTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: false,
reservedSize: 20,
interval: 100000,
getTitlesWidget: (value, meta) {
return Text(
value.toInt().toString(),
style: const TextStyle(fontSize: 12),
);
},
),
),
bottomTitles: AxisTitles(
sideTitles: SideTitles(
showTitles: true,
reservedSize: 80, // Added space for rotated titles
getTitlesWidget: (value, meta) {
if (value < groupByValues.length) {
String title = groupByValues.elementAt(value.toInt());
return Transform.rotate(
angle: -1.58, // Rotation in radians (~ -30 degrees)
child: Center(
child: SizedBox(
width: 80,
child: Text(
title,
style: const TextStyle(fontSize: 12),
softWrap: true,
maxLines: 2,
),
),
),
);
}
return const SizedBox.shrink();
},
),
),
rightTitles:
AxisTitles(sideTitles: SideTitles(showTitles: false)),
topTitles:
AxisTitles(sideTitles: SideTitles(showTitles: false)),
),
borderData: FlBorderData(
show: true,
border: const Border(
// left: BorderSide(color: Colors.grey),
bottom: BorderSide(color: Colors.white),
),
),
gridData: FlGridData(
show: false,
drawVerticalLine: true,
verticalInterval: 1,
horizontalInterval: 100000,
getDrawingHorizontalLine: (value) {
return FlLine(
color: Colors.grey.withOpacity(0.5),
strokeWidth: 1,
);
},
getDrawingVerticalLine: (value) {
return FlLine(
color: Colors.grey.withOpacity(0.5),
strokeWidth: 1,
);
},
),
barGroups:
_buildHorizontalRotateBarGroups(chartData, groupByValues),
alignment: BarChartAlignment.spaceAround,
),
gridData: FlGridData(
show: false,
drawVerticalLine: true,
verticalInterval: 1,
horizontalInterval: 100000,
getDrawingHorizontalLine: (value) {
return FlLine(
color: Colors.grey.withOpacity(0.5),
strokeWidth: 1,
);
},
getDrawingVerticalLine: (value) {
return FlLine(
color: Colors.grey.withOpacity(0.5),
strokeWidth: 1,
);
},
),
barGroups:
_buildHorizontalRotateBarGroups(chartData, groupByValues),
alignment: BarChartAlignment.spaceAround,
),
))
)
// Expanded(
// child: Stack(
// children:[
// BarChart(
// BarChartData(
// maxY: 400000,
// rotationQuarterTurns: rotationTurns,
// barTouchData: BarTouchData(
// touchTooltipData: BarTouchTooltipData(
// tooltipHorizontalAlignment: FLHorizontalAlignment.center,
// // Only show tooltip when touched
// getTooltipItem: (group, groupIndex, rod, rodIndex) {
// if (rod.toY == 0 || touchedGroupIndex == -1) {
// return null; // Don't show the tooltip if the value is 0 or there's no touch
// }
//
// if (groupIndex == touchedGroupIndex) {
// // print('Group Index: $groupIndex, Group : $group');
//
// // Get the group label dynamically
// String groupLabel = groupByValues.elementAt(groupIndex);
//
// // Fetch the crop for the current group from groupedCrops
// String cropType = groupByValues.elementAt(groupIndex);
// String crop = groupedCrops[cropType]![rodIndex];
// double value = rod.toY;
//
// String formattedValue;
// if (value >= 1000000) {
// formattedValue =
// (value / 1000000).toStringAsFixed(1) + 'M';
// } else if (value >= 1000) {
// formattedValue =
// (value / 1000).toStringAsFixed(1) + 'K';
// } else {
// formattedValue = value
// .toStringAsFixed(0); // for values smaller than 1000
// }
//
// return BarTooltipItem(
// '$groupLabel\n$crop',
// const TextStyle(
// color: Colors.white,
// fontWeight: FontWeight.bold,
// ),
// children: [
// TextSpan(
// text: ' Value: $formattedValue',
// style: const TextStyle(
// color: Colors.yellow,
// fontWeight: FontWeight.w500,
// ),
// ),
// ],
// );
// }
// return null;
// },
// ),
// touchCallback: (event, response) {
// if (event.isInterestedForInteractions &&
// response != null &&
// response.spot != null) {
// // setState(() {
// touchedGroupIndex = response.spot!.touchedBarGroupIndex;
// // });
// } else {
// // setState(() {
// touchedGroupIndex = -1; // Reset if no interaction
// // });
// }
// },
// ),
// titlesData: FlTitlesData(
// leftTitles: AxisTitles(
// sideTitles: SideTitles(
// showTitles: false,
// reservedSize: 20,
// interval: 100000,
// getTitlesWidget: (value, meta) {
// return Text(
// value.toInt().toString(),
// style: const TextStyle(fontSize: 12),
// );
// },
// ),
// ),
// bottomTitles: AxisTitles(
// sideTitles: SideTitles(
// showTitles: true,
// reservedSize: 80, // Added space for rotated titles
// getTitlesWidget: (value, meta) {
// if (value < groupByValues.length) {
// String title = groupByValues.elementAt(value.toInt());
// return Transform.rotate(
// angle: -1.58, // Rotation in radians (~ -30 degrees)
// child: Center(
// child: SizedBox(
// width: 80,
// child: Text(
// title,
// style: const TextStyle(fontSize: 12),
// softWrap: true,
// maxLines: 2,
// ),
// ),
// ),
// );
// }
// return const SizedBox.shrink();
// },
// ),
// ),
// rightTitles:
// AxisTitles(sideTitles: SideTitles(showTitles: false)),
// topTitles:
// AxisTitles(sideTitles: SideTitles(showTitles: false)),
// ),
// borderData: FlBorderData(
// show: true,
// border: const Border(
// // left: BorderSide(color: Colors.grey),
// bottom: BorderSide(color: Colors.white),
// ),
// ),
// gridData: FlGridData(
// show: false,
// drawVerticalLine: true,
// verticalInterval: 1,
// horizontalInterval: 100000,
// getDrawingHorizontalLine: (value) {
// return FlLine(
// color: Colors.grey.withOpacity(0.5),
// strokeWidth: 1,
// );
// },
// getDrawingVerticalLine: (value) {
// return FlLine(
// color: Colors.grey.withOpacity(0.5),
// strokeWidth: 1,
// );
// },
// ),
// barGroups:
// _buildHorizontalRotateBarGroups(chartData, groupByValues),
// alignment: BarChartAlignment.spaceAround,
// ),
//
// ),
// // Overlay Texts
// ..._buildHorizontalRotateBarGroups(chartData, groupByValues)
// .asMap()
// .entries
// .expand((entry) {
// int groupIndex = entry.key;
// BarChartGroupData groupData = entry.value;
// return groupData.barRods.asMap().entries.map((rodEntry) {
// int rodIndex = rodEntry.key;
// BarChartRodData rodData = rodEntry.value;
//
// // Position calculation
// double barHeight = rodData.toY / 400000 * MediaQuery.of(context).size.height;
//
// return Positioned(
// left: (groupIndex * 80).toDouble() + 20, // Adjust based on spacing
// bottom: barHeight / 2, // Centered inside the bar
// child: Transform.rotate(
// angle: -0.1,
// child: Text(
// // '${rodData.toY.toInt()}',
// "123",
// style: TextStyle(
// color: Colors.black,
// fontWeight: FontWeight.bold,
// fontSize: 12,
// ),
// ),
// ),
// );
// }).toList();
// }).toList(),
// ]))
]);
default:
return Center(child: Text('Unknown chart type'));
}
@ -1778,12 +1999,11 @@ class ChartWidget extends StatelessWidget {
toY: value, // Use the parsed value
color: barColor, // Dynamic color
width: 20,
// backDrawRodData: BackgroundBarChartRodData(
// backDrawRodData: BackgroundBarChartRodData(
// show: true,
// toY: 400000,
// color: Colors.grey.shade300,
// ),
//
);
}).toList();

View File

@ -1,5 +1,6 @@
import 'package:external_repos/external_repos.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
@ -17,7 +18,7 @@ import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart';
import 'package:uae_stat/presentation/components/space.dart';
import 'package:uae_stat/presentation/components/themed_text_field.dart';
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
import 'package:http/http.dart' as http;
import '../../Screens/auth_verification/registration.dart';
import 'package:pocketbase/pocketbase.dart';
@ -27,7 +28,9 @@ import '../../components/my_toggle.dart';
class LoginRoute extends HookConsumerWidget {
final pb = PocketBase('https://pb.venbait.in');
// final _pb = PocketBase('http://127.0.0.1:8090');
LoginRoute({super.key});
final bool isLoginScreen; // Pass `true` if this is the login screen
LoginRoute({Key? key, required this.isLoginScreen}) : super(key: key);
// LoginRoute({super.key});
dynamic userData;
String? role;
@ -253,6 +256,22 @@ class LoginRoute extends HookConsumerWidget {
if (!context.mounted || session == null) return;
final userId = session.id;
if (userId.isNotEmpty) {
final url =
Uri.parse("https://pb.venbait.in/api/login_success?id=$userId");
try {
final response = await http.get(url);
if (response.statusCode == 200) {
print("Login success API call successful: ${response.body}");
} else {
print(
"Failed to call login success API. Status code: ${response.statusCode}");
}
} catch (e) {
print("Error calling login success API: $e");
}
await saveUserId(userId);
}
try {
@ -340,7 +359,10 @@ class LoginRoute extends HookConsumerWidget {
),
),
6.horizontalSpace,
const Icon(Icons.chevron_right_outlined),
const Icon(
Icons.chevron_right_outlined,
color: Colors.white, // Set your desired color here
)
],
),
),
@ -368,8 +390,7 @@ class LoginRoute extends HookConsumerWidget {
validator: (text) {
if (text == null || text.isEmpty) {
return context.translate('Required', 'مطلوب');
}
else if (text.length < 8) {
} else if (text.length < 8) {
return 'The password must be at least 8 characters';
}
return FieldValidator.password(minLength: 8)(text);
@ -411,7 +432,7 @@ class LoginRoute extends HookConsumerWidget {
10.verticalSpace,
Text(
context.translate(
'Please login to access UAEs key official statistics',
'Please login to access \n UAEs key official statistics',
'يرجى تسجيل الدخول للوصول إلى الإحصاءات الرسمية الرئيسية لدولة الإمارات العربية المتحدة',
),
textAlign: TextAlign.center,
@ -422,7 +443,7 @@ class LoginRoute extends HookConsumerWidget {
),
fontSize: 18,
color: const Color(0xff898C81),
fontWeight: FontWeight.w700,
fontWeight: FontWeight.w600,
),
),
],
@ -466,61 +487,61 @@ class LoginRoute extends HookConsumerWidget {
),
),
);
final continueAsGuestBtn = SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () async {
final prefs = await SharedPreferences.getInstance();
prefs.clear();
final userId = 'guest';
if (userId.isNotEmpty) {
await saveUserId(userId);
}
context.go('/myhomepage');
//context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
},
//context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
style: ButtonStyle(
shape: WidgetStatePropertyAll(
RoundedRectangleBorder(
borderRadius: BorderRadius.circular(10),
),
),
padding: const WidgetStatePropertyAll(
EdgeInsets.symmetric(vertical: 10.5),
),
textStyle: WidgetStatePropertyAll(
TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 16,
fontWeight: FontWeight.w600,
),
),
backgroundColor: WidgetStatePropertyAll(
MyTheme.topicColor(IndicatorTopic.environment),
),
foregroundColor: const WidgetStatePropertyAll(
Colors.white,
),
),
child: Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
context.translate(
'Continue as Guest',
'استمر كضيف',
),
),
6.horizontalSpace,
const Icon(Icons.chevron_right_outlined),
],
),
),
);
// final continueAsGuestBtn = SizedBox(
// width: double.infinity,
// child: ElevatedButton(
// onPressed: () async {
// final prefs = await SharedPreferences.getInstance();
// prefs.clear();
// final userId = 'guest';
// if (userId.isNotEmpty) {
// await saveUserId(userId);
// }
// context.go('/myhomepage');
// //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
// },
// //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
// style: ButtonStyle(
// shape: WidgetStatePropertyAll(
// RoundedRectangleBorder(
// borderRadius: BorderRadius.circular(10),
// ),
// ),
// padding: const WidgetStatePropertyAll(
// EdgeInsets.symmetric(vertical: 10.5),
// ),
// textStyle: WidgetStatePropertyAll(
// TextStyle(
// fontFamily: context.translate(
// 'Roboto',
// 'NotoKufi',
// ),
// fontSize: 16,
// fontWeight: FontWeight.w600,
// ),
// ),
// backgroundColor: WidgetStatePropertyAll(
// MyTheme.topicColor(IndicatorTopic.environment),
// ),
// foregroundColor: const WidgetStatePropertyAll(
// Colors.white,
// ),
// ),
// child: Row(
// mainAxisAlignment: MainAxisAlignment.center,
// children: [
// Text(
// context.translate(
// 'Continue as Guest',
// 'استمر كضيف',
// ),
// ),
// 6.horizontalSpace,
// const Icon(Icons.chevron_right_outlined),
// ],
// ),
// ),
// );
final fcscBanner = Image.asset(
BannerAssetPath.fcsc,
height: 40,
@ -554,15 +575,46 @@ class LoginRoute extends HookConsumerWidget {
20.verticalSpace,
dontHaveAnAccountRegisterBtn,
20.verticalSpace,
continueAsGuestBtn,
// continueAsGuestBtn,
25.verticalSpace,
fcscBanner,
],
);
final bgScaffold = Scaffold(
backgroundColor: Colors.white,
body: SafeArea(child: scaffoldBody),
// final bgScaffold = Scaffold(
// backgroundColor: Colors.white,
// body: SafeArea(child: scaffoldBody),
// );
// return bgScaffold;
return PopScope(
canPop: !isLoginScreen, // Allow back navigation only if not login screen
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
_showExitConfirmation(context); // Show exit confirmation dialog
},
child: Scaffold(
backgroundColor: Colors.white,
body: SafeArea(child: scaffoldBody),
),
);
}
void _showExitConfirmation(BuildContext context) {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text("Exit App"),
content: Text("Are you sure you want to exit?"),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(), // Close dialog
child: Text("Cancel"),
),
TextButton(
onPressed: () => SystemNavigator.pop(), // Exit the app
child: Text("Exit"),
),
],
),
);
return bgScaffold;
}
}

View File

@ -165,6 +165,8 @@ import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart';
@ -205,7 +207,7 @@ class EconomyStatsWidget extends ConsumerStatefulWidget {
class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
List<dynamic> data = [];
final _pb = PocketBase('https://pb.venbait.in');
bool isLoading = true;
final GlobalKey cardTopicKey = GlobalKey();
@ -213,11 +215,12 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
late TutorialCoachMark tutorialCoachMark;
late List<TargetFocus> homeTargets;
late List<TargetFocus> previousHomeTargets;
Offset _imageCardPosition =Offset.zero;
Offset _imageTopicPosition =Offset.zero;
Offset _imageCardPosition = Offset.zero;
Offset _imageTopicPosition = Offset.zero;
void _calculateCardPosition() {
final RenderBox cardRenderBox = cardsKey.currentContext!.findRenderObject() as RenderBox;
final RenderBox cardRenderBox =
cardsKey.currentContext!.findRenderObject() as RenderBox;
final Offset cardPosition = cardRenderBox.localToGlobal(Offset.zero);
final Size cardSize = cardRenderBox.size;
@ -233,10 +236,10 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
void handleSkip() {
tutorialCoachMark.skip();
debugPrint('Skip clicked');
ref.read(chartsTourProvider.notifier).state = true;
ref.read(previousChartsTourProvider.notifier).state = true;
ref.read(homeTourProvider.notifier).state = true;
ref.read( previousHomeTourProvider.notifier).state = true;
ref.read(chartsTourProvider.notifier).state = true;
ref.read(previousChartsTourProvider.notifier).state = true;
ref.read(homeTourProvider.notifier).state = true;
ref.read(previousHomeTourProvider.notifier).state = true;
ref.read(scaffoldTourProvider.notifier).state = true;
ref.read(previousScaffoldTourProvider.notifier).state = true;
}
@ -288,11 +291,10 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
},
)..show(context: context);
}
}
void _initTarget(){
homeTargets=[
void _initTarget() {
homeTargets = [
TargetFocus(
identify: 'cardTopicKey',
keyTarget: cardTopicKey,
@ -308,7 +310,7 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
align: ContentAlign.bottom,
child: SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height*0.69,
height: MediaQuery.of(context).size.height * 0.69,
child: Stack(
children: [
Positioned(
@ -353,12 +355,14 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xFF7DAFBC),
border: Border.all(color: Color(0xFF7DAFBC), width: 1),
border: Border.all(
color: Color(0xFF7DAFBC), width: 1),
),
child: IconButton(
padding: EdgeInsets.zero,
iconSize: 20,
icon: const Icon(Icons.arrow_forward, color: Colors.white),
icon: const Icon(Icons.arrow_forward,
color: Colors.white),
onPressed: () {
tutorialCoachMark.next();
},
@ -379,21 +383,18 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
align: ContentAlign.bottom,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height:MediaQuery.of(context).size.height*0.69 ,
child: Stack(
children: [
Positioned(
left: MediaQuery.of(context).size.width*0.4,
top: _imageCardPosition.dy-29,
child: Image.asset(
'assets/app_tour/down_right.png',
width: 40,
height: 90,
),
),
]
),
height: MediaQuery.of(context).size.height * 0.69,
child: Stack(children: [
Positioned(
left: MediaQuery.of(context).size.width * 0.4,
top: _imageCardPosition.dy - 29,
child: Image.asset(
'assets/app_tour/down_right.png',
width: 40,
height: 90,
),
),
]),
),
),
],
@ -404,17 +405,17 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
shape: ShapeLightFocus.RRect,
contents: [
createTargetContent(
text:AppLocalizations.of(context)!.economy,
text: AppLocalizations.of(context)!.economy,
alignment: ContentAlign.bottom,
gap: 0,
space: 40,),
space: 40,
),
TargetContent(
align: ContentAlign.bottom,
child:
SizedBox(
child: SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height *0.5, // Set an appropriate height for the Stack
height: MediaQuery.of(context).size.height *
0.5, // Set an appropriate height for the Stack
child: Stack(
children: [
Positioned(
@ -425,7 +426,7 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
onPressed: () =>handleSkip,
onPressed: () => handleSkip,
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
@ -457,11 +458,13 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2.0),
border: Border.all(
color: Colors.white, width: 2.0),
),
child: IconButton(
iconSize: 20,
icon: const Icon(Icons.arrow_back, color: Colors.white),
icon: const Icon(Icons.arrow_back,
color: Colors.white),
onPressed: () {
tutorialCoachMark.previous();
},
@ -472,11 +475,13 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xFF7DAFBC),
border: Border.all(color: Color(0xFF7DAFBC), width: 1),
border: Border.all(
color: Color(0xFF7DAFBC), width: 1),
),
child: IconButton(
iconSize: 20,
icon: const Icon(Icons.arrow_forward, color: Colors.white),
icon: const Icon(Icons.arrow_forward,
color: Colors.white),
onPressed: () {
tutorialCoachMark.next();
},
@ -496,22 +501,19 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
TargetContent(
align: ContentAlign.bottom,
child: SizedBox(
width: MediaQuery.of(context).size.width ,
height:MediaQuery.of(context).size.height*0.69 ,
child: Stack(
children: [
Positioned(
left: MediaQuery.of(context).size.width*0.40,
top: _imageTopicPosition.dy-29,
child: Image.asset(
'assets/app_tour/down_right.png',
width: 40,
height: 90,
),
),
]
),
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height * 0.69,
child: Stack(children: [
Positioned(
left: MediaQuery.of(context).size.width * 0.40,
top: _imageTopicPosition.dy - 29,
child: Image.asset(
'assets/app_tour/down_right.png',
width: 40,
height: 90,
),
),
]),
),
),
],
@ -519,24 +521,25 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
];
}
void _initPreviousTarget(){
previousHomeTargets=[
void _initPreviousTarget() {
previousHomeTargets = [
TargetFocus(
identify: 'cardsKey',
keyTarget: cardsKey,
shape: ShapeLightFocus.RRect,
contents: [
createTargetContent(
text:AppLocalizations.of(context)!.economy,
text: AppLocalizations.of(context)!.economy,
alignment: ContentAlign.bottom,
gap: 0,
space: 40,),
space: 40,
),
TargetContent(
align: ContentAlign.bottom,
child:
SizedBox(
child: SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height *0.5, // Set an appropriate height for the Stack
height: MediaQuery.of(context).size.height *
0.5, // Set an appropriate height for the Stack
child: Stack(
children: [
Positioned(
@ -547,7 +550,7 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
ElevatedButton(
onPressed: () =>handleSkip(),
onPressed: () => handleSkip(),
style: ElevatedButton.styleFrom(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
@ -579,10 +582,12 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
Container(
decoration: BoxDecoration(
shape: BoxShape.circle,
border: Border.all(color: Colors.white, width: 2.0),
border: Border.all(
color: Colors.white, width: 2.0),
),
child: IconButton(
icon: const Icon(Icons.arrow_back, color: Colors.white),
icon: const Icon(Icons.arrow_back,
color: Colors.white),
onPressed: () {
tutorialCoachMark.next();
},
@ -593,14 +598,21 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xFF7DAFBC),
border: Border.all(color: Color(0xFF7DAFBC), width: 1.5),
border: Border.all(
color: Color(0xFF7DAFBC), width: 1.5),
),
child: IconButton(
iconSize: 20,
icon: const Icon(Icons.arrow_forward, color: Colors.white),
icon: const Icon(Icons.arrow_forward,
color: Colors.white),
onPressed: () {
ref.read(previousHomeTourProvider.notifier).state=true;
ref.read(chartsTourProvider.notifier).state=false;
ref
.read(
previousHomeTourProvider.notifier)
.state = true;
ref
.read(chartsTourProvider.notifier)
.state = false;
tutorialCoachMark.finish();
},
),
@ -620,21 +632,18 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
align: ContentAlign.bottom,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height:MediaQuery.of(context).size.height*0.69 ,
child: Stack(
children: [
Positioned(
left: MediaQuery.of(context).size.width*0.40,
top: _imageTopicPosition.dy-29,
child: Image.asset(
'assets/app_tour/down_right.png',
width: 40,
height: 90,
),
),
]
),
height: MediaQuery.of(context).size.height * 0.69,
child: Stack(children: [
Positioned(
left: MediaQuery.of(context).size.width * 0.40,
top: _imageTopicPosition.dy - 29,
child: Image.asset(
'assets/app_tour/down_right.png',
width: 40,
height: 90,
),
),
]),
),
),
],
@ -645,7 +654,7 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
shape: ShapeLightFocus.RRect,
contents: [
createTargetContent(
text:AppLocalizations.of(context)!.home_topic,
text: AppLocalizations.of(context)!.home_topic,
alignment: ContentAlign.bottom,
gap: 45,
space: 40,
@ -654,7 +663,7 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
align: ContentAlign.bottom,
child: SizedBox(
width: double.infinity,
height: MediaQuery.of(context).size.height*0.69,
height: MediaQuery.of(context).size.height * 0.69,
child: Stack(
children: [
Positioned(
@ -702,11 +711,13 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
decoration: BoxDecoration(
shape: BoxShape.circle,
color: Color(0xFF7DAFBC),
border: Border.all(color: Color(0xFF7DAFBC), width: 1.5),
border: Border.all(
color: Color(0xFF7DAFBC), width: 1.5),
),
child: IconButton(
iconSize: 20,
icon: const Icon(Icons.arrow_forward, color: Colors.white),
icon: const Icon(Icons.arrow_forward,
color: Colors.white),
onPressed: () {
tutorialCoachMark.previous();
},
@ -727,21 +738,18 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
align: ContentAlign.bottom,
child: SizedBox(
width: MediaQuery.of(context).size.width,
height:MediaQuery.of(context).size.height*0.69 ,
child: Stack(
children: [
Positioned(
left: MediaQuery.of(context).size.width*0.4,
top: _imageCardPosition.dy-29,
child: Image.asset(
'assets/app_tour/down_right.png',
width: 40,
height: 90,
),
),
]
),
height: MediaQuery.of(context).size.height * 0.69,
child: Stack(children: [
Positioned(
left: MediaQuery.of(context).size.width * 0.4,
top: _imageCardPosition.dy - 29,
child: Image.asset(
'assets/app_tour/down_right.png',
width: 40,
height: 90,
),
),
]),
),
),
],
@ -749,15 +757,12 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
];
}
@override
void initState() {
super.initState();
final locale = ref.read(localeProvider);
fetchData(locale?.languageCode ?? 'en');
WidgetsBinding.instance.addPostFrameCallback((_) {
_starTourRender();
});
_fetchUserData();
}
// @override
@ -768,6 +773,37 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
// fetchData(locale); // Pass the locale to the fetchData method
// }
Future<String?> getUserId() async {
final prefs = await SharedPreferences.getInstance();
return prefs.getString('userId'); // Retrieve the userId
}
Future<void> _fetchUserData() async {
try {
final userId = await getUserId();
print('EDIT PROFILE isPageLoad');
final adminAuth = await _pb.admins
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
final adminToken = adminAuth.token;
print('adminToken- $adminToken');
final userDetailsResponse = await _pb.collection('users').getOne(
userId!,
headers: {
'Authorization': 'Bearer $adminToken',
},
);
final loginCount = userDetailsResponse.data['login_count'];
print(loginCount);
if (loginCount == 1) {
WidgetsBinding.instance.addPostFrameCallback((_) {
_starTourRender();
});
}
} catch (e) {
print('Error fetching user details: $e');
}
}
Future<void> fetchData(locale) async {
const baseUrl = 'https://pb.venbait.in/api/getHomePageData';
try {
@ -875,7 +911,7 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
crossAxisAlignment: CrossAxisAlignment.start,
children: [
RoundedCornerContainer(
key: mainTopic['main_topic'] =='ECONOMY'
key: mainTopic['main_topic'] == 'ECONOMY'
? cardTopicKey
: null,
text: mainTopic['main_topic'],
@ -889,7 +925,7 @@ class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
SizedBox(
height: myheight / 4.8, // Set dynamic height
child: Container(
key:mainTopic['main_topic'] == 'ECONOMY'
key: mainTopic['main_topic'] == 'ECONOMY'
? cardsKey
: null,
// color: Colors.grey[200], // Set a background color for the scrollable container
@ -1111,7 +1147,6 @@ class InfoCard extends StatelessWidget {
final encodedTitle = Uri.encodeComponent(title);
final encodedKey = Uri.encodeQueryComponent('home');
return GestureDetector(
onTap: () {
context.go(

View File

@ -2,7 +2,7 @@ name: uae_stat
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
publish_to: "none"
#version: 0.5.10
version: 1.0.5+6
version: 1.0.6+7
environment:
sdk: ">=3.2.3 <4.0.0"
@ -117,6 +117,9 @@ flutter:
- assets/app_tour/
- assets/icons/uae_numbers/bookmarks.png
- assets/icons/uae_numbers/share.png
- assets/icons/misc/vector.png
- assets/icons/misc/visible_on.png
- assets/icons/misc/visibility_off.png
fonts:
- family: Segoe