uaestats_fe/lib/presentation/routes/drawer_routes/Drawer Items/bookmark.dart
2026-05-29 17:45:19 +05:30

1155 lines
42 KiB
Dart
Executable File

import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:flutter_svg/svg.dart';
import 'package:go_router/go_router.dart';
import 'package:dio/dio.dart';
import 'package:http/http.dart' as http;
import 'package:uae_stat/config/theme/service.dart';
import 'package:uae_stat/infrastructure/services/local_bookmarks_service.dart';
import 'package:uae_stat/l10n/app_localizations.dart';
import 'package:pocketbase/pocketbase.dart';
import 'package:shared_preferences/shared_preferences.dart';
import 'package:uae_stat/config/api_config.dart';
import 'package:uae_stat/lib/core/routing/app_router.dart';
import 'package:uae_stat/config/connectivity_provider.dart';
import 'package:uae_stat/config/theme/theme_provider.dart';
import 'package:uae_stat/config/toggle_lang_service.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/l10n/app_localizations.dart';
import 'package:uae_stat/presentation/components/indicators/locale_provider.dart';
import 'package:uae_stat/presentation/routes/drawer_routes/custom_drawer_routes.dart';
class BookMark extends ConsumerStatefulWidget {
const BookMark({super.key});
@override
ConsumerState<BookMark> createState() => _BookMarkState();
}
class _BookMarkState extends ConsumerState<BookMark> {
final _pb = PocketBase(apiUrl);
List<Map<String, dynamic>> dataList = [];
bool isLoading = true;
Map<String, Map<String, dynamic>> groupedMap = {};
int? expandedIndex = 0;
// Current selected tab index
int selectedTabIndex = 0;
late UserService _userService;
late ThemeMode currentTheme;
List<dynamic> homePageData = [];
List<dynamic> filteredData = [];
List<Map<String, dynamic>> sortedList = [];
@override
void initState() {
super.initState();
_userService = UserService();
final locale = ref.read(localeProvider);
currentTheme = ref.read(themeProvider);
// final isDark = currentTheme == ThemeMode.dark ||
// (currentTheme == ThemeMode.system &&
// MediaQuery.of(context).platformBrightness == Brightness.dark);
WidgetsBinding.instance.addPostFrameCallback((_) {
final isDark = currentTheme == ThemeMode.dark ||
(currentTheme == ThemeMode.system &&
MediaQuery.of(context).platformBrightness == Brightness.dark);
final themeMode = (isDark ? 'dark' : 'light');
fetchData(locale?.languageCode ?? 'en', themeMode);
fetchBookmarks(locale?.languageCode ?? 'en', themeMode);
});
}
Future<void> fetchData(locale, themeMode) async {
const baseUrl = '${apiUrl}api/getUAENumbersData';
try {
final response = await http.get(
Uri.parse(baseUrl + '?language=$locale&color_mode=$themeMode'),
headers: {'APP_SIGNATURE': 'fcsc.gov.ae.X7pL9qZm2A'});
if (response.statusCode == 200) {
setState(() {
homePageData = (json.decode(response.body) as List)
.map((e) => Map<String, dynamic>.from(e))
.toList();
filteredData = List.from(homePageData);
isLoading = false;
});
} else {
throw Exception('Failed to load data');
}
} catch (e) {
setState(() {
isLoading = false;
});
}
}
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) {
return const Color(0xFF80A8CD); // Default color
}
try {
return Color(int.parse(colorString.replaceFirst('#', '0xFF')));
} catch (e) {
return const Color(0xFF80A8CD); // Fallback color
}
}
Future<void> fetchBookmarks(locale, themeMode) async {
try {
final fetchedData = await LocalBookmarksService.getAll();
setState(() {
dataList = fetchedData.map((item) {
return {
'main_topic': item['main_topic'] ?? item['mainTopic'] ?? '',
'title': item['data_set_tile_heading'] ?? item['title'] ?? '',
'subtitle': item['sub_topic'] ?? '',
'value': item['value'] ?? '',
'value_source': item['value_source'] ?? '',
'data_set': item['data_set'] ?? item['dataset'] ?? '',
'valueColor': _parseColor(item['color_pattern']?.toString()),
'isBookmark': true,
'id': item['id'],
};
}).toList();
});
if (dataList.isNotEmpty) {
{
// grouped map build (unchanged structure)
List<Map<String, dynamic>> transformAndStore(
List<Map<String, dynamic>> fetchedData) {
// Define the required order
List<String> order = [
context.translate('ECONOMY', 'الاقتصاد'),
context.translate('SOCIAL', 'الاجتماعي'),
context.translate('ENVIRONMENT', 'البيئة')
];
// Create a list to store sorted data
// List<Map<String, dynamic>> sortedList = [];
// Group data based on categories
Map<String, List<Map<String, dynamic>>> groupedData = {
context.translate('ECONOMY', 'الاقتصاد'): [],
context.translate('SOCIAL', 'الاجتماعي'): [],
context.translate('ENVIRONMENT', 'البيئة'): []
};
// Categorize data
for (var item in fetchedData) {
String mainTopic = item["main_topic"]?.toString() ?? "";
if (groupedData.containsKey(mainTopic)) {
groupedData[mainTopic]!.add(item);
}
}
// Store sorted data in the correct order
for (String topic in order) {
if (groupedData.containsKey(topic)) {
sortedList.addAll(groupedData[topic]!);
}
}
// Store the sorted list (replace this with your storage method)
return sortedList;
}
groupedMap = {};
for (var item in dataList) {
String? mainTopic = item['main_topic'];
String subtitle = item['subtitle'];
// Ignore if main_topic is null
if (mainTopic == null) continue;
// If main_topic doesn't exist in groupedMap, create a new entry
if (!groupedMap.containsKey(mainTopic)) {
groupedMap[mainTopic] = {
'main_topic': mainTopic,
'valueColor': item['valueColor'],
'SubTopic': []
};
}
// Add subtitle as a key with its corresponding map value
groupedMap[mainTopic]!['SubTopic'].add({
'subtitle': subtitle,
'isBookmark': item['isBookmark'],
'value': item['value'],
'title': item['title'],
'value_source': item['value_source'],
'data_set': item['data_set'],
'id': item['id'],
});
}
}
}
} catch (e) {
setState(() {
dataList = []; // Clear the list
});
} finally {
setState(() {
isLoading = false;
});
}
}
Future<void> removeBookmark(bookmarkId) async {
try {
setState(() {
isLoading = true;
});
// final adminAuth = await _pb.admins
// .authWithPassword('pb@venbainfotech.com', 'pb@venbainfotech.com');
// final auth = ref.watch(authProvider);
// final adminAuth = await pb.admins.authWithPassword(
// auth.email,
// auth.password,
// );
//
//
await LocalBookmarksService.remove(bookmarkId!);
// currentTheme = ref.read(themeProvider);
// print('123456789');
// print(currentTheme);
final isDark = currentTheme == ThemeMode.dark ||
(currentTheme == ThemeMode.system &&
MediaQuery.of(context).platformBrightness == Brightness.dark);
final themeMode = (isDark ? 'dark' : 'light');
final locale = ref.read(localeProvider);
fetchBookmarks(locale?.languageCode ?? 'en', themeMode);
// ToastUtil.showSuccessToast("Removed from Bookmark.");
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
AppLocalizations.of(context)!.removed_from_Bookmark,
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
)),
),
duration: Duration(seconds: 2),
),
);
} catch (e) {
SnackBar(
content: Text(
context.translate(
'Unable to remove from bookmarks. Please try again',
'تعذر الإزالة من الإشارات المرجعية. يرجى المحاولة مرة أخرى.',
),
style: TextStyle(
color: Color(0xFFEB5F24),
fontWeight: FontWeight.w600,
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
),
),
backgroundColor: Color(0xFFD6E9C6),
duration: Duration(seconds: 2),
);
} finally {
setState(() {
isLoading = false;
});
}
}
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(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 18,
color: Color(0xFF898C81),
),
)
],
),
),
],
),
actions: [
SizedBox(height: 20),
Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
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(0xFFB68A34), // Set the outline color
width: 1, // Set the border width
),
),
child: Text(
context.translate('No', 'لا'),
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
color: Color(0xFFB68A34),
fontSize: 16,
),
),
),
),
SizedBox(
width: 100, // Set the desired width
child: TextButton(
onPressed: () {
Navigator.pop(context);
removeBookmark(id);
},
style: TextButton.styleFrom(
backgroundColor: Color(0xFFB68A34), // 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,
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
),
),
),
),
],
)
],
),
);
}
@override
Widget build(BuildContext context) {
ref.listen<AsyncValue<bool>>(connectivityProvider, (previous, hasInternet) {
if (hasInternet.value == false) {
context.push('/internetcheck');
}
});
ref.listen<Locale?>(localeProvider, (previous, next) async {
final localeCode = next?.languageCode ?? 'en'; // Default to 'en' if null
setState(() {
isLoading = true;
});
await _userService.updateLanguage(localeCode, ref);
final currentTheme = ref.read(themeProvider);
final isDark = currentTheme == ThemeMode.dark ||
(currentTheme == ThemeMode.system &&
MediaQuery.of(context).platformBrightness == Brightness.dark);
final themeString = isDark ? 'dark' : 'light';
fetchBookmarks(localeCode, themeString);
});
ref.listen<ThemeMode>(themeProvider, (previous, next) async {
final localeCode = ref.watch(localeProvider)?.languageCode ?? 'en';
// Default to 'en' if null
setState(() {
isLoading = true;
});
final currentTheme = ref.read(themeProvider);
final isDark = currentTheme == ThemeMode.dark ||
(currentTheme == ThemeMode.system &&
MediaQuery.of(context).platformBrightness == Brightness.dark);
final themeString = isDark ? 'dark' : 'light';
fetchBookmarks(localeCode, themeString);
});
final isDarkTheme = ref.watch(themeProvider) == ThemeMode.dark ||
(ref.watch(themeProvider) == ThemeMode.system &&
MediaQuery.of(context).platformBrightness == Brightness.dark);
final List<Map<String, dynamic>> tabs = [
{
'title': AppLocalizations.of(context)!.all_bookmarks,
'titleUpper': AppLocalizations.of(context)!.all_bookmarks,
'color': isDarkTheme ? Colors.white : Color(0xFFB68A34),
// 'color': isDarkTheme ? Colors.white : Colors.black,
},
{
'title': AppLocalizations.of(context)!.economy_title,
'titleUpper': AppLocalizations.of(context)!.economy_title_upper,
'color': isDarkTheme ? Color(0xFF89AFD8) : Color(0xFF89AFD8)
},
{
'title': AppLocalizations.of(context)!.social_title,
'titleUpper': AppLocalizations.of(context)!.social_title_upper,
'color': isDarkTheme ? Color(0xFF675863) : Color(0xFF675863)
},
{
'title': AppLocalizations.of(context)!.environment_title,
'titleUpper': AppLocalizations.of(context)!.environment_title_upper,
'color': isDarkTheme ? Color(0xFFB3CF99) : Color(0xFFB3CF99)
},
];
List<Map<String, dynamic>> bookmarks =
dataList.where((item) => item['isBookmark'] == true).toList();
List<Map<String, dynamic>> filteredBookmarks = dataList.where((bookmark) {
String mainTopic = bookmark['main_topic'].toString().trim().toLowerCase();
String selectedTabTitle =
tabs[selectedTabIndex]['title'].toString().trim().toLowerCase();
// Debugging prints
print(
"main_topic: '$mainTopic', selected_tab_title: '$selectedTabTitle'");
return mainTopic == selectedTabTitle;
}).toList();
// print( 'filtered one :${filteredBookmarks['main_topic']} , Tabs : ${tabs[selectedTabIndex]["title"]}');
List<Map<String, dynamic>> transformedList = groupedMap.values.toList();
return PopScope(
canPop: false,
onPopInvokedWithResult: (didPop, result) {
if (didPop) return;
context.go('/myhomepage');
},
child: BaseScaffold(
backgroundColor: isDarkTheme ? Colors.black : Colors.white,
appbarColor: isDarkTheme ? Colors.black : Colors.white,
title: Text(
AppLocalizations.of(context)!.bookmarks,
style: TextStyle(
color: isDarkTheme ? Colors.white : Colors.black,
fontFamily: context.translate(
'Roboto',
'NotoKufi',
)),
),
body: isLoading
? Container(
color: isDarkTheme ? Colors.black : Colors.white,
// color: Color(0x98FFFCE5), // Semi-transparent background
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Container(
margin: EdgeInsets.symmetric(
horizontal: 40), // Left & Right space
child: LinearProgressIndicator(
minHeight: 5, // Adjust thickness
backgroundColor:
Colors.grey[100], // Optional: Background color
valueColor: AlwaysStoppedAnimation<Color>(
Color(0xFFAA8E83)), // Loader color
),
),
],
),
)
: Column(
children: [
TabBarHeader(
tabs: tabs,
selectedIndex: selectedTabIndex,
onTabSelected: (index) {
setState(() {
selectedTabIndex = index;
});
},
isDarkTheme: isDarkTheme),
Expanded(
child: selectedTabIndex == 0
? (bookmarks.isNotEmpty
? SingleChildScrollView(
child: Container(
padding: const EdgeInsets.all(13.0),
child: Column(
children: List.generate(
transformedList.length, (i) {
final mainTopic = transformedList[i];
final list = List.from(
mainTopic['SubTopic'] ?? []);
return CustomExpandableTile(
index: i,
isExpanded: expandedIndex == i,
onTap: (int index) {
// 🔹 Expecting an index
setState(() {
expandedIndex =
(expandedIndex == index)
? null
: index;
});
},
title: mainTopic['main_topic'] ??
'No Topic',
childWidget: Container(
decoration: BoxDecoration(
color: isDarkTheme
? Colors.black
: Colors.white,
// borderRadius: BorderRadius.all(Radius.circular(20))
),
padding: const EdgeInsets.symmetric(
vertical: 16),
child: GridView.builder(
shrinkWrap: true,
physics:
NeverScrollableScrollPhysics(),
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
mainAxisExtent: 100,
),
itemCount: list.length,
itemBuilder: (context, index) {
return _buildBoxes(
mainTopic['SubTopic'][index],
context,
mainTopic['valueColor'],
isDarkTheme);
},
),
),
filteredBookmarks: List.from(
mainTopic['SubTopic'] ?? []),
titleBackgroundColor:
mainTopic['valueColor'],
// Ensure it's a new list
isDarkTheme: isDarkTheme,
);
}),
),
),
)
: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.info_outline,
size: 100, color: Colors.grey[400]),
SizedBox(height: 16),
Text(
context.translate('No BookMark Added',
'لم يتم إضافة أي علامة مرجعية'),
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 16,
color: Colors.grey),
),
],
),
))
: filteredBookmarks.isEmpty
? Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(Icons.info_outline,
size: 100, color: Colors.grey[400]),
SizedBox(height: 16),
Text(
context.translate('No BookMark Added',
'لم يتم إضافة أي علامة مرجعية'),
style: TextStyle(
fontSize: 16,
color: Colors.grey,
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
),
),
],
),
)
: Padding(
padding: const EdgeInsets.all(8.0),
child: Container(
margin: const EdgeInsets.all(8.0),
child: Column(
children: [
Container(
decoration: BoxDecoration(
color: tabs[selectedTabIndex]
['color'],
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20))
// borderRadius: BorderRadius.all(
// Radius.circular(35))
),
padding: const EdgeInsets.only(
left: 16,
bottom: 5,
top: 5,
right: 10),
child: Row(
mainAxisAlignment:
MainAxisAlignment.center,
children: [
Text(
tabs[selectedTabIndex]
['titleUpper'],
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 20,
),
),
],
),
),
SizedBox(
height: 20,
),
Expanded(
child: GridView.builder(
gridDelegate:
const SliverGridDelegateWithFixedCrossAxisCount(
crossAxisCount: 2,
crossAxisSpacing: 10.0,
mainAxisSpacing: 10.0,
mainAxisExtent: 100,
),
itemCount: filteredBookmarks.length,
itemBuilder: (context, index) {
return _buildBox(
filteredBookmarks[index],
context,
isDarkTheme);
},
),
),
],
),
),
),
),
],
),
),
);
}
Widget _buildBox(
Map<String, dynamic> data, BuildContext context, bool isDarkTheme) {
// 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
context.push(
AppRoutes.datasetDetailPath(
dataSet: data_set,
bgColor: hexColor,
mainTopic: encodedMainTopic,
title: encodedTitle,
kpi: data_set,
),
);
},
child: Container(
width: MediaQuery.of(context).size.width * 0.4,
height: 100,
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: isDarkTheme ? Colors.black : Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: data['valueColor']),
),
child: Stack(
children: [
Align(
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Align(
alignment: Alignment.center,
child: Text(
data['title'] ?? '',
style: TextStyle(
fontWeight: FontWeight.w500,
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
color: isDarkTheme ? Colors.white : null,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
),
GestureDetector(
onTap: () {
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']}");
// // showRemoveBookmarkDialog(data['id']);
// },
// child: const Icon(
// Icons.bookmarks_rounded,
// color: Colors.black,
// size: 20,
// ),
// ),
],
),
Text(
data['value_source'] ?? '',
style: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.grey,
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
Text(
data['value'] ?? '',
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 28,
fontWeight: FontWeight.bold,
color: data['valueColor'],
),
),
],
),
),
],
),
),
);
}
Widget _buildBoxes(
Map<String, dynamic> data,
BuildContext context,
Color styleColor,
bool isDarkTheme,
) {
// 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(styleColor);
debugPrint(
AppRoutes.datasetDetailPath(
dataSet: data_set,
bgColor: hexColor,
mainTopic: encodedMainTopic,
title: encodedTitle,
kpi: data_set,
),
);
// String hexColor = colorToHex(colorPattern); // Get hex string
// print(hexColor); // Prints: 0xFFAA8E83
// debugPrint("Box clicked: ${data['title']}");
context.push(
AppRoutes.datasetDetailPath(
dataSet: data_set,
bgColor: hexColor,
mainTopic: encodedMainTopic,
title: encodedTitle,
kpi: data_set,
),
);
},
child: Container(
width: MediaQuery.of(context).size.width * 0.4,
height: 100,
padding: const EdgeInsets.all(8.0),
decoration: BoxDecoration(
color: isDarkTheme ? Colors.black : Colors.white,
borderRadius: BorderRadius.circular(10),
border: Border.all(color: styleColor),
),
child: Align(
alignment: Alignment.center,
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.center,
mainAxisAlignment: MainAxisAlignment.center,
children: [
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Expanded(
child: Align(
alignment: Alignment.center,
child: Text(
data['title'] ?? '',
style: TextStyle(
fontWeight: FontWeight.w500,
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
color: isDarkTheme ? Colors.white : null,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
),
),
GestureDetector(
onTap: () {
debugPrint("Icon clicked in: ${data['title']}");
showRemoveBookmarkDialog(data['id']);
},
child: SvgPicture.asset(
BookmarkAssetPath.delete,
semanticsLabel: 'share',
width: 23,
height: 20,
)),
],
),
Text(
data['value_source'] ?? '',
style: TextStyle(
fontWeight: FontWeight.w500,
color: Colors.grey,
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
),
Text(
data['value'] ?? '',
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
fontSize: 28,
fontWeight: FontWeight.bold,
color: styleColor,
),
),
],
),
),
),
);
}
}
class TabBarHeader extends StatelessWidget {
final List<Map<String, dynamic>> tabs;
final int selectedIndex;
final ValueChanged<int> onTabSelected;
bool isDarkTheme;
TabBarHeader(
{required this.tabs,
required this.selectedIndex,
required this.onTabSelected,
required this.isDarkTheme});
@override
Widget build(BuildContext context) {
return Container(
color: isDarkTheme ? Colors.black : 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['title'];
return Row(
children: [
TextButton(
onPressed: () => onTabSelected(index),
style: ButtonStyle(
foregroundColor:
MaterialStateProperty.resolveWith((states) {
return selectedIndex == index
? entry.value['color']
: Color(0xFF898C81);
}),
),
child: Text(
text,
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
),
),
),
if (index < tabs.length - 1) buildDivider(),
],
);
}).toList(),
),
),
);
}
Widget buildDivider() {
return SizedBox(
height: 20,
child: const VerticalDivider(
color: Colors.grey,
thickness: 1,
width: 16,
),
);
}
}
class CustomExpandableTile extends StatefulWidget {
final String title;
final Color titleBackgroundColor;
final List filteredBookmarks;
final int index;
final bool isExpanded;
final ValueChanged<int> onTap;
final Widget childWidget;
final bool isDarkTheme;
const CustomExpandableTile({
required this.title,
required this.titleBackgroundColor,
required this.filteredBookmarks,
required this.index,
required this.isExpanded,
required this.onTap,
required this.childWidget,
required this.isDarkTheme,
});
@override
_CustomExpandableTileState createState() => _CustomExpandableTileState();
}
class _CustomExpandableTileState extends State<CustomExpandableTile> {
@override
void initState() {
super.initState(); // Initialize isExpanded based on widget's property
}
@override
Widget build(BuildContext context) {
double myheight = MediaQuery.of(context).size.height;
// print(widget.filteredBookmarks);
return Card(
elevation: 0,
child: Column(
children: [
GestureDetector(
onTap: () => widget.onTap(widget.index),
child: Container(
decoration: BoxDecoration(
color: widget.isDarkTheme
? Colors.black
: Colors
.white, // Ensuring the background outside the rounded container is white
),
child: Container(
decoration: BoxDecoration(
color: widget.titleBackgroundColor,
borderRadius: BorderRadius.only(
topLeft: Radius.circular(20),
topRight: Radius.circular(20))
// borderRadius: BorderRadius.all(Radius.circular(35))
),
padding: const EdgeInsets.only(
left: 16, bottom: 5, top: 5, right: 10),
child: Row(
// mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: [
Spacer(),
Text(
widget.title,
style: TextStyle(
fontFamily: context.translate(
'Roboto',
'NotoKufi',
),
color: Colors.white,
fontWeight: FontWeight.w600,
fontSize: 20,
),
),
Spacer(),
Icon(
widget.isExpanded
? Icons.keyboard_arrow_up
: Icons.keyboard_arrow_down,
color: Colors.white,
size: 28.0,
),
],
),
),
),
),
ClipRRect(
child: AnimatedContainer(
duration: Duration(milliseconds: 300),
curve: Curves.easeInOut,
width: double.infinity,
color: widget.isDarkTheme ? Colors.black : Colors.white,
// height: widget.isExpanded ? myheight * 0.4 : 0,
child: widget.isExpanded
? SingleChildScrollView(
child: Column(
children: [
widget.childWidget,
// Container(
// decoration: BoxDecoration(
// color: Colors.white,
// // borderRadius: BorderRadius.all(Radius.circular(20))
// ),
// padding: const EdgeInsets.all(16),
// child: GridView.builder(
// shrinkWrap: true,
// physics: NeverScrollableScrollPhysics(),
// gridDelegate:
// const SliverGridDelegateWithFixedCrossAxisCount(
// crossAxisCount: 2,
// crossAxisSpacing: 10.0,
// mainAxisSpacing: 10.0,
// mainAxisExtent: 100,
// ),
// itemCount: widget.filteredBookmarks.length,
// itemBuilder: (context, index) {
// return _buildBox(widget.filteredBookmarks[index], context,widget.titleBackgroundColor);
// },
// ),
// ),
],
),
)
: null,
),
),
],
),
);
}
}