SIAKAD 1.0

This commit is contained in:
Flatlogic Bot 2025-12-24 04:07:02 +00:00
parent d4291f001f
commit bb0884a9fc
29 changed files with 4699 additions and 148 deletions

42
assets/css/style.css Normal file
View File

@ -0,0 +1,42 @@
body {
font-family: 'Inter', sans-serif;
background-color: #F3F4F6;
}
.sidebar {
position: fixed;
top: 0;
left: 0;
height: 100%;
width: 250px;
background-color: #FFFFFF;
padding-top: 1rem;
border-right: 1px solid #e5e7eb;
}
.sidebar .nav-link {
color: #4B5563;
font-weight: 500;
}
.sidebar .nav-link.active,
.sidebar .nav-link:hover {
color: #4F46E5;
background-color: #EEF2FF;
}
.sidebar .nav-link .feather {
margin-right: 1rem;
color: #9CA3AF;
}
.sidebar .nav-link.active .feather,
.sidebar .nav-link:hover .feather {
color: #4F46E5;
}
.main-content {
margin-left: 250px;
padding: 2rem;
}

6
assets/js/main.js Normal file
View File

@ -0,0 +1,6 @@
(function () {
'use strict'
feather.replace()
})()

28
db/migrate.php Normal file
View File

@ -0,0 +1,28 @@
<?php
// db/migrate.php
require_once __DIR__ . '/config.php';
function run_migrations() {
try {
$pdo = db();
$migration_file = __DIR__ . '/migrations/001_create_murid_table.sql';
if (!file_exists($migration_file)) {
return ['success' => false, 'message' => 'File migrasi tidak ditemukan.'];
}
$sql = file_get_contents($migration_file);
$pdo->exec($sql);
return ['success' => true, 'message' => 'Migrasi tabel `murid` berhasil dijalankan.'];
} catch (PDOException $e) {
return ['success' => false, 'message' => 'Migrasi gagal: ' . $e->getMessage()];
}
}
// Jalankan migrasi jika file ini dieksekusi langsung dari CLI atau via include
if (basename(__FILE__) == basename($_SERVER['SCRIPT_FILENAME'])) {
$result = run_migrations();
echo $result['message'] . "\n";
}

View File

@ -0,0 +1,16 @@
-- 001_create_murid_table.sql
CREATE TABLE IF NOT EXISTS `murid` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`nis` VARCHAR(20) NOT NULL UNIQUE,
`nama_lengkap` VARCHAR(100) NOT NULL,
`tempat_lahir` VARCHAR(50) DEFAULT NULL,
`tanggal_lahir` DATE DEFAULT NULL,
`jenis_kelamin` ENUM('Laki-laki', 'Perempuan') DEFAULT NULL,
`alamat` TEXT DEFAULT NULL,
`no_telepon` VARCHAR(20) DEFAULT NULL,
`email` VARCHAR(100) DEFAULT NULL,
`foto` VARCHAR(255) DEFAULT 'default.png', -- Path to photo file
`created_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@ -0,0 +1,5 @@
ALTER TABLE `murid`
ADD COLUMN `nisn` VARCHAR(20) NULL AFTER `nis`,
ADD COLUMN `foto` VARCHAR(255) NULL AFTER `alamat`,
ADD COLUMN `latitude` VARCHAR(50) NULL AFTER `foto`,
ADD COLUMN `longitude` VARCHAR(50) NULL AFTER `latitude`;

View File

@ -0,0 +1,12 @@
CREATE TABLE IF NOT EXISTS guru (
id INT AUTO_INCREMENT PRIMARY KEY,
nip VARCHAR(50) UNIQUE NOT NULL,
nama VARCHAR(100) NOT NULL,
alamat TEXT,
telepon VARCHAR(20),
foto VARCHAR(255),
latitude VARCHAR(50),
longitude VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
);

View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS `kelas` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`nama_kelas` VARCHAR(100) NOT NULL,
`id_wali_kelas` INT,
FOREIGN KEY (`id_wali_kelas`) REFERENCES `guru`(`id`) ON DELETE SET NULL
) ENGINE=InnoDB;

View File

@ -0,0 +1,16 @@
--
-- Create table for schedule (jadwal)
--
CREATE TABLE IF NOT EXISTS `jadwal` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`id_kelas` INT NOT NULL,
`id_guru` INT NOT NULL,
`hari` VARCHAR(10) NOT NULL,
`jam_mulai` TIME NOT NULL,
`jam_selesai` TIME NOT NULL,
`mata_pelajaran` VARCHAR(100) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (`id_kelas`) REFERENCES `kelas`(`id`) ON DELETE CASCADE,
FOREIGN KEY (`id_guru`) REFERENCES `guru`(`id`) ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

View File

@ -0,0 +1,13 @@
CREATE TABLE IF NOT EXISTS absensi (
id INT AUTO_INCREMENT PRIMARY KEY,
jadwal_id INT NOT NULL,
murid_id INT NOT NULL,
tanggal DATE NOT NULL,
status ENUM('Hadir', 'Izin', 'Sakit', 'Alpa') NOT NULL,
keterangan TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
FOREIGN KEY (jadwal_id) REFERENCES jadwal(id) ON DELETE CASCADE,
FOREIGN KEY (murid_id) REFERENCES murid(id) ON DELETE CASCADE,
UNIQUE KEY (jadwal_id, murid_id, tanggal)
);

View File

@ -0,0 +1,3 @@
ALTER TABLE murid
ADD COLUMN kelas_id INT NULL AFTER email,
ADD FOREIGN KEY (kelas_id) REFERENCES kelas(id) ON DELETE SET NULL;

View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS `mata_pelajaran` (
`id` INT AUTO_INCREMENT PRIMARY KEY,
`nama_matapelajaran` VARCHAR(100) NOT NULL,
`created_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
`updated_at` TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
) ENGINE=INNODB;

View File

@ -0,0 +1,6 @@
ALTER TABLE `jadwal`
ADD COLUMN `id_matapelajaran` INT NULL AFTER `id_kelas`,
ADD CONSTRAINT `fk_jadwal_matapelajaran`
FOREIGN KEY (`id_matapelajaran`)
REFERENCES `mata_pelajaran`(`id`)
ON DELETE SET NULL;

61
export_laporan.php Normal file
View File

@ -0,0 +1,61 @@
<?php
ini_set('display_errors', 0); // Disable error display for this script
require_once 'db/config.php';
require_once 'functions.php';
require_once 'libs/SimpleXLSXGen.php';
// Check for required POST data
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['kelas_id'], $_POST['start_date'], $_POST['end_date'])) {
http_response_code(400);
echo "Bad Request: Missing required parameters.";
exit;
}
// Get filter data from POST
$kelas_id = $_POST['kelas_id'];
$start_date = $_POST['start_date'];
$end_date = $_POST['end_date'];
// Fetch the data
$rekap_data = get_rekap_absensi($kelas_id, $start_date, $end_date);
$kelas_info = get_kelas_by_id($kelas_id);
$nama_kelas = $kelas_info ? str_replace(' ', '_', $kelas_info['nama_kelas']) : 'Laporan';
// Prepare data for Excel generation
$data_for_excel = [
[
'<b>NIS</b>',
'<b>Nama Lengkap</b>',
'<b>Hadir</b>',
'<b>Sakit</b>',
'<b>Izin</b>',
'<b>Alpa</b>',
'<b>Total Jam</b>'
]
];
if (empty($rekap_data)) {
$data_for_excel[] = ['Tidak ada data absensi pada periode ini.', '', '', '', '', '', ''];
} else {
foreach ($rekap_data as $row) {
$data_for_excel[] = [
$row['nis'],
$row['nama_lengkap'],
(int)$row['total_hadir'],
(int)$row['total_sakit'],
(int)$row['total_izin'],
(int)$row['total_alpa'],
(int)$row['total_absensi'],
];
}
}
// Generate file name
$filename = "Laporan_Absensi_{$nama_kelas}_{$start_date}_to_{$end_date}.xlsx";
// Generate and download the Excel file
Shuchkin\SimpleXLSXGen::fromArray($data_for_excel)->downloadAs($filename);
exit();

34
export_murid.php Normal file
View File

@ -0,0 +1,34 @@
<?php
// export_murid.php
require_once 'db/config.php';
require_once 'functions.php';
require_once 'libs/SimpleXLSXGen.php';
// Ambil semua data murid
$murid = getAllMurid();
// Siapkan data untuk Excel
$data_for_excel = [];
// Tambahkan header
$data_for_excel[] = ['NIS', 'Nama Lengkap', 'Tanggal Lahir', 'Alamat'];
// Tambahkan data murid
if (!empty($murid)) {
foreach ($murid as $m) {
$data_for_excel[] = [
$m['nis'],
$m['nama_lengkap'],
$m['tanggal_lahir'],
$m['alamat']
];
}
} else {
// Jika tidak ada data, tambahkan baris kosong
$data_for_excel[] = ['Tidak ada data', '', '', ''];
}
// Buat dan unduh file Excel
$xlsx = Shuchkin\SimpleXLSXGen::fromArray($data_for_excel);
$xlsx->downloadAs('data_murid_'.date('Ymd').'.xlsx'); // Unduh dengan nama file dinamis

658
functions.php Normal file
View File

@ -0,0 +1,658 @@
<?php
function is_active($page_name) {
$page = $_GET['page'] ?? 'dashboard';
return $page === $page_name ? 'active' : '';
}
function get_page_title() {
$page = $_GET['page'] ?? 'dashboard';
return ucfirst($page);
}
function get_all_murid() {
$pdo = db();
$stmt = $pdo->query("SELECT m.id, m.nis, m.nisn, m.nama_lengkap, m.jenis_kelamin, m.email, m.foto, k.nama_kelas
FROM murid m
LEFT JOIN kelas k ON m.kelas_id = k.id
ORDER BY m.nama_lengkap ASC");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function get_murid_by_id($id) {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM murid WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
function handle_murid_action() {
$action = $_POST['action'] ?? $_GET['action'] ?? '';
// Handle Delete Action via GET first as it redirects
if ($action === 'delete' && isset($_GET['id'])) {
$id = $_GET['id'];
$murid = get_murid_by_id($id); // Get murid data to delete foto
$pdo = db();
try {
// Delete old photo if exists
if (!empty($murid['foto'])) {
$photo_path = 'assets/uploads/murid/' . $murid['foto'];
if (file_exists($photo_path)) {
unlink($photo_path);
}
}
$stmt = $pdo->prepare("DELETE FROM murid WHERE id = ?");
$stmt->execute([$id]);
header("Location: index.php?page=murid&status=deleted");
exit();
} catch (PDOException $e) {
header("Location: index.php?page=murid&status=error");
exit();
}
}
// Only proceed with POST actions from here
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return null;
}
$pdo = db();
$id = $_POST['id'] ?? null;
// Handle Import
if ($action === 'import') {
if (isset($_FILES['file_murid']) && $_FILES['file_murid']['error'] === UPLOAD_ERR_OK) {
$file_tmp_path = $_FILES['file_murid']['tmp_name'];
return import_murid_from_xlsx($file_tmp_path);
} else {
return ['success' => false, 'message' => 'Gagal mengunggah file. Silakan coba lagi.'];
}
}
// Handle Add/Edit
$nis = $_POST['nis'] ?? '';
$nisn = $_POST['nisn'] ?? '';
$nama_lengkap = $_POST['nama_lengkap'] ?? '';
$tempat_lahir = $_POST['tempat_lahir'] ?? '';
$tanggal_lahir = $_POST['tanggal_lahir'] ?? '';
$jenis_kelamin = $_POST['jenis_kelamin'] ?? '';
$alamat = $_POST['alamat'] ?? '';
$latitude = $_POST['latitude'] ?? '';
$longitude = $_POST['longitude'] ?? '';
$no_telepon = $_POST['no_telepon'] ?? '';
$email = $_POST['email'] ?? '';
$kelas_id = !empty($_POST['kelas_id']) ? $_POST['kelas_id'] : null;
$foto_filename = $_POST['foto_existing'] ?? null;
// Handle file upload
if (isset($_FILES['foto']) && $_FILES['foto']['error'] === UPLOAD_ERR_OK) {
$upload_dir = 'assets/uploads/murid/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$tmp_name = $_FILES['foto']['tmp_name'];
$original_name = basename($_FILES['foto']['name']);
$file_ext = strtolower(pathinfo($original_name, PATHINFO_EXTENSION));
$safe_filename = preg_replace('/[^A-Za-z0-9_.-]/', '_', pathinfo($original_name, PATHINFO_FILENAME));
$foto_filename = uniqid() . '_' . $safe_filename . '.' . $file_ext;
// Delete old photo if a new one is uploaded during edit
if ($action === 'edit' && !empty($_POST['foto_existing'])) {
$old_photo_path = $upload_dir . $_POST['foto_existing'];
if (file_exists($old_photo_path)) {
unlink($old_photo_path);
}
}
if (!move_uploaded_file($tmp_name, $upload_dir . $foto_filename)) {
return ['success' => false, 'message' => 'Gagal memindahkan file foto.'];
}
}
try {
if ($action === 'add') {
$stmt = $pdo->prepare(
"INSERT INTO murid (nis, nisn, nama_lengkap, tempat_lahir, tanggal_lahir, jenis_kelamin, alamat, foto, latitude, longitude, no_telepon, email, kelas_id)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
);
$stmt->execute([$nis, $nisn, $nama_lengkap, $tempat_lahir, $tanggal_lahir, $jenis_kelamin, $alamat, $foto_filename, $latitude, $longitude, $no_telepon, $email, $kelas_id]);
return ['success' => true, 'message' => 'Data murid berhasil ditambahkan.'];
} elseif ($action === 'edit' && $id) {
$stmt = $pdo->prepare(
"UPDATE murid SET nis = ?, nisn = ?, nama_lengkap = ?, tempat_lahir = ?, tanggal_lahir = ?,
jenis_kelamin = ?, alamat = ?, foto = ?, latitude = ?, longitude = ?, no_telepon = ?, email = ?, kelas_id = ? WHERE id = ?"
);
$stmt->execute([$nis, $nisn, $nama_lengkap, $tempat_lahir, $tanggal_lahir, $jenis_kelamin, $alamat, $foto_filename, $latitude, $longitude, $no_telepon, $email, $kelas_id, $id]);
return ['success' => true, 'message' => 'Data murid berhasil diperbarui.'];
}
} catch (PDOException $e) {
if ($e->getCode() == 23000) { // Integrity constraint violation
return ['success' => false, 'message' => 'Gagal menyimpan data. NIS atau NISN sudah terdaftar.'];
}
return ['success' => false, 'message' => 'Terjadi kesalahan database: ' . $e->getMessage()];
}
return null;
}
function import_murid_from_xlsx($filepath) {
// Include the parser library
require_once 'libs/SimpleXLSX.php';
// Check if the file exists and is readable
if (!file_exists($filepath) || !is_readable($filepath)) {
return ['success' => false, 'message' => 'File tidak ditemukan atau tidak bisa dibaca.'];
}
// Try to parse the XLSX file
if ($xlsx = Shuchkin\SimpleXLSX::parse($filepath)) {
$pdo = db();
$success_count = 0;
$fail_count = 0;
$errors = [];
// Get rows as array
$rows = $xlsx->rows();
// Skip header row (the first row)
$is_header = true;
foreach ($rows as $row) {
if ($is_header) {
$is_header = false;
continue;
}
// Assign columns to variables - assuming order: NIS, NISN, Nama, Tgl Lahir, Alamat
$nis = $row[0] ?? '';
$nisn = $row[1] ?? '';
$nama_lengkap = $row[2] ?? '';
$tanggal_lahir = $row[3] ?? '';
$alamat = $row[4] ?? '';
// Basic validation: skip if NIS or name is empty
if (empty($nis) || empty($nama_lengkap)) {
$fail_count++;
$errors[] = "Baris data dengan NIS '.htmlspecialchars($nis).' dan Nama '.htmlspecialchars($nama_lengkap).' dilewati karena data tidak lengkap.";
continue;
}
try {
// Using the existing add function logic
$stmt = $pdo->prepare(
"INSERT INTO murid (nis, nisn, nama_lengkap, tanggal_lahir, alamat)
VALUES (?, ?, ?, ?, ?)"
);
$stmt->execute([$nis, $nisn, $nama_lengkap, $tanggal_lahir, $alamat]);
$success_count++;
} catch (PDOException $e) {
$fail_count++;
if ($e->getCode() == 23000) {
$errors[] = "NIS atau NISN '.htmlspecialchars($nis).' sudah ada di database.";
} else {
$errors[] = "Gagal memasukkan data untuk NIS '.htmlspecialchars($nis).': " . $e->getMessage();
}
}
}
$message = "Impor selesai. Berhasil: {$success_count}, Gagal: {$fail_count}.";
if (!empty($errors)) {
$message .= "<br>Detail kegagalan:<br>" . implode("<br>", $errors);
}
return ['success' => ($fail_count === 0), 'message' => $message];
} else {
return ['success' => false, 'message' => 'Gagal memproses file XLSX: ' . Shuchkin\SimpleXLSX::parseError()];
}
}
function get_all_guru() {
$pdo = db();
$stmt = $pdo->query("SELECT id, nip, nama, foto FROM guru ORDER BY nama ASC");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function get_guru_by_id($id) {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM guru WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
function handle_guru_action() {
$action = $_POST['action'] ?? $_GET['action'] ?? '';
if ($action === 'delete' && isset($_GET['id'])) {
$id = $_GET['id'];
$guru = get_guru_by_id($id);
$pdo = db();
try {
if (!empty($guru['foto'])) {
$photo_path = 'assets/uploads/guru/' . $guru['foto'];
if (file_exists($photo_path)) {
unlink($photo_path);
}
}
$stmt = $pdo->prepare("DELETE FROM guru WHERE id = ?");
$stmt->execute([$id]);
header("Location: index.php?page=teachers&status=deleted");
exit();
} catch (PDOException $e) {
header("Location: index.php?page=teachers&status=error");
exit();
}
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return null;
}
$pdo = db();
$id = $_POST['id'] ?? null;
$nip = $_POST['nip'] ?? '';
$nama = $_POST['nama'] ?? '';
$alamat = $_POST['alamat'] ?? '';
$telepon = $_POST['telepon'] ?? '';
$latitude = $_POST['latitude'] ?? '';
$longitude = $_POST['longitude'] ?? '';
$foto_filename = $_POST['foto_existing'] ?? null;
if (isset($_FILES['foto']) && $_FILES['foto']['error'] === UPLOAD_ERR_OK) {
$upload_dir = 'assets/uploads/guru/';
if (!is_dir($upload_dir)) {
mkdir($upload_dir, 0777, true);
}
$tmp_name = $_FILES['foto']['tmp_name'];
$original_name = basename($_FILES['foto']['name']);
$file_ext = strtolower(pathinfo($original_name, PATHINFO_EXTENSION));
$safe_filename = preg_replace('/[^A-Za-z0-9_.-]/', '_', pathinfo($original_name, PATHINFO_FILENAME));
$foto_filename = uniqid() . '_' . $safe_filename . '.' . $file_ext;
if ($action === 'edit' && !empty($_POST['foto_existing'])) {
$old_photo_path = $upload_dir . $_POST['foto_existing'];
if (file_exists($old_photo_path)) {
unlink($old_photo_path);
}
}
if (!move_uploaded_file($tmp_name, $upload_dir . $foto_filename)) {
return ['success' => false, 'message' => 'Gagal memindahkan file foto.'];
}
}
try {
if ($action === 'add') {
$stmt = $pdo->prepare(
"INSERT INTO guru (nip, nama, alamat, telepon, foto, latitude, longitude)
VALUES (?, ?, ?, ?, ?, ?, ?)"
);
$stmt->execute([$nip, $nama, $alamat, $telepon, $foto_filename, $latitude, $longitude]);
return ['success' => true, 'message' => 'Data guru berhasil ditambahkan.'];
} elseif ($action === 'edit' && $id) {
$stmt = $pdo->prepare(
"UPDATE guru SET nip = ?, nama = ?, alamat = ?, telepon = ?, foto = ?, latitude = ?, longitude = ? WHERE id = ?"
);
$stmt->execute([$nip, $nama, $alamat, $telepon, $foto_filename, $latitude, $longitude, $id]);
return ['success' => true, 'message' => 'Data guru berhasil diperbarui.'];
}
} catch (PDOException $e) {
if ($e->getCode() == 23000) { // Integrity constraint violation
return ['success' => false, 'message' => 'Gagal menyimpan data. NIP sudah terdaftar.'];
}
return ['success' => false, 'message' => 'Terjadi kesalahan database: ' . $e->getMessage()];
}
return null;
}
function get_all_kelas() {
$pdo = db();
$stmt = $pdo->query("
SELECT k.id, k.nama_kelas, g.nama as nama_wali_kelas
FROM kelas k
LEFT JOIN guru g ON k.id_wali_kelas = g.id
ORDER BY k.nama_kelas ASC
");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function get_kelas_by_id($id) {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM kelas WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
function handle_kelas_action() {
$action = $_POST['action'] ?? $_GET['action'] ?? '';
if ($action === 'delete' && isset($_GET['id'])) {
$id = $_GET['id'];
$pdo = db();
try {
$stmt = $pdo->prepare("DELETE FROM kelas WHERE id = ?");
$stmt->execute([$id]);
header("Location: index.php?page=classes&status=deleted");
exit();
} catch (PDOException $e) {
// Foreign key constraint might fail, though ON DELETE SET NULL should prevent it.
// Good to have a generic error handler.
header("Location: index.php?page=classes&status=error");
exit();
}
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return null;
}
$pdo = db();
$id = $_POST['id'] ?? null;
$nama_kelas = $_POST['nama_kelas'] ?? '';
// Use 'none' or null for the wali kelas if not selected
$id_wali_kelas = !empty($_POST['id_wali_kelas']) ? $_POST['id_wali_kelas'] : null;
try {
if ($action === 'add') {
$stmt = $pdo->prepare(
"INSERT INTO kelas (nama_kelas, id_wali_kelas) VALUES (?, ?)"
);
$stmt->execute([$nama_kelas, $id_wali_kelas]);
return ['success' => true, 'message' => 'Data kelas berhasil ditambahkan.'];
} elseif ($action === 'edit' && $id) {
$stmt = $pdo->prepare(
"UPDATE kelas SET nama_kelas = ?, id_wali_kelas = ? WHERE id = ?"
);
$stmt->execute([$nama_kelas, $id_wali_kelas, $id]);
return ['success' => true, 'message' => 'Data kelas berhasil diperbarui.'];
}
} catch (PDOException $e) {
if ($e->getCode() == 23000) {
return ['success' => false, 'message' => 'Gagal menyimpan data. Nama kelas mungkin sudah ada.'];
}
return ['success' => false, 'message' => 'Terjadi kesalahan database: ' . $e->getMessage()];
}
return null;
}
function get_all_jadwal() {
$pdo = db();
$stmt = $pdo->query("
SELECT
j.id,
j.hari,
j.jam_mulai,
j.jam_selesai,
mp.nama_matapelajaran,
k.nama_kelas,
g.nama as nama_guru
FROM jadwal j
JOIN kelas k ON j.id_kelas = k.id
JOIN guru g ON j.id_guru = g.id
LEFT JOIN mata_pelajaran mp ON j.id_matapelajaran = mp.id
ORDER BY k.nama_kelas, FIELD(j.hari, 'Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Minggu'), j.jam_mulai
");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function get_jadwal_by_id($id) {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM jadwal WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
function handle_jadwal_action() {
$action = $_POST['action'] ?? $_GET['action'] ?? '';
if ($action === 'delete' && isset($_GET['id'])) {
$id = $_GET['id'];
$pdo = db();
try {
$stmt = $pdo->prepare("DELETE FROM jadwal WHERE id = ?");
$stmt->execute([$id]);
header("Location: index.php?page=schedule&status=deleted");
exit();
} catch (PDOException $e) {
header("Location: index.php?page=schedule&status=error");
exit();
}
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return null;
}
$pdo = db();
$id = $_POST['id'] ?? null;
$id_kelas = $_POST['id_kelas'] ?? '';
$id_guru = $_POST['id_guru'] ?? '';
$id_matapelajaran = $_POST['id_matapelajaran'] ?? ''; // New field
$hari = $_POST['hari'] ?? '';
$jam_mulai = $_POST['jam_mulai'] ?? '';
$jam_selesai = $_POST['jam_selesai'] ?? '';
// Basic validation
if (empty($id_kelas) || empty($id_guru) || empty($id_matapelajaran) || empty($hari) || empty($jam_mulai) || empty($jam_selesai)) {
return ['success' => false, 'message' => 'Semua kolom wajib diisi.'];
}
try {
if ($action === 'add') {
$stmt = $pdo->prepare(
"INSERT INTO jadwal (id_kelas, id_guru, id_matapelajaran, hari, jam_mulai, jam_selesai)
VALUES (?, ?, ?, ?, ?, ?)"
);
$stmt->execute([$id_kelas, $id_guru, $id_matapelajaran, $hari, $jam_mulai, $jam_selesai]);
return ['success' => true, 'message' => 'Data jadwal berhasil ditambahkan.'];
} elseif ($action === 'edit' && $id) {
$stmt = $pdo->prepare(
"UPDATE jadwal SET id_kelas = ?, id_guru = ?, id_matapelajaran = ?, hari = ?, jam_mulai = ?, jam_selesai = ?
WHERE id = ?"
);
$stmt->execute([$id_kelas, $id_guru, $id_matapelajaran, $hari, $jam_mulai, $jam_selesai, $id]);
return ['success' => true, 'message' => 'Data jadwal berhasil diperbarui.'];
}
} catch (PDOException $e) {
return ['success' => false, 'message' => 'Terjadi kesalahan database: ' . $e->getMessage()];
}
return null;
}
// Attendance Functions
function get_murid_by_kelas($kelas_id) {
$pdo = db();
$stmt = $pdo->prepare("SELECT id, nama_lengkap FROM murid WHERE kelas_id = ? ORDER BY nama_lengkap ASC");
$stmt->execute([$kelas_id]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function get_jadwal_by_kelas_and_hari($kelas_id, $hari) {
$pdo = db();
$stmt = $pdo->prepare("
SELECT j.id, mp.nama_matapelajaran, j.jam_mulai, j.jam_selesai
FROM jadwal j
LEFT JOIN mata_pelajaran mp ON j.id_matapelajaran = mp.id
WHERE j.id_kelas = ? AND j.hari = ? ORDER BY j.jam_mulai ASC");
$stmt->execute([$kelas_id, $hari]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function get_absensi($id_kelas, $tanggal) {
$pdo = db();
$stmt = $pdo->prepare("
SELECT murid_id, jadwal_id, status
FROM absensi
WHERE tanggal = ? AND jadwal_id IN (SELECT id FROM jadwal WHERE id_kelas = ?)
");
$stmt->execute([$tanggal, $id_kelas]);
$result = $stmt->fetchAll(PDO::FETCH_ASSOC);
// Format the result for easier lookup in the template
$absensi_data = [];
foreach ($result as $row) {
$absensi_data[$row['murid_id']][$row['jadwal_id']] = $row['status'];
}
return $absensi_data;
}
function handle_absensi_action() {
if ($_SERVER['REQUEST_METHOD'] !== 'POST' || !isset($_POST['action']) || $_POST['action'] !== 'save_absensi') {
return null;
}
$id_kelas = $_POST['id_kelas'] ?? '';
$tanggal = $_POST['tanggal'] ?? '';
$absensi = $_POST['absensi'] ?? [];
if (empty($id_kelas) || empty($tanggal) || empty($absensi)) {
return ['success' => false, 'message' => 'Data tidak lengkap. Harap pilih kelas, tanggal, dan isi absensi.'];
}
$pdo = db();
try {
$pdo->beginTransaction();
// Prepare statement for inserting/updating attendance
$stmt = $pdo->prepare("
INSERT INTO absensi (jadwal_id, murid_id, tanggal, status)
VALUES (:jadwal_id, :murid_id, :tanggal, :status)
ON DUPLICATE KEY UPDATE status = :status
");
foreach ($absensi as $murid_id => $jadwal_absensi) {
foreach ($jadwal_absensi as $jadwal_id => $status) {
if (!empty($status)) {
$stmt->execute([
':jadwal_id' => $jadwal_id,
':murid_id' => $murid_id,
':tanggal' => $tanggal,
':status' => $status
]);
}
}
}
$pdo->commit();
return ['success' => true, 'message' => 'Absensi berhasil disimpan.'];
} catch (PDOException $e) {
$pdo->rollBack();
return ['success' => false, 'message' => 'Gagal menyimpan absensi: ' . $e->getMessage()];
}
}
function get_rekap_absensi($id_kelas, $start_date, $end_date) {
$pdo = db();
// Validate input dates
if (empty($id_kelas) || empty($start_date) || empty($end_date)) {
return [];
}
$sql = "
SELECT
m.id as murid_id,
m.nis,
m.nama_lengkap,
COUNT(a.id) as total_absensi,
SUM(CASE WHEN a.status = 'Hadir' THEN 1 ELSE 0 END) as total_hadir,
SUM(CASE WHEN a.status = 'Sakit' THEN 1 ELSE 0 END) as total_sakit,
SUM(CASE WHEN a.status = 'Izin' THEN 1 ELSE 0 END) as total_izin,
SUM(CASE WHEN a.status = 'Alpa' THEN 1 ELSE 0 END) as total_alpa
FROM murid m
LEFT JOIN absensi a ON m.id = a.murid_id
WHERE m.kelas_id = :id_kelas
AND a.tanggal BETWEEN :start_date AND :end_date
GROUP BY m.id, m.nis, m.nama_lengkap
ORDER BY m.nama_lengkap ASC;
";
try {
$stmt = $pdo->prepare($sql);
$stmt->execute([
':id_kelas' => $id_kelas,
':start_date' => $start_date,
':end_date' => $end_date
]);
return $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
// Log error or handle it as needed
error_log("Rekap Absensi Error: " . $e->getMessage());
return [];
}
}
// Subject (Mata Pelajaran) Functions
function get_all_matapelajaran() {
$pdo = db();
$stmt = $pdo->query("SELECT * FROM mata_pelajaran ORDER BY nama_matapelajaran ASC");
return $stmt->fetchAll(PDO::FETCH_ASSOC);
}
function get_matapelajaran_by_id($id) {
$pdo = db();
$stmt = $pdo->prepare("SELECT * FROM mata_pelajaran WHERE id = ?");
$stmt->execute([$id]);
return $stmt->fetch(PDO::FETCH_ASSOC);
}
function handle_matapelajaran_action() {
$action = $_POST['action'] ?? $_GET['action'] ?? '';
if ($action === 'delete' && isset($_GET['id'])) {
$id = $_GET['id'];
$pdo = db();
try {
$stmt = $pdo->prepare("DELETE FROM mata_pelajaran WHERE id = ?");
$stmt->execute([$id]);
header("Location: index.php?page=subjects&status=deleted");
exit();
} catch (PDOException $e) {
header("Location: index.php?page=subjects&status=error&err_msg=" . urlencode($e->getMessage()));
exit();
}
}
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
return null;
}
$pdo = db();
$id = $_POST['id'] ?? null;
$nama_matapelajaran = $_POST['nama_matapelajaran'] ?? '';
try {
if ($action === 'add') {
$stmt = $pdo->prepare("INSERT INTO mata_pelajaran (nama_matapelajaran) VALUES (?)");
$stmt->execute([$nama_matapelajaran]);
return ['success' => true, 'message' => 'Data mata pelajaran berhasil ditambahkan.'];
} elseif ($action === 'edit' && $id) {
$stmt = $pdo->prepare("UPDATE mata_pelajaran SET nama_matapelajaran = ? WHERE id = ?");
$stmt->execute([$nama_matapelajaran, $id]);
return ['success' => true, 'message' => 'Data mata pelajaran berhasil diperbarui.'];
}
} catch (PDOException $e) {
if ($e->getCode() == 23000) {
return ['success' => false, 'message' => 'Gagal menyimpan data. Nama mata pelajaran mungkin sudah ada.'];
}
return ['success' => false, 'message' => 'Terjadi kesalahan database: ' . $e->getMessage()];
}
return null;
}
?>

178
index.php
View File

@ -1,150 +1,34 @@
<?php
declare(strict_types=1);
@ini_set('display_errors', '1');
@error_reporting(E_ALL);
@date_default_timezone_set('UTC');
require_once 'db/config.php';
require_once 'functions.php';
require_once 'templates/header.php';
require_once 'templates/sidebar.php';
$phpVersion = PHP_VERSION;
$now = date('Y-m-d H:i:s');
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>New Style</title>
<?php
// Read project preview data from environment
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
?>
<?php if ($projectDescription): ?>
<!-- Meta description -->
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
<!-- Open Graph meta tags -->
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<!-- Twitter meta tags -->
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
<?php endif; ?>
<?php if ($projectImageUrl): ?>
<!-- Open Graph image -->
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<!-- Twitter image -->
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
<?php endif; ?>
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
<style>
:root {
--bg-color-start: #6a11cb;
--bg-color-end: #2575fc;
--text-color: #ffffff;
--card-bg-color: rgba(255, 255, 255, 0.01);
--card-border-color: rgba(255, 255, 255, 0.1);
$page = $_GET['page'] ?? 'dashboard';
switch ($page) {
case 'murid':
include 'templates/murid.php';
break;
case 'teachers':
include 'templates/teachers.php';
break;
case 'classes':
include 'templates/classes.php';
break;
case 'attendance':
include 'templates/attendance.php';
break;
case 'schedule':
include 'templates/schedule.php';
break;
case 'reports':
include 'templates/reports.php';
break;
case 'dashboard':
default:
include 'templates/dashboard.php';
break;
}
body {
margin: 0;
font-family: 'Inter', sans-serif;
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
color: var(--text-color);
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
text-align: center;
overflow: hidden;
position: relative;
}
body::before {
content: '';
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
animation: bg-pan 20s linear infinite;
z-index: -1;
}
@keyframes bg-pan {
0% { background-position: 0% 0%; }
100% { background-position: 100% 100%; }
}
main {
padding: 2rem;
}
.card {
background: var(--card-bg-color);
border: 1px solid var(--card-border-color);
border-radius: 16px;
padding: 2rem;
backdrop-filter: blur(20px);
-webkit-backdrop-filter: blur(20px);
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
}
.loader {
margin: 1.25rem auto 1.25rem;
width: 48px;
height: 48px;
border: 3px solid rgba(255, 255, 255, 0.25);
border-top-color: #fff;
border-radius: 50%;
animation: spin 1s linear infinite;
}
@keyframes spin {
from { transform: rotate(0deg); }
to { transform: rotate(360deg); }
}
.hint {
opacity: 0.9;
}
.sr-only {
position: absolute;
width: 1px; height: 1px;
padding: 0; margin: -1px;
overflow: hidden;
clip: rect(0, 0, 0, 0);
white-space: nowrap; border: 0;
}
h1 {
font-size: 3rem;
font-weight: 700;
margin: 0 0 1rem;
letter-spacing: -1px;
}
p {
margin: 0.5rem 0;
font-size: 1.1rem;
}
code {
background: rgba(0,0,0,0.2);
padding: 2px 6px;
border-radius: 4px;
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
}
footer {
position: absolute;
bottom: 1rem;
font-size: 0.8rem;
opacity: 0.7;
}
</style>
</head>
<body>
<main>
<div class="card">
<h1>Analyzing your requirements and generating your website…</h1>
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
<span class="sr-only">Loading…</span>
</div>
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
<p class="hint">This page will update automatically as the plan is implemented.</p>
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
</div>
</main>
<footer>
Page updated: <?= htmlspecialchars($now) ?> (UTC)
</footer>
</body>
</html>
require_once 'templates/footer.php';

1231
libs/SimpleXLSX.php Normal file

File diff suppressed because it is too large Load Diff

1340
libs/SimpleXLSXGen.php Normal file

File diff suppressed because it is too large Load Diff

148
templates/attendance.php Normal file
View File

@ -0,0 +1,148 @@
<?php
// templates/attendance.php
// Handle attendance form submission
$feedback = handle_absensi_action();
// Get all classes for the selection dropdown
$all_kelas = get_all_kelas();
// Get filter values from GET request
$selected_kelas_id = $_GET['kelas_id'] ?? null;
$selected_tanggal = $_GET['tanggal'] ?? date('Y-m-d'); // Default to today
$murid_list = [];
$jadwal_hari_ini = [];
$absensi_data = [];
// Indonesian day name mapping
$day_map = [
'Sunday' => 'Minggu',
'Monday' => 'Senin',
'Tuesday' => 'Selasa',
'Wednesday' => 'Rabu',
'Thursday' => 'Kamis',
'Friday' => 'Jumat',
'Saturday' => 'Sabtu'
];
$day_of_week = date('l', strtotime($selected_tanggal));
$hari_indonesia = $day_map[$day_of_week];
if ($selected_kelas_id) {
$murid_list = get_murid_by_kelas($selected_kelas_id);
$jadwal_hari_ini = get_jadwal_by_kelas_and_hari($selected_kelas_id, $hari_indonesia);
$absensi_data = get_absensi($selected_kelas_id, $selected_tanggal);
}
$statuses = ['Hadir', 'Izin', 'Sakit', 'Alpa'];
?>
<main class="main-content">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Manajemen Absensi</h1>
</div>
<?php if (isset($feedback['message'])): ?>
<div class="alert alert-<?php echo $feedback['success'] ? 'success' : 'danger'; ?>">
<?php echo htmlspecialchars($feedback['message']); ?>
</div>
<?php endif; ?>
<!-- Filter Form -->
<div class="card mb-4">
<div class="card-header">
<h5 class="card-title">Pilih Kelas dan Tanggal</h5>
</div>
<div class="card-body">
<form action="index.php" method="GET">
<input type="hidden" name="page" value="attendance">
<div class="row">
<div class="col-md-5 mb-3">
<label for="kelas_id" class="form-label">Kelas</label>
<select class="form-select" id="kelas_id" name="kelas_id" required>
<option value="">-- Pilih Kelas --</option>
<?php foreach ($all_kelas as $kelas): ?>
<option value="<?php echo $kelas['id']; ?>" <?php echo ($selected_kelas_id == $kelas['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($kelas['nama_kelas']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="col-md-5 mb-3">
<label for="tanggal" class="form-label">Tanggal</label>
<input type="date" class="form-control" id="tanggal" name="tanggal" value="<?php echo htmlspecialchars($selected_tanggal); ?>" required>
</div>
<div class="col-md-2 d-flex align-items-end mb-3">
<button type="submit" class="btn btn-primary w-100">Tampilkan</button>
</div>
</div>
</form>
</div>
</div>
<?php if ($selected_kelas_id): ?>
<?php if (empty($murid_list) || empty($jadwal_hari_ini)): ?>
<div class="alert alert-warning">
<?php if (empty($murid_list)): ?>
Tidak ada murid di kelas ini.
<?php else: ?>
Tidak ada jadwal pelajaran untuk hari <strong><?php echo htmlspecialchars($hari_indonesia); ?></strong> di kelas ini.
<?php endif; ?>
</div>
<?php else: ?>
<!-- Attendance Table -->
<div class="card">
<div class="card-header">
<h5 class="card-title">Formulir Absensi - <?php echo htmlspecialchars($hari_indonesia . ', ' . date('d M Y', strtotime($selected_tanggal))); ?></h5>
</div>
<div class="card-body">
<form action="index.php?page=attendance&kelas_id=<?php echo $selected_kelas_id; ?>&tanggal=<?php echo $selected_tanggal; ?>" method="POST">
<input type="hidden" name="action" value="save_absensi">
<input type="hidden" name="id_kelas" value="<?php echo $selected_kelas_id; ?>">
<input type="hidden" name="tanggal" value="<?php echo $selected_tanggal; ?>">
<div class="table-responsive">
<table class="table table-bordered table-hover">
<thead class="table-light">
<tr>
<th scope="col" style="width: 25%;">Nama Murid</th>
<?php foreach ($jadwal_hari_ini as $jadwal): ?>
<th scope="col" class="text-center">
<?php echo htmlspecialchars($jadwal['mata_pelajaran']); ?><br>
<small class="text-muted"><?php echo htmlspecialchars(date('H:i', strtotime($jadwal['jam_mulai']))) . ' - ' . htmlspecialchars(date('H:i', strtotime($jadwal['jam_selesai']))); ?></small>
</th>
<?php endforeach; ?>
</tr>
</thead>
<tbody>
<?php foreach ($murid_list as $murid): ?>
<tr>
<td><?php echo htmlspecialchars($murid['nama_lengkap']); ?></td>
<?php foreach ($jadwal_hari_ini as $jadwal): ?>
<td class="text-center">
<select class="form-select form-select-sm" name="absensi[<?php echo $murid['id']; ?>][<?php echo $jadwal['id']; ?>]">
<option value="">-</option>
<?php
$current_status = $absensi_data[$murid['id']][$jadwal['id']] ?? null;
foreach ($statuses as $status):
?>
<option value="<?php echo $status; ?>" <?php echo ($current_status === $status) ? 'selected' : ''; ?>>
<?php echo $status; ?>
</option>
<?php endforeach; ?>
</select>
</td>
<?php endforeach; ?>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
<button type="submit" class="btn btn-success mt-3">Simpan Absensi</button>
</form>
</div>
</div>
<?php endif; ?>
<?php endif; ?>
</main>

108
templates/classes.php Normal file
View File

@ -0,0 +1,108 @@
<?php
// Handle form submissions
$page_action_result = handle_kelas_action();
// Fetch data for display
$kelas_list = get_all_kelas();
$guru_list = get_all_guru(); // Needed for the form dropdown
// Get data for editing, if applicable
$edit_kelas = null;
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
$edit_kelas = get_kelas_by_id($_GET['id']);
}
$form_action = $edit_kelas ? 'edit' : 'add';
$form_button_text = $edit_kelas ? 'Update Kelas' : 'Tambah Kelas';
?>
<div class="container-fluid">
<!-- Page Heading -->
<h1 class="h3 mb-4 text-gray-800">Manajemen Kelas</h1>
<?php if (isset($page_action_result) && !$page_action_result['success']): ?>
<div class="alert alert-danger" role="alert">
<?= htmlspecialchars($page_action_result['message']) ?>
</div>
<?php elseif (isset($page_action_result) && $page_action_result['success']): ?>
<div class="alert alert-success" role="alert">
<?= htmlspecialchars($page_action_result['message']) ?>
</div>
<?php endif; ?>
<div class="row">
<div class="col-lg-4">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary"><?= $edit_kelas ? 'Edit' : 'Tambah' ?> Kelas</h6>
</div>
<div class="card-body">
<form action="index.php?page=classes" method="post">
<input type="hidden" name="action" value="<?= $form_action ?>">
<?php if ($edit_kelas): ?>
<input type="hidden" name="id" value="<?= $edit_kelas['id'] ?>">
<?php endif; ?>
<div class="form-group">
<label for="nama_kelas">Nama Kelas</label>
<input type="text" class="form-control" id="nama_kelas" name="nama_kelas"
value="<?= htmlspecialchars($edit_kelas['nama_kelas'] ?? '') ?>" required>
</div>
<div class="form-group">
<label for="id_wali_kelas">Wali Kelas</label>
<select class="form-control" id="id_wali_kelas" name="id_wali_kelas">
<option value="">-- Pilih Wali Kelas --</option>
<?php foreach ($guru_list as $guru): ?>
<option value="<?= $guru['id'] ?>" <?= (isset($edit_kelas['id_wali_kelas']) && $edit_kelas['id_wali_kelas'] == $guru['id']) ? 'selected' : '' ?>>
<?= htmlspecialchars($guru['nama']) ?>
</option>
<?php endforeach; ?>
</select>
</div>
<button type="submit" class="btn btn-primary"><?= $form_button_text ?></button>
<?php if ($edit_kelas): ?>
<a href="index.php?page=classes" class="btn btn-secondary">Batal</a>
<?php endif; ?>
</form>
</div>
</div>
</div>
<div class="col-lg-8">
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Daftar Kelas</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Nama Kelas</th>
<th>Wali Kelas</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach ($kelas_list as $kelas): ?>
<tr>
<td><?= htmlspecialchars($kelas['nama_kelas']) ?></td>
<td><?= htmlspecialchars($kelas['nama_wali_kelas'] ?? '-') ?></td>
<td>
<a href="index.php?page=classes&action=edit&id=<?= $kelas['id'] ?>" class="btn btn-warning btn-sm">Edit</a>
<a href="index.php?page=classes&action=delete&id=<?= $kelas['id'] ?>" class="btn btn-danger btn-sm"
onclick="return confirm('Apakah Anda yakin ingin menghapus kelas ini?')">Hapus</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>
</div>

27
templates/dashboard.php Normal file
View File

@ -0,0 +1,27 @@
<main class="main-content">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Dashboard</h1>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">Manajemen Siswa</h5>
<p class="card-text">Kelola data siswa, tambah siswa baru, dan lihat daftar siswa.</p>
<a href="index.php?page=students" class="btn btn-primary">Go to Siswa</a>
</div>
</div>
</div>
<div class="col-md-6 mb-3">
<div class="card">
<div class="card-body">
<h5 class="card-title">Manajemen Kelas</h5>
<p class="card-text">Buat kelas baru, atur siswa ke dalam kelas, dan kelola informasi kelas.</p>
<a href="index.php?page=classes" class="btn btn-primary">Go to Kelas</a>
</div>
</div>
</div>
</div>
</main>

59
templates/footer.php Normal file
View File

@ -0,0 +1,59 @@
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/js/bootstrap.bundle.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<!-- LeafletJS for Maps -->
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
<script src="assets/js/main.js"></script>
<script>
// Initialize map only if the map container exists
document.addEventListener('DOMContentLoaded', function() {
if (document.getElementById('map')) {
const latInput = document.getElementById('latitude');
const lonInput = document.getElementById('longitude');
// Default coordinates (e.g., center of Indonesia)
let lat = -2.5489;
let lon = 118.0149;
let zoom = 5;
// If existing coordinates are provided, use them
if (latInput.value && lonInput.value) {
lat = parseFloat(latInput.value);
lon = parseFloat(lonInput.value);
zoom = 15; // Zoom in if location is known
}
const map = L.map('map').setView([lat, lon], zoom);
L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);
let marker = L.marker([lat, lon]).addTo(map);
// Update inputs on map click
map.on('click', function(e) {
const newLat = e.latlng.lat;
const newLon = e.latlng.lng;
latInput.value = newLat.toFixed(6);
lonInput.value = newLon.toFixed(6);
// Move marker to the new location
if (marker) {
marker.setLatLng(e.latlng);
} else {
marker = L.marker(e.latlng).addTo(map);
}
});
}
});
</script>
</body>
</html>

16
templates/header.php Normal file
View File

@ -0,0 +1,16 @@
<?php require_once 'functions.php'; ?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Sistem Informasi Akademik</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0-alpha1/dist/css/bootstrap.min.css" rel="stylesheet">
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
<link href="assets/css/style.css" rel="stylesheet">
</head>
<body>
<div class="d-flex">

243
templates/murid.php Normal file
View File

@ -0,0 +1,243 @@
<?php
// templates/murid.php
// Handle form submissions and actions
$feedback = handle_murid_action();
// Get the current action from URL, default to 'list'
$action = $_GET['action'] ?? 'list';
$id = $_GET['id'] ?? null;
// Get data for a single student if editing
$murid = null;
if ($action === 'edit' && $id) {
$murid = get_murid_by_id($id);
if (!$murid) {
// If student not found, redirect to list with an error
header("Location: index.php?page=murid&status=not_found");
exit();
}
}
// Get all classes for the dropdown
$all_kelas = get_all_kelas();
?>
<main class="main-content">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Manajemen Murid</h1>
<?php if ($action === 'list'): ?>
<div class="btn-toolbar mb-2 mb-md-0">
<a href="export_murid.php" class="btn btn-outline-success me-2">Ekspor ke XLSX</a>
<a href="index.php?page=murid&action=add" class="btn btn-primary">Tambah Murid</a>
</div>
<?php else: ?>
<a href="index.php?page=murid" class="btn btn-outline-secondary">Kembali ke Daftar</a>
<?php endif; ?>
</div>
<?php if (isset($feedback['message'])): ?>
<div class="alert alert-<?php echo $feedback['success'] ? 'success' : 'danger'; ?>">
<?php echo $feedback['message']; // Allow HTML for error details ?>
</div>
<?php endif; ?>
<?php if (isset($_GET['status']) && $_GET['status'] == 'deleted'): ?>
<div class="alert alert-success">Data murid berhasil dihapus.</div>
<?php endif; ?>
<?php if (isset($_GET['status']) && $_GET['status'] == 'error'): ?>
<div class="alert alert-danger">Terjadi kesalahan saat menghapus data.</div>
<?php endif; ?>
<?php if (isset($_GET['status']) && $_GET['status'] == 'not_found'): ?>
<div class="alert alert-warning">Data murid tidak ditemukan.</div>
<?php endif; ?>
<?php if ($action === 'add' || $action === 'edit'): ?>
<!-- Form for Adding and Editing Students -->
<div class="card">
<div class="card-header">
<h5 class="card-title"><?php echo $action === 'add' ? 'Tambah Murid Baru' : 'Ubah Data Murid'; ?></h5>
</div>
<div class="card-body">
<form action="index.php?page=murid" method="POST" enctype="multipart/form-data">
<input type="hidden" name="action" value="<?php echo $action; ?>">
<?php if ($id): ?>
<input type="hidden" name="id" value="<?php echo $id; ?>">
<?php endif; ?>
<div class="row">
<div class="col-md-6 mb-3">
<label for="nis" class="form-label">NIS (Nomor Induk Siswa)</label>
<input type="text" class="form-control" id="nis" name="nis" value="<?php echo htmlspecialchars($murid['nis'] ?? ''); ?>" required>
</div>
<div class="col-md-6 mb-3">
<label for="nisn" class="form-label">NISN</label>
<input type="text" class="form-control" id="nisn" name="nisn" value="<?php echo htmlspecialchars($murid['nisn'] ?? ''); ?>">
</div>
</div>
<div class="mb-3">
<label for="nama_lengkap" class="form-label">Nama Lengkap</label>
<input type="text" class="form-control" id="nama_lengkap" name="nama_lengkap" value="<?php echo htmlspecialchars($murid['nama_lengkap'] ?? ''); ?>" required>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="kelas_id" class="form-label">Kelas</label>
<select class="form-select" id="kelas_id" name="kelas_id">
<option value="">-- Pilih Kelas --</option>
<?php foreach ($all_kelas as $kelas): ?>
<option value="<?php echo $kelas['id']; ?>" <?php echo (isset($murid['kelas_id']) && $murid['kelas_id'] == $kelas['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($kelas['nama_kelas']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="tempat_lahir" class="form-label">Tempat Lahir</label>
<input type="text" class="form-control" id="tempat_lahir" name="tempat_lahir" value="<?php echo htmlspecialchars($murid['tempat_lahir'] ?? ''); ?>">
</div>
<div class="col-md-6 mb-3">
<label for="tanggal_lahir" class="form-label">Tanggal Lahir</label>
<input type="date" class="form-control" id="tanggal_lahir" name="tanggal_lahir" value="<?php echo htmlspecialchars($murid['tanggal_lahir'] ?? ''); ?>">
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="jenis_kelamin" class="form-label">Jenis Kelamin</label>
<select class="form-select" id="jenis_kelamin" name="jenis_kelamin">
<option value="Laki-laki" <?php echo (isset($murid['jenis_kelamin']) && $murid['jenis_kelamin'] === 'Laki-laki') ? 'selected' : ''; ?>>Laki-laki</option>
<option value="Perempuan" <?php echo (isset($murid['jenis_kelamin']) && $murid['jenis_kelamin'] === 'Perempuan') ? 'selected' : ''; ?>>Perempuan</option>
</select>
</div>
<div class="col-md-6 mb-3">
<label for="no_telepon" class="form-label">No. Telepon</label>
<input type="tel" class="form-control" id="no_telepon" name="no_telepon" value="<?php echo htmlspecialchars($murid['no_telepon'] ?? ''); ?>">
</div>
</div>
<div class="mb-3">
<label for="email" class="form-label">Email</label>
<input type="email" class="form-control" id="email" name="email" value="<?php echo htmlspecialchars($murid['email'] ?? ''); ?>">
</div>
<div class="mb-3">
<label for="alamat" class="form-label">Alamat</label>
<textarea class="form-control" id="alamat" name="alamat" rows="3"><?php echo htmlspecialchars($murid['alamat'] ?? ''); ?></textarea>
</div>
<hr>
<h5 class="mb-3">Foto dan Lokasi</h5>
<div class="row">
<div class="col-md-6 mb-3">
<label for="foto" class="form-label">Foto Murid</label>
<input class="form-control" type="file" id="foto" name="foto" accept="image/jpeg, image/png">
<?php if (!empty($murid['foto'])): ?>
<div class="mt-2">
<img src="assets/uploads/murid/<?php echo htmlspecialchars($murid['foto']); ?>" alt="Foto saat ini" style="max-height: 100px; border-radius: 4px;">
<input type="hidden" name="foto_existing" value="<?php echo htmlspecialchars($murid['foto']); ?>">
</div>
<?php endif; ?>
</div>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="latitude" class="form-label">Latitude</label>
<input type="text" class="form-control" id="latitude" name="latitude" value="<?php echo htmlspecialchars($murid['latitude'] ?? ''); ?>">
</div>
<div class="col-md-6 mb-3">
<label for="longitude" class="form-label">Longitude</label>
<input type="text" class="form-control" id="longitude" name="longitude" value="<?php echo htmlspecialchars($murid['longitude'] ?? ''); ?>">
</div>
</div>
<div id="map" style="height: 300px;" class="mb-3"></div>
<p class="form-text text-muted">Klik pada peta untuk mengatur koordinat Latitude dan Longitude.</p>
<button type="submit" class="btn btn-success">Simpan Data</button>
</form>
</div>
</div>
<?php else: ?>
<!-- Import Form -->
<div class="card mb-4">
<div class="card-header">
<h5 class="card-title">Impor Data dari XLSX</h5>
</div>
<div class="card-body">
<p>Pastikan urutan kolom di file Excel Anda adalah: NIS, NISN, Nama Lengkap, Tanggal Lahir, Alamat.</p>
<form action="index.php?page=murid&action=import" method="POST" enctype="multipart/form-data">
<input type="hidden" name="action" value="import">
<div class="mb-3">
<label for="file_murid" class="form-label">Pilih file .xlsx</label>
<input class="form-control" type="file" id="file_murid" name="file_murid" accept=".xlsx" required>
</div>
<button type="submit" class="btn btn-info">Impor</button>
</form>
</div>
</div>
<!-- Table of Students -->
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Foto</th>
<th scope="col">NIS</th>
<th scope="col">Nama Lengkap</th>
<th scope="col">Kelas</th>
<th scope="col">Jenis Kelamin</th>
<th scope="col">Aksi</th>
</tr>
</thead>
<tbody>
<?php
$all_murid = get_all_murid();
if (count($all_murid) > 0):
$i = 1;
foreach ($all_murid as $m):
$foto_path = 'assets/uploads/murid/' . ($m['foto'] ?? 'default.png');
if (empty($m['foto']) || !file_exists($foto_path)) {
$foto_path = 'assets/images/placeholder.png'; // Fallback to a placeholder
}
?>
<tr>
<td><?php echo $i++; ?></td>
<td>
<img src="<?php echo htmlspecialchars($foto_path); ?>" alt="Foto <?php echo htmlspecialchars($m['nama_lengkap']); ?>" style="width: 50px; height: 50px; object-fit: cover; border-radius: 50%;">
</td>
<td><?php echo htmlspecialchars($m['nis']); ?></td>
<td><?php echo htmlspecialchars($m['nama_lengkap']); ?></td>
<td><?php echo htmlspecialchars($m['nama_kelas'] ?? '<em>Belum diatur</em>'); ?></td>
<td><?php echo htmlspecialchars($m['jenis_kelamin']); ?></td>
<td>
<a href="index.php?page=murid&action=edit&id=<?php echo $m['id']; ?>" class="btn btn-sm btn-warning">Ubah</a>
<a href="index.php?page=murid&action=delete&id=<?php echo $m['id']; ?>" class="btn btn-sm btn-danger" onclick="return confirm('Apakah Anda yakin ingin menghapus data ini?');">Hapus</a>
</td>
</tr>
<?php
endforeach;
else:
?>
<tr>
<td colspan="7" class="text-center">Belum ada data murid.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</main>

111
templates/reports.php Normal file
View File

@ -0,0 +1,111 @@
<?php
// Ambil semua kelas untuk dropdown filter
$kelas_list = get_all_kelas();
// Inisialisasi variabel
$selected_kelas_id = $_GET['kelas_id'] ?? null;
$start_date = $_GET['start_date'] ?? date('Y-m-01');
$end_date = $_GET['end_date'] ?? date('Y-m-t');
$rekap_absensi = [];
// Jika kelas dipilih, ambil data rekap
if ($selected_kelas_id) {
$rekap_absensi = get_rekap_absensi($selected_kelas_id, $start_date, $end_date);
}
?>
<div class="container-fluid">
<h1 class="h3 mb-4 text-gray-800">Laporan Absensi Murid</h1>
<!-- Filter Form -->
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Filter Laporan</h6>
</div>
<div class="card-body">
<form method="GET">
<input type="hidden" name="page" value="reports">
<div class="form-row">
<div class="form-group col-md-4">
<label for="kelas_id">Kelas</label>
<select name="kelas_id" id="kelas_id" class="form-control" required>
<option value="">-- Pilih Kelas --</option>
<?php foreach ($kelas_list as $kelas) : ?>
<option value="<?php echo $kelas['id']; ?>" <?php echo ($selected_kelas_id == $kelas['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($kelas['nama_kelas']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group col-md-3">
<label for="start_date">Dari Tanggal</label>
<input type="date" name="start_date" id="start_date" class="form-control" value="<?php echo $start_date; ?>">
</div>
<div class="form-group col-md-3">
<label for="end_date">Sampai Tanggal</label>
<input type="date" name="end_date" id="end_date" class="form-control" value="<?php echo $end_date; ?>">
</div>
<div class="form-group col-md-2 d-flex align-items-end">
<button type="submit" class="btn btn-primary btn-block">Tampilkan</button>
</div>
</div>
</form>
</div>
</div>
<!-- Attendance Report Table -->
<?php if ($selected_kelas_id) : ?>
<div class="card shadow mb-4">
<div class="card-header py-3 d-flex justify-content-between align-items-center">
<h6 class="m-0 font-weight-bold text-primary">Rekapitulasi Absensi</h6>
<form action="export_laporan.php" method="POST" target="_blank">
<input type="hidden" name="kelas_id" value="<?php echo $selected_kelas_id; ?>">
<input type="hidden" name="start_date" value="<?php echo $start_date; ?>">
<input type="hidden" name="end_date" value="<?php echo $end_date; ?>">
<button type="submit" class="btn btn-success btn-sm">
<i class="fas fa-file-excel"></i> Ekspor ke Excel
</button>
</form>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>No</th>
<th>NIS</th>
<th>Nama Lengkap</th>
<th>Hadir</th>
<th>Sakit</th>
<th>Izin</th>
<th>Alpa</th>
<th>Total Jam</th>
</tr>
</thead>
<tbody>
<?php if (empty($rekap_absensi)) : ?>
<tr>
<td colspan="8" class="text-center">Tidak ada data absensi untuk periode dan kelas yang dipilih.</td>
</tr>
<?php else : ?>
<?php foreach ($rekap_absensi as $index => $rekap) : ?>
<tr>
<td><?php echo $index + 1; ?></td>
<td><?php echo htmlspecialchars($rekap['nis']); ?></td>
<td><?php echo htmlspecialchars($rekap['nama_lengkap']); ?></td>
<td><?php echo (int)$rekap['total_hadir']; ?></td>
<td><?php echo (int)$rekap['total_sakit']; ?></td>
<td><?php echo (int)$rekap['total_izin']; ?></td>
<td><?php echo (int)$rekap['total_alpa']; ?></td>
<td><?php echo (int)$rekap['total_absensi']; ?></td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
<?php endif; ?>
</div>

160
templates/schedule.php Normal file
View File

@ -0,0 +1,160 @@
<?php
// Handle form submission
$status_message = handle_jadwal_action();
// Determine if we are in edit mode
$edit_mode = false;
$jadwal_to_edit = null;
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
$jadwal_to_edit = get_jadwal_by_id($_GET['id']);
if ($jadwal_to_edit) {
$edit_mode = true;
}
}
// Fetch all required data
$all_jadwal = get_all_jadwal();
$all_kelas = get_all_kelas();
$all_guru = get_all_guru();
$all_matapelajaran = get_all_matapelajaran(); // Fetch subjects
$days = ['Senin', 'Selasa', 'Rabu', 'Kamis', 'Jumat', 'Sabtu', 'Minggu'];
?>
<div class="container-fluid">
<h1 class="h3 mb-4 text-gray-800"><?php echo $edit_mode ? 'Ubah Jadwal Pelajaran' : 'Tambah Jadwal Pelajaran'; ?></h1>
<?php if ($status_message): ?>
<div class="alert alert-<?php echo $status_message['success'] ? 'success' : 'danger'; ?>">
<?php echo $status_message['message']; ?>
</div>
<?php endif; ?>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Formulir Jadwal</h6>
</div>
<div class="card-body">
<form action="index.php?page=schedule" method="POST">
<input type="hidden" name="action" value="<?php echo $edit_mode ? 'edit' : 'add'; ?>">
<?php if ($edit_mode): ?>
<input type="hidden" name="id" value="<?php echo $jadwal_to_edit['id']; ?>">
<?php endif; ?>
<div class="form-row">
<div class="form-group col-md-6">
<label for="id_kelas">Kelas</label>
<select id="id_kelas" name="id_kelas" class="form-control" required>
<option value="" disabled selected>-- Pilih Kelas --</option>
<?php foreach ($all_kelas as $kelas): ?>
<option value="<?php echo $kelas['id']; ?>" <?php echo ($edit_mode && $jadwal_to_edit['id_kelas'] == $kelas['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($kelas['nama_kelas']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group col-md-6">
<label for="id_guru">Guru Pengajar</label>
<select id="id_guru" name="id_guru" class="form-control" required>
<option value="" disabled selected>-- Pilih Guru --</option>
<?php foreach ($all_guru as $guru): ?>
<option value="<?php echo $guru['id']; ?>" <?php echo ($edit_mode && $jadwal_to_edit['id_guru'] == $guru['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($guru['nama']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
</div>
<div class="form-group">
<label for="id_matapelajaran">Mata Pelajaran</label>
<select id="id_matapelajaran" name="id_matapelajaran" class="form-control" required>
<option value="" disabled selected>-- Pilih Mata Pelajaran --</option>
<?php foreach ($all_matapelajaran as $mapel): ?>
<option value="<?php echo $mapel['id']; ?>" <?php echo ($edit_mode && $jadwal_to_edit['id_matapelajaran'] == $mapel['id']) ? 'selected' : ''; ?>>
<?php echo htmlspecialchars($mapel['nama_matapelajaran']); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form-row">
<div class="form-group col-md-4">
<label for="hari">Hari</label>
<select id="hari" name="hari" class="form-control" required>
<option value="" disabled selected>-- Pilih Hari --</option>
<?php foreach ($days as $day): ?>
<option value="<?php echo $day; ?>" <?php echo ($edit_mode && $jadwal_to_edit['hari'] == $day) ? 'selected' : ''; ?>>
<?php echo $day; ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="form-group col-md-4">
<label for="jam_mulai">Jam Mulai</label>
<input type="time" class="form-control" id="jam_mulai" name="jam_mulai"
value="<?php echo $edit_mode ? $jadwal_to_edit['jam_mulai'] : ''; ?>" required>
</div>
<div class="form-group col-md-4">
<label for="jam_selesai">Jam Selesai</label>
<input type="time" class="form-control" id="jam_selesai" name="jam_selesai"
value="<?php echo $edit_mode ? $jadwal_to_edit['jam_selesai'] : ''; ?>" required>
</div>
</div>
<button type="submit" class="btn btn-primary">
<?php echo $edit_mode ? 'Simpan Perubahan' : 'Tambah Jadwal'; ?>
</button>
<?php if ($edit_mode): ?>
<a href="index.php?page=schedule" class="btn btn-secondary">Batal</a>
<?php endif; ?>
</form>
</div>
</div>
<div class="card shadow mb-4">
<div class="card-header py-3">
<h6 class="m-0 font-weight-bold text-primary">Daftar Jadwal Pelajaran</h6>
</div>
<div class="card-body">
<div class="table-responsive">
<table class="table table-bordered" id="dataTable" width="100%" cellspacing="0">
<thead>
<tr>
<th>Kelas</th>
<th>Hari</th>
<th>Waktu</th>
<th>Mata Pelajaran</th>
<th>Guru</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php if (empty($all_jadwal)): ?>
<tr>
<td colspan="6" class="text-center">Belum ada data jadwal.</td>
</tr>
<?php else: ?>
<?php foreach ($all_jadwal as $jadwal): ?>
<tr>
<td><?php echo htmlspecialchars($jadwal['nama_kelas']); ?></td>
<td><?php echo htmlspecialchars($jadwal['hari']); ?></td>
<td><?php echo htmlspecialchars(date('H:i', strtotime($jadwal['jam_mulai']))) . ' - ' . htmlspecialchars(date('H:i', strtotime($jadwal['jam_selesai']))); ?></td>
<td><?php echo htmlspecialchars($jadwal['nama_matapelajaran']); ?></td>
<td><?php echo htmlspecialchars($jadwal['nama_guru']); ?></td>
<td>
<a href="index.php?page=schedule&action=edit&id=<?php echo $jadwal['id']; ?>" class="btn btn-warning btn-sm">Ubah</a>
<a href="index.php?page=schedule&action=delete&id=<?php echo $jadwal['id']; ?>" class="btn btn-danger btn-sm" onclick="return confirm('Apakah Anda yakin ingin menghapus jadwal ini?');">Hapus</a>
</td>
</tr>
<?php endforeach; ?>
<?php endif; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>

58
templates/sidebar.php Normal file
View File

@ -0,0 +1,58 @@
<nav class="sidebar">
<div class="p-4">
<a href="index.php" class="d-flex align-items-center text-dark text-decoration-none">
<span class="fs-4 fw-bold">Akademik</span>
</a>
</div>
<ul class="nav flex-column mb-auto p-3">
<li class="nav-item">
<a href="index.php?page=dashboard" class="nav-link <?php echo is_active('dashboard'); ?>">
<i data-feather="home"></i>
Dashboard
</a>
</li>
<li class="nav-item">
<a href="index.php?page=murid" class="nav-link <?php echo is_active('murid'); ?>">
<i data-feather="users"></i>
Murid
</a>
</li>
<li class="nav-item">
<a href="index.php?page=teachers" class="nav-link <?php echo is_active('teachers'); ?>">
<i data-feather="user"></i>
Guru
</a>
</li>
<li class="nav-item">
<a href="index.php?page=classes" class="nav-link <?php echo is_active('classes'); ?>">
<i data-feather="archive"></i>
Kelas
</a>
</li>
<li class="nav-item">
<a href="index.php?page=subjects" class="nav-link <?php echo is_active('subjects'); ?>">
<i data-feather="book-open"></i>
Mata Pelajaran
</a>
</li>
<li class="nav-item">
<a href="index.php?page=attendance" class="nav-link <?php echo is_active('attendance'); ?>">
<i data-feather="check-square"></i>
Absensi
</a>
</li>
<li class="nav-item">
<a href="index.php?page=schedule" class="nav-link <?php echo is_active('schedule'); ?>">
<i data-feather="calendar"></i>
Jadwal
</a>
</li>
<li class="nav-item">
<a href="index.php?page=reports" class="nav-link <?php echo is_active('reports'); ?>">
<i data-feather="bar-chart-2"></i>
Laporan
</a>
</li>
</ul>
</nav>

88
templates/subjects.php Normal file
View File

@ -0,0 +1,88 @@
<?php
// Handle actions from the form
$notification = handle_matapelajaran_action();
// Get data for the view
$all_matapelajaran = get_all_matapelajaran();
// Determine form action (add or edit)
$form_action = 'add';
$form_title = "Tambah Mata Pelajaran Baru";
$nama_matapelajaran_value = '';
$id_value = '';
if (isset($_GET['action']) && $_GET['action'] === 'edit' && isset($_GET['id'])) {
$matapelajaran = get_matapelajaran_by_id($_GET['id']);
if ($matapelajaran) {
$form_action = 'edit';
$form_title = "Ubah Data Mata Pelajaran";
$nama_matapelajaran_value = $matapelajaran['nama_matapelajaran'];
$id_value = $matapelajaran['id'];
}
}
?>
<div class="container-fluid">
<div class="row">
<!-- Form to Add/Edit Subject -->
<div class="col-md-4">
<div class="card">
<div class="card-header">
<h3 class="card-title"><?= $form_title ?></h3>
</div>
<div class="card-body">
<?php if (isset($notification)): ?>
<div class="alert alert-<?= $notification['success'] ? 'success' : 'danger' ?>">
<?= $notification['message'] ?>
</div>
<?php endif; ?>
<form action="index.php?page=subjects" method="POST">
<input type="hidden" name="action" value="<?= $form_action ?>">
<input type="hidden" name="id" value="<?= $id_value ?>">
<div class="form-group">
<label for="nama_matapelajaran">Nama Mata Pelajaran</label>
<input type="text" class="form-control" id="nama_matapelajaran" name="nama_matapelajaran" value="<?= htmlspecialchars($nama_matapelajaran_value) ?>" required>
</div>
<button type="submit" class="btn btn-primary">Simpan</button>
<?php if ($form_action === 'edit'): ?>
<a href="index.php?page=subjects" class="btn btn-secondary">Batal</a>
<?php endif; ?>
</form>
</div>
</div>
</div>
<!-- Table of Subjects -->
<div class="col-md-8">
<div class="card">
<div class="card-header">
<h3 class="card-title">Daftar Mata Pelajaran</h3>
</div>
<div class="card-body">
<table id="matapelajaranTable" class="table table-bordered table-striped">
<thead>
<tr>
<th>No</th>
<th>Nama Mata Pelajaran</th>
<th>Aksi</th>
</tr>
</thead>
<tbody>
<?php foreach ($all_matapelajaran as $index => $mapel): ?>
<tr>
<td><?= $index + 1 ?></td>
<td><?= htmlspecialchars($mapel['nama_matapelajaran']) ?></td>
<td>
<a href="index.php?page=subjects&action=edit&id=<?= $mapel['id'] ?>" class="btn btn-sm btn-warning">Ubah</a>
<a href="index.php?page=subjects&action=delete&id=<?= $mapel['id'] ?>" class="btn btn-sm btn-danger" onclick="return confirm('Apakah Anda yakin ingin menghapus mata pelajaran ini?')">Hapus</a>
</td>
</tr>
<?php endforeach; ?>
</tbody>
</table>
</div>
</div>
</div>
</div>
</div>

166
templates/teachers.php Normal file
View File

@ -0,0 +1,166 @@
<?php
// templates/teachers.php
// Handle form submissions and actions
$feedback = handle_guru_action();
// Get the current action from URL, default to 'list'
$action = $_GET['action'] ?? 'list';
$id = $_GET['id'] ?? null;
// Get data for a single teacher if editing
$guru = null;
if ($action === 'edit' && $id) {
$guru = get_guru_by_id($id);
if (!$guru) {
// If teacher not found, redirect to list with an error
header("Location: index.php?page=teachers&status=not_found");
exit();
}
}
?>
<main class="main-content">
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pt-3 pb-2 mb-3 border-bottom">
<h1 class="h2">Manajemen Guru</h1>
<?php if ($action === 'list'): ?>
<a href="index.php?page=teachers&action=add" class="btn btn-primary">Tambah Guru</a>
<?php else: ?>
<a href="index.php?page=teachers" class="btn btn-outline-secondary">Kembali ke Daftar</a>
<?php endif; ?>
</div>
<?php if (isset($feedback['message'])): ?>
<div class="alert alert-<?php echo $feedback['success'] ? 'success' : 'danger'; ?>">
<?php echo htmlspecialchars($feedback['message']); ?>
</div>
<?php endif; ?>
<?php if (isset($_GET['status']) && $_GET['status'] == 'deleted'): ?>
<div class="alert alert-success">Data guru berhasil dihapus.</div>
<?php endif; ?>
<?php if (isset($_GET['status']) && $_GET['status'] == 'error'): ?>
<div class="alert alert-danger">Terjadi kesalahan saat menghapus data.</div>
<?php endif; ?>
<?php if (isset($_GET['status']) && $_GET['status'] == 'not_found'): ?>
<div class="alert alert-warning">Data guru tidak ditemukan.</div>
<?php endif; ?>
<?php if ($action === 'add' || $action === 'edit'): ?>
<div class="card">
<div class="card-header">
<h5 class="card-title"><?php echo $action === 'add' ? 'Tambah Guru Baru' : 'Ubah Data Guru'; ?></h5>
</div>
<div class="card-body">
<form action="index.php?page=teachers" method="POST" enctype="multipart/form-data">
<input type="hidden" name="action" value="<?php echo $action; ?>">
<?php if ($id): ?>
<input type="hidden" name="id" value="<?php echo $id; ?>">
<?php endif; ?>
<div class="row">
<div class="col-md-6 mb-3">
<label for="nip" class="form-label">NIP</label>
<input type="text" class="form-control" id="nip" name="nip" value="<?php echo htmlspecialchars($guru['nip'] ?? ''); ?>" required>
</div>
<div class="col-md-6 mb-3">
<label for="nama" class="form-label">Nama Lengkap</label>
<input type="text" class="form-control" id="nama" name="nama" value="<?php echo htmlspecialchars($guru['nama'] ?? ''); ?>" required>
</div>
</div>
<div class="mb-3">
<label for="alamat" class="form-label">Alamat</label>
<textarea class="form-control" id="alamat" name="alamat" rows="3"><?php echo htmlspecialchars($guru['alamat'] ?? ''); ?></textarea>
</div>
<div class="mb-3">
<label for="telepon" class="form-label">No. Telepon</label>
<input type="tel" class="form-control" id="telepon" name="telepon" value="<?php echo htmlspecialchars($guru['telepon'] ?? ''); ?>">
</div>
<hr>
<h5 class="mb-3">Foto dan Lokasi</h5>
<div class="mb-3">
<label for="foto" class="form-label">Foto Guru</label>
<input class="form-control" type="file" id="foto" name="foto" accept="image/jpeg, image/png">
<?php if (!empty($guru['foto'])): ?>
<div class="mt-2">
<img src="assets/uploads/guru/<?php echo htmlspecialchars($guru['foto']); ?>" alt="Foto saat ini" style="max-height: 100px; border-radius: 4px;">
<input type="hidden" name="foto_existing" value="<?php echo htmlspecialchars($guru['foto']); ?>">
</div>
<?php endif; ?>
</div>
<div class="row">
<div class="col-md-6 mb-3">
<label for="latitude" class="form-label">Latitude</label>
<input type="text" class="form-control" id="latitude" name="latitude" value="<?php echo htmlspecialchars($guru['latitude'] ?? ''); ?>">
</div>
<div class="col-md-6 mb-3">
<label for="longitude" class="form-label">Longitude</label>
<input type="text" class="form-control" id="longitude" name="longitude" value="<?php echo htmlspecialchars($guru['longitude'] ?? ''); ?>">
</div>
</div>
<div id="map" style="height: 300px;" class="mb-3"></div>
<p class="form-text text-muted">Klik pada peta untuk mengatur koordinat Latitude dan Longitude.</p>
<button type="submit" class="btn btn-success">Simpan Data</button>
</form>
</div>
</div>
<?php else: ?>
<div class="table-responsive">
<table class="table table-striped table-hover">
<thead class="table-dark">
<tr>
<th scope="col">#</th>
<th scope="col">Foto</th>
<th scope="col">NIP</th>
<th scope="col">Nama</th>
<th scope="col">Aksi</th>
</tr>
</thead>
<tbody>
<?php
$all_guru = get_all_guru();
if (count($all_guru) > 0):
$i = 1;
foreach ($all_guru as $g):
$foto_path = 'assets/uploads/guru/' . ($g['foto'] ?? 'default.png');
if (empty($g['foto']) || !file_exists($foto_path)) {
$foto_path = 'assets/images/placeholder.png';
}
?>
<tr>
<td><?php echo $i++; ?></td>
<td>
<img src="<?php echo htmlspecialchars($foto_path); ?>" alt="Foto <?php echo htmlspecialchars($g['nama']); ?>" style="width: 50px; height: 50px; object-fit: cover; border-radius: 50%;">
</td>
<td><?php echo htmlspecialchars($g['nip']); ?></td>
<td><?php echo htmlspecialchars($g['nama']); ?></td>
<td>
<a href="index.php?page=teachers&action=edit&id=<?php echo $g['id']; ?>" class="btn btn-sm btn-warning">Ubah</a>
<a href="index.php?page=teachers&action=delete&id=<?php echo $g['id']; ?>" class="btn btn-sm btn-danger" onclick="return confirm('Apakah Anda yakin ingin menghapus data ini?');">Hapus</a>
</td>
</tr>
<?php
endforeach;
else:
?>
<tr>
<td colspan="5" class="text-center">Belum ada data guru.</td>
</tr>
<?php endif; ?>
</tbody>
</table>
</div>
<?php endif; ?>
</main>