chart screen merged
This commit is contained in:
commit
9368e08f91
4
assets/icons/bookmark/delete.svg
Normal file
4
assets/icons/bookmark/delete.svg
Normal 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 |
@ -0,0 +1,4 @@
|
|||||||
|
abstract class BookmarkAssetPath {
|
||||||
|
static const _basePath = 'assets/icons/bookmark';
|
||||||
|
static const delete = '$_basePath/delete.svg';
|
||||||
|
}
|
||||||
@ -319,103 +319,103 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//when the popup need for bookmark
|
//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() {
|
void showAddBookmarkDialog() {
|
||||||
addBookmark();
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
showDialog(
|
||||||
// SnackBar(
|
context: context,
|
||||||
// content: Text(
|
barrierDismissible: false, // User must tap button to dismiss dialog
|
||||||
// 'The bookmark is added successfully',
|
builder: (context) => AlertDialog(
|
||||||
// ),
|
shape: RoundedRectangleBorder(
|
||||||
// backgroundColor: Colors.green,
|
borderRadius: BorderRadius.circular(5.0), // Rounded corners
|
||||||
// duration: Duration(seconds: 2),
|
),
|
||||||
// ),
|
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() {
|
void handleSkip() {
|
||||||
tutorialCoachMark.skip();
|
tutorialCoachMark.skip();
|
||||||
@ -2048,8 +2048,27 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
showAddBookmarkDialog();
|
showAddBookmarkDialog();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
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(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
isBookmarked?
|
||||||
|
Text(
|
||||||
|
context.translate(
|
||||||
|
'Bookmarked',
|
||||||
|
'إشارة مرجعية',
|
||||||
|
),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
color: Color(int.parse(
|
||||||
|
(chartScreenData['body_color'] ?? '#898C81')
|
||||||
|
.replaceFirst('#', '0xff'))),
|
||||||
|
),
|
||||||
|
):
|
||||||
Text(
|
Text(
|
||||||
context.translate(
|
context.translate(
|
||||||
'Bookmark',
|
'Bookmark',
|
||||||
@ -2080,15 +2099,18 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
// height: 24,
|
// height: 24,
|
||||||
// ),
|
// ),
|
||||||
Icon(
|
Icon(
|
||||||
|
size: 24,
|
||||||
Icons.bookmarks_rounded,
|
Icons.bookmarks_rounded,
|
||||||
color: isBookmarked
|
color: isBookmarked
|
||||||
? Colors.black
|
? Color(int.parse(
|
||||||
|
(chartScreenData['body_color'] ?? '#898C81')
|
||||||
|
.replaceFirst('#', '0xff')))
|
||||||
: Colors.white,
|
: Colors.white,
|
||||||
size: 23,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
@ -2106,77 +2128,13 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
),
|
),
|
||||||
SizedBox(width: 5),
|
SizedBox(width: 5),
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () async {
|
onTap: () => shareCurrentPage(context),
|
||||||
try {
|
child: SvgPicture.asset(
|
||||||
// Define share content
|
UaeNumbersAssetPath.share,
|
||||||
final String shareLink =
|
semanticsLabel: 'share',
|
||||||
'https://fcsc-da580.web.app'; // Your link
|
|
||||||
final String shareText =
|
|
||||||
'Check this out!';
|
|
||||||
final String svgAssetPath =
|
|
||||||
'assets/logos/fcsc.png'; // Your SVG asset path
|
|
||||||
|
|
||||||
// Create a controller to capture the SVG as an image
|
|
||||||
final screenshotController =
|
|
||||||
ScreenshotController();
|
|
||||||
|
|
||||||
// Render the SVG off-screen and capture it as PNG
|
|
||||||
final svgWidget = SvgPicture.asset(
|
|
||||||
svgAssetPath,
|
|
||||||
width: 200, // Adjust size as needed
|
|
||||||
height: 200,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Capture the SVG as a PNG
|
|
||||||
final Uint8List? capturedImage =
|
|
||||||
await screenshotController
|
|
||||||
.captureFromWidget(
|
|
||||||
Material(
|
|
||||||
child: svgWidget,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
if (capturedImage == null) {
|
|
||||||
throw Exception(
|
|
||||||
'Failed to capture SVG as image');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Save the captured PNG to a temporary file
|
|
||||||
final directory =
|
|
||||||
await getTemporaryDirectory();
|
|
||||||
final file = File(
|
|
||||||
'${directory.path}/shared_image.png');
|
|
||||||
await file.writeAsBytes(capturedImage);
|
|
||||||
|
|
||||||
// Share the PNG file with text and link
|
|
||||||
await Share.shareXFiles(
|
|
||||||
[XFile(file.path)],
|
|
||||||
text: '$shareText\n$shareLink',
|
|
||||||
subject: 'Shared Content',
|
|
||||||
);
|
|
||||||
|
|
||||||
// Clean up temporary file
|
|
||||||
await file.delete();
|
|
||||||
} catch (e) {
|
|
||||||
print("Error sharing file: $e");
|
|
||||||
ScaffoldMessenger.of(context)
|
|
||||||
.showSnackBar(
|
|
||||||
SnackBar(
|
|
||||||
content:
|
|
||||||
Text('Error sharing: $e')),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: Container(
|
|
||||||
width: 24,
|
width: 24,
|
||||||
height: 24,
|
height: 24,
|
||||||
child: Icon(
|
)
|
||||||
Icons.share,
|
|
||||||
color: Colors.white,
|
|
||||||
size: 24,
|
|
||||||
semanticLabel: 'Share',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -2825,7 +2783,47 @@ class _ChartScreen1State extends ConsumerState<ChartScreen1> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Future<void> shareCurrentPage(BuildContext context) async {
|
||||||
|
try {
|
||||||
|
// Get current route from go_router
|
||||||
|
final String currentRoute = GoRouterState.of(context).uri.toString();
|
||||||
|
final String baseAppLink = 'https://fcsc-da580.web.app';
|
||||||
|
final String shareLink = '$baseAppLink$currentRoute';
|
||||||
|
final String shareText = 'Check this out!';
|
||||||
|
final String svgAssetPath = 'assets/logos/fcsc.png';
|
||||||
|
|
||||||
|
final screenshotController = ScreenshotController();
|
||||||
|
final svgWidget = SvgPicture.asset(
|
||||||
|
svgAssetPath,
|
||||||
|
width: 200,
|
||||||
|
height: 200,
|
||||||
|
);
|
||||||
|
final Uint8List? capturedImage = await screenshotController.captureFromWidget(
|
||||||
|
Material(child: svgWidget),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (capturedImage == null) {
|
||||||
|
throw Exception('Failed to capture SVG as image');
|
||||||
|
}
|
||||||
|
|
||||||
|
final directory = await getTemporaryDirectory();
|
||||||
|
final file = File('${directory.path}/shared_image.png');
|
||||||
|
await file.writeAsBytes(capturedImage);
|
||||||
|
|
||||||
|
await Share.shareXFiles(
|
||||||
|
[XFile(file.path)],
|
||||||
|
text: '$shareText\n$shareLink',
|
||||||
|
subject: 'Shared Content',
|
||||||
|
);
|
||||||
|
|
||||||
|
await file.delete();
|
||||||
|
} catch (e) {
|
||||||
|
print("Error sharing file: $e");
|
||||||
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
|
SnackBar(content: Text('Error sharing: $e')),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
// Function to convert hex color string to Color
|
// Function to convert hex color string to Color
|
||||||
Color _getColorFromHex(String hexColor) {
|
Color _getColorFromHex(String hexColor) {
|
||||||
hexColor = hexColor.replaceFirst('#', '');
|
hexColor = hexColor.replaceFirst('#', '');
|
||||||
|
|||||||
@ -1,10 +1,13 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
|
import 'package:flutter_svg/svg.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:pocketbase/pocketbase.dart';
|
import 'package:pocketbase/pocketbase.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:uae_stat/domain/use_cases/language.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/components/indicators/locale_provider.dart';
|
||||||
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.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 = [];
|
List<Map<String, dynamic>> dataList = [];
|
||||||
bool isLoading = true;
|
bool isLoading = true;
|
||||||
|
|
||||||
|
// Current selected tab index
|
||||||
|
int selectedTabIndex = 0;
|
||||||
|
|
||||||
|
// Tab categories
|
||||||
|
final List<String> tabs = [
|
||||||
|
'All Bookmarks',
|
||||||
|
'Economy',
|
||||||
|
'Social',
|
||||||
|
'Environment',
|
||||||
|
];
|
||||||
|
|
||||||
@override
|
@override
|
||||||
void initState() {
|
void initState() {
|
||||||
super.initState();
|
super.initState();
|
||||||
@ -27,6 +41,11 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
fetchBookmarks(locale?.languageCode ?? 'en');
|
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
|
// Function to convert hex color string to int
|
||||||
Color _parseColor(String? colorString) {
|
Color _parseColor(String? colorString) {
|
||||||
if (colorString == null || colorString.isEmpty) {
|
if (colorString == null || colorString.isEmpty) {
|
||||||
@ -98,7 +117,6 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Remove bookmark from PocketBase
|
|
||||||
Future<void> removeBookmark(bookmarkId) async {
|
Future<void> removeBookmark(bookmarkId) async {
|
||||||
try {
|
try {
|
||||||
final adminAuth = await _pb.admins
|
final adminAuth = await _pb.admins
|
||||||
@ -124,6 +142,18 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
fetchBookmarks(locale?.languageCode ?? 'en');
|
fetchBookmarks(locale?.languageCode ?? 'en');
|
||||||
// ToastUtil.showSuccessToast("Removed from Bookmark.");
|
// 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");
|
print("Bookmark removed");
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
SnackBar(
|
SnackBar(
|
||||||
@ -139,7 +169,6 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Show confirmation dialog before removing bookmark
|
|
||||||
void showRemoveBookmarkDialog(id) {
|
void showRemoveBookmarkDialog(id) {
|
||||||
double myheight = MediaQuery.of(context).size.height;
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
showDialog(
|
showDialog(
|
||||||
@ -208,7 +237,7 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
removeBookmark(id); // Close dialog
|
removeBookmark(id);
|
||||||
},
|
},
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
backgroundColor: Color(0xFFAA8E83), // Set background color
|
backgroundColor: Color(0xFFAA8E83), // Set background color
|
||||||
@ -231,35 +260,63 @@ 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
|
@override
|
||||||
Widget build(BuildContext context) {
|
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(
|
List<Map<String, dynamic>> bookmarks = dataList.where((item) => item['isBookmark'] == true).toList();
|
||||||
canPop: false,
|
List<Map<String, dynamic>> filteredBookmarks = dataList
|
||||||
onPopInvokedWithResult: (didPop, result) {
|
.where((bookmark) =>
|
||||||
if (didPop) return;
|
bookmark['main_topic'].toString().trim().toLowerCase() == tabs[selectedTabIndex].toString().trim().toLowerCase())
|
||||||
context.go('/myhomepage');
|
.toList();
|
||||||
|
|
||||||
|
print('filtered $filteredBookmarks');
|
||||||
|
return BaseScaffold(
|
||||||
|
title: Text('Bookmarks'),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
TabBarHeader(
|
||||||
|
tabs: tabs,
|
||||||
|
selectedIndex: selectedTabIndex,
|
||||||
|
onTabSelected: (index) {
|
||||||
|
setState(() {
|
||||||
|
selectedTabIndex = index;
|
||||||
|
});
|
||||||
},
|
},
|
||||||
child: BaseScaffold(
|
),
|
||||||
title: Text(context.translate('Bookmark', 'إشارة مرجعية')),
|
Expanded(
|
||||||
body: isLoading
|
child: selectedTabIndex == 0
|
||||||
? const Center(child: CircularProgressIndicator())
|
? Padding(
|
||||||
: filteredList.isEmpty
|
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(
|
? Center(
|
||||||
child: Text(context.translate('No bookmarks found',
|
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(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: GridView.builder(
|
child: GridView.builder(
|
||||||
@ -270,16 +327,21 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
mainAxisSpacing: 10.0,
|
mainAxisSpacing: 10.0,
|
||||||
mainAxisExtent: 100,
|
mainAxisExtent: 100,
|
||||||
),
|
),
|
||||||
itemCount: filteredList.length,
|
itemCount: filteredBookmarks.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return _buildBox(filteredList[index], context);
|
return _buildBox(filteredBookmarks[index], context);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
],
|
||||||
|
|
||||||
|
),
|
||||||
|
|
||||||
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildBox(Map<String, dynamic> data, BuildContext context) {
|
Widget _buildBox(Map<String, dynamic> data, BuildContext context) {
|
||||||
// Color borderColor = data['valueColor'];
|
// Color borderColor = data['valueColor'];
|
||||||
return GestureDetector(
|
return GestureDetector(
|
||||||
@ -331,56 +393,28 @@ class _BookMarkState extends ConsumerState<BookMark> {
|
|||||||
GestureDetector(
|
GestureDetector(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
debugPrint("Icon clicked in: ${data['title']}");
|
debugPrint("Icon clicked in: ${data['title']}");
|
||||||
removeBookmark(data['id']);
|
showRemoveBookmarkDialog(data['id']);
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
// removeBookmark(data['id']);
|
||||||
SnackBar(
|
|
||||||
content: Text(
|
|
||||||
'Removed from BookMark',
|
|
||||||
),
|
|
||||||
backgroundColor: Colors.black,
|
|
||||||
duration: Duration(seconds: 2),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: const Icon(
|
child: SvgPicture.asset(
|
||||||
Icons.bookmarks_rounded,
|
BookmarkAssetPath.delete,
|
||||||
color: Colors.black,
|
semanticsLabel: 'share',
|
||||||
size: 20,
|
width:23,
|
||||||
),
|
height: 20,
|
||||||
|
)
|
||||||
),
|
),
|
||||||
|
|
||||||
// GestureDetector(
|
// GestureDetector(
|
||||||
// onTap: () {
|
// onTap: () {
|
||||||
// debugPrint("Icon clicked in: ${data['title']}");
|
// debugPrint("Icon clicked in: ${data['title']}");
|
||||||
// removeBookmark(data['id']);
|
// // showRemoveBookmarkDialog(data['id']);
|
||||||
// ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
// SnackBar(
|
|
||||||
// content: Text(
|
|
||||||
// 'The bookmark is removed successfully',
|
|
||||||
// ),
|
|
||||||
// backgroundColor: Colors.green,
|
|
||||||
// duration: Duration(seconds: 2),
|
|
||||||
// ),
|
|
||||||
// );
|
|
||||||
// },
|
// },
|
||||||
// child: const Icon(
|
// child: const Icon(
|
||||||
// Icons.delete,
|
// Icons.bookmarks_rounded,
|
||||||
// color: Colors.black,
|
// color: Colors.black,
|
||||||
// size: 20,
|
// 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(
|
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,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@ -1078,12 +1078,12 @@ class _BaseScaffoldState extends ConsumerState<BaseScaffold> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
void _showLogoutConfirmationDialog(context) {
|
void _showLogoutConfirmationDialog(BuildContext context) {
|
||||||
double myheight = MediaQuery.of(context).size.height;
|
double myheight = MediaQuery.of(context).size.height;
|
||||||
showDialog(
|
showDialog(
|
||||||
context: context,
|
context: context,
|
||||||
barrierDismissible: false, // User must tap a button to dismiss dialog
|
barrierDismissible: false, // User must tap a button to dismiss dialog
|
||||||
builder: (context) => AlertDialog(
|
builder: (dialogContext) => AlertDialog(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(5.0), // Rounded corners
|
borderRadius: BorderRadius.circular(5.0), // Rounded corners
|
||||||
),
|
),
|
||||||
@ -1113,7 +1113,7 @@ void _showLogoutConfirmationDialog(context) {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: 120, // Set button width
|
width: 120, // Set button width
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(dialogContext),
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: BorderRadius.circular(10.0),
|
borderRadius: BorderRadius.circular(10.0),
|
||||||
@ -1135,9 +1135,9 @@ void _showLogoutConfirmationDialog(context) {
|
|||||||
SizedBox(
|
SizedBox(
|
||||||
width: 120, // Set button width
|
width: 120, // Set button width
|
||||||
child: TextButton(
|
child: TextButton(
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
Navigator.pop(context);
|
await logout(dialogContext); // Pass dialogContext to logout
|
||||||
// Add logout function here
|
Navigator.pop(dialogContext); // Close the dialog
|
||||||
},
|
},
|
||||||
style: TextButton.styleFrom(
|
style: TextButton.styleFrom(
|
||||||
backgroundColor: Color(0xFFAA8E83), // Background color
|
backgroundColor: Color(0xFFAA8E83), // Background color
|
||||||
@ -1160,3 +1160,10 @@ void _showLogoutConfirmationDialog(context) {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<void> logout(BuildContext context) async {
|
||||||
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
await prefs.clear(); // Clear shared preferences
|
||||||
|
context.go('/login'); // Navigate to the root route (e.g., login screen)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,6 +7,7 @@ import Foundation
|
|||||||
|
|
||||||
import connectivity_plus
|
import connectivity_plus
|
||||||
import file_selector_macos
|
import file_selector_macos
|
||||||
|
import firebase_core
|
||||||
import flutter_secure_storage_macos
|
import flutter_secure_storage_macos
|
||||||
import package_info_plus
|
import package_info_plus
|
||||||
import path_provider_foundation
|
import path_provider_foundation
|
||||||
@ -19,6 +20,7 @@ import webview_flutter_wkwebview
|
|||||||
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
||||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||||
|
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||||
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin"))
|
||||||
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin"))
|
||||||
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin"))
|
||||||
|
|||||||
24
pubspec.lock
24
pubspec.lock
@ -429,6 +429,30 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.9.3+3"
|
version: "0.9.3+3"
|
||||||
|
firebase_core:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: firebase_core
|
||||||
|
sha256: "26de145bb9688a90962faec6f838247377b0b0d32cc0abecd9a4e43525fc856c"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.32.0"
|
||||||
|
firebase_core_platform_interface:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_core_platform_interface
|
||||||
|
sha256: d7253d255ff10f85cfd2adaba9ac17bae878fa3ba577462451163bd9f1d1f0bf
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "5.4.0"
|
||||||
|
firebase_core_web:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: firebase_core_web
|
||||||
|
sha256: e47f5c2776de018fa19bc9f6f723df136bc75cdb164d64b65305babd715c8e41
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "2.21.0"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
@ -33,7 +33,7 @@ dependencies:
|
|||||||
csv: ^6.0.0
|
csv: ^6.0.0
|
||||||
excel: ^4.0.2
|
excel: ^4.0.2
|
||||||
intl: ^0.19.0
|
intl: ^0.19.0
|
||||||
# firebase_core: ^2.27.0
|
firebase_core: ^2.27.0
|
||||||
the_validator: ^2.0.0
|
the_validator: ^2.0.0
|
||||||
pocketbase: ^0.18.1
|
pocketbase: ^0.18.1
|
||||||
flutter_secure_storage: ^9.0.0
|
flutter_secure_storage: ^9.0.0
|
||||||
@ -138,7 +138,7 @@ flutter:
|
|||||||
- assets/app_tour/
|
- assets/app_tour/
|
||||||
- assets/icons/misc/group.png
|
- assets/icons/misc/group.png
|
||||||
- assets/icons/misc/search.png
|
- assets/icons/misc/search.png
|
||||||
|
- assets/icons/bookmark/
|
||||||
|
|
||||||
fonts:
|
fonts:
|
||||||
- family: Segoe
|
- family: Segoe
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user