SIAKAD 1.0
This commit is contained in:
parent
d4291f001f
commit
bb0884a9fc
42
assets/css/style.css
Normal file
42
assets/css/style.css
Normal 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
6
assets/js/main.js
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
|
||||||
|
(function () {
|
||||||
|
'use strict'
|
||||||
|
|
||||||
|
feather.replace()
|
||||||
|
})()
|
||||||
28
db/migrate.php
Normal file
28
db/migrate.php
Normal 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";
|
||||||
|
}
|
||||||
|
|
||||||
16
db/migrations/001_create_murid_table.sql
Normal file
16
db/migrations/001_create_murid_table.sql
Normal 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;
|
||||||
5
db/migrations/002_add_location_and_photo_to_murid.sql
Normal file
5
db/migrations/002_add_location_and_photo_to_murid.sql
Normal 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`;
|
||||||
12
db/migrations/003_create_guru_table.sql
Normal file
12
db/migrations/003_create_guru_table.sql
Normal 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
|
||||||
|
);
|
||||||
6
db/migrations/004_create_kelas_table.sql
Normal file
6
db/migrations/004_create_kelas_table.sql
Normal 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;
|
||||||
16
db/migrations/005_create_jadwal_table.sql
Normal file
16
db/migrations/005_create_jadwal_table.sql
Normal 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;
|
||||||
13
db/migrations/006_create_absensi_table.sql
Normal file
13
db/migrations/006_create_absensi_table.sql
Normal 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)
|
||||||
|
);
|
||||||
3
db/migrations/007_add_kelas_id_to_murid.sql
Normal file
3
db/migrations/007_add_kelas_id_to_murid.sql
Normal 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;
|
||||||
6
db/migrations/008_create_matapelajaran_table.sql
Normal file
6
db/migrations/008_create_matapelajaran_table.sql
Normal 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;
|
||||||
6
db/migrations/009_add_matapelajaran_to_jadwal.sql
Normal file
6
db/migrations/009_add_matapelajaran_to_jadwal.sql
Normal 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
61
export_laporan.php
Normal 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
34
export_murid.php
Normal 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
658
functions.php
Normal 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
178
index.php
@ -1,150 +1,34 @@
|
|||||||
<?php
|
<?php
|
||||||
declare(strict_types=1);
|
require_once 'db/config.php';
|
||||||
@ini_set('display_errors', '1');
|
require_once 'functions.php';
|
||||||
@error_reporting(E_ALL);
|
require_once 'templates/header.php';
|
||||||
@date_default_timezone_set('UTC');
|
require_once 'templates/sidebar.php';
|
||||||
|
|
||||||
$phpVersion = PHP_VERSION;
|
$page = $_GET['page'] ?? 'dashboard';
|
||||||
$now = date('Y-m-d H:i:s');
|
|
||||||
?>
|
switch ($page) {
|
||||||
<!doctype html>
|
case 'murid':
|
||||||
<html lang="en">
|
include 'templates/murid.php';
|
||||||
<head>
|
break;
|
||||||
<meta charset="utf-8" />
|
case 'teachers':
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
include 'templates/teachers.php';
|
||||||
<title>New Style</title>
|
break;
|
||||||
<?php
|
case 'classes':
|
||||||
// Read project preview data from environment
|
include 'templates/classes.php';
|
||||||
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
break;
|
||||||
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
case 'attendance':
|
||||||
?>
|
include 'templates/attendance.php';
|
||||||
<?php if ($projectDescription): ?>
|
break;
|
||||||
<!-- Meta description -->
|
case 'schedule':
|
||||||
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
include 'templates/schedule.php';
|
||||||
<!-- Open Graph meta tags -->
|
break;
|
||||||
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
case 'reports':
|
||||||
<!-- Twitter meta tags -->
|
include 'templates/reports.php';
|
||||||
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
break;
|
||||||
<?php endif; ?>
|
case 'dashboard':
|
||||||
<?php if ($projectImageUrl): ?>
|
default:
|
||||||
<!-- Open Graph image -->
|
include 'templates/dashboard.php';
|
||||||
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
break;
|
||||||
<!-- 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);
|
|
||||||
}
|
}
|
||||||
body {
|
|
||||||
margin: 0;
|
require_once 'templates/footer.php';
|
||||||
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>
|
|
||||||
1231
libs/SimpleXLSX.php
Normal file
1231
libs/SimpleXLSX.php
Normal file
File diff suppressed because it is too large
Load Diff
1340
libs/SimpleXLSXGen.php
Normal file
1340
libs/SimpleXLSXGen.php
Normal file
File diff suppressed because it is too large
Load Diff
148
templates/attendance.php
Normal file
148
templates/attendance.php
Normal 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
108
templates/classes.php
Normal 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
27
templates/dashboard.php
Normal 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
59
templates/footer.php
Normal 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: '© <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
16
templates/header.php
Normal 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
243
templates/murid.php
Normal 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
111
templates/reports.php
Normal 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
160
templates/schedule.php
Normal 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
58
templates/sidebar.php
Normal 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
88
templates/subjects.php
Normal 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
166
templates/teachers.php
Normal 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>
|
||||||
Loading…
x
Reference in New Issue
Block a user