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>
This commit is contained in:
John Mizerek 2026-02-21 20:49:37 -08:00
parent 4ac148b638
commit 498a1534ed
3 changed files with 98 additions and 4 deletions

View file

@ -9,11 +9,13 @@ import 'behavioral_screen.dart';
class BaselineScreen extends StatefulWidget {
final bool readOnly;
final UserProfile? initialProfile;
final BehavioralInputs? initialBehaviors;
const BaselineScreen({
super.key,
this.readOnly = false,
this.initialProfile,
this.initialBehaviors,
});
@override
@ -479,7 +481,10 @@ class _BaselineScreenState extends State<BaselineScreen> {
if (mounted) {
Navigator.of(context).push(
MaterialPageRoute(
builder: (_) => BehavioralScreen(profile: profile),
builder: (_) => BehavioralScreen(
profile: profile,
initialBehaviors: widget.initialBehaviors,
),
),
);
}

View file

@ -1,4 +1,5 @@
import 'package:flutter/material.dart';
import '../models/models.dart';
import '../storage/local_storage.dart';
import '../theme.dart';
import 'about_screen.dart';
@ -57,7 +58,7 @@ class WelcomeScreen extends StatelessWidget {
SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () => _navigateToBaseline(context),
onPressed: () => _handleStart(context),
child: const Text('Start'),
),
),
@ -88,9 +89,70 @@ class WelcomeScreen extends StatelessWidget {
);
}
void _navigateToBaseline(BuildContext context) {
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: (_) => const BaselineScreen()),
MaterialPageRoute(
builder: (_) => BaselineScreen(
initialProfile: profile,
initialBehaviors: behaviors,
),
),
);
}

View file

@ -257,6 +257,33 @@ class LocalStorage {
return result.first['count'] as int;
}
static Future<SavedRun?> getMostRecentSavedRun() async {
final db = await database;
final results = await db.query(
_savedRunsTable,
orderBy: 'created_at DESC',
limit: 1,
);
if (results.isEmpty) return null;
final row = results.first;
return SavedRun(
id: row['id'] as String,
label: row['label'] as String,
result: CalculationResult.fromJson(
jsonDecode(row['result'] as String) as Map<String, dynamic>,
),
profile: UserProfile.fromJson(
jsonDecode(row['profile'] as String) as Map<String, dynamic>,
),
behaviors: BehavioralInputs.fromJson(
jsonDecode(row['behaviors'] as String) as Map<String, dynamic>,
),
createdAt: DateTime.fromMillisecondsSinceEpoch(row['created_at'] as int),
);
}
// ============================================
// Unit preference operations
// ============================================