bug fix and forgot password

This commit is contained in:
venbaittech 2025-03-27 18:43:32 +05:30
parent a0d7a733a4
commit efb0d38664
11 changed files with 636 additions and 502 deletions

View File

@ -20,12 +20,12 @@ if (project.hasProperty('google-services.json')) {
def flutterVersionCode = localProperties.getProperty("flutter.versionCode") def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = "43" flutterVersionCode = "44"
} }
def flutterVersionName = localProperties.getProperty("flutter.versionName") def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) { if (flutterVersionName == null) {
flutterVersionName = "1.0.42" flutterVersionName = "1.0.43"
} }
def keystorePropertiesFile = rootProject.file("key.properties") def keystorePropertiesFile = rootProject.file("key.properties")

View File

@ -30,13 +30,27 @@
<meta-data android:name="flutter_deeplinking_enabled" <meta-data android:name="flutter_deeplinking_enabled"
android:value="true"/> android:value="true"/>
<intent-filter android:autoVerify="true"> <intent-filter android:autoVerify="true">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="https" android:host="www.fcsc.com"/>
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" /> <category android:name="android.intent.category.BROWSABLE" />
<data <data
android:scheme="https" android:scheme="flutterdeeplink"
android:host="fcsc-a161c.web.app" android:host="fcsc"
android:pathPrefix="/login" />
<data
android:scheme="flutterdeeplink"
android:host="fcsc"
android:pathPrefix="/chartScreen"/> android:pathPrefix="/chartScreen"/>
<data
android:scheme="flutterdeeplink"
android:host="fcsc"
android:pathPrefix="/forgot-password"/>
</intent-filter> </intent-filter>
<!-- <intent-filter >--> <!-- <intent-filter >-->
<!-- <action android:name="android.intent.action.VIEW" />--> <!-- <action android:name="android.intent.action.VIEW" />-->

View File

@ -667,7 +667,8 @@ final GoRouter router = GoRouter(
redirect: (context, state) async { redirect: (context, state) async {
if (state.uri.path == '/SessionCheckScreen' || if (state.uri.path == '/SessionCheckScreen' ||
state.uri.path == '/login' || state.uri.path == '/login' ||
state.uri.path == '/register') { state.uri.path == '/register' ||
state.uri.path == '/forgot-password/:email') {
return null; return null;
} }

View File

@ -240,7 +240,8 @@ class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
onChanged: (value) { onChanged: (value) {
filterData( filterData(
value); // Call filter function directly on input change value); // Call filter function directly on input change
}, }, // Ensures vertical alignment
// Centers text horizontally
decoration: InputDecoration( decoration: InputDecoration(
hintText: AppLocalizations.of(context)!.search, hintText: AppLocalizations.of(context)!.search,
hintStyle: TextStyle(color: Color(0xFFAA8E83)), hintStyle: TextStyle(color: Color(0xFFAA8E83)),
@ -261,8 +262,9 @@ class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
// // fit: BoxFit.contain, // // fit: BoxFit.contain,
// ), // ),
border: InputBorder.none, border: InputBorder.none,
contentPadding: // contentPadding:
EdgeInsets.symmetric(vertical: 9, horizontal: 18.0), // EdgeInsets.symmetric(vertical: 9, horizontal: 18.0),
contentPadding: EdgeInsets.zero,
), ),
), ),
), ),

View File

@ -107,6 +107,66 @@ class _ForgotPasswordState extends ConsumerState<ForgotPassword> {
return null; return null;
} }
// Future<void> updatePassword(
// String email, String oldPassword, String newPassword) async {
// print(email);
// try {
// setState(() {
// isLoading = true;
// });
// // Authenticate as admin
// final adminAuth = await _pb.admins
// .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
// final token = adminAuth.token;
//
// final headers = {
// 'Authorization': 'Bearer $token',
// };
//
// // Update password
// await _pb.collection('users').update(
// email,
// body: {
// 'password': newPassword,
// 'passwordConfirm': newPassword,
// },
// headers: headers,
// );
//
// setState(() {
// isLoading = false;
// _isPasswordUpdated = true;
// });
//
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content:
// Text(AppLocalizations.of(context)!.password_update_successfully),
// backgroundColor: Colors.green,
// ),
// );
//
// print('_isPasswordUpdated $_isPasswordUpdated');
//
// // Navigator.push(
// // context,
// // MaterialPageRoute(
// // builder: (context) => ProfileScreen(userId: userId)),
// // );
// } catch (e) {
// setState(() {
// isLoading = false;
// });
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(context.translate(
// 'Failed to update password: $e', 'فشل في تحديث كلمة المرور')),
// backgroundColor: Colors.red,
// ),
// );
// }
// }
Future<void> updatePassword( Future<void> updatePassword(
String email, String oldPassword, String newPassword) async { String email, String oldPassword, String newPassword) async {
try { try {
@ -122,9 +182,27 @@ class _ForgotPasswordState extends ConsumerState<ForgotPassword> {
'Authorization': 'Bearer $token', 'Authorization': 'Bearer $token',
}; };
// Update password // Step 1: Find User by Email
final result = await _pb.collection('users').getList(
filter: 'email = "$email"',
headers: headers,
);
if (result.items.isEmpty) {
// throw Exception("User not found");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('User not found'),
backgroundColor: Colors.red,
),
);
}
final userId = result.items.first.id;
// Step 3: Update Password
await _pb.collection('users').update( await _pb.collection('users').update(
email, userId,
body: { body: {
'password': newPassword, 'password': newPassword,
'passwordConfirm': newPassword, 'passwordConfirm': newPassword,
@ -146,19 +224,14 @@ class _ForgotPasswordState extends ConsumerState<ForgotPassword> {
); );
print('_isPasswordUpdated $_isPasswordUpdated'); print('_isPasswordUpdated $_isPasswordUpdated');
// Navigator.push(
// context,
// MaterialPageRoute(
// builder: (context) => ProfileScreen(userId: userId)),
// );
} catch (e) { } catch (e) {
setState(() { setState(() {
isLoading = false; isLoading = false;
}); });
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar( SnackBar(
content: Text(context.translate('Failed to update password: $e','فشل في تحديث كلمة المرور')), content: Text('Failed to update password: $e'),
backgroundColor: Colors.red, backgroundColor: Colors.red,
), ),
); );

View File

@ -2695,50 +2695,54 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
} }
} }
Future<void> shareCurrentPage(BuildContext context, bool _isSharing) async { Future<void> shareCurrentPage(BuildContext context, bool isSharing) async {
if (_isSharing) return; // Prevent multiple taps if (isSharing) return; // Prevent multiple taps
_isSharing = true; isSharing = true;
try { try {
final String currentRoute = GoRouterState.of(context).uri.toString(); final String currentRoute = GoRouterState.of(context).uri.toString();
final String baseAppLink = 'https://fcsc-a161c.web.app'; final String baseAppLink = 'https://www.fcsc.com';
final String shareLink = '$baseAppLink$currentRoute'; final String shareLink = '$baseAppLink$currentRoute';
final String shareText = 'Check this out!'; final String shareText = 'Check this out!\n\n$shareLink';
final String svgAssetPath = 'assets/backgrounds/share/fcsc.svg'; print('Generated Share Link: $shareLink');
// Optional: Capture SVG to image
final String svgAssetPath = 'assets/backgrounds/share/fcsc.svg';
final screenshotController = ScreenshotController(); final screenshotController = ScreenshotController();
final svgWidget = SvgPicture.asset( final svgWidget = SvgPicture.asset(
svgAssetPath, svgAssetPath,
width: 200, width: 200,
height: 200, height: 200,
); );
final Uint8List? capturedImage = final Uint8List? capturedImage =
await screenshotController.captureFromWidget( await screenshotController.captureFromWidget(
Material(child: svgWidget), Material(child: svgWidget),
); );
if (capturedImage == null) { if (capturedImage == null) {
throw Exception('Failed to capture SVG as image'); print('SVG capture failed, proceeding without image.');
} await Share.share(shareText, subject: 'App Link');
} else {
final directory = await getTemporaryDirectory(); final directory = await getTemporaryDirectory();
final file = File('${directory.path}/share.svg'); final file = File('${directory.path}/share_image.png');
await file.writeAsBytes(capturedImage); await file.writeAsBytes(capturedImage);
await Share.shareXFiles( await Share.shareXFiles(
[XFile(file.path)], [XFile(file.path)],
text: '$shareText\n$shareLink', text: shareText,
subject: 'Shared Content', subject: 'Shared Content',
); );
await file.delete(); await file.delete();
}
} catch (e) { } catch (e) {
print("Error sharing file: $e"); print("Error sharing content: $e");
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error sharing: $e')), SnackBar(content: Text('Error sharing: ${e.toString()}')),
); );
} finally { } finally {
_isSharing = false; // Reset flag after sharing completes isSharing = false; // Reset flag
} }
} }

View File

@ -4,6 +4,7 @@ import 'dart:math';
import 'package:fl_chart/fl_chart.dart'; import 'package:fl_chart/fl_chart.dart';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:uae_stat/domain/use_cases/language.dart';
// import 'package:syncfusion_flutter_charts/charts.dart'; // import 'package:syncfusion_flutter_charts/charts.dart';
class ChartWidget extends StatelessWidget { class ChartWidget extends StatelessWidget {
@ -208,8 +209,7 @@ class ChartWidget extends StatelessWidget {
x: entry['ObsKey']['TIME_PERIOD'], x: entry['ObsKey']['TIME_PERIOD'],
y: double.tryParse(entry['ObsValue']['Value']) ?? 0.0, y: double.tryParse(entry['ObsValue']['Value']) ?? 0.0,
); );
}) }).toList();
.toList();
} }
List<BarChartGroupData> parseColumnChartData(dynamic chartData) { List<BarChartGroupData> parseColumnChartData(dynamic chartData) {
@ -380,7 +380,8 @@ class ChartWidget extends StatelessWidget {
// ]; // ];
// } // }
List<Widget> generateIndicators(dynamic chartData, double totalValue) { List<Widget> generateIndicators(
dynamic chartData, double totalValue, BuildContext context) {
var groupByKeyValue; var groupByKeyValue;
if (chartData['chart_type_json']['chart_type'] == 'bar_chart_horizontal' || if (chartData['chart_type_json']['chart_type'] == 'bar_chart_horizontal' ||
chartData['chart_type_json']['chart_type'] == 'horizontal_rotate') { chartData['chart_type_json']['chart_type'] == 'horizontal_rotate') {
@ -412,50 +413,83 @@ class ChartWidget extends StatelessWidget {
} }
// double percentage = (value / totalValue) * 100; // double percentage = (value / totalValue) * 100;
String percentage = String percentage = (totalValue > 0)
(totalValue > 0)
? ((value / totalValue) * 100).toStringAsFixed(1) ? ((value / totalValue) * 100).toStringAsFixed(1)
: "0.0"; : "0.0";
// bool isTouched = index == touchedIndex; // bool isTouched = index == touchedIndex;
// return Wrap(
// alignment: WrapAlignment.center,
// spacing: 12,
// runSpacing: 8,
// children: [
// Row(
// mainAxisSize: MainAxisSize.min,
// children: [
// Container(
// width: 10,
// height: 10,
// decoration: BoxDecoration(
// color: uniqueColors[index % uniqueColors.length],
// shape: BoxShape.circle,
// ),
// ),
// SizedBox(width: 8),
// Flexible(
// child: Text(
// context.translate(
// '$title -- $percentage%',
// '$title -- %$percentage',
// ),
// textAlign: TextAlign.start,
// style: TextStyle(fontSize: 12),
// softWrap: true,
// maxLines: 2, // Allows wrapping within two lines
// overflow: TextOverflow.ellipsis, // Prevents overflow
// ),
// ),
// ],
// ),
// ],
// );
return Row( return Row(
mainAxisSize: MainAxisSize.min, crossAxisAlignment:
CrossAxisAlignment.start, // Aligns dot to text start
children: [ children: [
Container( Container(
width: 10, width: 10,
height: 10, height: 10,
margin: EdgeInsets.only(top: 4), // Adjust to align with text
decoration: BoxDecoration( decoration: BoxDecoration(
color: uniqueColors[index % uniqueColors.length], color: uniqueColors[index % uniqueColors.length],
shape: BoxShape.circle, shape: BoxShape.circle,
), ),
), ),
SizedBox(width: 8), SizedBox(width: 8),
TooltipTheme( Expanded(
child: TooltipTheme(
data: TooltipThemeData( data: TooltipThemeData(
decoration: BoxDecoration( decoration: BoxDecoration(
color: Colors.blueGrey[800], // Change background color color: Colors.blueGrey[800], // Change background color
borderRadius: BorderRadius.circular( borderRadius: BorderRadius.circular(8),
8,
), // Optional: rounded corners
), ),
textStyle: TextStyle(color: Colors.white), // Change text color textStyle: TextStyle(color: Colors.white),
), ),
child: Tooltip( child: Tooltip(
message: title, // Full text on hover message: title, // Full text on hover
child: ConstrainedBox(
// Constrain width to allow wrapping
constraints: BoxConstraints(maxWidth: 250),
child: Text( child: Text(
context.translate(
'$title -- $percentage%', '$title -- $percentage%',
'$title -- %$percentage',
),
style: TextStyle(fontSize: 12), style: TextStyle(fontSize: 12),
softWrap: true, softWrap: true,
maxLines: 2, maxLines: 2,
// overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow
), ),
), ),
), ),
), ),
SizedBox(width: 5),
], ],
); );
}).toList(); }).toList();
@ -618,8 +652,7 @@ class ChartWidget extends StatelessWidget {
), ),
); );
case 'pie_chart': case 'pie_chart':
double totalValue = chartData['response'] double totalValue = chartData['response'].map<double>((entry) {
.map<double>((entry) {
var value = entry['ObsValue']['Value']; var value = entry['ObsValue']['Value'];
// print('Processing value: $value, type: ${value.runtimeType}'); // print('Processing value: $value, type: ${value.runtimeType}');
return (value is num) return (value is num)
@ -627,8 +660,7 @@ class ChartWidget extends StatelessWidget {
: value is String : value is String
? double.tryParse(value) ?? 0.0 ? double.tryParse(value) ?? 0.0
: 0.0; : 0.0;
}) }).fold(0.0, (prev, element) => prev + element);
.fold(0.0, (prev, element) => prev + element);
ValueNotifier<int?> touchedIndex = ValueNotifier(null); ValueNotifier<int?> touchedIndex = ValueNotifier(null);
@ -665,10 +697,8 @@ class ChartWidget extends StatelessWidget {
touchCallback: (FlTouchEvent event, pieTouchResponse) { touchCallback: (FlTouchEvent event, pieTouchResponse) {
if (pieTouchResponse?.touchedSection != null && if (pieTouchResponse?.touchedSection != null &&
event is! FlTapUpEvent) { event is! FlTapUpEvent) {
touchedIndex.value = touchedIndex.value = pieTouchResponse!
pieTouchResponse! .touchedSection!.touchedSectionIndex;
.touchedSection!
.touchedSectionIndex;
} else { } else {
touchedIndex.value = touchedIndex.value =
null; // Reset when not touching null; // Reset when not touching
@ -704,7 +734,8 @@ class ChartWidget extends StatelessWidget {
child: Column( child: Column(
// Change Row to Column // Change Row to Column
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: generateIndicators(chartData, totalValue), children:
generateIndicators(chartData, totalValue, context),
), ),
), ),
), ),
@ -870,8 +901,7 @@ class ChartWidget extends StatelessWidget {
child: Wrap( child: Wrap(
spacing: 10, // Horizontal spacing between items spacing: 10, // Horizontal spacing between items
runSpacing: 5, // Vertical spacing between rows runSpacing: 5, // Vertical spacing between rows
children: children: chunkedGroupByValues.expand((chunk) {
chunkedGroupByValues.expand((chunk) {
return chunk.map((group) { return chunk.map((group) {
List<String> groupByValuesList = groupByValues.toList(); List<String> groupByValuesList = groupByValues.toList();
int index = groupByValuesList.indexOf(group); int index = groupByValuesList.indexOf(group);
@ -938,8 +968,7 @@ class ChartWidget extends StatelessWidget {
print('LnTrnd1'); print('LnTrnd1');
// Extract all years from the chart data // Extract all years from the chart data
List<int> years = List<int> years = (chartData['response'] as List<dynamic>)
(chartData['response'] as List<dynamic>)
.map<int>( .map<int>(
(entry) => (entry) =>
int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0,
@ -974,8 +1003,7 @@ class ChartWidget extends StatelessWidget {
// Filter chart data to only include entries within the last 5 years // Filter chart data to only include entries within the last 5 years
List<dynamic> filteredData = List<dynamic> filteredData =
(chartData['response'] as List<dynamic>).where((entry) { (chartData['response'] as List<dynamic>).where((entry) {
int year = int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0;
int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0;
return year >= minYear && year <= maxYear; return year >= minYear && year <= maxYear;
}).toList(); }).toList();
print('LnTrnd2 $filteredData'); print('LnTrnd2 $filteredData');
@ -985,8 +1013,7 @@ class ChartWidget extends StatelessWidget {
// (entry) => double.parse(entry['ObsKey']['TIME_PERIOD'])) // (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']))
// .toSet(); // .toSet();
Set<String> uniqueXValues = Set<String> uniqueXValues = filteredData.map<String>((entry) {
filteredData.map<String>((entry) {
String? timePeriod = String? timePeriod =
entry['ObsKey']['TIME_PERIOD']; // Nullable String entry['ObsKey']['TIME_PERIOD']; // Nullable String
print('TIME_PERIOD- $timePeriod'); print('TIME_PERIOD- $timePeriod');
@ -1050,8 +1077,7 @@ class ChartWidget extends StatelessWidget {
throw FormatException("Invalid TIME_PERIOD format: $timePeriod"); throw FormatException("Invalid TIME_PERIOD format: $timePeriod");
} }
Set<double> uniqueXValuesProcessed = Set<double> uniqueXValuesProcessed = uniqueXValues
uniqueXValues
.where((value) => value.isNotEmpty) // Remove any empty strings .where((value) => value.isNotEmpty) // Remove any empty strings
.map(parseTimePeriod) .map(parseTimePeriod)
.toSet(); .toSet();
@ -1150,8 +1176,7 @@ class ChartWidget extends StatelessWidget {
child: Wrap( child: Wrap(
spacing: 12, spacing: 12,
runSpacing: 8, runSpacing: 8,
children: children: groupByValues.map((group) {
groupByValues.map((group) {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -1185,8 +1210,7 @@ class ChartWidget extends StatelessWidget {
// } // }
// Extract all years from the chart data // Extract all years from the chart data
List<int> years = List<int> years = (chartData['response'] as List<dynamic>)
(chartData['response'] as List<dynamic>)
.map<int>( .map<int>(
(entry) => (entry) =>
int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0,
@ -1212,13 +1236,11 @@ class ChartWidget extends StatelessWidget {
// Filter chart data to include only the selected 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 year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0;
int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0;
return selectedYears.contains(year); return selectedYears.contains(year);
}).toList(); }).toList();
Set<double> uniqueXValues = Set<double> uniqueXValues = filteredData
filteredData
.map<double>( .map<double>(
(entry) => double.parse(entry['ObsKey']['TIME_PERIOD']), (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']),
) )
@ -1296,8 +1318,7 @@ class ChartWidget extends StatelessWidget {
scrollDirection: Axis.horizontal, // Enable horizontal scrolling scrollDirection: Axis.horizontal, // Enable horizontal scrolling
padding: const EdgeInsets.only(right: 40, top: 10), padding: const EdgeInsets.only(right: 40, top: 10),
child: SizedBox( child: SizedBox(
width: width: (uniqueXValues.length * 50) +
(uniqueXValues.length * 50) +
50, // Adjust width dynamically 50, // Adjust width dynamically
child: LineChart( child: LineChart(
LineChartData( LineChartData(
@ -1318,8 +1339,7 @@ class ChartWidget extends StatelessWidget {
child: Wrap( child: Wrap(
spacing: 12, spacing: 12,
runSpacing: 8, runSpacing: 8,
children: children: groupByValues.map((group) {
groupByValues.map((group) {
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -1359,8 +1379,7 @@ class ChartWidget extends StatelessWidget {
// } // }
// Extract all years from the chart data // Extract all years from the chart data
List<int> years = List<int> years = (chartData['response'] as List<dynamic>)
(chartData['response'] as List<dynamic>)
.map<int>( .map<int>(
(entry) => (entry) =>
int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0, int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0,
@ -1386,13 +1405,11 @@ class ChartWidget extends StatelessWidget {
// Filter chart data to include only the selected 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 year = int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0;
int.tryParse(entry['ObsKey']['TIME_PERIOD'] ?? '0') ?? 0;
return selectedYears.contains(year); return selectedYears.contains(year);
}).toList(); }).toList();
Set<double> uniqueXValues = Set<double> uniqueXValues = filteredData
filteredData
.map<double>( .map<double>(
(entry) => double.parse(entry['ObsKey']['TIME_PERIOD']), (entry) => double.parse(entry['ObsKey']['TIME_PERIOD']),
) )
@ -1456,8 +1473,7 @@ class ChartWidget extends StatelessWidget {
scrollDirection: Axis.horizontal, // Enable horizontal scrolling scrollDirection: Axis.horizontal, // Enable horizontal scrolling
padding: const EdgeInsets.only(right: 40, top: 20), padding: const EdgeInsets.only(right: 40, top: 20),
child: SizedBox( child: SizedBox(
width: width: (uniqueXValues.length * 50) +
(uniqueXValues.length * 50) +
50, // Adjust width dynamically 50, // Adjust width dynamically
child: LineChart( child: LineChart(
LineChartData( LineChartData(
@ -1516,13 +1532,11 @@ class ChartWidget extends StatelessWidget {
int.tryParse(b['ObsKey']['TIME_PERIOD'].toString()) ?? 0; int.tryParse(b['ObsKey']['TIME_PERIOD'].toString()) ?? 0;
// Extract QUARTER and convert "Q1", "Q2", etc. to numeric values // Extract QUARTER and convert "Q1", "Q2", etc. to numeric values
int quarterA = int quarterA = int.tryParse(
int.tryParse(
a['ObsKey']['QUARTER'].toString().replaceAll('Q', ''), a['ObsKey']['QUARTER'].toString().replaceAll('Q', ''),
) ?? ) ??
0; 0;
int quarterB = int quarterB = int.tryParse(
int.tryParse(
b['ObsKey']['QUARTER'].toString().replaceAll('Q', ''), b['ObsKey']['QUARTER'].toString().replaceAll('Q', ''),
) ?? ) ??
0; 0;
@ -1536,22 +1550,44 @@ class ChartWidget extends StatelessWidget {
}); });
} }
print('chartData response sort: ${chartData['response']}');
// if (xValue != null && yValue != null) { // if (xValue != null && yValue != null) {
// xAxisData.add(xValue.toString()); // xAxisData.add(xValue.toString());
// yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); // yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0);
// } // }
if (xValue != null && yValue != null) { // if (xValue != null && yValue != null) {
// Check if additional_x_group is "Timeperiod" and concatenate // // Check if additional_x_group is "Timeperiod" and concatenate
// String xLabel = xValue.toString();
// if (xadditionalgroup == 'TIME_PERIOD' && xTimePeriod != null) {
// xLabel = '$xTimePeriod-$xValue'; // Format: Label (TimePeriod)
// }
//
// xAxisData.add(xLabel);
// yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0);
// // yAxisLabels.add(unitMsr ?? '');
// }
}
for (var entry in chartData['response']) {
var xValue = entry['ObsKey'][groupByKey];
var xTimePeriod = entry['ObsKey']['TIME_PERIOD'];
var yValue = entry['ObsValue']['Value'];
var xadditionalgroup =
chartData['chart_type_json']['additional_x_group'];
if (xValue != null) {
String xLabel = xValue.toString(); String xLabel = xValue.toString();
if (xadditionalgroup == 'TIME_PERIOD' && xTimePeriod != null) { if (xadditionalgroup == 'TIME_PERIOD' && xTimePeriod != null) {
xLabel = '$xTimePeriod-$xValue'; // Format: Label (TimePeriod) xLabel = '$xTimePeriod-$xValue'; // Format: Label (TimePeriod)
} }
xAxisData.add(xLabel); xAxisData.add(xLabel);
}
if (yValue != null) {
yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0);
// yAxisLabels.add(unitMsr ?? '');
} }
} }
print('xAxisData $xAxisData');
print('yAxisData $yAxisData');
return Column( return Column(
children: [ children: [
Text( Text(
@ -1581,21 +1617,18 @@ class ChartWidget extends StatelessWidget {
constraints: BoxConstraints( constraints: BoxConstraints(
minWidth: minWidth:
screenWidth, // Ensure it at least fills available width screenWidth, // Ensure it at least fills available width
maxWidth: maxWidth: chartWidth > screenWidth
chartWidth > screenWidth
? chartWidth ? chartWidth
: screenWidth, // Prevent non-normalized constraints : screenWidth, // Prevent non-normalized constraints
), ),
child: Center( child: Center(
child: SizedBox( child: SizedBox(
width: width: xAxisData.length *
xAxisData.length *
(40 + 10), // Bar width + manual spacing (40 + 10), // Bar width + manual spacing
child: BarChart( child: BarChart(
BarChartData( BarChartData(
alignment: BarChartAlignment.spaceAround, alignment: BarChartAlignment.spaceAround,
maxY: maxY: yAxisData.isNotEmpty
yAxisData.isNotEmpty
? yAxisData.reduce( ? yAxisData.reduce(
(a, b) => a > b ? a : b, (a, b) => a > b ? a : b,
) * ) *
@ -1625,8 +1658,8 @@ class ChartWidget extends StatelessWidget {
enabled: false, enabled: false,
handleBuiltInTouches: false, handleBuiltInTouches: false,
touchTooltipData: BarTouchTooltipData( touchTooltipData: BarTouchTooltipData(
getTooltipColor: getTooltipColor: (group) =>
(group) => Colors.transparent, Colors.transparent,
// fitInsideHorizontally: true, // fitInsideHorizontally: true,
// fitInsideVertically: true, // fitInsideVertically: true,
// tooltipPadding: const EdgeInsets.all(8), // tooltipPadding: const EdgeInsets.all(8),
@ -1666,8 +1699,7 @@ class ChartWidget extends StatelessWidget {
leftTitles: AxisTitles( leftTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: false, showTitles: false,
interval: interval: (yAxisData.isNotEmpty
(yAxisData.isNotEmpty
? yAxisData.reduce( ? yAxisData.reduce(
(a, b) => a > b ? a : b, (a, b) => a > b ? a : b,
) / ) /
@ -1691,10 +1723,12 @@ class ChartWidget extends StatelessWidget {
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
if (value.toInt() < xAxisData.length) { if (value.toInt() < xAxisData.length) {
String title = xAxisData[value.toInt()]; String title = xAxisData[value.toInt()];
String displayTitle = String displayTitle = title.length > 10
title.length > 10
? title.substring(0, 10) + '...' ? title.substring(0, 10) + '...'
: title; : title;
print('barChartVALUECHECKTITLE $title');
print(
'barChartVALUECHECK $displayTitle');
return Padding( return Padding(
padding: const EdgeInsets.only( padding: const EdgeInsets.only(
@ -1711,9 +1745,8 @@ class ChartWidget extends StatelessWidget {
child: TooltipTheme( child: TooltipTheme(
data: TooltipThemeData( data: TooltipThemeData(
decoration: BoxDecoration( decoration: BoxDecoration(
color: color: Colors.blueGrey[
Colors 800], // Change background color
.blueGrey[800], // Change background color
borderRadius: borderRadius:
BorderRadius.circular( BorderRadius.circular(
8, 8,
@ -1726,8 +1759,7 @@ class ChartWidget extends StatelessWidget {
child: TooltipTheme( child: TooltipTheme(
data: TooltipThemeData( data: TooltipThemeData(
decoration: BoxDecoration( decoration: BoxDecoration(
color: color: Colors
Colors
.black, // Change background color .black, // Change background color
// color: Colors.blueGrey[800], // Change background color // color: Colors.blueGrey[800], // Change background color
borderRadius: borderRadius:
@ -1844,8 +1876,7 @@ class ChartWidget extends StatelessWidget {
}); });
// If no valid TIME_PERIOD with a month is found, return original response // If no valid TIME_PERIOD with a month is found, return original response
List<Map<String, dynamic>> finalData = List<Map<String, dynamic>> finalData = sortedData.isNotEmpty
sortedData.isNotEmpty
? sortedData ? sortedData
: List.from(chartData['response']); : List.from(chartData['response']);
@ -1926,8 +1957,7 @@ class ChartWidget extends StatelessWidget {
leftTitles: AxisTitles( leftTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: false, showTitles: false,
interval: interval: (yAxisData.isNotEmpty
(yAxisData.isNotEmpty
? yAxisData.reduce((a, b) => a > b ? a : b) / 5 ? yAxisData.reduce((a, b) => a > b ? a : b) / 5
: 1), : 1),
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
@ -1994,8 +2024,7 @@ class ChartWidget extends StatelessWidget {
barsSpace: 20, barsSpace: 20,
barRods: [ barRods: [
BarChartRodData( BarChartRodData(
toY: toY: (yAxisData[index] == 0)
(yAxisData[index] == 0)
? 0.0001 ? 0.0001
: yAxisData[index], : yAxisData[index],
// color: Colors.blueAccent, // color: Colors.blueAccent,
@ -2132,8 +2161,7 @@ class ChartWidget extends StatelessWidget {
), // Dynamically calculate max Y ), // Dynamically calculate max Y
// barGroups: _buildHorizontalRotateBarGroups( // barGroups: _buildHorizontalRotateBarGroups(
// chartData, groupByValues), // Build bar groups // chartData, groupByValues), // Build bar groups
barGroups: barGroups: hasBarColors
hasBarColors
? _buildHorizontalRotateBarGroupsBarColors( ? _buildHorizontalRotateBarGroupsBarColors(
chartData, chartData,
groupByValues, groupByValues,
@ -2159,8 +2187,7 @@ class ChartWidget extends StatelessWidget {
value.toInt(), value.toInt(),
); );
String displayTitle = String displayTitle = title.length > 10
title.length > 10
? title.substring(0, 10) + '...' ? title.substring(0, 10) + '...'
: title; : title;
@ -2177,8 +2204,7 @@ class ChartWidget extends StatelessWidget {
child: TooltipTheme( child: TooltipTheme(
data: TooltipThemeData( data: TooltipThemeData(
decoration: BoxDecoration( decoration: BoxDecoration(
color: color: Colors
Colors
.black, // Change background color .black, // Change background color
// color: Colors.blueGrey[800], // Change background color // color: Colors.blueGrey[800], // Change background color
borderRadius: borderRadius:
@ -2273,8 +2299,7 @@ class ChartWidget extends StatelessWidget {
'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex', 'Crop is null or index out of bounds for cropType: $cropType and rodIndex: $rodIndex',
); );
// crop = cropType; // Fallback to cropType // crop = cropType; // Fallback to cropType
crop = crop = (crops != null && crops.isNotEmpty)
(crops != null && crops.isNotEmpty)
? crops.first ? crops.first
: cropType; : cropType;
} }
@ -2331,8 +2356,8 @@ class ChartWidget extends StatelessWidget {
); );
case 'horizontal_rotate': case 'horizontal_rotate':
String cropKey = String cropKey = chartData['chart_type_json']
chartData['chart_type_json']['y_sub_group']; // Dynamically get crop key ['y_sub_group']; // Dynamically get crop key
// Group crops by CROP_TYPE // Group crops by CROP_TYPE
Map<String, List<String>> groupedCrops = {}; Map<String, List<String>> groupedCrops = {};
@ -2551,9 +2576,7 @@ class ChartWidget extends StatelessWidget {
enabled: false, // Enable touch to show tooltip enabled: false, // Enable touch to show tooltip
handleBuiltInTouches: false, handleBuiltInTouches: false,
touchTooltipData: BarTouchTooltipData( touchTooltipData: BarTouchTooltipData(
getTooltipColor: getTooltipColor: (group) => Colors
(group) =>
Colors
.transparent, // Light background for visibility .transparent, // Light background for visibility
tooltipHorizontalAlignment: tooltipHorizontalAlignment:
FLHorizontalAlignment.center, FLHorizontalAlignment.center,
@ -2574,6 +2597,18 @@ class ChartWidget extends StatelessWidget {
String crop = groupedCrops[cropType]![rodIndex]; String crop = groupedCrops[cropType]![rodIndex];
double value = rod.toY; double value = rod.toY;
// Show tooltip for zero values
if (value == 0) {
return BarTooltipItem(
'0', // Display "0" instead of hiding
textAlign: TextAlign.right,
const TextStyle(
color: Colors.black,
fontSize: 12,
),
);
}
// Format values dynamically // Format values dynamically
// String formattedValue = value >= 1e6 // String formattedValue = value >= 1e6
// ? '${(value / 1e6).toStringAsFixed(1)}M' // ? '${(value / 1e6).toStringAsFixed(1)}M'
@ -2593,7 +2628,7 @@ class ChartWidget extends StatelessWidget {
0, 0,
); // for values smaller than 1000 ); // for values smaller than 1000
} }
print('formattedValue00 $formattedValue');
return BarTooltipItem( return BarTooltipItem(
formattedValue, formattedValue,
textAlign: TextAlign.right, textAlign: TextAlign.right,
@ -2690,8 +2725,7 @@ class ChartWidget extends StatelessWidget {
// barGroups: _buildHorizontalRotateBarGroups( // barGroups: _buildHorizontalRotateBarGroups(
// chartData, groupByValues), // chartData, groupByValues),
barGroups: barGroups: hasBarColors
hasBarColors
? _buildHorizontalRotateBarGroupsBarColors( ? _buildHorizontalRotateBarGroupsBarColors(
chartData, chartData,
groupByValues, groupByValues,
@ -2923,8 +2957,7 @@ class ChartWidget extends StatelessWidget {
// return FlSpot(xValue, yValue); // return FlSpot(xValue, yValue);
// }).toList(); // }).toList();
List<FlSpot> spots = List<FlSpot> spots = filteredData
filteredData
.where((entry) => entry['ObsKey'][groupByKey] == group) .where((entry) => entry['ObsKey'][groupByKey] == group)
.map<FlSpot>((entry) { .map<FlSpot>((entry) {
String timePeriod = entry['ObsKey']['TIME_PERIOD']; String timePeriod = entry['ObsKey']['TIME_PERIOD'];
@ -2946,8 +2979,7 @@ class ChartWidget extends StatelessWidget {
yValue = value; yValue = value;
} else if (value is String) { } else if (value is String) {
yValue = yValue =
double.tryParse(value) ?? double.tryParse(value) ?? 0.0; // Handle invalid strings safely
0.0; // Handle invalid strings safely
} else { } else {
throw Exception( throw Exception(
"Unexpected value type: ${value.runtimeType}", "Unexpected value type: ${value.runtimeType}",
@ -2956,8 +2988,7 @@ class ChartWidget extends StatelessWidget {
print('LineTrendX $xValue'); print('LineTrendX $xValue');
print('LineTrendY $yValue'); print('LineTrendY $yValue');
return FlSpot(xValue, yValue); return FlSpot(xValue, yValue);
}) }).toList()
.toList()
..sort((a, b) => a.x.compareTo(b.x)); ..sort((a, b) => a.x.compareTo(b.x));
print('spots - $spots'); print('spots - $spots');
@ -3014,8 +3045,7 @@ class ChartWidget extends StatelessWidget {
getTooltipColor: (spot) => Colors.black, getTooltipColor: (spot) => Colors.black,
getTooltipItems: (List<LineBarSpot> lineBarsSpot) { getTooltipItems: (List<LineBarSpot> lineBarsSpot) {
return lineBarsSpot.map((lineBarSpot) { return lineBarsSpot.map((lineBarSpot) {
Color lineColor = Color lineColor = lineBarSpot.bar is LineChartBarData
lineBarSpot.bar is LineChartBarData
? (lineBarSpot.bar).color ?? Colors.white ? (lineBarSpot.bar).color ?? Colors.white
: Colors.white; // Extract bar color safely : Colors.white; // Extract bar color safely
return LineTooltipItem( return LineTooltipItem(
@ -3030,8 +3060,7 @@ class ChartWidget extends StatelessWidget {
), ),
TextSpan( TextSpan(
// text: formatNumber(lineBarSpot.y), // text: formatNumber(lineBarSpot.y),
text: text: (chartConversion != null &&
(chartConversion != null &&
chartConversion.isNotEmpty && chartConversion.isNotEmpty &&
number_format != null) number_format != null)
? formatNumberConversion( ? formatNumberConversion(
@ -3128,10 +3157,10 @@ class ChartWidget extends StatelessWidget {
return FlGridData( return FlGridData(
show: false, show: false,
drawVerticalLine: true, drawVerticalLine: true,
getDrawingHorizontalLine: getDrawingHorizontalLine: (value) =>
(value) => FlLine(color: Colors.grey, strokeWidth: 1), FlLine(color: Colors.grey, strokeWidth: 1),
getDrawingVerticalLine: getDrawingVerticalLine: (value) =>
(value) => FlLine(color: Colors.grey, strokeWidth: 1), FlLine(color: Colors.grey, strokeWidth: 1),
); );
} }
@ -3568,18 +3597,16 @@ class ChartWidget extends StatelessWidget {
String groupValue = groupByValues.elementAt(i); String groupValue = groupByValues.elementAt(i);
// Filter data for the current group (grouping by CROP_TYPE) // Filter data for the current group (grouping by CROP_TYPE)
List<dynamic> groupData = List<dynamic> groupData = responseData.where((entry) {
responseData.where((entry) {
return entry['ObsKey'][groupByKeyValueData] == groupValue; return entry['ObsKey'][groupByKeyValueData] == groupValue;
}).toList(); }).toList();
// Create BarChartRodData for each bar in the group // Create BarChartRodData for each bar in the group
List<BarChartRodData> barRods = List<BarChartRodData> barRods = groupData.map((data) {
groupData.map((data) {
// Ensure to retrieve and parse 'ObsValue' value (which should be a double) // Ensure to retrieve and parse 'ObsValue' value (which should be a double)
double value = double value =
double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0; double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0;
// double minBarHeight = 0.5; double minBarHeight = 0.1;
print('multi_bar1.1'); print('multi_bar1.1');
// final List<Color> uniqueColorsForTwo = [ // final List<Color> uniqueColorsForTwo = [
// Color(0xFF648CBA), // Color(0xFF648CBA),
@ -3598,13 +3625,11 @@ class ChartWidget extends StatelessWidget {
chartData['dataset'] == 'hotel_guests' || chartData['dataset'] == 'hotel_guests' ||
chartData['dataset'] == 'health_services' || chartData['dataset'] == 'health_services' ||
chartData['dataset'] == 'clinics') { chartData['dataset'] == 'clinics') {
barColor = barColor = uniqueColorsForTwo[colorIndex % uniqueColorsForTwo.length];
uniqueColorsForTwo[colorIndex % uniqueColorsForTwo.length];
colorIndex++; colorIndex++;
} else if (chartData['dataset'] == 'cropsk') { } else if (chartData['dataset'] == 'cropsk') {
barColor = barColor =
uniqueColorsForThree[colorIndex % uniqueColorsForThree[colorIndex % uniqueColorsForThree.length];
uniqueColorsForThree.length];
colorIndex++; colorIndex++;
} else if (chartData['dataset'] == 'oil_and_gas') { } else if (chartData['dataset'] == 'oil_and_gas') {
barColor = barColor =
@ -3616,7 +3641,8 @@ class ChartWidget extends StatelessWidget {
} }
return BarChartRodData( return BarChartRodData(
toY: value, // Use the parsed value // toY: value,
toY: value == 0 ? minBarHeight : value, // Use the parsed value
color: barColor, // Dynamic color color: barColor, // Dynamic color
width: 20, width: 20,
@ -3677,8 +3703,7 @@ class ChartWidget extends StatelessWidget {
String groupValue = groupByValues.elementAt(i); String groupValue = groupByValues.elementAt(i);
// Filter data for the current group // Filter data for the current group
List<dynamic> groupData = List<dynamic> groupData = responseData.where((entry) {
responseData.where((entry) {
return entry['ObsKey'][groupByKeyValueData1] == groupValue; return entry['ObsKey'][groupByKeyValueData1] == groupValue;
}).toList(); }).toList();
@ -3698,8 +3723,7 @@ class ChartWidget extends StatelessWidget {
}); });
// Create BarChartRodData for each bar in the group // Create BarChartRodData for each bar in the group
List<BarChartRodData> barRods = List<BarChartRodData> barRods = groupData.map((data) {
groupData.map((data) {
double value = double value =
double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0; double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0;
@ -3714,9 +3738,8 @@ class ChartWidget extends StatelessWidget {
// Determine color dynamically // Determine color dynamically
Color barColor; Color barColor;
if (chartData['dataset'] == 'health_services') { if (chartData['dataset'] == 'health_services') {
barColor = barColor = uniqueColorsForTwo[
uniqueColorsForTwo[colorIndex % colorIndex % 2]; // Alternate between two colors
2]; // Alternate between two colors
colorIndex++; // Update index for next bar colorIndex++; // Update index for next bar
} else { } else {
// barColor = chartBarColors[gender] ?? Colors.grey; // Default gender-based color // barColor = chartBarColors[gender] ?? Colors.grey; // Default gender-based color
@ -3772,14 +3795,12 @@ Widget _buildChartLegend(
alignment: WrapAlignment.center, alignment: WrapAlignment.center,
spacing: 12, spacing: 12,
runSpacing: 6, runSpacing: 6,
children: children: uniqueCropTypes.map((cropType) {
uniqueCropTypes.map((cropType) {
// Color cropColor = parsedChartBarColors[cropType] ?? Colors.grey; // Fetch color for each crop type // Color cropColor = parsedChartBarColors[cropType] ?? Colors.grey; // Fetch color for each crop type
int index = uniqueCropTypes.toList().indexOf( int index = uniqueCropTypes.toList().indexOf(
cropType, cropType,
); // Get index for cycling colors ); // Get index for cycling colors
Color cropColor = Color cropColor = parsedChartBarColors.isNotEmpty &&
parsedChartBarColors.isNotEmpty &&
parsedChartBarColors.containsKey(cropType) parsedChartBarColors.containsKey(cropType)
? parsedChartBarColors[cropType]! ? parsedChartBarColors[cropType]!
: uniqueColors[index % uniqueColors.length]; : uniqueColors[index % uniqueColors.length];

View File

@ -702,6 +702,8 @@ class LoginRoute extends HookConsumerWidget {
); );
final dontHaveAnAccountRegisterBtn = TextButton( final dontHaveAnAccountRegisterBtn = TextButton(
onPressed: () => {context.push('/register')}, onPressed: () => {context.push('/register')},
// onPressed: () =>
// {context.push('/forgot-password/surendar.m@venbainfotech.com')},
child: Text.rich( child: Text.rich(
textAlign: TextAlign.center, textAlign: TextAlign.center,
TextSpan( TextSpan(

View File

@ -152,7 +152,9 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
isLoading = false; isLoading = false;
}); });
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(AppLocalizations.of(context)!.status_success),), SnackBar(
content: Text(AppLocalizations.of(context)!.status_success),
),
); );
} catch (e) { } catch (e) {
setState(() { setState(() {
@ -160,13 +162,16 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
}); });
Navigator.of(context).pop(); Navigator.of(context).pop();
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(context.translate('Error updating status: $e','$e خطأ في تحديث الحالة: '))), SnackBar(
content: Text(context.translate(
'Error updating status: $e', '$e خطأ في تحديث الحالة: '))),
); );
} }
} }
//Method to show a confirmation dialog when status is changed //Method to show a confirmation dialog when status is changed
Future<void> _showConfirmationDialog(User user, String newStatus,String statusUpdate) async { Future<void> _showConfirmationDialog(
User user, String newStatus, String statusUpdate) async {
print('user $user'); print('user $user');
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
@ -416,8 +421,9 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
// // fit: BoxFit.contain, // // fit: BoxFit.contain,
// ), // ),
border: InputBorder.none, border: InputBorder.none,
contentPadding: EdgeInsets.symmetric( // contentPadding: EdgeInsets.symmetric(
vertical: 9, horizontal: 18.0), // vertical: 9, horizontal: 18.0),
contentPadding: EdgeInsets.zero,
), ),
onChanged: filterUsers, onChanged: filterUsers,
), ),
@ -444,7 +450,8 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
SizedBox(height: 15), SizedBox(height: 15),
// Space between icon and text // Space between icon and text
Text( Text(
AppLocalizations.of(context)!.no_result_found, AppLocalizations.of(context)!
.no_result_found,
style: TextStyle( style: TextStyle(
fontSize: 24, fontSize: 24,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -455,7 +462,9 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
SizedBox(height: 12), // Space between texts SizedBox(height: 12), // Space between texts
FittedBox( FittedBox(
child: Text( child: Text(
context.translate("We couldn't find anything matching your search.",'لم نعثر على أي شيء يطابق بحثك.'), context.translate(
"We couldn't find anything matching your search.",
'لم نعثر على أي شيء يطابق بحثك.'),
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: 18,
color: Color(0xFF898C81)), color: Color(0xFF898C81)),
@ -533,7 +542,9 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
(index) => DataCell( (index) => DataCell(
index == 0 index == 0
? Text( ? Text(
AppLocalizations.of(context)!.no_result_found, AppLocalizations.of(
context)!
.no_result_found,
style: TextStyle( style: TextStyle(
fontStyle: FontStyle fontStyle: FontStyle
.italic), .italic),
@ -573,7 +584,11 @@ class _ManageUserRouterState extends ConsumerState<ManageUserRouter> {
print(user); print(user);
if (newStatus != null) { if (newStatus != null) {
_showConfirmationDialog( _showConfirmationDialog(
user, newStatus, statusOptions[newStatus]!,); user,
newStatus,
statusOptions[
newStatus]!,
);
} }
}, },
), ),

View File

@ -989,7 +989,9 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
ListTile( ListTile(
leading: Icon(Icons.mail_outlined), leading: Icon(Icons.mail_outlined),
title: Text(context.translate('Contact Us', 'اتصل بنا'),), title: Text(
context.translate('Contact Us', 'اتصل بنا'),
),
onTap: () => context.push('/contact'), onTap: () => context.push('/contact'),
), ),
if (userId != 'guest') if (userId != 'guest')

View File

@ -1,7 +1,7 @@
name: uae_stat name: uae_stat
description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness." description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness."
publish_to: "none" publish_to: "none"
version: 1.0.42+43 version: 1.0.43+44
environment: environment:
sdk: ">=3.2.3 <4.0.0" sdk: ">=3.2.3 <4.0.0"