340 lines
13 KiB
JavaScript
340 lines
13 KiB
JavaScript
import React, { useState } from "react";
|
|
import AdminLayout from "./Layout/AdminLayout";
|
|
import { MdOutlineFileUpload } from "react-icons/md";
|
|
import { Link } from "@inertiajs/react";
|
|
import HitApi from "../../Utils/HitApi";
|
|
import Swal from "sweetalert2";
|
|
const AddKuis = (props) => {
|
|
const { materi, soal } = props;
|
|
|
|
const [form, setForm] = useState({
|
|
soal: "",
|
|
gambar_soal: undefined,
|
|
jawaban: [
|
|
{
|
|
id: 0,
|
|
jawaban: "",
|
|
benar: 0,
|
|
},
|
|
{
|
|
id: 1,
|
|
jawaban: "",
|
|
benar: 0,
|
|
},
|
|
{
|
|
id: 2,
|
|
jawaban: "",
|
|
benar: 0,
|
|
},
|
|
{
|
|
id: 3,
|
|
jawaban: "",
|
|
benar: 0,
|
|
},
|
|
],
|
|
});
|
|
|
|
const handleSave = () => {
|
|
let error = false;
|
|
// buatkan datanya ke formdata
|
|
const formData = new FormData();
|
|
formData.append("id", materi.id);
|
|
formData.append("soal", form.soal);
|
|
formData.append("gambar_soal", form.gambar_soal);
|
|
form.jawaban.forEach((item, i) => {
|
|
if (item.jawaban == "") {
|
|
error = true;
|
|
}
|
|
formData.append(`jawaban[${i}]`, item.jawaban);
|
|
formData.append(`gambar_jawaban[${i}]`, item.gambar_jawaban);
|
|
formData.append(`benar[${i}]`, item.benar);
|
|
});
|
|
|
|
if (error) {
|
|
Swal.fire("Gagal", "Data tidak boleh kosong", "error");
|
|
return;
|
|
}
|
|
|
|
Swal.fire({
|
|
title: "Konfirmasi",
|
|
text: "Apakah anda yakin ingin menyimpan data?",
|
|
icon: "warning",
|
|
showCancelButton: true,
|
|
confirmButtonColor: "#3085d6",
|
|
cancelButtonColor: "#d33",
|
|
confirmButtonText: "Ya",
|
|
}).then((result) => {
|
|
if (result.isConfirmed) {
|
|
Swal.fire({
|
|
title: "Loading",
|
|
html: '<div class="body-loading"><div class="loadingspinner"></div></div>', // add html attribute if you want or remove
|
|
allowOutsideClick: false,
|
|
showConfirmButton: false,
|
|
});
|
|
|
|
HitApi({
|
|
url: "/api/v1/quiz/add",
|
|
method: "POST",
|
|
body: formData,
|
|
isFormData: true,
|
|
onSuccess: () => {
|
|
Swal.fire(
|
|
"Berhasil",
|
|
"Data berhasil disimpan",
|
|
"success"
|
|
);
|
|
|
|
// refresh page
|
|
location.reload();
|
|
},
|
|
onError: () => {
|
|
// Swal.fire("Gagal", "Data gagal ditambahkan", "error");
|
|
Swal.close();
|
|
},
|
|
});
|
|
}
|
|
});
|
|
};
|
|
|
|
const state = {
|
|
form,
|
|
setForm,
|
|
};
|
|
|
|
const [previewImage, setPreviewImage] = useState();
|
|
|
|
return (
|
|
<AdminLayout title="Materi">
|
|
<div className="flex flex-col md:flex-row gap-6 relative ">
|
|
<div className="flex flex-col flex-1 order-2 md:order-1">
|
|
<h1 className="font-semibold text-lg py-2">Input Soal</h1>
|
|
<textarea
|
|
className="textarea textarea-bordered h-[150px] w-full mt-2"
|
|
placeholder="Soal"
|
|
value={form.soal}
|
|
onChange={(e) => {
|
|
setForm({ ...form, soal: e.target.value });
|
|
}}
|
|
></textarea>
|
|
<div className="border-2 relative flex flex-col items-center rounded-md justify-center mt-4 min-h-[200px]">
|
|
{previewImage && (
|
|
<img
|
|
className="absolute w-full h-full object-cover"
|
|
src={
|
|
previewImage
|
|
? URL.createObjectURL(previewImage)
|
|
: `/uploads/soal/${form.gambar_soal}`
|
|
}
|
|
alt="Soal"
|
|
onLoad={(e) => {
|
|
e.target.style.display = "block";
|
|
}}
|
|
onError={(e) => {
|
|
e.target.style.display = "none";
|
|
}}
|
|
/>
|
|
)}
|
|
<input
|
|
onChange={(e) => {
|
|
setPreviewImage(e.target.files[0]);
|
|
setForm({
|
|
...form,
|
|
gambar_soal: e.target.files[0],
|
|
});
|
|
}}
|
|
className="flex w-full h-full opacity-0 absolute"
|
|
type="file"
|
|
name=""
|
|
id=""
|
|
/>
|
|
<MdOutlineFileUpload size={40} />
|
|
<p>Upload Gambar</p>
|
|
</div>
|
|
<h1 className="font-semibold text-lg py-2 mt-4">Jawaban</h1>
|
|
|
|
{form.jawaban.map((item, index) => (
|
|
<CardJawaban
|
|
id={item.id}
|
|
state={state}
|
|
jawaban={item.jawaban}
|
|
isTrue={item.benar}
|
|
key={index}
|
|
gambar={item.gambar_jawaban}
|
|
/>
|
|
))}
|
|
<div className="flex gap-4 justify-end">
|
|
{/* <button className="btn btn-error mt-6 w-fit">
|
|
Delete
|
|
</button> */}
|
|
<button
|
|
onClick={() => handleSave()}
|
|
className="btn btn-primary mt-6 w-fit"
|
|
>
|
|
Save
|
|
</button>
|
|
</div>
|
|
</div>
|
|
|
|
<div className="md:sticky md:top-12 md:right-0 h-fit order-1 md:order-2">
|
|
<div className="md:h-[40px]"></div>
|
|
<div className=" w-full md:w-[300px] lg:w-[400px] border-2 flex p-4 flex-col h-fit ">
|
|
<h1 className="font-semibold text-lg">No Soal</h1>
|
|
<div className="grid grid-cols-4 gap-3 mt-6">
|
|
{materi.kuis.map((item, index) => {
|
|
return (
|
|
<Link
|
|
key={index}
|
|
href={`/admin/quiz/input/${
|
|
materi.id
|
|
}?soal=${index + 1}`}
|
|
>
|
|
<CardNoSoal no={index + 1} />
|
|
</Link>
|
|
);
|
|
})}
|
|
<Link
|
|
href={`/admin/quiz/input/${materi.id}?soal=${
|
|
materi.kuis.length + 1
|
|
}`}
|
|
>
|
|
<CardNoSoal isBaru no={"Tambah Soal"} />
|
|
</Link>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</AdminLayout>
|
|
);
|
|
};
|
|
|
|
const CardNoSoal = ({ no = 1, isBaru = false }) => {
|
|
return (
|
|
<div
|
|
className={`${
|
|
isBaru ? "bg-gray-300 text-black" : "bg-primary text-white"
|
|
} flex items-center justify-center text-xs py-4 rounded-md px-3 text-center h-full`}
|
|
>
|
|
{no}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
const CardJawaban = ({ id, jawaban, gambar, isTrue = false, state }) => {
|
|
const { form, setForm } = state;
|
|
|
|
const [preview, setPreview] = useState();
|
|
|
|
return (
|
|
<label
|
|
className="flex flex-row gap-4 border-2 rounded-md px-4 py-6 my-4"
|
|
htmlFor=""
|
|
>
|
|
<div className="py-4">
|
|
<input
|
|
onChange={(e) => {
|
|
{
|
|
setForm({
|
|
...form,
|
|
jawaban: [
|
|
...form.jawaban.map((item) => {
|
|
if (item.id == e.target.value) {
|
|
return {
|
|
...item,
|
|
benar: 1,
|
|
};
|
|
} else {
|
|
return {
|
|
...item,
|
|
benar: 0,
|
|
};
|
|
}
|
|
}),
|
|
],
|
|
});
|
|
}
|
|
}}
|
|
type="radio"
|
|
value={id}
|
|
name="radio-7"
|
|
className="radio radio-info"
|
|
checked={isTrue}
|
|
/>
|
|
</div>
|
|
<div className="flex flex-col w-full">
|
|
<textarea
|
|
className="textarea w-full mt-2 ouli"
|
|
value={jawaban}
|
|
onChange={(e) => {
|
|
{
|
|
setForm({
|
|
...form,
|
|
jawaban: [
|
|
...form.jawaban.map((item) => {
|
|
if (item.id == id) {
|
|
return {
|
|
...item,
|
|
jawaban: e.target.value,
|
|
};
|
|
} else {
|
|
return item;
|
|
}
|
|
}),
|
|
],
|
|
});
|
|
}
|
|
}}
|
|
placeholder="Jawaban"
|
|
></textarea>
|
|
<div className="flex flex-col relative items-center bg-gray-100 rounded-md justify-center mt-4 min-h-[200px]">
|
|
{preview && (
|
|
<img
|
|
className="absolute w-full h-full object-cover"
|
|
src={
|
|
preview
|
|
? URL.createObjectURL(preview)
|
|
: `/uploads/jawaban/${gambar}`
|
|
}
|
|
alt="Jawaban"
|
|
onLoad={(e) => {
|
|
e.target.style.display = "block";
|
|
}}
|
|
onError={(e) => {
|
|
e.target.style.display = "none";
|
|
}}
|
|
/>
|
|
)}
|
|
<input
|
|
onChange={(e) => {
|
|
setPreview(e.target.files[0]);
|
|
setForm({
|
|
...form,
|
|
jawaban: [
|
|
...form.jawaban.map((item) => {
|
|
if (item.id == id) {
|
|
return {
|
|
...item,
|
|
gambar_jawaban:
|
|
e.target.files[0],
|
|
};
|
|
} else {
|
|
return item;
|
|
}
|
|
}),
|
|
],
|
|
});
|
|
}}
|
|
className="flex w-full h-full opacity-0 absolute"
|
|
type="file"
|
|
name=""
|
|
id=""
|
|
/>
|
|
<MdOutlineFileUpload size={40} />
|
|
<p>Upload Gambar</p>
|
|
</div>
|
|
</div>
|
|
</label>
|
|
);
|
|
};
|
|
|
|
export default AddKuis;
|