bookmark categrized

This commit is contained in:
Kalonkarthik 2025-02-21 17:57:08 +05:30
parent dc3bfbbaaa
commit 0dc95dd633
5 changed files with 352 additions and 230 deletions

View File

@ -0,0 +1,4 @@
<svg width="21" height="20" viewBox="0 0 21 20" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="20.913" height="19.24" rx="9.62" fill="white"/>
<path d="M6.63641 16.0334C6.24603 16.0334 5.91375 15.9073 5.63955 15.655C5.36536 15.4028 5.22826 15.0973 5.22826 14.7387V4.81006H4.35689V4.0084H7.8424V3.39111H13.0707V4.0084H16.5562V4.81006H15.6848V14.7387C15.6848 15.1075 15.5506 15.4156 15.2822 15.663C15.0138 15.9105 14.6786 16.0339 14.2766 16.0334H6.63641ZM14.8134 4.81006H6.09964V14.7387C6.09964 14.8825 6.14989 15.0006 6.25039 15.093C6.35089 15.1855 6.47956 15.2317 6.63641 15.2317H14.2775C14.4111 15.2317 14.534 15.1804 14.6461 15.0778C14.7582 14.9752 14.814 14.8619 14.8134 14.7379V4.81006ZM8.54647 13.6284H9.41785V6.4134H8.54647V13.6284ZM11.4952 13.6284H12.3666V6.4134H11.4952V13.6284Z" fill="#F14137"/>
</svg>

After

Width:  |  Height:  |  Size: 826 B

View File

@ -0,0 +1,4 @@
abstract class BookmarkAssetPath {
static const _basePath = 'assets/icons/bookmark';
static const delete = '$_basePath/delete.svg';
}

View File

@ -155,17 +155,17 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
});
// ToastUtil.showSuccessToast("Added to Bookmark.");
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(
// AppLocalizations.of(context)!.added_to_Bookmark,
// style: TextStyle(
// color: Color(0xFF2F692C), fontWeight: FontWeight.w600),
// ),
// backgroundColor: Color(0xFFD6E9C6),
// duration: Duration(seconds: 2),
// ),
// );
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context)!.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) {
@ -319,103 +319,103 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
}
//when the popup need for bookmark
// 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 showAddBookmarkDialog() {
addBookmark();
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(
// 'The bookmark is added successfully',
// ),
// backgroundColor: Colors.green,
// duration: Duration(seconds: 2),
// ),
// );
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 showAddBookmarkDialog() {
// addBookmark();
// // ScaffoldMessenger.of(context).showSnackBar(
// // SnackBar(
// // content: Text(
// // 'The bookmark is added successfully',
// // ),
// // backgroundColor: Colors.green,
// // duration: Duration(seconds: 2),
// // ),
// // );
// }
void handleSkip() {
tutorialCoachMark.skip();
@ -2028,45 +2028,67 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
showAddBookmarkDialog();
}
},
child: Row(
children: [
Text(
context.translate(
'Bookmark',
'إشارة مرجعية',
child: Container(
padding: EdgeInsets.all(4),
decoration: BoxDecoration(
color: isBookmarked ?Colors.white.withAlpha(90):null, // Background color
borderRadius: BorderRadius.circular(8), // Curved corners
),
child: Row(
children: [
isBookmarked?
Text(
context.translate(
'Bookmarked',
'إشارة مرجعية',
),
style: TextStyle(
fontSize: 16,
color: Color(int.parse(
(chartScreenData['body_color'] ?? '#898C81')
.replaceFirst('#', '0xff'))),
),
):
Text(
context.translate(
'Bookmark',
'إشارة مرجعية',
),
style: const TextStyle(
fontSize: 16,
color: Colors.white,
),
),
style: const TextStyle(
fontSize: 16,
color: Colors.white,
),
),
SizedBox(width: 5),
SizedBox(width: 5),
// 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,
// ),
Icon(
Icons.bookmarks_rounded,
color: isBookmarked
? Colors.black
: Colors.white,
size: 23,
),
],
// 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,
// ),
Icon(
size: 24,
Icons.bookmarks_rounded,
color: isBookmarked
? Color(int.parse(
(chartScreenData['body_color'] ?? '#898C81')
.replaceFirst('#', '0xff')))
: Colors.white,
),
],
),
),
),
],

View File

@ -1,10 +1,13 @@
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: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/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';
@ -20,6 +23,17 @@ class _BookMarkState extends ConsumerState<BookMark> {
List<Map<String, dynamic>> dataList = [];
bool isLoading = true;
// Current selected tab index
int selectedTabIndex = 0;
// Tab categories
final List<String> tabs = [
'All Bookmarks',
'Economy',
'Social',
'Environment',
];
@override
void initState() {
super.initState();
@ -27,6 +41,11 @@ class _BookMarkState extends ConsumerState<BookMark> {
fetchBookmarks(locale?.languageCode ?? 'en');
}
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()}';
}
// Function to convert hex color string to int
Color _parseColor(String? colorString) {
if (colorString == null || colorString.isEmpty) {
@ -98,7 +117,6 @@ class _BookMarkState extends ConsumerState<BookMark> {
}
}
/// Remove bookmark from PocketBase
Future<void> removeBookmark(bookmarkId) async {
try {
final adminAuth = await _pb.admins
@ -124,13 +142,25 @@ class _BookMarkState extends ConsumerState<BookMark> {
fetchBookmarks(locale?.languageCode ?? 'en');
// ToastUtil.showSuccessToast("Removed from Bookmark.");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Removed From Bookmark',
style: TextStyle(color: Color(0xFF2F692C),
fontWeight: FontWeight.w500),
),
backgroundColor: Color(0xFFD6E9C6),
duration: Duration(seconds: 2),
),
);
print("Bookmark removed");
} catch (e) {
SnackBar(
content: Text(
'Unable to remove from bookmarks. Please try again',
style:
TextStyle(color: Color(0xFFEB5F24), fontWeight: FontWeight.w600),
TextStyle(color: Color(0xFFEB5F24), fontWeight: FontWeight.w600),
),
backgroundColor: Color(0xFFD6E9C6),
duration: Duration(seconds: 2),
@ -139,7 +169,6 @@ class _BookMarkState extends ConsumerState<BookMark> {
}
}
/// Show confirmation dialog before removing bookmark
void showRemoveBookmarkDialog(id) {
double myheight = MediaQuery.of(context).size.height;
showDialog(
@ -208,7 +237,7 @@ class _BookMarkState extends ConsumerState<BookMark> {
child: TextButton(
onPressed: () {
Navigator.pop(context);
removeBookmark(id); // Close dialog
removeBookmark(id);
},
style: TextButton.styleFrom(
backgroundColor: Color(0xFFAA8E83), // Set background color
@ -231,55 +260,88 @@ class _BookMarkState extends ConsumerState<BookMark> {
);
}
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
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();
print('filtered $filteredBookmarks');
return BaseScaffold(
title: Text('Bookmarks'),
body: Column(
children: [
TabBarHeader(
tabs: tabs,
selectedIndex: selectedTabIndex,
onTabSelected: (index) {
setState(() {
selectedTabIndex = index;
});
},
),
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);
},
),
):filteredBookmarks.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);
},
),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.info_outline,
size: 100, color: Colors.grey[400]),
SizedBox(height: 16),
Text(
'No Bookmark is added',
style:
TextStyle(fontSize: 16, color: Colors.grey),
),
],
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
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);
},
),
),
),
],
),
);
}
Widget _buildBox(Map<String, dynamic> data, BuildContext context) {
// Color borderColor = data['valueColor'];
return GestureDetector(
@ -329,58 +391,30 @@ class _BookMarkState extends ConsumerState<BookMark> {
),
),
GestureDetector(
onTap: () {
debugPrint("Icon clicked in: ${data['title']}");
removeBookmark(data['id']);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
'Removed from BookMark',
),
backgroundColor: Colors.black,
duration: Duration(seconds: 2),
),
);
},
child: const Icon(
Icons.bookmarks_rounded,
color: Colors.black,
size: 20,
),
onTap: () {
debugPrint("Icon clicked in: ${data['title']}");
showRemoveBookmarkDialog(data['id']);
// removeBookmark(data['id']);
},
child: SvgPicture.asset(
BookmarkAssetPath.delete,
semanticsLabel: 'share',
width:23,
height: 20,
)
),
// GestureDetector(
// onTap: () {
// debugPrint("Icon clicked in: ${data['title']}");
// removeBookmark(data['id']);
// ScaffoldMessenger.of(context).showSnackBar(
// SnackBar(
// content: Text(
// 'The bookmark is removed successfully',
// ),
// backgroundColor: Colors.green,
// duration: Duration(seconds: 2),
// ),
// );
// // showRemoveBookmarkDialog(data['id']);
// },
// child: const Icon(
// Icons.delete,
// Icons.bookmarks_rounded,
// color: Colors.black,
// size: 20,
// ),
// ),
GestureDetector(
onTap: () {
debugPrint("Icon clicked in: ${data['title']}");
showRemoveBookmarkDialog(data['id']);
},
child: const Icon(
Icons.bookmarks_rounded,
color: Colors.black,
size: 20,
),
),
],
),
Text(
@ -407,3 +441,61 @@ class _BookMarkState extends ConsumerState<BookMark> {
);
}
}
class TabBarHeader extends StatelessWidget {
final List<String> tabs;
final int selectedIndex;
final ValueChanged<int> onTabSelected;
const TabBarHeader({
required this.tabs,
required this.selectedIndex,
required this.onTabSelected,
});
@override
Widget build(BuildContext context) {
return Container(
color: Colors.white,
padding: const EdgeInsets.symmetric(vertical: 8),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
mainAxisAlignment: MainAxisAlignment.start,
children: tabs.asMap().entries.map((entry) {
int index = entry.key;
String text = entry.value;
return Row(
children: [
TextButton(
onPressed: () => onTabSelected(index),
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.resolveWith((states) {
return selectedIndex == index
? Colors.black
: Colors.grey[700];
}),
),
child: Text(text),
),
if (index < tabs.length - 1) buildDivider(),
],
);
}).toList(),
),
),
);
}
Widget buildDivider() {
return Container(
height: 20,
child: const VerticalDivider(
color: Colors.grey,
thickness: 1,
width: 16,
),
);
}
}

View File

@ -138,7 +138,7 @@ flutter:
- assets/app_tour/
- assets/icons/misc/group.png
- assets/icons/misc/search.png
- assets/icons/bookmark/
fonts:
- family: Segoe