MIF_E31230892/sim-pkpps/resources/views/admin/kepulangan/create.blade.php

371 lines
20 KiB
PHP

{{-- resources/views/admin/kepulangan/create.blade.php --}}
@extends('layouts.app')
@section('title', 'Tambah Izin Kepulangan')
@section('content')
<div class="page-header">
<h2><i class="fas fa-plus-circle"></i> Tambah Izin Kepulangan</h2>
</div>
{{-- Info Periode Kuota --}}
<div style="background: #E8F7F2; padding: 15px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 11px;">
<div>
<strong> Periode Kuota:</strong><br>
{{ $settings->periode_mulai->format('d M Y') }} - {{ $settings->periode_akhir->format('d M Y') }}
</div>
<div>
<strong> Kuota Maksimal:</strong><br>
{{ $settings->kuota_maksimal }} Hari / Tahun
</div>
</div>
</div>
@if($errors->any())
<div class="alert alert-danger">
<ul style="margin: 0; padding-left: 20px;">
@foreach($errors->all() as $error)
<li>{{ $error }}</li>
@endforeach
</ul>
</div>
@endif
<div class="content-box">
<form action="{{ route('admin.kepulangan.store') }}" method="POST" id="kepulanganForm">
@csrf
<div class="form-group">
<label for="id_santri">
<i class="fas fa-user form-icon"></i>
Pilih Santri <span style="color: #dc3545;">*</span>
</label>
<select name="id_santri" id="id_santri" class="form-control" required>
<option value="">-- Pilih Santri --</option>
@foreach($santriList as $santri)
<option value="{{ $santri->id_santri }}" {{ old('id_santri') == $santri->id_santri ? 'selected' : '' }}>
{{ $santri->nama_lengkap }} ({{ $santri->id_santri }} - {{ $santri->kelas }})
</option>
@endforeach
</select>
</div>
{{-- Info Santri & Kuota --}}
<div id="santriInfo" style="display: none; background: #f8f9fa; padding: 14px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #6FBA9D;">
<h4 style="margin-top: 0; color: #2C3E50;"> Informasi Santri & Kuota</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;">
<div>
<p style="margin: 5px 0;"><strong>Nama:</strong> <span id="santriNama">-</span></p>
<p style="margin: 5px 0;"><strong>Kelas:</strong> <span id="santriKelas">-</span></p>
<p style="margin: 5px 0;"><strong>Periode:</strong> <span id="santriPeriode">-</span></p>
</div>
<div>
<p style="margin: 5px 0;"><strong>Kuota Maksimal:</strong> <span id="kuotaMaksimal">-</span></p>
<p style="margin: 5px 0;"><strong>Total Terpakai:</strong> <span id="totalTerpakai" class="badge">-</span></p>
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span id="sisaKuota" class="badge">-</span></p>
</div>
</div>
<div style="margin-top: 15px;">
<label style="font-size: 0.9rem; color: #7F8C8D; margin-bottom: 5px;">Penggunaan Kuota:</label>
<div style="width: 100%; height: 20px; background: #E0F0EC; border-radius: 10px; overflow: hidden; position: relative;">
<div id="progressBar" style="height: 100%; width: 0%; background: #28a745; transition: all 0.3s ease; display: flex; align-items: center; justify-content: center; color: white; font-size: 0.75rem; font-weight: 600;"></div>
</div>
<small id="progressText" style="color: #7F8C8D; margin-top: 5px; display: block;">0% dari kuota terpakai</small>
</div>
<div id="warningOverLimit" style="display: none; margin-top: 15px; padding: 12px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; color: #856404;">
<i class="fas fa-exclamation-triangle"></i>
<strong>PERHATIAN:</strong> <span id="warningText"></span>
</div>
</div>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px; margin-bottom: 14px;">
<div class="form-group">
<label for="tanggal_pulang">
<i class="fas fa-calendar-alt form-icon"></i>
Tanggal Pulang <span style="color: #dc3545;">*</span>
</label>
<input type="date" name="tanggal_pulang" id="tanggal_pulang" class="form-control"
value="{{ old('tanggal_pulang', date('Y-m-d')) }}" min="{{ date('Y-m-d') }}" required>
</div>
<div class="form-group">
<label for="tanggal_kembali">
<i class="fas fa-calendar-check form-icon"></i>
Tanggal Kembali <span style="color: #dc3545;">*</span>
</label>
<input type="date" name="tanggal_kembali" id="tanggal_kembali" class="form-control"
value="{{ old('tanggal_kembali') }}" required>
</div>
</div>
{{-- Info Durasi Izin --}}
<div id="durasiInfo" style="display: none; background: #fff3e0; padding: 14px; border-radius: 8px; margin-bottom: 14px; border-left: 4px solid #ff9800;">
<h4 style="margin-top: 0; color: #2C3E50;">Detail Durasi Izin</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: 11px;">
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Durasi Izin</div>
<div id="durasiHari" style="font-size: 2rem; font-weight: 700; color: #ff9800;">0</div>
<div style="font-size: 0.8rem; color: #7F8C8D;">hari</div>
</div>
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Total Setelah Izin</div>
<div id="totalSetelahIzin" style="font-size: 2rem; font-weight: 700; color: #2196f3;">0</div>
<div style="font-size: 0.8rem; color: #7F8C8D;">hari terpakai</div>
</div>
<div style="text-align: center; padding: 15px; background: white; border-radius: 8px;">
<div style="font-size: 0.85rem; color: #7F8C8D; margin-bottom: 5px;">Sisa Kuota</div>
<div id="sisaKuotaSetelah" style="font-size: 2rem; font-weight: 700; color: #28a745;">{{ $settings->kuota_maksimal }}</div>
<div style="font-size: 0.8rem; color: #7F8C8D;">hari tersisa</div>
</div>
</div>
<div id="warningDurasi" style="display: none; margin-top: 15px; padding: 12px; background: #ffebee; border: 1px solid #ffcdd2; border-radius: 6px; color: #c62828;">
<i class="fas fa-exclamation-circle"></i>
<strong>PERHATIAN:</strong> <span id="warningDurasiMessage"></span>
</div>
</div>
<div class="form-group">
<label for="alasan">
<i class="fas fa-comment-alt form-icon"></i>
Alasan Kepulangan <span style="color: #dc3545;">*</span>
</label>
<textarea name="alasan" id="alasan" class="form-control" rows="4"
placeholder="Jelaskan alasan kepulangan" required>{{ old('alasan') }}</textarea>
<small style="color: #7F8C8D; margin-top: 5px; display: block;">
<span id="charCount">0</span>/500 karakter
</small>
</div>
<div style="display: flex; gap: 10px; flex-wrap: wrap;">
<button type="submit" class="btn btn-primary" id="submitBtn">
<i class="fas fa-save"></i> Simpan Izin Kepulangan
</button>
<button type="reset" class="btn btn-secondary">
<i class="fas fa-undo"></i> Reset Form
</button>
<a href="{{ route('admin.kepulangan.index') }}" class="btn btn-danger">
<i class="fas fa-times"></i> Batal
</a>
</div>
</form>
</div>
{{-- Modal Konfirmasi Over Limit --}}
<div class="modal fade" id="overLimitModal" tabindex="-1" style="display: none;">
<div class="modal-dialog">
<div class="modal-content" style="background: white; border-radius: 12px; padding: 14px;">
<div style="margin-bottom: 14px;"><h3 style="margin: 0; color: #2C3E50;">Konfirmasi Izin Melebihi Batas</h3></div>
<div style="padding: 15px; background: #fff3cd; border: 1px solid #ffeaa7; border-radius: 6px; margin-bottom: 15px;">
<i class="fas fa-exclamation-triangle" style="font-size: 2rem; color: #856404; margin-bottom: 10px;"></i>
<h4 style="margin: 10px 0; color: #856404;">Peringatan!</h4>
<p id="overLimitMessage" style="margin: 0; color: #856404;"></p>
</div>
<p style="margin: 15px 0;">Izin tetap bisa diproses, tetapi santri ini akan <strong>melebihi kuota maksimal</strong>.</p>
<div style="display: flex; gap: 10px; justify-content: flex-end; margin-top: 14px;">
<button type="button" class="btn btn-secondary" onclick="closeModal('overLimitModal')">Batal</button>
<button type="button" class="btn btn-warning" id="confirmOverLimit" style="background: #ff9800; border-color: #ff9800;">
<i class="fas fa-check"></i> Ya, Lanjutkan Tetap
</button>
</div>
</div>
</div>
</div>
<style>
.modal.fade { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.5); z-index: 1000; align-items: center; justify-content: center; }
.modal-dialog { max-width: 500px; width: 90%; margin: auto; }
.modal-content { max-height: 90vh; overflow-y: auto; }
.badge { display: inline-block; padding: 4px 10px; border-radius: 4px; font-size: 0.9rem; font-weight: 600; }
</style>
{{-- FIX: Definisikan URL API dari Laravel, bukan hardcode --}}
<script>
const KEPULANGAN_API_URL = "{{ url('admin/kepulangan/api/santri') }}";
const KUOTA_MAKSIMAL = {{ $settings->kuota_maksimal }};
</script>
<script>
let currentSantriData = null;
let isOverLimit = false;
document.getElementById('id_santri').addEventListener('change', function() {
const santriId = this.value;
if (!santriId) {
document.getElementById('santriInfo').style.display = 'none';
currentSantriData = null;
calculateDurasi();
return;
}
const infoDiv = document.getElementById('santriInfo');
infoDiv.style.display = 'block';
infoDiv.innerHTML = '<div style="text-align: center; padding: 14px;"><i class="fas fa-spinner fa-spin"></i> Memuat data santri...</div>';
// ✅ FIX: pakai KEPULANGAN_API_URL dari Laravel
fetch(`${KEPULANGAN_API_URL}/${santriId}`)
.then(response => {
if (!response.ok) throw new Error('Network response was not ok');
return response.json();
})
.then(data => {
if (data.success) {
currentSantriData = data;
updateSantriInfo(data);
calculateDurasi();
} else {
showError(data.message || 'Gagal memuat data santri');
}
})
.catch(error => {
console.error('Error:', error);
showError('Terjadi kesalahan saat memuat data santri: ' + error.message);
});
});
function showError(message) {
const infoDiv = document.getElementById('santriInfo');
infoDiv.innerHTML = `
<div style="padding: 15px; background: #ffebee; border: 1px solid #ffcdd2; border-radius: 6px; color: #c62828;">
<i class="fas fa-exclamation-circle"></i> <strong>Error:</strong> ${message}
</div>`;
currentSantriData = null;
}
function updateSantriInfo(data) {
const santri = data.santri;
const kuota = data.penggunaan_izin;
const infoDiv = document.getElementById('santriInfo');
infoDiv.innerHTML = `
<h4 style="margin-top: 0; color: #2C3E50;">Informasi Santri & Kuota</h4>
<div style="display: grid; grid-template-columns: repeat(auto-fit, minmax(250px, 1fr)); gap: 20px;">
<div>
<p style="margin: 5px 0;"><strong>Nama:</strong> ${santri.nama_lengkap}</p>
<p style="margin: 5px 0;"><strong>Kelas:</strong> ${santri.kelas}</p>
<p style="margin: 5px 0;"><strong>Periode:</strong> ${kuota.periode_mulai} - ${kuota.periode_akhir}</p>
</div>
<div>
<p style="margin: 5px 0;"><strong>Kuota Maksimal:</strong> ${kuota.kuota_maksimal} hari</p>
<p style="margin: 5px 0;"><strong>Total Terpakai:</strong> <span style="display:inline-block;background:${getBadgeColor(kuota.badge_color)};color:${kuota.badge_color==='warning'?'#000':'white'};padding:4px 10px;border-radius:4px;font-weight:600;">${kuota.total_terpakai} hari</span></p>
<p style="margin: 5px 0;"><strong>Sisa Kuota:</strong> <span style="display:inline-block;background:${getBadgeColor(kuota.badge_color)};color:${kuota.badge_color==='warning'?'#000':'white'};padding:4px 10px;border-radius:4px;font-weight:600;">${kuota.sisa_kuota} hari</span></p>
</div>
</div>
<div style="margin-top: 15px;">
<label style="font-size: 0.9rem; color: #7F8C8D; margin-bottom: 5px;">Penggunaan Kuota:</label>
<div style="width: 100%; height: 20px; background: #E0F0EC; border-radius: 10px; overflow: hidden;">
<div style="height:100%;width:${Math.min(100,kuota.persentase)}%;background:${getProgressColor(kuota.persentase)};display:flex;align-items:center;justify-content:center;color:white;font-size:0.75rem;font-weight:600;">${kuota.persentase}%</div>
</div>
<small style="color: #7F8C8D; margin-top: 5px; display: block;">${kuota.persentase}% dari kuota terpakai</small>
</div>
<div style="display:${kuota.status==='melebihi'?'block':'none'};margin-top:15px;padding:12px;background:#fff3cd;border:1px solid #ffeaa7;border-radius:6px;color:#856404;">
<i class="fas fa-exclamation-triangle"></i> <strong>PERHATIAN:</strong> Santri ini sudah melebihi kuota ${kuota.kuota_maksimal} hari! Total terpakai: ${kuota.total_terpakai} hari.
</div>`;
}
function getBadgeColor(badge) {
return { 'success': '#28a745', 'warning': '#ffc107', 'danger': '#dc3545' }[badge] || '#6c757d';
}
function getProgressColor(p) {
return p >= 100 ? '#dc3545' : p >= 80 ? '#ffc107' : '#28a745';
}
document.getElementById('tanggal_pulang').addEventListener('change', calculateDurasi);
document.getElementById('tanggal_kembali').addEventListener('change', calculateDurasi);
function calculateDurasi() {
const tanggalPulang = document.getElementById('tanggal_pulang').value;
const tanggalKembali = document.getElementById('tanggal_kembali').value;
const durasiInfoDiv = document.getElementById('durasiInfo');
if (!tanggalPulang || !tanggalKembali) { durasiInfoDiv.style.display = 'none'; return; }
const startDate = new Date(tanggalPulang);
const endDate = new Date(tanggalKembali);
if (endDate <= startDate) { durasiInfoDiv.style.display = 'none'; return; }
const diffDays = Math.ceil(Math.abs(endDate - startDate) / (1000 * 60 * 60 * 24)) + 1;
durasiInfoDiv.style.display = 'block';
document.getElementById('durasiHari').textContent = diffDays;
let totalSetelah = diffDays;
let sisaSetelah = KUOTA_MAKSIMAL - diffDays;
let showWarning = false, warningMessage = '';
if (currentSantriData) {
const currentUsage = currentSantriData.penggunaan_izin.total_terpakai;
const kuotaMaks = currentSantriData.penggunaan_izin.kuota_maksimal;
totalSetelah = currentUsage + diffDays;
sisaSetelah = kuotaMaks - totalSetelah;
document.getElementById('totalSetelahIzin').textContent = totalSetelah;
document.getElementById('sisaKuotaSetelah').textContent = Math.max(0, sisaSetelah);
if (totalSetelah > kuotaMaks) {
document.getElementById('totalSetelahIzin').style.color = '#dc3545';
document.getElementById('sisaKuotaSetelah').style.color = '#dc3545';
showWarning = true;
warningMessage = `Izin ini akan melebihi batas ${kuotaMaks} hari (Total setelah izin: ${totalSetelah} hari, Kelebihan: ${totalSetelah - kuotaMaks} hari)`;
isOverLimit = true;
} else if (totalSetelah >= kuotaMaks * 0.8) {
document.getElementById('totalSetelahIzin').style.color = '#ff9800';
document.getElementById('sisaKuotaSetelah').style.color = '#ff9800';
showWarning = true;
warningMessage = `Kuota hampir habis! Sisa kuota setelah izin ini hanya ${sisaSetelah} hari.`;
isOverLimit = false;
} else {
document.getElementById('totalSetelahIzin').style.color = '#2196f3';
document.getElementById('sisaKuotaSetelah').style.color = '#28a745';
showWarning = false; isOverLimit = false;
}
}
const warningDiv = document.getElementById('warningDurasi');
warningDiv.style.display = showWarning ? 'block' : 'none';
if (showWarning) document.getElementById('warningDurasiMessage').textContent = warningMessage;
}
document.getElementById('alasan').addEventListener('input', function() {
const counter = document.getElementById('charCount');
counter.textContent = this.value.length;
counter.style.color = this.value.length > 500 ? 'red' : '#7F8C8D';
});
document.getElementById('kepulanganForm').addEventListener('submit', function(e) {
if (isOverLimit) {
e.preventDefault();
const msg = document.getElementById('warningDurasiMessage')?.textContent || 'Izin ini akan melebihi batas kuota';
document.getElementById('overLimitMessage').textContent = msg;
document.getElementById('overLimitModal').style.display = 'flex';
}
});
document.getElementById('confirmOverLimit').addEventListener('click', function() {
closeModal('overLimitModal');
isOverLimit = false;
document.getElementById('kepulanganForm').submit();
});
document.getElementById('tanggal_pulang').addEventListener('change', function() {
const pulangDate = new Date(this.value);
pulangDate.setDate(pulangDate.getDate() + 1);
const minKembali = pulangDate.toISOString().split('T')[0];
document.getElementById('tanggal_kembali').min = minKembali;
const currentKembali = document.getElementById('tanggal_kembali').value;
if (currentKembali && currentKembali <= this.value) document.getElementById('tanggal_kembali').value = minKembali;
});
document.querySelector('button[type="reset"]').addEventListener('click', function() {
setTimeout(() => {
document.getElementById('santriInfo').style.display = 'none';
document.getElementById('durasiInfo').style.display = 'none';
currentSantriData = null; isOverLimit = false;
document.getElementById('charCount').textContent = '0';
}, 100);
});
function closeModal(modalId) { document.getElementById(modalId).style.display = 'none'; }
document.addEventListener('DOMContentLoaded', function() {
document.getElementById('tanggal_pulang').min = new Date().toISOString().split('T')[0];
document.getElementById('charCount').textContent = document.getElementById('alasan').value.length;
calculateDurasi();
});
document.addEventListener('keydown', e => { if (e.key === 'Escape') document.querySelectorAll('.modal.fade').forEach(m => m.style.display = 'none'); });
document.querySelectorAll('.modal.fade').forEach(modal => {
modal.addEventListener('click', function(e) { if (e.target === this) this.style.display = 'none'; });
});
</script>
@endsection