From d7a1b5aa385966d8d6f7f57e00cdf73d079fc6c7 Mon Sep 17 00:00:00 2001 From: venbaittech Date: Fri, 28 Feb 2025 09:01:52 +0530 Subject: [PATCH] chart api changes and dev pocketbase url --- android/app/build.gradle | 4 +- lib/config/api_config.dart | 3 + lib/config/my_router.dart | 26 + .../services/pocketbase_service.dart | 4 +- lib/l10n/intl_ar.arb | 1 + lib/l10n/intl_en.arb | 2 +- lib/main.dart | 12 + .../UAE_Numbers/uae_numbers.dart | 4 +- .../auth_verification/changepassword.dart | 7 +- .../auth_verification/confirm_password.dart | 3 +- .../auth_verification/create_new_pw.dart | 3 +- .../auth_verification/otp_verification.dart | 3 +- .../auth_verification/registration.dart | 3 +- .../Screens/charts/screens/chart_screen.dart | 613 ++++-------------- .../Screens/charts/services/api_service.dart | 42 +- .../Screens/charts/widgets/chart_widget.dart | 181 ++++-- lib/presentation/Screens/profilepage.dart | 3 +- .../routes/auth_routes/login_route.dart | 7 +- .../tab_routes/home_route.dart | 8 +- .../drawer_routes/Drawer Items/bookmark.dart | 7 +- .../Drawer Items/edit_profile.dart | 5 +- .../drawer_routes/Drawer Items/feedback.dart | 3 +- .../Drawer Items/manage_users.dart | 3 +- .../notification/notification.dart | 3 +- .../drawer_routes/custom_drawer_routes.dart | 8 +- .../routes/drawer_routes/feedback_route.dart | 3 +- pubspec.yaml | 2 +- 27 files changed, 386 insertions(+), 577 deletions(-) create mode 100644 lib/config/api_config.dart diff --git a/android/app/build.gradle b/android/app/build.gradle index a74f4048..64443c26 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) { def flutterVersionCode = localProperties.getProperty("flutter.versionCode") if (flutterVersionCode == null) { - flutterVersionCode = "27" + flutterVersionCode = "28" } def flutterVersionName = localProperties.getProperty("flutter.versionName") if (flutterVersionName == null) { - flutterVersionName = "1.0.26" + flutterVersionName = "1.0.27" } def keystorePropertiesFile = rootProject.file("key.properties") diff --git a/lib/config/api_config.dart b/lib/config/api_config.dart new file mode 100644 index 00000000..07b7c7f4 --- /dev/null +++ b/lib/config/api_config.dart @@ -0,0 +1,3 @@ +// api_config.dart +// const String apiUrl = 'http://192.168.1.26:8090'; +const String apiUrl = 'https://pbdev.venbait.in/'; diff --git a/lib/config/my_router.dart b/lib/config/my_router.dart index 1130fe03..00f2c6a0 100644 --- a/lib/config/my_router.dart +++ b/lib/config/my_router.dart @@ -292,6 +292,8 @@ // return router; // } +import 'dart:convert'; + import 'package:flutter/material.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:go_router/go_router.dart'; @@ -414,11 +416,33 @@ final GoRouter router = GoRouter( final mainTopic = state.uri.queryParameters['mainTopic'] ?? ''; final title = state.uri.queryParameters['title'] ?? ''; final key = state.uri.queryParameters['key'] ?? ''; + final kpi = state.uri.queryParameters['kpi'] ?? ''; // Get kpi + + // Parse filter_data as a JSON list + // Parse filter_data as a JSON list + List> filterData = []; + + if (state.uri.queryParameters.containsKey('filter_data') && + state.uri.queryParameters['filter_data']!.isNotEmpty) { + try { + filterData = List>.from( + jsonDecode(state.uri.queryParameters['filter_data']!) + ); + } catch (e) { + print('Error parsing filter_data: $e'); + filterData = []; // Assign an empty list to prevent null issues + } + } else { + filterData = []; // Ensure it's a valid list + } + + print('Router dataSets: $dataSets'); print('Router bgColor: $bgColor'); print('Router mainTopic: $mainTopic'); print('Router title: $title'); + print('Router filter: $filterData'); // Pass both values to the screen return ChartScreen1( @@ -427,6 +451,8 @@ final GoRouter router = GoRouter( mainTopic: mainTopic, title: title, keyParam: key, + kpi: kpi, + filter_data: filterData, ); }, ), diff --git a/lib/infrastructure/services/pocketbase_service.dart b/lib/infrastructure/services/pocketbase_service.dart index 20fb6ace..017137df 100644 --- a/lib/infrastructure/services/pocketbase_service.dart +++ b/lib/infrastructure/services/pocketbase_service.dart @@ -1,9 +1,11 @@ import 'dart:convert'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; abstract class PocketBaseService { - static const _host = 'https://pb.venbait.in'; + static const _host = apiUrl; + // static const _host = 'https://pb.venbait.in'; // static const _host = 'http://127.0.0.1:8090'; static final _pb = PocketBase(_host); static final users = _pb.collection('users'); diff --git a/lib/l10n/intl_ar.arb b/lib/l10n/intl_ar.arb index 83622a31..c6b55469 100644 --- a/lib/l10n/intl_ar.arb +++ b/lib/l10n/intl_ar.arb @@ -4,6 +4,7 @@ "social_title":"اجتماعي", "environment_title":"البيئة", "bookmarks": "الإشارات المرجعية", + "feedback_title": "تعليق", "feedback_failed_msg": "لم يتم إرسال تعليقاتك. يرجى المحاولة مرة أخرى.", "thankYou": "شكراً", diff --git a/lib/l10n/intl_en.arb b/lib/l10n/intl_en.arb index 90c050e0..10d131d5 100644 --- a/lib/l10n/intl_en.arb +++ b/lib/l10n/intl_en.arb @@ -1,10 +1,10 @@ { - "all_bookmarks":"All Bookmarks", "economy_title":"Economy", "social_title":"Social", "environment_title":"Environment", "bookmarks": "Bookmarks", + "feedback_title": "Feedback", "feedback_failed_msg": "Your feedback could not be \n submitted. Please try again", "thankYou": "Thank you", diff --git a/lib/main.dart b/lib/main.dart index d58dbe2d..a795ed32 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -16,6 +16,8 @@ import 'package:uae_stat/presentation/Screens/auth_verification/registration.dar import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; + + // void main() async { // WidgetsFlutterBinding.ensureInitialized(); // // await (await SharedPreferences.getInstance()).clear(); @@ -89,6 +91,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart'; // } // } + + void main() async { WidgetsFlutterBinding.ensureInitialized(); configureDependencies(); @@ -102,10 +106,18 @@ void main() async { class MainApp extends ConsumerWidget { const MainApp({super.key}); + + + @override Widget build(BuildContext context, WidgetRef ref) { final locale = ref.watch(localeProvider); + final connectivityProvider = Provider((ref) { + return true; // Replace with actual logic + }); + + // ref.listen(connectivityProvider, (previous, hasInternet) { // print('Previous Internet Status: $previous'); // print('Current Internet Status: $hasInternet'); diff --git a/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart b/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart index c3940cf7..86daad93 100644 --- a/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart +++ b/lib/presentation/Screens/Bottom Navigation Pages/UAE_Numbers/uae_numbers.dart @@ -10,6 +10,8 @@ import 'package:uae_stat/presentation/routes/bottom_bar_routes/tab_routes/home_r import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart'; import 'package:uae_stat/presentation/components/constant/constant.dart'; import 'package:http/http.dart' as http; +import 'package:uae_stat/config/api_config.dart'; + class UaeNumbers extends StatelessWidget { const UaeNumbers({super.key}); @@ -83,7 +85,7 @@ class _UaenumberWidgetState extends ConsumerState { Future fetchData(locale) async { // const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; - const baseUrl = 'https://pb.venbait.in/api/getUAENumbersData'; + const baseUrl = '$apiUrl/api/getUAENumbersData'; try { final response = await http.get(Uri.parse(baseUrl + '?language=$locale')); if (response.statusCode == 200) { diff --git a/lib/presentation/Screens/auth_verification/changepassword.dart b/lib/presentation/Screens/auth_verification/changepassword.dart index 225c143a..c23170e8 100644 --- a/lib/presentation/Screens/auth_verification/changepassword.dart +++ b/lib/presentation/Screens/auth_verification/changepassword.dart @@ -5,6 +5,7 @@ import 'package:go_router/go_router.dart'; import 'package:http/http.dart' as http; import 'package:flutter/material.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'otp_verification.dart'; class Changepassword extends StatefulWidget { @@ -17,7 +18,7 @@ class Changepassword extends StatefulWidget { } class _ResetPasswordScreenState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); // final pb = PocketBase('http://127.0.0.1:8090'); final _formKey = GlobalKey(); final _emailController = TextEditingController(); @@ -46,7 +47,7 @@ class _ResetPasswordScreenState extends State { // Check if email exists in the user collection final userCheckResponse = await http.get( Uri.parse( - 'https://pb.venbait.in/api/collections/users/records?filter=email="$email"'), + '$apiUrl/api/collections/users/records?filter=email="$email"'), headers: { 'Authorization': 'Bearer $authToken', }, @@ -63,7 +64,7 @@ class _ResetPasswordScreenState extends State { // Proceed with OTP request final otpResponse = await http.post( Uri.parse( - 'https://pb.venbait.in/api/collections/otp_requests/records'), + '$apiUrl/api/collections/otp_requests/records'), headers: { 'Content-Type': 'application/json', 'Authorization': 'Bearer $authToken', diff --git a/lib/presentation/Screens/auth_verification/confirm_password.dart b/lib/presentation/Screens/auth_verification/confirm_password.dart index cef960e0..2cf9b323 100644 --- a/lib/presentation/Screens/auth_verification/confirm_password.dart +++ b/lib/presentation/Screens/auth_verification/confirm_password.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/presentation/Screens/profilepage.dart'; class ConfirmPassword extends StatefulWidget { @@ -12,7 +13,7 @@ class ConfirmPassword extends StatefulWidget { } class _ConfirmPasswordState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); // final pb = PocketBase('http://127.0.0.1:8090'); final _formKey = GlobalKey(); bool _obscurePassword = true; diff --git a/lib/presentation/Screens/auth_verification/create_new_pw.dart b/lib/presentation/Screens/auth_verification/create_new_pw.dart index 0b8de8da..a0303f4a 100644 --- a/lib/presentation/Screens/auth_verification/create_new_pw.dart +++ b/lib/presentation/Screens/auth_verification/create_new_pw.dart @@ -3,6 +3,7 @@ import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_router.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; @@ -26,7 +27,7 @@ class CreateNewPw extends ConsumerStatefulWidget { } class _CreateNewPwState extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); final _formKey = GlobalKey(); bool _obscureOldPassword = true; bool _obscureNewPassword = true; diff --git a/lib/presentation/Screens/auth_verification/otp_verification.dart b/lib/presentation/Screens/auth_verification/otp_verification.dart index f5c4c6c8..a6c1c309 100644 --- a/lib/presentation/Screens/auth_verification/otp_verification.dart +++ b/lib/presentation/Screens/auth_verification/otp_verification.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'package:flutter/material.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'confirm_password.dart'; @@ -24,7 +25,7 @@ class EmailVerificationScreen extends StatefulWidget { class _EmailVerificationScreenState extends State { // final pb = PocketBase('http://127.0.0.1:8090'); - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); final List _otpControllers = List.generate(4, (_) => TextEditingController()); int _secondsRemaining = 120; // 2 minutes timer diff --git a/lib/presentation/Screens/auth_verification/registration.dart b/lib/presentation/Screens/auth_verification/registration.dart index aa9166d0..e9faf1f5 100644 --- a/lib/presentation/Screens/auth_verification/registration.dart +++ b/lib/presentation/Screens/auth_verification/registration.dart @@ -5,6 +5,7 @@ import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_theme.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/banner_asset_path.dart'; @@ -38,7 +39,7 @@ class _RegisterScreenState extends ConsumerState { bool isRegistering = false; dynamic userID; - final pb = PocketBase('https://pb.venbait.in'); + final pb = PocketBase(apiUrl); // final pb = PocketBase('http://127.0.0.1:8090'); // Add focus nodes and hint states diff --git a/lib/presentation/Screens/charts/screens/chart_screen.dart b/lib/presentation/Screens/charts/screens/chart_screen.dart index dacfc19f..ab95b72b 100644 --- a/lib/presentation/Screens/charts/screens/chart_screen.dart +++ b/lib/presentation/Screens/charts/screens/chart_screen.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; @@ -8,6 +10,7 @@ import 'package:pocketbase/pocketbase.dart'; import 'package:screenshot/screenshot.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:tutorial_coach_mark/tutorial_coach_mark.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/toast_util.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart'; @@ -31,6 +34,8 @@ class ChartScreen1 extends ConsumerStatefulWidget { final String mainTopic; final String title; final String? keyParam; // Nullable String + final String kpi; + final List> filter_data; const ChartScreen1({ Key? key, @@ -39,13 +44,16 @@ class ChartScreen1 extends ConsumerStatefulWidget { required this.mainTopic, required this.title, required this.keyParam, + required this.kpi, + required this.filter_data, }); @override ConsumerState createState() => _ChartScreen1State(); } class _ChartScreen1State extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + // final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); List> selectedFiltersStorage = []; final GlobalKey _scaffoldKey = GlobalKey(); final ApiService apiService = ApiService(); @@ -67,6 +75,9 @@ class _ChartScreen1State extends ConsumerState { late Color backgroundColor; final ScrollController _scrollController = ScrollController(); int _activeTabIndex = 0; + dynamic tabWiseKpi=[]; + dynamic tabFilteredKpi=[]; + List> formattedFilters=[]; dynamic _tabsData = []; // List> _tabsData = []; @@ -85,11 +96,12 @@ class _ChartScreen1State extends ConsumerState { super.initState(); final String bgColor = widget.bgColor; print(' bgColor $bgColor'); - // fetchChartData(widget.dataSets); checkIfBookmarked(); locale = ref.read(localeProvider) ?? const Locale('en'); - fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) { - if (_tabsData.isNotEmpty) { + + fetchChartData(widget.dataSets, locale?.languageCode ?? 'en', widget.kpi, widget.filter_data) + .then((_) { + if(_tabsData.isNotEmpty) { // Call onTabSelected for the first tab onTabSelected(_tabsData[0]['id']); } @@ -1202,6 +1214,8 @@ class _ChartScreen1State extends ConsumerState { // } void processChartData(chartsData) { + print("PROCESSING FILTER CHART DATa"); + // Group data by 'kpi' Map>> groupedData = {}; @@ -1231,7 +1245,6 @@ class _ChartScreen1State extends ConsumerState { ? word[0].toUpperCase() + word.substring(1) : '') // Capitalize .join(' '); // Join words with space - return {'id': kpi, 'name': tabHeading, 'order': tabOrder.toString()}; }).toList(); @@ -1244,7 +1257,7 @@ class _ChartScreen1State extends ConsumerState { print('Sorted Tabs: $_tabs'); - print('Grouped Data: $groupedData'); + // print('Grouped Data: $groupedData'); print('Tabs: $_tabs'); setState(() { @@ -1252,8 +1265,13 @@ class _ChartScreen1State extends ConsumerState { }); } - Future fetchChartData(String dataSets, locale) async { - var data = await apiService.fetchChartData(dataSets, locale); + Future fetchChartData(String dataSets, locale, kpi, filter_data ) async { + var data = await apiService.fetchChartData(dataSets, locale,kpi,filter_data); + + tabFilteredKpi = kpi; + print('FETCH KPI- $kpi'); + print('FETCH KFilter- $filter_data'); + if (data.containsKey('filterData')) { var filterData = data['filterData']; @@ -1281,18 +1299,71 @@ class _ChartScreen1State extends ConsumerState { processChartData(chartsData); + onTabSelected(tabFilteredKpi); + print('chartsData :- $chartsData'); print('cardData :- $cardData'); print('chartScreenData :- $chartScreenData'); // print('filterData :- $filterData'); isLoading = false; }); - print('chartsData -$chartsData'); - print('cardData -$cardData'); + // print('chartsData -$chartsData'); + // print('cardData -$cardData'); } void applyFilters(BuildContext context, List filters, List data, List dataCard, List selectedFilters) { + + print('applyFilters called'); + print('Selected ApplyFilters: $selectedFilters'); + + if (selectedFilters.every((filter) => filter['filter_data'].isEmpty)) { + setState(() { + chartsData = + List.from(originalTabChartsData); // Restore the original data + // cardData = List.from(originalTabCardData); // Restore the original data + }); + print('Returning as no filters are selected'); + Navigator.pop(context); + return; // Exit early since all filter_data are empty + } + + // Transform the selectedFilters list into the required format + formattedFilters = selectedFilters + .where((filter) => filter['filter_data'] != null && filter['filter_data'].isNotEmpty) + .map((filter){ + return{ + 'filter_key': filter['filter_key'], + 'filter_data':filter['filter_data'].map((item)=> item.toString()).toList() + }; + }).toList(); + + print('Formatted Filters1: $formattedFilters'); + + // Convert to JSON format + String selectedFormatFilters = jsonEncode({ + 'kpi': tabWiseKpi, + 'filter_data': formattedFilters + }); + + print('Formatted Filters2: $selectedFormatFilters'); + + // Call fetchChartData with correct parameters + fetchChartData( + widget.dataSets, + locale.languageCode ?? 'en', + tabWiseKpi, // Ensure you are passing the correct KPI here + formattedFilters // Pass the formatted filter data here + ); + Navigator.pop(context); + + selectedFiltersStorage = List.from(selectedFilters); + print('selectedFiltersStoraged- $selectedFiltersStorage'); + + } + + void applyFilters1(BuildContext context, List filters, List data, + List dataCard, List selectedFilters) { print("applyFilters called"); print("Selected ApplyFilters: $selectedFilters"); print("Selected data: $data"); @@ -1429,6 +1500,9 @@ class _ChartScreen1State extends ConsumerState { } void showRightSideModal(BuildContext context, List filters, List data) { + + print('selectedFiltersStoraged1- $selectedFiltersStorage'); + // Initialize selected filters structure from the stored value, if exists List> selectedFilters = selectedFiltersStorage.isNotEmpty @@ -1437,6 +1511,8 @@ class _ChartScreen1State extends ConsumerState { return {"filter_key": filter["filter_key"], "filter_data": []}; }).toList(); // Or initialize empty filters + print('selectedFiltersStoragedrgt- $selectedFiltersStorage'); + showModalBottomSheet( context: context, isScrollControlled: true, @@ -1706,6 +1782,13 @@ class _ChartScreen1State extends ConsumerState { cardData = List.from(originalTabCardData); }); selectedFiltersStorage.clear(); + formattedFilters = []; + fetchChartData( + widget.dataSets, + locale.languageCode ?? 'en', + tabWiseKpi, // Ensure you are passing the correct KPI here + formattedFilters // Pass the formatted filter data here + ); Navigator.pop(context); }, style: ElevatedButton.styleFrom( @@ -1738,6 +1821,7 @@ class _ChartScreen1State extends ConsumerState { onPressed: () { print( "Selected Filters before applying: $selectedFilters"); + setState(() { chartsData = originalTabChartsData; cardData = originalTabCardData; @@ -1745,7 +1829,7 @@ class _ChartScreen1State extends ConsumerState { applyFilters(context, filters, chartsData, cardData, selectedFilters); - selectedFiltersStorage = List.from(selectedFilters); + // selectedFiltersStorage = List.from(selectedFilters); }, style: ElevatedButton.styleFrom( backgroundColor: Color(0xFF92722A), @@ -1787,8 +1871,10 @@ class _ChartScreen1State extends ConsumerState { } void onTabSelected(String tabId) { - print('Selected Tab: $tabId'); - selectedFiltersStorage.clear(); + print('Selected Tab on: $tabId'); + tabWiseKpi = tabId; + + // selectedFiltersStorage.clear(); // Filter the filterDataSet filterData = filterDataSet .where((item) => item['key'] == tabId) @@ -1824,7 +1910,8 @@ class _ChartScreen1State extends ConsumerState { } void performActionForTab(String tabId) { - print('Selected Tab: $tabId'); + + print('Selected Tab perform: $tabId'); // Filter the chartsData array based on the tabId tabFilteredChartData = chartsData.where((chart) { @@ -1920,12 +2007,18 @@ class _ChartScreen1State extends ConsumerState { final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null // fetchChartData(widget.dataSets, localeCode); - fetchChartData(widget.dataSets, localeCode).then((_) { + + final List> safeFilterData = widget.filter_data ?? []; + final String safeKpi = widget.kpi ?? ''; + fetchChartData(widget.dataSets,localeCode, safeKpi, safeFilterData).then((_) { + print('DEBUG KPI: $safeKpi'); if (_tabsData.isNotEmpty) { // Call onTabSelected for the first tab onTabSelected(_tabsData[0]['id']); } }); + + }); double myheight = MediaQuery.of(context).size.height; double mywidth = MediaQuery.of(context).size.width; @@ -2303,483 +2396,6 @@ class _ChartScreen1State extends ConsumerState { }, ), ), - // Padding( - // padding: const EdgeInsets.all(3.34), - // child: GridView.builder( - // key: cardKey, - // itemCount: cardData.length, - // shrinkWrap: true, - // physics: const NeverScrollableScrollPhysics(), - // gridDelegate: - // SliverGridDelegateWithFixedCrossAxisCount( - // crossAxisCount: 2, - // // crossAxisCount: cardData.length % 2 == 0 ? 2 : 3, - // - // crossAxisSpacing: 2, - // - // mainAxisSpacing: 5, - // - // childAspectRatio: MediaQuery.of(context) - // .size - // .width / - // (MediaQuery.of(context).size.height / - // (cardData.length % 2 == 0 ? 2 : 2)), - // ), - // - // // Sort and filter the 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_full_length = - // item['card_full_length']; - // print('cardfulllength $card_full_length'); - // final response = - // item['response'] as List? ?? - // []; - // 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; - // // double myheight = MediaQuery.of(context).size.height; - // // double mywidth = MediaQuery.of(context).size.width; - // // final cardWidth = rowItems.length == 1 ? myWidth : (myWidth - 16) / 2.6; - // print('find width $cardData'); - // final itemdata = cardData[index]; - // // bool isOddLength = cardData.length % 2 != 0; - // // bool isLastSingleCard = isOddLength && - // // index == cardData.length - 1; - // // print('isLastSingleCard $isLastSingleCard'); - // - // if (response.isEmpty) { - // return const SizedBox.shrink(); - // // return Container( - // // color: Colors.redAccent, - // // ); - // } - // if (response.length == 1) { - // return Container( - // margin: const EdgeInsets.all(10), - // width: card_full_length - // ? double.infinity - // : null, - // decoration: BoxDecoration( - // borderRadius: - // BorderRadius.circular(12), - // border: Border.all( - // color: Color(int.parse( - // (chartScreenData[ - // 'border_color'] ?? - // '#898C81') - // .replaceFirst( - // '#', '0xff'))), - // // Dynamic border color - // width: - // 1, // Adjust border thickness - // ), - // ), - // child: Card( - // margin: const EdgeInsets.all(0), - // shape: RoundedRectangleBorder( - // borderRadius: - // BorderRadius.circular(12), - // ), - // elevation: 2, - // child: Container( - // height: cardHeight, - // padding: const EdgeInsets.only( - // left: 16.0, - // right: 16.0, - // bottom: 1.0, - // top: 1.0), - // decoration: BoxDecoration( - // color: Colors - // .white, // Move color inside BoxDecoration - // borderRadius: BorderRadius.circular( - // 12), // Ensure border radius is applied - // ), - // child: Column( - // mainAxisSize: MainAxisSize.min, - // mainAxisAlignment: - // MainAxisAlignment.center, - // children: [ - // 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: 1), - // MouseRegion( - // onEnter: (event) { - // // Show tooltip on hover - // final overlay = Overlay - // .of(context) - // .context - // .findRenderObject() - // as RenderBox; - // final entry = - // OverlayEntry( - // builder: (context) => - // Positioned( - // left: overlay - // .localToGlobal( - // Offset.zero) - // .dx, - // top: overlay - // .localToGlobal( - // Offset.zero) - // .dy, - // child: Material( - // color: Colors - // .transparent, - // child: Container( - // padding: - // EdgeInsets - // .all(8), - // decoration: - // BoxDecoration( - // color: Colors - // .black87, - // borderRadius: - // BorderRadius - // .circular( - // 4), - // ), - // child: Text( - // chart_heading ?? - // 'NA', - // style: TextStyle( - // color: Colors - // .white), - // ), - // ), - // ), - // ), - // ); - // Overlay.of(context) - // .insert(entry); - // Future.delayed( - // Duration(seconds: 2), - // () => entry.remove()); - // }, - // child: Text( - // chart_heading ?? 'NA', - // textAlign: - // TextAlign.center, - // maxLines: 2, - // overflow: TextOverflow - // .ellipsis, // Truncate text with '...' - // style: TextStyle( - // fontSize: 11, - // fontWeight: - // FontWeight.w400, - // color: Colors.black87, - // ), - // ), - // ), - // const SizedBox(height: 5), - // Text( - // RegExp(r'\d').hasMatch( - // response[0][ - // 'display_value'] ?? - // '') - // ? '(${response[0]['display_value'] ?? 'NA'})' - // : '${response[0]['display_value'] ?? 'NA'}', - // style: const TextStyle( - // fontSize: 11, - // color: Colors.grey, - // overflow: TextOverflow - // .ellipsis, // Truncate if text overflows - // ), - // maxLines: - // 1, // Limit to one line to prevent overflow - // textAlign: TextAlign - // .center, // Ensure proper alignment - // ), - // const SizedBox(height: 1), - // Row( - // mainAxisAlignment: - // MainAxisAlignment - // .center, // Center-aligns the row contents - // children: [ - // Text( - // response[0]['value'] ?? - // 'NA', - // textAlign: TextAlign - // .center, // Ensures text is centered - // style: TextStyle( - // fontSize: 23, - // fontWeight: - // FontWeight.w800, - // color: (response[0][ - // 'font_color'] ?? - // '') - // .isEmpty - // ? bodyColor - // : _getColorFromHex( - // response[0][ - // 'font_color']), - // ), - // ), - // const SizedBox( - // width: - // 4), // Space between text and icon - // if (response[0] - // ['calculation'] == - // 'different') ...[ - // if (response[0][ - // 'font_color'] == - // '#D83731') - // const Icon( - // Icons - // .arrow_downward, - // color: Colors.red, - // size: 20) - // else if (response[0][ - // 'font_color'] == - // '#11AF22') - // const Icon( - // Icons - // .arrow_upward, - // color: - // Colors.green, - // size: 20), - // ], - // ], - // ) - // ], - // ), - // ), - // )); - // } else { - // return Container( - // margin: const EdgeInsets.all(10), - // width: card_full_length - // ? double.infinity - // : null, - // decoration: BoxDecoration( - // borderRadius: - // BorderRadius.circular(12), - // border: Border.all( - // color: Color(int.parse((chartScreenData[ - // 'border_color'] ?? - // '#898C81') - // .replaceFirst('#', - // '0xff'))), // Dynamic border color - // width: 1, // Adjust border thickness - // ), - // ), - // child: Card( - // margin: const EdgeInsets.all(0), - // shape: RoundedRectangleBorder( - // borderRadius: - // BorderRadius.circular(12), - // ), - // elevation: - // 0, // Remove shadow to keep only the outli - // - // child: Container( - // height: cardHeight, - // padding: const EdgeInsets.all(10.0), - // decoration: BoxDecoration( - // color: Colors - // .white, // Move color inside BoxDecoration - // borderRadius: BorderRadius.circular( - // 12), // Ensure border radius is applied - // ), - // child: Column( - // mainAxisSize: MainAxisSize - // .min, // Adjust card height based on content - // mainAxisAlignment: - // MainAxisAlignment.center, - // children: [ - // // 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), - // MouseRegion( - // onEnter: (event) { - // final overlay = - // Overlay.of(context); - // final entry = OverlayEntry( - // builder: (context) => - // Positioned( - // left: event.position.dx, - // top: event.position.dy + - // 10, // Adjust tooltip position - // child: Material( - // color: Colors - // .transparent, - // child: Container( - // padding: - // EdgeInsets.all( - // 8), - // decoration: - // BoxDecoration( - // color: Colors - // .black87, - // borderRadius: - // BorderRadius - // .circular( - // 4), - // ), - // child: Text( - // chart_heading ?? - // 'NA', - // style: TextStyle( - // color: Colors - // .white, - // fontSize: 10), - // ), - // ), - // ), - // ), - // ); - // overlay.insert(entry); - // Future.delayed( - // Duration(seconds: 2), - // () => entry.remove()); - // }, - // child: SizedBox( - // width: double - // .infinity, // Ensures it uses available space - // child: Text( - // chart_heading ?? 'NA', - // textAlign: - // TextAlign.center, - // maxLines: 2, - // overflow: TextOverflow - // .ellipsis, // Truncate with '...' - // style: TextStyle( - // fontSize: 11, - // fontWeight: - // FontWeight.w400, - // color: Colors.black87, - // ), - // ), - // ), - // ), - // const SizedBox(height: 1), - // Text( - // // '(${response[0]['display_value'] ?? 'NA'})', - // - // RegExp(r'\d').hasMatch(response[ - // 0][ - // 'display_value'] ?? - // '') - // ? '(${response[0]['display_value'] ?? 'NA'})' - // : '${response[0]['display_value'] ?? 'NA'}', - // - // style: const TextStyle( - // fontSize: 11, - // color: Colors.grey, - // overflow: - // TextOverflow.ellipsis, - // ), - // ), - // const SizedBox(height: 1), - // Text( - // response[0]['value'] ?? 'NA', - // overflow: TextOverflow - // .ellipsis, // Truncate text if it overflows - // maxLines: - // 1, // Ensures text stays in a single line - // style: TextStyle( - // fontSize: 23, - // fontWeight: FontWeight.w900, - // color: (response[0][ - // 'font_color'] ?? - // '') - // .isEmpty - // ? bodyColor - // : _getColorFromHex( - // response[0] - // ['font_color']), - // ), - // ), - // SizedBox( - // height: - // 2, // Height of the divider - // child: Divider( - // color: Color(0xFFBBBCBD), - // thickness: - // 1, // Divider line thickness - // ), - // ), - // Text( - // response[1]['value'] ?? 'NA', - // style: TextStyle( - // fontSize: 16, - // fontWeight: FontWeight.w600, - // color: (response[1][ - // 'font_color'] ?? - // '') - // .isEmpty - // ? const Color( - // 0xFFD83731) - // : _getColorFromHex( - // response[1] - // ['font_color']), - // ), - // textAlign: TextAlign - // .center, // Ensure proper alignment - // overflow: TextOverflow - // .ellipsis, // Truncate if text overflows - // ), - // Text( - // // '(${response[1]['display_value'] ?? 'NA'})', - // RegExp(r'\d').hasMatch(response[ - // 1][ - // 'display_value'] ?? - // '') - // ? '(${response[1]['display_value'] ?? 'NA'})' - // : '${response[1]['display_value'] ?? 'NA'}', - // style: const TextStyle( - // fontSize: 8, - // fontWeight: FontWeight.w500, - // color: Colors.grey, - // overflow: - // TextOverflow.ellipsis, - // ), - // ), - // ], - // ), - // ), - // ), - // ); - // } - // }, - // ), - // ), - // chartsData Cards ListView.builder( itemCount: chartsData.length, shrinkWrap: true, @@ -2818,7 +2434,7 @@ class _ChartScreen1State extends ConsumerState { ? 500 : (chartsData[index][ 'chart_type'] == - 'bar_chart_horizontal') + 'bar_chart_horizontal') ? 370 : (chartsData[index]['chart_type'] == 'fl_stacked_bar') ? 390 @@ -2980,7 +2596,12 @@ class CardWidget extends StatelessWidget { ), ); - if (response.length == 1) { + + if(response.isEmpty) + { + return SizedBox.shrink(); + } + else if (response.length == 1) { return Container( margin: const EdgeInsets.all(10), // width: card_full_length ? double.infinity : null, @@ -3117,7 +2738,7 @@ class CardWidget extends StatelessWidget { margin: const EdgeInsets.all(10), // width: card_full_length ? double.infinity : null, decoration: BoxDecoration( - borderRadius: BorderRadius.circular(12), + borderRadius: BorderRadius.circular(12), border: Border.all( color: Color(int.parse( (chartScreenData['border_color'] ?? '#898C81') @@ -3341,4 +2962,4 @@ class CardWidget extends StatelessWidget { // ), // ); } -} \ No newline at end of file +} diff --git a/lib/presentation/Screens/charts/services/api_service.dart b/lib/presentation/Screens/charts/services/api_service.dart index 196aed85..dfc29379 100644 --- a/lib/presentation/Screens/charts/services/api_service.dart +++ b/lib/presentation/Screens/charts/services/api_service.dart @@ -2,6 +2,8 @@ import 'dart:convert'; import 'package:http/http.dart' as http; import 'dart:collection'; +import 'package:uae_stat/config/api_config.dart'; + class ChartData { final DateTime? xDateTime; final String? x; // Optional for non-DateTime-based charts @@ -11,19 +13,49 @@ class ChartData { } class ApiService { - static const String baseUrl = 'https://pb.venbait.in/api/getDataSet'; + // static const String baseUrl = 'https://pb.venbait.in/api/getDataSet'; + static const String baseUrl = '$apiUrl/api/getDataSet'; - Future> fetchChartData(String dataSets, locale) async { + Future> fetchChartData(String dataSets, locale,kpi, + List> filterData) async { List isChartData = []; List nonChartData = []; List originalChartsData = []; List originalCardData = []; - final url = Uri.parse('$baseUrl?dataset=$dataSets&language=$locale'); + // final url = Uri.parse('$baseUrl?dataset=$dataSets&language=$locale'); + // final url = Uri.parse( + // '$baseUrl?dataset=$dataSets&language=$locale&kpi=$kpi&filter_data=${Uri.encodeComponent(jsonEncode(filterData))}' + // ); + + + final url = Uri.parse(baseUrl); // No query parameters in URL for POST + + final Map requestBody = { + 'dataset': dataSets, + 'language': locale, + 'kpi': kpi.isNotEmpty ? kpi : null, // Avoid sending empty kpi + 'filter_data': filterData.isNotEmpty ? filterData : null, // Avoid empty list + }; + + // final url = Uri.https('$baseUrl?dataset=$dataSets&language=$locale'); + + print('APISErvice - $url'); try { - final response = await http.get(url); - print('data'); + final response = await http.post( + url, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode(requestBody), + ); + + print('Response Status: ${response.statusCode}'); + print('Response Body: ${response.body}'); + + print('data -$response'); + print('API Request URL: $url'); + print('Filter Data: ${jsonEncode(filterData)}'); + if (response.statusCode == 200) { final Map jsonData = jsonDecode(response.body); // Variables to store filtered data diff --git a/lib/presentation/Screens/charts/widgets/chart_widget.dart b/lib/presentation/Screens/charts/widgets/chart_widget.dart index c3a8d0b4..8c95e730 100644 --- a/lib/presentation/Screens/charts/widgets/chart_widget.dart +++ b/lib/presentation/Screens/charts/widgets/chart_widget.dart @@ -91,6 +91,18 @@ class ChartWidget extends StatelessWidget { }).toList(); } + Color adjustColor(Color baseColor, int index) { + final HSLColor hsl = HSLColor.fromColor(baseColor); + + // Lightness variation (keeping it light, between 0.6 and 0.9) + double lightnessFactor = 0.6 + (index % 4) * 0.1; // Varies between 0.6 to 0.8 + final HSLColor adjustedHSL = hsl.withLightness( + lightnessFactor.clamp(0.6, 0.9), // Ensures light shades only + ); + + return adjustedHSL.toColor(); + } + List parsePieChartData( dynamic chartData, double totalValue, @@ -111,7 +123,7 @@ class ChartWidget extends StatelessWidget { if (rawValue is String) { value = double.tryParse(rawValue) ?? 0.0; - } else if (rawValue is int) { + } else if (rawValue is num) { value = rawValue.toDouble(); } else if (rawValue is double) { value = rawValue; @@ -125,7 +137,8 @@ class ChartWidget extends StatelessWidget { return PieChartSectionData( value: value, - color: Colors.primaries[index % Colors.primaries.length], + // color: Colors.primaries[index % Colors.primaries.length], + color: adjustColor(bodyColor, index), // Adjust alpha dynamically title: '${percentage.toStringAsFixed(1)}%', radius: isTouched ? 60 : 50, @@ -157,7 +170,7 @@ class ChartWidget extends StatelessWidget { width: 10, height: 10, decoration: BoxDecoration( - color: color, + color: adjustColor(bodyColor, index), shape: BoxShape.circle, ), ), @@ -404,6 +417,7 @@ class ChartWidget extends StatelessWidget { List groupByValuesList = groupByValues.toList(); int chunkSize = 5; List> chunkedGroupByValues = []; + print('flStackedBar1'); for (int i = 0; i < groupByValuesList.length; i += chunkSize) { chunkedGroupByValues.add( groupByValuesList.sublist( @@ -452,6 +466,8 @@ class ChartWidget extends StatelessWidget { getTooltipItem: (groupData, groupIndex, rodData, rodIndex) { // Get the list of group names dynamically + + List groupNames = []; for (var entry in chartData['response']) { String groupValue = entry['ObsKey'][groupByKey]; @@ -459,7 +475,6 @@ class ChartWidget extends StatelessWidget { groupNames.add(groupValue); } } - // Accessing the stacked rod items and calculating the tooltip text List rodStackItems = rodData.rodStackItems; @@ -486,6 +501,8 @@ class ChartWidget extends StatelessWidget { Color groupColor = _getColorForGroup( i); // Replace with your color logic + + // Add a TextSpan for the colored circle and the group name with value tooltipTextSpans.addAll([ TextSpan( @@ -682,18 +699,8 @@ class ChartWidget extends StatelessWidget { } else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) { // Year-MonthAbbr (2019-Nov) Map monthMap = { - 'Jan': 1, - 'Feb': 2, - 'Mar': 3, - 'Apr': 4, - 'May': 5, - 'Jun': 6, - 'Jul': 7, - 'Aug': 8, - 'Sep': 9, - 'Oct': 10, - 'Nov': 11, - 'Dec': 12 + 'Jan': 1, 'Feb': 2, 'Mar': 3, 'Apr': 4, 'May': 5, 'Jun': 6, 'Jul': 7, 'Aug': 8, + 'Sep': 9, 'Oct': 10, 'Nov': 11, 'Dec': 12 }; List parts = timePeriod.split('-'); @@ -951,9 +958,13 @@ class ChartWidget extends StatelessWidget { (entry) => double.parse(entry['ObsKey']['TIME_PERIOD'])) .toSet(); + print('uniqueXValuesLineTrend2- $uniqueXValues'); + // Generate line bars for the chart List lineBars = lineBarsData2(filteredData); + + return Column(children: [ Text( chartData['chart_heading'] ?? '', @@ -979,8 +990,7 @@ class ChartWidget extends StatelessWidget { scrollDirection: Axis.horizontal, // Enable horizontal scrolling padding: const EdgeInsets.only(right: 40, top: 20), child: SizedBox( - width: (uniqueXValues.length * 50) + - 50, // Adjust width dynamically + width: (uniqueXValues.length * 50) + 50, // Adjust width dynamically child: LineChart( LineChartData( lineTouchData: lineTouchData1(), @@ -1227,7 +1237,7 @@ class ChartWidget extends StatelessWidget { } return Container(); }, - reservedSize: 80, + reservedSize: 110, ), ), topTitles: AxisTitles( @@ -1253,13 +1263,13 @@ class ChartWidget extends StatelessWidget { barRods: [ BarChartRodData( toY: yAxisData[index], - color: Colors.blueAccent, + color: bodyColor, borderRadius: BorderRadius.circular(4), width: 20, ), ], showingTooltipIndicators: [0], - ), + ), ), ), )) @@ -1268,8 +1278,36 @@ class ChartWidget extends StatelessWidget { // Extract groupBy values and their corresponding y-axis values List xAxisData = []; List yAxisData = []; + List> sortedData = []; for (var entry in chartData['response']) { + String? timePeriod = entry['ObsKey']['TIME_PERIOD']; + if (timePeriod != null) { + // Check if it contains a month (i.e., has "-" and follows "YYYY-MM" format) + bool hasMonth = RegExp(r'^\d{4}-\d{2}$').hasMatch(timePeriod); + + if (hasMonth) { + print('Yes-TIME_PERIOD: $timePeriod'); + sortedData.add(entry); + } else { + print('No-TIME_PERIOD: $timePeriod'); + } + } + } + // Sort the data based on year and month + sortedData.sort((a, b) { + String timeA = a['ObsKey']['TIME_PERIOD']; + String timeB = b['ObsKey']['TIME_PERIOD']; + + return timeA.compareTo(timeB); // Lexicographical sorting works for YYYY-MM + }); + + // If no valid TIME_PERIOD with a month is found, return original response + List> finalData = sortedData.isNotEmpty ? sortedData : List.from(chartData['response']); + + + for (var entry in finalData) { + var xValue = entry['ObsKey'][groupByKey]; var yValue = entry['ObsValue']['Value']; if (xValue != null && yValue != null) { @@ -1277,8 +1315,11 @@ class ChartWidget extends StatelessWidget { yAxisData.add(double.tryParse(yValue.toString()) ?? 0.0); } } + print("chartData['chart_heading']"); - print(chartData['chart_heading']); + print('RESpns- ${chartData['chart_heading']}'); + print(chartData['response']); + int rotationTurns = 1; return Column(children: [ Text( @@ -1424,6 +1465,9 @@ class ChartWidget extends StatelessWidget { const double barWidth = 30; // Width for each bar, including spacing return totalBars * barWidth; // Calculate total chart width } + + print('multi_bar'); + String cropKey = chartData['chart_type_json']['x_sub_group']; // Group crops by CROP_TYPE Map> groupedCrops = {}; @@ -1462,6 +1506,8 @@ class ChartWidget extends StatelessWidget { // // print('groupedCropsflmutli- $groupedCrops'); + print('hormulti_bar'); + return Center( child: Column(children: [ Text( @@ -1503,7 +1549,7 @@ class ChartWidget extends StatelessWidget { bottomTitles: AxisTitles( sideTitles: SideTitles( showTitles: true, - reservedSize: 40, // Added space for rotated titles + reservedSize: 80, // Added space for rotated titles getTitlesWidget: (value, meta) { if (value < groupByValues.length) { String title = @@ -1514,12 +1560,11 @@ class ChartWidget extends StatelessWidget { : title; return Padding( - padding: const EdgeInsets.only(top: 8.0), + padding: const EdgeInsets.only(top: 8.0,left: 30.0), child: SizedBox( - width: - 60, // Limit width to force wrapping + width: 60, // Limit width to force wrapping child: Transform.rotate( - angle: -0.5, + angle: -1.5, child: TooltipTheme( data: TooltipThemeData( decoration: BoxDecoration( @@ -1529,15 +1574,15 @@ class ChartWidget extends StatelessWidget { 8), // Optional: rounded corners ), textStyle: TextStyle( - color: Colors - .white), // Change text color + color: Colors.white), // Change text color ), child: Tooltip( message: title, child: Text( displayTitle, softWrap: true, - // style: TextStyle(backgroundColor: Colors.blueGrey[800]), + maxLines:2 , + style: TextStyle(fontSize: 10), overflow: TextOverflow.ellipsis, )), ), @@ -1973,6 +2018,7 @@ class ChartWidget extends StatelessWidget { for (var entry in filteredData) { int year = int.tryParse(entry['ObsKey']['TIME_PERIOD'].toString()) ?? 0; String gender = entry['ObsKey']['GENDER']; + double value = double.tryParse(entry['ObsValue']['Value'].toString()) ?? 0.0; @@ -1980,9 +2026,9 @@ class ChartWidget extends StatelessWidget { yearGenderMap[year] = {'M': 0.0, 'F': 0.0}; } - if (gender == 'Male') { + if (gender == 'Male'|| gender == 'ذكر') { yearGenderMap[year]!['M'] = value; - } else if (gender == 'Female') { + } else if (gender == 'Female' || gender == 'أنثى') { yearGenderMap[year]!['F'] = value; } } @@ -1996,6 +2042,7 @@ class ChartWidget extends StatelessWidget { } }); + // Add a line for the ratio data lineBars.add( LineChartBarData( @@ -2105,7 +2152,22 @@ class ChartWidget extends StatelessWidget { // Use the timePeriod directly as a string for x-axis double xValue = parseTimePeriod(timePeriod); - double yValue = double.parse(entry['ObsValue']['Value']); + print('spotss'); + + // double yValue = double.parse(entry['ObsValue']['Value']); + double yValue; + var value = entry['ObsValue']['Value']; + + if (value is int) { + yValue = value.toDouble(); + } else if (value is double) { + yValue = value; + } else if (value is String) { + yValue = double.tryParse(value) ?? 0.0; // Handle invalid strings safely + } else { + throw Exception("Unexpected value type: ${value.runtimeType}"); + } + return FlSpot(xValue, yValue); }).toList(); @@ -2194,7 +2256,7 @@ class ChartWidget extends StatelessWidget { } FlTitlesData titlesData1(Set xValues) { - print('tileDATa1xvalue - $xValues'); + print('tileDATa1xvalueline2 - $xValues'); double findClosest(double value, Set values) { return values @@ -2209,10 +2271,13 @@ class ChartWidget extends StatelessWidget { getTitlesWidget: (value, meta) { // Format values as millions (M) String formattedValue; + print('LineTrend2val1 - $value '); if (value % 10 == 0) { // Check if the value is in the millions or thousands range - + if (kDebugMode) { + print('LineTrend2valKmode - $value '); + } if (value >= 1000000000000) { formattedValue = '${(value / 1000000000000).toStringAsFixed(0)}T'; @@ -2244,7 +2309,7 @@ class ChartWidget extends StatelessWidget { return const SizedBox.shrink(); // return Text( - // formattedValue, + // 'LINETRENTD2', // style: TextStyle(color: Colors.black, fontSize: 12), // ); }, @@ -2256,13 +2321,13 @@ class ChartWidget extends StatelessWidget { interval: null, // interval: 10, // Ensure each year is shown only once getTitlesWidget: (value, meta) { - print('BtmTiles :-$value'); - print('BtmTilesmeta :-$meta'); + // print('BtmTiles :-$value'); + // print('BtmTilesmeta :-$meta'); // if (xValues.contains(value)) double closestValue = findClosest(value, xValues); if ((closestValue - value).abs() < 0.15) { - print("Bottomtiles"); - print(value); + // print("Bottomtiles"); + // print(value); return Padding( padding: const EdgeInsets.only(top: 1.1), child: Transform.rotate( @@ -2321,12 +2386,26 @@ class ChartWidget extends StatelessWidget { List _generateBarGroups( BuildContext context, dynamic chartData, String groupByKey) { Map> groupedData = {}; - + print('flStackedBar3'); // Group data by `group_by` and `TIME_PERIOD`, accumulating the values for each group and year for (var entry in chartData['response']) { String groupValue = entry['ObsKey'][groupByKey]; String timePeriod = entry['ObsKey']['TIME_PERIOD']; - double value = double.tryParse(entry['ObsValue']['Value']) ?? 0.0; + // double value = double.tryParse(entry['ObsValue']['Value']) ?? 0.0; + + double value; + var rawValue = entry['ObsValue']['Value']; + + if (rawValue is num) { + value = rawValue.toDouble(); + } else if (rawValue is double) { + value = rawValue; + } else { + value = double.tryParse(rawValue.toString()) ?? 0.0; + } + + + print('flStackedBar3.1'); // print('fl_groupValue $groupValue'); // print('fl_timePeriod $timePeriod'); @@ -2335,6 +2414,7 @@ class ChartWidget extends StatelessWidget { if (!groupedData.containsKey(groupValue)) { groupedData[groupValue] = {}; } + if (!groupedData[groupValue]!.containsKey(timePeriod)) { groupedData[groupValue]![timePeriod] = 0.0; } @@ -2347,6 +2427,7 @@ class ChartWidget extends StatelessWidget { List timePeriods = groupedData.values.first.keys.toList(); print('timePeriods $timePeriods'); + // double barWidth = calculateBarWidth(context, timePeriods.length); // For each time period, generate a BarChartGroupData @@ -2360,7 +2441,6 @@ class ChartWidget extends StatelessWidget { int groupIndex = 0; // Track group index for color assignment for (var group in groupedData.keys) { double value = groupedData[group]![timePeriods[i]] ?? 0.0; - // Add stacked item with current `toY` value and the incremented one rodStackItems.add( BarChartRodStackItem( @@ -2496,11 +2576,17 @@ class ChartWidget extends StatelessWidget { double _calculateMaxY(dynamic chartData) { // Dynamically calculate the maximum Y value + + print('hormulti_bar2'); + List response = chartData['response'] ?? []; double maxY = 0; for (var entry in response) { - double value = double.tryParse(entry['ObsValue']['Value'] ?? '0') ?? 0; + // double value = double.tryParse(entry['ObsValue']['Value'] ?? '0') ?? 0; + double value = (entry['ObsValue']['Value'] as num?)?.toDouble() ?? 0; + + if (value > maxY) { maxY = value; } @@ -2514,6 +2600,9 @@ class ChartWidget extends StatelessWidget { List responseData = chartData['response']; List barGroups = []; int colorIndex = 0; + + print('hormulti_bar1.1'); + // Iterate through groupByValues and populate BarChartGroupData for (int i = 0; i < groupByValues.length; i++) { String groupValue = groupByValues.elementAt(i); @@ -2528,7 +2617,7 @@ class ChartWidget extends StatelessWidget { // Ensure to retrieve and parse 'ObsValue' value (which should be a double) double value = double.tryParse(data['ObsValue']['Value'].toString()) ?? 0.0; - + print('multi_bar1.1'); final List uniqueColorsForTwo = [ Color(0xFF648CBA), Color(0xFF90B0D5), @@ -2647,4 +2736,4 @@ class ChartData { final String? x; final double y; final DateTime? xDateTime; -} \ No newline at end of file +} diff --git a/lib/presentation/Screens/profilepage.dart b/lib/presentation/Screens/profilepage.dart index c93f003f..194aa8bc 100644 --- a/lib/presentation/Screens/profilepage.dart +++ b/lib/presentation/Screens/profilepage.dart @@ -12,6 +12,7 @@ import 'package:image_picker/image_picker.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_theme.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/data/p_auth_repo.dart'; @@ -34,7 +35,7 @@ class ProfileScreen extends ConsumerStatefulWidget { } class _ProfileScreenState extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); // final _pb = PocketBase('http://127.0.0.1:8090'); // Add focus nodes and hint states diff --git a/lib/presentation/routes/auth_routes/login_route.dart b/lib/presentation/routes/auth_routes/login_route.dart index 53bbf143..c7a386dd 100644 --- a/lib/presentation/routes/auth_routes/login_route.dart +++ b/lib/presentation/routes/auth_routes/login_route.dart @@ -25,13 +25,15 @@ import 'package:http/http.dart' as http; import '../../Screens/auth_verification/registration.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:uae_stat/config/api_config.dart'; import '../../components/indicators/locale_provider.dart'; import '../../components/my_toggle.dart'; class LoginRoute extends HookConsumerWidget { - final pb = PocketBase('https://pb.venbait.in'); + // final pb = PocketBase('https://pb.venbait.in'); + final pb = PocketBase(apiUrl); final FlutterSecureStorage _secureStorage = const FlutterSecureStorage(); // final _pb = PocketBase('http://127.0.0.1:8090'); // final bool isLoginScreen; // Pass `true` if this is the login screen @@ -342,7 +344,8 @@ class LoginRoute extends HookConsumerWidget { final userId = session.id; if (userId.isNotEmpty) { final url = - Uri.parse("https://pb.venbait.in/api/login_success?id=$userId"); + // Uri.parse("https://pb.venbait.in/api/login_success?id=$userId"); + Uri.parse('$apiUrl/api/login_success?id=$userId'); try { final response = await http.get(url); diff --git a/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart b/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart index 3a3bd377..61b1714e 100644 --- a/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart +++ b/lib/presentation/routes/bottom_bar_routes/tab_routes/home_route.dart @@ -167,6 +167,7 @@ import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:go_router/go_router.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/data/p_auth_repo.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; @@ -176,6 +177,7 @@ import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes. import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart'; import 'package:http/http.dart' as http; +import 'package:uae_stat/config/api_config.dart'; class MyHomePage extends ConsumerStatefulWidget { const MyHomePage({super.key}); @@ -344,7 +346,8 @@ class EconomyStatsWidget extends ConsumerStatefulWidget { class EconomyStatsState extends ConsumerState { List data = []; - final _pb = PocketBase('https://pb.venbait.in'); + // final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); bool isLoading = true; final GlobalKey cardTopicKey = GlobalKey(); @@ -1077,7 +1080,8 @@ class EconomyStatsState extends ConsumerState { // } Future fetchData(locale) async { - const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; + // const baseUrl = 'https://pb.venbait.in/api/getHomePageData'; + const baseUrl = '$apiUrl/api/getHomePageData'; try { final response = await http.get(Uri.parse(baseUrl + '?language=$locale')); if (response.statusCode == 200) { diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart index 3d472bf2..f4489c09 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart @@ -6,6 +6,7 @@ import 'package:dio/dio.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/bookmark_asset_path.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart'; @@ -21,7 +22,7 @@ class BookMark extends ConsumerStatefulWidget { } class _BookMarkState extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); List> dataList = []; bool isLoading = true; @@ -77,7 +78,7 @@ class _BookMarkState extends ConsumerState { } final response = await Dio().get( - 'https://pb.venbait.in/api/getUserBookmark', + '$apiUrl/api/getUserBookmark', queryParameters: {'user_id': userID, 'language': locale}, ); @@ -514,4 +515,4 @@ class TabBarHeader extends StatelessWidget { ), ); } -} \ No newline at end of file +} diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart b/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart index 7b291815..fd90a183 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/edit_profile.dart @@ -12,6 +12,7 @@ import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/config/my_theme.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; @@ -25,7 +26,7 @@ class EditProfile extends StatefulWidget { } class _EditProfileState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); // final _pb = PocketBase('http://127.0.0.1:8090'); bool _isProfileCompleted = false; bool _isLoading = false; @@ -203,7 +204,7 @@ class _EditProfileState extends State { if (avatarFilename.isNotEmpty && recordId.isNotEmpty) { _avatarUrl = - 'https://pb.venbait.in/api/files/$collectionId/$recordId/$avatarFilename'; + '$apiUrl/$collectionId/$recordId/$avatarFilename'; } else { _avatarUrl = ''; // Reset to default or empty } diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart b/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart index 5ea7e374..20830c6c 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/feedback.dart @@ -7,6 +7,7 @@ import 'package:intl/intl.dart'; import 'package:flutter_gen/gen_l10n/app_localizations.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/feedback_asset_path.dart'; @@ -30,7 +31,7 @@ class FeedbackForm extends StatefulWidget { class _FeedbackFormState extends State with WidgetsBindingObserver { final _pb = - PocketBase('https://pb.venbait.in'); // Initialize PocketBase client + PocketBase(apiUrl); // Initialize PocketBase client // final _pb = // PocketBase('http://127.0.0.1:8090'); // Initialize PocketBase client diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart b/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart index 164957bb..7113e72b 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/manage_users.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart'; import 'package:uae_stat/presentation/components/my_bottom_nav_bar.dart'; @@ -16,7 +17,7 @@ class ManageUserRouter extends StatefulWidget { } class _ManageUserRouterState extends State { - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); List userData = []; int _sortColumnIndex = 0; bool _isAscending = true; diff --git a/lib/presentation/routes/drawer_routes/Drawer Items/notification/notification.dart b/lib/presentation/routes/drawer_routes/Drawer Items/notification/notification.dart index 7fe036ed..c1b276cb 100644 --- a/lib/presentation/routes/drawer_routes/Drawer Items/notification/notification.dart +++ b/lib/presentation/routes/drawer_routes/Drawer Items/notification/notification.dart @@ -2,6 +2,7 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; +import 'package:uae_stat/config/api_config.dart'; import '../../custom_drawer_routes.dart'; class NotificationPage extends StatefulWidget { @@ -11,7 +12,7 @@ class NotificationPage extends StatefulWidget { class _NotificationPageState extends State { // Example notification data - final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); List> notifications = []; // Current selected tab index diff --git a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart index 96209340..322e04bc 100644 --- a/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart +++ b/lib/presentation/routes/drawer_routes/custom_drawer_routes.dart @@ -24,6 +24,7 @@ import 'package:uae_stat/presentation/components/my_toggle.dart'; import 'package:uae_stat/presentation/Screens/app_tour/Target_content.dart'; import 'package:uae_stat/presentation/components/indicators/locale_provider.dart'; import 'package:uae_stat/presentation/components/my_toggle.dart'; +import 'package:uae_stat/config/api_config.dart'; class BaseScaffold extends ConsumerStatefulWidget { const BaseScaffold({ @@ -58,7 +59,8 @@ class BaseScaffold extends ConsumerStatefulWidget { } class _BaseScaffoldState extends ConsumerState { - final _pb = PocketBase('https://pb.venbait.in'); + // final _pb = PocketBase('https://pb.venbait.in'); + final _pb = PocketBase(apiUrl); String _avatarUrl = ''; dynamic userId; String? userName; @@ -658,7 +660,7 @@ class _BaseScaffoldState extends ConsumerState { if (userAvatar!.isNotEmpty && recordId.isNotEmpty) { _avatarUrl = - 'https://pb.venbait.in/api/files/$collectionId/$recordId/$userAvatar'; + '$apiUrl/api/files/$collectionId/$recordId/$userAvatar'; } else { _avatarUrl = ''; // Reset to default or empty } @@ -704,7 +706,7 @@ class _BaseScaffoldState extends ConsumerState { title: Padding( padding: EdgeInsets.only(top: 10), child: Align( - alignment: Alignment.centerLeft, + alignment: (locale?.languageCode == 'ar') ? Alignment.centerRight : Alignment.centerLeft, child: DefaultTextStyle( style: TextStyle( color: widget.colorChange ? Colors.white : Color(0xFF414042), diff --git a/lib/presentation/routes/drawer_routes/feedback_route.dart b/lib/presentation/routes/drawer_routes/feedback_route.dart index d23f43fa..02cc918e 100644 --- a/lib/presentation/routes/drawer_routes/feedback_route.dart +++ b/lib/presentation/routes/drawer_routes/feedback_route.dart @@ -6,6 +6,7 @@ import 'package:go_router/go_router.dart'; import 'package:intl/intl.dart'; import 'package:pocketbase/pocketbase.dart'; import 'package:shared_preferences/shared_preferences.dart'; +import 'package:uae_stat/config/api_config.dart'; import 'package:uae_stat/domain/use_cases/language.dart'; import 'package:uae_stat/infrastructure/services/packages/go_router.dart'; import 'package:uae_stat/presentation/components/my_drawer.dart'; @@ -28,7 +29,7 @@ class FeedbackForm extends StatefulWidget { class _FeedbackFormState extends State with WidgetsBindingObserver { final _pb = - PocketBase('https://pb.venbait.in'); // Initialize PocketBase client + PocketBase(apiUrl); // Initialize PocketBase client // final _pb = // PocketBase('http://127.0.0.1:8090'); // Initialize PocketBase client diff --git a/pubspec.yaml b/pubspec.yaml index 092ea055..4248f8ff 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: uae_stat description: "View statistics about the UAE from the Federal Center for Statistics and Competitiveness." publish_to: "none" -version: 1.0.26+27 +version: 1.0.27+28 environment: sdk: ">=3.2.3 <4.0.0"