diff --git a/lib/screens/attempt_result_screen.dart b/lib/screens/attempt_result_screen.dart index 2b38d3a..a395e4f 100644 --- a/lib/screens/attempt_result_screen.dart +++ b/lib/screens/attempt_result_screen.dart @@ -131,6 +131,97 @@ class _AttemptResultScreenState extends State { ); } + void _showQuestionDetail(AnswerResult answerResult) { + final q = answerResult.question; + final correctSet = q.correctIndices.toSet(); + final userSet = answerResult.userAnswerIndices.toSet(); + showDialog( + context: context, + builder: (context) => AlertDialog( + title: const Text('Question'), + content: SingleChildScrollView( + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + q.prompt, + style: Theme.of(context).textTheme.titleMedium, + ), + const SizedBox(height: 16), + ...q.answers.asMap().entries.map((e) { + final i = e.key; + final answer = e.value; + final isCorrect = correctSet.contains(i); + final isUser = userSet.contains(i); + String? label; + Color? color; + if (isCorrect && isUser) { + label = 'Correct (your answer)'; + color = Colors.green; + } else if (isCorrect) { + label = 'Correct'; + color = Colors.green; + } else if (isUser) { + label = 'Your answer'; + color = Colors.red; + } + return Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + SizedBox( + width: 24, + child: isCorrect + ? Icon(Icons.check_circle, color: Colors.green, size: 20) + : isUser + ? Icon(Icons.cancel, color: Colors.red, size: 20) + : const Icon(Icons.radio_button_unchecked, size: 20, color: Colors.grey), + ), + const SizedBox(width: 8), + Expanded( + child: Text.rich( + TextSpan( + children: [ + if (label != null) + TextSpan( + text: '$label: ', + style: TextStyle( + color: color, + fontWeight: FontWeight.bold, + fontSize: Theme.of(context).textTheme.bodyLarge?.fontSize, + ), + ), + TextSpan( + text: answer, + style: TextStyle( + color: color, + fontWeight: label != null ? FontWeight.bold : null, + fontSize: Theme.of(context).textTheme.bodyLarge?.fontSize, + ), + ), + ], + ), + ), + ), + ], + ), + ); + }), + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Close'), + ), + ], + ), + ); + } + @override Widget build(BuildContext context) { if (_deck == null || _result == null) { @@ -278,47 +369,61 @@ class _AttemptResultScreenState extends State { Text( answerResult.question.prompt, style: Theme.of(context).textTheme.titleMedium, - ), - const SizedBox(height: 12), - Row( - children: [ - StatusChip(statusChange: answerResult.statusChange), - const Spacer(), - Text( - answerResult.userAnswerIndices.isEmpty - ? 'No answer' - : 'Your answer${answerResult.userAnswerIndices.length > 1 ? 's' : ''}: ${answerResult.userAnswerIndices.map((idx) => answerResult.question.answers[idx]).join(', ')}', - style: TextStyle( - color: Colors.red, - fontWeight: FontWeight.bold, - ), - ), - ], + overflow: TextOverflow.ellipsis, + maxLines: 3, ), const SizedBox(height: 8), + Text( + answerResult.userAnswerIndices.isEmpty + ? 'No answer' + : 'Your answer${answerResult.userAnswerIndices.length > 1 ? 's' : ''}: ${answerResult.userAnswerIndices.map((idx) => answerResult.question.answers[idx]).join(', ')}', + style: TextStyle( + color: Colors.red, + fontWeight: FontWeight.bold, + fontSize: Theme.of(context).textTheme.bodyMedium?.fontSize, + ), + overflow: TextOverflow.ellipsis, + maxLines: 2, + ), + const SizedBox(height: 4), Text( 'Correct answer${answerResult.question.correctIndices.length > 1 ? 's' : ''}: ${answerResult.question.correctIndices.map((idx) => answerResult.question.answers[idx]).join(', ')}', style: TextStyle( color: Colors.green, fontWeight: FontWeight.bold, + fontSize: Theme.of(context).textTheme.bodyMedium?.fontSize, ), + overflow: TextOverflow.ellipsis, + maxLines: 2, ), const SizedBox(height: 12), Row( - mainAxisAlignment: MainAxisAlignment.end, + mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ - TextButton.icon( - onPressed: () => _markNeedsPractice(answerResult.question.id), - icon: const Icon(Icons.replay, size: 20), - label: const Text('Needs practice'), - ), - IconButton( - onPressed: () => _toggleFlag(answerResult.question.id), - icon: Icon( - isFlagged ? Icons.flag : Icons.outlined_flag, - color: isFlagged ? Colors.red : null, - ), - tooltip: isFlagged ? 'Unflag' : 'Flag for review', + StatusChip(statusChange: answerResult.statusChange), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: () => _showQuestionDetail(answerResult), + icon: const Icon(Icons.visibility, size: 22), + tooltip: 'View question details', + ), + IconButton( + onPressed: () => _markNeedsPractice(answerResult.question.id), + icon: const Icon(Icons.replay, size: 22), + tooltip: 'Mark as needs practice', + ), + IconButton( + onPressed: () => _toggleFlag(answerResult.question.id), + icon: Icon( + isFlagged ? Icons.flag : Icons.outlined_flag, + color: isFlagged ? Colors.red : null, + size: 22, + ), + tooltip: isFlagged ? 'Unflag' : 'Flag for review', + ), + ], ), ], ), @@ -341,32 +446,58 @@ class _AttemptResultScreenState extends State { final isFlagged = currentQ?.isFlagged ?? false; return Card( margin: const EdgeInsets.only(bottom: 8), - child: ListTile( - title: Text(answerResult.question.prompt), - subtitle: Text( - answerResult.isCorrect - ? 'Correct' - : answerResult.userAnswerIndices.isEmpty - ? 'Incorrect - No answer' - : 'Incorrect - Selected: ${answerResult.userAnswerIndices.map((idx) => answerResult.question.answers[idx]).join(', ')}', - ), - trailing: Row( - mainAxisSize: MainAxisSize.min, + child: Padding( + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, children: [ - StatusChip(statusChange: answerResult.statusChange), - IconButton( - onPressed: () => _markNeedsPractice(answerResult.question.id), - icon: const Icon(Icons.replay, size: 22), - tooltip: 'Mark as needs practice', + Text( + answerResult.question.prompt, + style: Theme.of(context).textTheme.titleMedium, + overflow: TextOverflow.ellipsis, + maxLines: 3, ), - IconButton( - onPressed: () => _toggleFlag(answerResult.question.id), - icon: Icon( - isFlagged ? Icons.flag : Icons.outlined_flag, - color: isFlagged ? Colors.red : null, - size: 22, - ), - tooltip: isFlagged ? 'Unflag' : 'Flag for review', + const SizedBox(height: 4), + Text( + answerResult.isCorrect + ? 'Correct' + : answerResult.userAnswerIndices.isEmpty + ? 'Incorrect - No answer' + : 'Incorrect - Selected: ${answerResult.userAnswerIndices.map((idx) => answerResult.question.answers[idx]).join(', ')}', + style: Theme.of(context).textTheme.bodyMedium, + overflow: TextOverflow.ellipsis, + maxLines: 2, + ), + const SizedBox(height: 12), + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + StatusChip(statusChange: answerResult.statusChange), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + IconButton( + onPressed: () => _showQuestionDetail(answerResult), + icon: const Icon(Icons.visibility, size: 22), + tooltip: 'View question details', + ), + IconButton( + onPressed: () => _markNeedsPractice(answerResult.question.id), + icon: const Icon(Icons.replay, size: 22), + tooltip: 'Mark as needs practice', + ), + IconButton( + onPressed: () => _toggleFlag(answerResult.question.id), + icon: Icon( + isFlagged ? Icons.flag : Icons.outlined_flag, + color: isFlagged ? Colors.red : null, + size: 22, + ), + tooltip: isFlagged ? 'Unflag' : 'Flag for review', + ), + ], + ), + ], ), ], ),