Charts Added
This commit is contained in:
parent
1a39a7c740
commit
5c5243d02e
@ -374,6 +374,7 @@ final GoRouter router = GoRouter(
|
||||
'0xFFFFFFFF'; // Default white
|
||||
final mainTopic = state.uri.queryParameters['mainTopic'] ?? '';
|
||||
final title = state.uri.queryParameters['title'] ?? '';
|
||||
final key = state.uri.queryParameters['key'] ?? '';
|
||||
|
||||
print('Router dataSets: $dataSets');
|
||||
print('Router bgColor: $bgColor');
|
||||
@ -386,6 +387,7 @@ final GoRouter router = GoRouter(
|
||||
bgColor: bgColor,
|
||||
mainTopic: mainTopic,
|
||||
title: title,
|
||||
keyParam: key,
|
||||
);
|
||||
},
|
||||
),
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.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/drawer_routes/custom_drawer_routes.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});
|
||||
|
||||
@override
|
||||
_UaenumberWidgetState createState() => _UaenumberWidgetState();
|
||||
ConsumerState<uaenumberWidget> createState() => _UaenumberWidgetState();
|
||||
}
|
||||
|
||||
class _UaenumberWidgetState extends State<uaenumberWidget> {
|
||||
class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
|
||||
@override
|
||||
List<dynamic> homePageData = [];
|
||||
bool isLoading = true;
|
||||
int? expandedIndex = 0;
|
||||
|
||||
@override
|
||||
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/getUAENumbersData';
|
||||
try {
|
||||
final response = await http.get(Uri.parse(baseUrl));
|
||||
final response = await http.get(Uri.parse(baseUrl + '?language=$locale'));
|
||||
if (response.statusCode == 200) {
|
||||
setState(() {
|
||||
homePageData = json.decode(response.body);
|
||||
@ -63,6 +68,10 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
|
||||
}
|
||||
|
||||
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 mywidth = MediaQuery.of(context).size.width;
|
||||
|
||||
@ -99,7 +108,12 @@ class _UaenumberWidgetState extends State<uaenumberWidget> {
|
||||
|
||||
return CustomExpandableTile(
|
||||
index: index,
|
||||
isExpanded: isFirstTile,
|
||||
isExpanded: expandedIndex == index, // Compare with expandedIndex
|
||||
onTap: (index) {
|
||||
setState(() {
|
||||
expandedIndex = (expandedIndex == index) ? null : index;
|
||||
});
|
||||
},
|
||||
title: mainTopic['main_topic'],
|
||||
titleBackgroundColor: backgroundColor,
|
||||
children: _buildSubTopics(mainTopic['sub_topics'] ?? [], mywidth,
|
||||
@ -280,6 +294,8 @@ class CustomExpandableTile extends StatefulWidget {
|
||||
final List<Widget> children;
|
||||
final int index;
|
||||
final bool isExpanded;
|
||||
final ValueChanged<int> onTap;
|
||||
|
||||
|
||||
const CustomExpandableTile({
|
||||
required this.title,
|
||||
@ -287,6 +303,8 @@ class CustomExpandableTile extends StatefulWidget {
|
||||
required this.children,
|
||||
required this.index,
|
||||
required this.isExpanded,
|
||||
required this.onTap,
|
||||
|
||||
});
|
||||
|
||||
@override
|
||||
@ -294,14 +312,12 @@ class CustomExpandableTile extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
||||
// bool isExpanded = false;
|
||||
late bool isExpanded;
|
||||
bool isExpanded = false;
|
||||
// late bool isExpanded;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
isExpanded =
|
||||
widget.isExpanded; // Initialize isExpanded based on widget's property
|
||||
super.initState(); // Initialize isExpanded based on widget's property
|
||||
}
|
||||
|
||||
@override
|
||||
@ -312,11 +328,8 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
||||
child: Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
setState(() {
|
||||
isExpanded = !isExpanded;
|
||||
});
|
||||
},
|
||||
onTap: () => widget.onTap(widget.index),
|
||||
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: widget.titleBackgroundColor,
|
||||
@ -335,7 +348,7 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
isExpanded
|
||||
widget.isExpanded
|
||||
? Icons.keyboard_arrow_up
|
||||
: Icons.keyboard_arrow_down,
|
||||
color: Colors.white,
|
||||
@ -350,8 +363,8 @@ class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
width: double.infinity,
|
||||
height: isExpanded ? myheight * 0.52 : 0,
|
||||
child: isExpanded
|
||||
height: widget.isExpanded ? myheight * 0.52 : 0,
|
||||
child: widget.isExpanded
|
||||
? SingleChildScrollView(
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
|
||||
@ -205,7 +205,31 @@ class _CreateNewPwState extends State<CreateNewPw> {
|
||||
padding: const EdgeInsets.all(24.0),
|
||||
child: Column(
|
||||
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),
|
||||
|
||||
Text(
|
||||
// "Create New Password",
|
||||
AppLocalizations.of(context)!.create_new_password,
|
||||
|
||||
@ -1,15 +1,20 @@
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.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/widgets/chart_widget.dart';
|
||||
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
|
||||
|
||||
import '../filters/search_filter_helper.dart';
|
||||
|
||||
class ChartScreen1 extends StatefulWidget {
|
||||
class ChartScreen1 extends ConsumerStatefulWidget {
|
||||
final String dataSets;
|
||||
final String bgColor;
|
||||
final String mainTopic;
|
||||
final String title;
|
||||
final String? keyParam; // Nullable String
|
||||
|
||||
const ChartScreen1({
|
||||
Key? key,
|
||||
@ -17,18 +22,20 @@ class ChartScreen1 extends StatefulWidget {
|
||||
required String this.bgColor,
|
||||
required this.mainTopic,
|
||||
required this.title,
|
||||
required this.keyParam,
|
||||
});
|
||||
@override
|
||||
_ChartScreen1State createState() => _ChartScreen1State();
|
||||
ConsumerState<ChartScreen1> createState() => _ChartScreen1State();
|
||||
}
|
||||
|
||||
class _ChartScreen1State extends State<ChartScreen1> {
|
||||
class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
List<Map<String, dynamic>> selectedFiltersStorage = [];
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final ApiService apiService = ApiService();
|
||||
bool isLoading = true;
|
||||
List<dynamic> isChartData = [];
|
||||
List<dynamic> nonChartData = [];
|
||||
List<dynamic> filterDataSet = [];
|
||||
List<dynamic> filterData = [];
|
||||
List<dynamic> chartsData = [];
|
||||
List<dynamic> tabFilteredChartData = [];
|
||||
@ -50,7 +57,8 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
final String bgColor = widget.bgColor;
|
||||
print(' bgColor $bgColor');
|
||||
// fetchChartData(widget.dataSets);
|
||||
fetchChartData(widget.dataSets).then((_) {
|
||||
final locale = ref.read(localeProvider);
|
||||
fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) {
|
||||
if (_tabsData.isNotEmpty) {
|
||||
// Call onTabSelected for the first tab
|
||||
onTabSelected(_tabsData[0]['id']);
|
||||
@ -74,6 +82,7 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
});
|
||||
_scrollToIndex(_activeTabIndex);
|
||||
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) {
|
||||
// Group data by 'kpi'
|
||||
Map<String, List<Map<String, dynamic>>> groupedData = {};
|
||||
|
||||
for (var chart in chartsData) {
|
||||
String kpi = chart['kpi'] ?? '';
|
||||
if (!groupedData.containsKey(kpi)) {
|
||||
@ -98,30 +137,52 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
groupedData[kpi]!.add(chart);
|
||||
}
|
||||
|
||||
// Format 'kpi' values for _tabs
|
||||
List<Map<String, String>> _tabs = groupedData.keys.map((kpi) {
|
||||
String name = kpi
|
||||
// Format 'kpi' values for _tabs with tab_heading
|
||||
List<Map<String, String>> _tabs = groupedData.entries.map((entry) {
|
||||
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
|
||||
.map(
|
||||
(word) => word[0].toUpperCase() + word.substring(1)) // Capitalize
|
||||
.map((word) => word.isNotEmpty
|
||||
? word[0].toUpperCase() + word.substring(1)
|
||||
: '') // Capitalize
|
||||
.join(' '); // Join words with space
|
||||
|
||||
return {'id': kpi, 'name': name};
|
||||
return {'id': kpi, 'name': tabHeading};
|
||||
}).toList();
|
||||
|
||||
print('Grouped Data: $groupedData');
|
||||
print('Tabs: $_tabs');
|
||||
|
||||
setState(() {
|
||||
_tabsData = _tabs;
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> fetchChartData(String dataSets) async {
|
||||
var data = await apiService.fetchChartData(dataSets);
|
||||
Future<void> fetchChartData(String dataSets, locale) async {
|
||||
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(() {
|
||||
isChartData = data['isChartData'] ?? [];
|
||||
nonChartData = data['nonChartData'] ?? [];
|
||||
filterData = data['filterData'] ?? [];
|
||||
// filterData = data['filterData'] ?? [];
|
||||
|
||||
originalChartsData = List.from(isChartData); // Store original data
|
||||
originalCardData = List.from(nonChartData);
|
||||
@ -133,17 +194,19 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
|
||||
print('chartsData :- $chartsData');
|
||||
print('cardData :- $cardData');
|
||||
print('filterData :- $filterData');
|
||||
// print('filterData :- $filterData');
|
||||
isLoading = false;
|
||||
});
|
||||
print(chartsData);
|
||||
print(cardData);
|
||||
print('chartsData -$chartsData');
|
||||
print('cardData -$cardData');
|
||||
}
|
||||
|
||||
void applyFilters(BuildContext context, List filters, List data,
|
||||
List dataCard, List selectedFilters) {
|
||||
print("Selected Filters before applying: $selectedFilters");
|
||||
// Check if all filter_data is empty
|
||||
print("applyFilters called");
|
||||
print("Selected ApplyFilters: $selectedFilters");
|
||||
print("Selected data: $data");
|
||||
|
||||
if (selectedFilters.every((filter) => filter['filter_data'].isEmpty)) {
|
||||
setState(() {
|
||||
chartsData =
|
||||
@ -157,8 +220,9 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
|
||||
// Loop through each chart data in the `data` list
|
||||
List filteredData = [];
|
||||
Set<String> addedChartIds = {}; // Track unique chart identifiers
|
||||
for (var chart in data) {
|
||||
// Extract response data for filtering
|
||||
final groupBy = chart['group_by'];
|
||||
List response = chart['response'] ?? [];
|
||||
|
||||
// Filter the response based on selected filters
|
||||
@ -171,20 +235,31 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
final filterValues = filter['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();
|
||||
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();
|
||||
|
||||
// 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({
|
||||
...chart, // Include all other properties of the chart object
|
||||
'response': chartFilteredData, // Only include filtered response data
|
||||
...chart,
|
||||
'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
|
||||
setState(() {
|
||||
chartsData = filteredData;
|
||||
cardData = filteredCardData;
|
||||
cardData = filteredCardData; // Adjust this part as needed
|
||||
});
|
||||
|
||||
print("Filtered Data: $filteredData");
|
||||
@ -271,7 +346,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
'Filters',
|
||||
context.translate(
|
||||
'Filters',
|
||||
'المرشحات',
|
||||
),
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
@ -357,7 +435,12 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
setState(() {});
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('OK'),
|
||||
child: Text(
|
||||
context.translate(
|
||||
'OK',
|
||||
'نعم',
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
@ -428,7 +511,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
selectedFiltersStorage.clear();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
child: Text('Clear'),
|
||||
child: Text(context.translate(
|
||||
'Clear',
|
||||
'واضح',
|
||||
)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.grey,
|
||||
),
|
||||
@ -447,7 +533,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
// Save the selected filters to storage after applying
|
||||
selectedFiltersStorage = List.from(selectedFilters);
|
||||
},
|
||||
child: Text('Apply Filter'),
|
||||
child: Text(context.translate(
|
||||
'Apply Filter',
|
||||
'تطبيق الفلتر',
|
||||
)),
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.blue,
|
||||
),
|
||||
@ -466,6 +555,28 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
void onTabSelected(String tabId) {
|
||||
print('Selected Tab: $tabId');
|
||||
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(() {
|
||||
chartsData = originalChartsData;
|
||||
cardData = originalCardData;
|
||||
@ -507,22 +618,38 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
// For example, you can update the chart data or display the results
|
||||
}
|
||||
|
||||
double calculateAspectRatio(int itemCount) {
|
||||
// Modify the logic based on your layout requirements
|
||||
if (itemCount <= 2) {
|
||||
return 190.5 / 180;
|
||||
} else if (itemCount == 3) {
|
||||
return 180.0 / 300;
|
||||
} else if (itemCount == 4) {
|
||||
return 190.5 / 180;
|
||||
// double calculateAspectRatio(int itemCount) {
|
||||
// // Modify the logic based on your layout requirements
|
||||
// if (itemCount <= 2) {
|
||||
// return 190.5 / 180;
|
||||
// } else if (itemCount == 3) {
|
||||
// return 180.0 / 250;
|
||||
// } else if (itemCount == 4) {
|
||||
// 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 {
|
||||
return 180.0 / 260; // Default for more items
|
||||
// return 190.5 / 180;
|
||||
return crossAxisCount == 2 ? 1.5 : 0.9;
|
||||
// Shorter Content
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
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 mywidth = MediaQuery.of(context).size.width;
|
||||
final color =
|
||||
@ -536,11 +663,18 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
leading: IconButton(
|
||||
icon: Icon(Icons.arrow_back_ios_new, color: Colors.white),
|
||||
onPressed: () {
|
||||
context.go('/uaenumbers');
|
||||
if (widget.keyParam == 'home') {
|
||||
context.go('/myhomepage');
|
||||
} else {
|
||||
context.go('/uaenumbers');
|
||||
}
|
||||
},
|
||||
),
|
||||
title: Text(
|
||||
'UAE Numbers',
|
||||
context.translate(
|
||||
'UAE Numbers',
|
||||
'أرقام الإمارات',
|
||||
),
|
||||
style: TextStyle(color: Colors.white),
|
||||
),
|
||||
),
|
||||
@ -609,7 +743,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'Bookmark',
|
||||
context.translate(
|
||||
'Bookmark',
|
||||
'إشارة مرجعية',
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
@ -624,7 +761,10 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'Share',
|
||||
context.translate(
|
||||
'Share',
|
||||
'يشارك',
|
||||
),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white,
|
||||
@ -653,33 +793,37 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
// Left arrow button
|
||||
_buildArrowButton(
|
||||
onPressed: _activeTabIndex > 0 ? _scrollLeft : null,
|
||||
icon: Icons.arrow_back_ios_new,
|
||||
),
|
||||
if (_tabsData.length > 1)
|
||||
_buildArrowButton(
|
||||
onPressed:
|
||||
_activeTabIndex > 0 ? _scrollLeft : null,
|
||||
icon: Icons.arrow_back_ios_new,
|
||||
),
|
||||
// Tabs with horizontal scroll
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
controller: _scrollController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children:
|
||||
List.generate(_tabsData.length, (index) {
|
||||
return _buildTab(
|
||||
_tabsData[index],
|
||||
isActive: index == _activeTabIndex,
|
||||
);
|
||||
}),
|
||||
if (_tabsData.length > 1)
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
controller: _scrollController,
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
children:
|
||||
List.generate(_tabsData.length, (index) {
|
||||
return _buildTab(
|
||||
_tabsData[index],
|
||||
isActive: index == _activeTabIndex,
|
||||
);
|
||||
}),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Right arrow button
|
||||
_buildArrowButton(
|
||||
onPressed: _activeTabIndex < _tabsData.length - 1
|
||||
? _scrollRight
|
||||
: null,
|
||||
icon: Icons.arrow_forward_ios,
|
||||
),
|
||||
if (_tabsData.length > 1)
|
||||
_buildArrowButton(
|
||||
onPressed: _activeTabIndex < _tabsData.length - 1
|
||||
? _scrollRight
|
||||
: null,
|
||||
icon: Icons.arrow_forward_ios,
|
||||
),
|
||||
],
|
||||
),
|
||||
// Expanded(
|
||||
@ -699,25 +843,32 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
gridDelegate:
|
||||
SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: cardData.length == 2
|
||||
? 2
|
||||
: cardData.length == 3
|
||||
? 3
|
||||
: cardData.length == 4
|
||||
? 2
|
||||
: 3, // Default to 3 if more than 4 items // 2 cards per row
|
||||
crossAxisSpacing: 2,
|
||||
mainAxisSpacing: 5,
|
||||
childAspectRatio:
|
||||
calculateAspectRatio(cardData.length)),
|
||||
crossAxisCount: cardData.length == 2
|
||||
? 2
|
||||
: cardData.length == 3
|
||||
? 3
|
||||
: cardData.length == 4
|
||||
? 2
|
||||
: 3, // Default to 3 if more than 4 items // 2 cards per row
|
||||
crossAxisSpacing: 2,
|
||||
mainAxisSpacing: 5,
|
||||
childAspectRatio:
|
||||
calculateAspectRatio(cardData.length, cardData),
|
||||
),
|
||||
itemBuilder: (context, index) {
|
||||
final item = cardData[index];
|
||||
print('item item item $item');
|
||||
final chart_type = item['chart_type'];
|
||||
final chart_heading = item['chart_heading'];
|
||||
final card_logo = item['card_logo'];
|
||||
final data = apiService.processNonChartData(item);
|
||||
print('processNonChartData');
|
||||
|
||||
double cardHeight = (chart_type == 'totals' ||
|
||||
chart_type == 'averages')
|
||||
? 180.0
|
||||
: 130.0;
|
||||
|
||||
if (chart_type == 'total') {
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(10),
|
||||
@ -725,21 +876,41 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
borderRadius: BorderRadius.circular(12),
|
||||
),
|
||||
elevation: 4,
|
||||
child: Padding(
|
||||
child: Container(
|
||||
height: cardHeight,
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize
|
||||
.min, // Adjust card height based on content
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.public,
|
||||
color: Color(0xFF90B0D5), size: 30),
|
||||
// const Icon(Icons.public,
|
||||
// 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),
|
||||
Text(
|
||||
'${chart_heading ?? 'NA'}',
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.black87,
|
||||
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(
|
||||
@ -747,13 +918,19 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
style: const TextStyle(
|
||||
fontSize: 11, color: Colors.grey),
|
||||
),
|
||||
Text(
|
||||
apiService.formatAmount(
|
||||
data['lastYearValue']),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
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: 26,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: Color(0xFF90B0D5),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
@ -764,19 +941,27 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
1, // Divider line thickness
|
||||
),
|
||||
),
|
||||
Text(
|
||||
apiService.formatAmount(
|
||||
data['secondLastYearValue']),
|
||||
style: const TextStyle(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFFD83731),
|
||||
Flexible(
|
||||
fit: FlexFit.loose,
|
||||
child: FittedBox(
|
||||
fit: BoxFit.contain,
|
||||
child: Text(
|
||||
apiService.formatAmount(
|
||||
data['secondLastYearValue']),
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Color(0xFFD83731),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'(${data['secondLastYear'] ?? 'NA'})',
|
||||
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),
|
||||
),
|
||||
elevation: 4,
|
||||
child: Padding(
|
||||
child: Container(
|
||||
height: cardHeight,
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
const Icon(Icons.analytics,
|
||||
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: 5),
|
||||
Text(
|
||||
'${chart_heading ?? 'NA'}',
|
||||
@ -811,12 +1007,133 @@ class _ChartScreen1State extends State<ChartScreen1> {
|
||||
style: const TextStyle(
|
||||
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(
|
||||
'${data['roundedAverage'] ?? 'NA'}',
|
||||
'(${data['lastYear'] ?? 'NA'})',
|
||||
style: const TextStyle(
|
||||
fontSize: 22,
|
||||
fontWeight: FontWeight.w900,
|
||||
color: Color(0xFF90B0D5),
|
||||
fontSize: 11, color: Colors.grey),
|
||||
),
|
||||
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),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
@ -13,13 +13,13 @@ class ChartData {
|
||||
class ApiService {
|
||||
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> nonChartData = [];
|
||||
List<dynamic> originalChartsData = [];
|
||||
List<dynamic> originalCardData = [];
|
||||
|
||||
final url = Uri.parse('$baseUrl?dataset=$dataSets');
|
||||
final url = Uri.parse('$baseUrl?dataset=$dataSets&language=$locale');
|
||||
|
||||
try {
|
||||
final response = await http.get(url);
|
||||
@ -43,7 +43,8 @@ class ApiService {
|
||||
return {
|
||||
'isChartData': isChartData,
|
||||
'nonChartData': nonChartData,
|
||||
'filterData': jsonData['filter_data']
|
||||
'filterData': jsonData['new_filter_data']
|
||||
// 'filterData': jsonData['filter_data']
|
||||
// 'originalChartsData': originalChartsData,
|
||||
// 'originalCardData': originalCardData,
|
||||
};
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@ -461,8 +461,16 @@ class LoginRoute extends HookConsumerWidget {
|
||||
final continueAsGuestBtn = SizedBox(
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () =>
|
||||
context.go('/myhomepage'),
|
||||
onPressed: () async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
prefs.clear();
|
||||
final userId = 'guest';
|
||||
if (userId.isNotEmpty) {
|
||||
await saveUserId(userId);
|
||||
}
|
||||
context.go('/myhomepage');
|
||||
//context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
|
||||
},
|
||||
//context.go('/${context.language}/${BottomNavBarItem.home.routePath}'),
|
||||
style: ButtonStyle(
|
||||
shape: WidgetStatePropertyAll(
|
||||
|
||||
@ -163,43 +163,21 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.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 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
|
||||
class MyHomePage extends StatefulWidget {
|
||||
class MyHomePage extends ConsumerStatefulWidget {
|
||||
const MyHomePage({super.key});
|
||||
|
||||
@override
|
||||
State<MyHomePage> createState() => _MyHomePageState();
|
||||
ConsumerState<MyHomePage> createState() => _MyHomePageState();
|
||||
}
|
||||
|
||||
void handleInfoCardClick(BuildContext context, String data, Color color) {
|
||||
// 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> {
|
||||
class _MyHomePageState extends ConsumerState<MyHomePage> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
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});
|
||||
|
||||
@override
|
||||
EconomyStatsState createState() => EconomyStatsState();
|
||||
ConsumerState createState() => EconomyStatsState();
|
||||
}
|
||||
|
||||
class EconomyStatsState extends State<EconomyStatsWidget> {
|
||||
class EconomyStatsState extends ConsumerState<EconomyStatsWidget> {
|
||||
List<dynamic> data = [];
|
||||
|
||||
bool isLoading = true;
|
||||
@ -230,13 +208,22 @@ class EconomyStatsState extends State<EconomyStatsWidget> {
|
||||
@override
|
||||
void 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';
|
||||
try {
|
||||
final response = await http.get(Uri.parse(baseUrl));
|
||||
final response = await http.get(Uri.parse(baseUrl + '?language=$locale'));
|
||||
if (response.statusCode == 200) {
|
||||
setState(() {
|
||||
data = json.decode(response.body);
|
||||
@ -283,6 +270,10 @@ class EconomyStatsState extends State<EconomyStatsWidget> {
|
||||
}
|
||||
|
||||
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 mywidth = MediaQuery.of(context).size.width;
|
||||
|
||||
@ -386,7 +377,8 @@ class EconomyStatsState extends State<EconomyStatsWidget> {
|
||||
children: _buildRows(
|
||||
[tileData],
|
||||
borderColor,
|
||||
mainTopic['color_pattern']),
|
||||
mainTopic['color_pattern'],
|
||||
mainTopic['main_topic']),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -452,8 +444,8 @@ class EconomyStatsState extends State<EconomyStatsWidget> {
|
||||
// return rows;
|
||||
// }
|
||||
|
||||
List<Widget> _buildRows(
|
||||
List<Map<String, dynamic>> tileData, Color borderColor, color_pattern) {
|
||||
List<Widget> _buildRows(List<Map<String, dynamic>> tileData, Color borderColor,
|
||||
String colorPattern, String mainTopic) {
|
||||
// tileData.sort((a, b) =>
|
||||
// (a['data_set_list_order'] ?? 0).compareTo(b['data_set_list_order'] ?? 0),);
|
||||
|
||||
@ -479,8 +471,10 @@ List<Widget> _buildRows(
|
||||
dataset: tile['data_set']!,
|
||||
bordercolor: borderColor,
|
||||
textcolor: borderColor,
|
||||
colorPattern: colorPattern,
|
||||
backgroundColor:
|
||||
Colors.white, // Set background color for InfoCard
|
||||
mainTopic: mainTopic,
|
||||
onTap: () {},
|
||||
),
|
||||
);
|
||||
@ -529,10 +523,12 @@ class RoundedCornerContainer extends StatelessWidget {
|
||||
|
||||
class InfoCard extends StatelessWidget {
|
||||
final String title;
|
||||
final String mainTopic;
|
||||
final String subtitle;
|
||||
final String value;
|
||||
final String dataset;
|
||||
final Color bordercolor;
|
||||
final String colorPattern;
|
||||
final Color? textcolor;
|
||||
final VoidCallback onTap;
|
||||
final Color backgroundColor;
|
||||
@ -544,9 +540,11 @@ class InfoCard extends StatelessWidget {
|
||||
required this.value,
|
||||
required this.dataset,
|
||||
required this.bordercolor,
|
||||
required this.colorPattern,
|
||||
this.textcolor,
|
||||
required this.onTap,
|
||||
required this.backgroundColor,
|
||||
required this.mainTopic,
|
||||
}) : super(key: key);
|
||||
|
||||
@override
|
||||
@ -554,11 +552,16 @@ class InfoCard extends StatelessWidget {
|
||||
double myheight = MediaQuery.of(context).size.height;
|
||||
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(
|
||||
onTap: () {
|
||||
// Call handleInfoCardClick and pass the title and color
|
||||
handleInfoCardClick(
|
||||
context, dataset, bordercolor); // Pass 'title' to the function
|
||||
context.go(
|
||||
'/chartScreen/$dataset?bgColor=$colorPattern&mainTopic=$encodedMainTopic&title=$encodedTitle&key=$encodedKey');
|
||||
},
|
||||
child: Container(
|
||||
height: myheight / 12,
|
||||
|
||||
@ -5,6 +5,7 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:package_info_plus/package_info_plus.dart';
|
||||
import 'package:pocketbase/pocketbase.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
@ -57,6 +58,11 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
_checkUserId();
|
||||
}
|
||||
|
||||
Future<String> _getAppVersion() async {
|
||||
PackageInfo packageInfo = await PackageInfo.fromPlatform();
|
||||
return packageInfo.version; // Returns the app version
|
||||
}
|
||||
|
||||
Future<String?> getUserId() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
return prefs.getString('userId'); // Retrieve the userId
|
||||
@ -183,98 +189,130 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
),
|
||||
),
|
||||
drawer: Drawer(
|
||||
child: ListView(
|
||||
children: [
|
||||
DrawerHeader(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Row(
|
||||
children: [
|
||||
SizedBox(
|
||||
width: mywidth / 8,
|
||||
child: Image(
|
||||
image: AssetImage('assets/logos/fcsc.png'),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Divider(),
|
||||
InkWell(
|
||||
onTap: () => context.go('/editProfile'),
|
||||
child: Row(
|
||||
child: Column(children: [
|
||||
Expanded(
|
||||
child: ListView(
|
||||
children: [
|
||||
DrawerHeader(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
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/logos/fcsc.png'),
|
||||
),
|
||||
//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),
|
||||
),]
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.feedback),
|
||||
// title: const Text('Feedback'),
|
||||
title: Text(AppLocalizations.of(context)!.feedback_title),
|
||||
onTap: () => context.go('/feedback'),
|
||||
),
|
||||
if (role == 'admin')
|
||||
if(userId != 'guest')
|
||||
ListTile(
|
||||
leading: Icon(Icons.manage_accounts),
|
||||
title: Text('Manage User'),
|
||||
// title: Text(
|
||||
// AppLocalizations.of(context)!.manage_user,
|
||||
// ),
|
||||
onTap: () => context.go('/manageuser'),
|
||||
leading: Icon(Icons.feedback),
|
||||
// title: const Text('Feedback'),
|
||||
title: Text(AppLocalizations.of(context)!.feedback_title),
|
||||
onTap: () => context.go('/feedback'),
|
||||
),
|
||||
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(),
|
||||
),
|
||||
],
|
||||
if (role == 'admin')
|
||||
ListTile(
|
||||
leading: Icon(Icons.manage_accounts),
|
||||
// title: Text('Manage User'),
|
||||
title: Text(
|
||||
AppLocalizations.of(context)!.manage_user,
|
||||
),
|
||||
onTap: () => context.go('/manageuser'),
|
||||
),
|
||||
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(
|
||||
currentIndex: _getSelectedIndex(currentRoute),
|
||||
onTap: (index) => _onItemTapped(context, index),
|
||||
|
||||
@ -1,99 +1,100 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_carousel_widget/flutter_carousel_widget.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:video_player/video_player.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/presentation/components/space.dart';
|
||||
import 'package:uae_stat/presentation/components/themed_app_bar.dart';
|
||||
|
||||
typedef _UserGuideType = ({String videoPath, String enDesc, String arDesc});
|
||||
|
||||
class UserGuideRoute extends HookConsumerWidget {
|
||||
const UserGuideRoute({super.key});
|
||||
|
||||
static const List<_UserGuideType> _data = [
|
||||
(
|
||||
videoPath: UserGuideAssetPath.toggleLanguage,
|
||||
enDesc:
|
||||
'You can toggle between Arabic and English by click the toggle button.',
|
||||
arDesc:
|
||||
'يمكنك التبديل بين العربية والإنجليزية عن طريق النقر على زر التبديل.',
|
||||
),
|
||||
(
|
||||
videoPath: UserGuideAssetPath.searchIndicators,
|
||||
enDesc:
|
||||
'You can browse indicators by category or use the search functionality',
|
||||
arDesc: 'يمكنك تصفح المؤشرات حسب الفئة أو استخدام وظيفة البحث',
|
||||
),
|
||||
(
|
||||
videoPath: UserGuideAssetPath.bookmarkIndicators,
|
||||
enDesc:
|
||||
'You can bookmark indicators. You will be notified each time a bookmarked indicator is updated by email or mobile notifications.',
|
||||
arDesc:
|
||||
'يمكنك وضع إشارة مرجعية على المؤشرات. سيتم إعلامك في كل مرة يتم فيها تحديث المؤشر المرجعي عن طريق البريد الإلكتروني أو إشعارات الهاتف المحمول.',
|
||||
),
|
||||
];
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final e = useState<_UserGuideType>(_data.first);
|
||||
final carouselOptions = CarouselOptions(
|
||||
autoPlay: true,
|
||||
clipBehavior: Clip.none,
|
||||
onPageChanged: (index, reason) => e.value = _data[index],
|
||||
aspectRatio: 9 / 17,
|
||||
disableCenter: true,
|
||||
enlargeCenterPage: true,
|
||||
floatingIndicator: true,
|
||||
autoPlayInterval: const Duration(seconds: 10),
|
||||
);
|
||||
final bodyContent = Column(
|
||||
children: [
|
||||
Expanded(
|
||||
flex: 3,
|
||||
child: FlutterCarousel(
|
||||
options: carouselOptions,
|
||||
items: _data
|
||||
.map(
|
||||
(e) => VideoPlayer(
|
||||
VideoPlayerController.asset(
|
||||
e.videoPath,
|
||||
)..initialize(),
|
||||
),
|
||||
)
|
||||
.toList(),
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
padding: const EdgeInsets.fromLTRB(36, 24, 36, 36),
|
||||
child: Text(
|
||||
context.translate(e.value.enDesc, e.value.arDesc),
|
||||
),
|
||||
),
|
||||
),
|
||||
98.verticalSpace,
|
||||
],
|
||||
);
|
||||
final body = Column(
|
||||
children: [
|
||||
ThemedAppBar(
|
||||
titleText: context.translate(
|
||||
'User Guide',
|
||||
'دليل المستخدم',
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: bodyContent,
|
||||
),
|
||||
],
|
||||
);
|
||||
return ColoredBox(
|
||||
color: Colors.white,
|
||||
child: SafeArea(child: body),
|
||||
);
|
||||
}
|
||||
}
|
||||
// import 'package:flutter/material.dart';
|
||||
// import 'package:flutter_carousel_widget/flutter_carousel_widget.dart';
|
||||
// import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
// import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
// import 'package:video_player/video_player.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/presentation/components/space.dart';
|
||||
// import 'package:uae_stat/presentation/components/themed_app_bar.dart';
|
||||
//
|
||||
// typedef _UserGuideType = ({String videoPath, String enDesc, String arDesc});
|
||||
//
|
||||
// class UserGuideRoute extends HookConsumerWidget {
|
||||
// const UserGuideRoute({super.key});
|
||||
//
|
||||
// static const List<_UserGuideType> _data = [
|
||||
// (
|
||||
// videoPath: UserGuideAssetPath.toggleLanguage,
|
||||
// enDesc:
|
||||
// 'You can toggle between Arabic and English by click the toggle button.',
|
||||
// arDesc:
|
||||
// 'يمكنك التبديل بين العربية والإنجليزية عن طريق النقر على زر التبديل.',
|
||||
// ),
|
||||
// (
|
||||
// videoPath: UserGuideAssetPath.searchIndicators,
|
||||
// enDesc:
|
||||
// 'You can browse indicators by category or use the search functionality',
|
||||
// arDesc: 'يمكنك تصفح المؤشرات حسب الفئة أو استخدام وظيفة البحث',
|
||||
// ),
|
||||
// (
|
||||
// videoPath: UserGuideAssetPath.bookmarkIndicators,
|
||||
// enDesc:
|
||||
// 'You can bookmark indicators. You will be notified each time a bookmarked indicator is updated by email or mobile notifications.',
|
||||
// arDesc:
|
||||
// 'يمكنك وضع إشارة مرجعية على المؤشرات. سيتم إعلامك في كل مرة يتم فيها تحديث المؤشر المرجعي عن طريق البريد الإلكتروني أو إشعارات الهاتف المحمول.',
|
||||
// ),
|
||||
// ];
|
||||
//
|
||||
// @override
|
||||
// Widget build(BuildContext context, WidgetRef ref) {
|
||||
// final e = useState<_UserGuideType>(_data.first);
|
||||
// final carouselOptions
|
||||
// // final carouselOptions = CarouselOptions(
|
||||
// // autoPlay: true,
|
||||
// // clipBehavior: Clip.none,
|
||||
// // onPageChanged: (index, reason) => e.value = _data[index],
|
||||
// // aspectRatio: 9 / 17,
|
||||
// // disableCenter: true,
|
||||
// // enlargeCenterPage: true,
|
||||
// // floatingIndicator: true,
|
||||
// // autoPlayInterval: const Duration(seconds: 10),
|
||||
// // );
|
||||
// final bodyContent = Column(
|
||||
// children: [
|
||||
// Expanded(
|
||||
// flex: 3,
|
||||
// child: FlutterCarousel(
|
||||
// options: carouselOptions,
|
||||
// items: _data
|
||||
// .map(
|
||||
// (e) => VideoPlayer(
|
||||
// VideoPlayerController.asset(
|
||||
// e.videoPath,
|
||||
// )..initialize(),
|
||||
// ),
|
||||
// )
|
||||
// .toList(),
|
||||
// ),
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: SingleChildScrollView(
|
||||
// padding: const EdgeInsets.fromLTRB(36, 24, 36, 36),
|
||||
// child: Text(
|
||||
// context.translate(e.value.enDesc, e.value.arDesc),
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
// 98.verticalSpace,
|
||||
// ],
|
||||
// );
|
||||
// final body = Column(
|
||||
// children: [
|
||||
// ThemedAppBar(
|
||||
// titleText: context.translate(
|
||||
// 'User Guide',
|
||||
// 'دليل المستخدم',
|
||||
// ),
|
||||
// ),
|
||||
// Expanded(
|
||||
// child: bodyContent,
|
||||
// ),
|
||||
// ],
|
||||
// );
|
||||
// return ColoredBox(
|
||||
// color: Colors.white,
|
||||
// child: SafeArea(child: body),
|
||||
// );
|
||||
// }
|
||||
// }
|
||||
|
||||
Loading…
Reference in New Issue
Block a user