Charts Added

This commit is contained in:
venbaittech 2025-01-30 16:58:50 +05:30
parent 1a39a7c740
commit 5c5243d02e
10 changed files with 1737 additions and 542 deletions

View File

@ -374,6 +374,7 @@ final GoRouter router = GoRouter(
'0xFFFFFFFF'; // Default white '0xFFFFFFFF'; // Default white
final mainTopic = state.uri.queryParameters['mainTopic'] ?? ''; final mainTopic = state.uri.queryParameters['mainTopic'] ?? '';
final title = state.uri.queryParameters['title'] ?? ''; final title = state.uri.queryParameters['title'] ?? '';
final key = state.uri.queryParameters['key'] ?? '';
print('Router dataSets: $dataSets'); print('Router dataSets: $dataSets');
print('Router bgColor: $bgColor'); print('Router bgColor: $bgColor');
@ -386,6 +387,7 @@ final GoRouter router = GoRouter(
bgColor: bgColor, bgColor: bgColor,
mainTopic: mainTopic, mainTopic: mainTopic,
title: title, title: title,
keyParam: key,
); );
}, },
), ),

View File

@ -1,7 +1,9 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart'; import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
import 'package:uae_stat/presentation/components/constant/constant.dart'; import 'package:uae_stat/presentation/components/constant/constant.dart';
@ -23,28 +25,31 @@ class UaeNumbers extends StatelessWidget {
} }
} }
class uaenumberWidget extends StatefulWidget { class uaenumberWidget extends ConsumerStatefulWidget {
const uaenumberWidget({super.key}); const uaenumberWidget({super.key});
@override @override
_UaenumberWidgetState createState() => _UaenumberWidgetState(); ConsumerState<uaenumberWidget> createState() => _UaenumberWidgetState();
} }
class _UaenumberWidgetState extends State<uaenumberWidget> { class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
@override @override
List<dynamic> homePageData = []; List<dynamic> homePageData = [];
bool isLoading = true; bool isLoading = true;
int? expandedIndex = 0;
@override @override
void initState() { void initState() {
fetchData(); super.initState();
final locale = ref.read(localeProvider);
fetchData(locale?.languageCode ?? 'en');
} }
Future<void> fetchData() async { Future<void> fetchData(locale) async {
// const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; // const baseUrl = 'https://pb.venbait.in/api/getHomePageData';
const baseUrl = 'https://pb.venbait.in/api/getUAENumbersData'; const baseUrl = 'https://pb.venbait.in/api/getUAENumbersData';
try { try {
final response = await http.get(Uri.parse(baseUrl)); final response = await http.get(Uri.parse(baseUrl + '?language=$locale'));
if (response.statusCode == 200) { if (response.statusCode == 200) {
setState(() { setState(() {
homePageData = json.decode(response.body); homePageData = json.decode(response.body);
@ -63,6 +68,10 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
ref.listen<Locale?>(localeProvider, (previous, next) {
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
fetchData(localeCode);
});
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
@ -99,7 +108,12 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
return CustomExpandableTile( return CustomExpandableTile(
index: index, index: index,
isExpanded: isFirstTile, isExpanded: expandedIndex == index, // Compare with expandedIndex
onTap: (index) {
setState(() {
expandedIndex = (expandedIndex == index) ? null : index;
});
},
title: mainTopic['main_topic'], title: mainTopic['main_topic'],
titleBackgroundColor: backgroundColor, titleBackgroundColor: backgroundColor,
children: _buildSubTopics(mainTopic['sub_topics'] ?? [], mywidth, children: _buildSubTopics(mainTopic['sub_topics'] ?? [], mywidth,
@ -280,6 +294,8 @@ class CustomExpandableTile extends StatefulWidget {
final List<Widget> children; final List<Widget> children;
final int index; final int index;
final bool isExpanded; final bool isExpanded;
final ValueChanged<int> onTap;
const CustomExpandableTile({ const CustomExpandableTile({
required this.title, required this.title,
@ -287,6 +303,8 @@ class CustomExpandableTile extends StatefulWidget {
required this.children, required this.children,
required this.index, required this.index,
required this.isExpanded, required this.isExpanded,
required this.onTap,
}); });
@override @override
@ -294,14 +312,12 @@ class CustomExpandableTile extends StatefulWidget {
} }
class _CustomExpandableTileState extends State<CustomExpandableTile> { class _CustomExpandableTileState extends State<CustomExpandableTile> {
// bool isExpanded = false; bool isExpanded = false;
late bool isExpanded; // late bool isExpanded;
@override @override
void initState() { void initState() {
super.initState(); super.initState(); // Initialize isExpanded based on widget's property
isExpanded =
widget.isExpanded; // Initialize isExpanded based on widget's property
} }
@override @override
@ -312,11 +328,8 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
child: Column( child: Column(
children: [ children: [
GestureDetector( GestureDetector(
onTap: () { onTap: () => widget.onTap(widget.index),
setState(() {
isExpanded = !isExpanded;
});
},
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(
color: widget.titleBackgroundColor, color: widget.titleBackgroundColor,
@ -335,7 +348,7 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
), ),
), ),
Icon( Icon(
isExpanded widget.isExpanded
? Icons.keyboard_arrow_up ? Icons.keyboard_arrow_up
: Icons.keyboard_arrow_down, : Icons.keyboard_arrow_down,
color: Colors.white, color: Colors.white,
@ -350,8 +363,8 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
duration: Duration(milliseconds: 300), duration: Duration(milliseconds: 300),
curve: Curves.easeInOut, curve: Curves.easeInOut,
width: double.infinity, width: double.infinity,
height: isExpanded ? myheight * 0.52 : 0, height: widget.isExpanded ? myheight * 0.52 : 0,
child: isExpanded child: widget.isExpanded
? SingleChildScrollView( ? SingleChildScrollView(
child: Container( child: Container(
decoration: BoxDecoration( decoration: BoxDecoration(

View File

@ -205,7 +205,31 @@ class _CreateNewPwState extends State<CreateNewPw> {
padding: const EdgeInsets.all(24.0), padding: const EdgeInsets.all(24.0),
child: Column( child: Column(
children: [ children: [
// SizedBox(height: screenHeight / 7),
Align(
alignment: Alignment.topRight,
child: GestureDetector(
onTap: () {
context.go('/editProfile');
},
child: Container(
margin: EdgeInsets.only(top: 16,left: 16,bottom: 16,right: 1), // Add margin for positioning
width: 30, // Circle diameter
height: 30,
decoration: BoxDecoration(
color: Colors.grey[300], // Circle color
shape: BoxShape.circle,
),
child: Icon(
Icons.close,
size: 20, // Icon size
color: Colors.white, // Icon color
),
),
),
),
SizedBox(height: screenHeight / 6), SizedBox(height: screenHeight / 6),
Text( Text(
// "Create New Password", // "Create New Password",
AppLocalizations.of(context)!.create_new_password, AppLocalizations.of(context)!.create_new_password,

View File

@ -1,15 +1,20 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/presentation/Screens/charts/services/api_service.dart'; import 'package:uae_stat/presentation/Screens/charts/services/api_service.dart';
import 'package:uae_stat/presentation/Screens/charts/widgets/chart_widget.dart'; import 'package:uae_stat/presentation/Screens/charts/widgets/chart_widget.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import '../filters/search_filter_helper.dart'; import '../filters/search_filter_helper.dart';
class ChartScreen1 extends StatefulWidget { class ChartScreen1 extends ConsumerStatefulWidget {
final String dataSets; final String dataSets;
final String bgColor; final String bgColor;
final String mainTopic; final String mainTopic;
final String title; final String title;
final String? keyParam; // Nullable String
const ChartScreen1({ const ChartScreen1({
Key? key, Key? key,
@ -17,18 +22,20 @@ class ChartScreen1 extends StatefulWidget {
required String this.bgColor, required String this.bgColor,
required this.mainTopic, required this.mainTopic,
required this.title, required this.title,
required this.keyParam,
}); });
@override @override
_ChartScreen1State createState() => _ChartScreen1State(); ConsumerState<ChartScreen1> createState() => _ChartScreen1State();
} }
class _ChartScreen1State extends State<ChartScreen1> { class _ChartScreen1State extends ConsumerState<ChartScreen1> {
List<Map<String, dynamic>> selectedFiltersStorage = []; List<Map<String, dynamic>> selectedFiltersStorage = [];
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>(); final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
final ApiService apiService = ApiService(); final ApiService apiService = ApiService();
bool isLoading = true; bool isLoading = true;
List<dynamic> isChartData = []; List<dynamic> isChartData = [];
List<dynamic> nonChartData = []; List<dynamic> nonChartData = [];
List<dynamic> filterDataSet = [];
List<dynamic> filterData = []; List<dynamic> filterData = [];
List<dynamic> chartsData = []; List<dynamic> chartsData = [];
List<dynamic> tabFilteredChartData = []; List<dynamic> tabFilteredChartData = [];
@ -50,7 +57,8 @@ class _ChartScreen1State extends State<ChartScreen1> {
final String bgColor = widget.bgColor; final String bgColor = widget.bgColor;
print(' bgColor $bgColor'); print(' bgColor $bgColor');
// fetchChartData(widget.dataSets); // fetchChartData(widget.dataSets);
fetchChartData(widget.dataSets).then((_) { final locale = ref.read(localeProvider);
fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) {
if (_tabsData.isNotEmpty) { if (_tabsData.isNotEmpty) {
// Call onTabSelected for the first tab // Call onTabSelected for the first tab
onTabSelected(_tabsData[0]['id']); onTabSelected(_tabsData[0]['id']);
@ -74,6 +82,7 @@ class _ChartScreen1State extends State<ChartScreen1> {
}); });
_scrollToIndex(_activeTabIndex); _scrollToIndex(_activeTabIndex);
onTabSelected(_tabsData[_activeTabIndex]['id']!); // Pass the tab's id onTabSelected(_tabsData[_activeTabIndex]['id']!); // Pass the tab's id
print("TABFiltered Data: $filterData");
} }
} }
@ -87,9 +96,39 @@ class _ChartScreen1State extends State<ChartScreen1> {
} }
} }
// void processChartData(chartsData) {
// // Group data by 'kpi'
// Map<String, List<Map<String, dynamic>>> groupedData = {};
// for (var chart in chartsData) {
// String kpi = chart['kpi'] ?? '';
// if (!groupedData.containsKey(kpi)) {
// groupedData[kpi] = [];
// }
// groupedData[kpi]!.add(chart);
// }
//
// // Format 'kpi' values for _tabs
// List<Map<String, String>> _tabs = groupedData.keys.map((kpi) {
// String name = kpi
// .split('_') // Split by underscore
// .map(
// (word) => word[0].toUpperCase() + word.substring(1)) // Capitalize
// .join(' '); // Join words with space
//
// return {'id': kpi, 'name': name};
// }).toList();
//
// print('Grouped Data: $groupedData');
// print('Tabs: $_tabs');
// setState(() {
// _tabsData = _tabs;
// });
// }
void processChartData(chartsData) { void processChartData(chartsData) {
// Group data by 'kpi' // Group data by 'kpi'
Map<String, List<Map<String, dynamic>>> groupedData = {}; Map<String, List<Map<String, dynamic>>> groupedData = {};
for (var chart in chartsData) { for (var chart in chartsData) {
String kpi = chart['kpi'] ?? ''; String kpi = chart['kpi'] ?? '';
if (!groupedData.containsKey(kpi)) { if (!groupedData.containsKey(kpi)) {
@ -98,30 +137,52 @@ class _ChartScreen1State extends State<ChartScreen1> {
groupedData[kpi]!.add(chart); groupedData[kpi]!.add(chart);
} }
// Format 'kpi' values for _tabs // Format 'kpi' values for _tabs with tab_heading
List<Map<String, String>> _tabs = groupedData.keys.map((kpi) { List<Map<String, String>> _tabs = groupedData.entries.map((entry) {
String name = kpi String kpi = entry.key;
// Extract tab_heading from the first chart in the grouped list
String tabHeading = entry.value.isNotEmpty
? entry.value.first['tab_heading'] ?? 'Unknown'
: 'Unknown';
String formattedKpi = kpi
.split('_') // Split by underscore .split('_') // Split by underscore
.map( .map((word) => word.isNotEmpty
(word) => word[0].toUpperCase() + word.substring(1)) // Capitalize ? word[0].toUpperCase() + word.substring(1)
: '') // Capitalize
.join(' '); // Join words with space .join(' '); // Join words with space
return {'id': kpi, 'name': name}; return {'id': kpi, 'name': tabHeading};
}).toList(); }).toList();
print('Grouped Data: $groupedData'); print('Grouped Data: $groupedData');
print('Tabs: $_tabs'); print('Tabs: $_tabs');
setState(() { setState(() {
_tabsData = _tabs; _tabsData = _tabs;
}); });
} }
Future<void> fetchChartData(String dataSets) async { Future<void> fetchChartData(String dataSets, locale) async {
var data = await apiService.fetchChartData(dataSets); var data = await apiService.fetchChartData(dataSets, locale);
if (data.containsKey('filterData')) {
var filterData = data['filterData'];
filterDataSet = filterData.entries
.map((entry) => {'key': entry.key, 'value': entry.value})
.toList();
print("filterDataf1:- $filterData");
print("filterDataf11:- $filterDataSet");
} else {
filterDataSet = data['filterData'] ?? [];
print('filterData not found!');
}
setState(() { setState(() {
isChartData = data['isChartData'] ?? []; isChartData = data['isChartData'] ?? [];
nonChartData = data['nonChartData'] ?? []; nonChartData = data['nonChartData'] ?? [];
filterData = data['filterData'] ?? []; // filterData = data['filterData'] ?? [];
originalChartsData = List.from(isChartData); // Store original data originalChartsData = List.from(isChartData); // Store original data
originalCardData = List.from(nonChartData); originalCardData = List.from(nonChartData);
@ -133,17 +194,19 @@ class _ChartScreen1State extends State<ChartScreen1> {
print('chartsData :- $chartsData'); print('chartsData :- $chartsData');
print('cardData :- $cardData'); print('cardData :- $cardData');
print('filterData :- $filterData'); // print('filterData :- $filterData');
isLoading = false; isLoading = false;
}); });
print(chartsData); print('chartsData -$chartsData');
print(cardData); print('cardData -$cardData');
} }
void applyFilters(BuildContext context, List filters, List data, void applyFilters(BuildContext context, List filters, List data,
List dataCard, List selectedFilters) { List dataCard, List selectedFilters) {
print("Selected Filters before applying: $selectedFilters"); print("applyFilters called");
// Check if all filter_data is empty print("Selected ApplyFilters: $selectedFilters");
print("Selected data: $data");
if (selectedFilters.every((filter) => filter['filter_data'].isEmpty)) { if (selectedFilters.every((filter) => filter['filter_data'].isEmpty)) {
setState(() { setState(() {
chartsData = chartsData =
@ -157,8 +220,9 @@ class _ChartScreen1State extends State<ChartScreen1> {
// Loop through each chart data in the `data` list // Loop through each chart data in the `data` list
List filteredData = []; List filteredData = [];
Set<String> addedChartIds = {}; // Track unique chart identifiers
for (var chart in data) { for (var chart in data) {
// Extract response data for filtering final groupBy = chart['group_by'];
List response = chart['response'] ?? []; List response = chart['response'] ?? [];
// Filter the response based on selected filters // Filter the response based on selected filters
@ -171,20 +235,31 @@ class _ChartScreen1State extends State<ChartScreen1> {
final filterValues = filter['filter_data']; final filterValues = filter['filter_data'];
// Ensure the filter_key exists in the `ObsKey` and check if it matches any of the `filter_data` // Ensure the filter_key exists in the `ObsKey` and check if it matches any of the `filter_data`
if (obsKey.containsKey(filterKey)) { if (groupBy == filterKey && obsKey.containsKey(filterKey)) {
final obsKeyValue = obsKey[filterKey]?.toString(); final obsKeyValue = obsKey[filterKey]?.toString();
return filterValues.isEmpty || filterValues.contains(obsKeyValue); return filterValues.isEmpty || filterValues.contains(obsKeyValue);
} }
return false;
if (filterKey == 'TIME_PERIOD' && obsKey.containsKey('TIME_PERIOD')) {
final timePeriodValue = obsKey['TIME_PERIOD']?.toString();
return filterValues.isEmpty ||
filterValues.contains(timePeriodValue);
}
return true;
}); });
}).toList(); }).toList();
// If any data matches the filter, add the whole chart data object // If any data matches the filter, add the whole chart data object
if (chartFilteredData.isNotEmpty) { // Add filtered chart only once
if (chartFilteredData.isNotEmpty &&
!addedChartIds.contains(chart['chart_heading'])) {
filteredData.add({ filteredData.add({
...chart, // Include all other properties of the chart object ...chart,
'response': chartFilteredData, // Only include filtered response data 'response': chartFilteredData,
}); });
addedChartIds
.add(chart['chart_heading']); // Track by a unique identifier
} }
} }
@ -224,7 +299,7 @@ class _ChartScreen1State extends State<ChartScreen1> {
// Update the chartsData with the filtered data // Update the chartsData with the filtered data
setState(() { setState(() {
chartsData = filteredData; chartsData = filteredData;
cardData = filteredCardData; cardData = filteredCardData; // Adjust this part as needed
}); });
print("Filtered Data: $filteredData"); print("Filtered Data: $filteredData");
@ -271,7 +346,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [ children: [
Text( Text(
'Filters', context.translate(
'Filters',
'المرشحات',
),
style: TextStyle( style: TextStyle(
fontSize: 18, fontSize: 18,
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
@ -357,7 +435,12 @@ class _ChartScreen1State extends State<ChartScreen1> {
setState(() {}); setState(() {});
Navigator.pop(context); Navigator.pop(context);
}, },
child: Text('OK'), child: Text(
context.translate(
'OK',
'نعم',
),
),
), ),
], ],
); );
@ -428,7 +511,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
selectedFiltersStorage.clear(); selectedFiltersStorage.clear();
Navigator.pop(context); Navigator.pop(context);
}, },
child: Text('Clear'), child: Text(context.translate(
'Clear',
'واضح',
)),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.grey, backgroundColor: Colors.grey,
), ),
@ -447,7 +533,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
// Save the selected filters to storage after applying // Save the selected filters to storage after applying
selectedFiltersStorage = List.from(selectedFilters); selectedFiltersStorage = List.from(selectedFilters);
}, },
child: Text('Apply Filter'), child: Text(context.translate(
'Apply Filter',
'تطبيق الفلتر',
)),
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
backgroundColor: Colors.blue, backgroundColor: Colors.blue,
), ),
@ -466,6 +555,28 @@ class _ChartScreen1State extends State<ChartScreen1> {
void onTabSelected(String tabId) { void onTabSelected(String tabId) {
print('Selected Tab: $tabId'); print('Selected Tab: $tabId');
selectedFiltersStorage.clear(); selectedFiltersStorage.clear();
// Filter the filterDataSet
filterData = filterDataSet
.where((item) => item['key'] == tabId)
.map((item) => item['value'])
.where((item) => item != null && item is Iterable)
.expand((item) => item)
.toList();
for (var item in filterData) {
if (item['filter_key'] == 'TIME_PERIOD') {
// Convert the values to integers, sort them, and convert back to strings
List<int> timePeriodData = item['filter_data']
.map<int>((e) => int.parse(e.toString())) // Convert to int
.toList();
timePeriodData.sort((a, b) => a.compareTo(b)); // Sort numerically
// Optionally, convert sorted integers back to strings if necessary
item['filter_data'] = timePeriodData.map((e) => e.toString()).toList();
}
}
print("TABFiltered Data: $filterData");
setState(() { setState(() {
chartsData = originalChartsData; chartsData = originalChartsData;
cardData = originalCardData; cardData = originalCardData;
@ -507,22 +618,38 @@ class _ChartScreen1State extends State<ChartScreen1> {
// For example, you can update the chart data or display the results // For example, you can update the chart data or display the results
} }
double calculateAspectRatio(int itemCount) { // double calculateAspectRatio(int itemCount) {
// Modify the logic based on your layout requirements // // Modify the logic based on your layout requirements
if (itemCount <= 2) { // if (itemCount <= 2) {
return 190.5 / 180; // return 190.5 / 180;
} else if (itemCount == 3) { // } else if (itemCount == 3) {
return 180.0 / 300; // return 180.0 / 250;
} else if (itemCount == 4) { // } else if (itemCount == 4) {
return 190.5 / 180; // return 190.5 / 180;
// } else {
// return 180.0 / 180; // Default for more items
// // return 190.5 / 180;
// }
// }
double calculateAspectRatio(int crossAxisCount, List<dynamic> cardData) {
// Determine a default aspect ratio based on the most common chart type in the list
if (cardData.any((item) =>
item['chart_type'] == 'total' || item['chart_type'] == 'average')) {
return crossAxisCount == 2 ? 1.0 : 0.7; // Larger Content
// return crossAxisCount == 2 ? 1.5 : 0.9;
} else { } else {
return 180.0 / 260; // Default for more items return crossAxisCount == 2 ? 1.5 : 0.9;
// return 190.5 / 180; // Shorter Content
} }
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
ref.listen<Locale?>(localeProvider, (previous, next) {
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
fetchChartData(widget.dataSets, localeCode);
});
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
final color = final color =
@ -536,11 +663,18 @@ class _ChartScreen1State extends State<ChartScreen1> {
leading: IconButton( leading: IconButton(
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white), icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
onPressed: () { onPressed: () {
context.go('/uaenumbers'); if (widget.keyParam == 'home') {
context.go('/myhomepage');
} else {
context.go('/uaenumbers');
}
}, },
), ),
title: Text( title: Text(
'UAE Numbers', context.translate(
'UAE Numbers',
'أرقام الإمارات',
),
style: TextStyle(color: Colors.white), style: TextStyle(color: Colors.white),
), ),
), ),
@ -609,7 +743,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
Row( Row(
children: [ children: [
Text( Text(
'Bookmark', context.translate(
'Bookmark',
'إشارة مرجعية',
),
style: const TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 16,
color: Colors.white, color: Colors.white,
@ -624,7 +761,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
Row( Row(
children: [ children: [
Text( Text(
'Share', context.translate(
'Share',
'يشارك',
),
style: const TextStyle( style: const TextStyle(
fontSize: 16, fontSize: 16,
color: Colors.white, color: Colors.white,
@ -653,33 +793,37 @@ class _ChartScreen1State extends State<ChartScreen1> {
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
// Left arrow button // Left arrow button
_buildArrowButton( if (_tabsData.length > 1)
onPressed: _activeTabIndex > 0 ? _scrollLeft : null, _buildArrowButton(
icon: Icons.arrow_back_ios_new, onPressed:
), _activeTabIndex > 0 ? _scrollLeft : null,
icon: Icons.arrow_back_ios_new,
),
// Tabs with horizontal scroll // Tabs with horizontal scroll
Expanded( if (_tabsData.length > 1)
child: SingleChildScrollView( Expanded(
controller: _scrollController, child: SingleChildScrollView(
scrollDirection: Axis.horizontal, controller: _scrollController,
child: Row( scrollDirection: Axis.horizontal,
children: child: Row(
List.generate(_tabsData.length, (index) { children:
return _buildTab( List.generate(_tabsData.length, (index) {
_tabsData[index], return _buildTab(
isActive: index == _activeTabIndex, _tabsData[index],
); isActive: index == _activeTabIndex,
}), );
}),
),
), ),
), ),
),
// Right arrow button // Right arrow button
_buildArrowButton( if (_tabsData.length > 1)
onPressed: _activeTabIndex < _tabsData.length - 1 _buildArrowButton(
? _scrollRight onPressed: _activeTabIndex < _tabsData.length - 1
: null, ? _scrollRight
icon: Icons.arrow_forward_ios, : null,
), icon: Icons.arrow_forward_ios,
),
], ],
), ),
// Expanded( // Expanded(
@ -699,25 +843,32 @@ class _ChartScreen1State extends State<ChartScreen1> {
physics: const NeverScrollableScrollPhysics(), physics: const NeverScrollableScrollPhysics(),
gridDelegate: gridDelegate:
SliverGridDelegateWithFixedCrossAxisCount( SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: cardData.length == 2 crossAxisCount: cardData.length == 2
? 2 ? 2
: cardData.length == 3 : cardData.length == 3
? 3 ? 3
: cardData.length == 4 : cardData.length == 4
? 2 ? 2
: 3, // Default to 3 if more than 4 items // 2 cards per row : 3, // Default to 3 if more than 4 items // 2 cards per row
crossAxisSpacing: 2, crossAxisSpacing: 2,
mainAxisSpacing: 5, mainAxisSpacing: 5,
childAspectRatio: childAspectRatio:
calculateAspectRatio(cardData.length)), calculateAspectRatio(cardData.length, cardData),
),
itemBuilder: (context, index) { itemBuilder: (context, index) {
final item = cardData[index]; final item = cardData[index];
print('item item item $item'); print('item item item $item');
final chart_type = item['chart_type']; final chart_type = item['chart_type'];
final chart_heading = item['chart_heading']; final chart_heading = item['chart_heading'];
final card_logo = item['card_logo'];
final data = apiService.processNonChartData(item); final data = apiService.processNonChartData(item);
print('processNonChartData'); print('processNonChartData');
double cardHeight = (chart_type == 'totals' ||
chart_type == 'averages')
? 180.0
: 130.0;
if (chart_type == 'total') { if (chart_type == 'total') {
return Card( return Card(
margin: const EdgeInsets.all(10), margin: const EdgeInsets.all(10),
@ -725,21 +876,41 @@ class _ChartScreen1State extends State<ChartScreen1> {
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
elevation: 4, elevation: 4,
child: Padding( child: Container(
height: cardHeight,
padding: const EdgeInsets.all(10.0), padding: const EdgeInsets.all(10.0),
child: Column( child: Column(
mainAxisSize: MainAxisSize
.min, // Adjust card height based on content
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon(Icons.public, // const Icon(Icons.public,
color: Color(0xFF90B0D5), size: 30), // color: Color(0xFF90B0D5), size: 30),
Image.network(
card_logo ?? '',
width: 30,
height: 30,
errorBuilder:
(context, error, stackTrace) {
return Icon(Icons.public,
color: Color(0xFF90B0D5),
size: 30); // Fallback icon
},
),
const SizedBox(height: 3), const SizedBox(height: 3),
Text( Flexible(
'${chart_heading ?? 'NA'}', fit: FlexFit.loose,
textAlign: TextAlign.center, child: FittedBox(
style: TextStyle( // fit: BoxFit.contain,
fontSize: 11, child: Text(
fontWeight: FontWeight.w400, '${chart_heading ?? 'NA'}',
color: Colors.black87, textAlign: TextAlign.center,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
), ),
), ),
Text( Text(
@ -747,13 +918,19 @@ class _ChartScreen1State extends State<ChartScreen1> {
style: const TextStyle( style: const TextStyle(
fontSize: 11, color: Colors.grey), fontSize: 11, color: Colors.grey),
), ),
Text( Flexible(
apiService.formatAmount( fit: FlexFit.loose,
data['lastYearValue']), child: FittedBox(
style: const TextStyle( fit: BoxFit.contain,
fontSize: 16, child: Text(
fontWeight: FontWeight.w900, apiService.formatAmount(
color: Color(0xFF90B0D5), data['lastYearValue']),
style: const TextStyle(
fontSize: 26,
fontWeight: FontWeight.w900,
color: Color(0xFF90B0D5),
),
),
), ),
), ),
SizedBox( SizedBox(
@ -764,19 +941,27 @@ class _ChartScreen1State extends State<ChartScreen1> {
1, // Divider line thickness 1, // Divider line thickness
), ),
), ),
Text( Flexible(
apiService.formatAmount( fit: FlexFit.loose,
data['secondLastYearValue']), child: FittedBox(
style: const TextStyle( fit: BoxFit.contain,
fontSize: 12, child: Text(
fontWeight: FontWeight.w600, apiService.formatAmount(
color: Color(0xFFD83731), data['secondLastYearValue']),
style: const TextStyle(
fontSize: 16,
fontWeight: FontWeight.w600,
color: Color(0xFFD83731),
),
),
), ),
), ),
Text( Text(
'(${data['secondLastYear'] ?? 'NA'})', '(${data['secondLastYear'] ?? 'NA'})',
style: const TextStyle( style: const TextStyle(
fontSize: 11, color: Colors.grey), fontSize: 8,
fontWeight: FontWeight.w500,
color: Colors.grey),
), ),
], ],
), ),
@ -789,13 +974,24 @@ class _ChartScreen1State extends State<ChartScreen1> {
borderRadius: BorderRadius.circular(12), borderRadius: BorderRadius.circular(12),
), ),
elevation: 4, elevation: 4,
child: Padding( child: Container(
height: cardHeight,
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
child: Column( child: Column(
mainAxisSize: MainAxisSize.min,
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
const Icon(Icons.analytics, Image.network(
color: Color(0xFF90B0D5), size: 30), card_logo ?? '',
width: 30,
height: 30,
errorBuilder:
(context, error, stackTrace) {
return Icon(Icons.public,
color: Color(0xFF90B0D5),
size: 30); // Fallback icon
},
),
const SizedBox(height: 5), const SizedBox(height: 5),
Text( Text(
'${chart_heading ?? 'NA'}', '${chart_heading ?? 'NA'}',
@ -811,12 +1007,133 @@ class _ChartScreen1State extends State<ChartScreen1> {
style: const TextStyle( style: const TextStyle(
fontSize: 11, color: Colors.grey), fontSize: 11, color: Colors.grey),
), ),
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),
),
),
),
),
],
),
),
);
} else if (chart_type == 'totals') {
return Card(
margin: const EdgeInsets.all(10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 4,
child: Container(
height: cardHeight,
// height: maxHeight,
// padding: const EdgeInsets.all(10.0),
padding: const EdgeInsets.symmetric(
vertical: 0, horizontal: 10),
child: Column(
// mainAxisSize: MainAxisSize.min, // Adjust card height based on content
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.public,
color: Color(0xFF90B0D5), size: 30),
const SizedBox(height: 3),
Flexible(
fit: FlexFit.loose,
child: FittedBox(
// fit: BoxFit.contain,
child: Text(
'${chart_heading ?? 'NA'}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
),
),
Text( Text(
'${data['roundedAverage'] ?? 'NA'}', '(${data['lastYear'] ?? 'NA'})',
style: const TextStyle( style: const TextStyle(
fontSize: 22, fontSize: 11, color: Colors.grey),
fontWeight: FontWeight.w900, ),
color: Color(0xFF90B0D5), Flexible(
fit: FlexFit.loose,
child: FittedBox(
fit: BoxFit.contain,
child: Text(
apiService.formatAmount(
data['lastYearValue']),
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w900,
color: Color(0xFF90B0D5),
),
),
),
),
],
),
),
);
} else if (chart_type == 'averages') {
return Card(
margin: const EdgeInsets.all(10),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(12),
),
elevation: 4,
child: Container(
// height: maxHeight,
// height: 200,
height: cardHeight,
padding: const EdgeInsets.all(5.0),
// padding: const EdgeInsets.symmetric(vertical: 0, horizontal: 10),
child: Column(
// mainAxisSize: MainAxisSize.min, // Adjust card height based on content
mainAxisSize: MainAxisSize.max,
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Icon(Icons.public,
color: Color(0xFF90B0D5), size: 30),
const SizedBox(height: 5),
Text(
'${chart_heading ?? 'NA'}',
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 11,
fontWeight: FontWeight.w400,
color: Colors.black87,
),
),
Text(
'(${data['lastYear'] ?? 'NA'})',
style: const TextStyle(
fontSize: 11, color: Colors.grey),
),
const SizedBox(height: 5),
Flexible(
fit: FlexFit.loose,
child: FittedBox(
fit: BoxFit.contain,
child: Text(
apiService.formatAmount(
data['lastYearValue']),
style: const TextStyle(
fontSize: 22,
fontWeight: FontWeight.w900,
color: Color(0xFF90B0D5),
),
),
), ),
), ),
], ],

View File

@ -13,13 +13,13 @@ class ChartData {
class ApiService { class ApiService {
static const String baseUrl = 'https://pb.venbait.in/api/getDataSet'; static const String baseUrl = 'https://pb.venbait.in/api/getDataSet';
Future<Map<String, dynamic>> fetchChartData(String dataSets) async { Future<Map<String, dynamic>> fetchChartData(String dataSets, locale) async {
List<dynamic> isChartData = []; List<dynamic> isChartData = [];
List<dynamic> nonChartData = []; List<dynamic> nonChartData = [];
List<dynamic> originalChartsData = []; List<dynamic> originalChartsData = [];
List<dynamic> originalCardData = []; List<dynamic> originalCardData = [];
final url = Uri.parse('$baseUrl?dataset=$dataSets'); final url = Uri.parse('$baseUrl?dataset=$dataSets&language=$locale');
try { try {
final response = await http.get(url); final response = await http.get(url);
@ -43,7 +43,8 @@ class ApiService {
return { return {
'isChartData': isChartData, 'isChartData': isChartData,
'nonChartData': nonChartData, 'nonChartData': nonChartData,
'filterData': jsonData['filter_data'] 'filterData': jsonData['new_filter_data']
// 'filterData': jsonData['filter_data']
// 'originalChartsData': originalChartsData, // 'originalChartsData': originalChartsData,
// 'originalCardData': originalCardData, // 'originalCardData': originalCardData,
}; };

File diff suppressed because it is too large Load Diff

View File

@ -461,8 +461,16 @@ class LoginRoute extends HookConsumerWidget {
final continueAsGuestBtn = SizedBox( final continueAsGuestBtn = SizedBox(
width: double.infinity, width: double.infinity,
child: ElevatedButton( child: ElevatedButton(
onPressed: () => onPressed: () async {
context.go('/myhomepage'), 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}'), //context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
style: ButtonStyle( style: ButtonStyle(
shape: WidgetStatePropertyAll( shape: WidgetStatePropertyAll(

View File

@ -163,43 +163,21 @@
import 'dart:convert'; import 'dart:convert';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import '../../drawer_routes/custom_drawer_routes.dart'; import '../../drawer_routes/custom_drawer_routes.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
class MyHomePage extends StatefulWidget { class MyHomePage extends ConsumerStatefulWidget {
const MyHomePage({super.key}); const MyHomePage({super.key});
@override @override
State<MyHomePage> createState() => _MyHomePageState(); ConsumerState<MyHomePage> createState() => _MyHomePageState();
} }
void handleInfoCardClick(BuildContext context, String data, Color color) { class _MyHomePageState extends ConsumerState<MyHomePage> {
// Handle navigation and pass dynamic data
print(data);
final dataSets = data;
if (dataSets != null) {
// Perform navigation
context.go('/chartScreen/$dataSets');
} else {
// Show error if dataSet is null
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('No dataset available')),
);
}
// final dataSets = data;
// print(dataSets);
// if (dataSets == 'hotels') {
// context.go('/chartScreen/$dataSets');
// } else if (dataSets == 'divorces') {
// context.go('/chartScreen/$dataSets');
// } else if (dataSets == 'marriages') {
// context.go('/Chart/$dataSets');
// }
}
class _MyHomePageState extends State<MyHomePage> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
@ -215,14 +193,14 @@ class _MyHomePageState extends State<MyHomePage> {
} }
} }
class EconomyStatsWidget extends StatefulWidget { class EconomyStatsWidget extends ConsumerStatefulWidget {
const EconomyStatsWidget({super.key}); const EconomyStatsWidget({super.key});
@override @override
EconomyStatsState createState() => EconomyStatsState(); ConsumerState createState() => EconomyStatsState();
} }
class EconomyStatsState extends State<EconomyStatsWidget> { class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
List<dynamic> data = []; List<dynamic> data = [];
bool isLoading = true; bool isLoading = true;
@ -230,13 +208,22 @@ class EconomyStatsState extends State<EconomyStatsWidget> {
@override @override
void initState() { void initState() {
super.initState(); super.initState();
fetchData(); final locale = ref.read(localeProvider);
fetchData(locale?.languageCode ?? 'en');
} }
Future<void> fetchData() async { // @override
// void didChangeDependencies() {
// super.didChangeDependencies();
// // Access the provider here
// final locale = ref.watch(localeProvider);
// fetchData(locale); // Pass the locale to the fetchData method
// }
Future<void> fetchData(locale) async {
const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; const baseUrl = 'https://pb.venbait.in/api/getHomePageData';
try { try {
final response = await http.get(Uri.parse(baseUrl)); final response = await http.get(Uri.parse(baseUrl + '?language=$locale'));
if (response.statusCode == 200) { if (response.statusCode == 200) {
setState(() { setState(() {
data = json.decode(response.body); data = json.decode(response.body);
@ -283,6 +270,10 @@ class EconomyStatsState extends State<EconomyStatsWidget> {
} }
Widget build(BuildContext context) { Widget build(BuildContext context) {
ref.listen<Locale?>(localeProvider, (previous, next) {
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
fetchData(localeCode);
});
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
@ -386,7 +377,8 @@ class EconomyStatsState extends State<EconomyStatsWidget> {
children: _buildRows( children: _buildRows(
[tileData], [tileData],
borderColor, borderColor,
mainTopic['color_pattern']), mainTopic['color_pattern'],
mainTopic['main_topic']),
), ),
), ),
], ],
@ -452,8 +444,8 @@ class EconomyStatsState extends State<EconomyStatsWidget> {
// return rows; // return rows;
// } // }
List<Widget> _buildRows( List<Widget> _buildRows(List<Map<String, dynamic>> tileData, Color borderColor,
List<Map<String, dynamic>> tileData, Color borderColor, color_pattern) { String colorPattern, String mainTopic) {
// tileData.sort((a, b) => // tileData.sort((a, b) =>
// (a['data_set_list_order'] ?? 0).compareTo(b['data_set_list_order'] ?? 0),); // (a['data_set_list_order'] ?? 0).compareTo(b['data_set_list_order'] ?? 0),);
@ -479,8 +471,10 @@ List<Widget> _buildRows(
dataset: tile['data_set']!, dataset: tile['data_set']!,
bordercolor: borderColor, bordercolor: borderColor,
textcolor: borderColor, textcolor: borderColor,
colorPattern: colorPattern,
backgroundColor: backgroundColor:
Colors.white, // Set background color for InfoCard Colors.white, // Set background color for InfoCard
mainTopic: mainTopic,
onTap: () {}, onTap: () {},
), ),
); );
@ -529,10 +523,12 @@ class RoundedCornerContainer extends StatelessWidget {
class InfoCard extends StatelessWidget { class InfoCard extends StatelessWidget {
final String title; final String title;
final String mainTopic;
final String subtitle; final String subtitle;
final String value; final String value;
final String dataset; final String dataset;
final Color bordercolor; final Color bordercolor;
final String colorPattern;
final Color? textcolor; final Color? textcolor;
final VoidCallback onTap; final VoidCallback onTap;
final Color backgroundColor; final Color backgroundColor;
@ -544,9 +540,11 @@ class InfoCard extends StatelessWidget {
required this.value, required this.value,
required this.dataset, required this.dataset,
required this.bordercolor, required this.bordercolor,
required this.colorPattern,
this.textcolor, this.textcolor,
required this.onTap, required this.onTap,
required this.backgroundColor, required this.backgroundColor,
required this.mainTopic,
}) : super(key: key); }) : super(key: key);
@override @override
@ -554,11 +552,16 @@ class InfoCard extends StatelessWidget {
double myheight = MediaQuery.of(context).size.height; double myheight = MediaQuery.of(context).size.height;
double mywidth = MediaQuery.of(context).size.width; double mywidth = MediaQuery.of(context).size.width;
print("colorPatternInfo -$colorPattern $mainTopic");
final encodedMainTopic = Uri.encodeComponent(mainTopic);
final encodedTitle = Uri.encodeComponent(title);
final encodedKey = Uri.encodeQueryComponent('home');
return GestureDetector( return GestureDetector(
onTap: () { onTap: () {
// Call handleInfoCardClick and pass the title and color context.go(
handleInfoCardClick( '/chartScreen/$dataset?bgColor=$colorPattern&mainTopic=$encodedMainTopic&title=$encodedTitle&key=$encodedKey');
context, dataset, bordercolor); // Pass 'title' to the function
}, },
child: Container( child: Container(
height: myheight / 12, height: myheight / 12,

View File

@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:pocketbase/pocketbase.dart'; import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart'; import 'package:shared_preferences/shared_preferences.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart';
@ -57,6 +58,11 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
_checkUserId(); _checkUserId();
} }
Future<String> _getAppVersion() async {
PackageInfo packageInfo = await PackageInfo.fromPlatform();
return packageInfo.version; // Returns the app version
}
Future<String?> getUserId() async { Future<String?> getUserId() async {
final prefs = await SharedPreferences.getInstance(); final prefs = await SharedPreferences.getInstance();
return prefs.getString('userId'); // Retrieve the userId return prefs.getString('userId'); // Retrieve the userId
@ -183,98 +189,130 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
), ),
), ),
drawer: Drawer( drawer: Drawer(
child: ListView( child: Column(children: [
children: [ Expanded(
DrawerHeader( child: ListView(
child: Column( children: [
crossAxisAlignment: CrossAxisAlignment.stretch, DrawerHeader(
children: [ child: Column(
Row( crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
SizedBox( Row(
width: mywidth / 8,
child: Image(
image: AssetImage('assets/logos/fcsc.png'),
),
),
],
),
Divider(),
InkWell(
onTap: () => context.go('/editProfile'),
child: Row(
children: [ children: [
SizedBox( SizedBox(
width: mywidth / 8, width: mywidth / 8,
height: mywidth / 8, child: Image(
child: ClipOval( image: AssetImage('assets/logos/fcsc.png'),
child: _avatarUrl.isNotEmpty
? Image(
image: NetworkImage(_avatarUrl),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
)
: Image(
image: AssetImage(
'assets/edit_profile/profile.png',
),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
), ),
//child: Image(image: AssetImage('assets/edit_profile/profile.png'))
),
SizedBox(
width: mywidth / 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Text(userId ?? 'Loading user...'), // Display userId here
// Text('Mohammad@fcsc.com')
Text(userName ?? 'Loading...'),
Text(
userEmail ?? 'Loading...',
style: TextStyle(fontSize: 12),
),
],
), ),
], ],
), ),
), Divider(),
], InkWell(
onTap: () { if(userId != 'guest')context.go('/editProfile');},
child: Row(
children: [
SizedBox(
width: mywidth / 8,
height: mywidth / 8,
child: ClipOval(
child: _avatarUrl.isNotEmpty
? Image(
image: NetworkImage(_avatarUrl),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
)
: Image(
image: AssetImage(
'assets/edit_profile/profile.png',
),
fit: BoxFit.cover,
width: double.infinity,
height: double.infinity,
),
),
//child: Image(image: AssetImage('assets/edit_profile/profile.png'))
),
SizedBox(
width: mywidth / 20,
),
Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
// Text(userId ?? 'Loading user...'), // Display userId here
// Text('Mohammad@fcsc.com')
if(userId == "guest")...[ Text(userName ?? 'Guest User'),]
else...[Text(userName ?? 'Loading...'),
Text(
userEmail ?? 'Loading...',
style: TextStyle(fontSize: 12),
),]
],
),
],
),
),
],
),
), ),
), if(userId != 'guest')
ListTile(
leading: Icon(Icons.feedback),
// title: const Text('Feedback'),
title: Text(AppLocalizations.of(context)!.feedback_title),
onTap: () => context.go('/feedback'),
),
if (role == 'admin')
ListTile( ListTile(
leading: Icon(Icons.manage_accounts), leading: Icon(Icons.feedback),
title: Text('Manage User'), // title: const Text('Feedback'),
// title: Text( title: Text(AppLocalizations.of(context)!.feedback_title),
// AppLocalizations.of(context)!.manage_user, onTap: () => context.go('/feedback'),
// ),
onTap: () => context.go('/manageuser'),
), ),
ListTile( if (role == 'admin')
leading: Icon(Icons.book), ListTile(
title: const Text('User Guide'), leading: Icon(Icons.manage_accounts),
onTap: () => context.go('/user-guide'), // title: Text('Manage User'),
), title: Text(
ListTile( AppLocalizations.of(context)!.manage_user,
leading: Icon(Icons.logout), ),
title: const Text('Logout'), onTap: () => context.go('/manageuser'),
onTap: () => logout(), ),
), ListTile(
], leading: Icon(Icons.book),
title: const Text('User Guide'),
onTap: () => context.go('/user-guide'),
),
ListTile(
leading: Icon(Icons.logout),
title: const Text('Logout'),
onTap: () => logout(),
),
],
),
), ),
), Padding(
padding: const EdgeInsets.only(bottom: 16.0),
child: FutureBuilder<String>(
future: _getAppVersion(), // Function to get the app version
builder: (context, snapshot) {
if (snapshot.connectionState == ConnectionState.waiting) {
return Text(
'Loading version...',
style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.center,
);
} else if (snapshot.hasError) {
return Text(
'Error fetching version',
style: TextStyle(fontSize: 12, color: Colors.red),
textAlign: TextAlign.center,
);
} else {
return Text(
'Version ${snapshot.data}',
style: TextStyle(fontSize: 12, color: Colors.grey),
textAlign: TextAlign.center,
);
}
},
),
),
])),
bottomNavigationBar: BottomNavigationBar( bottomNavigationBar: BottomNavigationBar(
currentIndex: _getSelectedIndex(currentRoute), currentIndex: _getSelectedIndex(currentRoute),
onTap: (index) => _onItemTapped(context, index), onTap: (index) => _onItemTapped(context, index),

View File

@ -1,99 +1,100 @@
import 'package:flutter/material.dart'; // import 'package:flutter/material.dart';
import 'package:flutter_carousel_widget/flutter_carousel_widget.dart'; // import 'package:flutter_carousel_widget/flutter_carousel_widget.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; // import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; // import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:video_player/video_player.dart'; // import 'package:video_player/video_player.dart';
//
import 'package:uae_stat/domain/use_cases/language.dart'; // import 'package:uae_stat/domain/use_cases/language.dart';
import 'package:uae_stat/infrastructure/services/img_asset_paths/user_guide_asset_path.dart'; // import 'package:uae_stat/infrastructure/services/img_asset_paths/user_guide_asset_path.dart';
import 'package:uae_stat/presentation/components/space.dart'; // import 'package:uae_stat/presentation/components/space.dart';
import 'package:uae_stat/presentation/components/themed_app_bar.dart'; // import 'package:uae_stat/presentation/components/themed_app_bar.dart';
//
typedef _UserGuideType = ({String videoPath, String enDesc, String arDesc}); // typedef _UserGuideType = ({String videoPath, String enDesc, String arDesc});
//
class UserGuideRoute extends HookConsumerWidget { // class UserGuideRoute extends HookConsumerWidget {
const UserGuideRoute({super.key}); // const UserGuideRoute({super.key});
//
static const List<_UserGuideType> _data = [ // static const List<_UserGuideType> _data = [
( // (
videoPath: UserGuideAssetPath.toggleLanguage, // videoPath: UserGuideAssetPath.toggleLanguage,
enDesc: // enDesc:
'You can toggle between Arabic and English by click the toggle button.', // 'You can toggle between Arabic and English by click the toggle button.',
arDesc: // arDesc:
'يمكنك التبديل بين العربية والإنجليزية عن طريق النقر على زر التبديل.', // 'يمكنك التبديل بين العربية والإنجليزية عن طريق النقر على زر التبديل.',
), // ),
( // (
videoPath: UserGuideAssetPath.searchIndicators, // videoPath: UserGuideAssetPath.searchIndicators,
enDesc: // enDesc:
'You can browse indicators by category or use the search functionality', // 'You can browse indicators by category or use the search functionality',
arDesc: 'يمكنك تصفح المؤشرات حسب الفئة أو استخدام وظيفة البحث', // arDesc: 'يمكنك تصفح المؤشرات حسب الفئة أو استخدام وظيفة البحث',
), // ),
( // (
videoPath: UserGuideAssetPath.bookmarkIndicators, // videoPath: UserGuideAssetPath.bookmarkIndicators,
enDesc: // enDesc:
'You can bookmark indicators. You will be notified each time a bookmarked indicator is updated by email or mobile notifications.', // 'You can bookmark indicators. You will be notified each time a bookmarked indicator is updated by email or mobile notifications.',
arDesc: // arDesc:
'يمكنك وضع إشارة مرجعية على المؤشرات. سيتم إعلامك في كل مرة يتم فيها تحديث المؤشر المرجعي عن طريق البريد الإلكتروني أو إشعارات الهاتف المحمول.', // 'يمكنك وضع إشارة مرجعية على المؤشرات. سيتم إعلامك في كل مرة يتم فيها تحديث المؤشر المرجعي عن طريق البريد الإلكتروني أو إشعارات الهاتف المحمول.',
), // ),
]; // ];
//
@override // @override
Widget build(BuildContext context, WidgetRef ref) { // Widget build(BuildContext context, WidgetRef ref) {
final e = useState<_UserGuideType>(_data.first); // final e = useState<_UserGuideType>(_data.first);
final carouselOptions = CarouselOptions( // final carouselOptions
autoPlay: true, // // final carouselOptions = CarouselOptions(
clipBehavior: Clip.none, // // autoPlay: true,
onPageChanged: (index, reason) => e.value = _data[index], // // clipBehavior: Clip.none,
aspectRatio: 9 / 17, // // onPageChanged: (index, reason) => e.value = _data[index],
disableCenter: true, // // aspectRatio: 9 / 17,
enlargeCenterPage: true, // // disableCenter: true,
floatingIndicator: true, // // enlargeCenterPage: true,
autoPlayInterval: const Duration(seconds: 10), // // floatingIndicator: true,
); // // autoPlayInterval: const Duration(seconds: 10),
final bodyContent = Column( // // );
children: [ // final bodyContent = Column(
Expanded( // children: [
flex: 3, // Expanded(
child: FlutterCarousel( // flex: 3,
options: carouselOptions, // child: FlutterCarousel(
items: _data // options: carouselOptions,
.map( // items: _data
(e) => VideoPlayer( // .map(
VideoPlayerController.asset( // (e) => VideoPlayer(
e.videoPath, // VideoPlayerController.asset(
)..initialize(), // e.videoPath,
), // )..initialize(),
) // ),
.toList(), // )
), // .toList(),
), // ),
Expanded( // ),
child: SingleChildScrollView( // Expanded(
padding: const EdgeInsets.fromLTRB(36, 24, 36, 36), // child: SingleChildScrollView(
child: Text( // padding: const EdgeInsets.fromLTRB(36, 24, 36, 36),
context.translate(e.value.enDesc, e.value.arDesc), // child: Text(
), // context.translate(e.value.enDesc, e.value.arDesc),
), // ),
), // ),
98.verticalSpace, // ),
], // 98.verticalSpace,
); // ],
final body = Column( // );
children: [ // final body = Column(
ThemedAppBar( // children: [
titleText: context.translate( // ThemedAppBar(
'User Guide', // titleText: context.translate(
'دليل المستخدم', // 'User Guide',
), // 'دليل المستخدم',
), // ),
Expanded( // ),
child: bodyContent, // Expanded(
), // child: bodyContent,
], // ),
); // ],
return ColoredBox( // );
color: Colors.white, // return ColoredBox(
child: SafeArea(child: body), // color: Colors.white,
); // child: SafeArea(child: body),
} // );
} // }
// }