Files
examjam-frontend/examjam-admin/components/ExamBuilder.tsx
2025-07-03 01:43:25 +06:00

234 lines
6.6 KiB
TypeScript

import React, { useState } from "react";
const ExamBuilder = () => {
const [paper, setPaper] = useState({
id: "",
title: "",
data: {
metadata: {
type: "single",
marking: "",
duration: 0,
quantity: 0,
},
questions: [
{
id: 1,
type: "single",
options: {
a: "",
b: "",
c: "",
d: "",
},
question: "",
solution: "",
correctAnswer: "",
},
],
},
});
const handleChange = (e) => {
const { name, value } = e.target;
setPaper((prev) => ({
...prev,
[name]: value,
}));
};
const handleMetadataChange = (e) => {
const { name, value } = e.target;
setPaper((prev) => ({
...prev,
data: {
...prev.data,
metadata: {
...prev.data.metadata,
[name]: value,
},
},
}));
};
const handleQuestionChange = (index, field, value) => {
const updatedQuestions = paper.data.questions.map((q, i) =>
i === index ? { ...q, [field]: value } : q
);
setPaper((prev) => ({
...prev,
data: { ...prev.data, questions: updatedQuestions },
}));
};
const handleOptionChange = (index, optionKey, value) => {
const updatedQuestions = paper.data.questions.map((q, i) =>
i === index ? { ...q, options: { ...q.options, [optionKey]: value } } : q
);
setPaper((prev) => ({
...prev,
data: { ...prev.data, questions: updatedQuestions },
}));
};
const addQuestion = () => {
setPaper((prev) => ({
...prev,
data: {
...prev.data,
questions: [
...prev.data.questions,
{
id: prev.data.questions.length + 1,
type: "single",
options: { a: "", b: "", c: "", d: "" },
question: "",
solution: "",
correctAnswer: "",
},
],
},
}));
};
const handleSubmit = (e) => {
e.preventDefault();
console.log("Exam Paper Submitted: ", paper);
};
return (
<section className="flex w-3/4 gap-10 h-fit">
<section className="border-1 border-blue-100 rounded-2xl mt-5 py-10 px-10 max-h-[70vh] w-1/2">
<h1 className="text-white text-3xl font-bold text-center mb-6">
Exam Builder
</h1>
<form className="flex flex-col gap-4" onSubmit={handleSubmit}>
<h2 className="text-white text-2xl">General Information</h2>
<input
type="text"
name="title"
value={paper.title}
onChange={handleChange}
placeholder="Exam Title"
className="bg-white w-full rounded-full py-3 px-6"
/>
<h2 className="text-white text-2xl">Metadata</h2>
<select
name="type"
value={paper.data.metadata.type}
onChange={handleMetadataChange}
className="bg-white p-4 rounded-full"
>
<option value="single">Multiple Choice Questions (Single)</option>
<option value="multiple">
Multiple Choice Questions (Multiple)
</option>
</select>
<input
type="text"
name="marking"
value={paper.data.metadata.marking}
onChange={handleMetadataChange}
placeholder="Marking"
className="bg-white w-full rounded-full py-3 px-6"
/>
<input
type="number"
name="duration"
value={paper.data.metadata.duration}
onChange={handleMetadataChange}
placeholder="Duration"
className="bg-white w-full rounded-full py-3 px-6"
/>
<input
type="number"
name="quantity"
value={paper.data.metadata.quantity}
onChange={handleMetadataChange}
placeholder="How many questions?"
className="bg-white w-full rounded-full py-3 px-6"
/>
<button
type="submit"
className="bg-blue-500 text-white p-3 rounded-full mt-4"
>
Submit Exam
</button>
</form>
</section>
<section className="border-1 border-blue-100 rounded-2xl mt-5 py-10 px-10 w-1/2">
<h1 className="text-white text-3xl font-bold text-center mb-6">
Questions
</h1>
{paper.data.questions.map((question, index) => (
<div key={index} className="rounded-lg">
<h2 className="text-white text-xl mb-4">Question {index + 1}</h2>
<input
type="text"
value={question.question}
onChange={(e) =>
handleQuestionChange(index, "question", e.target.value)
}
placeholder="Question"
className="bg-white w-full rounded-full py-3 px-6 mb-2"
/>
<div className="">
{Object.keys(question.options).map((key) => (
<div key={key} className="flex items-center gap-2 mb-2">
<h3 className="text-white uppercase py-3 px-5 rounded-full bg-blue-600">
{key}
</h3>
<input
type="text"
value={question.options[key]}
onChange={(e) =>
handleOptionChange(index, key, e.target.value)
}
placeholder={`Option ${key.toUpperCase()}`}
className="bg-white w-full rounded-full py-3 px-6"
/>
</div>
))}
</div>
<input
type="text"
value={question.correctAnswer.toLowerCase()}
onChange={(e) =>
handleQuestionChange(index, "correctAnswer", e.target.value)
}
placeholder="Correct answer (a, b, c, d)"
className="bg-white w-full rounded-full py-3 px-6 mt-2"
/>
<input
type="text"
value={question.solution}
onChange={(e) =>
handleQuestionChange(index, "solution", e.target.value)
}
placeholder="Solution"
className="bg-white w-full rounded-full py-3 px-6 mt-2"
/>
</div>
))}
<button
type="button"
onClick={addQuestion}
className="bg-green-500 text-white p-3 rounded-full mt-2"
>
Add Question
</button>
</section>
</section>
);
};
export default ExamBuilder;
{
/* */
}