import 'package:flutter/material.dart'; import 'package:practice_engine/practice_engine.dart'; class DeckConfigScreen extends StatefulWidget { const DeckConfigScreen({super.key}); @override State createState() => _DeckConfigScreenState(); } class _DeckConfigScreenState extends State { Deck? _deck; DeckConfig? _config; late TextEditingController _consecutiveController; late TextEditingController _attemptSizeController; late TextEditingController _priorityIncreaseController; late TextEditingController _priorityDecreaseController; late bool _immediateFeedback; @override void initState() { super.initState(); _deck = null; } @override void didChangeDependencies() { super.didChangeDependencies(); if (_deck == null) { // Get deck from route arguments final args = ModalRoute.of(context)?.settings.arguments; _deck = args is Deck ? args : _createSampleDeck(); _config = _deck!.config; _consecutiveController = TextEditingController( text: _config!.requiredConsecutiveCorrect.toString(), ); _attemptSizeController = TextEditingController( text: _config!.defaultAttemptSize.toString(), ); _priorityIncreaseController = TextEditingController( text: _config!.priorityIncreaseOnIncorrect.toString(), ); _priorityDecreaseController = TextEditingController( text: _config!.priorityDecreaseOnCorrect.toString(), ); _immediateFeedback = _config!.immediateFeedbackEnabled; } } Deck _createSampleDeck() { return Deck( id: 'sample', title: 'Sample', description: 'Sample', questions: [], config: const DeckConfig(), ); } @override void dispose() { _consecutiveController.dispose(); _attemptSizeController.dispose(); _priorityIncreaseController.dispose(); _priorityDecreaseController.dispose(); super.dispose(); } void _save() { if (_deck == null || _config == null) return; final consecutive = int.tryParse(_consecutiveController.text); final attemptSize = int.tryParse(_attemptSizeController.text); final priorityIncrease = int.tryParse(_priorityIncreaseController.text); final priorityDecrease = int.tryParse(_priorityDecreaseController.text); if (consecutive == null || attemptSize == null || priorityIncrease == null || priorityDecrease == null) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Please enter valid numbers for all fields'), backgroundColor: Colors.red, ), ); return; } if (consecutive < 1 || attemptSize < 1 || priorityIncrease < 0 || priorityDecrease < 0) { ScaffoldMessenger.of(context).showSnackBar( const SnackBar( content: Text('Values must be positive (priority changes >= 0)'), backgroundColor: Colors.red, ), ); return; } final updatedConfig = _config!.copyWith( requiredConsecutiveCorrect: consecutive, defaultAttemptSize: attemptSize, priorityIncreaseOnIncorrect: priorityIncrease, priorityDecreaseOnCorrect: priorityDecrease, immediateFeedbackEnabled: _immediateFeedback, ); final updatedDeck = _deck!.copyWith(config: updatedConfig); Navigator.pop(context, updatedDeck); } void _cancel() { Navigator.pop(context); } @override Widget build(BuildContext context) { if (_deck == null || _config == null) { return const Scaffold( body: Center(child: CircularProgressIndicator()), ); } return Scaffold( appBar: AppBar( title: const Text('Deck Configuration'), ), body: SingleChildScrollView( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.stretch, children: [ Card( child: Padding( padding: const EdgeInsets.all(16), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Text( 'Practice Settings', style: Theme.of(context).textTheme.titleLarge, ), const SizedBox(height: 24), // Required Consecutive Correct TextField( controller: _consecutiveController, decoration: const InputDecoration( labelText: 'Required Consecutive Correct', helperText: 'Number of correct answers in a row to mark as known', border: OutlineInputBorder(), ), keyboardType: TextInputType.number, ), const SizedBox(height: 16), // Default Attempt Size TextField( controller: _attemptSizeController, decoration: const InputDecoration( labelText: 'Default Questions Per Attempt', helperText: 'Number of questions to include in each attempt', border: OutlineInputBorder(), ), keyboardType: TextInputType.number, ), const SizedBox(height: 16), // Priority Increase TextField( controller: _priorityIncreaseController, decoration: const InputDecoration( labelText: 'Priority Increase on Incorrect', helperText: 'Priority points added when answered incorrectly', border: OutlineInputBorder(), ), keyboardType: TextInputType.number, ), const SizedBox(height: 16), // Priority Decrease TextField( controller: _priorityDecreaseController, decoration: const InputDecoration( labelText: 'Priority Decrease on Correct', helperText: 'Priority points removed when answered correctly', border: OutlineInputBorder(), ), keyboardType: TextInputType.number, ), const SizedBox(height: 16), // Immediate Feedback Toggle SwitchListTile( title: const Text('Immediate Feedback'), subtitle: const Text( 'Show correct/incorrect immediately after answering', ), value: _immediateFeedback, onChanged: (value) { setState(() { _immediateFeedback = value; }); }, ), ], ), ), ), const SizedBox(height: 24), // Action Buttons Row( children: [ Expanded( child: OutlinedButton( onPressed: _cancel, child: const Text('Cancel'), ), ), const SizedBox(width: 16), Expanded( child: FilledButton( onPressed: _save, child: const Text('Save'), ), ), ], ), ], ), ), ); } }