Initial commit
This commit is contained in:
@@ -0,0 +1,462 @@
|
||||
<?php
|
||||
if(check_permission('siswa', 'can_view')):
|
||||
|
||||
$fotoSiswa = ($siswa->foto) ? base_url('uploads/siswa/'.$siswa->foto) : base_url('uploads/siswa/foto.jpg') ;
|
||||
|
||||
?>
|
||||
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js"></script>
|
||||
<div class="container mt-4">
|
||||
<?php if(check_permission('siswa', 'can_update')): ?>
|
||||
<div class="text-end mb-3">
|
||||
<button class="btn btn-success btn-eximport d-none d-lg-inline" id="downloadPdfBtn">
|
||||
<i class="bi bi-file-earmark-pdf-fill me-1"></i> Export PDF Halaman Ini
|
||||
</button>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<div id="containerDownload">
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h4 class="mb-0 fw-bold">Detail Santri</h4>
|
||||
</div>
|
||||
|
||||
<div class="row align-items-stretch">
|
||||
|
||||
<!-- ================== DETAIL SANTRI ================== -->
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card shadow-sm border-0 rounded-4 h-100">
|
||||
<div class="card-body p-4">
|
||||
|
||||
<h5 class="fw-semibold">Informasi Santri</h5>
|
||||
<hr>
|
||||
|
||||
<center>
|
||||
<img class="foto-santri rounded-4 shadow-sm mb-3"
|
||||
src="<?= $fotoSiswa; ?>"
|
||||
style="width:160px;height:200px;object-fit:cover;">
|
||||
</center>
|
||||
|
||||
<table class="table table-borderless">
|
||||
<tr>
|
||||
<th width="200">Nama</th>
|
||||
<td>: <?= $siswa->nama; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>NIS</th>
|
||||
<td>: <?= $siswa->nis; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Kelas</th>
|
||||
<td>: <?= $siswa->nama_kelas; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Kamar</th>
|
||||
<td>: <?= $siswa->nama_kamar . ' ('.$siswa->nama_gedung_kamar.')'; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Tahun Masuk</th>
|
||||
<td>: <?= $siswa->tahun_masuk; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Alamat</th>
|
||||
<td>: <?= $siswa->alamat; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Nama Wali Santri</th>
|
||||
<td>: <?= $siswa->nama_wali; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>No Whatsapp Wali Santri</th>
|
||||
<td>: <?= $siswa->nomor_whatsapp; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Email Wali Santri</th>
|
||||
<td>: <?= $siswa->email; ?></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<th>Jumlah Kunjungan</th>
|
||||
<td>: <?= $siswa->jumlah_kunjungan; ?></td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- ================== KARTU WALI SANTRI ================== -->
|
||||
<div class="col-md-6 mb-3">
|
||||
<div class="card shadow-sm border-0 rounded-4 h-100">
|
||||
<div class="card-body p-4">
|
||||
|
||||
<h5 class="fw-semibold">Kartu Tanda Wali Santri</h5>
|
||||
<hr>
|
||||
|
||||
<div class="items-card-center">
|
||||
<img id="defaultBg" src="<?= base_url($setting->card_background) ?>" hidden>
|
||||
<div id="cardPreview"></div>
|
||||
</div>
|
||||
|
||||
<div class="text-center mt-4">
|
||||
<?php if(check_permission('siswa', 'can_update')): ?>
|
||||
<button class="btn btn-success btn-add rounded-3 mt-4" onclick="printCardPDF()">
|
||||
<i class="bi bi-printer me-1"></i> Print ID Card
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="card modern-card shadow-sm border-0 rounded-4 mt-3 mb-4">
|
||||
<div class="card-body p-4">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center">
|
||||
<h5 class="mb-1">Riwayat Kunjungan</h5>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="tableHistory" class="table modern-table align-middle w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>Nama</th>
|
||||
<th>NIS</th>
|
||||
<th>Kelas</th>
|
||||
<th>Kamar</th>
|
||||
<th>Nama Wali</th>
|
||||
<th>Alamat</th>
|
||||
<th>Jam Masuk</th>
|
||||
<th>Petugas Masuk</th>
|
||||
<th>Jam Keluar</th>
|
||||
<th>Petugas Keluar</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready(function() {
|
||||
|
||||
let isInitialLoad = true;
|
||||
$('#dateRangeFilter').val('');
|
||||
|
||||
$('#dateRangeFilter').daterangepicker({
|
||||
autoUpdateInput: false,
|
||||
locale: { cancelLabel: false, format: 'YYYY-MM-DD' },
|
||||
linkedCalendars: false
|
||||
});
|
||||
|
||||
$('#dateRangeFilter').on('apply.daterangepicker', function(ev, picker) {
|
||||
$(this).val(picker.startDate.format('YYYY-MM-DD') + ' - ' + picker.endDate.format('YYYY-MM-DD'));
|
||||
table.ajax.reload();
|
||||
});
|
||||
|
||||
$('#dateRangeFilter').on('cancel.daterangepicker', function(ev, picker) {
|
||||
$(this).val('');
|
||||
table.ajax.reload();
|
||||
});
|
||||
|
||||
let table = $('#tableHistory').DataTable({
|
||||
dom: '<"dataTables_top d-flex justify-content-between mb-3"l f>rtip',
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
responsive: false,
|
||||
autoWidth: false,
|
||||
order: [],
|
||||
ajax: {
|
||||
url: "<?= base_url('siswa/get_kunjungan'); ?>",
|
||||
type: "POST",
|
||||
data: function(d) {
|
||||
|
||||
// Tambahkan id_siswa dari PHP
|
||||
d.id_siswa = `<?= $siswa->id; ?>`;
|
||||
|
||||
// Tambahkan filter tanggal
|
||||
var picker = $('#dateRangeFilter').data('daterangepicker');
|
||||
if (picker && picker.startDate && picker.startDate.isValid()) {
|
||||
d.startDate = picker.startDate.format('YYYY-MM-DD');
|
||||
}
|
||||
if (picker && picker.endDate && picker.endDate.isValid()) {
|
||||
d.endDate = picker.endDate.format('YYYY-MM-DD');
|
||||
}
|
||||
}
|
||||
},
|
||||
columns: [
|
||||
{ data: 0, orderable: false }, // No
|
||||
{ data: 1 }, // Nama
|
||||
{ data: 2 }, // NIS
|
||||
{ data: 3 }, // Kelas
|
||||
{ data: 4 }, // Kamar
|
||||
{ data: 5 }, // Nama Wali
|
||||
{ data: 6 }, // Alamat
|
||||
{
|
||||
data: 7, // Jam Masuk
|
||||
render: function(data) {
|
||||
return data ? data : '';
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 8, // Media Masuk
|
||||
orderable: false,
|
||||
render: function(data) {
|
||||
return data ? data : '';
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 9, // Jam Keluar
|
||||
render: function(data) {
|
||||
return data ? data : '';
|
||||
}
|
||||
},
|
||||
{
|
||||
data: 10, // Media Keluar
|
||||
orderable: false,
|
||||
render: function(data) {
|
||||
return data ? data : '';
|
||||
}
|
||||
}
|
||||
],
|
||||
language: {
|
||||
processing: `<div class="d-flex justify-content-center"><div class="spinner-border text-success"></div></div>`
|
||||
}
|
||||
});
|
||||
|
||||
$('.dataTables_filter input').attr('placeholder', 'Cari nama, nis, kelas...').css({
|
||||
'padding': '6px 12px',
|
||||
'border-radius': '6px',
|
||||
'border': '1px solid #ced4da',
|
||||
'font-size': '0.9rem',
|
||||
'box-sizing': 'border-box'
|
||||
});
|
||||
|
||||
table.on('draw', function() {
|
||||
$('#tableHistory tbody tr').each(function() {
|
||||
$(this).find('td').each(function(index) {
|
||||
let header = $('#tableHistory thead th').eq(index).text().trim();
|
||||
$(this).attr('data-label', header + ' : ');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
<script>
|
||||
|
||||
/* ============================================================
|
||||
1. DETEKSI ORIENTASI BACKGROUND & LOAD TEMPLATE OTOMATIS
|
||||
============================================================ */
|
||||
window.addEventListener("DOMContentLoaded", function () {
|
||||
let bg = document.getElementById("defaultBg");
|
||||
|
||||
if (!bg) {
|
||||
console.error("defaultBg tidak ditemukan!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Tunggu gambar background selesai diload
|
||||
bg.onload = function () {
|
||||
let isPortrait = bg.naturalHeight > bg.naturalWidth;
|
||||
|
||||
console.log("Background orientation:",
|
||||
isPortrait ? "POTRAIT" : "LANDSCAPE"
|
||||
);
|
||||
|
||||
loadCardPreviewFromImage(bg.src, isPortrait);
|
||||
};
|
||||
|
||||
// Jika gambar sudah cached & tidak trigger onload
|
||||
if (bg.complete) {
|
||||
bg.onload();
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
/* ============================================================
|
||||
2. LOAD TEMPLATE CARD
|
||||
============================================================ */
|
||||
function loadCardPreviewFromImage(imgSrc, isPortrait) {
|
||||
let preview = document.getElementById("cardPreview");
|
||||
if (!preview) return;
|
||||
|
||||
preview.style.backgroundImage = "url('" + imgSrc + "')";
|
||||
preview.className = "";
|
||||
|
||||
if (isPortrait) {
|
||||
preview.classList.add("id-card-potret");
|
||||
preview.innerHTML = portraitTemplate();
|
||||
} else {
|
||||
preview.classList.add("id-card-lemscape");
|
||||
preview.innerHTML = landscapeTemplate();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
3. TEMPLATE POTRAIT
|
||||
============================================================ */
|
||||
function portraitTemplate() {
|
||||
return `
|
||||
<div class="card-inner">
|
||||
|
||||
<div class="card-logo">
|
||||
<img src="<?= base_url('assets/img/logo.png'); ?>">
|
||||
</div>
|
||||
|
||||
<div class="card-title">Kartu Tanda Wali Santri</div>
|
||||
|
||||
<div class="photo-wrapper">
|
||||
<img src="<?= $fotoSiswa; ?>">
|
||||
</div>
|
||||
|
||||
<div class="card-info">
|
||||
<div class="nama"><?= $siswa->nama; ?></div>
|
||||
<div class="nis">NIS: <?= $siswa->nis; ?></div>
|
||||
<div class="kelas">Tahun Masuk: <?= $siswa->tahun_masuk; ?></div>
|
||||
<div class="alamat"><?= $siswa->alamat; ?></div>
|
||||
</div>
|
||||
|
||||
<div class="qr-wrapper">
|
||||
<img src="<?= base_url('qr/show/' . urlencode($siswa->qr_id)) ?>" width="100%">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
4. TEMPLATE LANDSCAPE
|
||||
============================================================ */
|
||||
function landscapeTemplate() {
|
||||
return `
|
||||
<div class="card-inner">
|
||||
|
||||
<div class="card-logo">
|
||||
<img src="<?= base_url('assets/img/logo.png'); ?>">
|
||||
</div>
|
||||
|
||||
<div class="card-title">Kartu Tanda Wali Santri</div>
|
||||
|
||||
<div class="landscape-content">
|
||||
|
||||
<div class="photo-wrapper">
|
||||
<img src="<?= $fotoSiswa; ?>">
|
||||
</div>
|
||||
|
||||
<div class="card-info">
|
||||
<div class="nama"><?= $siswa->nama; ?></div>
|
||||
<div class="nis">NIS: <?= $siswa->nis; ?></div>
|
||||
<div class="kelas">Tahun Masuk: <?= $siswa->tahun_masuk; ?></div>
|
||||
<div class="alamat"><?= $siswa->alamat; ?></div>
|
||||
</div>
|
||||
|
||||
<div class="qr-wrapper">
|
||||
<img src="<?= base_url('qr/show/' . urlencode($siswa->qr_id)) ?>" width="100%">
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
`;
|
||||
}
|
||||
|
||||
|
||||
/* ============================================================
|
||||
5. PRINT CARD DALAM MODE PDF
|
||||
============================================================ */
|
||||
function printCardPDF() {
|
||||
let card = document.getElementById("cardPreview");
|
||||
if (!card) {
|
||||
alert("Card Preview tidak ditemukan!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Ambil semua CSS di halaman
|
||||
let styles = "";
|
||||
document.querySelectorAll("style, link[rel='stylesheet']").forEach((el) => {
|
||||
styles += el.outerHTML;
|
||||
});
|
||||
|
||||
// Buka jendela print
|
||||
let w = window.open("", "_blank");
|
||||
|
||||
w.document.write(`
|
||||
<html>
|
||||
<head>
|
||||
<title>Cetak Kartu Santri</title>
|
||||
${styles} <!-- COPY semua CSS -->
|
||||
<style>
|
||||
body {
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
display: flex;
|
||||
zoom: 69%;
|
||||
background: #fff !important;
|
||||
}
|
||||
|
||||
/* Pastikan background ikut ke print */
|
||||
@media print {
|
||||
#cardPreview {
|
||||
-webkit-print-color-adjust: exact !important;
|
||||
print-color-adjust: exact !important;
|
||||
}
|
||||
* {
|
||||
-webkit-print-color-adjust: exact !important;
|
||||
print-color-adjust: exact !important;
|
||||
}
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
${card.outerHTML}
|
||||
</body>
|
||||
</html>
|
||||
`);
|
||||
|
||||
w.document.close();
|
||||
|
||||
// Tunggu elemen selesai render
|
||||
setTimeout(() => {
|
||||
w.print();
|
||||
// w.close(); // Kalau mau ditutup otomatis
|
||||
}, 500);
|
||||
}
|
||||
|
||||
</script>
|
||||
|
||||
<?php endif; ?>
|
||||
|
||||
<script>
|
||||
document.getElementById('downloadPdfBtn').addEventListener('click', function() {
|
||||
// Ambil seluruh container
|
||||
const container = document.getElementById('containerDownload');
|
||||
if (!container) {
|
||||
alert("Container tidak ditemukan!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Opsi PDF
|
||||
const opt = {
|
||||
margin: 0.5, // Margin dalam inch
|
||||
filename: 'Detail_Santri_<?= $siswa->nama ?>.pdf',
|
||||
image: { type: 'jpeg', quality: 0.98 },
|
||||
html2canvas: { scale: 2, logging: true, letterRendering: true, useCORS: true },
|
||||
jsPDF: { unit: 'in', format: 'a4', orientation: 'landscape' }
|
||||
};
|
||||
|
||||
// Generate PDF
|
||||
html2pdf().set(opt).from(container).save();
|
||||
});
|
||||
</script>
|
||||
@@ -0,0 +1,601 @@
|
||||
<style>
|
||||
.modern-tabs .nav-link {
|
||||
border: none;
|
||||
font-weight: 600;
|
||||
color: #555;
|
||||
border-radius: 8px 8px 0 0;
|
||||
}
|
||||
|
||||
.modern-tabs .nav-link.active {
|
||||
background: #0d6efd;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.import-dropzone {
|
||||
border: 2px dashed #c7d6ff;
|
||||
padding: 30px;
|
||||
border-radius: 12px;
|
||||
transition: .3s;
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
.import-dropzone.dragover {
|
||||
background: #eef5ff;
|
||||
border-color: #0d6efd;
|
||||
}
|
||||
|
||||
.export-card {
|
||||
border: 1px solid #eaeaea;
|
||||
background: #fafafa;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<div class="container mt-4">
|
||||
<div class="card modern-card shadow-sm border-0 rounded-4">
|
||||
<div class="card-body p-4">
|
||||
|
||||
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||
<h5 class="mb-0">Data Santri</h5>
|
||||
|
||||
<div>
|
||||
<?php if(check_permission('siswa', 'can_create')): ?>
|
||||
<button class="btn btn-success btn-add" style="margin-right: 5px;">
|
||||
<i class="bi bi-plus-circle me-1"></i> Tambah
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if(check_permission('siswa', 'can_export')): ?>
|
||||
<button class="btn btn-success btn-eximport d-none d-lg-inline" style="margin-right: 5px;" data-bs-toggle="modal" data-bs-target="#modalImport">
|
||||
<i class="bi bi-upload me-1"></i> Import
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php if(check_permission('siswa', 'can_import')): ?>
|
||||
<button class="btn btn-success btn-eximport d-none d-lg-inline" data-bs-toggle="modal" data-bs-target="#modalExport">
|
||||
<i class="bi bi-download me-1"></i> Export
|
||||
</button>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="table-responsive">
|
||||
<table id="tableSiswa" class="table modern-table align-middle w-100">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>No</th>
|
||||
<th>Foto</th>
|
||||
<th>Nama</th>
|
||||
<th>NIS</th>
|
||||
<th>Kelas</th>
|
||||
<th>Kamar</th>
|
||||
<th>Alamat</th>
|
||||
<th>Nama Wali</th>
|
||||
<th>Nomor Whatsapp</th>
|
||||
<th>Jumlah Kunjungan</th>
|
||||
<th>Aksi</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody></tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- MODAL TAMBAH / EDIT -->
|
||||
<div class="modal fade" id="modalTambah">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||
<div class="modal-content rounded-4">
|
||||
<div class="modal-header bg-success text-white rounded-top-4">
|
||||
<h5 class="modal-title">Tambah Santri</h5>
|
||||
<button class="btn-close btn-close-white" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<div class="card-foto-santri">
|
||||
<div class="foto-santri" id="previewFoto"></div>
|
||||
<input type="file" class="form-control d-none" id="imageSantri">
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
|
||||
<label class="fw-semibold mt-2">Nama</label>
|
||||
<input type="text" class="form-control" id="inputNama">
|
||||
|
||||
<label class="fw-semibold mt-2">NIS</label>
|
||||
<input type="text" class="form-control" id="inputNIS">
|
||||
|
||||
<label class="fw-semibold mt-2">Kelas</label>
|
||||
<select class="form-control" id="inputKelas">
|
||||
<option value="">-- Pilih Kelas --</option>
|
||||
</select>
|
||||
|
||||
<label class="fw-semibold mt-2">Kamar</label>
|
||||
<select class="form-control" id="inputKamar">
|
||||
<option value="">-- Pilih Kamar --</option>
|
||||
</select>
|
||||
|
||||
<label class="fw-semibold mt-2">Nama Wali Santri</label>
|
||||
<input type="text" class="form-control" id="inputWali">
|
||||
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
|
||||
<label class="fw-semibold mt-2">Nomor Whatsapp</label>
|
||||
<input type="text" class="form-control" id="inputWhatsapp">
|
||||
|
||||
<label class="fw-semibold mt-2">Email Wali Santri</label>
|
||||
<input type="text" class="form-control" id="inputEmail">
|
||||
|
||||
<label class="fw-semibold mt-2">Alamat</label>
|
||||
<textarea class="form-control" id="inputAlamat" rows="4"></textarea>
|
||||
|
||||
<label class="fw-semibold mt-2">Tahun Masuk</label>
|
||||
<select class="form-control" id="inputTahun">
|
||||
<option value="">-- Pilih Tahun --</option>
|
||||
</select>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
|
||||
<button class="btn btn-success" id="btnSimpan">Simpan</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Modal Import -->
|
||||
<div class="modal fade" id="modalImport" tabindex="-1">
|
||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||
<div class="modal-content shadow-lg rounded-4 border-0">
|
||||
|
||||
<div class="modal-header border-0 pb-0">
|
||||
<h5 class="modal-title fw-bold">
|
||||
<i class="bi bi-upload me-2"></i> Import Data Siswa
|
||||
</h5>
|
||||
<button class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="import-dropzone text-center" id="dropzone">
|
||||
<i class="bi bi-cloud-arrow-up fs-1 mb-2 text-primary"></i>
|
||||
<h6 class="fw-bold">Tarik File ke Sini</h6>
|
||||
<p class="small text-muted mb-2">Atau klik untuk memilih file Excel (.xlsx)</p>
|
||||
|
||||
<input type="file" id="fileImport" accept=".xlsx" hidden>
|
||||
<button class="btn btn-outline-primary btn-sm mt-2" id="btnSelectFile">
|
||||
Pilih File
|
||||
</button>
|
||||
|
||||
<div id="fileName" class="mt-3 fw-semibold text-success"></div>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-success w-100 mt-3" id="btnUpload">
|
||||
<i class="bi bi-check-circle me-2"></i> Upload & Proses
|
||||
</button>
|
||||
|
||||
<hr>
|
||||
<a href="<?= base_url('import/template'); ?>" class="btn btn-secondary w-100">
|
||||
<i class="bi bi-file-earmark-spreadsheet me-1"></i> Download Template Excel
|
||||
</a>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Modal Export -->
|
||||
<div class="modal fade" id="modalExport" tabindex="-1">
|
||||
<div class="modal-dialog modal-md modal-dialog-centered">
|
||||
<div class="modal-content shadow-lg rounded-4 border-0">
|
||||
|
||||
<div class="modal-header border-0 pb-0">
|
||||
<h5 class="modal-title fw-bold">
|
||||
<i class="bi bi-download me-2"></i> Export Data Siswa
|
||||
</h5>
|
||||
<button class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
|
||||
<div class="modal-body">
|
||||
|
||||
<div class="export-card p-3 rounded-3">
|
||||
<h6 class="fw-bold mb-3"><i class="bi bi-file-earmark-arrow-down me-1"></i> Pilih Format</h6>
|
||||
|
||||
<div class="d-flex gap-2">
|
||||
<a href="<?= base_url('export/siswa_excel'); ?>" class="btn btn-primary flex-fill">
|
||||
<i class="bi bi-file-earmark-excel me-1"></i> Excel
|
||||
</a>
|
||||
|
||||
<a href="<?= base_url('export/siswa_pdf'); ?>" class="btn btn-danger flex-fill">
|
||||
<i class="bi bi-file-earmark-pdf me-1"></i> PDF
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
$(document).ready(function(){
|
||||
|
||||
// ========================================================
|
||||
// INIT DATATABLE
|
||||
// ========================================================
|
||||
let table = $('#tableSiswa').DataTable({
|
||||
dom: '<"dataTables_top d-flex justify-content-between mb-3"lf>rtip',
|
||||
processing: true,
|
||||
serverSide: true,
|
||||
responsive: false,
|
||||
autoWidth: false,
|
||||
order: [],
|
||||
ajax: {
|
||||
url: "<?= base_url('siswa/get_data'); ?>",
|
||||
type: "POST"
|
||||
},
|
||||
columns: [
|
||||
{ data: 0, orderable: false },
|
||||
{ data: 1 },
|
||||
{ data: 2 },
|
||||
{ data: 3 },
|
||||
{ data: 4 },
|
||||
{ data: 5 },
|
||||
{ data: 6 },
|
||||
{ data: 7 },
|
||||
{ data: 8 },
|
||||
{ data: 9 },
|
||||
{ data: 10, orderable: false }
|
||||
],
|
||||
language: {
|
||||
processing: `<div class="d-flex justify-content-center"><div class="spinner-border text-success"></div></div>`
|
||||
}
|
||||
});
|
||||
|
||||
$('.dataTables_filter input')
|
||||
.attr('placeholder','Search...')
|
||||
.css({
|
||||
'min-width':'300px',
|
||||
'padding':'6px 12px',
|
||||
'border-radius':'6px',
|
||||
'border':'1px solid #ced4da',
|
||||
'font-size':'0.9rem'
|
||||
});
|
||||
|
||||
table.on('draw', function () {
|
||||
$('#tableSiswa tbody tr').each(function() {
|
||||
$(this).find('td').each(function(index) {
|
||||
let header = $('#tableSiswa thead th').eq(index).text().trim();
|
||||
$(this).attr('data-label', header + ' : ');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// ========================================================
|
||||
// MODAL ADD
|
||||
// ========================================================
|
||||
$(document).on('click', '.btn-add', function(){
|
||||
resetModal();
|
||||
|
||||
$('#modalTambah .modal-title').text('Tambah Santri');
|
||||
$('#btnSimpan').text('Simpan').data('action','add').removeData('id');
|
||||
|
||||
loadKelasList();
|
||||
loadKamarList();
|
||||
loadListTahun();
|
||||
|
||||
$('#modalTambah').modal('show');
|
||||
|
||||
// default foto
|
||||
$('#previewFoto').css('background-image', `url('uploads/siswa/foto.jpg')`);
|
||||
});
|
||||
|
||||
|
||||
// ========================================================
|
||||
// MODAL EDIT
|
||||
// ========================================================
|
||||
$(document).on('click', '.btn-edit', function(){
|
||||
resetModal();
|
||||
let id = $(this).data('id');
|
||||
|
||||
$.ajax({
|
||||
url: "<?= base_url('siswa/detailEdit'); ?>/" + id,
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function(res){
|
||||
|
||||
$('#inputNama').val(res.nama);
|
||||
$('#inputNIS').val(res.nis);
|
||||
$('#inputAlamat').val(res.alamat);
|
||||
$('#inputWali').val(res.nama_wali);
|
||||
$('#inputWhatsapp').val(res.nomor_whatsapp);
|
||||
$('#inputEmail').val(res.email);
|
||||
|
||||
loadKelasList(res.id_kelas);
|
||||
loadKamarList(res.id_kamar);
|
||||
loadListTahun(res.tahun_masuk);
|
||||
|
||||
if(res.foto){
|
||||
$('#previewFoto').css('background-image', `url('uploads/siswa/${res.foto}')`);
|
||||
} else {
|
||||
$('#previewFoto').css('background-image', `url('uploads/siswa/foto.jpg')`);
|
||||
}
|
||||
|
||||
$('#modalTambah .modal-title').text('Edit Santri');
|
||||
$('#btnSimpan').text('Update').data('action','edit').data('id', res.id);
|
||||
|
||||
$('#modalTambah').modal('show');
|
||||
},
|
||||
error: function(){
|
||||
Swal.fire('Error','Gagal memuat data edit.','error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// ========================================================
|
||||
// DELETE
|
||||
// ========================================================
|
||||
$(document).on('click', '.btn-delete', function(){
|
||||
let id = $(this).data('id');
|
||||
|
||||
Swal.fire({
|
||||
title: 'Yakin ingin hapus?',
|
||||
text: "Data tidak dapat dikembalikan!",
|
||||
icon: 'warning',
|
||||
showCancelButton: true,
|
||||
confirmButtonText: 'Ya, hapus',
|
||||
cancelButtonText: 'Batal'
|
||||
}).then((result)=>{
|
||||
if(result.isConfirmed){
|
||||
$.ajax({
|
||||
url: "<?= base_url('siswa/delete'); ?>/" + id,
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function(res){
|
||||
if(res.status){
|
||||
table.ajax.reload(null,false);
|
||||
Swal.fire('Terhapus!', res.message || 'Berhasil dihapus!', 'success');
|
||||
} else {
|
||||
Swal.fire('Gagal', res.message || 'Gagal menghapus!', 'error');
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
Swal.fire('Error','Terjadi kesalahan server.','error');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// ========================================================
|
||||
// FOTO PREVIEW + COMPRESS (SEND COMPRESSED)
|
||||
// ========================================================
|
||||
const fotoDiv = document.getElementById("previewFoto");
|
||||
const fileInput = document.getElementById("imageSantri");
|
||||
|
||||
fotoDiv.addEventListener("click", () => fileInput.click());
|
||||
|
||||
fileInput.addEventListener("change", function(e){
|
||||
const file = e.target.files[0];
|
||||
if(!file || !file.type.startsWith("image/")) return;
|
||||
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(evt){
|
||||
const img = new Image();
|
||||
|
||||
img.onload = function(){
|
||||
const canvas = document.createElement("canvas");
|
||||
let {width, height} = img;
|
||||
const maxDim = 800;
|
||||
|
||||
if(width > maxDim || height > maxDim){
|
||||
if(width > height){
|
||||
height = Math.round(height * maxDim / width);
|
||||
width = maxDim;
|
||||
} else {
|
||||
width = Math.round(width * maxDim / height);
|
||||
height = maxDim;
|
||||
}
|
||||
}
|
||||
|
||||
canvas.width = width;
|
||||
canvas.height = height;
|
||||
|
||||
const ctx = canvas.getContext("2d");
|
||||
ctx.drawImage(img, 0, 0, width, height);
|
||||
|
||||
let quality = 0.7;
|
||||
let compressed = canvas.toDataURL("image/jpeg", quality);
|
||||
|
||||
while(compressed.length/1024 > 250 && quality > 0.1){
|
||||
quality -= 0.05;
|
||||
compressed = canvas.toDataURL("image/jpeg", quality);
|
||||
}
|
||||
|
||||
fotoDiv.style.backgroundImage = `url('${compressed}')`;
|
||||
|
||||
// simpan hasil kompres ke element
|
||||
$('#previewFoto').data('compressed', compressed);
|
||||
};
|
||||
|
||||
img.src = evt.target.result;
|
||||
};
|
||||
|
||||
reader.readAsDataURL(file);
|
||||
});
|
||||
|
||||
|
||||
// ========================================================
|
||||
// SAVE / UPDATE
|
||||
// ========================================================
|
||||
$('#btnSimpan').click(function(){
|
||||
let action = $(this).data('action');
|
||||
let id = $(this).data('id') || '';
|
||||
|
||||
let formData = new FormData();
|
||||
formData.append('id', id);
|
||||
formData.append('nama', $('#inputNama').val());
|
||||
formData.append('nis', $('#inputNIS').val());
|
||||
formData.append('id_kelas', $('#inputKelas').val());
|
||||
formData.append('alamat', $('#inputAlamat').val());
|
||||
formData.append('nama_wali', $('#inputWali').val());
|
||||
formData.append('nomor_whatsapp', $('#inputWhatsapp').val());
|
||||
formData.append('email', $('#inputEmail').val());
|
||||
formData.append('tahun_masuk', $('#inputTahun').val());
|
||||
formData.append('id_kamar', $('#inputKamar').val());
|
||||
|
||||
// Ambil hasil kompres
|
||||
const compressedImage = $('#previewFoto').data('compressed');
|
||||
|
||||
if(compressedImage){
|
||||
formData.append('foto', compressedImage);
|
||||
}
|
||||
|
||||
let url = action === 'add' ? "<?= base_url('siswa/save'); ?>"
|
||||
: "<?= base_url('siswa/update'); ?>";
|
||||
|
||||
$.ajax({
|
||||
url: url,
|
||||
type: 'POST',
|
||||
data: formData,
|
||||
processData: false,
|
||||
contentType: false,
|
||||
dataType: 'json',
|
||||
success: function(res){
|
||||
if(res.status){
|
||||
$('#modalTambah').modal('hide');
|
||||
table.ajax.reload(null,false);
|
||||
Swal.fire('Sukses', res.message || 'Berhasil!', 'success');
|
||||
} else {
|
||||
Swal.fire('Gagal', res.message || 'Gagal!', 'error');
|
||||
}
|
||||
},
|
||||
error: function(){
|
||||
Swal.fire('Error','Terjadi kesalahan server.','error');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
// ========================================================
|
||||
// FUNCTIONS
|
||||
// ========================================================
|
||||
function resetModal(){
|
||||
$('#imageSantri').val('');
|
||||
$('#inputNama,#inputNIS,#inputAlamat,#inputWali,#inputWhatsapp,#inputEmail').val('');
|
||||
$('#inputKelas,#inputKamar,#inputTahun').val('');
|
||||
$('#previewFoto').css('background-image', `url('uploads/siswa/foto.jpg')`);
|
||||
$('#previewFoto').removeData('compressed');
|
||||
}
|
||||
|
||||
function loadKelasList(selectedId=''){
|
||||
$.ajax({
|
||||
url: "<?= base_url('kelas/get_list'); ?>",
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function(res){
|
||||
const select = $('#inputKelas');
|
||||
select.empty().append('<option value="">-- Pilih Kelas --</option>');
|
||||
res.forEach(k=>{
|
||||
select.append(`<option value="${k.id}" ${k.id==selectedId?'selected':''}>${k.nama}</option>`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadKamarList(selectedId=''){
|
||||
$.ajax({
|
||||
url: "<?= base_url('kamar/get_list'); ?>",
|
||||
type: "GET",
|
||||
dataType: "json",
|
||||
success: function(res){
|
||||
const select = $('#inputKamar');
|
||||
select.empty().append('<option value="">-- Pilih Kamar --</option>');
|
||||
res.forEach(k=>{
|
||||
select.append(`<option value="${k.id}" ${k.id==selectedId?'selected':''}>${k.nama} (${k.gedung})</option>`);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadListTahun(selected=''){
|
||||
const select = $('#inputTahun');
|
||||
select.empty().append('<option value="">-- Pilih Tahun --</option>');
|
||||
for(let tahun=2015; tahun<=2030; tahun++){
|
||||
select.append(`<option value="${tahun}" ${tahun==selected?'selected':''}>${tahun}</option>`);
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
</script>
|
||||
|
||||
|
||||
|
||||
<script>
|
||||
$("#btnSelectFile").click(function () {
|
||||
$("#fileImport").click();
|
||||
});
|
||||
|
||||
$("#fileImport").on("change", function () {
|
||||
$("#fileName").text(this.files[0].name);
|
||||
});
|
||||
|
||||
let dropzone = document.getElementById("dropzone");
|
||||
|
||||
dropzone.addEventListener("click", () => $("#fileImport").click());
|
||||
dropzone.addEventListener("dragover", (e) => {
|
||||
e.preventDefault(); dropzone.classList.add("dragover");
|
||||
});
|
||||
dropzone.addEventListener("dragleave", () => dropzone.classList.remove("dragover"));
|
||||
dropzone.addEventListener("drop", (e) => {
|
||||
e.preventDefault(); dropzone.classList.remove("dragover");
|
||||
|
||||
let file = e.dataTransfer.files[0];
|
||||
$("#fileImport")[0].files = e.dataTransfer.files;
|
||||
$("#fileName").text(file.name);
|
||||
});
|
||||
|
||||
$("#btnUpload").click(function () {
|
||||
let file = $("#fileImport")[0].files[0];
|
||||
|
||||
if (!file) {
|
||||
Swal.fire("Oops!", "Silakan pilih file terlebih dahulu!", "warning");
|
||||
return;
|
||||
}
|
||||
|
||||
let formData = new FormData();
|
||||
formData.append("file", file);
|
||||
|
||||
Swal.fire({ title: "Mengupload...", didOpen: () => Swal.showLoading() });
|
||||
|
||||
$.ajax({
|
||||
url: "<?= base_url('import/siswa'); ?>",
|
||||
type: "POST",
|
||||
data: formData,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
success: function () {
|
||||
Swal.fire("Berhasil!", "Data berhasil di-import.", "success");
|
||||
},
|
||||
error: function () {
|
||||
Swal.fire("Error!", "Gagal upload file.", "error");
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
</script>
|
||||
Reference in New Issue
Block a user