Saving local changes before pulling
@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) {
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = "26"
|
||||
flutterVersionCode = "28"
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||
if (flutterVersionName == null) {
|
||||
flutterVersionName = "1.0.25"
|
||||
flutterVersionName = "1.0.27"
|
||||
}
|
||||
|
||||
def keystorePropertiesFile = rootProject.file("key.properties")
|
||||
|
||||
10
assets/icons/enquiry/at.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2033_12443)">
|
||||
<path d="M13.7881 8.13281C13.7686 8.62109 13.6953 9.10449 13.5684 9.58301C13.4463 10.0566 13.2583 10.4888 13.0044 10.8794C12.7554 11.2651 12.4355 11.5752 12.0449 11.8096C11.6543 12.0391 11.1831 12.1538 10.6313 12.1538C10.3091 12.1538 10.021 12.0977 9.76709 11.9854C9.51318 11.873 9.30078 11.7119 9.12988 11.502C8.95898 11.2871 8.83447 11.0308 8.75635 10.7329C8.67822 10.4302 8.65137 10.0933 8.67578 9.72217L9.04932 5.54004H10.4263L10.0601 9.72217C10.0308 10.0005 10.0356 10.2275 10.0747 10.4033C10.1138 10.5791 10.1748 10.7158 10.2578 10.8135C10.3408 10.9062 10.436 10.9722 10.5435 11.0112C10.6558 11.0503 10.7656 11.0698 10.873 11.0698C11.1221 11.0698 11.3467 10.9966 11.5469 10.8501C11.752 10.6987 11.9277 10.4912 12.0742 10.2275C12.2207 9.96387 12.3354 9.65869 12.4185 9.31201C12.5015 8.96045 12.5503 8.58203 12.5649 8.17676C12.5942 7.50781 12.5601 6.89014 12.4624 6.32373C12.3696 5.75732 12.2085 5.25195 11.979 4.80762C11.7495 4.36328 11.4517 3.9873 11.0854 3.67969C10.7192 3.36719 10.2847 3.12793 9.78174 2.96191C9.27881 2.7959 8.7002 2.71289 8.0459 2.71289C7.44531 2.71289 6.89111 2.80811 6.3833 2.99854C5.87549 3.18408 5.41895 3.4502 5.01367 3.79688C4.61328 4.14355 4.26904 4.55859 3.98096 5.04199C3.69287 5.52539 3.46582 6.06494 3.2998 6.66064C3.13867 7.25635 3.04346 7.89355 3.01416 8.57227C2.97998 9.29004 3.0166 9.94434 3.12402 10.5352C3.23633 11.1211 3.41455 11.6387 3.65869 12.0879C3.90771 12.5371 4.22021 12.9155 4.59619 13.2231C4.97217 13.5308 5.40918 13.7627 5.90723 13.9189C6.40527 14.0752 6.95703 14.1533 7.5625 14.1533C7.9873 14.1533 8.41943 14.1045 8.85889 14.0068C9.30322 13.9092 9.67676 13.7847 9.97949 13.6333L10.2578 14.666C9.91602 14.8857 9.48877 15.0493 8.97607 15.1567C8.46826 15.2642 7.9873 15.3179 7.5332 15.3179C6.7666 15.3179 6.06592 15.2227 5.43115 15.0322C4.80127 14.8418 4.24463 14.5586 3.76123 14.1826C3.27783 13.8066 2.875 13.3477 2.55273 12.8057C2.23047 12.2637 1.99365 11.6387 1.84229 10.9307C1.69092 10.2227 1.63232 9.43652 1.6665 8.57227C1.70068 7.77148 1.82275 7.01953 2.03271 6.31641C2.24268 5.6084 2.5332 4.96631 2.9043 4.39014C3.27539 3.81396 3.71729 3.31836 4.22998 2.90332C4.74756 2.4834 5.32861 2.16113 5.97314 1.93652C6.61768 1.71191 7.31836 1.59961 8.0752 1.59961C8.83691 1.59961 9.52783 1.69971 10.1479 1.8999C10.7681 2.1001 11.3125 2.38818 11.7812 2.76416C12.25 3.14014 12.6382 3.59668 12.9458 4.13379C13.2534 4.6709 13.478 5.27637 13.6196 5.9502C13.7612 6.61914 13.8174 7.34668 13.7881 8.13281ZM6.36865 8.87256C6.33936 9.19482 6.33936 9.48535 6.36865 9.74414C6.39795 9.99805 6.4541 10.2104 6.53711 10.3813C6.625 10.5522 6.73975 10.6841 6.88135 10.7769C7.02295 10.8647 7.18896 10.9087 7.37939 10.9087C7.4917 10.9087 7.61377 10.8818 7.74561 10.8281C7.87744 10.7695 8.00684 10.6768 8.13379 10.5498C8.26562 10.418 8.39014 10.2422 8.50732 10.0225C8.62939 9.79785 8.73193 9.51709 8.81494 9.18018L9.40088 9.86865C9.28857 10.2446 9.14697 10.5742 8.97607 10.8574C8.81006 11.1406 8.61963 11.3774 8.40479 11.5679C8.18994 11.7583 7.95801 11.9023 7.70898 12C7.45996 12.0928 7.19873 12.1392 6.92529 12.1392C6.56885 12.1392 6.25146 12.061 5.97314 11.9048C5.69482 11.7485 5.46533 11.5288 5.28467 11.2456C5.104 10.9575 4.97461 10.6133 4.89648 10.2129C4.81836 9.8125 4.80371 9.36572 4.85254 8.87256C4.90625 8.36963 5.00146 7.90576 5.13818 7.48096C5.27979 7.05127 5.45557 6.66797 5.66553 6.33105C5.87549 5.99414 6.1123 5.7085 6.37598 5.47412C6.64453 5.23486 6.93262 5.0542 7.24023 4.93213C7.55273 4.81006 7.87744 4.74902 8.21436 4.74902C8.771 4.74902 9.20801 4.82959 9.52539 4.99072C9.84277 5.14697 10.1431 5.33008 10.4263 5.54004L9.7085 6.48486C9.56689 6.35303 9.38135 6.22852 9.15186 6.11133C8.92725 5.98926 8.65869 5.92822 8.34619 5.92822C8.06299 5.92822 7.80908 5.9917 7.58447 6.11865C7.36475 6.24561 7.17188 6.43359 7.00586 6.68262C6.83984 6.93164 6.70312 7.23926 6.5957 7.60547C6.48828 7.9668 6.4126 8.38916 6.36865 8.87256Z" fill="#878787"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2033_12443">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.0 KiB |
3
assets/icons/enquiry/building.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M12.6667 2.00033V14.0003H8.66667V11.667H7.33333V14.0003H3.33333V2.00033H12.6667ZM10 4.66699H11.3333V3.33366H10V4.66699ZM7.33333 4.66699H8.66667V3.33366H7.33333V4.66699ZM4.66667 4.66699H6V3.33366H4.66667V4.66699ZM10 7.33366H11.3333V6.00033H10V7.33366ZM7.33333 7.33366H8.66667V6.00033H7.33333V7.33366ZM4.66667 7.33366H6V6.00033H4.66667V7.33366ZM10 10.0003H11.3333V8.66699H10V10.0003ZM7.33333 10.0003H8.66667V8.66699H7.33333V10.0003ZM4.66667 10.0003H6V8.66699H4.66667V10.0003ZM10 12.667H11.3333V11.3337H10V12.667ZM4.66667 12.667H6V11.3337H4.66667V12.667ZM14 0.666992H2V15.3337H14V0.666992Z" fill="#878787"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 717 B |
3
assets/icons/enquiry/fax.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M5.02552 12.9998V6.33314H5.53818V3.23047H11.5382V6.33314H13.6915V12.9998H5.02552ZM1.92285 13.6665H4.51218V5.66647H1.92285V13.6665ZM6.20485 6.33314H10.8715V3.89714H6.20485V6.33314ZM6.02485 11.3331H8.69152V7.9998H6.02485V11.3331ZM9.35818 9.33314H10.6915V7.9998H9.35818V9.33314ZM11.2302 9.33314H12.5635V7.9998H11.2302V9.33314ZM9.35818 11.3331H10.6915V9.9998H9.35818V11.3331ZM11.2302 11.3331H12.5635V9.9998H11.2302V11.3331Z" fill="#878787"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 550 B |
10
assets/icons/enquiry/map.svg
Normal file
@ -0,0 +1,10 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g clip-path="url(#clip0_2033_12439)">
|
||||
<path d="M4.57143 0C4.64881 0 4.71577 0.0282738 4.77232 0.0848214C4.82887 0.141369 4.85714 0.208333 4.85714 0.285714V13.4286C4.85714 13.5476 4.80655 13.631 4.70536 13.6786L0.419643 15.9643C0.377976 15.9881 0.333333 16 0.285714 16C0.208333 16 0.141369 15.9717 0.0848214 15.9152C0.0282738 15.8586 0 15.7917 0 15.7143V2.57143C0 2.45238 0.0505952 2.36905 0.151786 2.32143L4.4375 0.0357143C4.47917 0.0119048 4.52381 0 4.57143 0ZM15.7143 0C15.7917 0 15.8586 0.0282738 15.9152 0.0848214C15.9717 0.141369 16 0.208333 16 0.285714V13.4286C16 13.5476 15.9494 13.631 15.8482 13.6786L11.5625 15.9643C11.5208 15.9881 11.4762 16 11.4286 16C11.3512 16 11.2842 15.9717 11.2277 15.9152C11.1711 15.8586 11.1429 15.7917 11.1429 15.7143V2.57143C11.1429 2.45238 11.1935 2.36905 11.2946 2.32143L15.5804 0.0357143C15.622 0.0119048 15.6667 0 15.7143 0ZM5.71429 0C5.76191 0 5.80357 0.00892857 5.83929 0.0267857L10.4107 2.3125C10.5179 2.37202 10.5714 2.45833 10.5714 2.57143V15.7143C10.5714 15.7917 10.5432 15.8586 10.4866 15.9152C10.4301 15.9717 10.3631 16 10.2857 16C10.2381 16 10.1964 15.9911 10.1607 15.9732L5.58929 13.6875C5.48214 13.628 5.42857 13.5417 5.42857 13.4286V0.285714C5.42857 0.208333 5.45685 0.141369 5.51339 0.0848214C5.56994 0.0282738 5.63691 0 5.71429 0Z" fill="#878787"/>
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="clip0_2033_12439">
|
||||
<rect width="16" height="16" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
3
assets/icons/enquiry/phone.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1 3C1 2.46957 1.21071 1.96086 1.58579 1.58579C1.96086 1.21071 2.46957 1 3 1H3.91467C4.488 1 4.988 1.39067 5.12733 1.94667L5.864 4.89533C5.92325 5.13401 5.91098 5.38484 5.82871 5.61659C5.74644 5.84834 5.59781 6.05077 5.40133 6.19867L4.53933 6.84533C4.44933 6.91267 4.43 7.01133 4.45533 7.08C4.83178 8.10312 5.426 9.03226 6.19687 9.80313C6.96774 10.574 7.89688 11.1682 8.92 11.5447C8.98867 11.57 9.08667 11.5507 9.15467 11.4607L9.80133 10.5987C9.94923 10.4022 10.1517 10.2536 10.3834 10.1713C10.6152 10.089 10.866 10.0767 11.1047 10.136L14.0533 10.8727C14.6093 11.012 15 11.512 15 12.086V13C15 13.5304 14.7893 14.0391 14.4142 14.4142C14.0391 14.7893 13.5304 15 13 15H11.5C5.70133 15 1 10.2987 1 4.5V3Z" fill="#878787"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 871 B |
3
assets/icons/misc/Search.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M23.1191 21.8809L17.6427 16.4056C19.2299 14.5 20.0214 12.0558 19.8525 9.58143C19.6836 7.10709 18.5672 4.79313 16.7357 3.12091C14.9041 1.4487 12.4984 0.546971 10.0189 0.603321C7.53944 0.65967 5.17715 1.66976 3.42345 3.42345C1.66976 5.17715 0.65967 7.53944 0.603321 10.0189C0.546971 12.4984 1.4487 14.9041 3.12091 16.7357C4.79313 18.5672 7.10709 19.6836 9.58143 19.8525C12.0558 20.0214 14.5 19.2299 16.4056 17.6427L21.8809 23.1191C21.9622 23.2004 22.0588 23.2649 22.165 23.3088C22.2712 23.3528 22.385 23.3755 22.5 23.3755C22.615 23.3755 22.7288 23.3528 22.835 23.3088C22.9413 23.2649 23.0378 23.2004 23.1191 23.1191C23.2004 23.0378 23.2649 22.9413 23.3088 22.835C23.3528 22.7288 23.3755 22.615 23.3755 22.5C23.3755 22.385 23.3528 22.2712 23.3088 22.165C23.2649 22.0588 23.2004 21.9622 23.1191 21.8809ZM2.37501 10.25C2.37501 8.69248 2.83687 7.16993 3.70218 5.87489C4.5675 4.57985 5.79741 3.57049 7.23637 2.97445C8.67534 2.37841 10.2587 2.22246 11.7863 2.52632C13.3139 2.83018 14.7171 3.5802 15.8185 4.68154C16.9198 5.78288 17.6698 7.18607 17.9737 8.71367C18.2775 10.2413 18.1216 11.8247 17.5256 13.2636C16.9295 14.7026 15.9202 15.9325 14.6251 16.7978C13.3301 17.6631 11.8075 18.125 10.25 18.125C8.16214 18.1227 6.16044 17.2923 4.6841 15.8159C3.20775 14.3396 2.37732 12.3379 2.37501 10.25Z" fill="#9EA2A9"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.4 KiB |
3
assets/icons/uae_numbers/Filter.svg
Normal file
@ -0,0 +1,3 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M3.125 3L10.325 11.6637V18.1683L13.925 20V11.6637L21.125 3H3.125Z" stroke="white" stroke-width="2" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 237 B |
3
lib/config/api_config.dart
Normal file
@ -0,0 +1,3 @@
|
||||
// api_config.dart
|
||||
// const String apiUrl = 'http://192.168.1.26:8090';
|
||||
const String apiUrl = 'https://pbdev.venbait.in/';
|
||||
@ -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';
|
||||
@ -304,6 +306,7 @@ import 'package:uae_stat/presentation/Screens/charts/chart.dart';
|
||||
import 'package:uae_stat/presentation/Screens/charts/screens/chart_screen.dart';
|
||||
import 'package:uae_stat/presentation/Screens/demo_home2.dart';
|
||||
import 'package:uae_stat/presentation/Screens/online_offline_verification/internet_check.dart';
|
||||
import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/contactUs.dart';
|
||||
import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/notification/notification.dart';
|
||||
import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/AboutTheApp/AboutFCSC.dart';
|
||||
import 'package:uae_stat/presentation/routes/drawer_routes/Drawer%20Items/user_guide/AboutTheApp/getStarted.dart';
|
||||
@ -414,11 +417,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<Map<String, dynamic>> filterData = [];
|
||||
|
||||
if (state.uri.queryParameters.containsKey('filter_data') &&
|
||||
state.uri.queryParameters['filter_data']!.isNotEmpty) {
|
||||
try {
|
||||
filterData = List<Map<String, dynamic>>.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 +452,8 @@ final GoRouter router = GoRouter(
|
||||
mainTopic: mainTopic,
|
||||
title: title,
|
||||
keyParam: key,
|
||||
kpi: kpi,
|
||||
filter_data: filterData,
|
||||
);
|
||||
},
|
||||
),
|
||||
@ -605,5 +632,10 @@ final GoRouter router = GoRouter(
|
||||
path: '/marriages',
|
||||
builder: (context, state) => Marriages(),
|
||||
),
|
||||
|
||||
GoRoute(
|
||||
path: '/contact',
|
||||
builder: (context, state) => Contact(),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@ -0,0 +1,8 @@
|
||||
abstract class EnquiryAssetIconPath {
|
||||
static const _basePath = 'assets/icons/enquiry';
|
||||
static const at = '$_basePath/at.svg';
|
||||
static const building = '$_basePath/building.svg';
|
||||
static const fax = '$_basePath/fax.svg';
|
||||
static const map = '$_basePath/map.svg';
|
||||
static const phone = '$_basePath/phone.svg';
|
||||
}
|
||||
@ -12,5 +12,5 @@ abstract class MiscIconAssetPath {
|
||||
static const save = '$_basePath/save.png';
|
||||
static const group = '$_basePath/group.png';
|
||||
static const search = '$_basePath/search.png';
|
||||
|
||||
static const Search = '$_basePath/Search.svg';
|
||||
}
|
||||
|
||||
@ -6,5 +6,6 @@ abstract class UaeNumbersAssetPath {
|
||||
// static const bookmarksSelectedUae = '$_basePath/bookmarksSelectedUae.png';
|
||||
// static const shareUae = '$_basePath/share.png';
|
||||
static const share = '$_basePath/share.svg';
|
||||
static const filterUae = '$_basePath/filters.png';
|
||||
static const filterUae = '$_basePath/filters.png';
|
||||
static const filterCharts = '$_basePath/Filter.svg';
|
||||
}
|
||||
|
||||
@ -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');
|
||||
|
||||
@ -1,4 +1,10 @@
|
||||
{
|
||||
"all_bookmarks":"كل العلامات المرجعية",
|
||||
"economy_title":"اقتصاد",
|
||||
"social_title":"اجتماعي",
|
||||
"environment_title":"بيئة",
|
||||
"bookmarks": "الإشارات المرجعية",
|
||||
|
||||
"feedback_title": "تعليق",
|
||||
"feedback_failed_msg": "لم يتم إرسال تعليقاتك. يرجى المحاولة مرة أخرى.",
|
||||
"thankYou": "شكراً",
|
||||
|
||||
@ -1,7 +1,11 @@
|
||||
{
|
||||
"all_bookmarks":"All Bookmarks",
|
||||
"economy_title":"Economy",
|
||||
"social_title":"Social",
|
||||
"environment_title":"Environment",
|
||||
"bookmarks": "Bookmarks",
|
||||
|
||||
|
||||
"feedback_title": "Feedback",
|
||||
"feedback_title": "Feedback",
|
||||
"feedback_failed_msg": "Your feedback could not be \n submitted. Please try again",
|
||||
"thankYou": "Thank you",
|
||||
"feedback_message": "For your valuable feedback, we truly appreciate your input!",
|
||||
|
||||
@ -15,6 +15,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();
|
||||
@ -88,6 +90,8 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
|
||||
void main() async {
|
||||
WidgetsFlutterBinding.ensureInitialized();
|
||||
configureDependencies();
|
||||
@ -100,10 +104,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<bool>((ref) {
|
||||
return true; // Replace with actual logic
|
||||
});
|
||||
|
||||
|
||||
// ref.listen<bool>(connectivityProvider, (previous, hasInternet) {
|
||||
// print('Previous Internet Status: $previous');
|
||||
// print('Current Internet Status: $hasInternet');
|
||||
|
||||
@ -2,6 +2,7 @@ import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:go_router/go_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';
|
||||
@ -10,6 +11,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 +86,7 @@ class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
|
||||
|
||||
Future<void> 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) {
|
||||
@ -197,11 +200,13 @@ class _UaenumberWidgetState extends ConsumerState<uaenumberWidget> {
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search",
|
||||
hintStyle: TextStyle(color: Color(0xFF898C81)),
|
||||
|
||||
prefixIcon: Image(
|
||||
image: ExactAssetImage(MiscIconAssetPath.search),
|
||||
width: 24,
|
||||
height: 24,
|
||||
prefixIconConstraints: BoxConstraints(maxWidth: 42, maxHeight: 42),
|
||||
prefixIcon: Container(
|
||||
padding: EdgeInsets.only(right: 5),
|
||||
child: SvgPicture.asset(
|
||||
MiscIconAssetPath.Search,
|
||||
semanticsLabel: 'Search',
|
||||
),
|
||||
),
|
||||
|
||||
// prefixIcon: Image.asset(
|
||||
|
||||
@ -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<Changepassword> {
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
final _pb = PocketBase(apiUrl);
|
||||
// final pb = PocketBase('http://127.0.0.1:8090');
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
final _emailController = TextEditingController();
|
||||
@ -46,7 +47,7 @@ class _ResetPasswordScreenState extends State<Changepassword> {
|
||||
// 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<Changepassword> {
|
||||
// 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',
|
||||
|
||||
@ -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<ConfirmPassword> {
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
final _pb = PocketBase(apiUrl);
|
||||
// final pb = PocketBase('http://127.0.0.1:8090');
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
bool _obscurePassword = true;
|
||||
|
||||
@ -3,8 +3,10 @@ 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/banner_asset_path.dart';
|
||||
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/misc_icon_asset_path.dart';
|
||||
import 'package:uae_stat/presentation/Screens/profilepage.dart';
|
||||
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
|
||||
@ -12,7 +14,7 @@ import 'package:uae_stat/presentation/components/my_toggle.dart';
|
||||
import 'package:uae_stat/presentation/components/space.dart';
|
||||
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
import '../../../config/my_theme.dart';
|
||||
import 'package:uae_stat/config/my_theme.dart';
|
||||
|
||||
class CreateNewPw extends ConsumerStatefulWidget {
|
||||
final String userId;
|
||||
@ -26,17 +28,22 @@ class CreateNewPw extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _CreateNewPwState extends ConsumerState<CreateNewPw> {
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
final _pb = PocketBase(apiUrl);
|
||||
final _formKey = GlobalKey<FormState>();
|
||||
bool _obscureOldPassword = true;
|
||||
bool _obscureNewPassword = true;
|
||||
bool _obscureConfirmPassword = true;
|
||||
bool _isPasswordUpdated = false; // Variable to toggle UI
|
||||
|
||||
bool hasValidated = false;
|
||||
String? _oldPassword;
|
||||
String? _newPassword;
|
||||
String? _confirmPassword;
|
||||
|
||||
final fcscBanner = Image.asset(
|
||||
BannerAssetPath.fcsc,
|
||||
height: 40,
|
||||
);
|
||||
|
||||
String? _validateOldPassword(String? value) {
|
||||
if (value == null || value.isEmpty) {
|
||||
return AppLocalizations.of(context)!.old_password_is_required;
|
||||
@ -242,10 +249,12 @@ class _CreateNewPwState extends ConsumerState<CreateNewPw> {
|
||||
pathColorWhenOn: Colors.grey.shade300,
|
||||
pathColorWhenOff: Colors.grey.shade300,
|
||||
onTap: () {
|
||||
print('has validated $hasValidated');
|
||||
final formState = _formKey.currentState;
|
||||
ref.read(localeProvider.notifier).toggleLocale();
|
||||
Future.delayed(Duration(milliseconds: 100), () {
|
||||
if (formState?.validate() == false) {
|
||||
if (hasValidated && formState?.validate() == false) {
|
||||
print('has validated $hasValidated');
|
||||
formState?.validate();
|
||||
}
|
||||
});
|
||||
@ -581,6 +590,9 @@ class _CreateNewPwState extends ConsumerState<CreateNewPw> {
|
||||
width: screenWidth / 1.1,
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
setState(() {
|
||||
hasValidated=true;
|
||||
});
|
||||
if ((_formKey.currentState?.validate() ?? false)) {
|
||||
await updatePassword(
|
||||
widget.userId,
|
||||
@ -618,16 +630,17 @@ class _CreateNewPwState extends ConsumerState<CreateNewPw> {
|
||||
),
|
||||
SizedBox(height: screenHeight / 5),
|
||||
Center(
|
||||
child: Container(
|
||||
height: screenHeight / 16,
|
||||
width: screenWidth / 2.5,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage("assets/splash_screen/logo.png"),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
),
|
||||
// child: Container(
|
||||
// height: screenHeight / 16,
|
||||
// width: screenWidth / 2.5,
|
||||
// decoration: BoxDecoration(
|
||||
// image: DecorationImage(
|
||||
// image: AssetImage("assets/splash_screen/logo.png"),
|
||||
// fit: BoxFit.fill,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
child: fcscBanner,
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -712,16 +725,17 @@ class _CreateNewPwState extends ConsumerState<CreateNewPw> {
|
||||
),
|
||||
SizedBox(height: screenHeight / 2.2),
|
||||
Center(
|
||||
child: Container(
|
||||
height: 40,
|
||||
width: screenWidth / 2.5,
|
||||
decoration: BoxDecoration(
|
||||
image: DecorationImage(
|
||||
image: AssetImage("assets/splash_screen/logo.png"),
|
||||
fit: BoxFit.fill,
|
||||
),
|
||||
),
|
||||
),
|
||||
// child: Container(
|
||||
// height: 40,
|
||||
// width: screenWidth / 2.5,
|
||||
// decoration: BoxDecoration(
|
||||
// image: DecorationImage(
|
||||
// image: AssetImage("assets/splash_screen/logo.png"),
|
||||
// fit: BoxFit.fill,
|
||||
// ),
|
||||
// ),
|
||||
// ),
|
||||
child: fcscBanner,
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@ -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<EmailVerificationScreen> {
|
||||
// final pb = PocketBase('http://127.0.0.1:8090');
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
final _pb = PocketBase(apiUrl);
|
||||
final List<TextEditingController> _otpControllers =
|
||||
List.generate(4, (_) => TextEditingController());
|
||||
int _secondsRemaining = 120; // 2 minutes timer
|
||||
|
||||
@ -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';
|
||||
@ -27,7 +28,7 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
|
||||
final _emailController = TextEditingController();
|
||||
final _passwordController = TextEditingController();
|
||||
final _confirmpasswordController = TextEditingController();
|
||||
|
||||
bool hasValidated = false;
|
||||
bool _obscurePassword = true;
|
||||
bool _obscureConfirmPassword = true;
|
||||
bool isChecked = false;
|
||||
@ -38,7 +39,7 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
|
||||
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
|
||||
@ -216,6 +217,9 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
|
||||
}
|
||||
|
||||
Future<void> _registerUser() async {
|
||||
setState(() {
|
||||
hasValidated = true;
|
||||
});
|
||||
if (_formKey.currentState?.validate() ?? false) {
|
||||
if (isChecked) {
|
||||
setState(() {
|
||||
@ -386,7 +390,7 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
|
||||
final formState = _formKey.currentState;
|
||||
ref.read(localeProvider.notifier).toggleLocale();
|
||||
Future.delayed(Duration(milliseconds: 100), () {
|
||||
if (formState?.validate() == false) {
|
||||
if (hasValidated && formState?.validate() == false) {
|
||||
formState?.validate();
|
||||
}
|
||||
});
|
||||
@ -1110,11 +1114,11 @@ class _RegisterScreenState extends ConsumerState<RegisterScreen> {
|
||||
?.languageCode ==
|
||||
'ar'
|
||||
? 0
|
||||
: 30.0,
|
||||
: 40.0,
|
||||
right: registerLocale
|
||||
?.languageCode ==
|
||||
'ar'
|
||||
? 40
|
||||
? 45
|
||||
: 0.0,),
|
||||
child: Text(
|
||||
context.translate('Required', 'مطلوب'),
|
||||
|
||||
@ -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<Map<String, dynamic>> fetchChartData(String dataSets, locale) async {
|
||||
Future<Map<String, dynamic>> fetchChartData(String dataSets, locale,kpi,
|
||||
List<Map<String, dynamic>> filterData) async {
|
||||
List<dynamic> isChartData = [];
|
||||
List<dynamic> nonChartData = [];
|
||||
List<dynamic> originalChartsData = [];
|
||||
List<dynamic> 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<String, dynamic> 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<String, dynamic> jsonData = jsonDecode(response.body);
|
||||
// Variables to store filtered data
|
||||
|
||||
@ -34,7 +34,7 @@ class ChartWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
String formatNumberConversion(
|
||||
double value, String chartConversion, String numberFormat) {
|
||||
double value, String chartConversion, String numberFormat,) {
|
||||
// Convert the input value to base unit (actual value)
|
||||
double baseValue = value;
|
||||
|
||||
@ -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<PieChartSectionData> 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,
|
||||
),
|
||||
),
|
||||
@ -175,16 +188,15 @@ class ChartWidget extends StatelessWidget {
|
||||
message: title, // Full text on hover
|
||||
child: ConstrainedBox(
|
||||
// Constrain width to allow wrapping
|
||||
constraints: BoxConstraints(maxWidth: 130),
|
||||
constraints: BoxConstraints(maxWidth: 200),
|
||||
child: Text(
|
||||
title,
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
),
|
||||
softWrap: true,
|
||||
maxLines: 2,
|
||||
overflow:
|
||||
TextOverflow.ellipsis, // Ensures text doesn't overflow
|
||||
// softWrap: true,
|
||||
// maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis, // Ensures text doesn't overflow
|
||||
),
|
||||
),
|
||||
),
|
||||
@ -365,31 +377,39 @@ class ChartWidget extends StatelessWidget {
|
||||
},
|
||||
),
|
||||
),
|
||||
SizedBox(height: 105),
|
||||
SizedBox(height: 45),
|
||||
Expanded(
|
||||
// child: SingleChildScrollView(
|
||||
// scrollDirection: Axis.horizontal,
|
||||
//
|
||||
|
||||
child: SingleChildScrollView(
|
||||
scrollDirection: Axis.vertical,
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
constraints:
|
||||
BoxConstraints(minHeight: 3), // Allow dynamic height
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 0.0, right: 0.0, bottom: 8.0, top: 1.0),
|
||||
child: Wrap(
|
||||
spacing: 2,
|
||||
runSpacing: 5,
|
||||
children:
|
||||
generateIndicators(chartData, chartData['group_by']),
|
||||
// child: SingleChildScrollView(
|
||||
// scrollDirection: Axis.vertical,
|
||||
child: Center(
|
||||
child: Container(
|
||||
width: double.infinity,
|
||||
constraints:
|
||||
BoxConstraints(minHeight: 3), // Allow dynamic height
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(
|
||||
left: 2.0, right: 2.0, bottom: 8.0, top: 1.0),
|
||||
child: Column( // Change Row to Column
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: generateIndicators(chartData, chartData['group_by']),
|
||||
),
|
||||
|
||||
|
||||
// child: Wrap(
|
||||
// spacing: 2,
|
||||
// runSpacing: 5,
|
||||
// children:
|
||||
// generateIndicators(chartData, chartData['group_by']),
|
||||
// ),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
// ),
|
||||
],
|
||||
);
|
||||
case 'fl_stacked_bar':
|
||||
@ -397,6 +417,7 @@ class ChartWidget extends StatelessWidget {
|
||||
List<String> groupByValuesList = groupByValues.toList();
|
||||
int chunkSize = 5;
|
||||
List<List<String>> chunkedGroupByValues = [];
|
||||
print('flStackedBar1');
|
||||
for (int i = 0; i < groupByValuesList.length; i += chunkSize) {
|
||||
chunkedGroupByValues.add(
|
||||
groupByValuesList.sublist(
|
||||
@ -445,6 +466,8 @@ class ChartWidget extends StatelessWidget {
|
||||
getTooltipItem:
|
||||
(groupData, groupIndex, rodData, rodIndex) {
|
||||
// Get the list of group names dynamically
|
||||
|
||||
|
||||
List<String> groupNames = [];
|
||||
for (var entry in chartData['response']) {
|
||||
String groupValue = entry['ObsKey'][groupByKey];
|
||||
@ -452,7 +475,6 @@ class ChartWidget extends StatelessWidget {
|
||||
groupNames.add(groupValue);
|
||||
}
|
||||
}
|
||||
|
||||
// Accessing the stacked rod items and calculating the tooltip text
|
||||
List<BarChartRodStackItem> rodStackItems =
|
||||
rodData.rodStackItems;
|
||||
@ -479,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(
|
||||
@ -568,10 +592,11 @@ class ChartWidget extends StatelessWidget {
|
||||
),
|
||||
textStyle: TextStyle(color: Colors.white),
|
||||
child: Text(
|
||||
group.length > 10
|
||||
? '${group.substring(0, 10)}...'
|
||||
: group,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
group,
|
||||
// group.length > 10
|
||||
// ? '${group.substring(0, 10)}...'
|
||||
// : group,
|
||||
// overflow: TextOverflow.ellipsis,
|
||||
style: TextStyle(fontSize: 11),
|
||||
),
|
||||
)
|
||||
@ -674,18 +699,8 @@ class ChartWidget extends StatelessWidget {
|
||||
} else if (RegExp(r'^\d{4}-[A-Za-z]{3}$').hasMatch(timePeriod)) {
|
||||
// Year-MonthAbbr (2019-Nov)
|
||||
Map<String, int> 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<String> parts = timePeriod.split('-');
|
||||
@ -943,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<LineChartBarData> lineBars = lineBarsData2(filteredData);
|
||||
|
||||
|
||||
|
||||
return Column(children: [
|
||||
Text(
|
||||
chartData['chart_heading'] ?? '',
|
||||
@ -971,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(),
|
||||
@ -1219,7 +1237,7 @@ class ChartWidget extends StatelessWidget {
|
||||
}
|
||||
return Container();
|
||||
},
|
||||
reservedSize: 80,
|
||||
reservedSize: 110,
|
||||
),
|
||||
),
|
||||
topTitles: AxisTitles(
|
||||
@ -1245,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],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
))
|
||||
@ -1260,8 +1278,36 @@ class ChartWidget extends StatelessWidget {
|
||||
// Extract groupBy values and their corresponding y-axis values
|
||||
List<String> xAxisData = [];
|
||||
List<double> yAxisData = [];
|
||||
List<Map<String, dynamic>> 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<Map<String, dynamic>> 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) {
|
||||
@ -1269,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(
|
||||
@ -1416,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<String, List<String>> groupedCrops = {};
|
||||
@ -1454,6 +1506,8 @@ class ChartWidget extends StatelessWidget {
|
||||
//
|
||||
// print('groupedCropsflmutli- $groupedCrops');
|
||||
|
||||
print('hormulti_bar');
|
||||
|
||||
return Center(
|
||||
child: Column(children: [
|
||||
Text(
|
||||
@ -1495,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 =
|
||||
@ -1506,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(
|
||||
@ -1521,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,
|
||||
)),
|
||||
),
|
||||
@ -1965,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;
|
||||
|
||||
@ -1972,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;
|
||||
}
|
||||
}
|
||||
@ -1988,6 +2042,7 @@ class ChartWidget extends StatelessWidget {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// Add a line for the ratio data
|
||||
lineBars.add(
|
||||
LineChartBarData(
|
||||
@ -2097,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();
|
||||
|
||||
@ -2186,7 +2256,7 @@ class ChartWidget extends StatelessWidget {
|
||||
}
|
||||
|
||||
FlTitlesData titlesData1(Set<double> xValues) {
|
||||
print('tileDATa1xvalue - $xValues');
|
||||
print('tileDATa1xvalueline2 - $xValues');
|
||||
|
||||
double findClosest(double value, Set<double> values) {
|
||||
return values
|
||||
@ -2201,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';
|
||||
@ -2227,12 +2300,16 @@ class ChartWidget extends StatelessWidget {
|
||||
_lastFormattedValue = formattedValue;
|
||||
|
||||
// print('formattedValueLine - $formattedValue');
|
||||
return Text(formattedValue, style: TextStyle(fontSize: 10));
|
||||
return Text(formattedValue, textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 10,
|
||||
|
||||
));
|
||||
}
|
||||
return const SizedBox.shrink();
|
||||
|
||||
// return Text(
|
||||
// formattedValue,
|
||||
// 'LINETRENTD2',
|
||||
// style: TextStyle(color: Colors.black, fontSize: 12),
|
||||
// );
|
||||
},
|
||||
@ -2244,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(
|
||||
@ -2309,12 +2386,26 @@ class ChartWidget extends StatelessWidget {
|
||||
List<BarChartGroupData> _generateBarGroups(
|
||||
BuildContext context, dynamic chartData, String groupByKey) {
|
||||
Map<String, Map<String, double>> 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');
|
||||
@ -2323,6 +2414,7 @@ class ChartWidget extends StatelessWidget {
|
||||
if (!groupedData.containsKey(groupValue)) {
|
||||
groupedData[groupValue] = {};
|
||||
}
|
||||
|
||||
if (!groupedData[groupValue]!.containsKey(timePeriod)) {
|
||||
groupedData[groupValue]![timePeriod] = 0.0;
|
||||
}
|
||||
@ -2335,6 +2427,7 @@ class ChartWidget extends StatelessWidget {
|
||||
List<String> timePeriods = groupedData.values.first.keys.toList();
|
||||
print('timePeriods $timePeriods');
|
||||
|
||||
|
||||
// double barWidth = calculateBarWidth(context, timePeriods.length);
|
||||
|
||||
// For each time period, generate a BarChartGroupData
|
||||
@ -2348,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(
|
||||
@ -2374,8 +2466,7 @@ class ChartWidget extends StatelessWidget {
|
||||
width: 20,
|
||||
// width: barWidth,
|
||||
borderRadius: BorderRadius.zero,
|
||||
color:
|
||||
Colors.black // This will act as a container for stacked items
|
||||
color: Colors.black // This will act as a container for stacked items
|
||||
),
|
||||
],
|
||||
);
|
||||
@ -2485,11 +2576,17 @@ class ChartWidget extends StatelessWidget {
|
||||
|
||||
double _calculateMaxY(dynamic chartData) {
|
||||
// Dynamically calculate the maximum Y value
|
||||
|
||||
print('hormulti_bar2');
|
||||
|
||||
List<dynamic> 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;
|
||||
}
|
||||
@ -2503,6 +2600,9 @@ class ChartWidget extends StatelessWidget {
|
||||
List<dynamic> responseData = chartData['response'];
|
||||
List<BarChartGroupData> 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);
|
||||
@ -2517,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<Color> uniqueColorsForTwo = [
|
||||
Color(0xFF648CBA),
|
||||
Color(0xFF90B0D5),
|
||||
|
||||
@ -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,9 +35,9 @@ class ProfileScreen extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
final _pb = PocketBase(apiUrl);
|
||||
// final _pb = PocketBase('http://127.0.0.1:8090');
|
||||
|
||||
bool hasValidated = false;
|
||||
// Add focus nodes and hint states
|
||||
final List<FocusNode> _focusNodes = List.generate(4, (_) => FocusNode());
|
||||
final List<bool> _showHints = [
|
||||
@ -456,6 +457,7 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final profileLocale = ref.watch(localeProvider);
|
||||
return PopScope(
|
||||
canPop: false, // Allow back navigation only if not login screen
|
||||
onPopInvokedWithResult: (didPop, result) {
|
||||
@ -488,7 +490,13 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||
pathColorWhenOn: Colors.grey.shade300,
|
||||
pathColorWhenOff: Colors.grey.shade300,
|
||||
onTap: () {
|
||||
final formState = _formKey.currentState;
|
||||
ref.read(localeProvider.notifier).toggleLocale();
|
||||
Future.delayed(Duration(milliseconds: 100), () {
|
||||
if (hasValidated && formState?.validate() == false) {
|
||||
formState?.validate();
|
||||
}
|
||||
});
|
||||
},
|
||||
);
|
||||
},
|
||||
@ -784,7 +792,7 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||
),
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
labelText: 'Select',
|
||||
labelText: context.translate('Select',' اختيار')
|
||||
),
|
||||
icon: Icon(Icons.keyboard_arrow_down_sharp,
|
||||
color:
|
||||
@ -910,7 +918,11 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 10.0),
|
||||
padding: EdgeInsets.only(left: 10.0, right: profileLocale
|
||||
?.languageCode ==
|
||||
'ar'
|
||||
? 15
|
||||
: 0.0,),
|
||||
child: Text(
|
||||
context.translate('Required', 'مطلوب'),
|
||||
style: TextStyle(
|
||||
@ -947,6 +959,9 @@ class _ProfileScreenState extends ConsumerState<ProfileScreen> {
|
||||
// ElevatedButton.icon(
|
||||
ElevatedButton(
|
||||
onPressed: () {
|
||||
setState(() {
|
||||
hasValidated = true;
|
||||
});
|
||||
if ((_formKey.currentState?.validate() ?? false) &&
|
||||
(isChecked)) {
|
||||
_formKey.currentState?.save();
|
||||
@ -1003,7 +1018,7 @@ class ConfirmationDialog extends StatelessWidget {
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text(
|
||||
"Are you sure you want to save this page?",
|
||||
AppLocalizations.of(context)!.sure_save_page,
|
||||
style: const TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xFF898C81),
|
||||
@ -1015,7 +1030,7 @@ class ConfirmationDialog extends StatelessWidget {
|
||||
SizedBox(height: 8),
|
||||
Text.rich(
|
||||
TextSpan(
|
||||
text: "Once saved, you will not be able to change your ",
|
||||
text: AppLocalizations.of(context)!.not_able_to_change,
|
||||
style: TextStyle(
|
||||
fontSize: 14,
|
||||
color: Color(0xFF898C81),
|
||||
@ -1024,15 +1039,15 @@ class ConfirmationDialog extends StatelessWidget {
|
||||
),
|
||||
children: [
|
||||
TextSpan(
|
||||
text: "Name",
|
||||
text: AppLocalizations.of(context)!.name,
|
||||
style:
|
||||
TextStyle(fontWeight: FontWeight.w700), // Bold for "name"
|
||||
),
|
||||
TextSpan(
|
||||
text: " or ",
|
||||
text: context.translate(' or ','أو'),
|
||||
),
|
||||
TextSpan(
|
||||
text: "Date of birth",
|
||||
text: AppLocalizations.of(context)!.dob,
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w700), // Bold for "date of birth"
|
||||
),
|
||||
|
||||
@ -45,7 +45,7 @@ class ThemedFormField extends HookWidget {
|
||||
final inputDecoration = InputDecoration(
|
||||
filled: true,
|
||||
fillColor: Colors.white,
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 14),
|
||||
contentPadding: const EdgeInsets.symmetric(vertical: 14, horizontal: 15),
|
||||
border: OutlineInputBorder(
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
borderSide: BorderSide(
|
||||
|
||||
@ -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
|
||||
@ -125,6 +127,7 @@ class LoginRoute extends HookConsumerWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final hasValidated = useState(false);
|
||||
final locale = ref.watch(localeProvider);
|
||||
final emailCtl = useTextEditingController();
|
||||
final pwCtl = useTextEditingController();
|
||||
@ -270,6 +273,7 @@ class LoginRoute extends HookConsumerWidget {
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: () async {
|
||||
hasValidated.value=true;
|
||||
final isValid = formKey.currentState!.validate();
|
||||
if (!isValid) return;
|
||||
final session = await context.loaderWithErrorDialog(
|
||||
@ -342,7 +346,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);
|
||||
@ -677,7 +682,7 @@ class LoginRoute extends HookConsumerWidget {
|
||||
final formState = formKey.currentState;
|
||||
ref.read(localeProvider.notifier).toggleLocale();
|
||||
Future.delayed(Duration(milliseconds: 100), () {
|
||||
if (formState?.validate() == false) {
|
||||
if (hasValidated.value && formState?.validate() == false) {
|
||||
formState?.validate();
|
||||
}
|
||||
});
|
||||
|
||||
@ -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<EconomyStatsWidget> {
|
||||
List<dynamic> 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<EconomyStatsWidget> {
|
||||
// }
|
||||
|
||||
Future<void> 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) {
|
||||
|
||||
@ -3,14 +3,17 @@ import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:flutter_svg/svg.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
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';
|
||||
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
|
||||
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
|
||||
|
||||
|
||||
class BookMark extends ConsumerStatefulWidget {
|
||||
const BookMark({super.key});
|
||||
|
||||
@ -19,26 +22,20 @@ class BookMark extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _BookMarkState extends ConsumerState<BookMark> {
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
final _pb = PocketBase(apiUrl);
|
||||
List<Map<String, dynamic>> dataList = [];
|
||||
bool isLoading = true;
|
||||
|
||||
Map<String, Map<String, dynamic>> groupedMap = {};
|
||||
int? expandedIndex = 0;
|
||||
// Current selected tab index
|
||||
int selectedTabIndex = 0;
|
||||
|
||||
// Tab categories
|
||||
final List<String> tabs = [
|
||||
'All Bookmarks',
|
||||
'Economy',
|
||||
'Social',
|
||||
'Environment',
|
||||
];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
final locale = ref.read(localeProvider);
|
||||
fetchBookmarks(locale?.languageCode ?? 'en');
|
||||
|
||||
}
|
||||
|
||||
String colorToHex(Color color) {
|
||||
@ -73,7 +70,7 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
}
|
||||
|
||||
final response = await Dio().get(
|
||||
'https://pb.venbait.in/api/getUserBookmark',
|
||||
'$apiUrl/api/getUserBookmark',
|
||||
queryParameters: {'user_id': userID, 'language': locale},
|
||||
);
|
||||
|
||||
@ -101,8 +98,36 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
'id': item['id'],
|
||||
};
|
||||
}).toList();
|
||||
print('dataList $dataList');
|
||||
// print('dataList $dataList');
|
||||
});
|
||||
groupedMap = {};
|
||||
for (var item in dataList) {
|
||||
String? mainTopic = item['main_topic'];
|
||||
String subtitle = item['subtitle'];
|
||||
|
||||
|
||||
// Ignore if main_topic is null
|
||||
if (mainTopic == null) continue;
|
||||
|
||||
// If main_topic doesn't exist in groupedMap, create a new entry
|
||||
if (!groupedMap.containsKey(mainTopic)) {
|
||||
groupedMap[mainTopic] = {'main_topic': mainTopic,
|
||||
'valueColor': item['valueColor'],
|
||||
'SubTopic': []
|
||||
};
|
||||
}
|
||||
|
||||
// Add subtitle as a key with its corresponding map value
|
||||
groupedMap[mainTopic]!['SubTopic'].add ({
|
||||
'subtitle': subtitle,
|
||||
'isBookmark': item['isBookmark'],
|
||||
'value': item['value'],
|
||||
'title':item['title'],
|
||||
'value_source':item['value_source'],
|
||||
'data_set':item['data_set'],
|
||||
'id': item['id'],
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
@ -126,18 +151,6 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
await _pb.collection('bookmark').delete(bookmarkId!, headers: {
|
||||
'Authorization': adminToken,
|
||||
});
|
||||
// Show success SnackBar
|
||||
// ScaffoldMessenger.of(context).showSnackBar(
|
||||
// const SnackBar(
|
||||
// content: Text(
|
||||
// 'Removed from Bookmark.',
|
||||
// style: TextStyle(
|
||||
// color: Color(0xFF2F692C), fontWeight: FontWeight.w600),
|
||||
// ),
|
||||
// backgroundColor: Color(0xFFD6E9C6),
|
||||
// duration: Duration(seconds: 2),
|
||||
// ),
|
||||
// );
|
||||
final locale = ref.read(localeProvider);
|
||||
fetchBookmarks(locale?.languageCode ?? 'en');
|
||||
// ToastUtil.showSuccessToast("Removed from Bookmark.");
|
||||
@ -145,11 +158,8 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'Removed From Bookmark',
|
||||
style: TextStyle(color: Color(0xFF2F692C),
|
||||
fontWeight: FontWeight.w500),
|
||||
AppLocalizations.of(context)!.removed_from_Bookmark,
|
||||
),
|
||||
backgroundColor: Color(0xFFD6E9C6),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
@ -263,15 +273,35 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
||||
final List<Map<String, dynamic>> tabs = [
|
||||
{ 'title':AppLocalizations.of(context)!.all_bookmarks, 'color': Colors.black},
|
||||
{ 'title': AppLocalizations.of(context)!.economy_title, 'color': Color(0xFF90B0D5)},
|
||||
{ 'title':AppLocalizations.of(context)!.social_title, 'color': Color(0xFFAA8E83)},
|
||||
{ 'title': AppLocalizations.of(context)!.environment_title, 'color': Color(0xFF7DAFBC)},
|
||||
];
|
||||
|
||||
ref.listen<Locale?>(localeProvider, (previous, next) {
|
||||
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
|
||||
fetchBookmarks(localeCode);
|
||||
});
|
||||
|
||||
List<Map<String, dynamic>> bookmarks = dataList.where((item) => item['isBookmark'] == true).toList();
|
||||
List<Map<String, dynamic>> filteredBookmarks = dataList
|
||||
.where((bookmark) =>
|
||||
bookmark['main_topic'].toString().trim().toLowerCase() == tabs[selectedTabIndex].toString().trim().toLowerCase())
|
||||
.toList();
|
||||
.where((bookmark) {
|
||||
String mainTopic = bookmark['main_topic'].toString().trim().toLowerCase();
|
||||
String selectedTabTitle = tabs[selectedTabIndex]['title'].toString().trim().toLowerCase();
|
||||
|
||||
print('filtered $filteredBookmarks');
|
||||
// Debugging prints
|
||||
print("main_topic: '$mainTopic', selected_tab_title: '$selectedTabTitle'");
|
||||
|
||||
return mainTopic == selectedTabTitle;
|
||||
})
|
||||
.toList();
|
||||
// print( 'filtered one :${filteredBookmarks['main_topic']} , Tabs : ${tabs[selectedTabIndex]["title"]}');
|
||||
List<Map<String, dynamic>> transformedList = groupedMap.values.toList();
|
||||
// print('filtered $filteredBookmarks');
|
||||
return BaseScaffold(
|
||||
title: Text('Bookmarks'),
|
||||
title: Text(AppLocalizations.of(context)!.bookmarks,),
|
||||
body: Column(
|
||||
children: [
|
||||
TabBarHeader(
|
||||
@ -285,23 +315,68 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
),
|
||||
Expanded(
|
||||
child: selectedTabIndex == 0
|
||||
? Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GridView.builder(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
mainAxisExtent: 100,
|
||||
),
|
||||
itemCount: bookmarks.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _buildBox(bookmarks[index], context);
|
||||
},
|
||||
? (bookmarks.isNotEmpty
|
||||
? SingleChildScrollView(
|
||||
child: Column(
|
||||
children: List.generate(transformedList.length, (i) {
|
||||
final mainTopic = transformedList[i];
|
||||
print('oustside1 $mainTopic');
|
||||
final list=List.from(mainTopic['SubTopic'] ?? []);
|
||||
print('oustside2 $list');
|
||||
return CustomExpandableTile(
|
||||
index: i,
|
||||
isExpanded: expandedIndex == i,
|
||||
onTap: (int index) { // 🔹 Expecting an index
|
||||
setState(() {
|
||||
expandedIndex = (expandedIndex == index) ? null : index;
|
||||
});
|
||||
},
|
||||
title: mainTopic['main_topic'] ?? 'No Topic',
|
||||
childWidget:
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
// borderRadius: BorderRadius.all(Radius.circular(20))
|
||||
),
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: GridView.builder(
|
||||
shrinkWrap: true,
|
||||
physics: NeverScrollableScrollPhysics(),
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
mainAxisExtent: 100,
|
||||
),
|
||||
itemCount:list.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _buildBoxes(mainTopic['SubTopic'][index], context,mainTopic['valueColor']);
|
||||
},
|
||||
),
|
||||
),
|
||||
filteredBookmarks: List.from(mainTopic['SubTopic'] ?? []), titleBackgroundColor: mainTopic['valueColor'],
|
||||
// Ensure it's a new list
|
||||
);
|
||||
}),
|
||||
),
|
||||
|
||||
):filteredBookmarks.isEmpty
|
||||
)
|
||||
: Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(Icons.info_outline,
|
||||
size: 100, color: Colors.grey[400]),
|
||||
SizedBox(height: 16),
|
||||
Text(
|
||||
context.translate('No BookMark Added','لم يتم إضافة أي علامة مرجعية'),
|
||||
style:
|
||||
TextStyle(fontSize: 16, color: Colors.grey),
|
||||
),
|
||||
],
|
||||
),
|
||||
))
|
||||
:filteredBookmarks.isEmpty
|
||||
? Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
@ -319,20 +394,47 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
)
|
||||
: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GridView.builder(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
mainAxisExtent: 100,
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: tabs[selectedTabIndex]['color'],
|
||||
borderRadius: BorderRadius.all(Radius.circular(35))
|
||||
),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16, bottom: 5, top: 5, right: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
tabs[selectedTabIndex]['title'],
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
itemCount: filteredBookmarks.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _buildBox(filteredBookmarks[index], context);
|
||||
},
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 20,),
|
||||
Expanded(
|
||||
child: GridView.builder(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
mainAxisExtent: 100,
|
||||
),
|
||||
|
||||
itemCount: filteredBookmarks.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _buildBox(filteredBookmarks[index], context);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -355,7 +457,7 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
print(hexColor); // Prints: 0xFFAA8E83
|
||||
|
||||
debugPrint("Box clicked: ${data['title']}");
|
||||
context.go(
|
||||
context.push(
|
||||
'/chartScreen/$data_set?bgColor=$hexColor&mainTopic=$encodedMainTopic&title=$encodedTitle');
|
||||
},
|
||||
child: Container(
|
||||
@ -440,10 +542,99 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildBoxes(Map<String, dynamic> data, BuildContext context, Color styleColor) {
|
||||
// Color borderColor = data['valueColor'];
|
||||
print('inside function $data');
|
||||
return GestureDetector(
|
||||
onTap: () {
|
||||
final data_set = data['data_set'];
|
||||
|
||||
// final Color colorPattern = data['valueColor'];
|
||||
final encodedMainTopic = data['main_topic'];
|
||||
final encodedTitle = data['title'];
|
||||
String hexColor = colorToHex(styleColor);
|
||||
|
||||
debugPrint( '/chartScreen/$data_set?bgColor=$hexColor&mainTopic=$encodedMainTopic&title=$encodedTitle');
|
||||
|
||||
// String hexColor = colorToHex(colorPattern); // Get hex string
|
||||
// print(hexColor); // Prints: 0xFFAA8E83
|
||||
|
||||
// debugPrint("Box clicked: ${data['title']}");
|
||||
context.push(
|
||||
'/chartScreen/$data_set?bgColor=$hexColor&mainTopic=$encodedMainTopic&title=$encodedTitle');
|
||||
},
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width * 0.4,
|
||||
height: 100,
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
border: Border.all(color: styleColor),
|
||||
),
|
||||
child:
|
||||
Align(
|
||||
alignment: Alignment.center,
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Align(
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
data['title'] ?? '',
|
||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
debugPrint("Icon clicked in: ${data['title']}");
|
||||
showRemoveBookmarkDialog(data['id']);
|
||||
},
|
||||
child: SvgPicture.asset(
|
||||
BookmarkAssetPath.delete,
|
||||
semanticsLabel: 'share',
|
||||
width:23,
|
||||
height: 20,
|
||||
)
|
||||
),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
data['value_source'] ?? '',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w500, color: Colors.grey),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
),
|
||||
Text(
|
||||
data['value'] ?? '',
|
||||
style: TextStyle(
|
||||
fontSize: 28,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: styleColor,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
class TabBarHeader extends StatelessWidget {
|
||||
final List<String> tabs;
|
||||
final List<Map<String, dynamic>> tabs;
|
||||
final int selectedIndex;
|
||||
final ValueChanged<int> onTabSelected;
|
||||
|
||||
@ -464,7 +655,7 @@ class TabBarHeader extends StatelessWidget {
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: tabs.asMap().entries.map((entry) {
|
||||
int index = entry.key;
|
||||
String text = entry.value;
|
||||
String text = entry.value['title'];
|
||||
return Row(
|
||||
children: [
|
||||
TextButton(
|
||||
@ -473,7 +664,7 @@ class TabBarHeader extends StatelessWidget {
|
||||
foregroundColor:
|
||||
MaterialStateProperty.resolveWith((states) {
|
||||
return selectedIndex == index
|
||||
? Colors.black
|
||||
? entry.value['color']
|
||||
: Colors.grey[700];
|
||||
}),
|
||||
),
|
||||
@ -489,7 +680,7 @@ class TabBarHeader extends StatelessWidget {
|
||||
}
|
||||
|
||||
Widget buildDivider() {
|
||||
return Container(
|
||||
return SizedBox(
|
||||
height: 20,
|
||||
child: const VerticalDivider(
|
||||
color: Colors.grey,
|
||||
@ -499,3 +690,123 @@ class TabBarHeader extends StatelessWidget {
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class CustomExpandableTile extends StatefulWidget {
|
||||
final String title;
|
||||
final Color titleBackgroundColor;
|
||||
final List filteredBookmarks;
|
||||
final int index;
|
||||
final bool isExpanded;
|
||||
final ValueChanged<int> onTap;
|
||||
final Widget childWidget;
|
||||
|
||||
const CustomExpandableTile({
|
||||
required this.title,
|
||||
required this.titleBackgroundColor,
|
||||
required this.filteredBookmarks,
|
||||
required this.index,
|
||||
required this.isExpanded,
|
||||
required this.onTap,
|
||||
required this.childWidget,
|
||||
});
|
||||
|
||||
@override
|
||||
_CustomExpandableTileState createState() => _CustomExpandableTileState();
|
||||
}
|
||||
|
||||
class _CustomExpandableTileState extends State<CustomExpandableTile> {
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState(); // Initialize isExpanded based on widget's property
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
double myheight = MediaQuery.of(context).size.height;
|
||||
// print(widget.filteredBookmarks);
|
||||
return Card(
|
||||
elevation: 0,
|
||||
child: Column(
|
||||
children: [
|
||||
GestureDetector(
|
||||
onTap: () => widget.onTap(widget.index),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white, // Ensuring the background outside the rounded container is white
|
||||
),
|
||||
child: Container(
|
||||
decoration: BoxDecoration(
|
||||
color: widget.titleBackgroundColor,
|
||||
borderRadius: BorderRadius.all(Radius.circular(35))
|
||||
),
|
||||
padding: const EdgeInsets.only(
|
||||
left: 16, bottom: 5, top: 5, right: 10),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
Text(
|
||||
widget.title,
|
||||
style: TextStyle(
|
||||
color: Colors.white,
|
||||
fontWeight: FontWeight.w600,
|
||||
fontSize: 20,
|
||||
),
|
||||
),
|
||||
Icon(
|
||||
widget.isExpanded
|
||||
? Icons.keyboard_arrow_up
|
||||
: Icons.keyboard_arrow_down,
|
||||
color: Colors.white,
|
||||
size: 28.0,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
ClipRRect(
|
||||
child: AnimatedContainer(
|
||||
duration: Duration(milliseconds: 300),
|
||||
curve: Curves.easeInOut,
|
||||
width: double.infinity,
|
||||
color: Colors.white,
|
||||
height:widget.isExpanded ? myheight * 0.4 : 0,
|
||||
child:widget.isExpanded
|
||||
? SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
widget.childWidget,
|
||||
// Container(
|
||||
// decoration: BoxDecoration(
|
||||
// color: Colors.white,
|
||||
// // borderRadius: BorderRadius.all(Radius.circular(20))
|
||||
// ),
|
||||
// padding: const EdgeInsets.all(16),
|
||||
// child: GridView.builder(
|
||||
// shrinkWrap: true,
|
||||
// physics: NeverScrollableScrollPhysics(),
|
||||
// gridDelegate:
|
||||
// const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
// crossAxisCount: 2,
|
||||
// crossAxisSpacing: 10.0,
|
||||
// mainAxisSpacing: 10.0,
|
||||
// mainAxisExtent: 100,
|
||||
// ),
|
||||
// itemCount: widget.filteredBookmarks.length,
|
||||
// itemBuilder: (context, index) {
|
||||
// return _buildBox(widget.filteredBookmarks[index], context,widget.titleBackgroundColor);
|
||||
// },
|
||||
// ),
|
||||
// ),
|
||||
],
|
||||
),
|
||||
)
|
||||
: null,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,145 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:uae_stat/domain/use_cases/language.dart';
|
||||
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/enquiry_asset_icon_path.dart';
|
||||
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
class Contact extends StatefulWidget {
|
||||
const Contact({super.key});
|
||||
|
||||
@override
|
||||
State<Contact> createState() => _ContactState();
|
||||
}
|
||||
|
||||
class _ContactState extends State<Contact> {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final double screenWidth= MediaQuery.of(context).size.width;
|
||||
final double screenHeight= MediaQuery.of(context).size.height;
|
||||
|
||||
|
||||
return BaseScaffold(
|
||||
body: Container(
|
||||
color: Colors.grey[200],
|
||||
width: screenWidth,
|
||||
padding: EdgeInsets.all(16.0),
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(4.0), // Slight curve
|
||||
),
|
||||
padding: EdgeInsets.all(7.0),
|
||||
height: screenHeight*0.35,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(context.translate('DUBAI - EMIRATES TOWER -32ND FLOOR','دبي - أبراج الإمارات - الطابق 32'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFF265E84),
|
||||
fontSize: 20,
|
||||
fontFamily: 'Roboto',
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
buildTextRow(EnquiryAssetIconPath.building,context.translate('Office : Dubai - Emirates Tower -32nd Floor','المقر الرئيسي : دبي - أبراج الإمارات - الطابق 32')),
|
||||
buildTextRow(EnquiryAssetIconPath.phone,context.translate('Tel : 00971 46080000','الهاتف : 0097146080000'),),
|
||||
buildTextRow(EnquiryAssetIconPath.fax, context.translate('Fax : 0097143273535','فاكس : 0097143273535')),
|
||||
buildTextRow(EnquiryAssetIconPath.map, context.translate('P.O.Box : 127000 Dubai','ص.ب: : 127000 دبي')),
|
||||
buildTextRow(EnquiryAssetIconPath.at, context.translate('Email Address : info@fcsc.gov.ae','البريد الإلكتروني : info@fcsc.gov.ae')),
|
||||
buildTextRow(EnquiryAssetIconPath.map,context.translate( 'Latitude : 25.223926','خط العرض : 25.223926')),
|
||||
buildTextRow(EnquiryAssetIconPath.map, context.translate('Longitude : 55.350526','خط الطول : 55.350526')),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10,),
|
||||
Container(
|
||||
padding: EdgeInsets.all(7.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(4.0), // Slight curve
|
||||
),
|
||||
height: screenHeight*0.34,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(context.translate('MEDIA SECTION','قسم الاعلام'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFF265E84),
|
||||
fontSize: 20,
|
||||
fontFamily: 'Roboto',
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
buildTextRow(EnquiryAssetIconPath.building,context.translate('Office : Media Section','المقر الرئيسي : قسم الاعلام')),
|
||||
buildTextRow(EnquiryAssetIconPath.phone,context.translate('Tel : 00971 46080000','الهاتف : 0097146080000'),),
|
||||
buildTextRow(EnquiryAssetIconPath.fax, context.translate('Fax : 0097143273535','فاكس : 0097143273535')),
|
||||
buildTextRow(EnquiryAssetIconPath.map, context.translate('P.O.Box : 127000 Dubai','ص.ب: : 127000 دبي')),
|
||||
buildTextRow(EnquiryAssetIconPath.at, context.translate('Email Address : GCO@fcsc.gov.ae','البريد الإلكتروني : GCO@fcsc.gov.ae')),
|
||||
buildTextRow(EnquiryAssetIconPath.map,context.translate( 'Latitude : 25.223926','خط العرض : 25.223926')),
|
||||
buildTextRow(EnquiryAssetIconPath.map, context.translate('Longitude : 55.350526','خط الطول : 55.350526')),
|
||||
],
|
||||
),
|
||||
),
|
||||
SizedBox(height: 10,),
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(4.0), // Slight curve
|
||||
),
|
||||
padding: EdgeInsets.all(7.0),
|
||||
height: screenHeight*0.34,
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(context.translate('SGDS','أهداف التنمية المستدامة'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFF265E84),
|
||||
fontSize: 20,
|
||||
fontFamily: 'Roboto',
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
),
|
||||
buildTextRow(EnquiryAssetIconPath.building,context.translate('Office : SDGs','المقر الرئيسي : أهداف التنمية المستدامة')),
|
||||
buildTextRow(EnquiryAssetIconPath.phone,context.translate('Tel : 00971 46080000','الهاتف : 0097146080000'),),
|
||||
buildTextRow(EnquiryAssetIconPath.fax, context.translate('Fax : 0097143273535','فاكس : 0097143273535')),
|
||||
buildTextRow(EnquiryAssetIconPath.map, context.translate('P.O.Box : 127000 Dubai','ص.ب: : 127000 دبي')),
|
||||
buildTextRow(EnquiryAssetIconPath.at, context.translate('Email Address : sdgs@fcsc.gov.ae','البريد الإلكتروني : sdgs@fcsc.gov.ae')),
|
||||
buildTextRow(EnquiryAssetIconPath.map,context.translate( 'Latitude : 25.223926','خط العرض : 25.223926')),
|
||||
buildTextRow(EnquiryAssetIconPath.map, context.translate('Longitude : 55.350526','خط الطول : 55.350526')),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
), title: Text(context.translate('Contact Us','اتصل بنا')),);
|
||||
}
|
||||
|
||||
Widget buildTextRow(String iconName, String text) {
|
||||
return Padding(
|
||||
padding: const EdgeInsets.only(top:8.0),
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
children: [
|
||||
SvgPicture.asset(
|
||||
iconName,
|
||||
semanticsLabel: 'Filter',
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
SizedBox(width: 8), // Add spacing if needed
|
||||
Text(
|
||||
text, // Dynamic text
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
color: Color(0xFF878787),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
@ -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<EditProfile> {
|
||||
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<EditProfile> {
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
@ -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<FeedbackForm>
|
||||
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
|
||||
|
||||
|
||||
@ -1,7 +1,9 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_svg/svg.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 +18,7 @@ class ManageUserRouter extends StatefulWidget {
|
||||
}
|
||||
|
||||
class _ManageUserRouterState extends State<ManageUserRouter> {
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
final _pb = PocketBase(apiUrl);
|
||||
List<User> userData = [];
|
||||
int _sortColumnIndex = 0;
|
||||
bool _isAscending = true;
|
||||
@ -342,11 +344,14 @@ class _ManageUserRouterState extends State<ManageUserRouter> {
|
||||
decoration: InputDecoration(
|
||||
hintText: "Search",
|
||||
hintStyle: TextStyle(color: Color(0xFF898C81)),
|
||||
prefixIcon: Image(
|
||||
image: ExactAssetImage(MiscIconAssetPath.search),
|
||||
width: 24,
|
||||
height: 24,
|
||||
color: Color(0xFFAA8E83)),
|
||||
prefixIconConstraints: BoxConstraints(maxWidth: 42, maxHeight: 42),
|
||||
prefixIcon: Container(
|
||||
padding: EdgeInsets.only(right: 5),
|
||||
child: SvgPicture.asset(
|
||||
MiscIconAssetPath.Search,
|
||||
semanticsLabel: 'Search',
|
||||
),
|
||||
),
|
||||
|
||||
// prefixIcon: Image.asset(
|
||||
// MiscIconAssetPath.search,
|
||||
|
||||
@ -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<NotificationPage> {
|
||||
// Example notification data
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
final _pb = PocketBase(apiUrl);
|
||||
List<Map<String, dynamic>> notifications = [];
|
||||
|
||||
// Current selected tab index
|
||||
|
||||
@ -7,7 +7,7 @@ import 'package:flutter_gen/gen_l10n/app_localizations.dart';
|
||||
|
||||
|
||||
class Userguide extends StatefulWidget {
|
||||
const Userguide({super.key});
|
||||
Userguide({super.key});
|
||||
|
||||
@override
|
||||
State<Userguide> createState() => _UserguideState();
|
||||
@ -20,6 +20,7 @@ class _UserguideState extends State<Userguide> {
|
||||
{'routePath':'faq','color': Color(0xFF7296BE), 'text': 'FAQs', 'icon': 'mdi:faq', 'text-ar': 'لأسئلة الشائعة'},
|
||||
];
|
||||
|
||||
@override
|
||||
Widget buildDynamicWidget(dynamic icons, Color color) {
|
||||
if (icons is IconData) {
|
||||
return Icon(
|
||||
@ -46,41 +47,41 @@ class _UserguideState extends State<Userguide> {
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
onPopInvokedWithResult: (didPop, result) {
|
||||
if (didPop) return;
|
||||
context.go('/myhomepage');
|
||||
},
|
||||
child: BaseScaffold(
|
||||
showDivider: true,
|
||||
bottomColor: Colors.white,
|
||||
dividerColor: Colors.grey[300],
|
||||
appbarColor: Colors.white,
|
||||
title: Text(AppLocalizations.of(context)!.guide_title) ,
|
||||
body: Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16 , vertical: 20),
|
||||
child: GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // Two columns
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
mainAxisExtent:MediaQuery.of(context).size.height* 0.15 ,
|
||||
canPop: false,
|
||||
onPopInvokedWithResult: (didPop, result) {
|
||||
if (didPop) return;
|
||||
context.go('/myhomepage');
|
||||
},
|
||||
child: BaseScaffold(
|
||||
showDivider: true,
|
||||
bottomColor: Colors.white,
|
||||
dividerColor: Colors.grey[300],
|
||||
appbarColor: Colors.white,
|
||||
title: Text(AppLocalizations.of(context)!.guide_title) ,
|
||||
body: Container(
|
||||
color: Colors.white,
|
||||
padding: const EdgeInsets.symmetric(horizontal: 16 , vertical: 20),
|
||||
child: GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
childAspectRatio: 1.7,
|
||||
// mainAxisExtent:MediaQuery.of(context).size.height* 0.15 ,
|
||||
),
|
||||
itemCount: guideList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return HoverContainer(
|
||||
iconName: guideList[index]['icon'],
|
||||
title: context.translate(guideList[index]['text'], guideList[index]['text-ar']),
|
||||
routePath: guideList[index]['routePath'],
|
||||
);
|
||||
},
|
||||
),
|
||||
itemCount: guideList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return HoverContainer(
|
||||
iconName: guideList[index]['icon'],
|
||||
title: context.translate(guideList[index]['text'], guideList[index]['text-ar']),
|
||||
routePath: guideList[index]['routePath'],
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@ -108,69 +109,69 @@ class _HoverContainerState extends State<HoverContainer> {
|
||||
return GestureDetector(
|
||||
onTap: () { context.push('/user-guide/${widget.routePath}');},
|
||||
child: MouseRegion(
|
||||
onEnter: (_) => setState(() => isHovered = true),
|
||||
onExit: (_) => setState(() => isHovered = true),
|
||||
child : Container(
|
||||
padding: EdgeInsets.only(top: 4, right: 4, left: 4, bottom: 6),
|
||||
height: screenHeight* 0.23 ,
|
||||
width: screenWidth*0.30,
|
||||
margin: EdgeInsets.all(1),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: isHovered
|
||||
? [
|
||||
BoxShadow(
|
||||
color: Colors.black.withValues(alpha:0.2),
|
||||
blurRadius:2,
|
||||
spreadRadius: 1,
|
||||
offset: Offset(0, 4),
|
||||
),
|
||||
]
|
||||
: [],
|
||||
border: Border.all(
|
||||
color: Color(0xFF7DAFBC),
|
||||
width: 1.0,
|
||||
),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
// duration: Duration(milliseconds: 200),
|
||||
onEnter: (_) => setState(() => isHovered = true),
|
||||
onExit: (_) => setState(() => isHovered = true),
|
||||
child : Container(
|
||||
padding: EdgeInsets.only(top: 4, right: 4, left: 4, bottom: 6),
|
||||
|
||||
child: LayoutBuilder(builder: (context, constraints){
|
||||
double containerWidth = constraints.maxWidth;
|
||||
// double containerHeight = constraints.maxHeight;
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
IconifyIcon(icon: widget.iconName,
|
||||
color: Color((0xFF7DAFBC)),
|
||||
size: containerWidth * 0.25,),
|
||||
// buildDynamicWidget(data['icon'], Color(0xFF7DAFBC)),
|
||||
SizedBox(width: 10,height: containerWidth * 0.04,), // Space between icon and text
|
||||
Container(
|
||||
width: containerWidth* 0.85,
|
||||
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 4),
|
||||
margin: EdgeInsets.only(bottom: 3),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFF7DAFBC),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
border: Border.all(color: Color(0xFF7DAFBC)),
|
||||
),
|
||||
child: Text(
|
||||
widget.title,
|
||||
style: TextStyle(
|
||||
color: Colors.white, // Text color
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
width: screenWidth*0.30,
|
||||
margin: EdgeInsets.all(1),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
boxShadow: isHovered
|
||||
? [
|
||||
BoxShadow(
|
||||
color: Colors.black.withOpacity(0.2),
|
||||
blurRadius:2,
|
||||
spreadRadius: 1,
|
||||
offset: Offset(0, 4),
|
||||
),
|
||||
]
|
||||
: [],
|
||||
border: Border.all(
|
||||
color: Color(0xFF7DAFBC),
|
||||
width: 1.0
|
||||
),
|
||||
],
|
||||
);
|
||||
},),
|
||||
),
|
||||
alignment: Alignment.center,
|
||||
// duration: Duration(milliseconds: 200),
|
||||
|
||||
child: LayoutBuilder(builder: (context, constraints){
|
||||
double containerWidth = constraints.maxWidth;
|
||||
double containerHeight = constraints.maxHeight;
|
||||
return Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
IconifyIcon(icon: widget.iconName,
|
||||
color: Color((0xFF7DAFBC)),
|
||||
size: containerHeight * 0.45,),
|
||||
// buildDynamicWidget(data['icon'], Color(0xFF7DAFBC)),
|
||||
SizedBox(width: 10,height: containerHeight * 0.04,), // Space between icon and text
|
||||
Container(
|
||||
width: containerWidth* 0.85,
|
||||
padding: EdgeInsets.symmetric(horizontal: 4, vertical: 4),
|
||||
margin: EdgeInsets.only(bottom: 3),
|
||||
decoration: BoxDecoration(
|
||||
color: Color(0xFF7DAFBC),
|
||||
borderRadius: BorderRadius.circular(5),
|
||||
border: Border.all(color: Color(0xFF7DAFBC))
|
||||
),
|
||||
child: Text(
|
||||
widget.title,
|
||||
style: TextStyle(
|
||||
color: Colors.white, // Text color
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
})
|
||||
|
||||
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
|
||||
|
||||
@ -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<BaseScaffold> {
|
||||
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<BaseScaffold> {
|
||||
|
||||
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<BaseScaffold> {
|
||||
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),
|
||||
@ -972,6 +974,11 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
||||
title: Text(AppLocalizations.of(context)!.guide_title),
|
||||
onTap: () => _navigateTo(context, '/user-guide'),
|
||||
),
|
||||
ListTile(
|
||||
leading: Icon(Icons.phone),
|
||||
title: const Text('Contact'),
|
||||
onTap: () => context.push('/contact'),
|
||||
),
|
||||
if (userId != 'guest')
|
||||
ListTile(
|
||||
leading: Icon(Icons.logout),
|
||||
|
||||
@ -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<FeedbackForm>
|
||||
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
|
||||
|
||||
|
||||
@ -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.25+26
|
||||
version: 1.0.27+28
|
||||
|
||||
environment:
|
||||
sdk: ">=3.2.3 <4.0.0"
|
||||
@ -141,6 +141,7 @@ flutter:
|
||||
- assets/icons/misc/group.png
|
||||
- assets/icons/misc/search.png
|
||||
- assets/icons/bookmark/
|
||||
- assets/icons/enquiry/
|
||||
|
||||
fonts:
|
||||
- family: Segoe
|
||||
|
||||