diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php
index 85866e4..9de1b68 100644
--- a/app/Http/Controllers/DashboardController.php
+++ b/app/Http/Controllers/DashboardController.php
@@ -19,6 +19,16 @@ public function index()
$bukuPinjamOffline = DummyDataService::getBukuPinjamOffline($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(
'user',
'stats',
@@ -27,7 +37,8 @@ public function index()
'progressMembaca',
'statistikBulanan',
'bukuPinjamOffline',
- 'bacaBukuOnline'
+ 'bacaBukuOnline',
+ 'greeting',
));
}
-}
\ No newline at end of file
+}
diff --git a/app/Http/Controllers/KatalogController.php b/app/Http/Controllers/KatalogController.php
index 089a36c..3c4f8b6 100644
--- a/app/Http/Controllers/KatalogController.php
+++ b/app/Http/Controllers/KatalogController.php
@@ -25,7 +25,6 @@ public function index(Request $request, $tipe = null)
'semuaBuku' => $semuaBuku,
'filterOptions' => $filterOptions,
'input' => $filters,
- 'tipe' => $tipe,
]);
}
}
diff --git a/app/Http/Controllers/PeminjamanController.php b/app/Http/Controllers/PeminjamanController.php
new file mode 100644
index 0000000..5992ea2
--- /dev/null
+++ b/app/Http/Controllers/PeminjamanController.php
@@ -0,0 +1,89 @@
+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!');
+ }
+}
\ No newline at end of file
diff --git a/app/Services/DummyDataService.php b/app/Services/DummyDataService.php
index 0bd8db8..f75a498 100644
--- a/app/Services/DummyDataService.php
+++ b/app/Services/DummyDataService.php
@@ -10,11 +10,13 @@ public static function getAllSiswa(): array
[
'id' => 1,
'nisn' => '1234567890',
- 'nama_lengkap' => 'John Doe',
- 'email' => 'johnskuy@smkn1perpus.sch.id',
- 'nomor_hp' => '081234567890',
+ 'nama_lengkap' => 'Silvi Rahmawati',
+ 'email' => 'silvi.rahmawati@smkn1perpus.sch.id',
+ 'nomor_hp' => '08123456789',
'password' => 'password',
'role' => 'siswa',
+ 'kelas' => 'XII RPL',
+ 'golongan' => 'A',
],
[
'id' => 2,
@@ -33,6 +35,8 @@ public static function getAllSiswa(): array
'nomor_hp' => '081998877665',
'password' => 'password',
'role' => 'siswa',
+ 'kelas' => 'XII RPL A',
+ 'golongan' => 'A',
],
[
'id' => 4,
@@ -42,6 +46,8 @@ public static function getAllSiswa(): array
'nomor_hp' => '081556677889',
'password' => 'password',
'role' => 'siswa',
+ 'kelas' => 'XII RPL A',
+ 'golongan' => 'A',
],
[
'id' => 5,
@@ -152,7 +158,7 @@ private static function getAllBooks()
'tahun' => 2023,
'status' => 'Tersedia',
'is_new' => false,
- 'tipe_akses' => 'online',
+ 'tipe_akses' => ['online', 'offline'],
'progress' => 100,
'user_id' => [3, 1],
],
@@ -206,7 +212,7 @@ private static function getAllBooks()
'is_new' => true,
'tipe_akses' => 'online',
'progress' => 40,
- 'user_id' => [1,4,5],
+ 'user_id' => [1, 4, 5],
],
[
'id' => 7,
@@ -219,9 +225,9 @@ private static function getAllBooks()
'is_new' => true,
'tipe_akses' => 'online',
'progress' => 0,
- 'user_id' => [3,1]
+ 'user_id' => [3, 1]
],
- [
+ [
'id' => 8,
'judul' => 'Buku Offline Tanpa Peminjam',
'penulis' => 'Penulis Misteri',
@@ -289,24 +295,38 @@ public static function getBacaBukuOnline($user): array
/**
* Mengambil daftar buku untuk katalog dengan filter.
*/
- public static function getKatalogBuku(array $filters = []): \Illuminate\Support\Collection
- {
- $buku = self::getAllBooks();
+ // app/Services/DummyDataService.php
- $buku = $buku->when($filters['search'] ?? null, function ($query, $search) {
- return $query->filter(fn($item) => str_contains(strtolower($item['judul']), strtolower($search)));
- })->when($filters['kategori'] ?? null, function ($query, $kategori) {
- return $query->where('kategori', $kategori);
- })->when($filters['tahun'] ?? null, function ($query, $tahun) {
- return $query->where('tahun', $tahun);
- })->when($filters['penulis'] ?? null, function ($query, $penulis) {
- return $query->where('penulis', $penulis);
- })->when($filters['tipe'] ?? null, function ($query, $tipe) {
- return $query->where('tipe_akses', $tipe);
- });
+public static function getKatalogBuku(array $filters = []): \Illuminate\Support\Collection
+{
+ $buku = self::getAllBooks();
- return $buku;
- }
+ $buku = $buku->when($filters['search'] ?? null, function ($query, $search) {
+ return $query->filter(fn($item) => str_contains(strtolower($item['judul']), strtolower($search)));
+ })->when($filters['kategori'] ?? null, function ($query, $kategori) {
+ return $query->where('kategori', $kategori);
+ })->when($filters['tahun'] ?? null, function ($query, $tahun) {
+ return $query->where('tahun', $tahun);
+ })->when($filters['penulis'] ?? null, function ($query, $penulis) {
+ return $query->where('penulis', $penulis);
+ })
+ ->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;
+}
/**
* Method baru untuk mengambil daftar unik untuk dropdown filter
diff --git a/public/js/dashboard-charts.js b/public/js/dashboard-charts.js
new file mode 100644
index 0000000..ba23c9c
--- /dev/null
+++ b/public/js/dashboard-charts.js
@@ -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%'
+ }
+ });
+ }
+});
\ No newline at end of file
diff --git a/resources/js/app.js b/resources/js/app.js
index 9b3b3cb..396c712 100644
--- a/resources/js/app.js
+++ b/resources/js/app.js
@@ -1,8 +1,9 @@
import './bootstrap';
-import 'bootstrap';
+import './peminjaman-form.js';
+import * as bootstrap from 'bootstrap';
+
+window.bootstrap = bootstrap;
import Alpine from 'alpinejs';
-
window.Alpine = Alpine;
-
-Alpine.start();
+Alpine.start();
\ No newline at end of file
diff --git a/resources/js/peminjaman-form.js b/resources/js/peminjaman-form.js
new file mode 100644
index 0000000..cda8ece
--- /dev/null
+++ b/resources/js/peminjaman-form.js
@@ -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 = ' Maksimal Buku Tercapai';
+ } else {
+ btnTambah.classList.remove('disabled');
+ btnTambah.innerHTML = ' Tambah Buku';
+ }
+ }
+
+ function updateSelectedBooks() {
+ const container = document.getElementById('selectedBooks');
+ const selected = semuaBuku.filter(book => bukuTerpilih.includes(book.id));
+ container.innerHTML = selected.map(book => `
${book.judul} `).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) => `
+
+
+
+
+
+
+
${book.judul}
+
${book.penulis}
+
${book.kategori}
+
+
+
+ ${book.id === bukuAwal.id
+ ? 'Buku Utama '
+ : 'Tambahan '}
+
+ ${book.id !== bukuAwal.id
+ ? `
+
+ `
+ : ''}
+
+
+
+ `).join('');
+
+
+ hiddenInputs.innerHTML = bukuTerpilih.map(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) =>
+ `
+ ${index + 1}. ${book.judul}
+ ${book.penulis}
+
`
+ ).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';
+ });
+ }
+ });
+}
\ No newline at end of file
diff --git a/resources/scss/_variables.scss b/resources/scss/_variables.scss
index 836e6c2..5ab1dfe 100644
--- a/resources/scss/_variables.scss
+++ b/resources/scss/_variables.scss
@@ -1,128 +1,139 @@
-$primary: #435ebe;
-$secondary: #6c757d;
-$success: #198754;
-$info: #0dcaf0;
-$warning: #ffc107;
-$danger: #dc3545;
-$light: #f4f7f8;
-$dark: #212529;
+// ===================================
+// VARIABLES & MAPS
+// ===================================
-// Derived colors untuk background light
-$primary-light: rgba($primary, 0.1);
-$success-light: rgba($success, 0.1);
-$warning-light: rgba($warning, 0.1);
-$danger-light: rgba($danger, 0.1);
-$info-light: rgba($info, 0.1);
-$secondary-light: rgba($secondary, 0.1);
+// Theme Colors Map
+$theme-colors: (
+ "primary": #435ebe,
+ "secondary": mix(#6c757d, #ffffff, 80%),
+ "success": mix(#198754, #ffffff, 85%),
+ "info": mix(#0dcaf0, #ffffff, 80%),
+ "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;
-$card-box-shadow: 0 0 1.25rem rgba(33,37,41,.05);
-
$border-radius-sm: 0.25rem;
$border-radius-lg: 1rem;
-$shadow-sm: 0 2px 4px rgba(0,0,0,0.08);
-$shadow-md: 0 4px 8px rgba(0,0,0,0.12);
-$shadow-lg: 0 8px 20px rgba(0,0,0,0.15);
+
+// 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-md: 0 4px 8px rgba(0, 0, 0, 0.12);
+$shadow-lg: 0 8px 20px rgba(0, 0, 0, 0.15);
$transition: all 0.3s ease;
// ===================================
-// CARD COMPONENTS
+// UTILITIES (GENERATED FROM MAPS)
// ===================================
-
-.card {
- box-shadow: $card-box-shadow;
-
- .card-header {
- &.bg-white {
- background-color: #fff !important;
- border-bottom: 1px solid rgba($secondary, 0.125);
- }
+@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);
}
}
// ===================================
-// ICON COMPONENTS
+// BASE COMPONENTS
// ===================================
-.icon-circle {
- width: 50px;
- height: 50px;
+.card {
+ box-shadow: $card-box-shadow;
+ .card-header {
+ background-color: #fff;
+ border-bottom: 1px solid rgba(map-get($grays, "dark"), 0.1); // DIPERBAIKI
+ }
+}
+
+.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;
+}
+
+// ===================================
+// CUSTOM COMPONENTS
+// ===================================
+
+.icon-circle, .icon-box {
display: flex;
align-items: center;
justify-content: center;
transition: $transition;
}
-.section-icon,
-.chart-icon,
-.notification-icon,
-.activity-icon {
+.icon-circle {
+ width: 50px;
+ height: 50px;
+ border-radius: 50%;
+}
+
+.icon-box {
width: 40px;
height: 40px;
border-radius: 10px;
- background-color: $primary-light;
- display: flex;
- align-items: center;
- justify-content: center;
- transition: $transition;
-
i {
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 {
transition: $transition;
box-shadow: $card-box-shadow;
-
&:hover {
transform: translateY(-2px);
- box-shadow: $shadow-md !important;
-
+ box-shadow: $shadow-md;
.book-cover {
transform: scale(1.03);
}
@@ -132,180 +143,169 @@ $transition: all 0.3s ease;
.book-cover {
transition: $transition;
border-radius: $border-radius-sm;
-
&-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;
}
}
-
-// ===================================
-// 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 {
padding-bottom: 15px;
- border-bottom: 2px solid $light;
-
+ border-bottom: 2px solid map-get($grays, "light"); // DIPERBAIKI
h5 {
- color: $dark;
+ color: map-get($grays, "dark"); // DIPERBAIKI
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 {
text-align: center;
padding: 3rem 1rem;
-
i {
font-size: 4rem;
- color: $secondary;
+ color: map-get($grays, "dark"); // DIPERBAIKI
margin-bottom: 1rem;
- opacity: 0.5;
+ opacity: 0.25;
}
-
p {
- color: $secondary;
+ color: map-get($grays, "dark"); // DIPERBAIKI
+ opacity: 0.7;
font-size: 1rem;
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;
}
\ No newline at end of file
diff --git a/resources/scss/app.scss b/resources/scss/app.scss
index 540a669..4e502dd 100644
--- a/resources/scss/app.scss
+++ b/resources/scss/app.scss
@@ -1,5 +1,6 @@
-@import 'variables';
-@import 'bootstrap/scss/bootstrap';
+@import "bootstrap/scss/functions";
+@import "variables";
+@import "bootstrap/scss/bootstrap";
body {
background-color: $light;
diff --git a/resources/views/components/book-card.blade.php b/resources/views/components/book-card.blade.php
new file mode 100644
index 0000000..d06e037
--- /dev/null
+++ b/resources/views/components/book-card.blade.php
@@ -0,0 +1,26 @@
+@props(['buku'])
+
+
+
+
+
+
+
+
+
+
+
+
+ {{ $buku['judul'] }}
+
+
+ {{ $buku['penulis'] }}
+
+
+
+ {{ $slot }}
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/views/dashboard.blade.php b/resources/views/dashboard.blade.php
index bd57d9c..45c89dc 100644
--- a/resources/views/dashboard.blade.php
+++ b/resources/views/dashboard.blade.php
@@ -7,15 +7,15 @@
--}}
-
Selamat Pagi, {{ $user->nama_lengkap }} !
+
{{ $greeting }}, {{ $user->nama_lengkap }} !
Apa yang ingin kamu baca hari ini?
@foreach ($stats as $stat)
-
-
+
+
{{ $stat['label'] }}
@@ -46,7 +46,8 @@
-
+ [], 'data' => []])'>
+
@@ -62,7 +63,8 @@
@@ -174,45 +176,22 @@ class="badge bg-{{ $item['type'] }}-soft text-{{ $item['type'] }} rounded-pill p
Buku Pinjam Offline
-
Lihat Semua
@forelse($bukuPinjamOffline as $buku)
-
-
-
-
-
-
-
-
-
-
-
-
- {{ $buku['judul'] }}
-
- {{ $buku['penulis'] }}
-
-
-
-
-
- Sisa: {{ $buku['sisa_hari'] }}
- hari
-
-
-
-
+
+
+
+
+ Sisa: {{ $buku['sisa_hari'] }} hari
-
+
@empty
@@ -233,7 +212,9 @@ class="alert alert-danger border-0 py-2 px-3 mb-0 d-flex align-items-center">
Baca Buku Online
-
Lihat Semua
@@ -241,45 +222,23 @@ class="alert alert-danger border-0 py-2 px-3 mb-0 d-flex align-items-center">
@forelse($bacaBukuOnline as $buku)
-
-
-
-
-
-
+
+
+
+
+ Progress
+ {{ $buku['progress'] }}%
-
-
-
-
- {{ $buku['judul'] }}
-
- {{ $buku['penulis'] }}
-
-
-
-
-
- Progress
- {{ $buku['progress'] }}%
-
-
-
-
+
-
+
+
@empty
@@ -368,87 +327,13 @@ class="badge bg-{{ $item['type'] }}-soft text-{{ $item['type'] }} rounded-pill p
-
+
+
diff --git a/resources/views/katalog.blade.php b/resources/views/katalog.blade.php
index 3710d95..b46837a 100644
--- a/resources/views/katalog.blade.php
+++ b/resources/views/katalog.blade.php
@@ -61,27 +61,48 @@
+ {{-- Badge diletakkan di atas judul --}}
- {{ $buku['kategori'] }}
+ {{ $buku['kategori'] }}
{{ $buku['status'] }}
-
{{ $buku['judul'] }}
+
{{ $buku['judul'] }}
{{ $buku['penulis'] }}
-
- @if ($buku['status'] == 'Dipinjam')
-
- Tidak Tersedia
- @else
- @if ($buku['tipe_akses'] == 'online')
+ @if ($buku['status'] == 'Tersedia')
+ @if (is_array($buku['tipe_akses']))
+
+ @elseif ($buku['tipe_akses'] == 'online')
Baca
Online
@else
-
Pinjam Offline
+
+ Pinjam Offline
+
+ @endif
+ @else
+ @if (is_array($buku['tipe_akses']))
+
+ Dipinjam
+
+ Baca
+
+ @else
+
Tidak Tersedia
@endif
@endif
diff --git a/resources/views/layouts/app.blade.php b/resources/views/layouts/app.blade.php
index cb170c7..bdd74aa 100644
--- a/resources/views/layouts/app.blade.php
+++ b/resources/views/layouts/app.blade.php
@@ -10,9 +10,15 @@
@vite(['resources/scss/app.scss', 'resources/js/app.js'])
+
+
+
+
+
+