Skip to content

Commit ecb1960

Browse files
committed
Reorder Questions Numbers
Signed-off-by: Tal Jacob <taljacob2@gmail.com>
1 parent a2513a8 commit ecb1960

1 file changed

Lines changed: 49 additions & 46 deletions

File tree

nextstep-frontend/src/pages/Quiz.tsx

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -16,33 +16,30 @@ import {
1616
Chip,
1717
Divider,
1818
Grid,
19+
Avatar, // <--- Ensure Avatar is imported
1920
} from '@mui/material';
2021
import {
2122
Visibility,
2223
VisibilityOff,
2324
LightbulbOutlined as LightbulbOutlinedIcon,
24-
WorkOutline as WorkOutlineIcon, // For Job Role
25-
InfoOutlined as InfoOutlinedIcon, // For Content/Process Details
26-
ForumOutlined as ForumOutlinedIcon, // For Interviewer Mindset
27-
BusinessOutlined as BusinessOutlinedIcon, // For Company Name
28-
LocalOfferOutlined as LocalOfferOutlinedIcon, // For Tags/Keywords
25+
WorkOutline as WorkOutlineIcon,
26+
InfoOutlined as InfoOutlinedIcon,
27+
ForumOutlined as ForumOutlinedIcon,
28+
BusinessOutlined as BusinessOutlinedIcon,
29+
LocalOfferOutlined as LocalOfferOutlinedIcon,
2930
} from '@mui/icons-material';
3031
import api from '../serverApi'; // Assuming you have a configured axios instance
3132
import { config } from '../config';
3233

3334
// Define interfaces for the API response schemas
34-
interface GeneratedQuestion {
35-
question: string;
36-
}
37-
3835
interface QuizGenerationResponse {
3936
_id: string;
4037
title: string;
4138
tags: string[];
4239
content: string;
4340
job_role: string;
4441
company_name_en: string;
45-
company_name_he: string; // Not used in display, but included for completeness
42+
company_name_he: string;
4643
process_details: string;
4744
question_list: string[];
4845
answer_list: string[];
@@ -61,7 +58,7 @@ interface UserAnsweredQuiz {
6158
process_details: string;
6259
question_list: string[];
6360
answer_list: string[];
64-
user_answer_list: string[]; // New field for user answers
61+
user_answer_list: string[];
6562
keywords: string[];
6663
interviewer_mindset: string;
6764
}
@@ -83,9 +80,9 @@ interface QuizGradingResponse {
8380
interface QuizStateQuestion {
8481
originalQuestion: string;
8582
userAnswer: string;
86-
correctAnswer?: string; // Will be populated after grading
87-
grade?: number; // Will be populated after grading
88-
tip?: string; // Will be populated after grading
83+
correctAnswer?: string;
84+
grade?: number;
85+
tip?: string;
8986
}
9087

9188
interface QuizState {
@@ -110,27 +107,27 @@ const Quiz: React.FC = () => {
110107
const [subject, setSubject] = useState<string>('');
111108
const [quiz, setQuiz] = useState<QuizState | null>(null);
112109
const [loading, setLoading] = useState<boolean>(false);
113-
const [showAnswer, setShowAnswer] = useState<{ [key: number]: boolean }>({}); // To toggle answer visibility
114-
const [quizSubmitted, setQuizSubmitted] = useState<boolean>(false); // To control UI after submission
110+
const [showAnswer, setShowAnswer] = useState<{ [key: number]: boolean }>({});
111+
const [quizSubmitted, setQuizSubmitted] = useState<boolean>(false);
115112

116113
const handleGenerateQuiz = async () => {
117-
if (!subject.trim()) return; // Ensure subject is not empty or just whitespace
114+
if (!subject.trim()) return;
118115
setLoading(true);
119-
setQuiz(null); // Clear previous quiz
120-
setQuizSubmitted(false); // Reset submission status
121-
setShowAnswer({}); // Reset answer visibility
116+
setQuiz(null);
117+
setQuizSubmitted(false);
118+
setShowAnswer({});
122119
try {
123120
const response = await api.post<QuizGenerationResponse>(`${config.app.backend_url()}/quiz/generate`, { subject });
124121

125122
const generatedQuestions: QuizStateQuestion[] = response.data.question_list.map((q: string, idx: number) => ({
126123
originalQuestion: q,
127-
userAnswer: '', // Initialize empty user answer
124+
userAnswer: '',
128125
correctAnswer: response.data.answer_list[idx], // Populate correct answer immediately
129126
}));
130127

131128
setQuiz({
132129
_id: response.data._id,
133-
subject: subject, // Use the input subject for consistency
130+
subject: subject,
134131
questions: generatedQuestions,
135132
title: response.data.title,
136133
tags: response.data.tags,
@@ -140,17 +137,9 @@ const Quiz: React.FC = () => {
140137
processDetails: response.data.process_details,
141138
keywords: response.data.keywords,
142139
interviewerMindset: response.data.interviewer_mindset,
143-
answer_list: response.data.answer_list, // Store for later use if needed, but questions now have it
140+
answer_list: response.data.answer_list,
144141
});
145142

146-
// Do NOT automatically show answers here. User should toggle.
147-
// const initialShowAnswer: { [key: number]: boolean } = {};
148-
// generatedQuestions.forEach((_, index) => {
149-
// initialShowAnswer[index] = true;
150-
// });
151-
// setShowAnswer(initialShowAnswer);
152-
153-
154143
} catch (error) {
155144
console.error('Error generating quiz:', error);
156145
alert('Failed to generate quiz. Please try again.');
@@ -175,21 +164,20 @@ const Quiz: React.FC = () => {
175164
};
176165

177166
const handleSubmitQuiz = async () => {
178-
if (!quiz || quizSubmitted) return; // Prevent multiple submissions
167+
if (!quiz || quizSubmitted) return;
179168
setLoading(true);
180169

181-
// Construct the request body as per the UserAnsweredQuiz schema
182170
const answeredQuizData: UserAnsweredQuiz = {
183171
_id: quiz._id,
184172
title: quiz.title || '',
185173
tags: quiz.tags || [],
186174
content: quiz.content || '',
187175
job_role: quiz.jobRole || '',
188176
company_name_en: quiz.companyNameEn || '',
189-
company_name_he: '', // Assuming this isn't strictly required for grading or can be empty
177+
company_name_he: '',
190178
process_details: quiz.processDetails || '',
191179
question_list: quiz.questions.map(q => q.originalQuestion),
192-
answer_list: quiz.answer_list || [], // Send the original correct answers if available
180+
answer_list: quiz.answer_list || [],
193181
user_answer_list: quiz.questions.map(q => q.userAnswer),
194182
keywords: quiz.keywords || [],
195183
interviewer_mindset: quiz.interviewerMindset || '',
@@ -200,13 +188,12 @@ const Quiz: React.FC = () => {
200188

201189
const gradedQuizData = response.data;
202190
const updatedQuestions = quiz.questions.map((q, index) => {
203-
// Find the corresponding graded answer by matching the question string
204191
const gradedAnswer = gradedQuizData.graded_answers.find(ga => ga.question === q.originalQuestion);
205192
return {
206193
...q,
207194
grade: gradedAnswer?.grade,
208195
tip: gradedAnswer?.tip,
209-
// correctAnswer is already present from generation, no need to set again here
196+
// correctAnswer is already present from generation
210197
};
211198
});
212199

@@ -216,9 +203,9 @@ const Quiz: React.FC = () => {
216203
finalGrade: gradedQuizData.final_quiz_grade,
217204
finalTip: gradedQuizData.final_summary_tip,
218205
});
219-
setQuizSubmitted(true); // Mark quiz as submitted
206+
setQuizSubmitted(true);
220207

221-
// After submission, it's generally good UX to show all correct answers and grades
208+
// After submission, automatically show all correct answers and grades
222209
const initialShowAnswer: { [key: number]: boolean } = {};
223210
updatedQuestions.forEach((_, index) => {
224211
initialShowAnswer[index] = true;
@@ -375,14 +362,30 @@ const Quiz: React.FC = () => {
375362
</Typography>
376363
{quiz.questions.map((q, index) => (
377364
<Paper key={index} sx={{ p: 2, mb: 3, border: '1px solid #e0e0e0' }}>
378-
<Box display="flex" justifyContent="space-between" alignItems="center" mb={1}>
365+
<Box display="flex" justifyContent="space-between" alignItems="flex-start" mb={1}>
366+
{/* Circled Numbering (Option 2) */}
367+
<Avatar
368+
sx={{
369+
bgcolor: 'primary.main',
370+
width: 32,
371+
height: 32,
372+
fontSize: '0.9rem',
373+
fontWeight: 'bold',
374+
mr: 1.5,
375+
boxShadow: 2,
376+
flexShrink: 0, // Prevent shrinking on small screens
377+
}}
378+
>
379+
{index + 1}
380+
</Avatar>
381+
{/* Question Text */}
379382
<Typography variant="h6" sx={{ flexGrow: 1 }}>
380-
Question {index + 1}: {q.originalQuestion}
383+
{q.originalQuestion}
381384
</Typography>
382-
{/* REMOVED: quizSubmitted condition here */}
383-
{q.correctAnswer && ( // Only show if a correct answer exists
385+
{/* Blinking Eye Icon (now always visible if answer exists) */}
386+
{q.correctAnswer && (
384387
<Tooltip title={showAnswer[index] ? 'Hide Answer' : 'Show Answer'} arrow>
385-
<IconButton onClick={() => handleToggleAnswerVisibility(index)} size="small">
388+
<IconButton onClick={() => handleToggleAnswerVisibility(index)} size="small" sx={{ flexShrink: 0, ml: 1 }}>
386389
{showAnswer[index] ? <VisibilityOff /> : <Visibility />}
387390
</IconButton>
388391
</Tooltip>
@@ -397,7 +400,7 @@ const Quiz: React.FC = () => {
397400
value={q.userAnswer}
398401
onChange={e => handleUserAnswerChange(index, e.target.value)}
399402
sx={{ mb: 2 }}
400-
disabled={quizSubmitted} // Disable input after submission
403+
disabled={quizSubmitted}
401404
/>
402405

403406
{/* Grade and Tip are still shown only after submission */}
@@ -414,7 +417,7 @@ const Quiz: React.FC = () => {
414417
min={0}
415418
max={100}
416419
sx={{ width: '90%', mx: 'auto' }}
417-
disabled // Make it non-interactive
420+
disabled
418421
/>
419422
</Box>
420423
<Box sx={{ mt: 2 }}>

0 commit comments

Comments
 (0)