const QB_TYPES = ['Objective', 'Fill Blanks', 'Match', 'Drag & Drop', 'Select Answer']; const QB_DIFFS = ['Easy', 'Medium', 'Difficult']; function QuestionBank({ onNavigate }) { const [trade, setTrade] = React.useState('Fitter'); const [diff, setDiff] = React.useState('All'); const [selected, setSelected] = React.useState({}); const [adding, setAdding] = React.useState(false); const [draft, setDraft] = React.useState({ q: '', type: 'Objective', diff: 'Easy', topic: '', marks: 1 }); const nextId = React.useRef(150); const trades = ['Fitter', 'Electrician', 'Welder', 'Turner', 'COPA']; const diffs = ['All', 'Easy', 'Medium', 'Difficult']; const types = { Objective: 'var(--navy-700)', 'Fill Blanks': 'var(--saffron-600)', 'Match': 'var(--green-600)', 'Drag & Drop': 'var(--navy-600)', 'Select Answer': 'var(--red-600)', }; const [questions, setQuestions] = React.useState([ { id: 'FTR-0142', q: 'Which file is used for finishing a flat surface?', type: 'Objective', diff: 'Easy', topic: 'Bench Work', marks: 1 }, { id: 'FTR-0143', q: 'The included angle of a centre punch is ____ degrees.', type: 'Fill Blanks', diff: 'Medium', topic: 'Marking', marks: 1 }, { id: 'FTR-0144', q: 'Match the fit type to its allowance value.', type: 'Match', diff: 'Difficult', topic: 'Fits & Tolerances', marks: 2 }, { id: 'FTR-0145', q: 'Arrange the drilling operation steps in correct sequence.', type: 'Drag & Drop', diff: 'Medium', topic: 'Drilling', marks: 2 }, { id: 'FTR-0146', q: 'Select the correct vernier caliper reading from the 3D image.', type: 'Select Answer', diff: 'Medium', topic: 'Measuring', marks: 2 }, { id: 'FTR-0147', q: 'What is the standard taper for a Morse taper shank?', type: 'Objective', diff: 'Difficult', topic: 'Machining', marks: 2 }, { id: 'FTR-0148', q: 'Least count of a metric vernier caliper is ____ mm.', type: 'Fill Blanks', diff: 'Easy', topic: 'Measuring', marks: 1 }, { id: 'FTR-0149', q: 'Identify the correct thread profile for a metric bolt.', type: 'Select Answer', diff: 'Easy', topic: 'Threading', marks: 1 }, ]); const filtered = questions.filter(q => diff === 'All' || q.diff === diff); const selCount = Object.values(selected).filter(Boolean).length; const selMarks = questions.filter(q => selected[q.id]).reduce((a, q) => a + q.marks, 0); const toggle = id => setSelected(s => ({ ...s, [id]: !s[id] })); const openAdd = () => { setDraft({ q: '', type: 'Objective', diff: 'Easy', topic: '', marks: 1 }); setAdding(true); }; const saveQuestion = () => { if (!draft.q.trim()) { window.toast('Please enter the question text'); return; } const code = trade.slice(0, 3).toUpperCase(); nextId.current += 1; const id = `${code}-${String(nextId.current).padStart(4, '0')}`; const rec = { id, q: draft.q.trim(), type: draft.type, diff: draft.diff, topic: draft.topic.trim() || 'General', marks: Number(draft.marks) || 1 }; setQuestions(qs => [rec, ...qs]); setAdding(false); window.toast('Question ' + id + ' added to the bank'); }; return (
Question Bank

500+ questions per trade, NCVT-aligned.

Filter by weightage & type, add your own questions, and assign timed tests to your batch.

{/* Stat row */}
{[ { k: '512', v: 'Questions in bank', s: 'Fitter trade' }, { k: '5', v: 'Question types', s: 'MCQ · Fill · Match · Drag · Select' }, { k: '38', v: 'Added by you', s: 'This academic year' }, { k: '14', v: 'Tests assigned', s: '3 currently active' }, ].map(s => (
{s.k}
{s.v}
{s.s}
))}
{/* Question list */}
{trades.map(t => ( ))}
{diffs.map(d => ( ))}
{filtered.map(q => ( toggle(q.id)}> ))}
QUESTION TYPE LEVEL MARKS
{selected[q.id] && }
{q.q}
{q.id} · {q.topic}
{q.type} {q.diff} {q.marks}
{/* Assign test panel */}
Build a test
Select questions from the bank to assemble a paper.
{selCount}
Questions
{selMarks}
Total marks
{[ { l: 'Assign to', v: 'Batch F-2024-A (38)' }, { l: 'Duration', v: '45 minutes · timed' }, { l: 'Random order', v: 'Enabled' }, { l: 'Result visibility', v: 'Instructor only' }, ].map(x => (
{x.l} {x.v}
))}
setAdding(false)} width={520} footer={<> } >