From d5c76f9f4b21b493349fec241c07ac45066946db Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 21 Nov 2025 08:59:40 +0000 Subject: [PATCH 1/3] Initial plan From 5484b928e1ab1f3c92943e342b6d55305c37cef3 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 21 Nov 2025 09:17:18 +0000 Subject: [PATCH 2/3] Add evaluation and response management features - Change evaluation default from 3 to null (no selection) - Add validation to prevent submitting evaluation without all ratings - Add "Clear All Responses" button to delete all recorded answers - Display previous evaluations history on practice page - Add visual indicators (*) for unselected evaluation fields - Add confirmation dialog for clearing all responses Co-authored-by: mbianchidev <37507190+mbianchidev@users.noreply.github.com> --- app/practice/page.tsx | 141 +++++++++++++++++++++++++++++++++++++----- 1 file changed, 124 insertions(+), 17 deletions(-) diff --git a/app/practice/page.tsx b/app/practice/page.tsx index cfc7486..aae88d6 100644 --- a/app/practice/page.tsx +++ b/app/practice/page.tsx @@ -3,8 +3,8 @@ import { useState, useEffect, useRef } from 'react'; import Link from 'next/link'; import { allQuestions } from '@/lib/questionsData'; -import { saveResponse, deleteResponse } from '@/lib/responseStorage'; -import { saveEvaluation } from '@/lib/evaluationStorage'; +import { saveResponse, deleteResponse, clearAllResponses } from '@/lib/responseStorage'; +import { saveEvaluation, getAllEvaluations, SelfEvaluation } from '@/lib/evaluationStorage'; interface Question { id: string; @@ -26,14 +26,25 @@ export default function PracticePage() { const [questionsInRound, setQuestionsInRound] = useState(0); const [extraTime, setExtraTime] = useState(0); const [showEvaluation, setShowEvaluation] = useState(false); - const [evaluation, setEvaluation] = useState({ - confidence: 3, - effectiveness: 3, - knowledge: 3, + const [evaluation, setEvaluation] = useState<{ + confidence: number | null; + effectiveness: number | null; + knowledge: number | null; + }>({ + confidence: null, + effectiveness: null, + knowledge: null, }); + const [previousEvaluations, setPreviousEvaluations] = useState([]); + const [showPreviousEvaluations, setShowPreviousEvaluations] = useState(false); const skipQuestionRef = useRef<(() => void) | null>(null); + // Load previous evaluations on mount + useEffect(() => { + setPreviousEvaluations(getAllEvaluations()); + }, []); + useEffect(() => { let interval: NodeJS.Timeout | null = null; @@ -148,7 +159,21 @@ export default function PracticePage() { }; const handleSubmitEvaluation = () => { - saveEvaluation(evaluation); + // Validate that all evaluations are filled + if (evaluation.confidence === null || evaluation.effectiveness === null || evaluation.knowledge === null) { + alert('Please rate all three categories before submitting.'); + return; + } + + saveEvaluation({ + confidence: evaluation.confidence, + effectiveness: evaluation.effectiveness, + knowledge: evaluation.knowledge, + }); + + // Reload evaluations to show the new one + setPreviousEvaluations(getAllEvaluations()); + // Reset for new round setShowEvaluation(false); setQuestionsInRound(0); @@ -157,6 +182,11 @@ export default function PracticePage() { setCurrentQuestion(null); setTimer(TIMER_DURATION); setIsActive(false); + setEvaluation({ + confidence: null, + effectiveness: null, + knowledge: null, + }); }; const handleStartNewRound = () => { @@ -166,6 +196,14 @@ export default function PracticePage() { getRandomQuestion(); }; + const handleClearAllResponses = () => { + if (window.confirm('Are you sure you want to delete all your recorded answers? This action cannot be undone.')) { + clearAllResponses(); + setResponse(''); + alert('All responses have been cleared.'); + } + }; + return (
@@ -194,7 +232,7 @@ export default function PracticePage() {
{[1, 2, 3, 4, 5].map((val) => ( @@ -215,7 +253,7 @@ export default function PracticePage() {
{[1, 2, 3, 4, 5].map((val) => ( @@ -236,7 +274,7 @@ export default function PracticePage() {
{[1, 2, 3, 4, 5].map((val) => ( @@ -262,6 +300,11 @@ export default function PracticePage() { > Submit Evaluation & Start New Round + {(evaluation.confidence === null || evaluation.effectiveness === null || evaluation.knowledge === null) && ( +

+ * Please rate all three categories before submitting +

+ )}
) : !currentQuestion ? (
@@ -271,13 +314,77 @@ export default function PracticePage() {

Finish questions early? Your extra time rolls over to the next question!

- + +
+ + + +
+ + {previousEvaluations.length > 0 && ( +
+ + + {showPreviousEvaluations && ( +
+ {previousEvaluations.slice().reverse().map((evalItem, index) => ( +
+
+

+ Round {evalItem.roundNumber} +

+ + {new Date(evalItem.timestamp).toLocaleDateString()} {new Date(evalItem.timestamp).toLocaleTimeString()} + +
+
+
+

Confidence

+
+ {evalItem.confidence} + /5 +
+
+
+

Effectiveness

+
+ {evalItem.effectiveness} + /5 +
+
+
+

Knowledge

+
+ {evalItem.knowledge} + /5 +
+
+
+
+ ))} +
+ )} +
+ )}
) : (
From b13559c10f2b005d77b31a82f76a055ae1d0a8d4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 21 Nov 2025 09:20:07 +0000 Subject: [PATCH 3/3] Fix React key anti-pattern in evaluations list Use evalItem.timestamp as unique key instead of array index Co-authored-by: mbianchidev <37507190+mbianchidev@users.noreply.github.com> --- app/practice/page.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/practice/page.tsx b/app/practice/page.tsx index aae88d6..de13e16 100644 --- a/app/practice/page.tsx +++ b/app/practice/page.tsx @@ -343,9 +343,9 @@ export default function PracticePage() { {showPreviousEvaluations && (
- {previousEvaluations.slice().reverse().map((evalItem, index) => ( + {previousEvaluations.slice().reverse().map((evalItem) => (