import 'package:flutter/material.dart'; import '../../../l10n/l10n.dart'; import '../../../models/today_progress.dart'; import '../../../widgets/seed_illustration.dart'; import '../../../widgets/surface_panel.dart'; class JourneyOverviewPanel extends StatelessWidget { const JourneyOverviewPanel({ required this.progress, required this.onReflect, super.key, }); final TodayProgress progress; final VoidCallback onReflect; @override Widget build(BuildContext context) { final l10n = context.l10n; final scheme = Theme.of(context).colorScheme; final completed = progress.completedSteps; final progressValue = completed / 4; final title = switch (completed) { 0 => l10n.journeyOverviewStartTitle, 4 => l10n.journeyOverviewDoneTitle, _ => l10n.journeyOverviewActiveTitle, }; final subtitle = switch (completed) { 0 => l10n.journeyOverviewStartBody, 4 => l10n.journeyOverviewDoneBody, _ => l10n.journeyOverviewActiveBody, }; final showReflectAction = progress.hasIntention && progress.hasFocus && !progress.hasReflection; return SurfacePanel( elevated: true, padding: EdgeInsets.zero, borderColor: scheme.outlineVariant.withValues(alpha: 0.45), child: Container( decoration: BoxDecoration( gradient: LinearGradient( begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [ scheme.primary.withValues(alpha: 0.20), scheme.surfaceContainerLowest.withValues(alpha: 0.96), scheme.secondary.withValues(alpha: 0.14), ], ), ), child: LayoutBuilder( builder: (context, constraints) { final textScale = MediaQuery.textScalerOf(context).scale(14) / 14; final compact = constraints.maxWidth < 360 || textScale > 1.25; final textContent = _OverviewText( title: title, subtitle: subtitle, completed: completed, progressValue: progressValue, showReflectAction: showReflectAction, onReflect: onReflect, ); if (compact) { return Stack( children: [ const Positioned( right: -18, top: -20, child: Opacity( opacity: 0.58, child: SeedIllustration(size: 128, hero: true), ), ), Padding( padding: const EdgeInsets.fromLTRB(16, 17, 106, 18), child: textContent, ), ], ); } return Stack( children: [ Positioned( right: -28, top: -22, bottom: -18, child: Opacity( opacity: 0.96, child: SeedIllustration( size: constraints.maxWidth.clamp(146, 184).toDouble(), hero: true, ), ), ), Positioned( right: 92, bottom: 18, child: _ProgressBadge(completed: completed), ), Padding( padding: const EdgeInsets.fromLTRB(18, 17, 168, 18), child: textContent, ), ], ); }, ), ), ); } } class _OverviewText extends StatelessWidget { const _OverviewText({ required this.title, required this.subtitle, required this.completed, required this.progressValue, required this.showReflectAction, required this.onReflect, }); final String title; final String subtitle; final int completed; final double progressValue; final bool showReflectAction; final VoidCallback onReflect; @override Widget build(BuildContext context) { final theme = Theme.of(context); final l10n = context.l10n; final scheme = theme.colorScheme; return Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( l10n.journeyOverviewLabel, style: theme.textTheme.labelSmall?.copyWith( color: scheme.primary, fontWeight: FontWeight.w800, ), ), const SizedBox(height: 6), Text( title, maxLines: 2, overflow: TextOverflow.ellipsis, style: theme.textTheme.titleLarge?.copyWith( fontWeight: FontWeight.w900, ), ), const SizedBox(height: 6), Text( subtitle, maxLines: 2, overflow: TextOverflow.ellipsis, style: theme.textTheme.bodyMedium?.copyWith( color: scheme.onSurfaceVariant, ), ), const SizedBox(height: 16), _ProgressSeeds(completed: completed, progressValue: progressValue), const SizedBox(height: 12), Row( children: [ Expanded( child: Text( l10n.journeyOverviewProgress(completed), maxLines: 1, overflow: TextOverflow.ellipsis, style: theme.textTheme.labelLarge, ), ), if (showReflectAction) TextButton.icon( onPressed: onReflect, icon: const Icon(Icons.edit_note_rounded, size: 18), label: Text(l10n.reviewNow), ), ], ), ], ); } } class _ProgressSeeds extends StatelessWidget { const _ProgressSeeds({required this.completed, required this.progressValue}); final int completed; final double progressValue; @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; return Semantics( value: '${(progressValue * 100).round()}%', child: Row( children: List.generate(4, (index) { final filled = index < completed; return Expanded( child: AnimatedContainer( duration: const Duration(milliseconds: 220), curve: Curves.easeOutCubic, height: 10, margin: EdgeInsets.only(right: index == 3 ? 0 : 7), decoration: BoxDecoration( color: filled ? scheme.primary : scheme.surfaceContainerHigh.withValues(alpha: 0.82), borderRadius: BorderRadius.circular(99), boxShadow: filled ? [ BoxShadow( color: scheme.primary.withValues(alpha: 0.28), blurRadius: 10, offset: const Offset(0, 4), ), ] : null, ), ), ); }), ), ); } } class _ProgressBadge extends StatelessWidget { const _ProgressBadge({required this.completed}); final int completed; @override Widget build(BuildContext context) { final scheme = Theme.of(context).colorScheme; final theme = Theme.of(context); return DecoratedBox( decoration: BoxDecoration( color: scheme.surfaceContainerLowest.withValues(alpha: 0.82), borderRadius: BorderRadius.circular(99), border: Border.all( color: scheme.outlineVariant.withValues(alpha: 0.65), ), boxShadow: [ BoxShadow( color: Colors.black.withValues(alpha: 0.10), blurRadius: 14, offset: const Offset(0, 7), ), ], ), child: Padding( padding: const EdgeInsets.symmetric(horizontal: 11, vertical: 7), child: Text( '$completed/4', style: theme.textTheme.labelLarge?.copyWith( color: scheme.primary, fontWeight: FontWeight.w900, ), ), ), ); } }