app/lib/screens/welcome_screen.dart
John Mizerek 498a1534ed Add prompt to continue from most recent saved run
When tapping Start with existing saved runs, shows dialog asking
whether to continue from last run or start fresh. Continuing pre-fills
all profile and behavior inputs from the saved run.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2026-02-21 20:49:37 -08:00

192 lines
5.8 KiB
Dart

import 'package:flutter/material.dart';
import '../models/models.dart';
import '../storage/local_storage.dart';
import '../theme.dart';
import 'about_screen.dart';
import 'baseline_screen.dart';
class WelcomeScreen extends StatelessWidget {
const WelcomeScreen({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 32),
child: Column(
children: [
const Spacer(flex: 1),
// Main question - large and centered
Text(
'Simple questions.\nHonest answers.',
style: Theme.of(context).textTheme.headlineLarge?.copyWith(
fontSize: 32,
height: 1.3,
),
textAlign: TextAlign.center,
),
const SizedBox(height: 40),
Text(
"What's the single biggest change I can make to live a longer, healthier life?",
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
fontWeight: FontWeight.w400,
color: AppColors.textSecondary,
height: 1.4,
),
textAlign: TextAlign.center,
),
const Spacer(flex: 2),
// Privacy note
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Icon(
Icons.lock_outline,
size: 16,
color: AppColors.textSecondary,
),
const SizedBox(width: 8),
Text(
'All data stays on your device',
style: Theme.of(context).textTheme.bodySmall,
),
],
),
const SizedBox(height: 24),
// Start button
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () => _handleStart(context),
child: const Text('Start'),
),
),
const SizedBox(height: 16),
// Skip Forever and About links
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
TextButton(
onPressed: () => _showSkipForeverConfirmation(context),
child: const Text('Skip Forever'),
),
const SizedBox(width: 24),
TextButton(
onPressed: () => Navigator.push(
context,
MaterialPageRoute(builder: (_) => const AboutScreen()),
),
child: const Text('About'),
),
],
),
const SizedBox(height: 16),
],
),
),
),
);
}
Future<void> _handleStart(BuildContext context) async {
final recentRun = await LocalStorage.getMostRecentSavedRun();
if (recentRun == null) {
// No saved runs, start fresh
if (context.mounted) {
_navigateToBaseline(context, null, null);
}
return;
}
// Show dialog to choose between continuing or starting fresh
if (context.mounted) {
_showContinueDialog(context, recentRun);
}
}
void _showContinueDialog(BuildContext context, SavedRun recentRun) {
showDialog(
context: context,
builder: (dialogContext) => AlertDialog(
title: const Text('Continue from last run?'),
content: Text(
'You have a saved run from ${recentRun.displayDate}. '
'Would you like to start with those inputs and make adjustments?',
),
actions: [
TextButton(
onPressed: () {
Navigator.pop(dialogContext);
_navigateToBaseline(context, null, null);
},
child: const Text('Start Fresh'),
),
TextButton(
onPressed: () {
Navigator.pop(dialogContext);
_navigateToBaseline(
context,
recentRun.profile,
recentRun.behaviors,
);
},
child: const Text('Continue'),
),
],
),
);
}
void _navigateToBaseline(
BuildContext context,
UserProfile? profile,
BehavioralInputs? behaviors,
) {
if (!context.mounted) return;
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => BaselineScreen(
initialProfile: profile,
initialBehaviors: behaviors,
),
),
);
}
void _showSkipForeverConfirmation(BuildContext context) {
showDialog(
context: context,
builder: (dialogContext) => AlertDialog(
title: const Text('Skip Forever?'),
content: const Text(
'You won\'t be asked to complete the questionnaire again. '
'You can still access the app from the About screen.',
),
actions: [
TextButton(
onPressed: () => Navigator.pop(dialogContext),
child: const Text('Cancel'),
),
TextButton(
onPressed: () async {
await LocalStorage.setSkipForever(true);
Navigator.pop(dialogContext);
if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(
content: Text('Questionnaire skipped'),
duration: Duration(seconds: 2),
),
);
}
},
child: const Text('Skip Forever'),
),
],
),
);
}
}