Files
gp/lib/src/features/journey/widgets/journey_overview_panel.dart
T

175 lines
5.1 KiB
Dart

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,
color: scheme.surfaceContainerLowest,
child: Container(
padding: const EdgeInsets.fromLTRB(18, 16, 16, 18),
decoration: BoxDecoration(
gradient: LinearGradient(
begin: Alignment.topLeft,
end: Alignment.bottomRight,
colors: [
scheme.primary.withValues(alpha: 0.12),
scheme.surfaceContainerLowest,
scheme.secondary.withValues(alpha: 0.07),
],
),
),
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 Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const Align(
alignment: Alignment.centerRight,
child: SeedIllustration(size: 88),
),
const SizedBox(height: 8),
textContent,
],
);
}
return Row(
children: [
Expanded(child: textContent),
const SizedBox(width: 12),
const SeedIllustration(size: 112),
],
);
},
),
),
);
}
}
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: 14),
ClipRRect(
borderRadius: BorderRadius.circular(99),
child: LinearProgressIndicator(
minHeight: 8,
value: progressValue,
backgroundColor: scheme.surfaceContainerHigh,
),
),
const SizedBox(height: 10),
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),
),
],
),
],
);
}
}