Bug Fix - Manage User

This commit is contained in:
Juki-shiba 2025-02-17 18:32:56 +05:30
commit e25ddaafd1
10 changed files with 1188 additions and 1088 deletions

View File

@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) {
def flutterVersionCode = localProperties.getProperty("flutter.versionCode") def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) { if (flutterVersionCode == null) {
flutterVersionCode = "16" flutterVersionCode = "20"
} }
def flutterVersionName = localProperties.getProperty("flutter.versionName") def flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) { if (flutterVersionName == null) {
flutterVersionName = "1.0.15" flutterVersionName = "1.0.19"
} }
//def keystorePropertiesFile = rootProject.file("key.properties") //def keystorePropertiesFile = rootProject.file("key.properties")

View File

@ -15,6 +15,11 @@
"exit": "خروج", "exit": "خروج",
"bookmark_title": "إشارة مرجعية", "bookmark_title": "إشارة مرجعية",
"failed_To_Remove": "فشلت الإزالة",
"removed_from_Bookmark": "تمت الإزالة من الإشارة المرجعية",
"added_to_Bookmark":"تمت إضافته إلى الإشارة المرجعية",
"guide_title": "نموذج الملاحظات",
"notification": "إشعار",
"guide_title": "نموذج الملاحظات", "guide_title": "نموذج الملاحظات",

View File

@ -16,6 +16,10 @@
"cancel": "Cancel", "cancel": "Cancel",
"exit": "Exit", "exit": "Exit",
"bookmark_title": "Bookmark", "bookmark_title": "Bookmark",
"failed_To_Remove": "Failed to Remove",
"removed_from_Bookmark": "Removed from Bookmark",
"added_to_Bookmark": "Added to Bookmark.",
"notification": "Notification",
"register_title": "Register", "register_title": "Register",
"register_details": "Please enter your details", "register_details": "Please enter your details",

View File

@ -188,7 +188,7 @@ class _CreateNewPwState extends ConsumerState<CreateNewPw> {
} }
@override @override
Widget build(BuildContext contextx) { Widget build(BuildContext context) {
double screenHeight = MediaQuery.of(context).size.height; double screenHeight = MediaQuery.of(context).size.height;
double screenWidth = MediaQuery.of(context).size.width; double screenWidth = MediaQuery.of(context).size.width;
final passwordLocale = ref.watch(localeProvider); final passwordLocale = ref.watch(localeProvider);

File diff suppressed because it is too large Load Diff

View File

@ -231,6 +231,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 20), SizedBox(height: 20),
Expanded( Expanded(
child: ValueListenableBuilder<int?>( child: ValueListenableBuilder<int?>(
@ -261,21 +270,23 @@ class ChartWidget extends StatelessWidget {
), ),
), ),
SizedBox(height: 25), SizedBox(height: 25),
Flexible( Flexible(
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.vertical, scrollDirection: Axis.vertical,
child: Container( child: Container(
constraints: BoxConstraints(minHeight: 5), // Allow dynamic height constraints:
BoxConstraints(minHeight: 5), // Allow dynamic height
child: Padding( child: Padding(
padding: const EdgeInsets.only(left: 8.0 ,right: 8.0,bottom: 8.0,top:20.0), padding: const EdgeInsets.only(
child: Wrap( left: 8.0, right: 8.0, bottom: 8.0, top: 20.0),
spacing: 12, child: Wrap(
runSpacing: 8, spacing: 12,
children: generateIndicators(chartData, chartData['group_by']), runSpacing: 8,
), children:
), generateIndicators(chartData, chartData['group_by']),
), ),
),
),
), ),
), ),
], ],
@ -305,6 +316,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
AspectRatio( AspectRatio(
aspectRatio: 1.5, aspectRatio: 1.5,
@ -520,6 +540,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -622,6 +651,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
Expanded( Expanded(
@ -629,8 +667,8 @@ class ChartWidget extends StatelessWidget {
scrollDirection: Axis.horizontal, // Enable horizontal scrolling scrollDirection: Axis.horizontal, // Enable horizontal scrolling
padding: const EdgeInsets.only(right: 40), padding: const EdgeInsets.only(right: 40),
child: SizedBox( child: SizedBox(
width: (uniqueXValues.length * 80) + width: (uniqueXValues.length * 50) +
80, // Adjust width dynamically 50, // Adjust width dynamically
child: LineChart(LineChartData( child: LineChart(LineChartData(
lineTouchData: lineTouchData1(), lineTouchData: lineTouchData1(),
gridData: gridData(), gridData: gridData(),
@ -733,6 +771,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -740,8 +787,8 @@ class ChartWidget extends StatelessWidget {
scrollDirection: Axis.horizontal, // Enable horizontal scrolling scrollDirection: Axis.horizontal, // Enable horizontal scrolling
padding: const EdgeInsets.only(right: 40), padding: const EdgeInsets.only(right: 40),
child: SizedBox( child: SizedBox(
width: (uniqueXValues.length * 80) + width: (uniqueXValues.length * 50) +
80, // Adjust width dynamically 50, // Adjust width dynamically
child: LineChart( child: LineChart(
LineChartData( LineChartData(
lineTouchData: lineTouchData1(), lineTouchData: lineTouchData1(),
@ -751,6 +798,7 @@ class ChartWidget extends StatelessWidget {
lineBarsData: lineBars, lineBarsData: lineBars,
minX: uniqueXValues.reduce((a, b) => a < b ? a : b), minX: uniqueXValues.reduce((a, b) => a < b ? a : b),
maxX: uniqueXValues.reduce((a, b) => a > b ? a : b), maxX: uniqueXValues.reduce((a, b) => a > b ? a : b),
minY: 0,
), ),
), ),
), ),
@ -779,6 +827,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -886,6 +943,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -896,7 +962,22 @@ class ChartWidget extends StatelessWidget {
? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2 ? yAxisData.reduce((a, b) => a > b ? a : b) * 1.2
: 10, : 10,
rotationQuarterTurns: rotationTurns, rotationQuarterTurns: rotationTurns,
barTouchData: BarTouchData(enabled: true), barTouchData: BarTouchData(
enabled: true,
handleBuiltInTouches: true,
touchTooltipData: BarTouchTooltipData(
fitInsideHorizontally: true,
fitInsideVertically: true,
tooltipPadding: const EdgeInsets.all(8),
tooltipMargin: 16,
getTooltipItem: (group, groupIndex, rod, rodIndex) {
return BarTooltipItem(
'${rod.toY.toStringAsFixed(1)}',
const TextStyle(color: Colors.white),
);
},
),
),
titlesData: FlTitlesData( titlesData: FlTitlesData(
leftTitles: AxisTitles( leftTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
@ -925,11 +1006,11 @@ class ChartWidget extends StatelessWidget {
// angle: -45 * // angle: -45 *
// (3.1415927 / 180), // Rotating by -45 degrees // (3.1415927 / 180), // Rotating by -45 degrees
alignment: Alignment.center, alignment: Alignment.center,
child: Center( child: Center(
child: SizedBox( child: SizedBox(
width: 100, width: 100,
child: Text( child: Text(
xAxisData[value.toInt()], xAxisData[value.toInt()],
style: const TextStyle(fontSize: 12), style: const TextStyle(fontSize: 12),
softWrap: true, softWrap: true,
maxLines: 2, maxLines: 2,
@ -977,39 +1058,15 @@ class ChartWidget extends StatelessWidget {
const double barWidth = 30; // Width for each bar, including spacing const double barWidth = 30; // Width for each bar, including spacing
return totalBars * barWidth; // Calculate total chart width return totalBars * barWidth; // Calculate total chart width
} }
String cropKey = chartData['chart_type_json']['x_sub_group'];
// Group crops by CROP_TYPE // Group crops by CROP_TYPE
Map<String, List<String>> groupedCrops = {}; Map<String, List<String>> groupedCrops = {};
int touchedGroupIndex = -1; int touchedGroupIndex = -1;
// Iterate over the chartData to group crops by CROP_TYPE // Iterate over the chartData to group crops by CROP_TYPE
for (var item in chartData['response']) { for (var item in chartData['response']) {
String crop, cropType; String crop, cropType;
if (chartData['dataset'] == 'health_services') { crop = item['ObsKey'][cropKey];
crop = item['ObsKey']['SECTOR']; cropType = item['ObsKey'][groupByKey];
cropType = item['ObsKey'][groupByKey];
} else if (chartData['dataset'] == 'general_education') {
print(chartData['dataset'] == 'general_education');
crop = item['ObsKey']['GENDER'];
cropType = item['ObsKey'][groupByKey];
} else if (chartData['dataset'] == 'higher_education') {
crop = item['ObsKey']['GENDER'];
cropType = item['ObsKey'][groupByKey];
} else if (chartData['dataset'] == 'labour_force') {
crop = item['ObsKey']['GENDER'];
cropType = item['ObsKey'][groupByKey];
} else if (chartData['dataset'] == 'clinics') {
if (kDebugMode) {
print('forclinics');
print('ObsKey: ${item['ObsKey']}');
// print('NR_TYPE: ${item['ObsKey']?['NR_TYPE']}');
}
crop = item['ObsKey']['MEASURE'];
cropType = item['ObsKey'][groupByKey];
} else {
crop = item['ObsKey']['CROP'];
cropType = item['ObsKey'][groupByKey];
}
if (groupedCrops.containsKey(cropType)) { if (groupedCrops.containsKey(cropType)) {
groupedCrops[cropType]!.add(crop); groupedCrops[cropType]!.add(crop);
@ -1026,6 +1083,15 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
@ -1187,64 +1253,17 @@ class ChartWidget extends StatelessWidget {
]); ]);
case 'horizontal_rotate': case 'horizontal_rotate':
String cropKey = chartData['chart_type_json']
['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 = {};
// Iterate over the chartData to group crops by CROP_TYPE // Iterate over the chartData to group crops by CROP_TYPE
for (var item in chartData['response']) { for (var item in chartData['response']) {
String crop, cropType; String crop, cropType;
if (chartData['dataset'] == 'natural_reserves') { // crop = item['ObsKey']['CROP'];
crop = item['ObsKey']['NR_TYPE']; crop = item['ObsKey'][cropKey];
cropType = item['ObsKey'][groupByKey]; cropType = item['ObsKey'][groupByKey];
}
else if(chartData['dataset'] == 'gdp')
{
print("ForGDP");
if (kDebugMode) {
print('ObsKey: ${item['ObsKey']}');
// print('NR_TYPE: ${item['ObsKey']?['NR_TYPE']}');
}
crop = item['ObsKey']['BOP_ITEM'];
cropType = item['ObsKey'][groupByKey];
} else if(chartData['dataset'] == 'air_transport')
{
print("Forair_transport");
if (kDebugMode) {
print('ObsKey: ${item['ObsKey']}');
// print('NR_TYPE: ${item['ObsKey']?['NR_TYPE']}');
}
crop = item['ObsKey']['MEASURE'];
cropType = item['ObsKey'][groupByKey];
} else if(chartData['dataset'] == 'import')
{
print("Forimport");
if (kDebugMode) {
print('ObsKey: ${item['ObsKey']}');
// print('NR_TYPE: ${item['ObsKey']?['NR_TYPE']}');
}
crop = item['ObsKey']['COUNTRY'];
cropType = item['ObsKey'][groupByKey];
}
else if(chartData['dataset'] == 'gdpq')
{
print("ForGDPq");
if (kDebugMode) {
print('ObsKey: ${item['ObsKey']}');
}
crop = item['ObsKey']['MEASURE'];
// crop = item['ObsKey']['TIME_PERIOD'];
cropType = item['ObsKey'][groupByKey];
}
else {
crop = item['ObsKey']['CROP'];
cropType = item['ObsKey'][groupByKey];
}
if (groupedCrops.containsKey(cropType)) { if (groupedCrops.containsKey(cropType)) {
groupedCrops[cropType]!.add(crop); groupedCrops[cropType]!.add(crop);
@ -1257,16 +1276,17 @@ class ChartWidget extends StatelessWidget {
int rotationTurns = 1; int rotationTurns = 1;
print('Grouped Crops: $groupedCrops'); print('Grouped Crops: $groupedCrops');
int numberOfBars = groupedCrops.length; // Number of grouped sets (bar groups) int numberOfBars =
groupedCrops.length; // Number of grouped sets (bar groups)
double barHeight = 40.0; // Height per individual bar double barHeight = 40.0; // Height per individual bar
double barSpacing = 30.0; // Space between bar sets double barSpacing = 30.0; // Space between bar sets
double minHeight = 300.0; // Minimum chart height double minHeight = 300.0; // Minimum chart height
double maxHeight = 1000.0; // Maximum chart height double maxHeight = 1000.0; // Maximum chart height
// Calculate total height dynamically // Calculate total height dynamically
double chartHeight = ((numberOfBars * barHeight) + ((numberOfBars - 1) * barSpacing)) double chartHeight =
.clamp(minHeight, maxHeight); ((numberOfBars * barHeight) + ((numberOfBars - 1) * barSpacing))
.clamp(minHeight, maxHeight);
return Column(children: [ return Column(children: [
Text( Text(
@ -1277,169 +1297,184 @@ class ChartWidget extends StatelessWidget {
), ),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
SizedBox(height: 5),
Text(
chartData['chart_sub_heading'] ?? '',
style: TextStyle(
fontSize: 13,
fontWeight: FontWeight.w300,
),
textAlign: TextAlign.center,
),
SizedBox(height: 10), SizedBox(height: 10),
// Chart // Chart
Expanded( Expanded(
child: SingleChildScrollView(
scrollDirection: Axis.vertical,
child: SingleChildScrollView( child: SingleChildScrollView(
scrollDirection: Axis.horizontal, scrollDirection: Axis.vertical,
child:SizedBox( child: SingleChildScrollView(
width: 1000, scrollDirection: Axis.horizontal,
height: chartHeight, child: SizedBox(
child: BarChart( width: 1000,
BarChartData( height: chartHeight,
maxY: 400000, child: BarChart(
rotationQuarterTurns: rotationTurns, BarChartData(
barTouchData: BarTouchData( maxY: 400000,
touchTooltipData: BarTouchTooltipData( rotationQuarterTurns: rotationTurns,
tooltipHorizontalAlignment: FLHorizontalAlignment.center, barTouchData: BarTouchData(
tooltipRoundedRadius: 8, touchTooltipData: BarTouchTooltipData(
fitInsideHorizontally: tooltipHorizontalAlignment:
true, // Ensure it fits within the screen FLHorizontalAlignment.center,
fitInsideVertically: true, tooltipRoundedRadius: 8,
tooltipPadding: EdgeInsets.all(8), fitInsideHorizontally:
tooltipMargin: 16, true, // Ensure it fits within the screen
// Only show tooltip when touched fitInsideVertically: true,
getTooltipItem: (group, groupIndex, rod, rodIndex) { tooltipPadding: EdgeInsets.all(8),
if (rod.toY == 0 || touchedGroupIndex == -1) { tooltipMargin: 16,
return null; // Don't show the tooltip if the value is 0 or there's no touch // 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) { if (groupIndex == touchedGroupIndex) {
// print('Group Index: $groupIndex, Group : $group'); // print('Group Index: $groupIndex, Group : $group');
// Get the group label dynamically // Get the group label dynamically
String groupLabel = groupByValues.elementAt(groupIndex); String groupLabel =
groupByValues.elementAt(groupIndex);
// Fetch the crop for the current group from groupedCrops // Fetch the crop for the current group from groupedCrops
String cropType = groupByValues.elementAt(groupIndex); String cropType =
String crop = groupedCrops[cropType]![rodIndex]; groupByValues.elementAt(groupIndex);
double value = rod.toY; String crop = groupedCrops[cropType]![rodIndex];
double value = rod.toY;
String formattedValue; String formattedValue;
if (value >= 1000000) { if (value >= 1000000) {
formattedValue = formattedValue =
(value / 1000000).toStringAsFixed(1) + 'M'; (value / 1000000).toStringAsFixed(1) + 'M';
} else if (value >= 1000) { } else if (value >= 1000) {
formattedValue = formattedValue =
(value / 1000).toStringAsFixed(1) + 'K'; (value / 1000).toStringAsFixed(1) + 'K';
} else { } else {
formattedValue = value.toStringAsFixed( formattedValue = value.toStringAsFixed(
0); // for values smaller than 1000 0); // for values smaller than 1000
} }
return BarTooltipItem( return BarTooltipItem(
'$groupLabel\n$crop', '$groupLabel\n$crop',
const TextStyle( const TextStyle(
color: Colors.white, color: Colors.white,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
),
children: [
TextSpan(
text: ' Value: $formattedValue',
style: const TextStyle(
color: Colors.yellow,
fontWeight: FontWeight.w500,
), ),
), children: [
], TextSpan(
); text: ' Value: $formattedValue',
} style: const TextStyle(
return null; color: Colors.yellow,
}, fontWeight: FontWeight.w500,
), ),
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 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
// });
} }
return const SizedBox.shrink();
}, },
), ),
), titlesData: FlTitlesData(
rightTitles: leftTitles: AxisTitles(
AxisTitles(sideTitles: SideTitles(showTitles: false)), sideTitles: SideTitles(
topTitles: showTitles: false,
AxisTitles(sideTitles: SideTitles(showTitles: false)), reservedSize: 20,
), interval: 100000,
borderData: FlBorderData( getTitlesWidget: (value, meta) {
show: true, return Text(
border: const Border( value.toInt().toString(),
// left: BorderSide(color: Colors.grey), style: const TextStyle(fontSize: 12),
bottom: BorderSide(color: Colors.white), );
},
),
),
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( // Expanded(
// child: Stack( // child: Stack(
@ -1837,12 +1872,15 @@ class ChartWidget extends StatelessWidget {
bottomTitles: AxisTitles( bottomTitles: AxisTitles(
sideTitles: SideTitles( sideTitles: SideTitles(
showTitles: true, showTitles: true,
interval: 1, // Ensure each year is shown only once interval: 10, // Ensure each year is shown only once
getTitlesWidget: (value, meta) { getTitlesWidget: (value, meta) {
if (xValues.contains(value)) { if (xValues.contains(value)) {
return Text( return Transform.rotate(
value.toInt().toString(), angle: -0.5, // Slight rotation to improve readability
style: TextStyle(color: Colors.black, fontSize: 12), child: Text(
value.toInt().toString(),
style: TextStyle(color: Colors.black, fontSize: 12),
),
); );
} else { } else {
return SizedBox.shrink(); // Hide non-relevant labels return SizedBox.shrink(); // Hide non-relevant labels
@ -2109,9 +2147,8 @@ class ChartWidget extends StatelessWidget {
chartData['dataset'] == 'higher_education' || chartData['dataset'] == 'higher_education' ||
chartData['dataset'] == 'air_transport' || chartData['dataset'] == 'air_transport' ||
chartData['dataset'] == 'labour_force' || chartData['dataset'] == 'labour_force' ||
chartData['dataset'] == 'gdp' chartData['dataset'] == 'gdp' ||
) { chartData['dataset'] == 'clinics') {
barColor = uniqueColorsForTwo[colorIndex % uniqueColorsForTwo.length]; barColor = uniqueColorsForTwo[colorIndex % uniqueColorsForTwo.length];
colorIndex++; colorIndex++;
} else { } else {

View File

@ -21,6 +21,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
int _sortColumnIndex = 0; int _sortColumnIndex = 0;
bool _isAscending = true; bool _isAscending = true;
List<User> filteredUserData = []; List<User> filteredUserData = [];
bool isLoading = true;
// final List<String> statusOptions = ['Approved', 'Denied', 'Pending']; // final List<String> statusOptions = ['Approved', 'Denied', 'Pending'];
@ -52,9 +53,9 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
); );
setState(() { setState(() {
isLoading = true;
userData = result.map((record) { userData = result.map((record) {
final createdDate = final createdDate = DateTime.parse(record.created).add(Duration(hours: 4));// Parse the created date
DateTime.parse(record.created); // Parse the created date
final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate); final formattedDate = DateFormat('dd/MM/yyyy').format(createdDate);
return User( return User(
id: record.id, // Correctly passing the ID id: record.id, // Correctly passing the ID
@ -64,7 +65,17 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
status: record.getStringValue('status'), status: record.getStringValue('status'),
); );
}).toList(); }).toList();
userData.sort((a,b){
DateTime dateA= DateFormat('dd/MM/yyyy').parse(a.registrationDate);
DateTime dateB = DateFormat('dd/MM/yyyy').parse(b.registrationDate);
return dateB.compareTo(dateA);
});
filteredUserData = List.from(userData); filteredUserData = List.from(userData);
isLoading = false;
}); });
} catch (e) { } catch (e) {
print('Error fetching unverified users: $e'); print('Error fetching unverified users: $e');
@ -338,6 +349,7 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
image: ExactAssetImage(MiscIconAssetPath.search), image: ExactAssetImage(MiscIconAssetPath.search),
width: 24, width: 24,
height: 24, height: 24,
color: Color(0xFFAA8E83)
), ),
@ -349,10 +361,13 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
contentPadding: contentPadding:
EdgeInsets.symmetric(vertical: 8.0, horizontal: 18.0), EdgeInsets.symmetric(vertical: 8.0, horizontal: 18.0),
), ),
onChanged: filterUsers,
),), ),),
), ),
SizedBox(height: myheight / 40), SizedBox(height: myheight / 40),
filteredUserData.isEmpty isLoading
? Center(child: CircularProgressIndicator())
:filteredUserData.isEmpty
? Center( ? Center(
child: Padding( child: Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),

View File

@ -1,5 +1,7 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:intl/intl.dart';
import 'package:pocketbase/pocketbase.dart';
import '../../custom_drawer_routes.dart'; import '../../custom_drawer_routes.dart';
class NotificationPage extends StatefulWidget { class NotificationPage extends StatefulWidget {
@ -9,23 +11,63 @@ class NotificationPage extends StatefulWidget {
class _NotificationPageState extends State<NotificationPage> { class _NotificationPageState extends State<NotificationPage> {
// Example notification data // Example notification data
List<Map<String, dynamic>> notifications = [ final _pb = PocketBase('https://pb.venbait.in');
{"title": "Social datasets are updated", "date": "04 Nov 2024 08:25 PM", "category": "Social"}, List<Map<String, dynamic>> notifications = [];
{"title": "New feature updated", "date": "04 Nov 2024 08:25 PM", "category": "App updates"},
];
// Current selected tab index // Current selected tab index
int selectedTabIndex = 0; int selectedTabIndex = 0;
// Tab categories // Tab categories
final List<String> tabs = ["All updates", "App updates", "Social", "Economy", "Environment", "Favourites"]; final List<String> tabs = [
"All updates",
"App updates",
"Social",
"Economy",
"Environment",
"Favourites"
];
String formatDate(String dateString) {
try {
DateTime dateTime =
DateTime.parse(dateString); // Convert API date to DateTime
return DateFormat('dd MMM yyyy hh:mm a')
.format(dateTime); // Format DateTime
} catch (e) {
return 'Invalid Date'; // Handle parsing errors
}
}
Future<void> fetchNotifications() async {
try {
await _pb.admins
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
final result = await _pb.collection('notification').getFullList();
setState(() {
notifications = result.map((record) => record.toJson()).toList();
});
} catch (e) {
print('Error fetching notifications: $e');
}
}
@override
void initState() {
super.initState();
fetchNotifications();
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
// Filter notifications based on the selected tab // Filter notifications based on the selected tab
List<Map<String, dynamic>> filteredNotifications = selectedTabIndex == 0 List<Map<String, dynamic>> filteredNotifications = selectedTabIndex == 0
? notifications ? notifications
: notifications.where((notification) => notification["category"] == tabs[selectedTabIndex]).toList(); : notifications
.where((notification) =>
notification["category"] == tabs[selectedTabIndex])
.toList();
return PopScope( return PopScope(
canPop: false, canPop: false,
@ -49,49 +91,51 @@ class _NotificationPageState extends State<NotificationPage> {
Expanded( Expanded(
child: selectedTabIndex == 1 child: selectedTabIndex == 1
? Center( ? Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Image.asset( Image.asset(
'assets/backgrounds/Notification/Update_notific.png', 'assets/backgrounds/Notification/Update_notific.png',
height: 200, height: 200,
), ),
SizedBox(height: 16), SizedBox(height: 16),
Text( Text(
filteredNotifications.isNotEmpty filteredNotifications.isNotEmpty
? filteredNotifications[0]['title'] ? filteredNotifications[0]['title']
: 'No updates available.', : 'No updates available.',
style: TextStyle(fontSize: 16, color: Colors.grey), style: TextStyle(fontSize: 16, color: Colors.grey),
textAlign: TextAlign.center, textAlign: TextAlign.center,
), ),
], ],
), ),
) )
: filteredNotifications.isEmpty : filteredNotifications.isEmpty
? Center( ? Center(
child: Column( child: Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
Icon(Icons.info_outline, size: 100, color: Colors.grey[400]), Icon(Icons.info_outline,
SizedBox(height: 16), size: 100, color: Colors.grey[400]),
Text( SizedBox(height: 16),
'No notifications available.', Text(
style: TextStyle(fontSize: 16, color: Colors.grey), 'No notifications available.',
), style:
], TextStyle(fontSize: 16, color: Colors.grey),
), ),
) ],
: ListView.builder( ),
itemCount: filteredNotifications.length, )
itemBuilder: (context, index) { : ListView.builder(
final notification = filteredNotifications[index]; itemCount: filteredNotifications.length,
return NotificationTile( itemBuilder: (context, index) {
title: notification["title"]!, final notification = filteredNotifications[index];
date: notification["date"]!, return NotificationTile(
category: notification["category"]!, title: notification['title'] ?? 'No Title',
); date: formatDate(notification['created'] ?? ''),
}, category: notification['category'] ?? 'Unknown',
), );
},
),
), ),
], ],
), ),
@ -128,8 +172,11 @@ class TabBarHeader extends StatelessWidget {
TextButton( TextButton(
onPressed: () => onTabSelected(index), onPressed: () => onTabSelected(index),
style: ButtonStyle( style: ButtonStyle(
foregroundColor: MaterialStateProperty.resolveWith((states) { foregroundColor:
return selectedIndex == index ? Color(0xFF985400) : Colors.grey[700]; MaterialStateProperty.resolveWith((states) {
return selectedIndex == index
? Color(0xFF985400)
: Colors.grey[700];
}), }),
), ),
child: Text(text), child: Text(text),
@ -169,7 +216,8 @@ class NotificationTile extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return ListTile( return ListTile(
leading: Icon(Icons.circle, size: 12, color: category == "Social" ? Colors.red : Colors.grey), leading: Icon(Icons.circle,
size: 12, color: category == "Social" ? Colors.red : Colors.grey),
title: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)), title: Text(title, style: const TextStyle(fontWeight: FontWeight.bold)),
subtitle: Text(date), subtitle: Text(date),
); );

View File

@ -42,11 +42,11 @@ class BaseScaffold extends ConsumerStatefulWidget {
}); });
final Widget body; final Widget body;
final Widget title; final Widget title;
final Widget? navBackArrow; final Widget? navBackArrow;
final Color? dividerColor; final Color? dividerColor;
final bool showDivider; final bool showDivider;
final bool showBackButton; final bool showBackButton;
final bool colorChange; final bool colorChange;
final bool? mycenterTitle; final bool? mycenterTitle;
final List<Widget>? actions; final List<Widget>? actions;
final Color? bottomColor; final Color? bottomColor;
@ -640,7 +640,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
return Scaffold( return Scaffold(
backgroundColor: Colors.white, backgroundColor: Colors.white,
appBar: AppBar( appBar: AppBar(
title: Padding( title: Padding(
padding: EdgeInsets.only(top: 10), padding: EdgeInsets.only(top: 10),
child: Align( child: Align(
alignment: Alignment.centerLeft, alignment: Alignment.centerLeft,
@ -698,9 +698,9 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
], ],
leading: Padding( leading: Padding(
padding: const EdgeInsets.only(top: 7.0,left: 4), padding: const EdgeInsets.only(top: 7.0, left: 4),
child: Row( child: Row(
mainAxisSize:MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
if (widget.showBackButton == true) if (widget.showBackButton == true)
SizedBox( SizedBox(
@ -721,7 +721,9 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
}, },
), ),
), ),
SizedBox(width: 7,), SizedBox(
width: 7,
),
Builder( Builder(
builder: (BuildContext context) { builder: (BuildContext context) {
return SizedBox( return SizedBox(
@ -743,8 +745,6 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
], ],
), ),
), ),
), ),
drawer: Drawer( drawer: Drawer(
backgroundColor: Colors.white, backgroundColor: Colors.white,
@ -826,21 +826,22 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
if (userId != 'guest') if (userId != 'guest')
ListTile( ListTile(
leading: Icon(Icons.notifications_none), leading: Icon(Icons.notifications_none),
title: const Text('Notification'), title: Text(AppLocalizations.of(context)!.notification),
onTap: () => _navigateTo(context, '/notification'), onTap: () => _navigateTo(context, '/notification'),
), ),
ListTile( ListTile(
leading: Icon(Icons.message_outlined), leading: Icon(Icons.message_outlined),
// leading: Image.asset( // leading: Image.asset(
// DrawerAssetIconPath.feedback, // DrawerAssetIconPath.feedback,
// color: Colors.black, // color: Colors.black,
// width: 20, // width: 20,
// height: 20, // height: 20,
// ), // ),
// title: const Text('Feedback'), // title: const Text('Feedback'),
title: Text(AppLocalizations.of(context)!.feedback_title), title: Text(AppLocalizations.of(context)!.feedback_title),
onTap: () => _navigateTo(context, '/feedback', extra: userName), onTap: () =>
), _navigateTo(context, '/feedback', extra: userName),
),
if (role == 'admin') if (role == 'admin')
ListTile( ListTile(
leading: Icon(Icons.manage_accounts_outlined), leading: Icon(Icons.manage_accounts_outlined),
@ -1014,6 +1015,7 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
body: widget.body, body: widget.body,
); );
} }
//drawer close code //drawer close code
void _navigateTo(BuildContext context, String route, {Object? extra}) { void _navigateTo(BuildContext context, String route, {Object? extra}) {
Navigator.pop(context); // Close the drawer Navigator.pop(context); // Close the drawer

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.15+16 version: 1.0.19+20
environment: environment:
sdk: ">=3.2.3 <4.0.0" sdk: ">=3.2.3 <4.0.0"