refactor(exam): flat sidebar list, weight badges, UI cleanup
Signed-off-by: Abhinav Sinha <[email protected]>
This commit is contained in:
@@ -2,11 +2,18 @@ import { useState, useEffect, useRef } from 'react'
|
||||
import styles from './ExamStartModal.module.css'
|
||||
|
||||
export default function ExamStartModal({ bundle, onStart, onCancel }) {
|
||||
const totalScenarios = bundle?.scenario_ids?.length || 0
|
||||
const [minutes, setMinutes] = useState(bundle?.exam_minutes || 120)
|
||||
const [scenarioCount, setScenarioCount] = useState(totalScenarios)
|
||||
const inputRef = useRef(null)
|
||||
|
||||
// Keep scenarioCount in sync if bundle changes
|
||||
useEffect(() => {
|
||||
// Focus input on open
|
||||
setScenarioCount(bundle?.scenario_ids?.length || 0)
|
||||
}, [bundle])
|
||||
|
||||
useEffect(() => {
|
||||
// Focus duration input on open
|
||||
const t = setTimeout(() => inputRef.current?.select(), 60)
|
||||
return () => clearTimeout(t)
|
||||
}, [])
|
||||
@@ -14,11 +21,14 @@ export default function ExamStartModal({ bundle, onStart, onCancel }) {
|
||||
if (!bundle) return null
|
||||
|
||||
const numMinutes = Number(minutes)
|
||||
const isValid = numMinutes >= 5 && numMinutes <= 300
|
||||
const numScenarios = Number(scenarioCount)
|
||||
const isMinutesValid = numMinutes >= 5 && numMinutes <= 300
|
||||
const isScenariosValid = numScenarios >= 1 && numScenarios <= totalScenarios
|
||||
const isValid = isMinutesValid && isScenariosValid
|
||||
|
||||
const handleStart = () => {
|
||||
if (!isValid) return
|
||||
onStart(numMinutes)
|
||||
onStart(numMinutes, numScenarios)
|
||||
}
|
||||
|
||||
const presets = [
|
||||
@@ -42,9 +52,10 @@ export default function ExamStartModal({ bundle, onStart, onCancel }) {
|
||||
<div className={styles.body}>
|
||||
<div className={styles.info}>
|
||||
<span>📋</span>
|
||||
<span>{bundle.scenario_ids?.length || '?'} scenarios · Recommended: <strong>{bundle.exam_minutes} min</strong></span>
|
||||
<span>{totalScenarios} scenarios · Recommended: <strong>{bundle.exam_minutes} min</strong></span>
|
||||
</div>
|
||||
|
||||
{/* Duration field */}
|
||||
<div className={styles.field}>
|
||||
<label className={styles.label}>Exam Duration</label>
|
||||
<div className={styles.presets}>
|
||||
@@ -73,13 +84,46 @@ export default function ExamStartModal({ bundle, onStart, onCancel }) {
|
||||
<span className={styles.unit}>minutes</span>
|
||||
</div>
|
||||
<div className={styles.hint}>
|
||||
{!isValid ? (
|
||||
{!isMinutesValid ? (
|
||||
<span style={{ color: 'var(--red)' }}>⚠ Duration must be between 5 and 300 minutes</span>
|
||||
) : numMinutes < 60 ? '⚡ Speed run mode' :
|
||||
numMinutes <= 120 ? '🎯 Realistic exam timing' :
|
||||
'🧘 Relaxed practice pace'}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Scenario count field */}
|
||||
<div className={styles.field}>
|
||||
<label className={styles.label}>Number of Scenarios</label>
|
||||
<div className={styles.scenarioRow}>
|
||||
<input
|
||||
type="range"
|
||||
className={styles.slider}
|
||||
value={numScenarios}
|
||||
min={1}
|
||||
max={totalScenarios}
|
||||
step={1}
|
||||
onChange={e => setScenarioCount(Number(e.target.value))}
|
||||
style={{ '--bcolor': bundle.color }}
|
||||
/>
|
||||
<input
|
||||
type="number"
|
||||
className={styles.input}
|
||||
value={scenarioCount}
|
||||
min={1}
|
||||
max={totalScenarios}
|
||||
onChange={e => setScenarioCount(e.target.value)}
|
||||
onKeyDown={e => e.key === 'Enter' && handleStart()}
|
||||
/>
|
||||
</div>
|
||||
<div className={styles.hint}>
|
||||
{!isScenariosValid ? (
|
||||
<span style={{ color: 'var(--red)' }}>⚠ Must be between 1 and {totalScenarios}</span>
|
||||
) : numScenarios === totalScenarios
|
||||
? `📚 Full exam — all ${totalScenarios} scenarios`
|
||||
: `🎯 ${numScenarios} randomly selected scenario${numScenarios > 1 ? 's' : ''}`}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div className={styles.actions}>
|
||||
|
||||
Reference in New Issue
Block a user