bookmark added
This commit is contained in:
parent
e0fd4267f2
commit
3dd2aa40fe
@ -15,12 +15,12 @@ if (localPropertiesFile.exists()) {
|
||||
|
||||
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
|
||||
if (flutterVersionCode == null) {
|
||||
flutterVersionCode = "11"
|
||||
flutterVersionCode = "12"
|
||||
}
|
||||
|
||||
def flutterVersionName = localProperties.getProperty("flutter.versionName")
|
||||
if (flutterVersionName == null) {
|
||||
flutterVersionName = "1.0.10"
|
||||
flutterVersionName = "1.0.11"
|
||||
}
|
||||
|
||||
def keystorePropertiesFile = rootProject.file("key.properties")
|
||||
|
||||
BIN
assets/icons/uae_numbers/bookmarksSelectedUae.png
Normal file
BIN
assets/icons/uae_numbers/bookmarksSelectedUae.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 266 B |
29
lib/config/toast_util.dart
Normal file
29
lib/config/toast_util.dart
Normal file
@ -0,0 +1,29 @@
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
class ToastUtil {
|
||||
/// **General Toast**
|
||||
static void showToast(String message,
|
||||
{Color bgColor = Colors.black, Color textColor = Colors.white}) {
|
||||
Fluttertoast.showToast(
|
||||
msg: message,
|
||||
toastLength: Toast.LENGTH_SHORT,
|
||||
gravity: ToastGravity.BOTTOM,
|
||||
backgroundColor: bgColor,
|
||||
textColor: textColor,
|
||||
fontSize: 16.0,
|
||||
);
|
||||
}
|
||||
|
||||
/// **Success Toast**
|
||||
static void showSuccessToast(String message) {
|
||||
showToast(message,
|
||||
bgColor: Color(0xFFD6E9C6), textColor: Color(0xFF2F692C));
|
||||
}
|
||||
|
||||
/// **Delete Toast**
|
||||
static void showDeleteToast(String message) {
|
||||
showToast(message,
|
||||
bgColor: Color(0xFFEB5F24), textColor: Color(0xFF544C4C));
|
||||
}
|
||||
}
|
||||
@ -3,5 +3,6 @@ import 'package:flutter/material.dart';
|
||||
abstract class UaeNumbersAssetPath {
|
||||
static const _basePath = 'assets/icons/uae_numbers';
|
||||
static const bookmarksUae = '$_basePath/bookmarks.png';
|
||||
static const bookmarksSelectedUae = '$_basePath/bookmarksSelectedUae.png';
|
||||
static const shareUae = '$_basePath/share.png';
|
||||
}
|
||||
}
|
||||
|
||||
@ -2,7 +2,10 @@ import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:pocketbase/pocketbase.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:tutorial_coach_mark/tutorial_coach_mark.dart';
|
||||
import 'package:uae_stat/config/toast_util.dart';
|
||||
import 'package:uae_stat/domain/use_cases/language.dart';
|
||||
import 'package:uae_stat/infrastructure/services/img_asset_paths/icons/uae_numbers_asset_path.dart';
|
||||
import 'package:uae_stat/presentation/Screens/charts/services/api_service.dart';
|
||||
@ -34,6 +37,7 @@ class ChartScreen1 extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
List<Map<String, dynamic>> selectedFiltersStorage = [];
|
||||
final GlobalKey<ScaffoldState> _scaffoldKey = GlobalKey<ScaffoldState>();
|
||||
final ApiService apiService = ApiService();
|
||||
@ -60,7 +64,9 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
late TutorialCoachMark tutorialCoachMark;
|
||||
final GlobalKey chartKey = GlobalKey();
|
||||
final GlobalKey bookMarkKey = GlobalKey();
|
||||
final GlobalKey cardKey= GlobalKey();
|
||||
final GlobalKey cardKey = GlobalKey();
|
||||
bool isBookmarked = false; // Track bookmark state
|
||||
String? bookmarkId; // Stores the ID of the bookmark record in PocketBase
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
@ -68,6 +74,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
final String bgColor = widget.bgColor;
|
||||
print(' bgColor $bgColor');
|
||||
// fetchChartData(widget.dataSets);
|
||||
checkIfBookmarked();
|
||||
final locale = ref.read(localeProvider);
|
||||
fetchChartData(widget.dataSets, locale?.languageCode ?? 'en').then((_) {
|
||||
if (_tabsData.isNotEmpty) {
|
||||
@ -81,13 +88,317 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
});
|
||||
}
|
||||
|
||||
/// Check if the item is already bookmarked
|
||||
Future<void> checkIfBookmarked() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final userID = prefs.getString('userId');
|
||||
try {
|
||||
final adminAuth = await _pb.admins.authWithPassword(
|
||||
'pb@venbainfotech.com',
|
||||
'pb@venbainfotech.com',
|
||||
);
|
||||
|
||||
final adminToken = adminAuth.token;
|
||||
|
||||
final result = await _pb.collection('bookmark').getList(
|
||||
filter: "user_id = '${userID}' && dataset = '${widget.dataSets}'",
|
||||
headers: {
|
||||
'Authorization': adminToken, // Pass the admin token
|
||||
},
|
||||
);
|
||||
|
||||
if (result.items.isNotEmpty) {
|
||||
setState(() {
|
||||
isBookmarked = true;
|
||||
bookmarkId = result.items.first.id;
|
||||
});
|
||||
}
|
||||
} catch (e) {
|
||||
print("Error checking bookmark: $e");
|
||||
}
|
||||
}
|
||||
|
||||
/// Add bookmark to PocketBase
|
||||
Future<void> addBookmark() async {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final userID = prefs.getString('userId');
|
||||
try {
|
||||
final adminAuth = await _pb.admins
|
||||
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
|
||||
final adminToken = adminAuth.token;
|
||||
final response = await _pb.collection('bookmark').create(body: {
|
||||
'user_id': userID,
|
||||
'dataset': widget.dataSets,
|
||||
'bgColor': widget.bgColor,
|
||||
'mainTopic': widget.mainTopic,
|
||||
'title': widget.title,
|
||||
'keyParam': widget.keyParam,
|
||||
}, headers: {
|
||||
'Authorization': adminToken
|
||||
});
|
||||
|
||||
setState(() {
|
||||
isBookmarked = true;
|
||||
bookmarkId = response.id;
|
||||
});
|
||||
|
||||
// ToastUtil.showSuccessToast("Added to Bookmark.");
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
const SnackBar(
|
||||
content: Text(
|
||||
'Added to Bookmark.',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF2F692C), fontWeight: FontWeight.w600),
|
||||
),
|
||||
backgroundColor: Color(0xFFD6E9C6),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
|
||||
print("Bookmark added: ${response.id}");
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'Failed to Add',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF544C4C), fontWeight: FontWeight.w600),
|
||||
),
|
||||
backgroundColor: Color(0xFFEB5F24),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
// ToastUtil.showDeleteToast("Unable to add to bookmarks. Please try again");
|
||||
print("Error adding bookmark: $e");
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove bookmark from PocketBase
|
||||
Future<void> removeBookmark() async {
|
||||
try {
|
||||
final adminAuth = await _pb.admins
|
||||
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
|
||||
final adminToken = adminAuth.token;
|
||||
if (bookmarkId != null) {
|
||||
await _pb.collection('bookmark').delete(bookmarkId!, headers: {
|
||||
'Authorization': adminToken,
|
||||
});
|
||||
|
||||
setState(() {
|
||||
isBookmarked = false;
|
||||
bookmarkId = null;
|
||||
});
|
||||
// ToastUtil.showSuccessToast("Removed from Bookmark.");
|
||||
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),
|
||||
),
|
||||
);
|
||||
print("Bookmark removed");
|
||||
}
|
||||
} catch (e) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'Failed to Remove',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF544C4C), fontWeight: FontWeight.w600),
|
||||
),
|
||||
backgroundColor: Color(0xFFEB5F24),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
// ToastUtil.showDeleteToast(
|
||||
// "Unable to remove from bookmarks. Please try again");
|
||||
print("Error removing bookmark: $e");
|
||||
}
|
||||
}
|
||||
|
||||
/// Show confirmation dialog before removing bookmark
|
||||
void showRemoveBookmarkDialog() {
|
||||
double myheight = MediaQuery.of(context).size.height;
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false, // User must tap button to dismiss dialog
|
||||
builder: (context) => AlertDialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5.0), // Rounded corners
|
||||
),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: myheight / 30,
|
||||
),
|
||||
Text(
|
||||
context.translate(
|
||||
'Are you sure you want to remove this bookmark?',
|
||||
'هل أنت متأكد أنك تريد إزالة هذه الإشارة المرجعية؟'),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Color(0xFF898C81),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 100, // Set the desired width
|
||||
child: TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
style: TextButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
10.0), // Adjust the radius as needed
|
||||
),
|
||||
side: BorderSide(
|
||||
color: Color(0xFFAA8E83), // Set the outline color
|
||||
width: 1, // Set the border width
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
context.translate('No', 'لا'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAA8E83),
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 100, // Set the desired width
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
removeBookmark(); // Close dialog
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: Color(0xFFAA8E83), // Set background color
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10.0), // Set text color
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
context.translate('Yes', 'نعم'),
|
||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void showAddBookmarkDialog() {
|
||||
double myheight = MediaQuery.of(context).size.height;
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false, // User must tap button to dismiss dialog
|
||||
builder: (context) => AlertDialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5.0), // Rounded corners
|
||||
),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: myheight / 30,
|
||||
),
|
||||
Text(
|
||||
context.translate(
|
||||
'Do you want to add this to bookmarks?',
|
||||
'هل تريد إضافة هذا إلى الإشارات المرجعية؟',
|
||||
),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Color(0xFF898C81),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 100, // Set the desired width
|
||||
child: TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
style: TextButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
10.0), // Adjust the radius as needed
|
||||
),
|
||||
side: BorderSide(
|
||||
color: Color(0xFFAA8E83), // Set the outline color
|
||||
width: 1, // Set the border width
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
context.translate('No', 'لا'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAA8E83),
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 100, // Set the desired width
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
addBookmark(); // Close dialog
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: Color(0xFFAA8E83), // Set background color
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10.0), // Set text color
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
context.translate('Yes', 'نعم'),
|
||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void handleSkip() {
|
||||
tutorialCoachMark.skip();
|
||||
debugPrint('Skip clicked');
|
||||
ref.read(chartsTourProvider.notifier).state = true;
|
||||
ref.read(previousChartsTourProvider.notifier).state = true;
|
||||
ref.read(homeTourProvider.notifier).state = true;
|
||||
ref.read( previousHomeTourProvider.notifier).state = true;
|
||||
ref.read(chartsTourProvider.notifier).state = true;
|
||||
ref.read(previousChartsTourProvider.notifier).state = true;
|
||||
ref.read(homeTourProvider.notifier).state = true;
|
||||
ref.read(previousHomeTourProvider.notifier).state = true;
|
||||
ref.read(scaffoldTourProvider.notifier).state = true;
|
||||
ref.read(previousScaffoldTourProvider.notifier).state = true;
|
||||
context.go('/myhomepage');
|
||||
@ -101,7 +412,6 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
tutorialCoachMark = TutorialCoachMark(
|
||||
paddingFocus: 0,
|
||||
useSafeArea: true,
|
||||
|
||||
pulseEnable: false,
|
||||
hideSkip: true,
|
||||
targets: marriageTargets,
|
||||
@ -109,26 +419,22 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
context.go('/myhomepage');
|
||||
debugPrint('Marriage Tutorial Finished');
|
||||
},
|
||||
|
||||
)..show(context: context);
|
||||
}
|
||||
|
||||
|
||||
void _startTutorialAfterRender() {
|
||||
final chartTour = ref.watch(chartsTourProvider);
|
||||
final previousChartTour = ref.watch(previousChartsTourProvider);
|
||||
debugPrint('render problem');
|
||||
if (cardKey.currentContext != null && !chartTour) {
|
||||
_kpiTutorialCoachMark();
|
||||
} else if(cardKey.currentContext != null && !previousChartTour) {
|
||||
} else if (cardKey.currentContext != null && !previousChartTour) {
|
||||
_previousKpiTutorial();
|
||||
}
|
||||
else if (!chartTour || !previousChartTour){
|
||||
} else if (!chartTour || !previousChartTour) {
|
||||
Future.delayed(Duration(milliseconds: 100), _startTutorialAfterRender);
|
||||
}else{
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void _previousKpiTutorial() {
|
||||
@ -143,14 +449,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
context.go('/myhomepage');
|
||||
debugPrint('Previous Marriage Tutorial Finished');
|
||||
},
|
||||
|
||||
)..show(context: context);
|
||||
|
||||
}
|
||||
void _initmarriageTargets(){
|
||||
final double screenWidth= MediaQuery.of(context).size.width;
|
||||
final double screenHeight= MediaQuery.of(context).size.height;
|
||||
marriageTargets=[
|
||||
|
||||
void _initmarriageTargets() {
|
||||
final double screenWidth = MediaQuery.of(context).size.width;
|
||||
final double screenHeight = MediaQuery.of(context).size.height;
|
||||
marriageTargets = [
|
||||
TargetFocus(
|
||||
identify: 'cardKey',
|
||||
keyTarget: cardKey,
|
||||
@ -161,14 +466,14 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
createTargetContent(
|
||||
text: AppLocalizations.of(context)!.kpiCards,
|
||||
alignment: ContentAlign.top,
|
||||
gap:55,
|
||||
gap: 55,
|
||||
space: 0,
|
||||
),
|
||||
TargetContent(
|
||||
align: ContentAlign.bottom,
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: MediaQuery.of(context).size.height*0.3,
|
||||
height: MediaQuery.of(context).size.height * 0.3,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
@ -179,15 +484,15 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child:Padding(
|
||||
padding: EdgeInsets.only(right:10),
|
||||
child:Text(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 10),
|
||||
child: Text(
|
||||
'3/7',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
fontSize: 14,
|
||||
),
|
||||
) ,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
@ -217,14 +522,21 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2.0),
|
||||
border: Border.all(
|
||||
color: Colors.white, width: 2.0),
|
||||
),
|
||||
child: IconButton(
|
||||
iconSize: 20,
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
icon: const Icon(Icons.arrow_back,
|
||||
color: Colors.white),
|
||||
onPressed: () {
|
||||
ref.read(chartsTourProvider.notifier).state=true;
|
||||
ref.read(previousHomeTourProvider.notifier).state=false;
|
||||
ref
|
||||
.read(chartsTourProvider.notifier)
|
||||
.state = true;
|
||||
ref
|
||||
.read(
|
||||
previousHomeTourProvider.notifier)
|
||||
.state = false;
|
||||
tutorialCoachMark.finish();
|
||||
},
|
||||
),
|
||||
@ -234,11 +546,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Color(0xFF7DAFBC),
|
||||
border: Border.all(color:Color(0xFF7DAFBC), width: 1.5),
|
||||
border: Border.all(
|
||||
color: Color(0xFF7DAFBC), width: 1.5),
|
||||
),
|
||||
child: IconButton(
|
||||
iconSize: 20,
|
||||
icon: const Icon(Icons.arrow_forward, color: Colors.white),
|
||||
icon: const Icon(Icons.arrow_forward,
|
||||
color: Colors.white),
|
||||
onPressed: () {
|
||||
tutorialCoachMark.next();
|
||||
},
|
||||
@ -256,25 +570,25 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
),
|
||||
),
|
||||
TargetContent(
|
||||
padding: EdgeInsets.only(bottom: 0,top : 0,),
|
||||
padding: EdgeInsets.only(
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
),
|
||||
align: ContentAlign.top,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height:MediaQuery.of(context).size.height*0.69 ,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: MediaQuery.of(context).size.width*0.40,
|
||||
bottom: 0,
|
||||
child: Image.asset(
|
||||
'assets/app_tour/leftUp.png',
|
||||
width: 100,
|
||||
height: 90,
|
||||
),
|
||||
),
|
||||
]
|
||||
),
|
||||
|
||||
height: MediaQuery.of(context).size.height * 0.69,
|
||||
child: Stack(children: [
|
||||
Positioned(
|
||||
left: MediaQuery.of(context).size.width * 0.40,
|
||||
bottom: 0,
|
||||
child: Image.asset(
|
||||
'assets/app_tour/leftUp.png',
|
||||
width: 100,
|
||||
height: 90,
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -397,7 +711,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
align: ContentAlign.bottom,
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: MediaQuery.of(context).size.height*0.60,
|
||||
height: MediaQuery.of(context).size.height * 0.60,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
@ -408,8 +722,9 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Padding(padding: EdgeInsets.only(right: 10),
|
||||
child: Text(
|
||||
child: Padding(
|
||||
padding: EdgeInsets.only(right: 10),
|
||||
child: Text(
|
||||
'4/7',
|
||||
style: const TextStyle(
|
||||
color: Colors.white,
|
||||
@ -445,11 +760,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2.0),
|
||||
border: Border.all(
|
||||
color: Colors.white, width: 2.0),
|
||||
),
|
||||
child: IconButton(
|
||||
iconSize: 20,
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
icon: const Icon(Icons.arrow_back,
|
||||
color: Colors.white),
|
||||
onPressed: () {
|
||||
tutorialCoachMark.previous();
|
||||
},
|
||||
@ -460,14 +777,20 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Color(0xFF7DAFBC),
|
||||
border: Border.all(color: Color(0xFF7DAFBC), width: 1),
|
||||
border: Border.all(
|
||||
color: Color(0xFF7DAFBC), width: 1),
|
||||
),
|
||||
child: IconButton(
|
||||
iconSize: 20,
|
||||
icon: const Icon(Icons.arrow_forward, color: Colors.white),
|
||||
icon: const Icon(Icons.arrow_forward,
|
||||
color: Colors.white),
|
||||
onPressed: () {
|
||||
ref.read(chartsTourProvider.notifier).state=true;
|
||||
ref.read(scaffoldTourProvider.notifier).state=false;
|
||||
ref
|
||||
.read(chartsTourProvider.notifier)
|
||||
.state = true;
|
||||
ref
|
||||
.read(scaffoldTourProvider.notifier)
|
||||
.state = false;
|
||||
tutorialCoachMark.finish();
|
||||
},
|
||||
),
|
||||
@ -484,10 +807,10 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
),
|
||||
),
|
||||
TargetContent(
|
||||
padding: EdgeInsets.only(left:0, top:0),
|
||||
padding: EdgeInsets.only(left: 0, top: 0),
|
||||
align: ContentAlign.right,
|
||||
child: Container(
|
||||
width: screenWidth/4,
|
||||
width: screenWidth / 4,
|
||||
height: screenHeight,
|
||||
child: Stack(
|
||||
children: [
|
||||
@ -513,14 +836,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
void _initpreviousTargets(){
|
||||
final double screenWidth= MediaQuery.of(context).size.width;
|
||||
final double screenHeight= MediaQuery.of(context).size.height;
|
||||
previousMarriageTargets=[
|
||||
void _initpreviousTargets() {
|
||||
final double screenWidth = MediaQuery.of(context).size.width;
|
||||
final double screenHeight = MediaQuery.of(context).size.height;
|
||||
previousMarriageTargets = [
|
||||
TargetFocus(
|
||||
identify: 'BookMarkKey',
|
||||
keyTarget: bookMarkKey,
|
||||
@ -538,7 +860,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
align: ContentAlign.bottom,
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: MediaQuery.of(context).size.height*0.60,
|
||||
height: MediaQuery.of(context).size.height * 0.60,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
@ -549,7 +871,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
children: [
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child:Padding(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 10.0),
|
||||
child: Text(
|
||||
'4/7',
|
||||
@ -587,11 +909,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2.0),
|
||||
border: Border.all(
|
||||
color: Colors.white, width: 2.0),
|
||||
),
|
||||
child: IconButton(
|
||||
iconSize: 20,
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
icon: const Icon(Icons.arrow_back,
|
||||
color: Colors.white),
|
||||
onPressed: () {
|
||||
tutorialCoachMark.next();
|
||||
},
|
||||
@ -602,14 +926,20 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Color(0xFF7DAFBC),
|
||||
border: Border.all(color:Color(0xFF7DAFBC), width: 1.5),
|
||||
border: Border.all(
|
||||
color: Color(0xFF7DAFBC), width: 1.5),
|
||||
),
|
||||
child: IconButton(
|
||||
iconSize: 20,
|
||||
icon: const Icon(Icons.arrow_forward, color: Colors.white),
|
||||
icon: const Icon(Icons.arrow_forward,
|
||||
color: Colors.white),
|
||||
onPressed: () {
|
||||
ref.read(chartsTourProvider.notifier).state=true;
|
||||
ref.read(scaffoldTourProvider.notifier).state=false;
|
||||
ref
|
||||
.read(chartsTourProvider.notifier)
|
||||
.state = true;
|
||||
ref
|
||||
.read(scaffoldTourProvider.notifier)
|
||||
.state = false;
|
||||
tutorialCoachMark.finish();
|
||||
},
|
||||
),
|
||||
@ -626,10 +956,10 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
),
|
||||
),
|
||||
TargetContent(
|
||||
padding: EdgeInsets.only(left:0, top: 10),
|
||||
padding: EdgeInsets.only(left: 0, top: 10),
|
||||
align: ContentAlign.right,
|
||||
child: Container(
|
||||
width: screenWidth/4,
|
||||
width: screenWidth / 4,
|
||||
height: screenHeight,
|
||||
child: Stack(
|
||||
children: [
|
||||
@ -666,13 +996,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
text: AppLocalizations.of(context)!.kpiCards,
|
||||
space: 0,
|
||||
alignment: ContentAlign.top,
|
||||
gap:50,
|
||||
gap: 50,
|
||||
),
|
||||
TargetContent(
|
||||
align: ContentAlign.bottom,
|
||||
child: SizedBox(
|
||||
width: double.infinity,
|
||||
height: MediaQuery.of(context).size.height*0.30,
|
||||
height: MediaQuery.of(context).size.height * 0.30,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
@ -681,9 +1011,10 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
right: 16,
|
||||
child: Column(
|
||||
children: [
|
||||
Align(alignment: Alignment.bottomRight,
|
||||
child:Padding(
|
||||
padding: const EdgeInsets.only(right:10.0),
|
||||
Align(
|
||||
alignment: Alignment.bottomRight,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.only(right: 10.0),
|
||||
child: Text(
|
||||
'3/7',
|
||||
style: const TextStyle(
|
||||
@ -691,7 +1022,8 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
fontSize: 14,
|
||||
),
|
||||
),
|
||||
),),
|
||||
),
|
||||
),
|
||||
const SizedBox(height: 5),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
@ -719,14 +1051,22 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
Container(
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
border: Border.all(color: Colors.white, width: 2.0),
|
||||
border: Border.all(
|
||||
color: Colors.white, width: 2.0),
|
||||
),
|
||||
child: IconButton(
|
||||
iconSize: 20,
|
||||
icon: const Icon(Icons.arrow_back, color: Colors.white),
|
||||
icon: const Icon(Icons.arrow_back,
|
||||
color: Colors.white),
|
||||
onPressed: () {
|
||||
ref.read(previousChartsTourProvider.notifier).state=true;
|
||||
ref.read(previousHomeTourProvider.notifier).state=false;
|
||||
ref
|
||||
.read(previousChartsTourProvider
|
||||
.notifier)
|
||||
.state = true;
|
||||
ref
|
||||
.read(
|
||||
previousHomeTourProvider.notifier)
|
||||
.state = false;
|
||||
tutorialCoachMark.finish();
|
||||
},
|
||||
),
|
||||
@ -736,11 +1076,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
decoration: BoxDecoration(
|
||||
shape: BoxShape.circle,
|
||||
color: Color(0xFF7DAFBC),
|
||||
border: Border.all(color:Color(0xFF7DAFBC), width: 1.5),
|
||||
border: Border.all(
|
||||
color: Color(0xFF7DAFBC), width: 1.5),
|
||||
),
|
||||
child: IconButton(
|
||||
iconSize: 20,
|
||||
icon: const Icon(Icons.arrow_forward, color: Colors.white),
|
||||
icon: const Icon(Icons.arrow_forward,
|
||||
color: Colors.white),
|
||||
onPressed: () {
|
||||
tutorialCoachMark.previous();
|
||||
},
|
||||
@ -758,31 +1100,29 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
),
|
||||
),
|
||||
TargetContent(
|
||||
padding: EdgeInsets.only(bottom: 0,top : 0,),
|
||||
padding: EdgeInsets.only(
|
||||
bottom: 0,
|
||||
top: 0,
|
||||
),
|
||||
align: ContentAlign.top,
|
||||
child: SizedBox(
|
||||
width: MediaQuery.of(context).size.width,
|
||||
height:MediaQuery.of(context).size.height*0.69 ,
|
||||
child: Stack(
|
||||
children: [
|
||||
Positioned(
|
||||
left: MediaQuery.of(context).size.width*0.40,
|
||||
bottom: 0,
|
||||
child: Image.asset(
|
||||
'assets/app_tour/leftUp.png',
|
||||
width: 100,
|
||||
height: 90,
|
||||
),
|
||||
),
|
||||
]
|
||||
),
|
||||
|
||||
height: MediaQuery.of(context).size.height * 0.69,
|
||||
child: Stack(children: [
|
||||
Positioned(
|
||||
left: MediaQuery.of(context).size.width * 0.40,
|
||||
bottom: 0,
|
||||
child: Image.asset(
|
||||
'assets/app_tour/leftUp.png',
|
||||
width: 100,
|
||||
height: 90,
|
||||
),
|
||||
),
|
||||
]),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
|
||||
];
|
||||
}
|
||||
|
||||
@ -1295,8 +1635,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
});
|
||||
selectedFiltersStorage.clear();
|
||||
Navigator.pop(context);
|
||||
},
|
||||
|
||||
},
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Color(0xFF92722A),
|
||||
shape: RoundedRectangleBorder(
|
||||
@ -1305,7 +1644,8 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 0.0, vertical: 14.2), // Added padding
|
||||
horizontal: 0.0,
|
||||
vertical: 14.2), // Added padding
|
||||
child: Text(
|
||||
context.translate('Clear', 'واضح'),
|
||||
style: TextStyle(
|
||||
@ -1343,7 +1683,8 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.symmetric(
|
||||
horizontal: 0.0, vertical: 16.0), // Added padding
|
||||
horizontal: 0.0,
|
||||
vertical: 16.0), // Added padding
|
||||
child: FittedBox(
|
||||
fit: BoxFit
|
||||
.scaleDown, // Ensures text resizes if necessary
|
||||
@ -1360,7 +1701,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
maxLines: 1, // Ensures single line
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
@ -1602,11 +1943,35 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
),
|
||||
),
|
||||
SizedBox(width: 5),
|
||||
Image.asset(
|
||||
UaeNumbersAssetPath.bookmarksUae,
|
||||
color: Colors.white,
|
||||
width: 24,
|
||||
height: 24,
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
if (isBookmarked) {
|
||||
showRemoveBookmarkDialog();
|
||||
} else {
|
||||
showAddBookmarkDialog();
|
||||
}
|
||||
},
|
||||
child: Row(
|
||||
children: [
|
||||
Text(
|
||||
"Bookmark",
|
||||
style: const TextStyle(
|
||||
fontSize: 16,
|
||||
color: Colors.white),
|
||||
),
|
||||
const SizedBox(width: 5),
|
||||
Image.asset(
|
||||
isBookmarked
|
||||
? UaeNumbersAssetPath
|
||||
.bookmarksSelectedUae // Filled bookmark image
|
||||
: UaeNumbersAssetPath
|
||||
.bookmarksUae, // Default bookmark image
|
||||
// color: Colors.white,
|
||||
width: 24,
|
||||
height: 24,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
@ -1695,7 +2060,7 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(3.34),
|
||||
child: GridView.builder(
|
||||
key:cardKey,
|
||||
key: cardKey,
|
||||
itemCount: cardData.length,
|
||||
shrinkWrap: true,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
|
||||
@ -1,6 +1,11 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:pocketbase/pocketbase.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:uae_stat/domain/use_cases/language.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 {
|
||||
@ -11,93 +16,284 @@ class BookMark extends ConsumerStatefulWidget {
|
||||
}
|
||||
|
||||
class _BookMarkState extends ConsumerState<BookMark> {
|
||||
// Example dynamic data
|
||||
final List<Map<String, dynamic>> dataList = [
|
||||
{
|
||||
'title': 'GDP(Constant)',
|
||||
'subtitle': '(2022)(AED)',
|
||||
'value': '1.62T',
|
||||
'valueColor': Color(0xFF80A8CD),
|
||||
'isBookmark': true
|
||||
},
|
||||
{
|
||||
'title': 'Trade Value',
|
||||
'subtitle': '(Jan-Jan 2024)-AED',
|
||||
'value': '215.4B',
|
||||
'valueColor': Color(0xFF80A8CD),
|
||||
'isBookmark': true
|
||||
},
|
||||
{
|
||||
'title': 'Electricity Production',
|
||||
'subtitle': '(2022) (GWh)',
|
||||
'value': '155,438',
|
||||
'valueColor': Color(0xFFAA8E83),
|
||||
'isBookmark': true
|
||||
},
|
||||
{
|
||||
'title': 'Crude Oil Production',
|
||||
'subtitle': '(2022) (1000 b/d)',
|
||||
'value': '3,064',
|
||||
'valueColor': Color(0xFF80A8CD),
|
||||
'isBookmark': true
|
||||
},
|
||||
{
|
||||
'title': 'Quantitiy of Export Oil',
|
||||
'subtitle': '(2022) (1000 b/d)',
|
||||
'value': '2717',
|
||||
'valueColor': Color(0xFF7DAFBC),
|
||||
'isBookmark': true
|
||||
},
|
||||
{
|
||||
'title': 'Desalinated Water Production',
|
||||
'subtitle': '(2022) (MCM)',
|
||||
'value': '1823.8',
|
||||
'valueColor': Color(0xFF7DAFBC),
|
||||
'isBookmark': true
|
||||
},
|
||||
];
|
||||
final _pb = PocketBase('https://pb.venbait.in');
|
||||
List<Map<String, dynamic>> dataList = [];
|
||||
bool isLoading = true;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final filteredList =
|
||||
dataList.where((item) => item['isBookmark'] == true).toList();
|
||||
return PopScope(
|
||||
canPop: false, // Allow back navigation only if not login screen
|
||||
onPopInvokedWithResult: (didPop, result) {
|
||||
if (didPop) return;
|
||||
context.go('/myhomepage'); // Show exit confirmation dialog
|
||||
},
|
||||
child: BaseScaffold(
|
||||
title: Text('Bookmark'),
|
||||
body: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GridView.builder(
|
||||
gridDelegate: SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2, // Two columns
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
mainAxisExtent: 100,
|
||||
),
|
||||
itemCount: filteredList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _buildBox(filteredList[index], context);
|
||||
},
|
||||
void initState() {
|
||||
super.initState();
|
||||
final locale = ref.read(localeProvider);
|
||||
fetchBookmarks(locale?.languageCode ?? 'en');
|
||||
}
|
||||
|
||||
// Function to convert hex color string to int
|
||||
Color _parseColor(String? colorString) {
|
||||
if (colorString == null || colorString.isEmpty) {
|
||||
return const Color(0xFF80A8CD); // Default color
|
||||
}
|
||||
|
||||
try {
|
||||
return Color(int.parse(colorString.replaceFirst('#', '0xFF')));
|
||||
} catch (e) {
|
||||
debugPrint("Invalid color format: $colorString");
|
||||
return const Color(0xFF80A8CD); // Fallback color
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> fetchBookmarks(locale) async {
|
||||
try {
|
||||
final prefs = await SharedPreferences.getInstance();
|
||||
final userID = prefs.getString('userId') ?? '';
|
||||
|
||||
if (userID.isEmpty) {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
final response = await Dio().get(
|
||||
'https://pb.venbait.in/api/getUserBookmark',
|
||||
queryParameters: {'user_id': userID, 'language': locale},
|
||||
);
|
||||
|
||||
if (response.statusCode == 200 && response.data != null) {
|
||||
if (response.data is Map<String, dynamic> &&
|
||||
response.data.containsKey("error")) {
|
||||
// API returned an error message instead of bookmark data
|
||||
setState(() {
|
||||
dataList = []; // Clear the list
|
||||
});
|
||||
print("No bookmarks found.");
|
||||
} else {
|
||||
List<dynamic> fetchedData = response.data;
|
||||
setState(() {
|
||||
dataList = fetchedData.map((item) {
|
||||
return {
|
||||
'main_topic': item['main_topic'] ?? '',
|
||||
'title': item['data_set_tile_heading'] ?? '',
|
||||
'subtitle': item['sub_topic'] ?? '',
|
||||
'value': item['value'] ?? '',
|
||||
'value_source': item['value_source'] ?? '',
|
||||
'data_set': item['data_set'] ?? '',
|
||||
'valueColor': _parseColor(item['color_pattern']),
|
||||
'isBookmark': true,
|
||||
'id': item['id'],
|
||||
};
|
||||
}).toList();
|
||||
print('dataList $dataList');
|
||||
});
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
setState(() {
|
||||
dataList = []; // Clear the list
|
||||
});
|
||||
debugPrint("Error fetching bookmarks: $e");
|
||||
} finally {
|
||||
setState(() {
|
||||
isLoading = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// Remove bookmark from PocketBase
|
||||
Future<void> removeBookmark(bookmarkId) async {
|
||||
try {
|
||||
final adminAuth = await _pb.admins
|
||||
.authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
|
||||
final adminToken = adminAuth.token;
|
||||
|
||||
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.");
|
||||
|
||||
print("Bookmark removed");
|
||||
} catch (e) {
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'Unable to remove from bookmarks. Please try again',
|
||||
style:
|
||||
TextStyle(color: Color(0xFFEB5F24), fontWeight: FontWeight.w600),
|
||||
),
|
||||
backgroundColor: Color(0xFFD6E9C6),
|
||||
duration: Duration(seconds: 2),
|
||||
);
|
||||
print("Error removing bookmark: $e");
|
||||
}
|
||||
}
|
||||
|
||||
/// Show confirmation dialog before removing bookmark
|
||||
void showRemoveBookmarkDialog(id) {
|
||||
double myheight = MediaQuery.of(context).size.height;
|
||||
showDialog(
|
||||
context: context,
|
||||
barrierDismissible: false, // User must tap button to dismiss dialog
|
||||
builder: (context) => AlertDialog(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(5.0), // Rounded corners
|
||||
),
|
||||
contentPadding: EdgeInsets.zero,
|
||||
content: Stack(
|
||||
children: [
|
||||
Padding(
|
||||
padding: const EdgeInsets.all(10.0),
|
||||
child: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: myheight / 30,
|
||||
),
|
||||
Text(
|
||||
context.translate(
|
||||
'Are you sure you want to remove this bookmark?',
|
||||
'هل أنت متأكد أنك تريد إزالة هذه الإشارة المرجعية؟'),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
fontSize: 18,
|
||||
color: Color(0xFF898C81),
|
||||
),
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
actions: [
|
||||
SizedBox(height: 20),
|
||||
SizedBox(
|
||||
width: 100, // Set the desired width
|
||||
child: TextButton(
|
||||
onPressed: () => Navigator.pop(context),
|
||||
style: TextButton.styleFrom(
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(
|
||||
10.0), // Adjust the radius as needed
|
||||
),
|
||||
side: BorderSide(
|
||||
color: Color(0xFFAA8E83), // Set the outline color
|
||||
width: 1, // Set the border width
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
context.translate('No', 'لا'),
|
||||
style: TextStyle(
|
||||
color: Color(0xFFAA8E83),
|
||||
fontSize: 16,
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
SizedBox(
|
||||
width: 100, // Set the desired width
|
||||
child: TextButton(
|
||||
onPressed: () {
|
||||
Navigator.pop(context);
|
||||
removeBookmark(id); // Close dialog
|
||||
},
|
||||
style: TextButton.styleFrom(
|
||||
backgroundColor: Color(0xFFAA8E83), // Set background color
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(10.0), // Set text color
|
||||
),
|
||||
),
|
||||
child: Text(
|
||||
context.translate('Yes', 'نعم'),
|
||||
style: TextStyle(color: Colors.white, fontSize: 16),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
String colorToHex(Color color) {
|
||||
return '0xFF${color.red.toRadixString(16).padLeft(2, '0').toUpperCase()}'
|
||||
'${color.green.toRadixString(16).padLeft(2, '0').toUpperCase()}'
|
||||
'${color.blue.toRadixString(16).padLeft(2, '0').toUpperCase()}';
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
ref.listen<Locale?>(localeProvider, (previous, next) {
|
||||
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
|
||||
fetchBookmarks(localeCode);
|
||||
});
|
||||
final filteredList =
|
||||
dataList.where((item) => item['isBookmark'] == true).toList();
|
||||
|
||||
return PopScope(
|
||||
canPop: false,
|
||||
onPopInvokedWithResult: (didPop, result) {
|
||||
if (didPop) return;
|
||||
context.go('/myhomepage');
|
||||
},
|
||||
child: BaseScaffold(
|
||||
title: Text(context.translate('Bookmark', 'إشارة مرجعية')),
|
||||
body: isLoading
|
||||
? const Center(child: CircularProgressIndicator())
|
||||
: filteredList.isEmpty
|
||||
? Center(
|
||||
child: Text(context.translate('No bookmarks found',
|
||||
'لم يتم العثور على إشارات مرجعية')))
|
||||
: Padding(
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
child: GridView.builder(
|
||||
gridDelegate:
|
||||
const SliverGridDelegateWithFixedCrossAxisCount(
|
||||
crossAxisCount: 2,
|
||||
crossAxisSpacing: 10.0,
|
||||
mainAxisSpacing: 10.0,
|
||||
mainAxisExtent: 100,
|
||||
),
|
||||
itemCount: filteredList.length,
|
||||
itemBuilder: (context, index) {
|
||||
return _buildBox(filteredList[index], context);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Widget for creating a box
|
||||
Widget _buildBox(Map<String, dynamic> data, BuildContext context) {
|
||||
// Color borderColor = data['valueColor'];
|
||||
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(colorPattern); // Get hex string
|
||||
print(hexColor); // Prints: 0xFFAA8E83
|
||||
|
||||
debugPrint("Box clicked: ${data['title']}");
|
||||
context.go(
|
||||
'/chartScreen/$data_set?bgColor=$hexColor&mainTopic=$encodedMainTopic&title=$encodedTitle');
|
||||
},
|
||||
child: Container(
|
||||
width: MediaQuery.of(context).size.width * 0.4,
|
||||
height: 100,
|
||||
padding: EdgeInsets.all(8.0),
|
||||
padding: const EdgeInsets.all(8.0),
|
||||
decoration: BoxDecoration(
|
||||
color: Colors.white,
|
||||
borderRadius: BorderRadius.circular(10),
|
||||
@ -120,54 +316,18 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
alignment: Alignment.center,
|
||||
child: Text(
|
||||
data['title'] ?? '',
|
||||
style: TextStyle(
|
||||
fontWeight: FontWeight.w500,
|
||||
),
|
||||
style: const TextStyle(fontWeight: FontWeight.w500),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
// Truncate long text
|
||||
maxLines: 1, // Limit to 1 line
|
||||
maxLines: 1,
|
||||
),
|
||||
),
|
||||
),
|
||||
GestureDetector(
|
||||
onTap: () {
|
||||
debugPrint("Icon clicked in: ${data['title']}");
|
||||
setState(() {
|
||||
// Change isOpen to false when icon is clicked
|
||||
int index = dataList.indexWhere(
|
||||
(item) => item['title'] == data['title'],
|
||||
);
|
||||
if (index != -1) {
|
||||
dataList[index]['isBookmark'] = false;
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'Removed From Bookmark',
|
||||
style: TextStyle(
|
||||
color: Color(0xFF2F692C),
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
backgroundColor: Color(0xFFD6E9C6),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
} else {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'Failed to Remove',
|
||||
style: TextStyle(
|
||||
color: Color(0xFFEB5F24),
|
||||
fontWeight: FontWeight.w600),
|
||||
),
|
||||
backgroundColor: Color(0xFF544C4C),
|
||||
duration: Duration(seconds: 2),
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
showRemoveBookmarkDialog(data['id']);
|
||||
},
|
||||
child: Icon(
|
||||
child: const Icon(
|
||||
Icons.bookmarks_rounded,
|
||||
color: Colors.black,
|
||||
size: 20,
|
||||
@ -176,8 +336,8 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
||||
],
|
||||
),
|
||||
Text(
|
||||
data['subtitle'] ?? '',
|
||||
style: TextStyle(
|
||||
data['value_source'] ?? '',
|
||||
style: const TextStyle(
|
||||
fontWeight: FontWeight.w500, color: Colors.grey),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
maxLines: 1,
|
||||
|
||||
@ -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.10+11
|
||||
version: 1.0.11+12
|
||||
|
||||
environment:
|
||||
sdk: ">=3.2.3 <4.0.0"
|
||||
@ -37,7 +37,7 @@ dependencies:
|
||||
pocketbase: ^0.18.1
|
||||
flutter_secure_storage: ^9.0.0
|
||||
jwt_decoder: ^2.0.1
|
||||
fluttertoast: ^8.2.5
|
||||
fluttertoast: ^8.2.11
|
||||
webview_flutter: ^4.5.0
|
||||
video_player: ^2.8.5
|
||||
flutter_carousel_widget: ^3.1.0
|
||||
@ -113,6 +113,7 @@ flutter:
|
||||
- assets/edit_profile/
|
||||
- assets/splash_screen/
|
||||
- assets/icons/uae_numbers/bookmarks.png
|
||||
- assets/icons/uae_numbers/bookmarksSelectedUae.png
|
||||
- assets/icons/uae_numbers/share.png
|
||||
- assets/icons/misc/vector.png
|
||||
- assets/icons/misc/visible_on.png
|
||||
|
||||
Loading…
Reference in New Issue
Block a user