fix: extract collection dialogs into own StatefulWidgets
Same _dependents.isEmpty crash as the password dialog the Add/Already Exists dialogs were sharing the parent context across async DB calls. Now each dialog is an independent widget with its own lifecycle.
This commit is contained in:
parent
8c453e3f13
commit
7a6975e146
1 changed files with 85 additions and 61 deletions
146
lib/main.dart
146
lib/main.dart
|
|
@ -380,15 +380,12 @@ class HomeScreen extends StatelessWidget {
|
|||
|
||||
/// Opens the scanner, gets the hw_id, then queries the DB.
|
||||
Future<void> _openScanner(BuildContext context) async {
|
||||
// 1. Navigate to the scanner screen and wait for the result.
|
||||
final hwId = await Navigator.of(context).push<String>(
|
||||
MaterialPageRoute(builder: (_) => const ScannerScreen()),
|
||||
);
|
||||
|
||||
// User cancelled / went back without selecting an ID.
|
||||
if (hwId == null || !context.mounted) return;
|
||||
|
||||
// 2. Query the database.
|
||||
try {
|
||||
final data = await supabase
|
||||
.from('hotwheels')
|
||||
|
|
@ -399,11 +396,15 @@ class HomeScreen extends StatelessWidget {
|
|||
if (!context.mounted) return;
|
||||
|
||||
if (data != null) {
|
||||
// ── Car already exists ──
|
||||
_showAlreadyExistsDialog(context, hwId);
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) => _AlreadyExistsDialog(hwId: hwId),
|
||||
);
|
||||
} else {
|
||||
// ── Car is new — offer to add it ──
|
||||
_showAddDialog(context, hwId);
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (_) => _AddCarDialog(hwId: hwId),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (!context.mounted) return;
|
||||
|
|
@ -412,62 +413,85 @@ class HomeScreen extends StatelessWidget {
|
|||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Shows an alert: this car is already in the collection.
|
||||
void _showAlreadyExistsDialog(BuildContext context, String hwId) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
icon: const Icon(Icons.check_circle, color: Colors.green, size: 48),
|
||||
title: const Text('Already in Collection!'),
|
||||
content: Text('$hwId is already in your shared garage.'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
child: const Text('Got it'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
// ── "Already in Collection" Dialog ────────────────────────────────────
|
||||
class _AlreadyExistsDialog extends StatelessWidget {
|
||||
final String hwId;
|
||||
const _AlreadyExistsDialog({required this.hwId});
|
||||
|
||||
/// Shows a confirmation dialog to add a new car.
|
||||
void _showAddDialog(BuildContext context, String hwId) {
|
||||
showDialog<void>(
|
||||
context: context,
|
||||
builder: (ctx) => AlertDialog(
|
||||
icon: const Icon(Icons.add_circle_outline, color: Colors.deepPurple, size: 48),
|
||||
title: const Text('New Car Found!'),
|
||||
content: Text('$hwId is not in your collection yet.\nAdd it now?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(ctx).pop(),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: () async {
|
||||
try {
|
||||
await supabase.from('hotwheels').insert({
|
||||
'hw_id': hwId,
|
||||
'user_id': supabase.auth.currentUser!.id,
|
||||
});
|
||||
if (!ctx.mounted) return;
|
||||
Navigator.of(ctx).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('$hwId added to your collection! 🎉')),
|
||||
);
|
||||
} catch (e) {
|
||||
if (!ctx.mounted) return;
|
||||
Navigator.of(ctx).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to add: $e'), backgroundColor: Colors.red),
|
||||
);
|
||||
}
|
||||
},
|
||||
child: const Text('Add to Collection'),
|
||||
),
|
||||
],
|
||||
),
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
icon: const Icon(Icons.check_circle, color: Colors.green, size: 48),
|
||||
title: const Text('Already in Collection!'),
|
||||
content: Text('$hwId is already in your shared garage.'),
|
||||
actions: [
|
||||
ElevatedButton(
|
||||
onPressed: () => Navigator.of(context).pop(),
|
||||
child: const Text('Got it'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// ── "Add to Collection" Dialog ────────────────────────────────────────
|
||||
class _AddCarDialog extends StatefulWidget {
|
||||
final String hwId;
|
||||
const _AddCarDialog({required this.hwId});
|
||||
|
||||
@override
|
||||
State<_AddCarDialog> createState() => _AddCarDialogState();
|
||||
}
|
||||
|
||||
class _AddCarDialogState extends State<_AddCarDialog> {
|
||||
bool _isAdding = false;
|
||||
|
||||
Future<void> _addCar() async {
|
||||
setState(() => _isAdding = true);
|
||||
|
||||
try {
|
||||
await supabase.from('hotwheels').insert({
|
||||
'hw_id': widget.hwId,
|
||||
'user_id': supabase.auth.currentUser!.id,
|
||||
});
|
||||
if (!mounted) return;
|
||||
Navigator.of(context).pop();
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('${widget.hwId} added to your collection! 🎉')),
|
||||
);
|
||||
} catch (e) {
|
||||
if (!mounted) return;
|
||||
setState(() => _isAdding = false);
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to add: $e'), backgroundColor: Colors.red),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return AlertDialog(
|
||||
icon: const Icon(Icons.add_circle_outline, color: Colors.deepPurple, size: 48),
|
||||
title: const Text('New Car Found!'),
|
||||
content: Text('${widget.hwId} is not in your collection yet.\nAdd it now?'),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: _isAdding ? null : () => Navigator.of(context).pop(),
|
||||
child: const Text('Cancel'),
|
||||
),
|
||||
ElevatedButton(
|
||||
onPressed: _isAdding ? null : _addCar,
|
||||
child: _isAdding
|
||||
? const SizedBox(
|
||||
height: 18,
|
||||
width: 18,
|
||||
child: CircularProgressIndicator(strokeWidth: 2),
|
||||
)
|
||||
: const Text('Add to Collection'),
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in a new issue