// ignore_for_file: unnecessary_import, deprecated_member_use import 'package:cached_network_image/cached_network_image.dart'; import 'package:didvan/views/home/explore/explore.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter_animate/flutter_animate.dart'; import 'package:flutter_svg/flutter_svg.dart'; import 'package:provider/provider.dart'; import 'package:persian_number_utility/persian_number_utility.dart'; import 'package:universal_html/html.dart' as html; import 'package:didvan/config/design_config.dart'; import 'package:didvan/models/content/content_item.dart'; import 'package:didvan/utils/category_labels.dart'; import 'package:didvan/models/home_page_content/content.dart'; import 'package:didvan/models/home_page_content/home_page_list.dart'; import 'package:didvan/models/home_page_content/swot.dart'; import 'package:didvan/models/new_statistic/new_statistics_model.dart' as stat; import 'package:didvan/views/home/home_state.dart'; import 'package:didvan/views/home/main/main_page_state.dart'; import 'package:didvan/views/home/new_statistic/new_statistics_state.dart'; import 'package:didvan/views/widgets/mini_chart.dart'; import 'package:didvan/views/home/main/widgets/main_content.dart'; import 'package:didvan/views/home/main/widgets/story_section.dart'; import 'package:didvan/views/home/main/widgets/simple_explore_card.dart'; import 'package:didvan/views/home/main/widgets/didvan_plus_section.dart'; import 'package:didvan/views/home/main/widgets/didvan_voice_section.dart'; import 'package:didvan/views/widgets/didvan/text.dart'; import 'package:didvan/views/widgets/state_handlers/state_handler.dart'; import 'package:didvan/views/widgets/carousel_3d.dart'; import 'package:didvan/views/widgets/text_divider.dart'; import 'package:didvan/routes/routes.dart'; import 'package:didvan/views/widgets/home_app_bar.dart'; bool isAnyMobile() { if (kIsWeb) { final userAgent = html.window.navigator.userAgent.toLowerCase(); return userAgent.contains('mobile') || userAgent.contains('android') || userAgent.contains('ios'); } return defaultTargetPlatform == TargetPlatform.android || defaultTargetPlatform == TargetPlatform.iOS; } class MainPage extends StatefulWidget { const MainPage({super.key}); @override State createState() => _MainPageState(); } class _MainPageState extends State { @override void initState() { super.initState(); WidgetsBinding.instance.addPostFrameCallback((_) { context.read().init(); context.read().init(); }); } @override Widget build(BuildContext context) { return StateHandler( onRetry: () => context.read().init(), state: context.watch(), builder: (context, state) { debugPrint( '🏠 MainPage build - didvanPlus: ${state.didvanPlus != null}'); debugPrint( '🏠 MainPage build - didvanVoice: ${state.didvanVoice != null}'); return Column( children: [ const HomeAppBar( showBackButton: false, showSearchField: true, ), Expanded( child: ListView( padding: const EdgeInsets.only(top: 0, bottom: 16), children: [ if (state.stories.isNotEmpty) ...[ const TextDivider(text: 'دیده‌بان') .animate() .fadeIn(delay: 400.ms, duration: 500.ms), const _DidvanSignalsTitle() .animate() .fadeIn(delay: 500.ms, duration: 500.ms), Padding( padding: const EdgeInsets.symmetric(horizontal: 8), child: StorySection(stories: state.stories), ).animate().fadeIn(delay: 600.ms, duration: 500.ms), ], if (state.didvanPlus != null) ...[ const SizedBox(height: 28), DidvanPlusSection( didvanPlus: state.didvanPlus!, allItems: state.didvanPlusList, ).animate().fadeIn(delay: 650.ms, duration: 500.ms), ], const SizedBox(height: 12), const TextDivider(text: 'پیشخوان استراتژیک') .animate() .fadeIn(delay: 700.ms, duration: 500.ms), const Padding( padding: EdgeInsets.symmetric(horizontal: 16), child: MainPageMainContent(), ).animate().fadeIn(delay: 800.ms, duration: 500.ms), if (state.content != null && state.content!.lists.isNotEmpty) ...[ const _ExploreLatestTitle() .animate() .fadeIn(delay: 900.ms, duration: 500.ms), _ExploreLatestSlider( lists: state.content!.lists, swotItems: state.swotItems, ).animate().fadeIn(delay: 1000.ms, duration: 500.ms), ] else if (state.exploreLists.isNotEmpty) ...[ const _ExploreLatestTitle() .animate() .fadeIn(delay: 900.ms, duration: 500.ms), _ExploreLatestSlider( lists: state.exploreLists, swotItems: state.swotItems, ).animate().fadeIn(delay: 1000.ms, duration: 500.ms), ] else if (state.swotItems.isNotEmpty) ...[ const _ExploreLatestTitle() .animate() .fadeIn(delay: 900.ms, duration: 500.ms), _ExploreLatestSliderNew( items: const [], swotItems: state.swotItems, ).animate().fadeIn(delay: 1000.ms, duration: 500.ms), ], if (state.swotItems.isNotEmpty) SwotSection( swotItems: state.swotItems, headerSize: 13, moreSize: 12, ).animate().fadeIn(delay: 1100.ms, duration: 500.ms), // --- Didvan Voice --- if (state.didvanVoice != null) ...[ const SizedBox(height: 10), _DidvanVoiceTitle( showMore: state.didvanVoiceList.isNotEmpty, onViewAll: state.didvanVoiceList.isEmpty ? null : () => Navigator.of(context).pushNamed( Routes.didvanVoiceList, arguments: state.didvanVoiceList, ), ).animate().fadeIn(delay: 1150.ms, duration: 500.ms), const SizedBox(height: 20), DidvanVoiceSection(didvanVoice: state.didvanVoice!) .animate() .fadeIn(delay: 1200.ms, duration: 500.ms), ], // --- Commented Out Section (Industry Pulse) --- // const _IndustryPulseTitle() // .animate() // .fadeIn(delay: 1100.ms, duration: 500.ms), // const _IndustryPulseCards() // .animate() // .fadeIn(delay: 1200.ms, duration: 500.ms), ], ), ), ], ); }, ); } } class _DidvanSignalsTitle extends StatelessWidget { const _DidvanSignalsTitle(); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), child: Row( children: [ SvgPicture.asset( 'lib/assets/icons/Signal.svg', width: 25, height: 25, ), const SizedBox(width: 5), DidvanText( "نشانک‌های آینده", style: Theme.of(context).textTheme.titleMedium, color: const Color.fromARGB(255, 0, 89, 119), fontSize: 13, ), ], ), ); } } class _DidvanVoiceTitle extends StatelessWidget { final bool showMore; final VoidCallback? onViewAll; const _DidvanVoiceTitle({ this.showMore = true, this.onViewAll, }); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.symmetric(horizontal: 18), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ SvgPicture.asset( 'lib/assets/icons/akar-icons_sound-on.svg', width: 25, height: 25, ), const SizedBox(width: 5), DidvanText( "یک لقمه استراتژی", style: Theme.of(context).textTheme.titleMedium, color: const Color.fromARGB(255, 0, 89, 119), fontSize: 13, fontWeight: FontWeight.bold, ), ], ), if (showMore && onViewAll != null) InkWell( onTap: onViewAll, child: const DidvanText( 'مشاهده همه', fontSize: 12, color: Color.fromARGB(255, 0, 126, 167), ), ), ], ), ); } } class _ExploreLatestTitle extends StatelessWidget { const _ExploreLatestTitle(); @override Widget build(BuildContext context) { return Padding( padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Row( children: [ SvgPicture.asset( 'lib/assets/icons/discover.svg', width: 25, height: 25, color: const Color.fromARGB(255, 0, 126, 167), ), const SizedBox(width: 5), DidvanText( "تازه‌ترین کاوش‌ها", style: Theme.of(context).textTheme.titleMedium, color: DesignConfig.isDark ? const Color.fromARGB(255, 0, 125, 166) : const Color.fromARGB(255, 0, 89, 119), fontSize: 13, ), ], ), GestureDetector( onTap: () { context.read().tabController.animateTo(3); }, child: const Row( children: [ DidvanText( "مشاهده همه", color: Color.fromARGB(255, 0, 126, 167), fontWeight: FontWeight.normal, fontSize: 12, ), ], ), ) ], ), ); } } class _ExploreLatestSlider extends StatelessWidget { final List lists; final List swotItems; const _ExploreLatestSlider({required this.lists, required this.swotItems}); @override Widget build(BuildContext context) { debugPrint('🟢🟢🟢 _ExploreLatestSlider build called 🟢🟢🟢'); final List items = []; final List< ({String type, MainPageContentType? content, SwotItem? swotItem})> itemsData = []; for (var list in lists) { if (['video', 'podcast', 'delphi', 'survey'].contains(list.type)) { continue; } if (list.contents.isNotEmpty) { final newestContent = list.contents.first; if (list.type == 'monthly') { debugPrint( '🔍 MONTHLY in carousel - ID: ${newestContent.id}, File: ${newestContent.file}, Link: ${newestContent.link}'); } items.add( Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: SimpleExploreCard( content: newestContent, type: list.type, ), ), ); itemsData .add((type: list.type, content: newestContent, swotItem: null)); } } /* if (swotItems.isNotEmpty) { items.add( Padding( padding: const EdgeInsets.symmetric(horizontal: 4.0), child: SimpleExploreCard( swotItem: swotItems.first, ), ), ); itemsData.add((type: 'swot', content: null, swotItem: swotItems.first)); } */ if (items.isEmpty) return const SizedBox.shrink(); debugPrint('📱 Building Carousel3D with ${items.length} items'); debugPrint('📱 ItemsData length: ${itemsData.length}'); for (var i = 0; i < itemsData.length; i++) { debugPrint( ' [$i] Type: ${itemsData[i].type}, ID: ${itemsData[i].content?.id}'); } return Carousel3D( items: items, height: 220, autoPlayDuration: const Duration(seconds: 5), showControls: true, onItemChanged: (index) {}, onItemTap: (index) { final data = itemsData[index]; if (data.content != null) { final String? rawFile = data.content!.file; final String fileString = (rawFile != null) ? rawFile.toString() : ''; context.read().navigationHandler( data.type, data.content!.id, data.content!.link ?? '', description: data.content!.title, file: fileString, // Pass new-API UUID so news/radar details use // getContentDetail instead of the legacy endpoint, which // fails with "اتصال اینترنت برقرار نیست" for these ids. contentUuid: data.content!.contentId, ); } }, ); } } class _IndustryPulseSection extends StatelessWidget { const _IndustryPulseSection(); @override Widget build(BuildContext context) { return StateHandler( state: context.watch(), placeholder: const SizedBox.shrink(), onRetry: () => context.read().init(), builder: (context, statState) { final items = []; for (final cat in statState.contents) { items.addAll(cat.contents); } if (items.isEmpty) return const SizedBox.shrink(); final show = items.take(10).toList(); return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ const Padding( padding: EdgeInsets.fromLTRB(16, 0, 16, 12), child: TextDivider(text: 'نبض صنعت'), ), SizedBox( height: 150, child: ListView.builder( scrollDirection: Axis.horizontal, padding: const EdgeInsets.symmetric(horizontal: 12), itemCount: show.length, itemBuilder: (context, index) => _IndustryPulseCard(item: show[index]), ), ), ], ); }, ); } } class _IndustryPulseCard extends StatelessWidget { final stat.Content item; const _IndustryPulseCard({required this.item}); @override Widget build(BuildContext context) { final theme = Theme.of(context); final isUp = item.data.dt == 'high'; final isDown = item.data.dt == 'low'; final diffColor = isUp ? Colors.green : (isDown ? Colors.red : theme.colorScheme.onSurface); return Container( width: 150, margin: const EdgeInsets.symmetric(horizontal: 6), padding: const EdgeInsets.all(12), decoration: BoxDecoration( color: theme.cardColor, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.08), blurRadius: 6, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ MiniChart( label: item.label, width: double.infinity, height: 36, lineColor: diffColor, changePercent: item.data.dp.toDouble(), trend: item.data.dt, prices: item.data.prices, ), DidvanText( item.title.toPersianDigit(), style: theme.textTheme.bodyMedium ?.copyWith(fontWeight: FontWeight.w600), maxLines: 1, overflow: TextOverflow.ellipsis, ), DidvanText( item.data.p.toPersianDigit(), style: theme.textTheme.bodySmall, ), if (item.data.dp != 0) Container( padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), decoration: BoxDecoration( color: diffColor.withValues(alpha: 0.12), borderRadius: BorderRadius.circular(4), ), child: DidvanText( '${item.data.dp}%'.toPersianDigit(), fontSize: 12, color: diffColor, ), ), ], ), ); } } class _ExploreLatestSliderNew extends StatelessWidget { final List items; final List swotItems; const _ExploreLatestSliderNew({ required this.items, this.swotItems = const [], }); @override Widget build(BuildContext context) { final contentSlice = items.take(7).toList(); final swotSlice = swotItems.take(1).toList(); final cards = [ ...contentSlice.map((item) => Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: _ExploreContentCard(item: item), )), ...swotSlice.map((s) => Padding( padding: const EdgeInsets.symmetric(horizontal: 4), child: SimpleExploreCard(swotItem: s), )), ]; if (cards.isEmpty) return const SizedBox.shrink(); return Carousel3D( items: cards, height: 220, autoPlayDuration: const Duration(seconds: 5), showControls: true, onItemChanged: (index) {}, onItemTap: (index) { if (index < contentSlice.length) { final item = contentSlice[index]; // Route to the correct details page based on the content's // metadata type. 'content' as a nav type isn't handled by // navigationHandler and produces the "اتصال اینترنت برقرار // نیست" empty state. final metaType = (item.metaType ?? '').toLowerCase(); final navType = (metaType == 'threat' || metaType == 'opportunity') ? 'radar' : 'news'; context.read().navigationHandler( navType, item.id.hashCode, null, description: item.title, contentUuid: item.id, ); } }, ); } } class _ExploreContentCard extends StatelessWidget { final ContentItem item; const _ExploreContentCard({required this.item}); @override Widget build(BuildContext context) { return Container( width: 280, height: 200, decoration: BoxDecoration( color: Theme.of(context).cardColor, borderRadius: BorderRadius.circular(12), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.1), spreadRadius: 1, blurRadius: 8, offset: const Offset(0, 2), ), ], ), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Expanded( flex: 4, child: ClipRRect( borderRadius: const BorderRadius.vertical( top: Radius.circular(12), ), child: item.coverImage != null ? CachedNetworkImage( imageUrl: item.coverImage!, width: double.infinity, fit: BoxFit.cover, placeholder: (_, __) => Container( color: Theme.of(context).colorScheme.surface, ), errorWidget: (_, __, ___) => Container( color: Theme.of(context).colorScheme.surface, alignment: Alignment.center, child: const Icon(Icons.image_not_supported_outlined), ), ) : Container( width: double.infinity, color: Theme.of(context).colorScheme.surface, alignment: Alignment.center, child: const Icon(Icons.article_outlined, size: 40), ), ), ), Container( width: double.infinity, height: 40, decoration: const BoxDecoration( color: Color.fromRGBO(0, 69, 92, 1), borderRadius: BorderRadius.vertical( bottom: Radius.circular(12), ), ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), child: Center( child: DidvanText( item.title, style: Theme.of(context).textTheme.titleSmall?.copyWith( fontWeight: FontWeight.w600, color: Colors.white, ), maxLines: 1, overflow: TextOverflow.ellipsis, textAlign: TextAlign.center, ), ), ), ), ], ), ); } } class _NewContentsList extends StatelessWidget { final List items; const _NewContentsList({required this.items}); @override Widget build(BuildContext context) { return ListView.builder( shrinkWrap: true, physics: const NeverScrollableScrollPhysics(), padding: const EdgeInsets.symmetric(horizontal: 16), itemCount: items.length, itemBuilder: (context, index) => _NewContentCard(item: items[index]), ); } } class _NewContentCard extends StatelessWidget { final ContentItem item; const _NewContentCard({required this.item}); @override Widget build(BuildContext context) { final theme = Theme.of(context); return Card( margin: const EdgeInsets.symmetric(vertical: 6), child: InkWell( borderRadius: DesignConfig.mediumBorderRadius, onTap: () { // See _ExploreLatestSliderNew — route by metaType, pass UUID so // details uses the new-API path. final metaType = (item.metaType ?? '').toLowerCase(); final navType = (metaType == 'threat' || metaType == 'opportunity') ? 'radar' : 'news'; context.read().navigationHandler( navType, item.id.hashCode, null, description: item.title, contentUuid: item.id, ); }, child: Padding( padding: const EdgeInsets.all(12), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ if (item.coverImage != null) ClipRRect( borderRadius: DesignConfig.lowBorderRadius, child: CachedNetworkImage( imageUrl: item.coverImage!, height: 160, width: double.infinity, fit: BoxFit.cover, placeholder: (_, __) => Container( height: 160, color: theme.colorScheme.surface, ), errorWidget: (_, __, ___) => Container( height: 160, color: theme.colorScheme.surface, alignment: Alignment.center, child: const Icon(Icons.broken_image_outlined), ), ), ), if (item.coverImage != null) const SizedBox(height: 8), DidvanText( item.title, style: theme.textTheme.titleMedium, fontWeight: FontWeight.w700, maxLines: 2, overflow: TextOverflow.ellipsis, ), if (item.summary != null && item.summary!.isNotEmpty) ...[ const SizedBox(height: 6), DidvanText( item.summary!, style: theme.textTheme.bodySmall, maxLines: 3, overflow: TextOverflow.ellipsis, ), ], const SizedBox(height: 8), Row( children: [ // Show the CONTENT'S own subcategory (from the panel-side // metadata.category, translated to Persian), not the parent // section name. Falls back to the first metaCategories entry, // then the first tag, then the parent category — so the // badge is empty only when the item has no classification // at all. Builder( builder: (_) { String label = CategoryLabels.label(item.metaCategory); if (label.isEmpty && item.metaCategories.isNotEmpty) { label = CategoryLabels.label(item.metaCategories.first); } if (label.isEmpty && item.tagNames.isNotEmpty) { label = item.tagNames.first; } if (label.isEmpty && item.category?.name != null) { label = item.category!.name!; } if (label.isEmpty) return const SizedBox.shrink(); return Container( padding: const EdgeInsets.symmetric( horizontal: 8, vertical: 2), decoration: BoxDecoration( color: theme.colorScheme.primary.withOpacity(0.1), borderRadius: BorderRadius.circular(10), ), child: DidvanText( label, fontSize: 11, color: theme.colorScheme.primary, ), ); }, ), const Spacer(), IconButton( icon: Icon( item.isLiked ? Icons.favorite : Icons.favorite_border, color: item.isLiked ? Colors.red : theme.colorScheme.onSurface, size: 20, ), onPressed: () => context.read().toggleLike(item), padding: EdgeInsets.zero, constraints: const BoxConstraints(), visualDensity: VisualDensity.compact, ), const SizedBox(width: 4), DidvanText( item.likeCount.toString(), fontSize: 12, ), const SizedBox(width: 12), IconButton( icon: Icon( item.isBookmarked ? Icons.bookmark : Icons.bookmark_border, color: item.isBookmarked ? theme.colorScheme.primary : theme.colorScheme.onSurface, size: 20, ), onPressed: () => context.read().toggleBookmark(item), padding: EdgeInsets.zero, constraints: const BoxConstraints(), visualDensity: VisualDensity.compact, ), ], ), ], ), ), ), ); } } // --------------------------------------------------------------------------- // ------------------------- COMMENTED OUT SECTIONS -------------------------- // --------------------------------------------------------------------------- // class _IndustryPulseTitle extends StatelessWidget { // const _IndustryPulseTitle(); // @override // Widget build(BuildContext context) { // return Padding( // padding: const EdgeInsets.only( // left: 16, // right: 16, // bottom: 16, // top: 16, // ), // child: Row( // mainAxisAlignment: MainAxisAlignment.spaceBetween, // children: [ // Row( // children: [ // SvgPicture.asset( // 'lib/assets/icons/chart 2.svg', // color: Theme.of(context).colorScheme.title, // width: 30, // height: 30, // ), // const SizedBox(width: 5), // DidvanText( // "نبض صنعت", // style: Theme.of(context).textTheme.titleMedium, // color: const Color.fromARGB(255, 0, 89, 119), // fontSize: 13, // ), // ], // ), // GestureDetector( // onTap: () { // context.read().tabController.animateTo(2); // }, // child: const Row( // children: [ // DidvanText( // "مشاهده همه", // color: Color.fromARGB(255, 0, 126, 167), // fontWeight: FontWeight.normal, // fontSize: 12, // ), // ], // ), // ) // ], // ), // ); // } // } // class _IndustryPulseCards extends StatefulWidget { // const _IndustryPulseCards(); // @override // State<_IndustryPulseCards> createState() => _IndustryPulseCardsState(); // } // class _IndustryPulseCardsState extends State<_IndustryPulseCards> { // late PageController _pageController; // @override // void initState() { // super.initState(); // _pageController = PageController(viewportFraction: 0.45); // } // @override // void dispose() { // _pageController.dispose(); // super.dispose(); // } // @override // Widget build(BuildContext context) { // return StateHandler( // state: context.watch(), // placeholder: const Center(child: CircularProgressIndicator()), // onRetry: () => context.read().init(), // builder: (context, statisticState) { // if (statisticState.contents.isEmpty) { // return const SizedBox.shrink(); // } // final List allItems = []; // statisticState.contents.forEach((category) { // allItems.addAll(category.contents); // }); // final List desiredTitles = [ // 'دلار', // 'بیت کوین', // 'نیکل', // 'نفت خام' // ]; // final List itemsToShow = allItems // .where((item) => desiredTitles.contains(item.title)) // .toList(); // if (itemsToShow.isEmpty) { // return const SizedBox.shrink(); // } // return Padding( // padding: const EdgeInsets.only(left: 16.0), // child: Align( // alignment: Alignment.centerLeft, // child: SizedBox( // height: 165, // child: PageView.builder( // padEnds: false, // controller: _pageController, // itemCount: itemsToShow.length, // itemBuilder: (context, index) { // return Padding( // padding: const EdgeInsets.only(right: 8.0), // child: AspectRatio( // aspectRatio: 1, // child: _IndustryPulseCard(statistic: itemsToShow[index]), // ), // ) // .animate() // .fadeIn(delay: (200 * index).ms, duration: 500.ms) // .slideX( // begin: -0.5, duration: 500.ms, curve: Curves.easeOut); // }, // ), // ), // ), // ); // }, // ); // } // } // class _IndustryPulseCard extends StatelessWidget { // final Content statistic; // const _IndustryPulseCard({required this.statistic}); // Color _diffColor(BuildContext context) => statistic.data.dt == 'high' // ? Theme.of(context).colorScheme.success // : Theme.of(context).colorScheme.error; // bool get _hasDiff => statistic.data.dp != 0; // @override // Widget build(BuildContext context) { // final state = context.read(); // return GestureDetector( // onTap: () => // Navigator.of(context).pushNamed(Routes.statisticDetails, arguments: { // 'onMarkChanged': (value) => onMarkChanged(statistic.id, value), // 'label': statistic.label, // 'title': statistic.title, // 'marked': statistic.marked, // }).then( // (value) => state.getStatistic(), // ), // child: DidvanCard( // padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 9), // child: Column( // mainAxisAlignment: MainAxisAlignment.center, // crossAxisAlignment: CrossAxisAlignment.center, // children: [ // Padding( // padding: const EdgeInsets.symmetric(horizontal: 8.0), // child: Row( // children: [ // Expanded( // child: MiniChart( // label: statistic.label, // width: double.infinity, // height: 38, // lineColor: _hasDiff // ? _diffColor(context) // : Theme.of(context).colorScheme.primary, // changePercent: statistic.data.dp.toDouble(), // trend: statistic.data.dt, // ), // ), // ], // ), // ), // const SizedBox(height: 20), // Row( // mainAxisAlignment: MainAxisAlignment.center, // children: [ // if (statistic.marked) // Icon( // Icons.star, // color: Theme.of(context).colorScheme.yellow, // size: 16, // ), // if (statistic.marked) const SizedBox(width: 4), // DidvanText( // statistic.title, // style: Theme.of(context).textTheme.bodyMedium?.copyWith( // fontWeight: FontWeight.w600, // ), // maxLines: 1, // overflow: TextOverflow.ellipsis, // ), // ], // ), // const SizedBox(height: 6), // DidvanText( // statistic.data.p, // style: Theme.of(context).textTheme.bodySmall?.copyWith( // fontWeight: FontWeight.w500, // ), // ), // if (_hasDiff) const SizedBox(height: 6), // if (_hasDiff) // Container( // padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), // decoration: BoxDecoration( // color: statistic.data.dt == 'high' // ? const Color.fromRGBO(245, 255, 252, 1) // : const Color.fromRGBO(255, 248, 248, 1), // borderRadius: BorderRadius.circular(4), // ), // child: Row( // mainAxisSize: MainAxisSize.min, // mainAxisAlignment: MainAxisAlignment.center, // children: [ // Icon( // statistic.data.dt == 'high' // ? DidvanIcons.angle_up_regular // : DidvanIcons.angle_down_regular, // size: 16, // color: _diffColor(context), // ), // const SizedBox(width: 4), // DidvanText( // '${statistic.data.dp}%', // style: Theme.of(context).textTheme.bodySmall, // color: _diffColor(context), // ), // ], // ), // ), // ], // ), // ), // ); // } // void onMarkChanged(int id, bool value) { // UserProvider.changeStatisticMark(id, value); // } // }