237 lines
9.8 KiB
PHP
237 lines
9.8 KiB
PHP
<?php
|
|
declare(strict_types=1);
|
|
@date_default_timezone_set('UTC');
|
|
|
|
require_once __DIR__ . '/includes/db_init.php';
|
|
|
|
$db = db();
|
|
ensure_schema($db);
|
|
seed_classes($db);
|
|
|
|
$roles = ['admin', 'guru', 'orang_tua', 'siswa', 'bendahara'];
|
|
$role = $_GET['role'] ?? 'admin';
|
|
if (!in_array($role, $roles, true)) {
|
|
$role = 'admin';
|
|
}
|
|
|
|
$errors = [];
|
|
$success = isset($_GET['success']) ? (int)$_GET['success'] : 0;
|
|
|
|
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
|
$studentCode = trim($_POST['student_code'] ?? '');
|
|
$fullName = trim($_POST['full_name'] ?? '');
|
|
$gender = trim($_POST['gender'] ?? '');
|
|
$classId = (int)($_POST['class_id'] ?? 0);
|
|
$guardianName = trim($_POST['guardian_name'] ?? '');
|
|
$status = trim($_POST['status'] ?? 'aktif');
|
|
$notes = trim($_POST['notes'] ?? '');
|
|
|
|
if ($studentCode === '' || strlen($studentCode) < 3) {
|
|
$errors[] = 'Kode siswa wajib diisi (min 3 karakter).';
|
|
}
|
|
if ($fullName === '') {
|
|
$errors[] = 'Nama lengkap wajib diisi.';
|
|
}
|
|
if ($classId <= 0) {
|
|
$errors[] = 'Silakan pilih kelas.';
|
|
}
|
|
if ($status === '') {
|
|
$errors[] = 'Status siswa wajib dipilih.';
|
|
}
|
|
|
|
if (!$errors) {
|
|
try {
|
|
$stmt = $db->prepare("INSERT INTO students (student_code, full_name, gender, class_id, guardian_name, status, notes)
|
|
VALUES (:code, :name, :gender, :class_id, :guardian, :status, :notes)");
|
|
$stmt->execute([
|
|
':code' => $studentCode,
|
|
':name' => $fullName,
|
|
':gender' => $gender !== '' ? $gender : null,
|
|
':class_id' => $classId,
|
|
':guardian' => $guardianName !== '' ? $guardianName : null,
|
|
':status' => $status,
|
|
':notes' => $notes !== '' ? $notes : null,
|
|
]);
|
|
header('Location: students.php?role=' . urlencode($role) . '&success=1');
|
|
exit;
|
|
} catch (PDOException $e) {
|
|
if ((int)$e->getCode() === 23000) {
|
|
$errors[] = 'Kode siswa sudah digunakan. Gunakan kode lain.';
|
|
} else {
|
|
$errors[] = 'Gagal menyimpan data siswa.';
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
$classes = $db->query("SELECT id, name, grade_level FROM classes ORDER BY grade_level, name")->fetchAll();
|
|
$students = $db->query("
|
|
SELECT s.id, s.student_code, s.full_name, s.status, s.created_at,
|
|
c.name AS class_name, c.grade_level
|
|
FROM students s
|
|
LEFT JOIN classes c ON c.id = s.class_id
|
|
ORDER BY s.created_at DESC
|
|
LIMIT 50
|
|
")->fetchAll();
|
|
|
|
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
|
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
|
$projectName = $_SERVER['PROJECT_NAME'] ?? 'School Management System';
|
|
?>
|
|
<!doctype html>
|
|
<html lang="id">
|
|
<head>
|
|
<meta charset="utf-8" />
|
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
|
<title><?= htmlspecialchars($projectName) ?> — Data Siswa</title>
|
|
<?php if ($projectDescription): ?>
|
|
<meta name="description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
|
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
|
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
|
<?php endif; ?>
|
|
<?php if ($projectImageUrl): ?>
|
|
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
|
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
|
<?php endif; ?>
|
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600&display=swap" rel="stylesheet">
|
|
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
|
<link rel="stylesheet" href="assets/css/custom.css?v=<?= time(); ?>">
|
|
</head>
|
|
<body>
|
|
<div class="app-shell">
|
|
<nav class="navbar navbar-expand-lg">
|
|
<div class="container-fluid px-4">
|
|
<a class="navbar-brand" href="index.php?role=<?= urlencode($role) ?>">EduCore CMS</a>
|
|
<div class="ms-auto">
|
|
<a class="btn btn-outline-secondary btn-sm" href="index.php?role=<?= urlencode($role) ?>">Kembali ke Dashboard</a>
|
|
</div>
|
|
</div>
|
|
</nav>
|
|
|
|
<main class="container-fluid px-4 py-4">
|
|
<div class="row g-3">
|
|
<div class="col-lg-5">
|
|
<div class="card-soft p-3 h-100">
|
|
<div class="section-title">Registrasi Siswa Baru</div>
|
|
<form method="post" novalidate>
|
|
<div class="mb-2">
|
|
<label class="form-label">Kode Siswa</label>
|
|
<input type="text" name="student_code" class="form-control" placeholder="SIM-2026-001" required>
|
|
</div>
|
|
<div class="mb-2">
|
|
<label class="form-label">Nama Lengkap</label>
|
|
<input type="text" name="full_name" class="form-control" placeholder="Nama siswa" required>
|
|
</div>
|
|
<div class="mb-2">
|
|
<label class="form-label">Jenis Kelamin</label>
|
|
<select name="gender" class="form-select">
|
|
<option value="">Pilih</option>
|
|
<option value="Laki-laki">Laki-laki</option>
|
|
<option value="Perempuan">Perempuan</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-2">
|
|
<label class="form-label">Kelas</label>
|
|
<select name="class_id" class="form-select" required>
|
|
<option value="">Pilih kelas</option>
|
|
<?php foreach ($classes as $class): ?>
|
|
<option value="<?= (int)$class['id'] ?>"><?= htmlspecialchars($class['name']) ?> (Kelas <?= htmlspecialchars($class['grade_level']) ?>)</option>
|
|
<?php endforeach; ?>
|
|
</select>
|
|
</div>
|
|
<div class="mb-2">
|
|
<label class="form-label">Nama Wali</label>
|
|
<input type="text" name="guardian_name" class="form-control" placeholder="Nama orang tua/wali">
|
|
</div>
|
|
<div class="mb-2">
|
|
<label class="form-label">Status</label>
|
|
<select name="status" class="form-select" required>
|
|
<option value="aktif">Aktif</option>
|
|
<option value="mutasi">Mutasi</option>
|
|
<option value="lulus">Lulus</option>
|
|
<option value="alumni">Alumni</option>
|
|
</select>
|
|
</div>
|
|
<div class="mb-3">
|
|
<label class="form-label">Catatan</label>
|
|
<textarea name="notes" class="form-control" rows="3" placeholder="Catatan tambahan"></textarea>
|
|
</div>
|
|
<button class="btn btn-primary w-100" type="submit">Simpan Data Siswa</button>
|
|
</form>
|
|
|
|
<?php if ($errors): ?>
|
|
<div class="alert alert-danger mt-3 mb-0">
|
|
<ul class="mb-0">
|
|
<?php foreach ($errors as $err): ?>
|
|
<li><?= htmlspecialchars($err) ?></li>
|
|
<?php endforeach; ?>
|
|
</ul>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-7">
|
|
<div class="card-soft p-3 h-100">
|
|
<div class="d-flex flex-column flex-md-row justify-content-between align-items-md-center gap-2">
|
|
<div class="section-title mb-0">Daftar Siswa Terbaru</div>
|
|
<input id="studentSearch" type="text" class="form-control form-control-sm search-input" placeholder="Cari nama atau kode">
|
|
</div>
|
|
<?php if (!$students): ?>
|
|
<div class="empty-state mt-3">Belum ada siswa yang terdaftar. Tambahkan data pertama di form.</div>
|
|
<?php else: ?>
|
|
<div class="table-responsive mt-3">
|
|
<table class="table table-sm align-middle">
|
|
<thead>
|
|
<tr>
|
|
<th>Kode</th>
|
|
<th>Nama</th>
|
|
<th>Kelas</th>
|
|
<th>Status</th>
|
|
<th></th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<?php foreach ($students as $student): ?>
|
|
<?php
|
|
$searchHay = strtolower($student['student_code'] . ' ' . $student['full_name'] . ' ' . ($student['class_name'] ?? ''));
|
|
?>
|
|
<tr data-student-row="<?= htmlspecialchars($searchHay) ?>">
|
|
<td><?= htmlspecialchars($student['student_code']) ?></td>
|
|
<td><?= htmlspecialchars($student['full_name']) ?></td>
|
|
<td><?= htmlspecialchars($student['class_name'] ?? '-') ?></td>
|
|
<td><span class="badge text-bg-light border"><?= htmlspecialchars(ucfirst($student['status'])) ?></span></td>
|
|
<td class="text-end">
|
|
<a class="btn btn-sm btn-outline-secondary" href="student.php?id=<?= (int)$student['id'] ?>&role=<?= urlencode($role) ?>">Detail</a>
|
|
</td>
|
|
</tr>
|
|
<?php endforeach; ?>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<?php endif; ?>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</main>
|
|
|
|
<footer class="footer text-center">
|
|
© <?= date('Y') ?> EduCore CMS • Modul Data Siswa
|
|
</footer>
|
|
</div>
|
|
|
|
<div class="toast-container position-fixed bottom-0 end-0 p-3">
|
|
<div id="liveToast" class="toast" role="alert" aria-live="assertive" aria-atomic="true" data-autoshow="<?= $success ? '1' : '0' ?>">
|
|
<div class="toast-header">
|
|
<strong class="me-auto">Sukses</strong>
|
|
<small>Baru saja</small>
|
|
<button type="button" class="btn-close" data-bs-dismiss="toast" aria-label="Close"></button>
|
|
</div>
|
|
<div class="toast-body">Data siswa berhasil ditambahkan.</div>
|
|
</div>
|
|
</div>
|
|
|
|
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
|
<script src="assets/js/main.js?v=<?= time(); ?>"></script>
|
|
</body>
|
|
</html>
|