542 lines
21 KiB
HTML
542 lines
21 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="en">
|
|
|
|
<head>
|
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1, user-scalable=no">
|
|
<meta name="description" content="">
|
|
<meta name="author" content="">
|
|
|
|
<title>SMKS Muhammad Ahmad Dahlan | Kuis & Soalan</title>
|
|
|
|
<!-- Main Styles -->
|
|
<link rel="stylesheet" href="/styles/style.min.css">
|
|
|
|
<!-- mCustomScrollbar -->
|
|
<link rel="stylesheet" href="/plugin/mCustomScrollbar/jquery.mCustomScrollbar.min.css">
|
|
|
|
<!-- Waves Effect -->
|
|
<link rel="stylesheet" href="/plugin/waves/waves.min.css">
|
|
|
|
<!-- Sweet Alert -->
|
|
<link rel="stylesheet" href="/plugin/sweet-alert/sweetalert.css">
|
|
|
|
<link rel="stylesheet" href="/fonts/fontello/fontello.css">
|
|
|
|
<!-- Toastr -->
|
|
<link rel="stylesheet" href="/plugin/toastr/toastr.css">
|
|
|
|
<link rel="stylesheet" href="/fonts/material-design-iconic-font/css/material-design-iconic-font.min.css">
|
|
<link rel="stylesheet" href="/fonts/material-design/css/materialdesignicons.css">
|
|
<script src="/auth.js"></script>
|
|
<style>
|
|
.box-title {
|
|
cursor: pointer;
|
|
user-select: none;
|
|
}
|
|
|
|
.toggle-icon {
|
|
display: inline-block;
|
|
transition: transform 0.2s ease;
|
|
margin-right: 6px;
|
|
}
|
|
|
|
.box-content.card.minimized .toggle-icon {
|
|
transform: rotate(-90deg);
|
|
}
|
|
|
|
.box-content.card.error {
|
|
border: 2px solid red !important;
|
|
box-shadow: 0 0 6px red;
|
|
}
|
|
</style>
|
|
|
|
|
|
</head>
|
|
|
|
<body>
|
|
<div class="main-menu">
|
|
<header class="header">
|
|
<a href="/admin" class="logo">SMK Mahda</a>
|
|
<button type="button" class="button-close fa fa-times js__menu_close"></button>
|
|
<div class="user">
|
|
<a href="#" class="avatar"><img src="/images/admin.png" class="img-avatar" alt=""><span
|
|
class="status online"></span></a>
|
|
<h5 class="name"><a href="#" id="h5-title">...</a></h5>
|
|
<h5 class="position">Guru</h5>
|
|
|
|
</div>
|
|
<!-- /.user -->
|
|
</header>
|
|
<!-- /.header -->
|
|
<div class="content">
|
|
|
|
<div class="navigation">
|
|
<h5 class="title">Navigasi</h5>
|
|
<!-- /.title -->
|
|
<ul class="menu js__accordion">
|
|
<li>
|
|
<a class="waves-effect" href="/guru"><i class="menu-icon fa fa-home"></i><span>Halaman
|
|
Utama</span></a>
|
|
</li>
|
|
|
|
<li>
|
|
<a class="waves-effect" href="#" onclick="notAvailable()"><i
|
|
class="menu-icon ico icon-table"></i><span>Materi</span></a>
|
|
</li>
|
|
|
|
<!-- <li>
|
|
<a class="waves-effect" href="#" onclick="notAvailable()"><i
|
|
class="menu-icon fa fa-users"></i><span>List User</span></a>
|
|
</li> -->
|
|
|
|
<li class="current active">
|
|
<a class="waves-effect" href="/guru/quiz"><i class="menu-icon ico icon-table"></i><span>Kuis &
|
|
Soal</span></a>
|
|
</li>
|
|
|
|
<li>
|
|
<a class="waves-effect" href="#" onclick="notAvailable()"><i
|
|
class="menu-icon fa fa-unlock-alt"></i><span>Ganti Password</span></a>
|
|
</li>
|
|
|
|
|
|
<li>
|
|
<a class="waves-effect" href="#" onclick="logout()"><i
|
|
class="menu-icon ico icon-logout"></i><span>Logout</span></a>
|
|
</li>
|
|
</ul>
|
|
|
|
</div>
|
|
<!-- /.navigation -->
|
|
</div>
|
|
<!-- /.content -->
|
|
</div>
|
|
<!-- /.main-menu -->
|
|
|
|
<div class="fixed-navbar">
|
|
<div class="pull-left">
|
|
<button type="button"
|
|
class="menu-mobile-button glyphicon glyphicon-menu-hamburger js__menu_mobile"></button>
|
|
<h1 class="page-title">Kuis & Soalan</h1>
|
|
<!-- /.page-title -->
|
|
</div>
|
|
<!-- /.pull-left -->
|
|
<div class="pull-right">
|
|
|
|
|
|
<a href="#" class="ico-item ico icon-logout" onclick="logout()"></a>
|
|
</div>
|
|
<!-- /.pull-right -->
|
|
</div>
|
|
<!-- /.fixed-navbar -->
|
|
|
|
<div id="wrapper">
|
|
<div class="main-content">
|
|
<div class="row small-spacing">
|
|
<div class="col-lg-4 col-md-4 col-xs-12"></div>
|
|
<div class="col-lg-4 col-md-4 col-xs-12">
|
|
<div class="box-content card">
|
|
<h4 class="box-title">Detail Soal</h4>
|
|
<div class="card-content">
|
|
<form class="form-horizontal">
|
|
<div class="col-sm-12">
|
|
<div class="form-group">
|
|
<input type="text" class="form-control" id="judul_soal"
|
|
placeholder="Masukkan Judul Soal">
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12">
|
|
<div class="form-group">
|
|
<select name="mata_pelajaran" id="mata_pelajaran" class="form-control">
|
|
<option value="" disabled selected>-Sila Pilih Mata Pelajaran-</option>
|
|
<option value="Bahasa Melayu">Bahasa Melayu</option>
|
|
<option value="Bahasa Inggeris">Bahasa Inggeris</option>
|
|
<option value="Bahasa Arab">Bahasa Arab</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="col-sm-12">
|
|
<div class="form-group">
|
|
<select name="kelas" id="kelas" class="form-control">
|
|
<option value="" disabled selected>-Sila Pilih Kelas-</option>
|
|
<option value="1">X</option>
|
|
<option value="2">XI</option>
|
|
<option value="3">XII</option>
|
|
</select>
|
|
</div>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<div class="col-sm-9">
|
|
<input type="number" class="form-control" id="jumlah_soal"
|
|
placeholder="Masukkan Jumlah Soal">
|
|
</div>
|
|
<div class="col-sm-3">
|
|
<button type="button"
|
|
class="btn btn-social btn-success waves-effect waves-light "><i
|
|
class="ico fa fa-check" onclick="buatSoal()"></i></button>
|
|
</div>
|
|
</div>
|
|
<!-- <div class="form-group">
|
|
|
|
</div> -->
|
|
</form>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-4 col-md-4 col-xs-12"></div>
|
|
</div>
|
|
|
|
<div class="row small-spacing">
|
|
<div class="col-lg-12 col-md-12 col-xs-12" id="container-soal">
|
|
<!-- <div class="box-content card " id="soal-1">
|
|
<h4 class="box-title">Soal 1</h4>
|
|
<div class="card-content">
|
|
|
|
<div class="form-group">
|
|
<select class="form-control" id="jenis_soal">
|
|
<option value="" disabled selected>-Pilih Jenis Soal</option>
|
|
<option value="pilihan_ganda">Pilihan Ganda</option>
|
|
<option value="isian">Isian</option>
|
|
</select>
|
|
</div>
|
|
|
|
</div>
|
|
</div> -->
|
|
</div>
|
|
</div>
|
|
<br>
|
|
<center><button type="button" class="btn btn-success waves-effect waves-light "
|
|
onclick="validateQuestions()"><i class="ico fa fa-check"></i> Simpan Soal</button></center>
|
|
|
|
<footer class="footer">
|
|
<ul class="list-inline">
|
|
<li>Gerbang Pembelajaran Interaktif - SMKS Muhammad Ahmad Dahlan © Rika Rahman 2025.</li>
|
|
<!-- <li><a href="#">Privacy</a></li>
|
|
<li><a href="#">Terms</a></li>
|
|
<li><a href="#">Help</a></li> -->
|
|
</ul>
|
|
</footer>
|
|
</div>
|
|
<!-- /.main-content -->
|
|
</div><!--/#wrapper -->
|
|
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
|
<!--[if lt IE 9]>
|
|
<script src="/script/html5shiv.min.js"></script>
|
|
<script src="/script/respond.min.js"></script>
|
|
<![endif]-->
|
|
<!--
|
|
================================================== -->
|
|
<!-- Placed at the end of the document so the pages load faster -->
|
|
<script src="/scripts/jquery.min.js"></script>
|
|
<script src="/scripts/modernizr.min.js"></script>
|
|
<script src="/plugin/bootstrap/js/bootstrap.min.js"></script>
|
|
<script src="/plugin/mCustomScrollbar/jquery.mCustomScrollbar.concat.min.js"></script>
|
|
<script src="/plugin/nprogress/nprogress.js"></script>
|
|
<script src="/plugin/sweet-alert/sweetalert.min.js"></script>
|
|
<script src="/plugin/waves/waves.min.js"></script>
|
|
<!-- Full Screen Plugin -->
|
|
<script src="/plugin/fullscreen/jquery.fullscreen-min.js"></script>
|
|
|
|
<!-- Toastr -->
|
|
<script src="/plugin/toastr/toastr.min.js"></script>
|
|
|
|
<script src="/scripts/main.min.js"></script>
|
|
<script src="/my-js.js"></script>
|
|
|
|
<script>
|
|
console.log(datanya.jk);
|
|
$(".img-avatar").attr("src", datanya.jk == "Laki-laki" ? "/images/guru3.png" : "/images/guru2.png");
|
|
$("#h5-title").html(datanya.nama);
|
|
|
|
</script>
|
|
|
|
<script>
|
|
function minimizeDiv(id) {
|
|
const soalDiv = document.getElementById(id);
|
|
const content = soalDiv.querySelector(".card-content");
|
|
|
|
// Toggle a class to track the state
|
|
soalDiv.classList.toggle("minimized");
|
|
|
|
if (soalDiv.classList.contains("minimized")) {
|
|
// Minimize: smoothly hide
|
|
$(content).slideUp(200);
|
|
} else {
|
|
// Maximize: smoothly show
|
|
$(content).slideDown(200);
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
let soalData = {}; // Store all question data temporarily
|
|
let dataAll;
|
|
|
|
function saveCurrentData() {
|
|
soalData = {}; // reset
|
|
dataAll = [];
|
|
document.querySelectorAll(".box-content.card").forEach((soalDiv, index) => {
|
|
const id = soalDiv.id;
|
|
const jenis = soalDiv.querySelector(".jenis-soal")?.value || "";
|
|
const inputs = soalDiv.querySelectorAll("textarea, input");
|
|
|
|
// ini untuk simpan data agar ditampilkan kemudian
|
|
soalData[id] = {
|
|
jenis,
|
|
values: Array.from(inputs).map((el) => el.value)
|
|
};
|
|
// dataAll.push(soalData[id]);
|
|
|
|
// ini untuk simpan jawaban untuk dipost
|
|
const jenisContainer = soalDiv.querySelector(".jenis-container");
|
|
|
|
let data = {};
|
|
if (jenis === "pilihan_ganda") {
|
|
const pertanyaan = jenisContainer.querySelector("textarea:nth-of-type(1)")?.value || "";
|
|
const jawabans = Array.from(jenisContainer.querySelectorAll("textarea"))
|
|
.slice(1, 6)
|
|
.map(t => t.value || "");
|
|
const jawabanBenar = jenisContainer.querySelector("input")?.value || "";
|
|
const pembahasan = jenisContainer.querySelector("textarea:last-of-type")?.value || "";
|
|
|
|
data = {
|
|
jenis: "pilihan_ganda",
|
|
soal: pertanyaan,
|
|
A: jawabans[0],
|
|
B: jawabans[1],
|
|
C: jawabans[2],
|
|
D: jawabans[3],
|
|
E: jawabans[4],
|
|
benar: jawabanBenar,
|
|
pembahasan: pembahasan
|
|
};
|
|
}
|
|
else if (jenis === "isian") {
|
|
const pertanyaan = jenisContainer.querySelector("textarea:nth-of-type(1)")?.value || "";
|
|
const pembahasan = jenisContainer.querySelector("textarea:nth-of-type(2)")?.value || "";
|
|
data = {
|
|
jenis: "isian",
|
|
soal: pertanyaan,
|
|
pembahasan: pembahasan
|
|
};
|
|
}
|
|
|
|
dataAll.push(data);
|
|
|
|
|
|
});
|
|
|
|
|
|
console.log(JSON.stringify(dataAll));
|
|
}
|
|
|
|
|
|
function restoreData() {
|
|
// console.log(soalData);
|
|
for (const [id, data] of Object.entries(soalData)) {
|
|
const soalDiv = document.getElementById(id);
|
|
if (!soalDiv) continue; // skip deleted
|
|
if (data.jenis) {
|
|
soalDiv.querySelector(".jenis-soal").value = data.jenis;
|
|
tukarJenisSoal(data.jenis, id);
|
|
// Wait a tiny bit so the elements exist before restoring
|
|
setTimeout(() => {
|
|
const inputs = soalDiv.querySelectorAll("textarea, input");
|
|
data.values.forEach((val, i) => {
|
|
if (inputs[i]) inputs[i].value = val;
|
|
});
|
|
}, 50);
|
|
}
|
|
}
|
|
}
|
|
|
|
function buatSoal() {
|
|
// Save current input before rebuild
|
|
saveCurrentData();
|
|
|
|
const jumlah = parseInt(document.getElementById("jumlah_soal").value);
|
|
const container = document.getElementById("container-soal");
|
|
const existingCount = container.children.length;
|
|
|
|
if (isNaN(jumlah) || jumlah <= 0) {
|
|
alert("Masukkan jumlah soal yang valid!");
|
|
return;
|
|
}
|
|
|
|
// If decreasing: remove extras
|
|
if (jumlah < existingCount) {
|
|
for (let i = existingCount; i > jumlah; i--) {
|
|
const soalDiv = document.getElementById(`soal-${i}`);
|
|
if (soalDiv) soalDiv.remove();
|
|
delete soalData[`soal-${i}`]; // remove its data
|
|
}
|
|
}
|
|
|
|
// If increasing: add new ones
|
|
for (let i = existingCount + 1; i <= jumlah; i++) {
|
|
const soalDiv = document.createElement("div");
|
|
soalDiv.className = "box-content card";
|
|
soalDiv.id = `soal-${i}`;
|
|
soalDiv.innerHTML = `
|
|
<h4 class="box-title">Soal ${i}</h4>
|
|
<div class="card-content">
|
|
<div class="form-group">
|
|
<label for="jenis_soal_${i}">Pilih Jenis Soal:</label>
|
|
<select class="form-control jenis-soal" id="jenis_soal_${i}" data-id="soal-${i}">
|
|
<option value="" disabled selected>- Pilih Jenis Soal -</option>
|
|
<option value="pilihan_ganda">Pilihan Ganda</option>
|
|
<option value="isian">Isian</option>
|
|
</select>
|
|
</div>
|
|
<div class="jenis-container"></div>
|
|
</div>
|
|
`;
|
|
container.appendChild(soalDiv);
|
|
}
|
|
|
|
// Restore any saved data
|
|
restoreData();
|
|
}
|
|
|
|
// Event listener for dynamic selects
|
|
$(document).on("change", ".jenis-soal", function () {
|
|
const jenis = $(this).val();
|
|
const id = $(this).data("id");
|
|
tukarJenisSoal(jenis, id);
|
|
|
|
// Restore previously typed answers (if exist)
|
|
if (soalData[id]?.jenis === jenis && soalData[id]?.values?.length) {
|
|
setTimeout(() => {
|
|
const inputs = document.querySelectorAll(`#${id} textarea, #${id} input`);
|
|
soalData[id].values.forEach((val, i) => {
|
|
if (inputs[i]) inputs[i].value = val;
|
|
});
|
|
}, 50);
|
|
}
|
|
});
|
|
|
|
function tukarJenisSoal(jenis, id) {
|
|
const card = document.querySelector(`#${id} .jenis-container`);
|
|
card.innerHTML = ""; // clear old content
|
|
|
|
if (jenis === "pilihan_ganda") {
|
|
card.innerHTML = `
|
|
<div class="form-group">
|
|
<label>Pertanyaan:</label>
|
|
<textarea class="form-control" placeholder="Tulis pertanyaan..."></textarea>
|
|
</div>
|
|
|
|
<label>Pilihan Jawaban:</label>
|
|
${["A", "B", "C", "D", "E"]
|
|
.map(
|
|
(huruf) => `
|
|
<div class="form-group">
|
|
<label>${huruf}:</label>
|
|
<textarea class="form-control" placeholder="Jawaban ${huruf}..."></textarea>
|
|
</div>
|
|
`
|
|
)
|
|
.join("")}
|
|
|
|
<div class="form-group">
|
|
<label>Jawaban Benar (contoh: A):</label>
|
|
<input type="text" class="form-control" maxlength="1" placeholder="Masukkan huruf jawaban benar...">
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Pembahasan:</label>
|
|
<textarea class="form-control" placeholder="Tulis pembahasan..."></textarea>
|
|
</div>
|
|
`;
|
|
} else if (jenis === "isian") {
|
|
card.innerHTML = `
|
|
<div class="form-group">
|
|
<label>Pertanyaan:</label>
|
|
<textarea class="form-control" placeholder="Tulis pertanyaan..."></textarea>
|
|
</div>
|
|
|
|
<div class="form-group">
|
|
<label>Jawaban / Pembahasan:</label>
|
|
<textarea class="form-control" placeholder="Tulis jawaban atau pembahasan..."></textarea>
|
|
</div>
|
|
`;
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<script>
|
|
function validateQuestions() {
|
|
let incomplete = [];
|
|
const soalDivs = $(".box-content.card");
|
|
const jumlahSoalInput = parseInt($("#jumlah_soal").val()) || 0;
|
|
|
|
soalDivs.removeClass("error");
|
|
|
|
// 🧩 CASE 1: No question divs
|
|
if (soalDivs.length === 0) {
|
|
alert("❌ Belum ada soal yang dibuat!");
|
|
return;
|
|
}
|
|
|
|
// 🧩 CASE 2: Jumlah soal mismatch
|
|
if (jumlahSoalInput === 0) {
|
|
alert("❌ Jumlah soal belum diisi!");
|
|
return;
|
|
}
|
|
if (soalDivs.length !== jumlahSoalInput) {
|
|
alert(`⚠️ Jumlah soal (${soalDivs.length}) tidak sesuai dengan input jumlah soal (${jumlahSoalInput})!`);
|
|
return;
|
|
}
|
|
|
|
// 🧩 Validate each question
|
|
soalDivs.each(function (index) {
|
|
const soalDiv = $(this);
|
|
const nomor = index + 1;
|
|
const jenis = soalDiv.find(".jenis-soal").val();
|
|
let allFilled = true;
|
|
|
|
if (!jenis) {
|
|
allFilled = false;
|
|
} else {
|
|
soalDiv.find(".jenis-container").find("input, textarea").each(function () {
|
|
if ($(this).val().trim() === "") {
|
|
allFilled = false;
|
|
}
|
|
});
|
|
}
|
|
|
|
if (!allFilled) {
|
|
incomplete.push(nomor);
|
|
soalDiv.addClass("error");
|
|
}
|
|
});
|
|
|
|
if (incomplete.length > 0) {
|
|
alert("❌ Soal nomor " + incomplete.join(", ") + " belum lengkap!");
|
|
$("html, body").animate({
|
|
scrollTop: $("#soal-" + incomplete[0]).offset().top - 100
|
|
}, 600);
|
|
return;
|
|
}
|
|
|
|
// ✅ Semua lengkap → kumpulkan data
|
|
saveCurrentData(); // Save current input before rebuild and dataAll
|
|
console.log(dataAll);
|
|
|
|
alert("✅ Semua soal sudah lengkap dan data siap dikirim!");
|
|
// Di sini bisa kirim via AJAX, atau simpan ke localStorage, dsb
|
|
// contoh: localStorage.setItem("soalData", JSON.stringify(soalData));
|
|
}
|
|
|
|
// 🧠 Function untuk mengumpulkan data dari semua soal
|
|
</script>
|
|
|
|
|
|
</body>
|
|
|
|
</html> |