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 createState() => _BookMarkState(); } class _BookMarkState extends ConsumerState { final _pb = PocketBase(apiUrl); List> dataList = []; bool isLoading = true; Map> groupedMap = {}; int? expandedIndex = 0; // Current selected tab index int selectedTabIndex = 0; late UserService _userService; late ThemeMode currentTheme; List homePageData = []; List filteredData = []; List> 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 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.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 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> transformAndStore( List> fetchedData) { // Define the required order List order = [ context.translate('ECONOMY', 'الاقتصاد'), context.translate('SOCIAL', 'الاجتماعي'), context.translate('ENVIRONMENT', 'البيئة') ]; // Create a list to store sorted data // List> sortedList = []; // Group data based on categories Map>> 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 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>(connectivityProvider, (previous, hasInternet) { if (hasInternet.value == false) { context.push('/internetcheck'); } }); ref.listen(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(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> 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> bookmarks = dataList.where((item) => item['isBookmark'] == true).toList(); List> 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> 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(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 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 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> tabs; final int selectedIndex; final ValueChanged 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 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 { @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, ), ), ], ), ); } }