feat: Feature peminjaman offline
This commit is contained in:
parent
88490ce78b
commit
172ac9e3b7
|
|
@ -19,6 +19,16 @@ public function index()
|
||||||
$bukuPinjamOffline = DummyDataService::getBukuPinjamOffline($user);
|
$bukuPinjamOffline = DummyDataService::getBukuPinjamOffline($user);
|
||||||
$bacaBukuOnline = DummyDataService::getBacaBukuOnline($user);
|
$bacaBukuOnline = DummyDataService::getBacaBukuOnline($user);
|
||||||
|
|
||||||
|
$hour = date('H');
|
||||||
|
$greeting = "Selamat Pagi";
|
||||||
|
if ($hour >= 12 && $hour < 15) {
|
||||||
|
$greeting = "Selamat Siang";
|
||||||
|
} elseif ($hour >= 15 && $hour < 18) {
|
||||||
|
$greeting = "Selamat Sore";
|
||||||
|
} elseif ($hour >= 18) {
|
||||||
|
$greeting = "Selamat Malam";
|
||||||
|
}
|
||||||
|
|
||||||
return view('dashboard', compact(
|
return view('dashboard', compact(
|
||||||
'user',
|
'user',
|
||||||
'stats',
|
'stats',
|
||||||
|
|
@ -27,7 +37,8 @@ public function index()
|
||||||
'progressMembaca',
|
'progressMembaca',
|
||||||
'statistikBulanan',
|
'statistikBulanan',
|
||||||
'bukuPinjamOffline',
|
'bukuPinjamOffline',
|
||||||
'bacaBukuOnline'
|
'bacaBukuOnline',
|
||||||
|
'greeting',
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -25,7 +25,6 @@ public function index(Request $request, $tipe = null)
|
||||||
'semuaBuku' => $semuaBuku,
|
'semuaBuku' => $semuaBuku,
|
||||||
'filterOptions' => $filterOptions,
|
'filterOptions' => $filterOptions,
|
||||||
'input' => $filters,
|
'input' => $filters,
|
||||||
'tipe' => $tipe,
|
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers;
|
||||||
|
|
||||||
|
use App\Services\DummyDataService;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
|
||||||
|
class PeminjamanController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Menampilkan daftar buku yang bisa dipinjam offline,
|
||||||
|
* dengan memanfaatkan filter dari getKatalogBuku.
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
$filters = $request->only(['search', 'kategori', 'tahun', 'penulis']);
|
||||||
|
$filters['tipe_akses'] = 'offline';
|
||||||
|
$semuaBuku = DummyDataService::getKatalogBuku($filters);
|
||||||
|
$filterOptions = DummyDataService::getFilterOptions();
|
||||||
|
|
||||||
|
return view('peminjaman.index', [
|
||||||
|
'semuaBuku' => $semuaBuku,
|
||||||
|
'filterOptions' => $filterOptions,
|
||||||
|
'input' => $request->query(),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menampilkan halaman ringkasan buku sebelum meminjam.
|
||||||
|
*/
|
||||||
|
public function ringkasan($id)
|
||||||
|
{
|
||||||
|
// Untuk simulasi, kita anggap user sudah login
|
||||||
|
// $user = Auth::user();
|
||||||
|
$user = DummyDataService::getAllSiswa()[0];
|
||||||
|
|
||||||
|
$buku = DummyDataService::getKatalogBuku()->firstWhere('id', $id);
|
||||||
|
|
||||||
|
return view('peminjaman.ringkasan', compact('user', 'buku'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menampilkan form peminjaman dengan semua buku offline untuk pilihan tambahan.
|
||||||
|
*/
|
||||||
|
public function form($id)
|
||||||
|
{
|
||||||
|
// $user = Auth::user();
|
||||||
|
$user = DummyDataService::getAllSiswa()[0];
|
||||||
|
|
||||||
|
// Buku yang dipilih pertama kali
|
||||||
|
$buku = DummyDataService::getKatalogBuku()->firstWhere('id', $id);
|
||||||
|
|
||||||
|
// Semua buku offline untuk pilihan tambahan
|
||||||
|
$filters = ['tipe_akses' => 'offline'];
|
||||||
|
$semuaBuku = DummyDataService::getKatalogBuku($filters);
|
||||||
|
|
||||||
|
return view('peminjaman.form', compact('user', 'buku', 'semuaBuku'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proses pengiriman form peminjaman multi buku
|
||||||
|
*/
|
||||||
|
public function store(Request $request)
|
||||||
|
{
|
||||||
|
// Validasi input
|
||||||
|
$request->validate([
|
||||||
|
'buku_ids' => 'required|array|min:1|max:3',
|
||||||
|
'buku_ids.*' => 'integer|exists:books,id' // Sesuaikan dengan tabel yang ada
|
||||||
|
]);
|
||||||
|
|
||||||
|
// Logic untuk menyimpan peminjaman multiple books
|
||||||
|
$bukuIds = $request->input('buku_ids');
|
||||||
|
|
||||||
|
// Contoh logic penyimpanan:
|
||||||
|
foreach ($bukuIds as $bukuId) {
|
||||||
|
// Simpan ke database peminjaman
|
||||||
|
// Peminjaman::create([
|
||||||
|
// 'user_id' => auth()->id(),
|
||||||
|
// 'book_id' => $bukuId,
|
||||||
|
// 'tanggal_pinjam' => now(),
|
||||||
|
// 'tanggal_kembali' => now()->addDays(7),
|
||||||
|
// 'status' => 'dipinjam'
|
||||||
|
// ]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()->route('dashboard')
|
||||||
|
->with('success', 'Berhasil meminjam ' . count($bukuIds) . ' buku!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -10,11 +10,13 @@ public static function getAllSiswa(): array
|
||||||
[
|
[
|
||||||
'id' => 1,
|
'id' => 1,
|
||||||
'nisn' => '1234567890',
|
'nisn' => '1234567890',
|
||||||
'nama_lengkap' => 'John Doe',
|
'nama_lengkap' => 'Silvi Rahmawati',
|
||||||
'email' => 'johnskuy@smkn1perpus.sch.id',
|
'email' => 'silvi.rahmawati@smkn1perpus.sch.id',
|
||||||
'nomor_hp' => '081234567890',
|
'nomor_hp' => '08123456789',
|
||||||
'password' => 'password',
|
'password' => 'password',
|
||||||
'role' => 'siswa',
|
'role' => 'siswa',
|
||||||
|
'kelas' => 'XII RPL',
|
||||||
|
'golongan' => 'A',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => 2,
|
'id' => 2,
|
||||||
|
|
@ -33,6 +35,8 @@ public static function getAllSiswa(): array
|
||||||
'nomor_hp' => '081998877665',
|
'nomor_hp' => '081998877665',
|
||||||
'password' => 'password',
|
'password' => 'password',
|
||||||
'role' => 'siswa',
|
'role' => 'siswa',
|
||||||
|
'kelas' => 'XII RPL A',
|
||||||
|
'golongan' => 'A',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => 4,
|
'id' => 4,
|
||||||
|
|
@ -42,6 +46,8 @@ public static function getAllSiswa(): array
|
||||||
'nomor_hp' => '081556677889',
|
'nomor_hp' => '081556677889',
|
||||||
'password' => 'password',
|
'password' => 'password',
|
||||||
'role' => 'siswa',
|
'role' => 'siswa',
|
||||||
|
'kelas' => 'XII RPL A',
|
||||||
|
'golongan' => 'A',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => 5,
|
'id' => 5,
|
||||||
|
|
@ -152,7 +158,7 @@ private static function getAllBooks()
|
||||||
'tahun' => 2023,
|
'tahun' => 2023,
|
||||||
'status' => 'Tersedia',
|
'status' => 'Tersedia',
|
||||||
'is_new' => false,
|
'is_new' => false,
|
||||||
'tipe_akses' => 'online',
|
'tipe_akses' => ['online', 'offline'],
|
||||||
'progress' => 100,
|
'progress' => 100,
|
||||||
'user_id' => [3, 1],
|
'user_id' => [3, 1],
|
||||||
],
|
],
|
||||||
|
|
@ -289,6 +295,8 @@ public static function getBacaBukuOnline($user): array
|
||||||
/**
|
/**
|
||||||
* Mengambil daftar buku untuk katalog dengan filter.
|
* Mengambil daftar buku untuk katalog dengan filter.
|
||||||
*/
|
*/
|
||||||
|
// app/Services/DummyDataService.php
|
||||||
|
|
||||||
public static function getKatalogBuku(array $filters = []): \Illuminate\Support\Collection
|
public static function getKatalogBuku(array $filters = []): \Illuminate\Support\Collection
|
||||||
{
|
{
|
||||||
$buku = self::getAllBooks();
|
$buku = self::getAllBooks();
|
||||||
|
|
@ -301,9 +309,21 @@ public static function getKatalogBuku(array $filters = []): \Illuminate\Support\
|
||||||
return $query->where('tahun', $tahun);
|
return $query->where('tahun', $tahun);
|
||||||
})->when($filters['penulis'] ?? null, function ($query, $penulis) {
|
})->when($filters['penulis'] ?? null, function ($query, $penulis) {
|
||||||
return $query->where('penulis', $penulis);
|
return $query->where('penulis', $penulis);
|
||||||
})->when($filters['tipe'] ?? null, function ($query, $tipe) {
|
})
|
||||||
return $query->where('tipe_akses', $tipe);
|
->when($filters['tipe_akses'] ?? null, function ($query, $tipe) {
|
||||||
|
if ($tipe === 'offline') {
|
||||||
|
return $query->filter(function ($buku) {
|
||||||
|
return $buku['tipe_akses'] === 'offline' || (is_array($buku['tipe_akses']) && in_array('offline', $buku['tipe_akses']));
|
||||||
});
|
});
|
||||||
|
}
|
||||||
|
if ($tipe === 'online') {
|
||||||
|
return $query->filter(function ($buku) {
|
||||||
|
return $buku['tipe_akses'] === 'online' || (is_array($buku['tipe_akses']) && in_array('online', $buku['tipe_akses']));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return $query;
|
||||||
|
})
|
||||||
|
->sortByDesc('status');
|
||||||
|
|
||||||
return $buku;
|
return $buku;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,83 @@
|
||||||
|
// public/js/dashboard-charts.js
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
// Ambil elemen canvas Bar Chart
|
||||||
|
const barChartEl = document.getElementById('barChart');
|
||||||
|
if (barChartEl) {
|
||||||
|
const statistikData = JSON.parse(barChartEl.dataset.stats);
|
||||||
|
|
||||||
|
new Chart(barChartEl.getContext('2d'), {
|
||||||
|
type: 'bar',
|
||||||
|
data: {
|
||||||
|
labels: statistikData.labels,
|
||||||
|
datasets: [{
|
||||||
|
label: 'Buku Dibaca',
|
||||||
|
backgroundColor: '#435ebe',
|
||||||
|
data: statistikData.data,
|
||||||
|
borderRadius: 8
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
scales: {
|
||||||
|
y: {
|
||||||
|
beginAtZero: true,
|
||||||
|
grid: {
|
||||||
|
color: 'rgba(0,0,0,0.05)',
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
color: '#6c757d',
|
||||||
|
font: {
|
||||||
|
size: 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
x: {
|
||||||
|
grid: {
|
||||||
|
display: false,
|
||||||
|
},
|
||||||
|
ticks: {
|
||||||
|
color: '#6c757d',
|
||||||
|
font: {
|
||||||
|
size: 12
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const donutChartEl = document.getElementById('donutChart');
|
||||||
|
if (donutChartEl) {
|
||||||
|
const progressData = JSON.parse(donutChartEl.dataset.progress);
|
||||||
|
|
||||||
|
new Chart(donutChartEl.getContext('2d'), {
|
||||||
|
type: 'doughnut',
|
||||||
|
data: {
|
||||||
|
labels: ['Telah Dibaca', 'Belum Dibaca'],
|
||||||
|
datasets: [{
|
||||||
|
data: [progressData.selesai, progressData.sisa],
|
||||||
|
backgroundColor: ['#435ebe', '#e9ecef'],
|
||||||
|
borderColor: ['#ffffff'],
|
||||||
|
borderWidth: 3,
|
||||||
|
}]
|
||||||
|
},
|
||||||
|
options: {
|
||||||
|
responsive: true,
|
||||||
|
maintainAspectRatio: false,
|
||||||
|
plugins: {
|
||||||
|
legend: {
|
||||||
|
display: false
|
||||||
|
}
|
||||||
|
},
|
||||||
|
cutout: '75%'
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
@ -1,8 +1,9 @@
|
||||||
import './bootstrap';
|
import './bootstrap';
|
||||||
import 'bootstrap';
|
import './peminjaman-form.js';
|
||||||
|
import * as bootstrap from 'bootstrap';
|
||||||
|
|
||||||
|
window.bootstrap = bootstrap;
|
||||||
|
|
||||||
import Alpine from 'alpinejs';
|
import Alpine from 'alpinejs';
|
||||||
|
|
||||||
window.Alpine = Alpine;
|
window.Alpine = Alpine;
|
||||||
|
|
||||||
Alpine.start();
|
Alpine.start();
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
const formPeminjamanElement = document.getElementById('formPeminjaman');
|
||||||
|
|
||||||
|
if (formPeminjamanElement) {
|
||||||
|
// Ambil data yang sudah disimpan di elemen HTML
|
||||||
|
const semuaBuku = JSON.parse(formPeminjamanElement.dataset.semuaBuku);
|
||||||
|
const bukuAwal = JSON.parse(formPeminjamanElement.dataset.bukuAwal);
|
||||||
|
|
||||||
|
let bukuTerpilih = [bukuAwal.id];
|
||||||
|
const maxBuku = 3;
|
||||||
|
|
||||||
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
|
updateCounter();
|
||||||
|
updateSelectedBooks();
|
||||||
|
updateCheckboxes();
|
||||||
|
updateBtnTambahBuku();
|
||||||
|
updateDaftarBuku();
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateCounter() {
|
||||||
|
document.getElementById('counterBuku').textContent = bukuTerpilih.length;
|
||||||
|
document.getElementById('sisaSlot').textContent = maxBuku - bukuTerpilih.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateBtnTambahBuku() {
|
||||||
|
const btnTambah = document.getElementById('btnTambahBuku');
|
||||||
|
if (bukuTerpilih.length >= maxBuku) {
|
||||||
|
btnTambah.classList.add('disabled');
|
||||||
|
btnTambah.innerHTML = '<i class="bi bi-check-circle me-1"></i>Maksimal Buku Tercapai';
|
||||||
|
} else {
|
||||||
|
btnTambah.classList.remove('disabled');
|
||||||
|
btnTambah.innerHTML = '<i class="bi bi-plus-circle me-1"></i>Tambah Buku';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateSelectedBooks() {
|
||||||
|
const container = document.getElementById('selectedBooks');
|
||||||
|
const selected = semuaBuku.filter(book => bukuTerpilih.includes(book.id));
|
||||||
|
container.innerHTML = selected.map(book => `<li>${book.judul}</li>`).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateCheckboxes() {
|
||||||
|
document.querySelectorAll('.book-checkbox').forEach(checkbox => {
|
||||||
|
const bookId = parseInt(checkbox.value);
|
||||||
|
checkbox.checked = bukuTerpilih.includes(bookId);
|
||||||
|
|
||||||
|
if (bukuTerpilih.length >= maxBuku && !bukuTerpilih.includes(bookId)) {
|
||||||
|
checkbox.disabled = true;
|
||||||
|
} else if (bookId !== bukuAwal.id) {
|
||||||
|
checkbox.disabled = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
window.toggleBookSelection = function (bookId) {
|
||||||
|
if (bookId === bukuAwal.id) return;
|
||||||
|
|
||||||
|
const checkbox = document.getElementById('book' + bookId);
|
||||||
|
if (!checkbox.disabled) {
|
||||||
|
checkbox.checked = !checkbox.checked;
|
||||||
|
handleCheckboxChange(checkbox);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function handleCheckboxChange(checkbox) {
|
||||||
|
const bookId = parseInt(checkbox.value);
|
||||||
|
if (checkbox.checked) {
|
||||||
|
if (bukuTerpilih.length < maxBuku && !bukuTerpilih.includes(bookId)) {
|
||||||
|
bukuTerpilih.push(bookId);
|
||||||
|
} else {
|
||||||
|
checkbox.checked = false;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
bukuTerpilih = bukuTerpilih.filter(id => id !== bookId);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateCounter();
|
||||||
|
updateSelectedBooks();
|
||||||
|
updateCheckboxes();
|
||||||
|
updateBtnTambahBuku();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.addEventListener('change', function (e) {
|
||||||
|
if (e.target.classList.contains('book-checkbox')) {
|
||||||
|
if (e.target.value != bukuAwal.id) {
|
||||||
|
handleCheckboxChange(e.target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('searchBuku')?.addEventListener('input', function (e) {
|
||||||
|
const searchTerm = e.target.value.toLowerCase();
|
||||||
|
document.querySelectorAll('.book-option').forEach(option => {
|
||||||
|
const title = option.getAttribute('data-book-title');
|
||||||
|
const author = option.getAttribute('data-book-author');
|
||||||
|
|
||||||
|
if (title.includes(searchTerm) || author.includes(searchTerm)) {
|
||||||
|
option.style.display = 'block';
|
||||||
|
} else {
|
||||||
|
option.style.display = 'none';
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateDaftarBuku() {
|
||||||
|
const container = document.getElementById('daftarBukuPinjam');
|
||||||
|
const hiddenInputs = document.getElementById('hiddenInputs');
|
||||||
|
const selected = semuaBuku.filter(book => bukuTerpilih.includes(book.id));
|
||||||
|
|
||||||
|
container.innerHTML = selected.map((book) => `
|
||||||
|
<div class="book-item border rounded p-3 mb-3 shadow-sm" data-book-id="${book.id}">
|
||||||
|
<div class="d-flex align-items-start">
|
||||||
|
|
||||||
|
<img src="/${book.cover}" alt="Cover"
|
||||||
|
class="rounded me-3 form-book-cover"
|
||||||
|
style="width: 60px; height: 80px; object-fit: cover;">
|
||||||
|
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<h6 class="fw-bold mb-1">${book.judul}</h6>
|
||||||
|
<p class="text-muted small mb-1">${book.penulis}</p>
|
||||||
|
<span class="badge bg-info">${book.kategori}</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-flex flex-column align-items-end gap-2">
|
||||||
|
${book.id === bukuAwal.id
|
||||||
|
? '<span class="badge bg-success">Buku Utama</span>'
|
||||||
|
: '<span class="badge bg-primary">Tambahan</span>'}
|
||||||
|
|
||||||
|
${book.id !== bukuAwal.id
|
||||||
|
? `<button type="button" class="btn btn-sm btn-outline-danger remove-book"
|
||||||
|
onclick="removeBuku(${book.id})"
|
||||||
|
title="Hapus Buku">
|
||||||
|
<i class="bi bi-trash"></i>
|
||||||
|
</button>`
|
||||||
|
: ''}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
`).join('');
|
||||||
|
|
||||||
|
|
||||||
|
hiddenInputs.innerHTML = bukuTerpilih.map(id =>
|
||||||
|
`<input type="hidden" name="buku_ids[]" value="${id}">`
|
||||||
|
).join('');
|
||||||
|
}
|
||||||
|
|
||||||
|
window.removeBuku = function (bookId) {
|
||||||
|
if (bookId !== bukuAwal.id) {
|
||||||
|
bukuTerpilih = bukuTerpilih.filter(id => id !== bookId);
|
||||||
|
updateDaftarBuku();
|
||||||
|
updateCounter();
|
||||||
|
updateSelectedBooks();
|
||||||
|
updateCheckboxes();
|
||||||
|
updateBtnTambahBuku();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
window.konfirmasiPilihanBuku = function () {
|
||||||
|
updateDaftarBuku();
|
||||||
|
const modal = bootstrap.Modal.getInstance(document.getElementById('pilihBukuModal'));
|
||||||
|
modal.hide();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('konfirmasiModal')?.addEventListener('show.bs.modal', function () {
|
||||||
|
const selected = semuaBuku.filter(book => bukuTerpilih.includes(book.id));
|
||||||
|
const ringkasan = selected.map((book, index) =>
|
||||||
|
`<div class="d-flex justify-content-between">
|
||||||
|
<span>${index + 1}. ${book.judul}</span>
|
||||||
|
<small class="text-muted">${book.penulis}</small>
|
||||||
|
</div>`
|
||||||
|
).join('');
|
||||||
|
document.getElementById('ringkasanBuku').innerHTML = ringkasan;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.kirimForm = function () {
|
||||||
|
document.getElementById('formPeminjaman').submit();
|
||||||
|
}
|
||||||
|
|
||||||
|
document.getElementById('pilihBukuModal')?.addEventListener('hidden.bs.modal', function () {
|
||||||
|
const searchInput = document.getElementById('searchBuku');
|
||||||
|
if (searchInput) {
|
||||||
|
searchInput.value = '';
|
||||||
|
document.querySelectorAll('.book-option').forEach(option => {
|
||||||
|
option.style.display = 'block';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
@ -1,128 +1,139 @@
|
||||||
$primary: #435ebe;
|
// ===================================
|
||||||
$secondary: #6c757d;
|
// VARIABLES & MAPS
|
||||||
$success: #198754;
|
// ===================================
|
||||||
$info: #0dcaf0;
|
|
||||||
$warning: #ffc107;
|
|
||||||
$danger: #dc3545;
|
|
||||||
$light: #f4f7f8;
|
|
||||||
$dark: #212529;
|
|
||||||
|
|
||||||
// Derived colors untuk background light
|
// Theme Colors Map
|
||||||
$primary-light: rgba($primary, 0.1);
|
$theme-colors: (
|
||||||
$success-light: rgba($success, 0.1);
|
"primary": #435ebe,
|
||||||
$warning-light: rgba($warning, 0.1);
|
"secondary": mix(#6c757d, #ffffff, 80%),
|
||||||
$danger-light: rgba($danger, 0.1);
|
"success": mix(#198754, #ffffff, 85%),
|
||||||
$info-light: rgba($info, 0.1);
|
"info": mix(#0dcaf0, #ffffff, 80%),
|
||||||
$secondary-light: rgba($secondary, 0.1);
|
"warning": mix(#ffc107, #ffffff, 80%),
|
||||||
|
"danger": mix(#dc3545, #ffffff, 80%),
|
||||||
|
);
|
||||||
|
|
||||||
// Border radius
|
// Gray Colors Map
|
||||||
|
$grays: (
|
||||||
|
"light": #f4f7f8,
|
||||||
|
"dark": #4c5053
|
||||||
|
);
|
||||||
|
|
||||||
|
// Spacing & Sizing
|
||||||
$border-radius: 0.5rem;
|
$border-radius: 0.5rem;
|
||||||
$card-box-shadow: 0 0 1.25rem rgba(33,37,41,.05);
|
|
||||||
|
|
||||||
$border-radius-sm: 0.25rem;
|
$border-radius-sm: 0.25rem;
|
||||||
$border-radius-lg: 1rem;
|
$border-radius-lg: 1rem;
|
||||||
|
|
||||||
|
// Shadows & Transitions
|
||||||
|
$card-box-shadow: 0 0 1.25rem rgba(33, 37, 41, 0.05);
|
||||||
$shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.08);
|
$shadow-sm: 0 2px 4px rgba(0, 0, 0, 0.08);
|
||||||
$shadow-md: 0 4px 8px rgba(0, 0, 0, 0.12);
|
$shadow-md: 0 4px 8px rgba(0, 0, 0, 0.12);
|
||||||
$shadow-lg: 0 8px 20px rgba(0, 0, 0, 0.15);
|
$shadow-lg: 0 8px 20px rgba(0, 0, 0, 0.15);
|
||||||
$transition: all 0.3s ease;
|
$transition: all 0.3s ease;
|
||||||
|
|
||||||
// ===================================
|
// ===================================
|
||||||
// CARD COMPONENTS
|
// UTILITIES (GENERATED FROM MAPS)
|
||||||
|
// ===================================
|
||||||
|
@each $color, $value in $theme-colors {
|
||||||
|
.bg-#{$color}-light {
|
||||||
|
background-color: rgba($value, 0.25) !important;
|
||||||
|
}
|
||||||
|
.bg-#{$color}-soft {
|
||||||
|
background-color: rgba($value, 0.25);
|
||||||
|
color: $value;
|
||||||
|
}
|
||||||
|
.alert-#{$color} {
|
||||||
|
background-color: rgba($value, 0.2);
|
||||||
|
color: darken($value, 25%);
|
||||||
|
border-color: rgba($value, 0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================
|
||||||
|
// BASE COMPONENTS
|
||||||
// ===================================
|
// ===================================
|
||||||
|
|
||||||
.card {
|
.card {
|
||||||
box-shadow: $card-box-shadow;
|
box-shadow: $card-box-shadow;
|
||||||
|
|
||||||
.card-header {
|
.card-header {
|
||||||
&.bg-white {
|
background-color: #fff;
|
||||||
background-color: #fff !important;
|
border-bottom: 1px solid rgba(map-get($grays, "dark"), 0.1); // DIPERBAIKI
|
||||||
border-bottom: 1px solid rgba($secondary, 0.125);
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.alert {
|
||||||
|
border-radius: $border-radius;
|
||||||
|
box-shadow: $shadow-sm;
|
||||||
|
.alert-icon {
|
||||||
|
width: 24px;
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
.modal-content {
|
||||||
|
border: none;
|
||||||
|
border-radius: $border-radius-lg;
|
||||||
|
box-shadow: 0 20px 40px rgba(0, 0, 0, 0.15);
|
||||||
|
.modal-header,
|
||||||
|
.modal-footer {
|
||||||
|
border-color: rgba(map-get($grays, "dark"), 0.1);
|
||||||
|
padding: 1.5rem;
|
||||||
|
}
|
||||||
|
.modal-title {
|
||||||
|
color: map-get($grays, "dark"); // DIPERBAIKI
|
||||||
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn{
|
||||||
|
padding: 0.5rem 1.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
&.btn-sm {
|
||||||
|
padding: 0.375rem 1.25rem;
|
||||||
|
font-size: 0.875rem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.badge.rounded-pill {
|
||||||
|
font-weight: 500;
|
||||||
|
padding: 0.5rem 1rem;
|
||||||
|
}
|
||||||
|
|
||||||
// ===================================
|
// ===================================
|
||||||
// ICON COMPONENTS
|
// CUSTOM COMPONENTS
|
||||||
// ===================================
|
// ===================================
|
||||||
|
|
||||||
|
.icon-circle, .icon-box {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
transition: $transition;
|
||||||
|
}
|
||||||
|
|
||||||
.icon-circle {
|
.icon-circle {
|
||||||
width: 50px;
|
width: 50px;
|
||||||
height: 50px;
|
height: 50px;
|
||||||
border-radius: $border-radius;
|
border-radius: 50%;
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
transition: $transition;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.section-icon,
|
.icon-box {
|
||||||
.chart-icon,
|
|
||||||
.notification-icon,
|
|
||||||
.activity-icon {
|
|
||||||
width: 40px;
|
width: 40px;
|
||||||
height: 40px;
|
height: 40px;
|
||||||
border-radius: 10px;
|
border-radius: 10px;
|
||||||
background-color: $primary-light;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
transition: $transition;
|
|
||||||
|
|
||||||
i {
|
i {
|
||||||
font-size: 1.2rem;
|
font-size: 1.2rem;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================
|
|
||||||
// BACKGROUND COLORS
|
|
||||||
// ===================================
|
|
||||||
|
|
||||||
// Light backgrounds for icon circles
|
|
||||||
.bg-primary-light { background-color: $primary-light; }
|
|
||||||
.bg-success-light { background-color: $success-light; }
|
|
||||||
.bg-warning-light { background-color: $warning-light; }
|
|
||||||
.bg-danger-light { background-color: $danger-light; }
|
|
||||||
.bg-info-light { background-color: $info-light; }
|
|
||||||
.bg-secondary-light { background-color: $secondary-light; }
|
|
||||||
|
|
||||||
// Soft badge colors
|
|
||||||
.bg-primary-soft {
|
|
||||||
background-color: $primary-light;
|
|
||||||
color: $primary;
|
|
||||||
}
|
|
||||||
.bg-success-soft {
|
|
||||||
background-color: $success-light;
|
|
||||||
color: $success;
|
|
||||||
}
|
|
||||||
.bg-warning-soft {
|
|
||||||
background-color: $warning-light;
|
|
||||||
color: $warning;
|
|
||||||
}
|
|
||||||
.bg-danger-soft {
|
|
||||||
background-color: $danger-light;
|
|
||||||
color: $danger;
|
|
||||||
}
|
|
||||||
.bg-info-soft {
|
|
||||||
background-color: $info-light;
|
|
||||||
color: $info;
|
|
||||||
}
|
|
||||||
.bg-secondary-soft {
|
|
||||||
background-color: $secondary-light;
|
|
||||||
color: $secondary;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================================
|
|
||||||
// BOOK COMPONENTS
|
|
||||||
// ===================================
|
|
||||||
|
|
||||||
.book-card {
|
.book-card {
|
||||||
transition: $transition;
|
transition: $transition;
|
||||||
box-shadow: $card-box-shadow;
|
box-shadow: $card-box-shadow;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
transform: translateY(-2px);
|
transform: translateY(-2px);
|
||||||
box-shadow: $shadow-md !important;
|
box-shadow: $shadow-md;
|
||||||
|
|
||||||
.book-cover {
|
.book-cover {
|
||||||
transform: scale(1.03);
|
transform: scale(1.03);
|
||||||
}
|
}
|
||||||
|
|
@ -132,180 +143,169 @@ $transition: all 0.3s ease;
|
||||||
.book-cover {
|
.book-cover {
|
||||||
transition: $transition;
|
transition: $transition;
|
||||||
border-radius: $border-radius-sm;
|
border-radius: $border-radius-sm;
|
||||||
|
|
||||||
&-container {
|
&-container {
|
||||||
background: linear-gradient(135deg, rgba($light, 0.5) 0%, rgba($light, 0.8) 100%);
|
background: linear-gradient(
|
||||||
|
135deg,
|
||||||
|
rgba(map-get($grays, "light"), 0.5) 0%, // DIPERBAIKI
|
||||||
|
rgba(map-get($grays, "light"), 0.8) 100% // DIPERBAIKI
|
||||||
|
);
|
||||||
border-radius: $border-radius-sm 0 0 $border-radius-sm;
|
border-radius: $border-radius-sm 0 0 $border-radius-sm;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// ===================================
|
|
||||||
// ALERT COMPONENTS
|
|
||||||
// ===================================
|
|
||||||
|
|
||||||
.alert {
|
|
||||||
border-radius: $border-radius;
|
|
||||||
box-shadow: $shadow-sm;
|
|
||||||
|
|
||||||
.alert-icon {
|
|
||||||
width: 24px;
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
justify-content: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
&.alert-primary {
|
|
||||||
background-color: rgba($primary, 0.1);
|
|
||||||
color: darken($primary, 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.alert-success {
|
|
||||||
background-color: rgba($success, 0.1);
|
|
||||||
color: darken($success, 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.alert-warning {
|
|
||||||
background-color: rgba($warning, 0.1);
|
|
||||||
color: darken($warning, 20%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.alert-danger {
|
|
||||||
background-color: rgba($danger, 0.1);
|
|
||||||
color: darken($danger, 10%);
|
|
||||||
}
|
|
||||||
|
|
||||||
&.alert-info {
|
|
||||||
background-color: rgba($info, 0.1);
|
|
||||||
color: darken($info, 10%);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================================
|
|
||||||
// SECTION COMPONENTS
|
|
||||||
// ===================================
|
|
||||||
|
|
||||||
.section-header {
|
.section-header {
|
||||||
padding-bottom: 15px;
|
padding-bottom: 15px;
|
||||||
border-bottom: 2px solid $light;
|
border-bottom: 2px solid map-get($grays, "light"); // DIPERBAIKI
|
||||||
|
|
||||||
h5 {
|
h5 {
|
||||||
color: $dark;
|
color: map-get($grays, "dark"); // DIPERBAIKI
|
||||||
font-weight: 700;
|
font-weight: 700;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ===================================
|
|
||||||
// MODAL COMPONENTS
|
|
||||||
// ===================================
|
|
||||||
|
|
||||||
.modal {
|
|
||||||
.modal-content {
|
|
||||||
border: none;
|
|
||||||
border-radius: $border-radius-lg;
|
|
||||||
box-shadow: 0 20px 40px rgba(0,0,0,0.15);
|
|
||||||
|
|
||||||
.modal-header {
|
|
||||||
border-bottom: 1px solid rgba($secondary, 0.125);
|
|
||||||
padding: 1.5rem;
|
|
||||||
|
|
||||||
.modal-title {
|
|
||||||
color: $dark;
|
|
||||||
font-weight: 700;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.modal-footer {
|
|
||||||
border-top: 1px solid rgba($secondary, 0.125);
|
|
||||||
padding: 1.5rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================================
|
|
||||||
// UTILITY CLASSES
|
|
||||||
// ===================================
|
|
||||||
|
|
||||||
.line-clamp-2 {
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 2;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
.line-clamp-3 {
|
|
||||||
display: -webkit-box;
|
|
||||||
-webkit-line-clamp: 3;
|
|
||||||
-webkit-box-orient: vertical;
|
|
||||||
overflow: hidden;
|
|
||||||
line-height: 1.4;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Rounded buttons
|
|
||||||
.btn {
|
|
||||||
&.rounded-pill {
|
|
||||||
border-radius: 50px;
|
|
||||||
padding: 0.5rem 1.5rem;
|
|
||||||
font-weight: 500;
|
|
||||||
|
|
||||||
&.btn-sm {
|
|
||||||
padding: 0.375rem 1.25rem;
|
|
||||||
font-size: 0.875rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Badge
|
|
||||||
.badge {
|
|
||||||
&.rounded-pill {
|
|
||||||
font-weight: 500;
|
|
||||||
padding: 0.5rem 1rem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================================
|
|
||||||
// SCROLLBAR CUSTOMIZATION
|
|
||||||
// ===================================
|
|
||||||
|
|
||||||
.modal-dialog-scrollable .modal-body {
|
|
||||||
&::-webkit-scrollbar {
|
|
||||||
width: 6px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-track {
|
|
||||||
background: #f1f1f1;
|
|
||||||
border-radius: 3px;
|
|
||||||
}
|
|
||||||
|
|
||||||
&::-webkit-scrollbar-thumb {
|
|
||||||
background: #c1c1c1;
|
|
||||||
border-radius: 3px;
|
|
||||||
|
|
||||||
&:hover {
|
|
||||||
background: #a8a8a8;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ===================================
|
|
||||||
// EMPTY STATES
|
|
||||||
// ===================================
|
|
||||||
|
|
||||||
.empty-state {
|
.empty-state {
|
||||||
text-align: center;
|
text-align: center;
|
||||||
padding: 3rem 1rem;
|
padding: 3rem 1rem;
|
||||||
|
|
||||||
i {
|
i {
|
||||||
font-size: 4rem;
|
font-size: 4rem;
|
||||||
color: $secondary;
|
color: map-get($grays, "dark"); // DIPERBAIKI
|
||||||
margin-bottom: 1rem;
|
margin-bottom: 1rem;
|
||||||
opacity: 0.5;
|
opacity: 0.25;
|
||||||
}
|
}
|
||||||
|
|
||||||
p {
|
p {
|
||||||
color: $secondary;
|
color: map-get($grays, "dark"); // DIPERBAIKI
|
||||||
|
opacity: 0.7;
|
||||||
font-size: 1rem;
|
font-size: 1rem;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.btn-primary-soft {
|
||||||
|
--bs-btn-color: #{map-get($grays, "dark")};
|
||||||
|
--bs-btn-bg: #{map-get($theme-colors, "primary")};
|
||||||
|
--bs-btn-border-color: #{map-get($theme-colors, "primary")};
|
||||||
|
--bs-btn-hover-color: #{map-get($grays, "dark")};
|
||||||
|
--bs-btn-hover-bg: #{darken(map-get($theme-colors, "primary"), 5%)};
|
||||||
|
--bs-btn-hover-border-color: #{darken(map-get($theme-colors, "primary"), 7.5%)};
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================
|
||||||
|
// UTILITIES & CUSTOMIZATIONS
|
||||||
|
// ===================================
|
||||||
|
|
||||||
|
.line-clamp-2,
|
||||||
|
.line-clamp-3 {
|
||||||
|
display: -webkit-box;
|
||||||
|
-webkit-box-orient: vertical;
|
||||||
|
overflow: hidden;
|
||||||
|
line-height: 1.4;
|
||||||
|
}
|
||||||
|
.line-clamp-2 { -webkit-line-clamp: 2; }
|
||||||
|
.line-clamp-3 { -webkit-line-clamp: 3; }
|
||||||
|
|
||||||
|
// Custom Scrollbar
|
||||||
|
::-webkit-scrollbar {
|
||||||
|
width: 6px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-track {
|
||||||
|
background: map-get($grays, "light"); // DIPERBAIKI
|
||||||
|
border-radius: 3px;
|
||||||
|
}
|
||||||
|
::-webkit-scrollbar-thumb {
|
||||||
|
background: rgba(map-get($grays, "dark"), 0.25); // DIPERBAIKI
|
||||||
|
border-radius: 3px;
|
||||||
|
&:hover {
|
||||||
|
background: rgba(map-get($grays, "dark"), 0.4); // DIPERBAIKI
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ===================================
|
||||||
|
// Style untuk kartu pemilihan buku di dalam modal
|
||||||
|
// ===================================
|
||||||
|
|
||||||
|
.card-book-select {
|
||||||
|
cursor: pointer;
|
||||||
|
position: relative;
|
||||||
|
transition: $transition;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
transform: translateY(-5px);
|
||||||
|
box-shadow: $shadow-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card-select-overlay {
|
||||||
|
position: absolute;
|
||||||
|
top: 0; left: 0; right: 0; bottom: 0;
|
||||||
|
background-color: rgba(#435ebe, 0.7);
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: center;
|
||||||
|
opacity: 0;
|
||||||
|
transition: $transition;
|
||||||
|
border-radius: $border-radius-sm;
|
||||||
|
|
||||||
|
i {
|
||||||
|
text-shadow: 0 1px 3px rgba(0,0,0,0.3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
border: 2px solid map-get($theme-colors, "primary");
|
||||||
|
|
||||||
|
.card-select-overlay {
|
||||||
|
opacity: 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.disabled {
|
||||||
|
cursor: not-allowed;
|
||||||
|
opacity: 0.6;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// ===================================
|
||||||
|
// Styling untuk Form Peminjaman
|
||||||
|
// ===================================
|
||||||
|
|
||||||
|
.form-book-cover {
|
||||||
|
width: 60px;
|
||||||
|
height: 80px;
|
||||||
|
object-fit: cover;
|
||||||
|
}
|
||||||
|
|
||||||
|
.book-item {
|
||||||
|
background-color: map-get($grays, "light");
|
||||||
|
border-left: 4px solid map-get($theme-colors, "primary");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Styling untuk kartu buku di dalam modal pemilihan
|
||||||
|
.book-card {
|
||||||
|
cursor: pointer;
|
||||||
|
transition: $transition;
|
||||||
|
border: 2px solid transparent;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
border-color: map-get($theme-colors, "primary");
|
||||||
|
box-shadow: $shadow-md;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Style khusus ketika checkbox di dalamnya terpilih
|
||||||
|
&:has(.book-checkbox:checked) {
|
||||||
|
border-color: map-get($theme-colors, "success");
|
||||||
|
background-color: rgba(map-get($theme-colors, "success"), 0.05);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.remove-book {
|
||||||
|
padding: 2px 6px;
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.btn.disabled {
|
||||||
|
pointer-events: none;
|
||||||
|
opacity: 0.65;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
.book-option[style*="display: none"] {
|
||||||
|
display: none !important;
|
||||||
|
}
|
||||||
|
|
@ -1,5 +1,6 @@
|
||||||
@import 'variables';
|
@import "bootstrap/scss/functions";
|
||||||
@import 'bootstrap/scss/bootstrap';
|
@import "variables";
|
||||||
|
@import "bootstrap/scss/bootstrap";
|
||||||
|
|
||||||
body {
|
body {
|
||||||
background-color: $light;
|
background-color: $light;
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,26 @@
|
||||||
|
@props(['buku'])
|
||||||
|
|
||||||
|
<div class="card border-0 shadow-sm h-100 book-card">
|
||||||
|
<div class="row g-0 h-100">
|
||||||
|
<div class="col-4">
|
||||||
|
<div class="book-cover-container d-flex align-items-center justify-content-center p-3 h-100">
|
||||||
|
<img src="{{ asset($buku['cover']) }}" class="img-fluid rounded shadow-sm book-cover" alt="Cover {{ $buku['judul'] }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="col-8">
|
||||||
|
<div class="card-body d-flex flex-column h-100 p-3">
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<h6 class="card-title fw-bold text-dark mb-2 line-clamp-2">
|
||||||
|
{{ $buku['judul'] }}
|
||||||
|
</h6>
|
||||||
|
<p class="card-subtitle text-muted small mb-3">
|
||||||
|
<i class="bi bi-person-fill me-1"></i>{{ $buku['penulis'] }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-auto">
|
||||||
|
{{ $slot }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
@ -7,14 +7,14 @@
|
||||||
</button> --}}
|
</button> --}}
|
||||||
|
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<h3>Selamat Pagi, {{ $user->nama_lengkap }} !</h3>
|
<h3>{{ $greeting }}, {{ $user->nama_lengkap }} !</h3>
|
||||||
<p class="text-muted">Apa yang ingin kamu baca hari ini?</p>
|
<p class="text-muted">Apa yang ingin kamu baca hari ini?</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="row g-4 mb-4">
|
<div class="row g-4 mb-4">
|
||||||
@foreach ($stats as $stat)
|
@foreach ($stats as $stat)
|
||||||
<div class="col-xl-3 col-lg-6 col-md-6">
|
<div class="col-xl-3 col-lg-6 col-md-6">
|
||||||
<div class="card border-0 shadow-sm h-100">
|
<div class="card rounded-2 bg-{{ $stat['color'] }}-light border-0 h-100">
|
||||||
<div class="card-body p-4 ">
|
<div class="card-body p-4 ">
|
||||||
<div class="d-flex justify-content-between align-items-start">
|
<div class="d-flex justify-content-between align-items-start">
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
|
|
@ -46,7 +46,8 @@
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<canvas id="barChart" style="max-height: 300px;"></canvas>
|
<canvas id="barChart" style="max-height: 300px;" data-stats='@json($statistikBulanan ?? ['labels' => [], 'data' => []])'>
|
||||||
|
</canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -62,7 +63,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body text-center d-flex justify-content-center align-items-center p-4">
|
<div class="card-body text-center d-flex justify-content-center align-items-center p-4">
|
||||||
<div class="chart-container" style="position: relative; height: 200px; width: 200px;">
|
<div class="chart-container" style="position: relative; height: 200px; width: 200px;">
|
||||||
<canvas id="donutChart"></canvas>
|
<canvas id="donutChart" data-progress='@json($progressMembaca ?? ['selesai' => 0, 'sisa' => 0])'>
|
||||||
|
</canvas>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-center py-3">
|
<div class="text-center py-3">
|
||||||
|
|
@ -174,45 +176,22 @@ class="badge bg-{{ $item['type'] }}-soft text-{{ $item['type'] }} rounded-pill p
|
||||||
</div>
|
</div>
|
||||||
<h6 class="mb-0 fw-bold text-dark">Buku Pinjam Offline</h6>
|
<h6 class="mb-0 fw-bold text-dark">Buku Pinjam Offline</h6>
|
||||||
</div>
|
</div>
|
||||||
<button type-="button" :class="expanded ? 'btn btn-sm btn-primary rounded-pill px-3' : 'btn btn-sm btn-outline-primary rounded-pill px-3'"
|
<button type="button"
|
||||||
|
:class="expanded ? 'btn btn-sm btn-primary rounded-pill px-3' :
|
||||||
|
'btn btn-sm btn-outline-primary rounded-pill px-3'"
|
||||||
@click="expanded = !expanded" x-show="{{ count($bukuPinjamOffline) > 2 }}">
|
@click="expanded = !expanded" x-show="{{ count($bukuPinjamOffline) > 2 }}">
|
||||||
<span x-text="expanded ? 'Tampilkan Lebih Sedikit' : 'Lihat Semua'">Lihat Semua</span>
|
<span x-text="expanded ? 'Tampilkan Lebih Sedikit' : 'Lihat Semua'">Lihat Semua</span>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
@forelse($bukuPinjamOffline as $buku)
|
@forelse($bukuPinjamOffline as $buku)
|
||||||
<div class="col-xl-4 col-md-6" x-show="{{ $loop->index }} < 3 || expanded" x-transition>
|
<div class="col-xl-4 col-md-6" x-show="{{ $loop->index }} < 2 || expanded" x-transition>
|
||||||
<div class="card border-0 shadow-sm h-100 book-card">
|
<x-book-card :buku="$buku">
|
||||||
<div class="row g-0 h-100">
|
<div class="alert alert-danger border-0 py-2 px-3 mb-0 d-flex align-items-center">
|
||||||
<div class="col-4">
|
|
||||||
<div
|
|
||||||
class="book-cover-container d-flex align-items-center justify-content-center p-3 h-100">
|
|
||||||
<img src="{{ asset($buku['cover']) }}"
|
|
||||||
class="img-fluid rounded shadow-sm book-cover"
|
|
||||||
alt="Cover {{ $buku['judul'] }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-8">
|
|
||||||
<div class="card-body d-flex flex-column h-100 p-3">
|
|
||||||
<div class="flex-grow-1">
|
|
||||||
<h6 class="card-title fw-bold text-dark mb-2 line-clamp-2">
|
|
||||||
{{ $buku['judul'] }}</h6>
|
|
||||||
<p class="card-subtitle text-muted small mb-2">
|
|
||||||
<i class="bi bi-person-fill me-1"></i>{{ $buku['penulis'] }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="mt-auto">
|
|
||||||
<div
|
|
||||||
class="alert alert-danger border-0 py-2 px-3 mb-0 d-flex align-items-center">
|
|
||||||
<i class="bi bi-clock-fill me-2"></i>
|
<i class="bi bi-clock-fill me-2"></i>
|
||||||
<span class="fw-bold small">Sisa: {{ $buku['sisa_hari'] }}
|
<span class="fw-bold small">Sisa: {{ $buku['sisa_hari'] }} hari</span>
|
||||||
hari</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
|
</x-book-card>
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
|
@ -233,7 +212,9 @@ class="alert alert-danger border-0 py-2 px-3 mb-0 d-flex align-items-center">
|
||||||
</div>
|
</div>
|
||||||
<h6 class="mb-0 fw-bold text-dark">Baca Buku Online</h6>
|
<h6 class="mb-0 fw-bold text-dark">Baca Buku Online</h6>
|
||||||
</div>
|
</div>
|
||||||
<button type="button" :class="expanded ? 'btn btn-sm btn-primary rounded-pill px-3' : 'btn btn-sm btn-outline-primary rounded-pill px-3'"
|
<button type="button"
|
||||||
|
:class="expanded ? 'btn btn-sm btn-primary rounded-pill px-3' :
|
||||||
|
'btn btn-sm btn-outline-primary rounded-pill px-3'"
|
||||||
@click="expanded = !expanded" x-show="{{ count($bacaBukuOnline) > 3 }}">
|
@click="expanded = !expanded" x-show="{{ count($bacaBukuOnline) > 3 }}">
|
||||||
<span x-text="expanded ? 'Tampilkan Lebih Sedikit' : 'Lihat Semua'">Lihat Semua</span>
|
<span x-text="expanded ? 'Tampilkan Lebih Sedikit' : 'Lihat Semua'">Lihat Semua</span>
|
||||||
</button>
|
</button>
|
||||||
|
|
@ -241,45 +222,23 @@ class="alert alert-danger border-0 py-2 px-3 mb-0 d-flex align-items-center">
|
||||||
<div class="row g-4">
|
<div class="row g-4">
|
||||||
@forelse($bacaBukuOnline as $buku)
|
@forelse($bacaBukuOnline as $buku)
|
||||||
<div class="col-xl-4 col-md-6" x-show="{{ $loop->index }} < 3 || expanded" x-transition>
|
<div class="col-xl-4 col-md-6" x-show="{{ $loop->index }} < 3 || expanded" x-transition>
|
||||||
<div class="card border-0 shadow-sm h-100 book-card">
|
|
||||||
<div class="row g-0 h-100">
|
<x-book-card :buku="$buku">
|
||||||
<div class="col-4">
|
|
||||||
<div
|
|
||||||
class="book-cover-container d-flex align-items-center justify-content-center p-3 h-100">
|
|
||||||
<img src="{{ asset($buku['cover']) }}"
|
|
||||||
class="img-fluid rounded shadow-sm book-cover"
|
|
||||||
alt="Cover {{ $buku['judul'] }}">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="col-8">
|
|
||||||
<div class="card-body d-flex flex-column h-100 p-3">
|
|
||||||
<div class="flex-grow-1">
|
|
||||||
<h6 class="card-title fw-bold text-dark mb-2 line-clamp-2">
|
|
||||||
{{ $buku['judul'] }}</h6>
|
|
||||||
<p class="card-subtitle text-muted small mb-3">
|
|
||||||
<i class="bi bi-person-fill me-1"></i>{{ $buku['penulis'] }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="mt-auto">
|
|
||||||
<div class="progress-wrapper">
|
<div class="progress-wrapper">
|
||||||
<div
|
<div class="d-flex justify-content-between align-items-center mb-1">
|
||||||
class="d-flex justify-content-between align-items-center mb-2">
|
|
||||||
<span class="small text-muted">Progress</span>
|
<span class="small text-muted">Progress</span>
|
||||||
<span
|
<span class="small fw-bold text-primary">{{ $buku['progress'] }}%</span>
|
||||||
class="small fw-bold text-primary">{{ $buku['progress'] }}%</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="progress" style="height: 8px;">
|
<div class="progress" style="height: 8px;">
|
||||||
<div class="progress-bar bg-gradient"
|
<div class="progress-bar bg-primary rounded-pill"
|
||||||
style="width: {{ $buku['progress'] }}%"
|
style="width: {{ $buku['progress'] }}%" role="progressbar"
|
||||||
role="progressbar">
|
aria-valuenow="{{ $buku['progress'] }}" aria-valuemin="0"
|
||||||
</div>
|
aria-valuemax="100">
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</x-book-card>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<div class="col-12">
|
<div class="col-12">
|
||||||
|
|
@ -368,87 +327,13 @@ class="badge bg-{{ $item['type'] }}-soft text-{{ $item['type'] }} rounded-pill p
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const statistikData = @json($statistikBulanan ?? ['labels' => [], 'data' => []]);
|
const statistikData = @json($statistikBulanan ?? ['labels' => [], 'data' => []]);
|
||||||
const progressData = @json($progressMembaca ?? ['selesai' => 0, 'sisa' => 0]);
|
const progressData = @json($progressMembaca ?? ['selesai' => 0, 'sisa' => 0]);
|
||||||
|
|
||||||
// Bar Chart with improved styling
|
|
||||||
const ctxBar = document.getElementById('barChart').getContext('2d');
|
|
||||||
new Chart(ctxBar, {
|
|
||||||
type: 'bar',
|
|
||||||
data: {
|
|
||||||
labels: statistikData.labels,
|
|
||||||
datasets: [{
|
|
||||||
label: 'Buku Dibaca',
|
|
||||||
data: statistikData.data,
|
|
||||||
backgroundColor: '#435ebe',
|
|
||||||
borderRadius: 8,
|
|
||||||
borderSkipped: false,
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
scales: {
|
|
||||||
y: {
|
|
||||||
beginAtZero: true,
|
|
||||||
grid: {
|
|
||||||
color: 'rgba(0,0,0,0.05)',
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
color: '#6c757d',
|
|
||||||
font: {
|
|
||||||
size: 12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
x: {
|
|
||||||
grid: {
|
|
||||||
display: false,
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
color: '#6c757d',
|
|
||||||
font: {
|
|
||||||
size: 12
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Donut Chart
|
|
||||||
const ctxDonut = document.getElementById('donutChart').getContext('2d');
|
|
||||||
new Chart(ctxDonut, {
|
|
||||||
type: 'doughnut',
|
|
||||||
data: {
|
|
||||||
labels: ['Telah Dibaca', 'Belum Dibaca'],
|
|
||||||
datasets: [{
|
|
||||||
data: [progressData.selesai, progressData.sisa],
|
|
||||||
backgroundColor: ['#435ebe', '#e9ecef'],
|
|
||||||
borderColor: ['#435ebe', '#dee2e6'],
|
|
||||||
borderWidth: 3,
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: false,
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false
|
|
||||||
}
|
|
||||||
},
|
|
||||||
cutout: '75%'
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
||||||
|
|
||||||
|
<script src="{{ asset('js/dashboard-charts.js') }}"></script>
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
|
||||||
|
|
@ -61,27 +61,48 @@
|
||||||
|
|
||||||
<div class="card-body d-flex flex-column p-3">
|
<div class="card-body d-flex flex-column p-3">
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
|
{{-- Badge diletakkan di atas judul --}}
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
<span class="badge fw-normal bg-light text-dark border me-1">{{ $buku['kategori'] }}</span>
|
<span class="badge fw-normal text-primary border me-1">{{ $buku['kategori'] }}</span>
|
||||||
<span
|
<span
|
||||||
class="badge fw-normal {{ $buku['status'] == 'Tersedia' ? 'bg-success-subtle text-success-emphasis' : 'bg-warning-subtle text-warning-emphasis' }} border">{{ $buku['status'] }}</span>
|
class="badge fw-normal {{ $buku['status'] == 'Tersedia' ? 'bg-success-subtle text-success-emphasis' : 'bg-warning-subtle text-warning-emphasis' }} border">{{ $buku['status'] }}</span>
|
||||||
</div>
|
</div>
|
||||||
<h5 class="card-title fw-bold ">{{ $buku['judul'] }}</h5>
|
<h6 class="card-title fw-bold line-clamp-2">{{ $buku['judul'] }}</h6>
|
||||||
<p class="card-text small text-muted mb-2">{{ $buku['penulis'] }}</p>
|
<p class="card-text small text-muted mb-2">{{ $buku['penulis'] }}</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<div class="d-grid mt-auto">
|
<div class="d-grid mt-auto">
|
||||||
@if ($buku['status'] == 'Dipinjam')
|
@if ($buku['status'] == 'Tersedia')
|
||||||
<button class="btn btn-secondary btn-sm" disabled><i class="bi bi-x-circle me-1"></i>
|
@if (is_array($buku['tipe_akses']))
|
||||||
Tidak Tersedia</button>
|
<div class="d-flex gap-2">
|
||||||
@else
|
<a href="{{ route('peminjaman.ringkasan', $buku['id']) }}"
|
||||||
@if ($buku['tipe_akses'] == 'online')
|
class="btn btn-outline-primary btn-sm w-100">
|
||||||
|
<i class="bi bi-arrow-down-up me-1"></i> Pinjam
|
||||||
|
</a>
|
||||||
|
|
||||||
|
<button class="btn btn-primary btn-sm w-100"><i class="bi bi-book me-1"></i>
|
||||||
|
Baca</button>
|
||||||
|
</div>
|
||||||
|
@elseif ($buku['tipe_akses'] == 'online')
|
||||||
<button class="btn btn-primary btn-sm"><i class="bi bi-book me-1"></i> Baca
|
<button class="btn btn-primary btn-sm"><i class="bi bi-book me-1"></i> Baca
|
||||||
Online</button>
|
Online</button>
|
||||||
@else
|
@else
|
||||||
<button class="btn btn-outline-primary btn-sm"><i
|
<a href="{{ route('peminjaman.ringkasan', $buku['id']) }}"
|
||||||
class="bi bi-arrow-down-up me-1"></i> Pinjam Offline</button>
|
class="btn btn-outline-primary btn-sm">
|
||||||
|
<i class="bi bi-arrow-down-up me-1"></i> Pinjam Offline
|
||||||
|
</a>
|
||||||
|
@endif
|
||||||
|
@else
|
||||||
|
@if (is_array($buku['tipe_akses']))
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
<button class="btn btn-secondary btn-sm w-100" disabled><i
|
||||||
|
class="bi bi-x-circle me-1"></i> Dipinjam</button>
|
||||||
|
<button class="btn btn-primary btn-sm w-100"><i class="bi bi-book me-1"></i>
|
||||||
|
Baca</button>
|
||||||
|
</div>
|
||||||
|
@else
|
||||||
|
<button class="btn btn-secondary btn-sm" disabled><i
|
||||||
|
class="bi bi-x-circle me-1"></i> Tidak Tersedia</button>
|
||||||
@endif
|
@endif
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,15 @@
|
||||||
|
|
||||||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap-icons@1.11.3/font/bootstrap-icons.min.css">
|
||||||
@vite(['resources/scss/app.scss', 'resources/js/app.js'])
|
@vite(['resources/scss/app.scss', 'resources/js/app.js'])
|
||||||
|
<!-- Flatpickr CSS & JS -->
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/flatpickr.min.css">
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/flatpickr/dist/themes/material_blue.css">
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/flatpickr"></script>
|
||||||
|
<script src="https://npmcdn.com/flatpickr/dist/l10n/id.js"></script>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
body {
|
body {
|
||||||
background-color: #f4f7f8;
|
background-color: #f3f3f3;
|
||||||
}
|
}
|
||||||
|
|
||||||
.sidebar {
|
.sidebar {
|
||||||
|
|
@ -156,6 +162,7 @@ function toggleDesktopSidebar() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
@stack('scripts')
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
|
@ -40,7 +40,8 @@
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a href="#" class="nav-link">
|
<a href="{{ route('peminjaman.index') }}"
|
||||||
|
class="nav-link {{ request()->routeIs('peminjaman.*') ? 'active' : '' }}">
|
||||||
<i class="bi bi-arrow-left-right"></i>
|
<i class="bi bi-arrow-left-right"></i>
|
||||||
<span class="nav-text ms-2">Peminjaman Offline</span>
|
<span class="nav-text ms-2">Peminjaman Offline</span>
|
||||||
</a>
|
</a>
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,304 @@
|
||||||
|
<x-app-layout>
|
||||||
|
<div class="d-flex align-items-center mb-4">
|
||||||
|
<a href="{{ route('peminjaman.ringkasan', $buku['id']) }}" class="btn btn-outline-secondary me-3">
|
||||||
|
<i class="bi bi-arrow-left"></i>
|
||||||
|
</a>
|
||||||
|
<h1 class="h2 mb-0">Form Peminjaman Offline</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-md-8">
|
||||||
|
<div class="card border-0 shadow-sm">
|
||||||
|
<div class="card-body p-4 p-md-5">
|
||||||
|
|
||||||
|
{{-- Informasi Peminjam --}}
|
||||||
|
<div class="mb-5">
|
||||||
|
<div class="card border-0 shadow-sm">
|
||||||
|
<div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
|
||||||
|
<h5 class="fw-bold m-0">Informasi Peminjam</h5>
|
||||||
|
<a href="#" class="btn btn-sm btn-outline-secondary ">Edit Profil</a>
|
||||||
|
</div>
|
||||||
|
<div class="card-body p-4">
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small">Nama Lengkap</label>
|
||||||
|
<p class="fw-semibold">{{ $user['nama_lengkap'] }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small">Nomor Handphone</label>
|
||||||
|
<p class="fw-semibold">{{ $user['nomor_hp'] }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small">Kelas</label>
|
||||||
|
<p class="fw-semibold">{{ $user['kelas'] }}</p>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label class="form-label text-muted small">Golongan</label>
|
||||||
|
<p class="fw-semibold">{{ $user['golongan'] }}</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Form untuk submit data --}}
|
||||||
|
<form action="{{ route('peminjaman.store') }}" method="POST" id="formPeminjaman"
|
||||||
|
data-semua-buku="{{ json_encode($semuaBuku->values()) }}"
|
||||||
|
data-buku-awal="{{ json_encode($buku) }}">
|
||||||
|
@csrf
|
||||||
|
|
||||||
|
{{-- Informasi Buku & Tanggal --}}
|
||||||
|
<div class="mb-5">
|
||||||
|
<div class="d-flex justify-content-between align-items-center border-bottom pb-2 mb-3">
|
||||||
|
<h5 class="fw-bold m-0">Buku yang Dipinjam</h5>
|
||||||
|
<button type="button" class="btn btn-sm btn-primary " data-bs-toggle="modal"
|
||||||
|
data-bs-target="#pilihBukuModal" id="btnTambahBuku">
|
||||||
|
<i class="bi bi-plus-circle me-1"></i>Tambah Buku
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Container untuk daftar buku yang dipinjam --}}
|
||||||
|
<div id="daftarBukuPinjam" class="mb-4">
|
||||||
|
<div class="book-item border rounded p-3 mb-3" data-book-id="{{ $buku['id'] }}">
|
||||||
|
<div class="d-flex align-items-start">
|
||||||
|
<img src="{{ asset($buku['cover']) }}" alt="Cover"
|
||||||
|
class="rounded me-3 form-book-cover">
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<h6 class="fw-bold mb-1">{{ $buku['judul'] }}</h6>
|
||||||
|
<p class="text-muted small mb-1">{{ $buku['penulis'] }}</p>
|
||||||
|
<span class="badge bg-info">{{ $buku['kategori'] }}</span>
|
||||||
|
</div>
|
||||||
|
<span class="badge bg-success">Buku Utama</span>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Hidden inputs untuk buku yang dipilih --}}
|
||||||
|
<div id="hiddenInputs">
|
||||||
|
<input type="hidden" name="buku_ids[]" value="{{ $buku['id'] }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Tanggal Peminjaman --}}
|
||||||
|
<div class="row g-3">
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="tanggalPinjam" class="form-label text-muted">Tanggal Pinjam</label>
|
||||||
|
<input type="text" id="tanggalPinjam" name="tanggal_pinjam" class="form-control"
|
||||||
|
placeholder="Pilih tanggal pinjam"
|
||||||
|
value="{{ \Carbon\Carbon::now()->format('d F Y') }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-6">
|
||||||
|
<label for="tanggalKembali" class="form-label text-muted">Tanggal Kembali</label>
|
||||||
|
<input type="text" id="tanggalKembali" name="tanggal_kembali"
|
||||||
|
placeholder="Pilih tanggal kembali" class="form-control"
|
||||||
|
value="{{ \Carbon\Carbon::now()->addDays(7)->format('d F Y') }}">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Peraturan Peminjaman --}}
|
||||||
|
<div class="mb-4">
|
||||||
|
<h5 class="fw-bold border-bottom pb-2 mb-3">Peraturan Peminjaman</h5>
|
||||||
|
<div class="alert alert-info border-0 bg-info-subtle">
|
||||||
|
<ol class="mb-0 ps-3">
|
||||||
|
<li>Perpustakaan buka pada jam operasional sekolah.</li>
|
||||||
|
<li>Setiap siswa hanya dapat meminjam sebanyak 2-3 buku dalam satu waktu.</li>
|
||||||
|
<li>Buku yang dipinjam harus dikembalikan dalam jangka waktu yang telah ditentukan.
|
||||||
|
</li>
|
||||||
|
<li>Jika buku tidak dikembalikan tepat waktu, akan dikenakan denda atau sanksi
|
||||||
|
lainnya.</li>
|
||||||
|
<li>Buku yang dikembalikan harus dalam kondisi baik, tanpa kerusakan atau hilang.
|
||||||
|
</li>
|
||||||
|
<li>Dilarang merusak atau mencoret-coret buku.</li>
|
||||||
|
<li>Setiap siswa bertanggung jawab penuh terhadap buku yang dipinjam.</li>
|
||||||
|
</ol>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Tombol Kirim Form --}}
|
||||||
|
<div class="d-grid">
|
||||||
|
<button type="button" class="btn btn-primary btn-lg " data-bs-toggle="modal"
|
||||||
|
data-bs-target="#konfirmasiModal">
|
||||||
|
Kirim Form
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Modal Pilih Buku --}}
|
||||||
|
<div class="modal fade" id="pilihBukuModal" tabindex="-1" aria-labelledby="pilihBukuModalLabel" aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-lg modal-dialog-scrollable">
|
||||||
|
<div class="modal-content border-0 shadow-lg rounded-3">
|
||||||
|
|
||||||
|
<!-- Header -->
|
||||||
|
<div class="modal-header bg-light">
|
||||||
|
<h5 class="modal-title fw-bold" id="pilihBukuModalLabel">
|
||||||
|
<i class="bi bi-book-half me-2 text-primary"></i>Pilih Buku Tambahan
|
||||||
|
</h5>
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Body -->
|
||||||
|
<div class="modal-body">
|
||||||
|
|
||||||
|
<!-- Alert Info -->
|
||||||
|
<div class="alert alert-info border-0 bg-info-subtle mb-4 d-flex align-items-center">
|
||||||
|
<i class="bi bi-info-circle-fill me-2"></i>
|
||||||
|
<span>Anda dapat memilih maksimal <strong><span id="sisaSlot">2</span> buku</strong> lagi.
|
||||||
|
Total maksimal 3 buku.</span>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Search Box -->
|
||||||
|
<div class="mb-3">
|
||||||
|
<div class="input-group shadow-sm">
|
||||||
|
<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 buku...">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Daftar Buku -->
|
||||||
|
<div id="daftarBukuModal" class="row g-3">
|
||||||
|
@foreach ($semuaBuku as $bukuItem)
|
||||||
|
@if ($bukuItem['status'] == 'Tersedia' || $bukuItem['id'] == $buku['id'])
|
||||||
|
<div class="col-12 book-option" data-book-id="{{ $bukuItem['id'] }}"
|
||||||
|
data-book-title="{{ strtolower($bukuItem['judul']) }}"
|
||||||
|
data-book-author="{{ strtolower($bukuItem['penulis']) }}">
|
||||||
|
|
||||||
|
<div class="card book-card h-100 border-0 shadow-sm hover-shadow transition"
|
||||||
|
onclick="toggleBookSelection({{ $bukuItem['id'] }})">
|
||||||
|
|
||||||
|
<div class="card-body p-3">
|
||||||
|
<div class="d-flex align-items-start">
|
||||||
|
|
||||||
|
<!-- Cover Buku -->
|
||||||
|
<img src="{{ asset($bukuItem['cover']) }}" alt="Cover"
|
||||||
|
class="rounded me-3 form-book-cover"
|
||||||
|
style="width: 60px; height: 80px; object-fit: cover;">
|
||||||
|
|
||||||
|
<!-- Detail Buku -->
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<h6 class="fw-bold mb-1">{{ $bukuItem['judul'] }}</h6>
|
||||||
|
<p class="text-muted small mb-1">{{ $bukuItem['penulis'] }}</p>
|
||||||
|
<div class="d-flex align-items-center flex-wrap gap-2">
|
||||||
|
<span class="badge bg-info">{{ $bukuItem['kategori'] }}</span>
|
||||||
|
<span class="badge bg-success"><i
|
||||||
|
class="bi bi-check-circle me-1"></i>Tersedia</span>
|
||||||
|
@if ($bukuItem['id'] == $buku['id'])
|
||||||
|
<span class="badge bg-primary"><i
|
||||||
|
class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Checkbox -->
|
||||||
|
<div class="form-check ms-2">
|
||||||
|
<input class="form-check-input book-checkbox" type="checkbox"
|
||||||
|
value="{{ $bukuItem['id'] }}" id="book{{ $bukuItem['id'] }}"
|
||||||
|
@if ($bukuItem['id'] == $buku['id']) checked disabled @endif
|
||||||
|
onclick="event.stopPropagation()">
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
@endforeach
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Counter Buku Terpilih -->
|
||||||
|
<div class="mt-4 p-3 bg-light rounded shadow-sm">
|
||||||
|
<div class="d-flex justify-content-between align-items-center">
|
||||||
|
<span class="fw-semibold">
|
||||||
|
<i class="bi bi-collection me-2 text-primary"></i>Buku Terpilih:
|
||||||
|
<span id="counterBuku" class="text-dark">1</span>/3
|
||||||
|
</span>
|
||||||
|
<ul>
|
||||||
|
<li id="selectedBooks" class="text-muted small"></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Footer -->
|
||||||
|
<div class="modal-footer bg-light">
|
||||||
|
<button type="button" class="btn btn-outline-secondary" data-bs-dismiss="modal">
|
||||||
|
<i class="bi bi-x-circle me-1"></i> Batal
|
||||||
|
</button>
|
||||||
|
<button type="button" class="btn btn-primary" id="konfirmasiBuku"
|
||||||
|
onclick="konfirmasiPilihanBuku()">
|
||||||
|
<i class="bi bi-check2-circle me-1"></i> Konfirmasi Pilihan
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
|
||||||
|
{{-- Modal Konfirmasi Kirim --}}
|
||||||
|
<div class="modal fade" id="konfirmasiModal" tabindex="-1" aria-labelledby="konfirmasiModalLabel"
|
||||||
|
aria-hidden="true">
|
||||||
|
<div class="modal-dialog modal-dialog-centered">
|
||||||
|
<div class="modal-content border-0 shadow-lg">
|
||||||
|
<div class="modal-header border-0 text-center d-block">
|
||||||
|
<h5 class="modal-title fw-bold" id="konfirmasiModalLabel">Apakah Anda Yakin Ingin Mengirim Form?
|
||||||
|
</h5>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body text-center">
|
||||||
|
<div class="text-muted mb-3">Pastikan data yang Anda kirim sudah benar.</div>
|
||||||
|
<div class="alert alert-info border-0 bg-info-subtle text-start">
|
||||||
|
<strong>Ringkasan Peminjaman:</strong>
|
||||||
|
<div id="ringkasanBuku" class="mt-2"></div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer border-0 justify-content-center">
|
||||||
|
<button type="button" class="btn btn-secondary px-4" data-bs-dismiss="modal">Batal</button>
|
||||||
|
|
||||||
|
{{-- Button Setuju jika sudah ada backend --}}
|
||||||
|
{{-- <button type="button" class="btn btn-primary px-4" onclick="kirimForm()">Setuju</button> --}}
|
||||||
|
|
||||||
|
{{-- Button Setuju jika belum ada backend, akan ter direct ke peminjaman.index --}}
|
||||||
|
<a href="{{ route('peminjaman.index') }}" class="btn btn-primary px-4">
|
||||||
|
Setuju
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<script>
|
||||||
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
const tglPinjam = flatpickr("#tanggalPinjam", {
|
||||||
|
dateFormat: "d F Y",
|
||||||
|
altInput: true,
|
||||||
|
altFormat: "d F Y",
|
||||||
|
defaultDate: "{{ \Carbon\Carbon::now()->format('Y-m-d') }}",
|
||||||
|
locale: "id",
|
||||||
|
minDate: "today",
|
||||||
|
onChange: function(selectedDates, dateStr) {
|
||||||
|
if (tglKembali.selectedDates[0] <= selectedDates[0]) {
|
||||||
|
const newDate = new Date(selectedDates[0]);
|
||||||
|
newDate.setDate(newDate.getDate() + 1);
|
||||||
|
tglKembali.setDate(newDate);
|
||||||
|
}
|
||||||
|
tglKembali.set("minDate", new Date(selectedDates[0]).fp_incr(1));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const tglKembali = flatpickr("#tanggalKembali", {
|
||||||
|
dateFormat: "d F Y",
|
||||||
|
altInput: true,
|
||||||
|
altFormat: "d F Y",
|
||||||
|
defaultDate: "{{ \Carbon\Carbon::now()->addDays(7)->format('Y-m-d') }}",
|
||||||
|
locale: "id",
|
||||||
|
minDate: new Date().fp_incr(1)
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -0,0 +1,100 @@
|
||||||
|
<x-app-layout>
|
||||||
|
<div class="d-flex justify-content-between flex-wrap flex-md-nowrap align-items-center pb-2 mb-3 border-bottom">
|
||||||
|
<h1 class="h2">Daftar Buku Peminjaman Offline</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Filter & Pencarian -->
|
||||||
|
<div class="card mb-4">
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{ route('peminjaman.index') }}" method="GET">
|
||||||
|
<div class="row g-3 align-items-center">
|
||||||
|
<div class="col-md-4">
|
||||||
|
<input type="text" name="search" class="form-control"
|
||||||
|
placeholder="Cari buku berdasarkan judul..." value="{{ $input['search'] ?? '' }}">
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<select name="kategori" class="form-select">
|
||||||
|
<option value="">Semua Kategori</option>
|
||||||
|
@foreach ($filterOptions['kategori'] as $kategori)
|
||||||
|
<option value="{{ $kategori }}"
|
||||||
|
{{ ($input['kategori'] ?? '') == $kategori ? 'selected' : '' }}>{{ $kategori }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<select name="tahun" class="form-select">
|
||||||
|
<option value="">Semua Tahun</option>
|
||||||
|
@foreach ($filterOptions['tahun'] as $tahun)
|
||||||
|
<option value="{{ $tahun }}"
|
||||||
|
{{ ($input['tahun'] ?? '') == $tahun ? 'selected' : '' }}>{{ $tahun }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2">
|
||||||
|
<select name="penulis" class="form-select">
|
||||||
|
<option value="">Semua Penulis</option>
|
||||||
|
@foreach ($filterOptions['penulis'] as $penulis)
|
||||||
|
<option value="{{ $penulis }}"
|
||||||
|
{{ ($input['penulis'] ?? '') == $penulis ? 'selected' : '' }}>{{ $penulis }}
|
||||||
|
</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-2 d-grid">
|
||||||
|
<button type="submit" class="btn btn-primary">Filter</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<p class="fw-bold">Daftar buku yang tersedia secara offline dan dapat diambil di perpustakaan dengan mengisi form
|
||||||
|
yang tersedia.</p>
|
||||||
|
|
||||||
|
<!-- Daftar Buku -->
|
||||||
|
<div class="row row-cols-2 row-cols-md-3 row-cols-lg-5 g-4">
|
||||||
|
@forelse ($semuaBuku as $buku)
|
||||||
|
<div class="col">
|
||||||
|
<div class="card h-100 shadow-sm border-0">
|
||||||
|
<img src="{{ asset($buku['cover']) }}" class="card-img-top rounded-2 object-fit-cover"
|
||||||
|
style="height: 310px;" alt="Cover {{ $buku['judul'] }}">
|
||||||
|
|
||||||
|
<div class="card-body d-flex flex-column p-3">
|
||||||
|
<div class="flex-grow-1">
|
||||||
|
<div class="mb-2">
|
||||||
|
<span class="badge fw-normal text-primary border me-1">{{ $buku['kategori'] }}</span>
|
||||||
|
<span
|
||||||
|
class="badge fw-normal {{ $buku['status'] == 'Tersedia' ? 'bg-success-subtle text-success-emphasis' : 'bg-warning-subtle text-warning-emphasis' }} border">{{ $buku['status'] }}</span>
|
||||||
|
</div>
|
||||||
|
<h6 class="card-title fw-bold line-clamp-2">{{ $buku['judul'] }}</h6>
|
||||||
|
<p class="card-text small text-muted mb-2">{{ $buku['penulis'] }}</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="d-grid mt-auto">
|
||||||
|
@if ($buku['status'] == 'Tersedia')
|
||||||
|
<a href="{{ route('peminjaman.ringkasan', $buku['id']) }}"
|
||||||
|
class="btn btn-outline-primary btn-sm">
|
||||||
|
<i class="bi bi-arrow-down-up me-1"></i> Pinjam Offline
|
||||||
|
</a>
|
||||||
|
@else
|
||||||
|
<button class="btn btn-secondary btn-sm" disabled><i class="bi bi-x-circle me-1"></i>
|
||||||
|
Tidak Tersedia</button>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@empty
|
||||||
|
<div class="col-12">
|
||||||
|
<div class="alert alert-warning text-center">
|
||||||
|
<h4 class="alert-heading">Tidak Ada Hasil</h4>
|
||||||
|
<p>Tidak ada buku yang cocok dengan kriteria filter Anda. Coba reset atau ubah filter.</p>
|
||||||
|
<hr>
|
||||||
|
<a href="{{ route('peminjaman') }}" class="btn btn-primary">Reset Filter</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endforelse
|
||||||
|
</div>
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
<x-app-layout>
|
||||||
|
<div class="d-flex flex-column" style="min-height: calc(100vh - 110px);">
|
||||||
|
|
||||||
|
{{-- Header --}}
|
||||||
|
<div class="d-flex align-items-center mb-4">
|
||||||
|
<a href="{{ route('peminjaman.index')}}" class="btn btn-outline-secondary me-3">
|
||||||
|
<i class="bi bi-arrow-left"></i>
|
||||||
|
</a>
|
||||||
|
<h1 class="h2 mb-0">Ringkasan Buku</h1>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Wrapper main content --}}
|
||||||
|
<main class="flex-grow-1 d-flex align-items-center justify-content-center">
|
||||||
|
<div class="container-fluid">
|
||||||
|
<div class="row g-5 align-items-center">
|
||||||
|
|
||||||
|
{{-- Kolom Kiri untuk Cover Buku --}}
|
||||||
|
<div class="col-lg-4 text-center">
|
||||||
|
<img src="{{ asset($buku['cover']) }}" class="img-fluid rounded-3 shadow-lg"
|
||||||
|
style="max-height: 450px; max-width: 300px; object-fit: cover;" alt="Cover {{ $buku['judul'] }}">
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- Kolom Kanan untuk Detail & Button --}}
|
||||||
|
<div class="col-lg-8">
|
||||||
|
<h1 class="display-5 fw-bold mb-2">{{ $buku['judul'] }}</h1>
|
||||||
|
<p class="h5 text-muted mb-4">oleh {{ $buku['penulis'] }}</p>
|
||||||
|
|
||||||
|
<p class="lead" style="text-align: justify;">
|
||||||
|
Ini adalah ringkasan atau sinopsis dari buku "{{ $buku['judul'] }}". Lorem ipsum dolor sit
|
||||||
|
amet, consectetur adipiscing elit. Sed do eiusmod tempor incididunt ut labore et dolore
|
||||||
|
magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut
|
||||||
|
aliquip ex ea commodo consequat.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div class="mt-5">
|
||||||
|
<a href="{{ route('peminjaman.form', $buku['id']) }}" class="btn btn-primary btn-lg rounded-pill px-5 py-3">
|
||||||
|
<i class="bi bi-file-earmark-text-fill me-2"></i>
|
||||||
|
Lanjutkan ke Form Peminjaman
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
<footer class="mt-auto text-center text-muted py-3">
|
||||||
|
<small>Copyright © {{ date('Y') }} Perpus.</small>
|
||||||
|
</footer>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
use App\Http\Controllers\DashboardController;
|
use App\Http\Controllers\DashboardController;
|
||||||
use App\Http\Controllers\KatalogController;
|
use App\Http\Controllers\KatalogController;
|
||||||
|
use App\Http\Controllers\PeminjamanController;
|
||||||
use App\Http\Controllers\ProfileController;
|
use App\Http\Controllers\ProfileController;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
|
@ -15,6 +16,11 @@
|
||||||
Route::get('/katalog', [KatalogController::class, 'index'])
|
Route::get('/katalog', [KatalogController::class, 'index'])
|
||||||
->middleware('auth')->name('katalog');
|
->middleware('auth')->name('katalog');
|
||||||
|
|
||||||
|
// Route untuk peminjaman offline
|
||||||
|
Route::get('/peminjaman-offline', [PeminjamanController::class, 'index'])->name('peminjaman.index');
|
||||||
|
Route::get('/peminjaman-offline/{id}/ringkasan', [PeminjamanController::class, 'ringkasan'])->name('peminjaman.ringkasan');
|
||||||
|
Route::get('/peminjaman-offline/{id}/form', [PeminjamanController::class, 'form'])->name('peminjaman.form');
|
||||||
|
Route::post('/peminjaman/store', [PeminjamanController::class, 'store'])->name('peminjaman.store');
|
||||||
|
|
||||||
// Route untuk user profile dari laravel breeze
|
// Route untuk user profile dari laravel breeze
|
||||||
Route::middleware('auth')->group(function () {
|
Route::middleware('auth')->group(function () {
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue