TIF_NGANJUK_E41220778/resources/views/admin/peminjaman/create.blade.php

285 lines
16 KiB
PHP

<x-app-layout>
@section('page-title', $pageTitle)
<div class="d-flex align-items-center mb-4">
<a href="{{ route('admin.peminjaman.index') }}" class="btn btn-outline-secondary me-3">
<i class="bi bi-arrow-left"></i>
</a>
<h3 class="my-0 fw-bold">Formulir Peminjaman Manual</h3>
</div>
<form action="{{ route('admin.peminjaman.store') }}" method="POST" id="formPeminjaman" autocomplete="off"> @csrf
<div class="row g-4">
<div class="col-lg-7">
<div class="card border-0 shadow-sm">
<div class="card-body p-4">
<h5 class="fw-bold mb-3">Data Peminjaman</h5>
<div class="mb-3">
<label for="peminjam_id" class="form-label">Pilih Peminjam (Siswa/Guru) <span class="text-danger">*</span></label>
<select class="form-control @error('peminjam_id') is-invalid @enderror" id="peminjam_id" name="peminjam_id" placeholder="Cari nama atau email...">
<option value="">Pilih...</option>
@foreach ($groupedUsers as $role => $users)
<optgroup label="{{ ucfirst($role) }}">
@foreach ($users as $user)
<option value="{{ $user['id'] }}"
data-role="{{ strtolower($role) }}"
data-identitas="{{ $user['nip'] ?? $user['nisn'] ?? '-' }}"
data-kontak="{{ $user['phone'] ?? '-' }}"
data-info="{{ strtolower($role) == 'guru' ? ($user['jabatan'] ?? 'Guru') : ($user['kelas'] ?? 'Siswa') }}"
{{ $user['disabled'] ? 'disabled' : '' }}
{{ old('peminjam_id') == $user['id'] ? 'selected' : '' }}>
{{ $user['name'] }} {{ $user['status_text'] }}
</option>
@endforeach
</optgroup>
@endforeach
</select>
@error('peminjam_id') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div id="detailPeminjamCard" class="alert alert-secondary d-none mb-3">
<h6 class="fw-bold mb-2 border-bottom pb-1"><i class="bi bi-person-badge me-2"></i>Detail Identitas</h6>
<div class="row small">
<div class="col-6 mb-1"><span class="text-muted">NIP/NISN:</span> <strong id="lblIdentitas">-</strong></div>
<div class="col-6 mb-1"><span class="text-muted">No. HP:</span> <strong id="lblKontak">-</strong></div>
<div class="col-6"><span class="text-muted">Jabatan/Kelas:</span> <strong id="lblInfo">-</strong></div>
<div class="col-6"><span class="text-muted">Role:</span> <strong id="lblRole" class="text-uppercase">-</strong></div>
</div>
</div>
<div class="row g-3">
<div class="col-md-6">
<label for="tanggal_pinjam" class="form-label">Tanggal Pinjam <span class="text-danger">*</span></label>
<input type="text" class="form-control @error('tanggal_pinjam') is-invalid @enderror"
id="tanggal_pinjam" name="tanggal_pinjam" value="{{ old('tanggal_pinjam') }}"
placeholder="Pilih tanggal pinjam" required readonly>
@error('tanggal_pinjam') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
<div class="col-md-6">
<label for="tanggal_kembali" class="form-label">Tenggat Kembali <span class="text-danger">*</span></label>
<input type="text" class="form-control @error('tanggal_kembali') is-invalid @enderror"
id="tanggal_kembali" name="tanggal_kembali" value="{{ old('tanggal_kembali') }}"
placeholder="Pilih tenggat kembali" required readonly>
@error('tanggal_kembali') <div class="invalid-feedback">{{ $message }}</div> @enderror
</div>
</div>
<hr class="my-4">
<div class="d-flex justify-content-between align-items-center mb-3">
<h5 class="fw-bold m-0">Buku Terpilih</h5>
<span class="badge bg-primary-soft" id="counterBuku">0 Buku</span>
</div>
@error('buku_ids')
<div class="alert alert-danger py-2 small">
<i class="bi bi-exclamation-triangle me-1"></i> {{ $message }}
</div>
@enderror
<div id="daftarBukuPinjam" class="mb-3">
<div id="emptyStateBuku" class="text-center text-muted py-4">
<i class="bi bi-collection fs-1" style="opacity: 0.25;"></i>
<p class="mb-0 mt-2">Belum ada buku yang dipilih.</p>
</div>
</div>
<div id="hiddenInputs"></div>
<div class="d-grid">
<button type="submit" class="btn btn-primary">
<i class="bi bi-save me-1"></i> Simpan Peminjaman
</button>
</div>
</div>
</div>
</div>
<div class="col-lg-5">
<div class="card border-0 shadow-sm">
<div class="card-header bg-white py-3">
<h5 class="fw-bold m-0">Pilih Buku</h5>
</div>
<div class="card-body p-4">
<div class="mb-3">
<div class="input-group">
<span class="input-group-text bg-white"><i class="bi bi-search"></i></span>
<input type="text" class="form-control border-start-0" id="searchBuku" placeholder="Cari judul atau penulis...">
</div>
</div>
<div id="bookSelectionList" style="max-height: 600px; overflow-y: auto;">
@foreach ($daftarBuku as $buku)
<div class="book-option p-2" data-book-id="{{ $buku['id'] }}"
data-book-title="{{ strtolower($buku['judul']) }}"
data-book-author="{{ strtolower($buku['penulis']) }}"
data-book-cover="{{ asset($buku['cover']) }}"
data-book-kategori="{{ $buku['kategori'] }}">
<div class="d-flex align-items-center book-item-list"
onclick="toggleBookSelection(this, {{ $buku['id'] }})" style="cursor: pointer;">
<img src="{{ asset($buku['cover']) }}" alt="Cover" class="rounded me-3" style="width: 50px; height: 70px; object-fit: cover;">
<div class="flex-grow-1">
<h6 class="fw-bold mb-1 line-clamp-2">{{ $buku['judul'] }}</h6>
<p class="text-muted small mb-1">{{ $buku['penulis'] }}</p>
<span class="badge bg-info-soft">{{ $buku['kategori'] }}</span>
</div>
<div class="form-check ms-3">
<input class="form-check-input book-checkbox" type="checkbox" value="{{ $buku['id'] }}" id="book-check-{{ $buku['id'] }}" style="pointer-events: none;">
</div>
</div>
</div>
@endforeach
</div>
</div>
</div>
</div>
</div>
</form>
@push('scripts')
<script>
document.addEventListener("DOMContentLoaded", function() {
const tomSelect = new TomSelect("#peminjam_id", {
create: false,
sortField: { field: "text", direction: "asc" },
onChange: function(value) {
const selectedOption = this.options[value];
const detailCard = document.getElementById('detailPeminjamCard');
if(selectedOption && value !== "") {
document.getElementById('lblRole').textContent = selectedOption.dataset.role;
document.getElementById('lblIdentitas').textContent = selectedOption.dataset.identitas;
document.getElementById('lblKontak').textContent = selectedOption.dataset.kontak;
document.getElementById('lblInfo').textContent = selectedOption.dataset.info;
detailCard.classList.remove('d-none');
} else {
detailCard.classList.add('d-none');
}
}
});
const tglPinjam = flatpickr("#tanggal_pinjam", {
dateFormat: "Y-m-d", altInput: true, altFormat: "d/m/Y", defaultDate: "{{ old('tanggal_pinjam', date('Y-m-d')) }}", locale: "id",
onChange: function(selectedDates, dateStr) {
if (selectedDates.length > 0) tglKembali.set("minDate", new Date(selectedDates[0]).fp_incr(1));
}
});
const tglKembali = flatpickr("#tanggal_kembali", {
dateFormat: "Y-m-d", altInput: true, altFormat: "d/m/Y", defaultDate: "{{ old('tanggal_kembali', date('Y-m-d', strtotime('+7 days'))) }}", locale: "id", minDate: new Date().fp_incr(1)
});
const MAX_BOOKS_SISWA = 2;
let selectedBookIds = new Set();
const allBooks = new Map();
document.querySelectorAll('.book-option').forEach(el => {
const id = el.dataset.bookId;
allBooks.set(id, { id: id, title: el.querySelector('h6').textContent, author: el.querySelector('p').textContent, cover: el.dataset.bookCover });
});
const daftarBukuPinjamEl = document.getElementById('daftarBukuPinjam');
const hiddenInputsEl = document.getElementById('hiddenInputs');
const counterBukuEl = document.getElementById('counterBuku');
const emptyStateBukuEl = document.getElementById('emptyStateBuku');
function renderSelectedBooks() {
daftarBukuPinjamEl.querySelectorAll('.selected-book-item').forEach(el => el.remove());
hiddenInputsEl.innerHTML = '';
emptyStateBukuEl.style.display = selectedBookIds.size === 0 ? 'block' : 'none';
selectedBookIds.forEach(id => {
const book = allBooks.get(String(id));
if (!book) return;
const itemHtml = `
<div class="selected-book-item book-item d-flex align-items-start p-3 mb-2 rounded" data-selected-id="${id}">
<img src="${book.cover}" alt="Cover" class="rounded me-3" style="width: 45px; height: 60px; object-fit: cover;">
<div class="flex-grow-1">
<h6 class="fw-bold mb-0 line-clamp-1">${book.title}</h6>
<p class="text-muted small mb-0">${book.author}</p>
</div>
<button type="button" class="btn btn-sm btn-outline-danger remove-book" onclick="removeBook(${id})"><i class="bi bi-trash"></i></button>
</div>`;
daftarBukuPinjamEl.insertAdjacentHTML('beforeend', itemHtml);
hiddenInputsEl.insertAdjacentHTML('beforeend', `<input type="hidden" name="buku_ids[]" value="${id}">`);
});
counterBukuEl.textContent = `${selectedBookIds.size} Buku`;
}
window.toggleBookSelection = function(itemElement, id) {
const selectEl = document.getElementById('peminjam_id');
if(selectEl.value === "") {
alert("Silakan pilih Peminjam (Siswa/Guru) terlebih dahulu sebelum memilih buku!");
return;
}
const selectedOption = selectEl.options[selectEl.selectedIndex];
const roleUser = selectedOption.dataset.role;
const checkbox = itemElement.querySelector('.book-checkbox');
const stringId = String(id);
if (selectedBookIds.has(stringId)) {
selectedBookIds.delete(stringId);
checkbox.checked = false;
itemElement.style.background = 'transparent';
} else {
if (roleUser === 'siswa' && selectedBookIds.size >= MAX_BOOKS_SISWA) {
alert(`Maaf, role Siswa hanya dapat meminjam maksimal ${MAX_BOOKS_SISWA} buku secara bersamaan.`);
return;
}
selectedBookIds.add(stringId);
checkbox.checked = true;
itemElement.style.background = 'rgba(var(--bs-primary-rgb), 0.05)';
}
renderSelectedBooks();
}
window.removeBook = function(id) {
selectedBookIds.delete(String(id));
const itemElement = document.querySelector(`.book-option[data-book-id="${id}"] .book-item-list`);
if (itemElement) {
itemElement.querySelector('.book-checkbox').checked = false;
itemElement.style.background = 'transparent';
}
renderSelectedBooks();
}
document.getElementById('searchBuku').addEventListener('keyup', function() {
const searchTerm = this.value.toLowerCase();
document.querySelectorAll('.book-option').forEach(el => {
const title = el.dataset.bookTitle;
const author = el.dataset.bookAuthor;
el.style.display = (title.includes(searchTerm) || author.includes(searchTerm)) ? 'block' : 'none';
});
});
document.getElementById('formPeminjaman').addEventListener('submit', function() {
modernSwal.fire({
title: 'Memproses...',
allowOutsideClick: false,
didOpen: () => Swal.showLoading()
});
});
// Restore old state if any
@if(old('buku_ids'))
@foreach(old('buku_ids') as $oldId)
selectedBookIds.add("{{ $oldId }}");
const oldItem = document.querySelector(`.book-option[data-book-id="{{ $oldId }}"] .book-item-list`);
if(oldItem) {
oldItem.querySelector('.book-checkbox').checked = true;
oldItem.style.background = 'rgba(var(--bs-primary-rgb), 0.05)';
}
@endforeach
renderSelectedBooks();
@endif
});
</script>
@endpush
</x-app-layout>