import 'package:flutter/material.dart'; import '../../../app/app_theme.dart'; import '../../../l10n/l10n.dart'; import '../../../models/today_progress.dart'; import '../../../widgets/surface_panel.dart'; class JourneyTimeline extends StatelessWidget { const JourneyTimeline({ required this.progress, required this.onReflect, super.key, }); final TodayProgress progress; final VoidCallback onReflect; @override Widget build(BuildContext context) { final l10n = context.l10n; final items = [ _TimelineData( title: l10n.progressIntention, detail: progress.hasIntention ? progress.intention : l10n.chooseOneOutcome, icon: Icons.flag_outlined, complete: progress.hasIntention, ), _TimelineData( title: l10n.progressFocus, detail: progress.hasFocus ? l10n.focusedMinutes(progress.focusMinutes) : l10n.noFocusSessionYet, icon: Icons.timer_outlined, complete: progress.hasFocus, ), _TimelineData( title: l10n.progressHabits, detail: l10n.habitsCompleted( progress.completedHabits, progress.totalHabits, ), icon: Icons.eco_outlined, complete: progress.hasHabits, ), _TimelineData( title: l10n.progressReflect, detail: progress.hasReflection ? l10n.reflectionCaptured : l10n.reflectionAction, icon: Icons.auto_awesome_outlined, complete: progress.hasReflection, action: progress.hasReflection ? null : onReflect, ), _TimelineData( title: l10n.growthTitle, detail: progress.hasReflection ? l10n.growthFlowerOpen : l10n.growthLocked, icon: Icons.local_florist_outlined, complete: progress.hasReflection, ), ]; return Column( children: [ for (var index = 0; index < items.length; index++) _TimelineItem(data: items[index], isLast: index == items.length - 1), ], ); } } class _TimelineItem extends StatelessWidget { const _TimelineItem({required this.data, required this.isLast}); final _TimelineData data; final bool isLast; @override Widget build(BuildContext context) { final theme = Theme.of(context); final visuals = FocusSeedVisuals.of(context); final accent = data.icon == Icons.auto_awesome_outlined ? visuals.reflection : theme.colorScheme.primary; return IntrinsicHeight( child: Row( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ SizedBox( width: 38, child: Column( children: [ Container( width: 30, height: 30, decoration: BoxDecoration( shape: BoxShape.circle, color: data.complete ? accent : theme.colorScheme.surfaceContainerLowest, border: Border.all(color: accent), ), child: Icon( data.complete ? Icons.check_rounded : data.icon, size: 16, color: data.complete ? theme.colorScheme.onPrimary : accent, ), ), if (!isLast) Expanded( child: Container( width: 2, color: data.complete ? accent.withValues(alpha: 0.55) : theme.colorScheme.outlineVariant, ), ), ], ), ), const SizedBox(width: 8), Expanded( child: Padding( padding: const EdgeInsets.only(bottom: 10), child: SurfacePanel( padding: const EdgeInsets.all(14), borderColor: data.action == null ? null : accent.withValues(alpha: 0.5), onTap: data.action, child: Row( children: [ Expanded( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text(data.title, style: theme.textTheme.labelLarge), const SizedBox(height: 3), Text( data.detail, maxLines: 3, overflow: TextOverflow.ellipsis, style: theme.textTheme.bodyMedium?.copyWith( color: theme.colorScheme.onSurfaceVariant, ), ), ], ), ), if (data.action != null) Icon(Icons.arrow_forward_rounded, color: accent), ], ), ), ), ), ], ), ); } } class _TimelineData { const _TimelineData({ required this.title, required this.detail, required this.icon, required this.complete, this.action, }); final String title; final String detail; final IconData icon; final bool complete; final VoidCallback? action; }