import 'package:flutter/material.dart'; import 'package:practice_engine/practice_engine.dart'; import '../routes.dart'; class DeckOverviewScreen extends StatefulWidget { const DeckOverviewScreen({super.key}); @override State createState() => _DeckOverviewScreenState(); } class _DeckOverviewScreenState extends State { Deck? _deck; @override void didChangeDependencies() { super.didChangeDependencies(); // Get deck from route arguments or create sample final args = ModalRoute.of(context)?.settings.arguments; if (args is Deck) { setState(() { _deck = args; }); } else if (_deck == null) { // Only create sample if we don't have a deck yet setState(() { _deck = _createSampleDeck(); }); } } @override void initState() { super.initState(); } Deck _createSampleDeck() { const config = DeckConfig(); final questions = List.generate(20, (i) { return Question( id: 'q$i', prompt: 'Sample Question $i?', answers: ['Answer A', 'Answer B', 'Answer C', 'Answer D'], correctAnswerIndex: i % 4, isKnown: i < 5, // First 5 are known ); }); return Deck( id: 'sample-deck', title: 'Sample Practice Deck', description: 'This is a sample deck for practicing. It contains various questions to help you learn.', questions: questions, config: config, ); } void _startAttempt() { if (_deck == null || _deck!.questions.isEmpty) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Cannot start attempt: No questions in deck'), backgroundColor: Colors.red, ), ); return; } Navigator.pushNamed( context, Routes.attempt, arguments: _deck!, ); } void _openConfig() { if (_deck == null) return; Navigator.pushNamed(context, Routes.deckConfig, arguments: _deck) .then((updatedDeck) { if (updatedDeck != null && updatedDeck is Deck) { setState(() { _deck = updatedDeck; }); } }); } Future _resetDeck() async { final confirmed = await showDialog( context: context, builder: (context) => AlertDialog( title: const Text('Reset Deck Progress'), content: const Text( 'Are you sure you want to reset all progress? This will reset streaks, known status, and priorities for all questions.', ), actions: [ TextButton( onPressed: () => Navigator.pop(context, false), child: const Text('Cancel'), ), FilledButton( onPressed: () => Navigator.pop(context, true), style: FilledButton.styleFrom( backgroundColor: Colors.red, ), child: const Text('Reset'), ), ], ), ); if (confirmed == true && _deck != null) { setState(() { _deck = DeckService.resetDeck(deck: _deck!, resetAttemptCounts: false); }); if (mounted) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Deck progress has been reset'), backgroundColor: Colors.green, ), ); } } } @override Widget build(BuildContext context) { if (_deck == null) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } return Scaffold( appBar: AppBar( title: Text(_deck!.title), actions: [ IconButton( icon: const Icon(Icons.refresh), tooltip: 'Reset Progress', onPressed: _resetDeck, ), ], ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ // Deck Description Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Description', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 8), Text( _deck!.description, style: Theme.of(context).textTheme.bodyMedium, ), ], ), ), ), const SizedBox(height: 24), // Practice Progress Card( child: Padding( padding: const EdgeInsets.all(24), child: Column( children: [ Text( 'Practice Progress', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 24), CircularProgressIndicator( value: _deck!.practicePercentage / 100, strokeWidth: 8, ), const SizedBox(height: 16), Text( '${_deck!.practicePercentage.toStringAsFixed(1)}%', style: Theme.of(context).textTheme.headlineMedium?.copyWith( fontWeight: FontWeight.bold, ), ), const SizedBox(height: 8), Text( '${_deck!.knownCount} of ${_deck!.numberOfQuestions} questions known', style: Theme.of(context).textTheme.bodyMedium, ), ], ), ), ), const SizedBox(height: 24), // Statistics Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Statistics', style: Theme.of(context).textTheme.titleMedium, ), const SizedBox(height: 16), Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ _StatItem( label: 'Total Questions', value: '${_deck!.numberOfQuestions}', icon: Icons.quiz, ), _StatItem( label: 'Known', value: '${_deck!.knownCount}', icon: Icons.check_circle, ), _StatItem( label: 'Needs Practice', value: '${_deck!.numberOfQuestions - _deck!.knownCount}', icon: Icons.school, ), ], ), ], ), ), ), const SizedBox(height: 24), // Action Buttons FilledButton.icon( onPressed: _startAttempt, icon: const Icon(Icons.play_arrow), label: const Text('Start Attempt'), style: FilledButton.styleFrom( padding: const EdgeInsets.symmetric(vertical: 16), ), ), const SizedBox(height: 12), OutlinedButton.icon( onPressed: _openConfig, icon: const Icon(Icons.settings), label: const Text('Configure Deck'), ), ], ), ), ); } } class _StatItem extends StatelessWidget { final String label; final String value; final IconData icon; const _StatItem({ required this.label, required this.value, required this.icon, }); @override Widget build(BuildContext context) { return Column( children: [ Icon(icon, size: 32), const SizedBox(height: 8), Text( value, style: Theme.of(context).textTheme.titleLarge?.copyWith( fontWeight: FontWeight.bold, ), ), Text( label, style: Theme.of(context).textTheme.bodySmall, ), ], ); } }