Feat: Finalize denda system, implemented manual sanction for teachers, fixed dashboard error, and updated UI modal
This commit is contained in:
parent
156a4e00a9
commit
779ef38952
|
|
@ -29,14 +29,11 @@ public function retrieveById($identifier)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Rehash the user's password if required.
|
* Rehash the user's password if required.
|
||||||
* Method ini wajib ada di Laravel 12. Kita biarkan kosong karena tidak relevan untuk data dummy.
|
|
||||||
*/
|
*/
|
||||||
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void
|
public function rehashPasswordIfRequired(Authenticatable $user, array $credentials, bool $force = false): void
|
||||||
{
|
{
|
||||||
// Biarkan kosong
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Fungsi-fungsi di bawah ini tidak kita pakai, tapi harus ada.
|
|
||||||
public function retrieveByToken($identifier, $token) { return null; }
|
public function retrieveByToken($identifier, $token) { return null; }
|
||||||
public function updateRememberToken(Authenticatable $user, $token) { }
|
public function updateRememberToken(Authenticatable $user, $token) { }
|
||||||
public function retrieveByCredentials(array $credentials) { return null; }
|
public function retrieveByCredentials(array $credentials) { return null; }
|
||||||
|
|
|
||||||
|
|
@ -9,36 +9,78 @@
|
||||||
|
|
||||||
class AdminPeminjamanController extends Controller
|
class AdminPeminjamanController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Menampilkan halaman utama manajemen peminjaman (Tabel).
|
|
||||||
*/
|
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
// Panggil data dari DummyDataService
|
|
||||||
$peminjamanAktif = DummyDataService::getAdminPeminjamanAktif();
|
$peminjamanAktif = DummyDataService::getAdminPeminjamanAktif();
|
||||||
|
|
||||||
|
// LOGIC DENDA & WA LINK (Update Request Client)
|
||||||
|
$peminjamanAktif = $peminjamanAktif->map(function ($item) {
|
||||||
|
// Hitung Denda Flat 1000/hari
|
||||||
|
$tenggat = Carbon::parse($item['tenggat_kembali']);
|
||||||
|
$now = Carbon::now();
|
||||||
|
|
||||||
|
$item['hari_terlambat'] = 0;
|
||||||
|
$item['total_denda'] = 0;
|
||||||
|
|
||||||
|
if ($now->greaterThan($tenggat)) {
|
||||||
|
$hariTelat = $tenggat->diffInDays($now);
|
||||||
|
$item['hari_terlambat'] = $hariTelat;
|
||||||
|
$item['total_denda'] = $hariTelat * 1000;
|
||||||
|
$item['denda_per_hari'] = 1000;
|
||||||
|
}
|
||||||
|
// Generate WA Link
|
||||||
|
$hp = $item['nomor_hp'];
|
||||||
|
if (substr($hp, 0, 1) == '0') {
|
||||||
|
$hp = '62' . substr($hp, 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
$pesan = "Halo kak {$item['peminjam']}, buku anda sudah terlambat {$item['hari_terlambat']} hari dengan denda Rp " . number_format($item['total_denda'], 0, ',', '.') . ". Mohon segera dikembalikan ya.";
|
||||||
|
$item['wa_link'] = "https://wa.me/{$hp}?text=" . urlencode($pesan);
|
||||||
|
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
|
||||||
$daftarPeminjam = $peminjamanAktif->pluck('peminjam')->unique();
|
$daftarPeminjam = $peminjamanAktif->pluck('peminjam')->unique();
|
||||||
|
|
||||||
|
|
||||||
return view('admin.peminjaman.index', [
|
return view('admin.peminjaman.index', [
|
||||||
'pageTitle' => 'Manajemen Peminjaman',
|
'pageTitle' => 'Manajemen Peminjaman & Denda',
|
||||||
'peminjamanAktif' => $peminjamanAktif,
|
'peminjamanAktif' => $peminjamanAktif,
|
||||||
'daftarPeminjam' => $daftarPeminjam,
|
'daftarPeminjam' => $daftarPeminjam,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Menampilkan formulir untuk membuat peminjaman manual.
|
|
||||||
*/
|
|
||||||
public function create()
|
public function create()
|
||||||
{
|
{
|
||||||
$allUsers = collect(DummyDataService::getAllSiswa());
|
$allUsers = collect(DummyDataService::getAllSiswa());
|
||||||
|
$peminjamanAktif = DummyDataService::getAdminPeminjamanAktif();
|
||||||
|
|
||||||
// Kelompokkan berdasarkan 'role'
|
|
||||||
$groupedUsers = $allUsers
|
$groupedUsers = $allUsers
|
||||||
->whereIn('role', ['siswa', 'guru'])
|
->whereIn('role', ['siswa', 'guru'])
|
||||||
|
->map(function ($user) use ($peminjamanAktif) {
|
||||||
|
|
||||||
|
// Hitung berapa buku yang sedang dipinjam
|
||||||
|
$jumlahPinjam = $peminjamanAktif->where('peminjam', $user['nama_lengkap'])->count();
|
||||||
|
|
||||||
|
// Cek Status
|
||||||
|
$user['jumlah_pinjam'] = $jumlahPinjam;
|
||||||
|
$user['kena_limit'] = $jumlahPinjam >= 2;
|
||||||
|
|
||||||
|
// Cek apakah user di-banned (Nonaktif Manual)
|
||||||
|
$user['is_banned'] = $user['is_banned'] ?? false;
|
||||||
|
$user['disabled'] = $user['kena_limit'] || $user['is_banned'];
|
||||||
|
|
||||||
|
if ($user['is_banned']) {
|
||||||
|
$user['status_text'] = "(Akun Dibekukan)";
|
||||||
|
} elseif ($user['kena_limit']) {
|
||||||
|
$user['status_text'] = "(Limit Penuh: 2/2)";
|
||||||
|
} else {
|
||||||
|
$user['status_text'] = "";
|
||||||
|
}
|
||||||
|
|
||||||
|
return $user;
|
||||||
|
})
|
||||||
->groupBy('role');
|
->groupBy('role');
|
||||||
|
|
||||||
// Filter hanya buku offline
|
|
||||||
$daftarBuku = DummyDataService::getAllBooks()
|
$daftarBuku = DummyDataService::getAllBooks()
|
||||||
->where('status', 'Tersedia')
|
->where('status', 'Tersedia')
|
||||||
->filter(function ($buku) {
|
->filter(function ($buku) {
|
||||||
|
|
@ -54,4 +96,96 @@ public function create()
|
||||||
'daftarBuku' => $daftarBuku,
|
'daftarBuku' => $daftarBuku,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Menampilkan halaman KHUSUS Manajemen Denda (Siswa & Guru Telat).
|
||||||
|
*/
|
||||||
|
public function dendaIndex()
|
||||||
|
{
|
||||||
|
$allData = DummyDataService::getAdminPeminjamanAktif();
|
||||||
|
$allSiswaRaw = collect(DummyDataService::getAllSiswa());
|
||||||
|
$now = \Carbon\Carbon::now();
|
||||||
|
|
||||||
|
// LOGIC AUTO-BAN
|
||||||
|
$allSiswa = $allSiswaRaw->map(function ($siswa) use ($allData, $now) {
|
||||||
|
|
||||||
|
// Cek siswa punya pinjaman yang telat
|
||||||
|
$pinjamanUser = $allData->firstWhere('user_id', $siswa['id']);
|
||||||
|
|
||||||
|
$isTelat = false;
|
||||||
|
if ($pinjamanUser) {
|
||||||
|
$isTelat = $pinjamanUser['tenggat_kembali']->startOfDay()->lt($now->startOfDay());
|
||||||
|
}
|
||||||
|
|
||||||
|
// Jika Role SISWA dan TELAT -> Wajib AUTO BAN (Override true)
|
||||||
|
// ika Role GURU -> Ikut status asli database (Manual Ban)
|
||||||
|
if ($siswa['role'] === 'siswa' && $isTelat) {
|
||||||
|
$siswa['is_banned'] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $siswa;
|
||||||
|
});
|
||||||
|
|
||||||
|
$siswaTelat = $allData->filter(function ($item) use ($now, $allSiswa) {
|
||||||
|
$userData = $allSiswa->firstWhere('id', $item['user_id']);
|
||||||
|
|
||||||
|
if (!$userData)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$isTelat = $item['tenggat_kembali']->startOfDay()->lt($now->startOfDay());
|
||||||
|
$isBanned = $userData['is_banned'];
|
||||||
|
$isTargetRole = in_array($userData['role'], ['siswa', 'guru']);
|
||||||
|
|
||||||
|
return ($isTelat || $isBanned) && $isTargetRole;
|
||||||
|
})->map(function ($item) use ($now, $allSiswa) {
|
||||||
|
|
||||||
|
// Hitungan Denda
|
||||||
|
$tenggat = $item['tenggat_kembali']->startOfDay();
|
||||||
|
|
||||||
|
// Jika belum telat (tapi banned/manual), hari telat 0
|
||||||
|
$hariTelat = ($tenggat->lt($now->startOfDay()))
|
||||||
|
? $tenggat->diffInDays($now->startOfDay())
|
||||||
|
: 0;
|
||||||
|
|
||||||
|
$totalDenda = $hariTelat * $item['denda_per_hari'];
|
||||||
|
|
||||||
|
$item['hari_terlambat'] = $hariTelat;
|
||||||
|
$item['total_denda'] = $totalDenda;
|
||||||
|
|
||||||
|
// Ambil status is_banned TERBARU dari $allSiswa
|
||||||
|
$dataSiswa = $allSiswa->firstWhere('id', $item['user_id']);
|
||||||
|
$item['is_banned'] = $dataSiswa['is_banned'] ?? false;
|
||||||
|
$item['kelas'] = $dataSiswa['kelas'] ?? 'Guru';
|
||||||
|
|
||||||
|
// Link WA
|
||||||
|
$hp = $item['nomor_hp'];
|
||||||
|
if (substr($hp, 0, 1) == '0')
|
||||||
|
$hp = '62' . substr($hp, 1);
|
||||||
|
|
||||||
|
if ($hariTelat > 0) {
|
||||||
|
$pesan = "Halo {$item['peminjam']}, anda terlambat pengembalian buku. Total Denda: Rp " . number_format($totalDenda, 0, ',', '.');
|
||||||
|
} else {
|
||||||
|
$pesan = "Halo {$item['peminjam']}, akun anda sedang dinonaktifkan sementara. Mohon hubungi petugas.";
|
||||||
|
}
|
||||||
|
$item['wa_link'] = "https://wa.me/{$hp}?text=" . urlencode($pesan);
|
||||||
|
|
||||||
|
return $item;
|
||||||
|
});
|
||||||
|
|
||||||
|
$listKelas = $siswaTelat->pluck('kelas')->unique()->values();
|
||||||
|
|
||||||
|
return view('admin.denda.index', [
|
||||||
|
'pageTitle' => 'Manajemen Denda & Sanksi',
|
||||||
|
'siswaTelat' => $siswaTelat,
|
||||||
|
'listKelas' => $listKelas
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Dummy function untuk tombol Sanksi
|
||||||
|
*/
|
||||||
|
public function berikanSanksi(Request $request)
|
||||||
|
{
|
||||||
|
return response()->json(['status' => 'success']);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -11,17 +11,31 @@ class DashboardController extends Controller
|
||||||
public function index()
|
public function index()
|
||||||
{
|
{
|
||||||
$user = Auth::user();
|
$user = Auth::user();
|
||||||
|
$bukuPinjam = DummyDataService::getBukuPinjamOffline($user);
|
||||||
|
|
||||||
|
$isTelat = collect($bukuPinjam)->contains(function ($buku) {
|
||||||
|
return $buku['sisa_hari'] < 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
if ($isTelat && $user->role === 'siswa') {
|
||||||
|
$user->is_banned = true;
|
||||||
|
}
|
||||||
|
|
||||||
$stats = DummyDataService::getDashboardStats();
|
$stats = DummyDataService::getDashboardStats();
|
||||||
$pengumuman = DummyDataService::getPengumuman();
|
$pengumuman = DummyDataService::getPengumuman();
|
||||||
$pemberitahuan = DummyDataService::getPemberitahuan();
|
$pemberitahuan = DummyDataService::getPemberitahuan();
|
||||||
$progressMembaca = DummyDataService::getProgressMembaca();
|
$progressMembaca = DummyDataService::getProgressMembaca();
|
||||||
$statistikBulanan = DummyDataService::getStatistikBulanan();
|
$statistikBulanan = DummyDataService::getStatistikBulanan();
|
||||||
$bukuPinjamOffline = DummyDataService::getBukuPinjamOffline($user);
|
$bukuPinjamOffline = $bukuPinjam;
|
||||||
$bacaBukuOnline = DummyDataService::getBacaBukuOnline($user);
|
$bacaBukuOnline = DummyDataService::getBacaBukuOnline($user);
|
||||||
$rekomendasiPembelajaran = DummyDataService::getRekomendasiPembelajaran();
|
$rekomendasiPembelajaran = DummyDataService::getRekomendasiPembelajaran();
|
||||||
|
$personalNotif = DummyDataService::getNotifikasiForUser($user);
|
||||||
|
|
||||||
|
// Cek apakah ada notifikasi denda aktif
|
||||||
|
$dendaAlert = collect($personalNotif)->where('type', 'denda_active');
|
||||||
|
|
||||||
// Menambahkan thumbnail YouTube ke setiap rekomendasi
|
// Menambahkan thumbnail YouTube ke setiap rekomendasi
|
||||||
$rekomendasiPembelajaran = DummyDataService::getRekomendasiPembelajaran()->map(function ($item) {
|
$rekomendasiPembelajaran = $rekomendasiPembelajaran->map(function ($item) {
|
||||||
$videoId = $this->extractYouTubeId($item['youtube_link']);
|
$videoId = $this->extractYouTubeId($item['youtube_link']);
|
||||||
if ($videoId) {
|
if ($videoId) {
|
||||||
$item['thumbnail'] = "https://img.youtube.com/vi/{$videoId}/hqdefault.jpg";
|
$item['thumbnail'] = "https://img.youtube.com/vi/{$videoId}/hqdefault.jpg";
|
||||||
|
|
@ -31,28 +45,30 @@ public function index()
|
||||||
return $item;
|
return $item;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$dendaAlert = collect($personalNotif)->where('type', 'denda_active');
|
||||||
|
|
||||||
$hour = date('H');
|
$hour = date('H');
|
||||||
$greeting = "Selamat Pagi";
|
$greeting = "Selamat Pagi";
|
||||||
if ($hour >= 12 && $hour < 15) {
|
if ($hour >= 12 && $hour < 15)
|
||||||
$greeting = "Selamat Siang";
|
$greeting = "Selamat Siang";
|
||||||
} elseif ($hour >= 15 && $hour < 18) {
|
elseif ($hour >= 15 && $hour < 18)
|
||||||
$greeting = "Selamat Sore";
|
$greeting = "Selamat Sore";
|
||||||
} elseif ($hour >= 18) {
|
elseif ($hour >= 18)
|
||||||
$greeting = "Selamat Malam";
|
$greeting = "Selamat Malam";
|
||||||
}
|
|
||||||
|
|
||||||
return view('dashboard', compact(
|
return view('dashboard', compact(
|
||||||
'user',
|
'user',
|
||||||
'stats',
|
'stats',
|
||||||
'pengumuman',
|
'pengumuman',
|
||||||
'pemberitahuan',
|
'pemberitahuan',
|
||||||
|
'dendaAlert',
|
||||||
'progressMembaca',
|
'progressMembaca',
|
||||||
'statistikBulanan',
|
'statistikBulanan',
|
||||||
'bukuPinjamOffline',
|
'bukuPinjamOffline',
|
||||||
'bacaBukuOnline',
|
'bacaBukuOnline',
|
||||||
'greeting',
|
'greeting',
|
||||||
'rekomendasiPembelajaran'
|
'rekomendasiPembelajaran'
|
||||||
));
|
))->with('notifikasi', $personalNotif);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
||||||
|
|
@ -4,13 +4,23 @@
|
||||||
|
|
||||||
use App\Services\DummyDataService;
|
use App\Services\DummyDataService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
|
||||||
class KatalogController extends Controller
|
class KatalogController extends Controller
|
||||||
{
|
{
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
$filters = $request->only(['search', 'kategori', 'tahun', 'penulis']);
|
$user = Auth::user();
|
||||||
|
|
||||||
|
$isBanned = false;
|
||||||
|
if ($user && $user->role === 'siswa') {
|
||||||
|
$bukuPinjam = DummyDataService::getBukuPinjamOffline($user);
|
||||||
|
$isTelat = collect($bukuPinjam)->contains(fn($b) => $b['sisa_hari'] < 0);
|
||||||
|
$isBannedManual = $user->is_banned ?? false;
|
||||||
|
$isBanned = $isTelat || $isBannedManual;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filters = $request->only(['search', 'kategori', 'tahun', 'penulis']);
|
||||||
$semuaBuku = DummyDataService::getKatalogBuku($filters);
|
$semuaBuku = DummyDataService::getKatalogBuku($filters);
|
||||||
$filterOptions = DummyDataService::getFilterOptions();
|
$filterOptions = DummyDataService::getFilterOptions();
|
||||||
|
|
||||||
|
|
@ -20,6 +30,7 @@ public function index(Request $request)
|
||||||
'input' => $filters,
|
'input' => $filters,
|
||||||
'pageTitle' => 'Katalog Buku',
|
'pageTitle' => 'Katalog Buku',
|
||||||
'mode' => 'umum',
|
'mode' => 'umum',
|
||||||
|
'isBanned' => $isBanned,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -10,6 +10,18 @@ class PeminjamanController extends Controller
|
||||||
{
|
{
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
|
$user = \Illuminate\Support\Facades\Auth::user();
|
||||||
|
$bukuPinjam = \App\Services\DummyDataService::getBukuPinjamOffline($user);
|
||||||
|
$isTelat = collect($bukuPinjam)->contains(function ($buku) {
|
||||||
|
return $buku['sisa_hari'] < 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
$isBannedManual = $user->is_banned ?? false;
|
||||||
|
|
||||||
|
if (($isTelat || $isBannedManual) && $user->role === 'siswa') {
|
||||||
|
return redirect()->route('dashboard')->with('error', 'AKSES DITOLAK: Akun Anda sedang dibekukan karena ada buku terlambat!');
|
||||||
|
}
|
||||||
|
|
||||||
$filters = $request->only(['search', 'kategori', 'tahun', 'penulis']);
|
$filters = $request->only(['search', 'kategori', 'tahun', 'penulis']);
|
||||||
$filters['tipe_akses'] = 'offline';
|
$filters['tipe_akses'] = 'offline';
|
||||||
$semuaBuku = DummyDataService::getKatalogBuku($filters);
|
$semuaBuku = DummyDataService::getKatalogBuku($filters);
|
||||||
|
|
|
||||||
|
|
@ -4,15 +4,16 @@
|
||||||
|
|
||||||
use App\Services\DummyDataService;
|
use App\Services\DummyDataService;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\Auth; // Tambahkan ini
|
||||||
|
|
||||||
class RiwayatController extends Controller
|
class RiwayatController extends Controller
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* Menampilkan halaman riwayat peminjaman offline.
|
|
||||||
*/
|
|
||||||
public function offlineIndex()
|
public function offlineIndex()
|
||||||
{
|
{
|
||||||
$riwayatOffline = DummyDataService::getRiwayatOffline();
|
$user = \Illuminate\Support\Facades\Auth::user();
|
||||||
|
if (!$user) $user = (object) ['id' => 1];
|
||||||
|
|
||||||
|
$riwayatOffline = DummyDataService::getRiwayatOffline($user);
|
||||||
|
|
||||||
return view('riwayat.offline', [
|
return view('riwayat.offline', [
|
||||||
'pageTitle' => 'Riwayat Peminjaman Offline',
|
'pageTitle' => 'Riwayat Peminjaman Offline',
|
||||||
|
|
@ -20,9 +21,6 @@ public function offlineIndex()
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Menampilkan halaman riwayat baca online.
|
|
||||||
*/
|
|
||||||
public function onlineIndex()
|
public function onlineIndex()
|
||||||
{
|
{
|
||||||
$riwayatOnline = DummyDataService::getRiwayatOnline();
|
$riwayatOnline = DummyDataService::getRiwayatOnline();
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
use App\Services\DummyDataService;
|
use App\Services\DummyDataService;
|
||||||
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\URL;
|
use Illuminate\Support\Facades\URL;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
use Illuminate\Support\Facades\View;
|
use Illuminate\Support\Facades\View;
|
||||||
|
|
@ -26,18 +27,18 @@ public function boot(): void
|
||||||
URL::forceScheme('https');
|
URL::forceScheme('https');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// View Composer untuk semua view (*)
|
||||||
View::composer('*', function ($view) {
|
View::composer('*', function ($view) {
|
||||||
$notifikasi = collect([]);
|
if (Auth::check()) {
|
||||||
$unreadNotificationsCount = 0;
|
$user = Auth::user();
|
||||||
|
|
||||||
// Hanya ambil notifikasi jika ada pengguna yang login
|
|
||||||
if (auth()->check()) {
|
|
||||||
$user = auth()->user();
|
|
||||||
$notifikasi = collect(DummyDataService::getNotifikasiForUser($user));
|
$notifikasi = collect(DummyDataService::getNotifikasiForUser($user));
|
||||||
$unreadNotificationsCount = $notifikasi->where('read', false)->count();
|
$unreadCount = $notifikasi->where('read', false)->count();
|
||||||
|
$view->with('notifikasi', $notifikasi);
|
||||||
|
$view->with('unreadNotificationsCount', $unreadCount);
|
||||||
|
} else {
|
||||||
|
$view->with('notifikasi', collect([]));
|
||||||
|
$view->with('unreadNotificationsCount', 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
$view->with(compact('notifikasi', 'unreadNotificationsCount'));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ public static function getAllSiswa(): array
|
||||||
'role' => 'siswa',
|
'role' => 'siswa',
|
||||||
'kelas' => 'XII RPL',
|
'kelas' => 'XII RPL',
|
||||||
'golongan' => 'A',
|
'golongan' => 'A',
|
||||||
|
'is_banned' => false,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => 2,
|
'id' => 2,
|
||||||
|
|
@ -41,6 +42,7 @@ public static function getAllSiswa(): array
|
||||||
'role' => 'siswa',
|
'role' => 'siswa',
|
||||||
'kelas' => 'XII RPL A',
|
'kelas' => 'XII RPL A',
|
||||||
'golongan' => 'A',
|
'golongan' => 'A',
|
||||||
|
'is_banned' => true,
|
||||||
],
|
],
|
||||||
|
|
||||||
[
|
[
|
||||||
|
|
@ -53,6 +55,7 @@ public static function getAllSiswa(): array
|
||||||
'role' => 'siswa',
|
'role' => 'siswa',
|
||||||
'kelas' => 'XII RPL A',
|
'kelas' => 'XII RPL A',
|
||||||
'golongan' => 'A',
|
'golongan' => 'A',
|
||||||
|
'is_banned' => false,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => 5,
|
'id' => 5,
|
||||||
|
|
@ -61,6 +64,7 @@ public static function getAllSiswa(): array
|
||||||
'email' => 'rina.marlina@smkn1perpus.sch.id',
|
'email' => 'rina.marlina@smkn1perpus.sch.id',
|
||||||
'password' => 'password',
|
'password' => 'password',
|
||||||
'role' => 'guru',
|
'role' => 'guru',
|
||||||
|
'is_banned' => false,
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
@ -81,157 +85,39 @@ public static function getAktivitasMingguan(): array
|
||||||
*/
|
*/
|
||||||
public static function getAdminPeminjamanAktif(): \Illuminate\Support\Collection
|
public static function getAdminPeminjamanAktif(): \Illuminate\Support\Collection
|
||||||
{
|
{
|
||||||
return collect([
|
$allBooks = self::getAllBooks();
|
||||||
[
|
$allSiswa = collect(self::getAllSiswa());
|
||||||
'id_peminjaman' => 'PIN-202510-001',
|
$bukuDipinjam = $allBooks->whereIn('status', ['Dipinjam', 'Terlambat']);
|
||||||
'peminjam' => 'Silvi Rahmawati',
|
$grouped = $bukuDipinjam->groupBy(function ($item) {
|
||||||
'nomor_hp' => '08123456789',
|
return is_array($item['user_id']) ? $item['user_id'][0] : $item['user_id'];
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(12),
|
});
|
||||||
'tenggat_kembali' => Carbon::now()->subDays(5), // Terlambat 5 hari
|
|
||||||
'denda_per_hari' => 1000,
|
return $grouped->map(function ($books, $userId) use ($allSiswa) {
|
||||||
'books' => [
|
$siswa = $allSiswa->firstWhere('id', $userId);
|
||||||
['id' => 5, 'judul' => 'Si Anak Pintar'],
|
$firstBook = $books->first();
|
||||||
['id' => 8, 'judul' => 'Ayah'],
|
$tglKembali = Carbon::now()->addDays($firstBook['sisa_hari']);
|
||||||
]
|
|
||||||
],
|
return [
|
||||||
[
|
'id_peminjaman' => 'PIN-ADM-' . sprintf('%03d', $userId),
|
||||||
'id_peminjaman' => 'PIN-202510-002',
|
'user_id' => $userId,
|
||||||
'peminjam' => 'Andi Pratama',
|
'role' => $siswa ? $siswa['role'] : 'siswa',
|
||||||
'nomor_hp' => '081556677889',
|
'is_banned' => $siswa ? ($siswa['is_banned'] ?? false) : false,
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(4),
|
|
||||||
'tenggat_kembali' => Carbon::now()->addDays(3), // Sisa 3 hari
|
'peminjam' => $siswa ? $siswa['nama_lengkap'] : 'User Tidak Dikenal',
|
||||||
'denda_per_hari' => 1000,
|
'nomor_hp' => $siswa ? ($siswa['nomor_hp'] ?? '-') : '-',
|
||||||
'books' => [
|
|
||||||
['id' => 7, 'judul' => 'The Last Spell Breather'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-003',
|
|
||||||
'peminjam' => 'Siti Nurhaliza',
|
|
||||||
'nomor_hp' => '081998877665',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(7),
|
'tanggal_pinjam' => Carbon::now()->subDays(7),
|
||||||
'tenggat_kembali' => Carbon::now(), // Hari ini
|
'tenggat_kembali' => $tglKembali,
|
||||||
'denda_per_hari' => 1000,
|
'denda_per_hari' => 1000,
|
||||||
'books' => [
|
|
||||||
['id' => 1, 'judul' => 'Modul Ajar IPAS'],
|
'books' => $books->map(function ($b) {
|
||||||
]
|
return [
|
||||||
],
|
'id' => $b['id'],
|
||||||
[
|
'judul' => $b['judul'],
|
||||||
'id_peminjaman' => 'PIN-202510-004',
|
'cover' => $b['cover']
|
||||||
'peminjam' => 'Dewi Lestari',
|
];
|
||||||
'nomor_hp' => '082134567891',
|
})->toArray()
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(15),
|
];
|
||||||
'tenggat_kembali' => Carbon::now()->subDays(8), // Terlambat 8 hari
|
})->values();
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 2, 'judul' => 'Modul Ajar Pendidikan Pancasila'],
|
|
||||||
['id' => 6, 'judul' => 'Matematika Dasar'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-005',
|
|
||||||
'peminjam' => 'Eko Prasetyo',
|
|
||||||
'nomor_hp' => '085612345678',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(2),
|
|
||||||
'tenggat_kembali' => Carbon::now()->addDays(5), // Sisa 5 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 9, 'judul' => 'Senja, Hujan, & Cerita yang Telah Usai'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-006',
|
|
||||||
'peminjam' => 'Rina Marlina',
|
|
||||||
'nomor_hp' => '081987654321',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(10),
|
|
||||||
'tenggat_kembali' => Carbon::now()->subDays(3), // Terlambat 3 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 4, 'judul' => 'Modul Pembelajaran Seni Budaya'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-007',
|
|
||||||
'peminjam' => 'Budi Santoso',
|
|
||||||
'nomor_hp' => '082298765432',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(6),
|
|
||||||
'tenggat_kembali' => Carbon::now()->addDays(1), // Sisa 1 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 3, 'judul' => 'Modul Belajar Sosiologi'],
|
|
||||||
['id' => 10, 'judul' => 'Hijrah itu Cinta'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-008',
|
|
||||||
'peminjam' => 'Putri Amelia',
|
|
||||||
'nomor_hp' => '085743219876',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(18),
|
|
||||||
'tenggat_kembali' => Carbon::now()->subDays(11), // Terlambat 11 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 1, 'judul' => 'Modul Ajar IPAS'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-009',
|
|
||||||
'peminjam' => 'Ahmad Haziq',
|
|
||||||
'nomor_hp' => '081345678902',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(3),
|
|
||||||
'tenggat_kembali' => Carbon::now()->addDays(4), // Sisa 4 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 7, 'judul' => 'The Last Spell Breather'],
|
|
||||||
['id' => 8, 'judul' => 'Ayah'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-010',
|
|
||||||
'peminjam' => 'John Wick',
|
|
||||||
'nomor_hp' => '082187654309',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(8),
|
|
||||||
'tenggat_kembali' => Carbon::now()->subDays(1), // Terlambat 1 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 5, 'judul' => 'Si Anak Pintar'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-011',
|
|
||||||
'peminjam' => 'Silvi Rahmawati',
|
|
||||||
'nomor_hp' => '08123456789',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(5),
|
|
||||||
'tenggat_kembali' => Carbon::now()->addDays(2), // Sisa 2 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 2, 'judul' => 'Modul Ajar Pendidikan Pancasila'],
|
|
||||||
['id' => 4, 'judul' => 'Modul Pembelajaran Seni Budaya'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-012',
|
|
||||||
'peminjam' => 'Andi Pratama',
|
|
||||||
'nomor_hp' => '081556677889',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(20),
|
|
||||||
'tenggat_kembali' => Carbon::now()->subDays(13), // Terlambat 13 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 6, 'judul' => 'Matematika Dasar'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'id_peminjaman' => 'PIN-202510-013',
|
|
||||||
'peminjam' => 'Siti Nurhaliza',
|
|
||||||
'nomor_hp' => '081998877665',
|
|
||||||
'tanggal_pinjam' => Carbon::now()->subDays(1),
|
|
||||||
'tenggat_kembali' => Carbon::now()->addDays(6), // Sisa 6 hari
|
|
||||||
'denda_per_hari' => 1000,
|
|
||||||
'books' => [
|
|
||||||
['id' => 9, 'judul' => 'Senja, Hujan, & Cerita yang Telah Usai'],
|
|
||||||
['id' => 10, 'judul' => 'Hijrah itu Cinta'],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -328,7 +214,7 @@ public static function getSiswaTeraktif(): array
|
||||||
['nama' => 'Rina Marlina', 'total_buku' => 20, 'kelas' => 'XII TKJ A'],
|
['nama' => 'Rina Marlina', 'total_buku' => 20, 'kelas' => 'XII TKJ A'],
|
||||||
['nama' => 'Budi Santoso', 'total_buku' => 18, 'kelas' => 'X OTKP'],
|
['nama' => 'Budi Santoso', 'total_buku' => 18, 'kelas' => 'X OTKP'],
|
||||||
['nama' => 'Putri Amelia', 'total_buku' => 16, 'kelas' => 'XI RPL C'],
|
['nama' => 'Putri Amelia', 'total_buku' => 16, 'kelas' => 'XI RPL C'],
|
||||||
['nama' => 'Ahmad Haziq', 'total_buku' => 12, 'kelas' => 'X TKJ B'],
|
['nama' => 'Ahmad Jono', 'total_buku' => 12, 'kelas' => 'X TKJ B'],
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -483,158 +369,157 @@ public static function getStatistikBulanan(): array
|
||||||
* @return \Illuminate\Support\Collection
|
* @return \Illuminate\Support\Collection
|
||||||
*/
|
*/
|
||||||
public static function getAllBooks()
|
public static function getAllBooks()
|
||||||
{
|
{
|
||||||
return collect([
|
return collect([
|
||||||
[
|
// --- BUKU MILIK USER 1 (SILVI) ---
|
||||||
'id' => 1,
|
[
|
||||||
'judul' => 'Modul Ajar IPAS',
|
'id' => 1,
|
||||||
'penulis' => 'Tim Kemdikbud Ristek',
|
'judul' => 'Modul Ajar IPAS',
|
||||||
'cover' => 'images/covers/ipas.jpg',
|
'penulis' => 'Tim Kemdikbud Ristek',
|
||||||
'kode_buku' => '510', // 500 (Sains)
|
'cover' => 'images/covers/ipas.jpg',
|
||||||
'kategori' => 'Sains',
|
'kode_buku' => '510',
|
||||||
'tahun' => 2022,
|
'kategori' => 'Sains',
|
||||||
'status' => 'Tersedia',
|
'tahun' => 2022,
|
||||||
'is_new' => true,
|
'status' => 'Dipinjam',
|
||||||
'tipe_akses' => ['online', 'offline'],
|
'is_new' => true,
|
||||||
'file_pdf' => 'ipas.pdf',
|
'tipe_akses' => ['online', 'offline'],
|
||||||
'progress' => 75,
|
'sisa_hari' => -5,
|
||||||
'sisa_hari' => 14,
|
'user_id' => 1,
|
||||||
'user_id' => 1,
|
],
|
||||||
],
|
[
|
||||||
[
|
'id' => 2,
|
||||||
'id' => 2,
|
'judul' => 'Perahu Kertas',
|
||||||
'judul' => 'Modul Ajar Pendidikan Pancasila',
|
'penulis' => 'Dewi Lestari',
|
||||||
'penulis' => 'Tim Guru Pancasila',
|
'cover' => 'images/covers/ayah.png',
|
||||||
'cover' => 'images/covers/pancasila.jpg',
|
'kode_buku' => '844',
|
||||||
'kode_buku'=> '370', // 370 (Pendidikan, bagian dari 300-Sosial)
|
'kategori' => 'Fiksi',
|
||||||
'kategori' => 'Pendidikan',
|
'tahun' => 2012,
|
||||||
'tahun' => 2023,
|
'status' => 'Dipinjam',
|
||||||
'status' => 'Tersedia',
|
'is_new' => false,
|
||||||
'is_new' => false,
|
'tipe_akses' => 'offline',
|
||||||
'tipe_akses' => 'offline',
|
'sisa_hari' => 3,
|
||||||
'sisa_hari' => 3,
|
'user_id' => 1,
|
||||||
'progress' => 100,
|
],
|
||||||
'user_id' => [3, 1],
|
|
||||||
],
|
// --- BUKU TERSEDIA (UNTUK CEK PEMINJAMAN BARU) ---
|
||||||
[
|
[
|
||||||
'id' => 3,
|
'id' => 3,
|
||||||
'judul' => 'Modul Belajar Sosiologi',
|
'judul' => 'Si Anak Pintar',
|
||||||
'penulis' => 'Tim Cendekia',
|
'penulis' => 'Tere Liye',
|
||||||
'cover' => 'images/covers/sosiologi.jpg',
|
'cover' => 'images/covers/sianakpintar.jpg',
|
||||||
'kode_buku' => '340', // 300 (Ilmu Sosial)
|
'kode_buku' => '843',
|
||||||
'kategori' => 'Sosial',
|
'kategori' => 'Fiksi',
|
||||||
'tahun' => 2021,
|
'tahun' => 2018,
|
||||||
'status' => 'Dipinjam',
|
'status' => 'Tersedia',
|
||||||
'is_new' => false,
|
'is_new' => true,
|
||||||
'tipe_akses' => 'offline',
|
'tipe_akses' => 'offline',
|
||||||
'sisa_hari' => 8,
|
'sisa_hari' => 0,
|
||||||
'user_id' => 3,
|
'user_id' => null,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => 4,
|
'id' => 4,
|
||||||
'judul' => 'Modul Pembelajaran Seni Budaya',
|
'judul' => 'Laskar Pelangi',
|
||||||
'penulis' => 'Cahya Wulan, S.Pd.',
|
'penulis' => 'Andrea Hirata',
|
||||||
'cover' => 'images/covers/senbud.jpg',
|
'cover' => 'https://upload.wikimedia.org/wikipedia/id/8/8e/Laskar_pelangi_sampul.jpg',
|
||||||
'kode_buku' => '752', // 700 (Seni)
|
'kode_buku' => 'NOV-001',
|
||||||
'kategori' => 'Seni',
|
'kategori' => 'Novel',
|
||||||
'tahun' => 2022,
|
'tahun' => 2005,
|
||||||
'status' => 'Dipinjam',
|
'status' => 'Tersedia',
|
||||||
'is_new' => false,
|
'is_new' => false,
|
||||||
'tipe_akses' => 'offline',
|
'tipe_akses' => 'offline',
|
||||||
'sisa_hari' => 14,
|
'sisa_hari' => 0,
|
||||||
'user_id' => [1, 3],
|
'user_id' => null,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => 5,
|
'id' => 5,
|
||||||
'judul' => 'Si Anak Pintar',
|
'judul' => 'Filosofi Teras',
|
||||||
'penulis' => 'Tere Liye',
|
'penulis' => 'Henry Manampiring',
|
||||||
'cover' => 'images/covers/sianakpintar.jpg',
|
'cover' => 'https://upload.wikimedia.org/wikipedia/id/3/36/Filosofi_Teras.jpg',
|
||||||
'kode_buku' => '843', // 800 (Fiksi/Sastra)
|
'kode_buku' => 'PSI-002',
|
||||||
'kategori' => 'Fiksi',
|
'kategori' => 'Psikologi',
|
||||||
'tahun' => 2018,
|
'tahun' => 2018,
|
||||||
'status' => 'Dipinjam',
|
'status' => 'Tersedia',
|
||||||
'is_new' => true,
|
'is_new' => true,
|
||||||
'tipe_akses' => 'offline',
|
'tipe_akses' => 'offline',
|
||||||
'sisa_hari' => 5,
|
'sisa_hari' => 0,
|
||||||
'user_id' => 1,
|
'user_id' => null,
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'id' => 6,
|
'id' => 6,
|
||||||
'judul' => 'Matematika Dasar',
|
'judul' => 'Atomic Habits',
|
||||||
'penulis' => 'Prof. Dr. Matematikus',
|
'penulis' => 'James Clear',
|
||||||
'cover' => 'images/covers/mtk.jpg',
|
'cover' => 'https://images-na.ssl-images-amazon.com/images/I/91bYsX41DVL.jpg',
|
||||||
'kode_buku' => '374', // 370 (Pendidikan)
|
'kode_buku' => 'SELF-003',
|
||||||
'kategori' => 'Pendidikan',
|
'kategori' => 'Refleksi Diri',
|
||||||
'tahun' => 2023,
|
'tahun' => 2018,
|
||||||
'status' => 'Tersedia',
|
'status' => 'Tersedia',
|
||||||
'is_new' => true,
|
'is_new' => true,
|
||||||
'tipe_akses' => ['online', 'offline'],
|
'tipe_akses' => ['offline', 'online'],
|
||||||
'file_pdf' => 'mtk.pdf',
|
'sisa_hari' => 0,
|
||||||
'sisa_hari' => 7,
|
'user_id' => null,
|
||||||
'progress' => 40,
|
],
|
||||||
'user_id' => [1, 4, 5],
|
[
|
||||||
],
|
'id' => 7,
|
||||||
[
|
'judul' => 'Bumi Manusia',
|
||||||
'id' => 7,
|
'penulis' => 'Pramoedya Ananta Toer',
|
||||||
'judul' => 'The Last Spell Breather',
|
'cover' => 'https://upload.wikimedia.org/wikipedia/id/4/44/Bumi_Manusia.jpg',
|
||||||
'penulis' => 'Julie Pike',
|
'kode_buku' => 'SAS-004',
|
||||||
'cover' => 'images/covers/thelastspellbreather.jpg',
|
'kategori' => 'Sastra',
|
||||||
'kode_buku' => '834', // 800 (Fantasi/Sastra)
|
'tahun' => 1980,
|
||||||
'kategori' => 'Fantasi',
|
'status' => 'Tersedia',
|
||||||
'tahun' => 2024,
|
'is_new' => false,
|
||||||
'status' => 'Tersedia',
|
'tipe_akses' => 'offline',
|
||||||
'is_new' => true,
|
'sisa_hari' => 0,
|
||||||
'tipe_akses' => 'offline',
|
'user_id' => null,
|
||||||
'sisa_hari' => 4,
|
],
|
||||||
'progress' => 0,
|
[
|
||||||
'user_id' => [3, 1]
|
'id' => 8,
|
||||||
],
|
'judul' => 'Laut Bercerita',
|
||||||
[
|
'penulis' => 'Leila S. Chudori',
|
||||||
'id' => 8,
|
'cover' => 'https://upload.wikimedia.org/wikipedia/id/6/6d/Laut_Bercerita.jpeg',
|
||||||
'judul' => 'Ayah',
|
'kode_buku' => 'NOV-005',
|
||||||
'penulis' => 'Andrea Hirata',
|
'kategori' => 'Novel',
|
||||||
'cover' => 'images/covers/ayah.png',
|
'tahun' => 2017,
|
||||||
'kategori' => 'Novel',
|
'status' => 'Tersedia',
|
||||||
'tahun' => 2015,
|
'is_new' => true,
|
||||||
'status' => 'Tersedia',
|
'tipe_akses' => 'offline',
|
||||||
'is_new' => true,
|
'sisa_hari' => 0,
|
||||||
'tipe_akses' => 'online',
|
'user_id' => null,
|
||||||
'file_pdf' => 'ayah.pdf',
|
],
|
||||||
'progress' => 0,
|
// --- BUKU MILIK USER 3 (SITI) - TELAT ---
|
||||||
'user_id' => [1, 2, 3],
|
[
|
||||||
],
|
'id' => 99,
|
||||||
[
|
'judul' => 'Seni Berbicara',
|
||||||
'id' => 9,
|
'penulis' => 'Larry King',
|
||||||
'judul' => 'Senja, Hujan, & Cerita yang Telah Usai',
|
'cover' => 'https://via.placeholder.com/150',
|
||||||
'penulis' => 'Boy Candra',
|
'kode_buku' => 'COM-001',
|
||||||
'cover' => 'images/covers/senja.png',
|
'kategori' => 'Refleksi Diri',
|
||||||
'kode_buku' => '845', // 800 (Novel/Sastra)
|
'tahun' => 2019,
|
||||||
'kategori' => 'Novel',
|
'status' => 'Dipinjam',
|
||||||
'tahun' => 2015,
|
'is_new' => false,
|
||||||
'status' => 'Tersedia',
|
'tipe_akses' => 'offline',
|
||||||
'is_new' => true,
|
'sisa_hari' => -2,
|
||||||
'tipe_akses' => ['online', 'offline'],
|
'user_id' => 3,
|
||||||
'file_pdf' => 'senja.pdf',
|
],
|
||||||
'progress' => 0,
|
|
||||||
'sisa_hari' => 14,
|
// --- BUKU MILIK GURU (USER 5) - TESTING MANUAL BAN ---
|
||||||
'user_id' => [1, 3],
|
[
|
||||||
],
|
'id' => 88,
|
||||||
[
|
'judul' => 'Strategi Pembelajaran Abad 21',
|
||||||
'id' => 10,
|
'penulis' => 'Prof. Dr. Pendidikan',
|
||||||
'judul' => 'Hijrah itu Cinta',
|
'cover' => 'https://via.placeholder.com/150',
|
||||||
'penulis' => 'Abay Adhitya',
|
'kode_buku' => 'GURU-001',
|
||||||
'cover' => 'images/covers/hijrah.png',
|
'kategori' => 'Pendidikan',
|
||||||
'kategori' => 'Religi',
|
'tahun' => 2020,
|
||||||
'tahun' => 2018,
|
'status' => 'Dipinjam',
|
||||||
'status' => 'Tersedia',
|
'is_new' => false,
|
||||||
'is_new' => true,
|
'tipe_akses' => 'offline',
|
||||||
'tipe_akses' => 'online',
|
'sisa_hari' => -3,
|
||||||
'file_pdf' => 'hijrah.pdf',
|
'user_id' => 5,
|
||||||
'progress' => 0,
|
],
|
||||||
'user_id' => [2, 3],
|
]);
|
||||||
]
|
}
|
||||||
]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Data untuk buku pinjam offline
|
* Data untuk buku pinjam offline
|
||||||
|
|
@ -642,9 +527,16 @@ public static function getAllBooks()
|
||||||
public static function getBukuPinjamOffline($user): array
|
public static function getBukuPinjamOffline($user): array
|
||||||
{
|
{
|
||||||
return self::getAllBooks()
|
return self::getAllBooks()
|
||||||
->where('tipe_akses', 'offline')
|
->filter(function ($buku) {
|
||||||
|
// Handle tipe akses string atau array
|
||||||
|
if (is_array($buku['tipe_akses'])) {
|
||||||
|
return in_array('offline', $buku['tipe_akses']);
|
||||||
|
}
|
||||||
|
return $buku['tipe_akses'] === 'offline';
|
||||||
|
})
|
||||||
->filter(function ($buku) use ($user) {
|
->filter(function ($buku) use ($user) {
|
||||||
if (!isset($buku['user_id'])) return false;
|
if (!isset($buku['user_id']) || $buku['user_id'] === null)
|
||||||
|
return false;
|
||||||
|
|
||||||
if (is_array($buku['user_id'])) {
|
if (is_array($buku['user_id'])) {
|
||||||
return in_array($user->id, $buku['user_id']);
|
return in_array($user->id, $buku['user_id']);
|
||||||
|
|
@ -669,7 +561,8 @@ public static function getBacaBukuOnline($user): array
|
||||||
return self::getAllBooks()
|
return self::getAllBooks()
|
||||||
->where('tipe_akses', 'online')
|
->where('tipe_akses', 'online')
|
||||||
->filter(function ($buku) use ($user) {
|
->filter(function ($buku) use ($user) {
|
||||||
if (!isset($buku['user_id'])) return false;
|
if (!isset($buku['user_id']))
|
||||||
|
return false;
|
||||||
|
|
||||||
if (is_array($buku['user_id'])) {
|
if (is_array($buku['user_id'])) {
|
||||||
return in_array($user->id, $buku['user_id']);
|
return in_array($user->id, $buku['user_id']);
|
||||||
|
|
@ -738,52 +631,47 @@ public static function getFilterOptions(): array
|
||||||
* Data untuk riwayat peminjaman offline.
|
* Data untuk riwayat peminjaman offline.
|
||||||
* Setiap item mewakili satu transaksi peminjaman.
|
* Setiap item mewakili satu transaksi peminjaman.
|
||||||
*/
|
*/
|
||||||
public static function getRiwayatOffline(): array
|
public static function getRiwayatOffline($user): array
|
||||||
{
|
{
|
||||||
return [
|
$allBooks = self::getAllBooks();
|
||||||
[
|
$myBooks = $allBooks->filter(function ($buku) use ($user) {
|
||||||
'id' => 1,
|
if (is_array($buku['user_id'])) {
|
||||||
'id_peminjaman' => 'PIN-20240520-001',
|
return in_array($user->id, $buku['user_id']);
|
||||||
'kode_buku' => '510',
|
}
|
||||||
'judul_utama' => 'Modul Ajar IPAS',
|
return $buku['user_id'] == $user->id;
|
||||||
'tanggal_pinjam' => '20/05/2024',
|
})->whereIn('status', ['Dipinjam', 'Dikembalikan', 'Terlambat']);
|
||||||
'tanggal_kembali' => '27/05/2024',
|
|
||||||
'status' => 'Dikembalikan',
|
// Mapping ke format tampilan View
|
||||||
|
return $myBooks->map(function ($buku, $index) {
|
||||||
|
|
||||||
|
// Logika Tanggal Dummy
|
||||||
|
$tglPinjam = Carbon::now()->subDays(7);
|
||||||
|
|
||||||
|
// Hitung tanggal kembali berdasarkan sisa hari di Master Data
|
||||||
|
$tglKembali = Carbon::now()->addDays($buku['sisa_hari']);
|
||||||
|
|
||||||
|
return [
|
||||||
|
'id' => $index + 1,
|
||||||
|
'id_peminjaman' => 'PIN-' . date('Ym') . '-' . sprintf('%03d', $buku['id']),
|
||||||
|
'kode_buku' => $buku['kode_buku'],
|
||||||
|
'judul_utama' => $buku['judul'],
|
||||||
|
'tanggal_pinjam' => $tglPinjam->format('d/m/Y'),
|
||||||
|
'tanggal_kembali' => $tglKembali->format('d/m/Y'),
|
||||||
|
'status' => $buku['status'],
|
||||||
'books' => [
|
'books' => [
|
||||||
[
|
[
|
||||||
'id' => 1,
|
'id' => $buku['id'],
|
||||||
'judul' => 'Modul Ajar IPAS',
|
'judul' => $buku['judul'],
|
||||||
'kode_buku' => '510',
|
'kode_buku' => $buku['kode_buku'],
|
||||||
'cover' => 'images/covers/ipas.jpg',
|
'cover' => $buku['cover'],
|
||||||
'deskripsi' => 'Buku ini berisi ajakan kepada anak-anak untuk semangat pergi ke sekolah dan menuntut ilmu.',
|
'deskripsi' => 'Deskripsi buku ' . $buku['judul'],
|
||||||
'kategori' => 'Pendidikan',
|
'kategori' => $buku['kategori'],
|
||||||
'tahun' => 2022,
|
'tahun' => $buku['tahun'],
|
||||||
'keterangan' => 'Buku dikembalikan dalam kondisi baik. Terdapat denda keterlambatan 2 hari: Rp 2.000,-'
|
'keterangan' => ($buku['sisa_hari'] < 0) ? 'Buku Terlambat' : null,
|
||||||
]
|
]
|
||||||
]
|
]
|
||||||
],
|
];
|
||||||
[
|
})->values()->toArray();
|
||||||
'id' => 2,
|
|
||||||
'id_peminjaman' => 'PIN-20240527-002',
|
|
||||||
'kode_buku' => '844',
|
|
||||||
'judul_utama' => 'Perahu Kertas',
|
|
||||||
'tanggal_pinjam' => '27/05/2024',
|
|
||||||
'tanggal_kembali' => '04/06/2024',
|
|
||||||
'status' => 'Dipinjam',
|
|
||||||
'books' => [
|
|
||||||
[
|
|
||||||
'id' => 8,
|
|
||||||
'judul' => 'Perahu Kertas',
|
|
||||||
'kode_buku' => '844',
|
|
||||||
'cover' => 'images/covers/ayah.png',
|
|
||||||
'deskripsi' => 'Cerita penggambaran pasang surut hubungan dua anak manusia, yaitu Kugy dan Keenan.',
|
|
||||||
'kategori' => 'Fiksi',
|
|
||||||
'tahun' => 2022,
|
|
||||||
'keterangan' => null,
|
|
||||||
],
|
|
||||||
]
|
|
||||||
],
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -821,79 +709,62 @@ public static function getRiwayatOnline(): array
|
||||||
public static function getNotifikasiForUser($user): array
|
public static function getNotifikasiForUser($user): array
|
||||||
{
|
{
|
||||||
$notifikasi = [];
|
$notifikasi = [];
|
||||||
|
$allBooks = self::getAllBooks();
|
||||||
|
$myBooks = $allBooks->filter(function ($buku) use ($user) {
|
||||||
|
if (!isset($buku['user_id']) || $buku['user_id'] === null) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$bukuPinjaman = self::getBukuPinjamOffline($user);
|
if (is_array($buku['user_id'])) {
|
||||||
|
return in_array($user->id, $buku['user_id']);
|
||||||
|
}
|
||||||
|
return $buku['user_id'] == $user->id;
|
||||||
|
});
|
||||||
|
|
||||||
if (!empty($bukuPinjaman)) {
|
foreach ($myBooks as $buku) {
|
||||||
$bukuTerbaru = $bukuPinjaman[0];
|
// LOGIC TELAT
|
||||||
$notifikasi[] = [
|
if ($buku['sisa_hari'] < 0 && $buku['status'] == 'Dipinjam') {
|
||||||
'icon' => 'bi-check2-circle',
|
$hariTelat = abs($buku['sisa_hari']);
|
||||||
'color' => 'success',
|
$denda = $hariTelat * 1000;
|
||||||
'title' => 'Buku "' . $bukuTerbaru['judul'] . '" berhasil dipinjam.',
|
|
||||||
'time' => '5 menit yang lalu',
|
|
||||||
'read' => false,
|
|
||||||
'type' => 'riwayat_peminjaman',
|
|
||||||
'link_id' => null,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
foreach ($bukuPinjaman as $buku) {
|
|
||||||
if ($buku['sisa_hari'] <= 3) {
|
|
||||||
$notifikasi[] = [
|
$notifikasi[] = [
|
||||||
'icon' => 'bi-exclamation-triangle',
|
'icon' => 'bi-exclamation-octagon-fill',
|
||||||
'color' => 'danger',
|
'color' => 'danger',
|
||||||
'title' => 'Buku "' . $buku['judul'] . '" akan jatuh tempo!',
|
'title' => 'TERLAMBAT: ' . $buku['judul'],
|
||||||
'time' => '1 jam yang lalu',
|
'content' => "Telat {$hariTelat} hari. Denda: Rp " . number_format($denda, 0, ',', '.'),
|
||||||
|
'time' => 'Sekarang',
|
||||||
'read' => false,
|
'read' => false,
|
||||||
'type' => 'riwayat_peminjaman',
|
'type' => 'denda_active',
|
||||||
|
'link_id' => null,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
// LOGIC JATUH TEMPO
|
||||||
|
elseif ($buku['sisa_hari'] >= 0 && $buku['sisa_hari'] <= 3 && $buku['status'] == 'Dipinjam') {
|
||||||
|
$notifikasi[] = [
|
||||||
|
'icon' => 'bi-exclamation-triangle-fill',
|
||||||
|
'color' => 'warning',
|
||||||
|
'title' => 'Jatuh Tempo: ' . $buku['judul'],
|
||||||
|
'content' => "Sisa waktu tinggal " . $buku['sisa_hari'] . " hari lagi.",
|
||||||
|
'time' => 'Segera',
|
||||||
|
'read' => false,
|
||||||
|
'type' => 'warning_jatuh_tempo',
|
||||||
'link_id' => null,
|
'link_id' => null,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if ($user->role === 'guru') {
|
// Notif Default
|
||||||
$notifikasi[] = [
|
$notifikasi[] = [
|
||||||
'icon' => 'bi-lightbulb-fill',
|
'icon' => 'bi-info-circle-fill',
|
||||||
'color' => 'success',
|
'color' => 'primary',
|
||||||
'title' => 'Rekomendasi pembelajaran baru telah ditambahkan.',
|
'title' => 'Selamat Datang di DigiPus!',
|
||||||
'time' => 'Kemarin',
|
'content' => 'Silakan jelajahi koleksi buku terbaru kami.',
|
||||||
'read' => true,
|
'time' => 'Baru saja',
|
||||||
'type' => 'rekomendasi',
|
'read' => true,
|
||||||
'link_id' => 1,
|
'type' => 'info',
|
||||||
];
|
'link_id' => null,
|
||||||
}
|
|
||||||
|
|
||||||
$notifikasiUmum = [
|
|
||||||
[
|
|
||||||
'icon' => 'bi-book-half',
|
|
||||||
'color' => 'info',
|
|
||||||
'title' => 'Buku baru ditambahkan ke kategori Fiksi.',
|
|
||||||
'time' => '3 jam yang lalu',
|
|
||||||
'read' => false,
|
|
||||||
'type' => 'katalog_kategori',
|
|
||||||
'link_id' => 'Fiksi',
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'icon' => 'bi-megaphone-fill',
|
|
||||||
'color' => 'warning',
|
|
||||||
'title' => 'Perpustakaan akan tutup lebih awal pada hari Jumat.',
|
|
||||||
'time' => '1 hari yang lalu',
|
|
||||||
'read' => true,
|
|
||||||
'type' => 'halaman_profil',
|
|
||||||
'link_id' => null,
|
|
||||||
],
|
|
||||||
[
|
|
||||||
'icon' => 'bi-calendar-event',
|
|
||||||
'color' => 'primary',
|
|
||||||
'title' => 'Acara "Bedah Buku" akan diadakan minggu depan.',
|
|
||||||
'time' => '2 hari yang lalu',
|
|
||||||
'read' => true,
|
|
||||||
'type' => 'halaman_profil',
|
|
||||||
'link_id' => null,
|
|
||||||
],
|
|
||||||
];
|
];
|
||||||
|
|
||||||
return array_merge($notifikasi, $notifikasiUmum);
|
return $notifikasi;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -825,7 +825,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
"resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.11.8.tgz",
|
||||||
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
"integrity": "sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"funding": {
|
"funding": {
|
||||||
"type": "opencollective",
|
"type": "opencollective",
|
||||||
"url": "https://opencollective.com/popperjs"
|
"url": "https://opencollective.com/popperjs"
|
||||||
|
|
@ -2590,7 +2589,6 @@
|
||||||
"resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz",
|
"resolved": "https://registry.npmjs.org/sass/-/sass-1.93.2.tgz",
|
||||||
"integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==",
|
"integrity": "sha512-t+YPtOQHpGW1QWsh1CHQ5cPIr9lbbGZLZnbihP/D/qZj/yuV68m8qarcV17nvkOX81BCrvzAlq2klCQFZghyTg==",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"chokidar": "^4.0.0",
|
"chokidar": "^4.0.0",
|
||||||
"immutable": "^5.0.2",
|
"immutable": "^5.0.2",
|
||||||
|
|
@ -2677,8 +2675,7 @@
|
||||||
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.16.tgz",
|
"resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.16.tgz",
|
||||||
"integrity": "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==",
|
"integrity": "sha512-pONL5awpaQX4LN5eiv7moSiSPd/DLDzKVRJz8Q9PgzmAdd1R4307GQS2ZpfiN7ZmekdQrfhZZiSE5jkLR4WNaA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT"
|
||||||
"peer": true
|
|
||||||
},
|
},
|
||||||
"node_modules/tapable": {
|
"node_modules/tapable": {
|
||||||
"version": "2.3.0",
|
"version": "2.3.0",
|
||||||
|
|
@ -2735,7 +2732,6 @@
|
||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
|
|
@ -2779,7 +2775,6 @@
|
||||||
"integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==",
|
"integrity": "sha512-ZWyE8YXEXqJrrSLvYgrRP7p62OziLW7xI5HYGWFzOvupfAlrLvURSzv/FyGyy0eidogEM3ujU+kUG1zuHgb6Ug==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"esbuild": "^0.25.0",
|
"esbuild": "^0.25.0",
|
||||||
"fdir": "^6.5.0",
|
"fdir": "^6.5.0",
|
||||||
|
|
@ -2884,7 +2879,6 @@
|
||||||
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
"integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"peer": true,
|
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,7 @@ if (formPeminjamanElement) {
|
||||||
const bukuAwal = JSON.parse(formPeminjamanElement.dataset.bukuAwal);
|
const bukuAwal = JSON.parse(formPeminjamanElement.dataset.bukuAwal);
|
||||||
|
|
||||||
let bukuTerpilih = [bukuAwal.id];
|
let bukuTerpilih = [bukuAwal.id];
|
||||||
const maxBuku = 3;
|
const maxBuku = 2;
|
||||||
|
|
||||||
document.addEventListener('DOMContentLoaded', function () {
|
document.addEventListener('DOMContentLoaded', function () {
|
||||||
updateCounter();
|
updateCounter();
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,248 @@
|
||||||
|
<x-app-layout>
|
||||||
|
@section('page-title', 'Manajemen Denda')
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-4">
|
||||||
|
<div>
|
||||||
|
<h3 class="my-0 fw-bold">Manajemen Denda & Sanksi</h3>
|
||||||
|
<p class="text-muted mb-0">Pantau siswa terlambat dan berikan sanksi jika diperlukan.</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{-- FILTER SECTION --}}
|
||||||
|
<div class="card border-0 shadow-sm mb-4">
|
||||||
|
<div class="card-body py-3">
|
||||||
|
<div class="row g-3 align-items-center">
|
||||||
|
<div class="col-md-auto">
|
||||||
|
<span class="fw-bold text-muted"><i class="bi bi-funnel-fill me-1"></i> Filter Data:</span>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select id="filterKelas" class="form-select form-select-sm">
|
||||||
|
<option value="">Semua Kelas</option>
|
||||||
|
@foreach ($listKelas as $kelas)
|
||||||
|
<option value="{{ $kelas }}">{{ $kelas }}</option>
|
||||||
|
@endforeach
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<select id="filterBesaran" class="form-select form-select-sm">
|
||||||
|
<option value="">Semua Nominal</option>
|
||||||
|
<option value="ringan">Denda Ringan (< Rp 10.000)</option>
|
||||||
|
<option value="berat">Denda Berat (> Rp 10.000)</option>
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-auto ms-auto">
|
||||||
|
<button id="resetFilter" class="btn btn-sm btn-light border text-muted">
|
||||||
|
<i class="bi bi-arrow-counterclockwise"></i> Reset
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="card border-0 shadow-sm">
|
||||||
|
<div class="card-body">
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table id="dendaTable" class="table table-striped table-hover align-middle" style="width:100%">
|
||||||
|
<thead class="table-light">
|
||||||
|
<tr>
|
||||||
|
<th class="text-center" width="5%">NO</th>
|
||||||
|
<th width="25%">SISWA & KELAS</th>
|
||||||
|
<th width="25%">BUKU TERLAMBAT</th>
|
||||||
|
<th width="15%">STATUS</th>
|
||||||
|
<th width="15%">DENDA</th>
|
||||||
|
<th width="15%">AKSI</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@forelse ($siswaTelat as $item)
|
||||||
|
<tr>
|
||||||
|
<td class="text-center">{{ $loop->iteration }}</td>
|
||||||
|
<td>
|
||||||
|
<div class="fw-bold text-dark">{{ $item['peminjam'] }}</div>
|
||||||
|
<span
|
||||||
|
class="badge bg-light text-secondary border mt-1 mb-1">{{ $item['kelas'] }}</span>
|
||||||
|
<div class="small text-muted"><i
|
||||||
|
class="bi bi-telephone me-1"></i>{{ $item['nomor_hp'] }}</div>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<ul class="mb-0 ps-3 small text-muted">
|
||||||
|
@foreach ($item['books'] as $buku)
|
||||||
|
<li>{{ $buku['judul'] }}</li>
|
||||||
|
@endforeach
|
||||||
|
</ul>
|
||||||
|
</td>
|
||||||
|
<td data-order="{{ $item['tenggat_kembali']->timestamp }}">
|
||||||
|
<span
|
||||||
|
class="badge bg-danger-subtle text-danger border border-danger-subtle rounded-pill px-3">
|
||||||
|
Telat {{ $item['hari_terlambat'] }} Hari
|
||||||
|
</span>
|
||||||
|
<div class="small text-muted mt-1">
|
||||||
|
Tenggat: {{ $item['tenggat_kembali']->format('d/m/Y') }}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
|
||||||
|
<td data-order="{{ $item['total_denda'] }}">
|
||||||
|
<div class="fw-bold text-danger">Rp
|
||||||
|
{{ number_format($item['total_denda'], 0, ',', '.') }}</div>
|
||||||
|
<small class="text-muted" style="font-size: 0.75rem;">Rp 1.000/hari</small>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="d-flex gap-2">
|
||||||
|
{{-- Tombol WA --}}
|
||||||
|
<a href="{{ $item['wa_link'] }}" target="_blank"
|
||||||
|
class="btn btn-sm btn-success text-white" title="Tagih via WhatsApp">
|
||||||
|
<i class="bi bi-whatsapp"></i>
|
||||||
|
</a>
|
||||||
|
|
||||||
|
{{-- LOGIC TOMBOL AKTIFKAN / SANKSI --}}
|
||||||
|
@if ($item['is_banned'])
|
||||||
|
{{-- Jika sudah dibekukan (Otomatis/Manual), muncul tombol AKTIFKAN --}}
|
||||||
|
<button class="btn btn-sm btn-outline-success btn-aktifkan"
|
||||||
|
data-nama="{{ $item['peminjam'] }}" title="Aktifkan Kembali Akun">
|
||||||
|
<i class="bi bi-shield-check"></i> Aktifkan
|
||||||
|
</button>
|
||||||
|
@else
|
||||||
|
{{-- Jika belum dibekukan, muncul tombol SANKSI (Manual) --}}
|
||||||
|
<button class="btn btn-sm btn-outline-danger btn-sanksi"
|
||||||
|
data-nama="{{ $item['peminjam'] }}" title="Berikan Sanksi">
|
||||||
|
<i class="bi bi-slash-circle"></i> Sanksi
|
||||||
|
</button>
|
||||||
|
@endif
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@empty
|
||||||
|
<tr>
|
||||||
|
<td colspan="6" class="text-center py-5">
|
||||||
|
<div class="text-muted opacity-50">
|
||||||
|
<i class="bi bi-emoji-smile fs-1 mb-2 d-block"></i>
|
||||||
|
<p class="mb-0">Tidak ada siswa yang terlambat hari ini.</p>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforelse
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
@push('scripts')
|
||||||
|
<script>
|
||||||
|
$(document).ready(function() {
|
||||||
|
var table = $('#dendaTable').DataTable({
|
||||||
|
order: [
|
||||||
|
[3, 'desc']
|
||||||
|
],
|
||||||
|
|
||||||
|
columnDefs: [{
|
||||||
|
"searchable": false,
|
||||||
|
"orderable": false,
|
||||||
|
"targets": 0
|
||||||
|
}],
|
||||||
|
|
||||||
|
language: {
|
||||||
|
search: "_INPUT_",
|
||||||
|
searchPlaceholder: "Cari nama siswa..."
|
||||||
|
},
|
||||||
|
dom: 'rtip'
|
||||||
|
});
|
||||||
|
|
||||||
|
table.on('order.dt search.dt', function() {
|
||||||
|
table.column(0, {
|
||||||
|
search: 'applied',
|
||||||
|
order: 'applied'
|
||||||
|
}).nodes().each(function(cell, i) {
|
||||||
|
cell.innerHTML = i + 1;
|
||||||
|
});
|
||||||
|
}).draw();
|
||||||
|
|
||||||
|
$.fn.dataTable.ext.search.push(
|
||||||
|
function(settings, data, dataIndex) {
|
||||||
|
var filterKelas = $('#filterKelas').val();
|
||||||
|
var filterBesaran = $('#filterBesaran').val();
|
||||||
|
var dataSiswa = data[1] || "";
|
||||||
|
var dataDendaRaw = data[4] || "0";
|
||||||
|
var dataDenda = parseInt(dataDendaRaw.replace(/[^0-9]/g, ''), 10);
|
||||||
|
|
||||||
|
if (filterKelas !== "" && !dataSiswa.includes(filterKelas)) return false;
|
||||||
|
if (filterBesaran === "ringan" && dataDenda >= 10000) return false;
|
||||||
|
if (filterBesaran === "berat" && dataDenda < 10000) return false;
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
$('#filterKelas, #filterBesaran').change(function() {
|
||||||
|
table.draw();
|
||||||
|
});
|
||||||
|
$('#resetFilter').click(function() {
|
||||||
|
$('#filterKelas').val('');
|
||||||
|
$('#filterBesaran').val('');
|
||||||
|
table.draw();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// --- LOGIC TOMBOL SANKSI ---
|
||||||
|
$(document).on('click', '.btn-sanksi', function() {
|
||||||
|
const nama = $(this).data('nama');
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Nonaktifkan Guru?',
|
||||||
|
text: `Apakah Anda yakin ingin memberikan sanksi pembekuan akun kepada ${nama}?`,
|
||||||
|
icon: 'warning',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Bekukan',
|
||||||
|
confirmButtonColor: '#dc3545',
|
||||||
|
cancelButtonText: 'Batal'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Memproses...',
|
||||||
|
timer: 1000,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Sanksi Diterapkan',
|
||||||
|
text: `Akun ${nama} berhasil dibekukan.`
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
// Logic Tombol Aktifkan (Unban)
|
||||||
|
$(document).on('click', '.btn-aktifkan', function() {
|
||||||
|
const nama = $(this).data('nama');
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Aktifkan Akun?',
|
||||||
|
text: `Pastikan ${nama} sudah melunasi denda. Akun akan diaktifkan kembali.`,
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Aktifkan',
|
||||||
|
confirmButtonColor: '#198754',
|
||||||
|
cancelButtonText: 'Batal'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
// Simulasi Loading & Sukses
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Memproses...',
|
||||||
|
timer: 1000,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
})
|
||||||
|
.then(() => {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Akun Diaktifkan',
|
||||||
|
text: `Status sanksi pada ${nama} telah dicabut.`
|
||||||
|
});
|
||||||
|
$(this).closest('td').html('<span class="badge bg-success">Aktif</span>');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
</script>
|
||||||
|
@endpush
|
||||||
|
</x-app-layout>
|
||||||
|
|
@ -25,7 +25,11 @@
|
||||||
@foreach ($groupedUsers as $role => $users)
|
@foreach ($groupedUsers as $role => $users)
|
||||||
<optgroup label="{{ ucfirst($role) }}">
|
<optgroup label="{{ ucfirst($role) }}">
|
||||||
@foreach ($users as $user)
|
@foreach ($users as $user)
|
||||||
<option value="{{ $user['id'] }}">{{ $user['nama_lengkap'] }}</option>
|
{{-- Logic Disable User --}}
|
||||||
|
<option value="{{ $user['id'] }}"
|
||||||
|
{{ $user['disabled'] ? 'disabled' : '' }}>
|
||||||
|
{{ $user['nama_lengkap'] }} {{ $user['status_text'] }}
|
||||||
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</optgroup>
|
</optgroup>
|
||||||
@endforeach
|
@endforeach
|
||||||
|
|
@ -40,8 +44,8 @@
|
||||||
</div>
|
</div>
|
||||||
<div class="col-md-6">
|
<div class="col-md-6">
|
||||||
<label for="tanggal_kembali" class="form-label">Tenggat Kembali</label>
|
<label for="tanggal_kembali" class="form-label">Tenggat Kembali</label>
|
||||||
<input type="text" class="form-control" id="tanggal_kembali"
|
<input type="text" class="form-control" id="tanggal_kembali" name="tanggal_kembali"
|
||||||
name="tanggal_kembali" placeholder="Pilih tenggat kembali">
|
placeholder="Pilih tenggat kembali">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
@ -57,7 +61,7 @@
|
||||||
<i class="bi bi-collection fs-1" style="opacity: 0.25;"></i>
|
<i class="bi bi-collection fs-1" style="opacity: 0.25;"></i>
|
||||||
<p class="mb-0 mt-2">Belum ada buku yang dipilih.</p>
|
<p class="mb-0 mt-2">Belum ada buku yang dipilih.</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div id="hiddenInputs"></div>
|
<div id="hiddenInputs"></div>
|
||||||
|
|
||||||
|
|
@ -96,19 +100,16 @@
|
||||||
<div class="d-flex align-items-center book-item-list"
|
<div class="d-flex align-items-center book-item-list"
|
||||||
onclick="toggleBookSelection(this, {{ $buku['id'] }})"
|
onclick="toggleBookSelection(this, {{ $buku['id'] }})"
|
||||||
style="cursor: pointer;">
|
style="cursor: pointer;">
|
||||||
<img src="{{ asset($buku['cover']) }}" alt="Cover"
|
<img src="{{ asset($buku['cover']) }}" alt="Cover" class="rounded me-3"
|
||||||
class="rounded me-3"
|
|
||||||
style="width: 50px; height: 70px; object-fit: cover;">
|
style="width: 50px; height: 70px; object-fit: cover;">
|
||||||
<div class="flex-grow-1">
|
<div class="flex-grow-1">
|
||||||
<h6 class="fw-bold mb-1 line-clamp-2">{{ $buku['judul'] }}</h6>
|
<h6 class="fw-bold mb-1 line-clamp-2">{{ $buku['judul'] }}</h6>
|
||||||
<p class="text-muted small mb-1">{{ $buku['penulis'] }}</p>
|
<p class="text-muted small mb-1">{{ $buku['penulis'] }}</p>
|
||||||
<span
|
<span class="badge bg-info-soft">{{ $buku['kategori'] }}</span>
|
||||||
class="badge bg-info-soft">{{ $buku['kategori'] }}</span>
|
|
||||||
</div>
|
</div>
|
||||||
<div class="form-check ms-3">
|
<div class="form-check ms-3">
|
||||||
<input class="form-check-input book-checkbox" type="checkbox"
|
<input class="form-check-input book-checkbox" type="checkbox"
|
||||||
value="{{ $buku['id'] }}"
|
value="{{ $buku['id'] }}" id="book-check-{{ $buku['id'] }}"
|
||||||
id="book-check-{{ $buku['id'] }}"
|
|
||||||
style="pointer-events: none;">
|
style="pointer-events: none;">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -125,9 +126,6 @@ class="badge bg-info-soft">{{ $buku['kategori'] }}</span>
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
|
|
||||||
// Inisialisasi Library & Simpan Instansinya
|
|
||||||
|
|
||||||
const tomSelect = new TomSelect("#peminjam_id", {
|
const tomSelect = new TomSelect("#peminjam_id", {
|
||||||
create: false,
|
create: false,
|
||||||
sortField: {
|
sortField: {
|
||||||
|
|
@ -160,8 +158,7 @@ class="badge bg-info-soft">{{ $buku['kategori'] }}</span>
|
||||||
|
|
||||||
|
|
||||||
// Logika Pemilihan Buku
|
// Logika Pemilihan Buku
|
||||||
|
const MAX_BOOKS = 2;
|
||||||
const MAX_BOOKS = 3;
|
|
||||||
let selectedBookIds = new Set();
|
let selectedBookIds = new Set();
|
||||||
const allBooks = new Map();
|
const allBooks = new Map();
|
||||||
document.querySelectorAll('.book-option').forEach(el => {
|
document.querySelectorAll('.book-option').forEach(el => {
|
||||||
|
|
@ -257,7 +254,8 @@ function renderSelectedBooks() {
|
||||||
const stringId = String(id);
|
const stringId = String(id);
|
||||||
selectedBookIds.delete(stringId);
|
selectedBookIds.delete(stringId);
|
||||||
|
|
||||||
const itemElement = document.querySelector(`.book-option[data-book-id="${id}"] .book-item-list`);
|
const itemElement = document.querySelector(
|
||||||
|
`.book-option[data-book-id="${id}"] .book-item-list`);
|
||||||
if (itemElement) {
|
if (itemElement) {
|
||||||
itemElement.querySelector('.book-checkbox').checked = false;
|
itemElement.querySelector('.book-checkbox').checked = false;
|
||||||
itemElement.style.background = 'transparent';
|
itemElement.style.background = 'transparent';
|
||||||
|
|
@ -266,8 +264,6 @@ function renderSelectedBooks() {
|
||||||
renderSelectedBooks();
|
renderSelectedBooks();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Logika Reset Saat Reload Halaman
|
|
||||||
|
|
||||||
const form = document.getElementById('formPeminjaman');
|
const form = document.getElementById('formPeminjaman');
|
||||||
form.reset();
|
form.reset();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,8 @@
|
||||||
<div class="card border-0 shadow-sm">
|
<div class="card border-0 shadow-sm">
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="table-responsive">
|
<div class="table-responsive">
|
||||||
<table id="peminjamanTable" class="table table-striped table-hover nowrap dt-responsive" style="width:100%">
|
<table id="peminjamanTable" class="table table-striped table-hover nowrap dt-responsive"
|
||||||
|
style="width:100%">
|
||||||
<thead class="table-light">
|
<thead class="table-light">
|
||||||
<tr>
|
<tr>
|
||||||
<th>NO</th>
|
<th>NO</th>
|
||||||
|
|
@ -32,6 +33,7 @@
|
||||||
$now = \Carbon\Carbon::now();
|
$now = \Carbon\Carbon::now();
|
||||||
$counter = 1;
|
$counter = 1;
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@forelse ($peminjamanAktif as $transaksi)
|
@forelse ($peminjamanAktif as $transaksi)
|
||||||
@php
|
@php
|
||||||
$tenggat = $transaksi['tenggat_kembali'];
|
$tenggat = $transaksi['tenggat_kembali'];
|
||||||
|
|
@ -39,177 +41,178 @@
|
||||||
$isHariIni = $now->startOfDay()->isSameDay($tenggat->startOfDay());
|
$isHariIni = $now->startOfDay()->isSameDay($tenggat->startOfDay());
|
||||||
$selisihHari = $now->startOfDay()->diffInDays($tenggat->startOfDay(), false);
|
$selisihHari = $now->startOfDay()->diffInDays($tenggat->startOfDay(), false);
|
||||||
|
|
||||||
$statusKeterlambatan = '';
|
|
||||||
$dendaKeterlambatan = 0;
|
|
||||||
$statusClass = '';
|
|
||||||
|
|
||||||
if ($isTerlambat) {
|
if ($isTerlambat) {
|
||||||
$hariTerlambat = $tenggat->startOfDay()->diffInDays($now->startOfDay());
|
|
||||||
$statusKeterlambatan = "Terlambat $hariTerlambat hari";
|
|
||||||
$dendaKeterlambatan = $hariTerlambat * $transaksi['denda_per_hari'];
|
|
||||||
$statusClass = 'badge rounded-pill bg-danger-subtle text-danger-emphasis';
|
$statusClass = 'badge rounded-pill bg-danger-subtle text-danger-emphasis';
|
||||||
|
$statusText =
|
||||||
|
'Terlambat ' . $tenggat->startOfDay()->diffInDays($now->startOfDay()) . ' hari';
|
||||||
} elseif ($isHariIni) {
|
} elseif ($isHariIni) {
|
||||||
$statusKeterlambatan = 'Hari ini';
|
|
||||||
$statusClass = 'badge rounded-pill bg-warning-subtle text-warning-emphasis';
|
$statusClass = 'badge rounded-pill bg-warning-subtle text-warning-emphasis';
|
||||||
|
$statusText = 'Jatuh Tempo Hari Ini';
|
||||||
} else {
|
} else {
|
||||||
$sisaHari = abs($selisihHari);
|
|
||||||
$statusKeterlambatan = "Sisa $sisaHari hari";
|
|
||||||
$statusClass = 'badge rounded-pill bg-success-subtle text-success-emphasis';
|
$statusClass = 'badge rounded-pill bg-success-subtle text-success-emphasis';
|
||||||
|
$statusText = 'Sisa ' . abs($selisihHari) . ' hari';
|
||||||
}
|
}
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
@foreach ($transaksi['books'] as $index => $buku)
|
<tr>
|
||||||
<tr>
|
<td>{{ $counter++ }}</td>
|
||||||
<td>{{ $counter++ }}</td>
|
<td>
|
||||||
<td>
|
<span
|
||||||
<span
|
class="badge bg-primary-subtle text-primary fw-bold">{{ $transaksi['id_peminjaman'] }}</span>
|
||||||
class="badge bg-primary-light text-primary fw-semibold">{{ $transaksi['id_peminjaman'] }}</span>
|
</td>
|
||||||
</td>
|
<td>
|
||||||
<td>{{ $transaksi['peminjam'] }}</td>
|
<div class="fw-bold">{{ $transaksi['peminjam'] }}</div>
|
||||||
<td>{{ $buku['judul'] }}</td>
|
<div class="small text-muted">{{ $transaksi['nomor_hp'] }}</div>
|
||||||
<td>{{ $transaksi['tanggal_pinjam']->format('d/m/Y') }}</td>
|
</td>
|
||||||
<td>{{ $transaksi['tenggat_kembali']->format('d/m/Y') }}</td>
|
<td>
|
||||||
<td>
|
<ul class="mb-0 ps-3 small">
|
||||||
<span class="badge {{ $statusClass }}">{{ $statusKeterlambatan }}</span>
|
@foreach ($transaksi['books'] as $buku)
|
||||||
</td>
|
<li>{{ $buku['judul'] }}</li>
|
||||||
<td>
|
@endforeach
|
||||||
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal"
|
</ul>
|
||||||
data-bs-target="#modalPengembalian-{{ $transaksi['id_peminjaman'] }}-{{ $buku['id'] }}">
|
</td>
|
||||||
Proses
|
<td>{{ $transaksi['tanggal_pinjam']->format('d/m/Y') }}</td>
|
||||||
</button>
|
<td>{{ $transaksi['tenggat_kembali']->format('d/m/Y') }}</td>
|
||||||
</td>
|
<td>
|
||||||
</tr>
|
<span class="{{ $statusClass }}">{{ $statusText }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-sm btn-outline-primary" data-bs-toggle="modal"
|
||||||
|
data-bs-target="#modalPengembalian-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
Proses Pengembalian
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
|
||||||
<div class="modal fade"
|
{{-- MODAL PENGEMBALIAN --}}
|
||||||
id="modalPengembalian-{{ $transaksi['id_peminjaman'] }}-{{ $buku['id'] }}"
|
<div class="modal fade" id="modalPengembalian-{{ $transaksi['id_peminjaman'] }}"
|
||||||
tabindex="-1" aria-labelledby="modalLabel-{{ $buku['id'] }}" aria-hidden="true">
|
tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg modal-dialog-centered">
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||||
<div class="modal-content border-0 shadow-lg rounded-3">
|
<div class="modal-content border-0 shadow-lg rounded-3">
|
||||||
<div class="modal-header p-4">
|
<div class="modal-header p-4">
|
||||||
<h1 class="modal-title fs-5" id="modalLabel-{{ $buku['id'] }}">
|
<h5 class="modal-title fw-bold">Proses Pengembalian
|
||||||
Proses Pengembalian Buku</h1>
|
({{ count($transaksi['books']) }} Buku)
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
</h5>
|
||||||
aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal"
|
||||||
|
aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
<div class="modal-body p-4">
|
||||||
|
<div class="alert alert-light border mb-4">
|
||||||
|
<div class="d-flex justify-content-between">
|
||||||
|
<span>Peminjam:
|
||||||
|
<strong>{{ $transaksi['peminjam'] }}</strong></span>
|
||||||
|
<span>ID: <strong>{{ $transaksi['id_peminjaman'] }}</strong></span>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body p-4">
|
|
||||||
<div class="row g-4">
|
|
||||||
<div class="col-md-6">
|
|
||||||
<h6 class="fw-bold">Informasi Peminjaman</h6>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label small text-muted">Nama
|
|
||||||
Peminjam</label>
|
|
||||||
<input type="text" class="form-control"
|
|
||||||
value="{{ $transaksi['peminjam'] }}" readonly>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3">
|
|
||||||
<label class="form-label small text-muted">Judul
|
|
||||||
Buku</label>
|
|
||||||
<input type="text" class="form-control"
|
|
||||||
value="{{ $buku['judul'] }}" readonly>
|
|
||||||
</div>
|
|
||||||
<hr>
|
|
||||||
<h6 class="fw-bold">1. Kondisi Buku</h6>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input radio-kondisi" type="radio"
|
|
||||||
name="kondisi_buku_{{ $buku['id'] }}"
|
|
||||||
id="kondisi_baik_{{ $buku['id'] }}" value="baik"
|
|
||||||
checked data-denda="0">
|
|
||||||
<label class="form-check-label"
|
|
||||||
for="kondisi_baik_{{ $buku['id'] }}">
|
|
||||||
Kondisi Baik
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check">
|
|
||||||
<input class="form-check-input radio-kondisi" type="radio"
|
|
||||||
name="kondisi_buku_{{ $buku['id'] }}"
|
|
||||||
id="kondisi_rusak_{{ $buku['id'] }}" value="rusak"
|
|
||||||
data-denda="0">
|
|
||||||
<label class="form-check-label"
|
|
||||||
for="kondisi_rusak_{{ $buku['id'] }}">
|
|
||||||
Buku Rusak
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-check mb-3">
|
|
||||||
<input class="form-check-input radio-kondisi" type="radio"
|
|
||||||
name="kondisi_buku_{{ $buku['id'] }}"
|
|
||||||
id="kondisi_hilang_{{ $buku['id'] }}" value="hilang"
|
|
||||||
data-denda="0">
|
|
||||||
<label class="form-check-label"
|
|
||||||
for="kondisi_hilang_{{ $buku['id'] }}">
|
|
||||||
Buku Hilang
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="mb-3 d-none denda-rusak-input-wrapper">
|
|
||||||
<label class="form-label text-danger">Denda
|
|
||||||
Kerusakan/Kehilangan (Rp)</label>
|
|
||||||
<input type="number" class="form-control denda-rusak-input"
|
|
||||||
value="0" placeholder="Masukkan nominal denda">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<div class="col-md-6">
|
<h6 class="fw-bold mb-3">Daftar Buku yang Dikembalikan:</h6>
|
||||||
<h6 class="fw-bold">2. Status Keterlambatan</h6>
|
|
||||||
<div class="mb-3">
|
@foreach ($transaksi['books'] as $buku)
|
||||||
<label class="form-label small text-muted">Status</label>
|
<div class="card mb-3 border bg-light">
|
||||||
<input type="text" class="form-control"
|
<div class="card-body p-3">
|
||||||
value="{{ $statusKeterlambatan }}" readonly>
|
<h6 class="fw-bold text-primary mb-2">{{ $buku['judul'] }}</h6>
|
||||||
</div>
|
<div class="row">
|
||||||
<div class="mb-3">
|
<div class="col-md-6">
|
||||||
<label class="form-label small text-muted">Denda
|
<label class="form-label small text-muted mb-1">Kondisi
|
||||||
Keterlambatan</label>
|
Buku</label>
|
||||||
<input type="text"
|
<div class="d-flex gap-3">
|
||||||
class="form-control denda-keterlambatan-display"
|
<div class="form-check">
|
||||||
value="Rp {{ number_format($dendaKeterlambatan, 0, ',', '.') }}"
|
<input class="form-check-input radio-kondisi"
|
||||||
readonly
|
type="radio"
|
||||||
data-denda-keterlambatan="{{ $dendaKeterlambatan }}">
|
name="kondisi_{{ $buku['id'] }}_{{ $transaksi['id_peminjaman'] }}"
|
||||||
</div>
|
value="baik" checked>
|
||||||
<hr>
|
<label
|
||||||
<h6 class="fw-bold">3. Rangkuman & Aksi</h6>
|
class="form-check-label small">Baik</label>
|
||||||
<div class="mb-3">
|
</div>
|
||||||
<label for="catatan_petugas_{{ $buku['id'] }}"
|
<div class="form-check">
|
||||||
class="form-label small text-muted">Catatan Petugas
|
<input class="form-check-input radio-kondisi"
|
||||||
(Opsional)
|
type="radio"
|
||||||
</label>
|
name="kondisi_{{ $buku['id'] }}_{{ $transaksi['id_peminjaman'] }}"
|
||||||
<textarea class="form-control" id="catatan_petugas_{{ $buku['id'] }}" rows="2"></textarea>
|
value="rusak">
|
||||||
</div>
|
<label
|
||||||
<div class="form-check form-switch mb-3">
|
class="form-check-label small">Rusak/Hilang</label>
|
||||||
<input class="form-check-input" type="checkbox"
|
</div>
|
||||||
role="switch" id="notif_wa_{{ $buku['id'] }}"
|
</div>
|
||||||
checked>
|
</div>
|
||||||
<label class="form-check-label"
|
<div class="col-md-6 denda-rusak-input-wrapper d-none">
|
||||||
for="notif_wa_{{ $buku['id'] }}">
|
<label class="form-label small text-muted mb-1">Denda
|
||||||
Kirim notifikasi ke WA ({{ $transaksi['nomor_hp'] }})
|
Kerusakan</label>
|
||||||
</label>
|
<input type="number"
|
||||||
</div>
|
class="form-control form-control-sm denda-rusak-input"
|
||||||
<div class="p-3 bg-primary-light rounded-3 text-primary">
|
placeholder="0">
|
||||||
<h5 class="fw-bold mb-0 text-center">Total Denda Diterima
|
</div>
|
||||||
</h5>
|
<div class="col-12">
|
||||||
<h3 class="fw-bold mb-0 text-center total-denda-display">
|
<label class="form-label small text-muted mb-1">
|
||||||
Rp
|
<i class="bi bi-pencil-square me-1"></i>Catatan
|
||||||
{{ number_format($dendaKeterlambatan, 0, ',', '.') }}
|
Petugas
|
||||||
</h3>
|
</label>
|
||||||
|
<textarea class="form-control form-control-sm" rows="2"
|
||||||
|
placeholder="Contoh: Ada coretan di halaman 10, Cover sedikit terlipat, dll..."></textarea>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@endforeach
|
||||||
|
|
||||||
|
<hr>
|
||||||
|
|
||||||
|
<div class="d-flex justify-content-between align-items-center mb-3">
|
||||||
|
<span>Denda Keterlambatan ({{ $statusText }})</span>
|
||||||
|
@php
|
||||||
|
$dendaTelat = 0;
|
||||||
|
if ($isTerlambat) {
|
||||||
|
$hari = $tenggat->startOfDay()->diffInDays($now->startOfDay());
|
||||||
|
$dendaTelat = $hari * 1000;
|
||||||
|
}
|
||||||
|
@endphp
|
||||||
|
{{-- Data Attribute untuk JS --}}
|
||||||
|
<strong class="text-danger denda-keterlambatan-display"
|
||||||
|
data-denda-keterlambatan="{{ $dendaTelat }}">
|
||||||
|
Rp {{ number_format($dendaTelat, 0, ',', '.') }}
|
||||||
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-footer p-4">
|
|
||||||
<button type="button" class="btn btn-outline-primary"
|
<div
|
||||||
data-bs-dismiss="modal">Batal</button>
|
class="d-flex justify-content-between align-items-center mb-3 bg-danger bg-opacity-10 p-2 rounded">
|
||||||
<button type="button" class="btn btn-primary">Konfirmasi
|
<span class="fw-bold text-danger">TOTAL YANG HARUS DIBAYAR</span>
|
||||||
Pengembalian</button>
|
<strong class="text-danger fs-5 total-denda-display">
|
||||||
|
Rp {{ number_format($dendaTelat, 0, ',', '.') }}
|
||||||
|
</strong>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
<div class="form-check form-switch mb-0">
|
||||||
|
<input class="form-check-input" type="checkbox" role="switch" checked
|
||||||
|
id="waStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
<label class="form-check-label small"
|
||||||
|
for="waStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
Kirim <strong>Bukti Pengembalian</strong> ke WhatsApp siswa
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
<div class="form-check form-switch mb-0">
|
||||||
|
<input class="form-check-input email-toggle" type="checkbox"
|
||||||
|
role="switch" checked
|
||||||
|
id="emailStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
<label class="form-check-label small"
|
||||||
|
for="emailStrukToggle-{{ $transaksi['id_peminjaman'] }}">
|
||||||
|
Kirim Bukti Pengembalian</strong> ke Email
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="modal-footer p-3 bg-light">
|
||||||
|
<button type="button" class="btn btn-outline-secondary"
|
||||||
|
data-bs-dismiss="modal">Batal</button>
|
||||||
|
<button type="button" class="btn btn-primary btn-konfirmasi-kembali"
|
||||||
|
data-nama-peminjam="{{ $transaksi['peminjam'] }}"
|
||||||
|
data-nomor-hp="{{ $transaksi['nomor_hp'] }}">
|
||||||
|
Konfirmasi & Selesai
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@endforeach
|
</div>
|
||||||
@empty
|
@empty
|
||||||
<tr>
|
<tr>
|
||||||
<td colspan="8" class="text-center py-5">
|
<td colspan="8" class="text-center py-5">Tidak ada data.</td>
|
||||||
<div class="empty-state">
|
|
||||||
<i class="bi bi-journal-x"></i>
|
|
||||||
<p>Tidak ada data peminjaman yang sedang aktif.</p>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
</tr>
|
</tr>
|
||||||
@endforelse
|
@endforelse
|
||||||
</tbody>
|
</tbody>
|
||||||
|
|
@ -220,18 +223,15 @@ class="form-label small text-muted">Catatan Petugas
|
||||||
|
|
||||||
@push('scripts')
|
@push('scripts')
|
||||||
<script>
|
<script>
|
||||||
// Inisialisasi DataTables
|
|
||||||
$(document).ready(function() {
|
$(document).ready(function() {
|
||||||
$('#peminjamanTable').DataTable({
|
$('#peminjamanTable').DataTable({
|
||||||
pageLength: 10,
|
pageLength: 10,
|
||||||
order: [
|
order: [
|
||||||
[0, 'asc']
|
[0, 'asc']
|
||||||
],
|
],
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// Logika Modal
|
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
function formatRupiah(angka) {
|
function formatRupiah(angka) {
|
||||||
return new Intl.NumberFormat('id-ID', {
|
return new Intl.NumberFormat('id-ID', {
|
||||||
|
|
@ -243,21 +243,33 @@ function formatRupiah(angka) {
|
||||||
|
|
||||||
function hitungTotalDenda(modal) {
|
function hitungTotalDenda(modal) {
|
||||||
const dendaKeterlambatanEl = modal.querySelector('.denda-keterlambatan-display');
|
const dendaKeterlambatanEl = modal.querySelector('.denda-keterlambatan-display');
|
||||||
const dendaRusakEl = modal.querySelector('.denda-rusak-input');
|
const dendaRusakInputs = modal.querySelectorAll('.denda-rusak-input');
|
||||||
const totalDendaEl = modal.querySelector('.total-denda-display');
|
const totalDendaEl = modal.querySelector('.total-denda-display');
|
||||||
const dendaKeterlambatan = parseInt(dendaKeterlambatanEl.dataset.dendaKeterlambatan) || 0;
|
|
||||||
const dendaRusak = parseInt(dendaRusakEl.value) || 0;
|
let dendaKeterlambatan = parseInt(dendaKeterlambatanEl.dataset.dendaKeterlambatan) || 0;
|
||||||
const totalDenda = dendaKeterlambatan + dendaRusak;
|
let totalDendaRusak = 0;
|
||||||
|
|
||||||
|
dendaRusakInputs.forEach(input => {
|
||||||
|
if (!input.closest('.denda-rusak-input-wrapper').classList.contains('d-none')) {
|
||||||
|
totalDendaRusak += parseInt(input.value) || 0;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const totalDenda = dendaKeterlambatan + totalDendaRusak;
|
||||||
totalDendaEl.textContent = formatRupiah(totalDenda);
|
totalDendaEl.textContent = formatRupiah(totalDenda);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Logic Radio Button Kondisi Buku
|
||||||
const radioKondisi = document.querySelectorAll('.radio-kondisi');
|
const radioKondisi = document.querySelectorAll('.radio-kondisi');
|
||||||
radioKondisi.forEach(radio => {
|
radioKondisi.forEach(radio => {
|
||||||
radio.addEventListener('change', function() {
|
radio.addEventListener('change', function() {
|
||||||
const modal = this.closest('.modal-content');
|
const cardBody = this.closest('.card-body');
|
||||||
const dendaRusakWrapper = modal.querySelector('.denda-rusak-input-wrapper');
|
const dendaRusakWrapper = cardBody.querySelector('.denda-rusak-input-wrapper');
|
||||||
const dendaRusakInput = modal.querySelector('.denda-rusak-input');
|
const dendaRusakInput = cardBody.querySelector('.denda-rusak-input');
|
||||||
if (this.value === 'rusak' || this.value === 'hilang') {
|
|
||||||
|
const modal = this.closest('.modal');
|
||||||
|
|
||||||
|
if (this.value === 'rusak') {
|
||||||
dendaRusakWrapper.classList.remove('d-none');
|
dendaRusakWrapper.classList.remove('d-none');
|
||||||
} else {
|
} else {
|
||||||
dendaRusakWrapper.classList.add('d-none');
|
dendaRusakWrapper.classList.add('d-none');
|
||||||
|
|
@ -267,15 +279,71 @@ function hitungTotalDenda(modal) {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Logic Input Denda Rusak
|
||||||
const dendaRusakInputs = document.querySelectorAll('.denda-rusak-input');
|
const dendaRusakInputs = document.querySelectorAll('.denda-rusak-input');
|
||||||
dendaRusakInputs.forEach(input => {
|
dendaRusakInputs.forEach(input => {
|
||||||
input.addEventListener('input', function() {
|
input.addEventListener('input', function() {
|
||||||
const modal = this.closest('.modal-content');
|
const modal = this.closest('.modal');
|
||||||
hitungTotalDenda(modal);
|
hitungTotalDenda(modal);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
$(document).on('click', '.btn-konfirmasi-kembali', function() {
|
||||||
|
const nama = $(this).data('nama-peminjam');
|
||||||
|
const modalEl = $(this).closest('.modal');
|
||||||
|
const modalInstance = bootstrap.Modal.getInstance(modalEl[0]);
|
||||||
|
const isEmailChecked = modalEl.find('.email-toggle').is(':checked');
|
||||||
|
|
||||||
|
modalInstance.hide();
|
||||||
|
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Selesaikan Transaksi?',
|
||||||
|
text: `Buku dari ${nama} akan ditandai sudah kembali.`,
|
||||||
|
icon: 'question',
|
||||||
|
showCancelButton: true,
|
||||||
|
confirmButtonText: 'Ya, Selesaikan',
|
||||||
|
cancelButtonText: 'Batal'
|
||||||
|
}).then((result) => {
|
||||||
|
if (result.isConfirmed) {
|
||||||
|
// Loading Simpan DB
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Menyimpan Data...',
|
||||||
|
timer: 800,
|
||||||
|
timerProgressBar: true,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
// Loading Kirim Email (Jika dicentang)
|
||||||
|
if (isEmailChecked) {
|
||||||
|
const dummyEmail = nama.replace(/\s+/g, '.').toLowerCase() +
|
||||||
|
'@sekolah.sch.id';
|
||||||
|
modernSwal.fire({
|
||||||
|
title: 'Mengirim Email...',
|
||||||
|
html: `Mengirim nota ke: <b>${dummyEmail}</b>`,
|
||||||
|
timer: 2000,
|
||||||
|
timerProgressBar: true,
|
||||||
|
didOpen: () => Swal.showLoading()
|
||||||
|
}).then(() => {
|
||||||
|
finishTransaction(true);
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
finishTransaction(false);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
modalInstance.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function finishTransaction(withEmail) {
|
||||||
|
Toast.fire({
|
||||||
|
icon: 'success',
|
||||||
|
title: 'Berhasil',
|
||||||
|
text: withEmail ? 'Buku kembali & Email terkirim.' : 'Buku berhasil dikembalikan.'
|
||||||
|
});
|
||||||
|
setTimeout(() => location.reload(), 1500);
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|
||||||
</x-app-layout>
|
</x-app-layout>
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,28 @@
|
||||||
Pinjam Buku Baru
|
Pinjam Buku Baru
|
||||||
</button> --}}
|
</button> --}}
|
||||||
|
|
||||||
|
{{-- CEK STATUS BANNED --}}
|
||||||
|
@if (Auth::user()->is_banned)
|
||||||
|
<div class="alert alert-danger border-0 shadow-sm d-flex align-items-center mb-4" role="alert">
|
||||||
|
<div class="display-1 text-danger me-4">
|
||||||
|
<i class="bi bi-shield-lock-fill"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h4 class="alert-heading fw-bold">AKUN ANDA DIBEKUKAN SEMENTARA!</h4>
|
||||||
|
<p class="mb-1">
|
||||||
|
Sistem mendeteksi adanya <strong>keterlambatan pengembalian buku</strong> atau <strong>tunggakan
|
||||||
|
denda</strong> yang belum diselesaikan.
|
||||||
|
</p>
|
||||||
|
<hr>
|
||||||
|
<p class="mb-0 small">
|
||||||
|
<i class="bi bi-info-circle me-1"></i>
|
||||||
|
Fitur peminjaman buku dinonaktifkan. Silakan segera kembalikan buku ke perpustakaan atau hubungi
|
||||||
|
petugas untuk mengaktifkan kembali akun Anda.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
|
|
||||||
<div class="card border-0 shadow-sm rounded-4 my-4 p-4 position-relative" style="background-color: #CEDEFF;">
|
<div class="card border-0 shadow-sm rounded-4 my-4 p-4 position-relative" style="background-color: #CEDEFF;">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-12 col-md-8 p-4 p-md-5" style="z-index: 2;">
|
<div class="col-12 col-md-8 p-4 p-md-5" style="z-index: 2;">
|
||||||
|
|
@ -192,7 +214,9 @@ class="badge bg-{{ $item['type'] }}-soft text-{{ $item['type'] }} rounded-pill p
|
||||||
@forelse($bukuPinjamOffline as $buku)
|
@forelse($bukuPinjamOffline as $buku)
|
||||||
<div class="col-xl-4 col-md-6" x-show="expanded || {{ $loop->index }} < 3" x-transition>
|
<div class="col-xl-4 col-md-6" x-show="expanded || {{ $loop->index }} < 3" x-transition>
|
||||||
<x-book-card :buku="$buku">
|
<x-book-card :buku="$buku">
|
||||||
<div class="d-flex align-items-center text-danger bg-white bg-opacity-75 rounded-2 px-2 py-1"> <i class="bi bi-clock-fill me-2 shadow-md"></i>
|
<div
|
||||||
|
class="d-flex align-items-center text-danger bg-white bg-opacity-75 rounded-2 px-2 py-1">
|
||||||
|
<i class="bi bi-clock-fill me-2 shadow-md"></i>
|
||||||
<span class="fw-bold small">Sisa: {{ $buku['sisa_hari'] }} hari</span>
|
<span class="fw-bold small">Sisa: {{ $buku['sisa_hari'] }} hari</span>
|
||||||
</div>
|
</div>
|
||||||
</x-book-card>
|
</x-book-card>
|
||||||
|
|
|
||||||
|
|
@ -68,10 +68,29 @@ class="badge fw-normal {{ $buku['status'] == 'Tersedia' ? 'bg-success-subtle tex
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="d-flex flex-column gap-2 mt-auto pt-2 border-top">
|
<div class="d-flex flex-column gap-2 mt-auto pt-2 border-top">
|
||||||
@if ($mode === 'offline')
|
@php
|
||||||
@if ($buku['status'] == 'Dipinjam')
|
$userBanned = $isBanned ?? false;
|
||||||
<button class="btn btn-sm btn-secondary w-100" disabled>
|
$isOfflineAccess =
|
||||||
<i class="bi bi-x-circle me-1"></i> Tidak Tersedia
|
$buku['tipe_akses'] === 'offline' ||
|
||||||
|
(is_array($buku['tipe_akses']) && in_array('offline', $buku['tipe_akses']));
|
||||||
|
$isOnlineAccess =
|
||||||
|
$buku['tipe_akses'] === 'online' ||
|
||||||
|
(is_array($buku['tipe_akses']) && in_array('online', $buku['tipe_akses']));
|
||||||
|
$stokHabis = $buku['status'] == 'Dipinjam';
|
||||||
|
@endphp
|
||||||
|
|
||||||
|
{{-- TOMBOL PINJAM (OFFLINE) --}}
|
||||||
|
@if ($isOfflineAccess && $mode !== 'online')
|
||||||
|
@if ($stokHabis)
|
||||||
|
@if (!$isOnlineAccess)
|
||||||
|
<button class="btn btn-sm btn-light border w-100 text-muted" disabled><i
|
||||||
|
class="bi bi-x-circle me-1"></i> Tidak Tersedia</button>
|
||||||
|
@endif
|
||||||
|
@elseif($userBanned)
|
||||||
|
{{-- LOGIC : Jika Banned, tombol Pinjam MATI --}}
|
||||||
|
<button class="btn btn-sm btn-secondary w-100" disabled
|
||||||
|
title="Akun Anda bermasalah">
|
||||||
|
<i class="bi bi-lock-fill me-1"></i> Akun Dikunci
|
||||||
</button>
|
</button>
|
||||||
@else
|
@else
|
||||||
<a href="{{ route('peminjaman.ringkasan', $buku['id']) }}"
|
<a href="{{ route('peminjaman.ringkasan', $buku['id']) }}"
|
||||||
|
|
@ -79,37 +98,14 @@ class="btn btn-sm btn-outline-primary w-100">
|
||||||
<i class="bi bi-arrow-left-right me-1"></i> Pinjam
|
<i class="bi bi-arrow-left-right me-1"></i> Pinjam
|
||||||
</a>
|
</a>
|
||||||
@endif
|
@endif
|
||||||
@elseif($mode === 'online')
|
@endif
|
||||||
|
|
||||||
|
{{-- TOMBOL BACA (ONLINE) - Selalu Nyala --}}
|
||||||
|
@if ($isOnlineAccess && $mode !== 'offline')
|
||||||
<a href="{{ route('baca.ringkasan', $buku['id']) }}"
|
<a href="{{ route('baca.ringkasan', $buku['id']) }}"
|
||||||
class="btn btn-sm btn-primary w-100">
|
class="btn btn-sm btn-primary w-100">
|
||||||
<i class="bi bi-search me-1"></i> Baca
|
<i class="bi bi-book-half me-1"></i> Baca
|
||||||
</a>
|
</a>
|
||||||
@else
|
|
||||||
{{-- Mode 'umum' --}}
|
|
||||||
@if ($buku['status'] == 'Dipinjam')
|
|
||||||
<button class="btn btn-sm btn-secondary w-100" disabled>
|
|
||||||
<i class="bi bi-x-circle me-1"></i> Tidak Tersedia
|
|
||||||
</button>
|
|
||||||
@else
|
|
||||||
@if (is_array($buku['tipe_akses']))
|
|
||||||
<a href="{{ route('peminjaman.ringkasan', $buku['id']) }}"
|
|
||||||
class="btn btn-sm btn-outline-primary flex-fill"><i
|
|
||||||
class="bi bi-arrow-left-right me-1"></i> Pinjam</a>
|
|
||||||
<a href="{{ route('baca.ringkasan', $buku['id']) }}"
|
|
||||||
class="btn btn-sm btn-primary flex-fill"><i class="bi bi-book-half me-1"></i>
|
|
||||||
Baca</a>
|
|
||||||
@elseif ($buku['tipe_akses'] === 'offline')
|
|
||||||
<a href="{{ route('peminjaman.ringkasan', $buku['id']) }}"
|
|
||||||
class="btn btn-sm btn-outline-primary w-100">
|
|
||||||
<i class="bi bi-arrow-left-right me-1"></i> Pinjam
|
|
||||||
</a>
|
|
||||||
@elseif ($buku['tipe_akses'] === 'online')
|
|
||||||
<a href="{{ route('baca.ringkasan', $buku['id']) }}"
|
|
||||||
class="btn btn-sm btn-primary w-100">
|
|
||||||
<i class="bi bi-book-half me-1"></i> Baca
|
|
||||||
</a>
|
|
||||||
@endif
|
|
||||||
@endif
|
|
||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
||||||
|
|
@ -32,6 +32,13 @@
|
||||||
<div class="main-wrapper flex-grow-1">
|
<div class="main-wrapper flex-grow-1">
|
||||||
@include('layouts.navigation')
|
@include('layouts.navigation')
|
||||||
<main class="container-fluid py-4 px-4">
|
<main class="container-fluid py-4 px-4">
|
||||||
|
@if (session('error'))
|
||||||
|
<div class="alert alert-danger alert-dismissible fade show m-3" role="alert">
|
||||||
|
<i class="bi bi-exclamation-octagon-fill me-2"></i>
|
||||||
|
<strong>DITOLAK!</strong> {{ session('error') }}
|
||||||
|
<button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>
|
||||||
|
</div>
|
||||||
|
@endif
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
</main>
|
</main>
|
||||||
<footer class="footer text-center py-3">
|
<footer class="footer text-center py-3">
|
||||||
|
|
@ -60,6 +67,8 @@
|
||||||
if (isset($item['type'])) {
|
if (isset($item['type'])) {
|
||||||
if ($item['type'] === 'riwayat_peminjaman') {
|
if ($item['type'] === 'riwayat_peminjaman') {
|
||||||
$url = route('riwayat.offline');
|
$url = route('riwayat.offline');
|
||||||
|
} elseif ($item['type'] === 'denda_active') {
|
||||||
|
$url = route('riwayat.offline');
|
||||||
} elseif ($item['type'] === 'rekomendasi' && isset($item['link_id'])) {
|
} elseif ($item['type'] === 'rekomendasi' && isset($item['link_id'])) {
|
||||||
$url = route('rekomendasi.show', $item['link_id']);
|
$url = route('rekomendasi.show', $item['link_id']);
|
||||||
} elseif ($item['type'] === 'katalog_kategori' && isset($item['link_id'])) {
|
} elseif ($item['type'] === 'katalog_kategori' && isset($item['link_id'])) {
|
||||||
|
|
@ -103,6 +112,8 @@ class="notification-item d-flex my-1 rounded-3 text-body text-decoration-none @i
|
||||||
<!-- Tom Select -->
|
<!-- Tom Select -->
|
||||||
<script src="https://cdn.jsdelivr.net/npm/tom-select/dist/js/tom-select.complete.min.js"></script>
|
<script src="https://cdn.jsdelivr.net/npm/tom-select/dist/js/tom-select.complete.min.js"></script>
|
||||||
|
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener('DOMContentLoaded', function() {
|
document.addEventListener('DOMContentLoaded', function() {
|
||||||
const sidebar = document.getElementById('sidebar');
|
const sidebar = document.getElementById('sidebar');
|
||||||
|
|
@ -150,6 +161,34 @@ function toggleDesktopSidebar() {
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
const modernSwal = Swal.mixin({
|
||||||
|
customClass: {
|
||||||
|
popup: 'rounded-4 border-0 shadow-lg',
|
||||||
|
title: 'fw-bold text-dark fs-4',
|
||||||
|
html: 'text-muted',
|
||||||
|
confirmButton: 'btn btn-primary rounded-pill px-4 py-2 fw-bold ms-2',
|
||||||
|
cancelButton: 'btn btn-light text-muted rounded-pill px-4 py-2 fw-bold'
|
||||||
|
},
|
||||||
|
buttonsStyling: false,
|
||||||
|
reverseButtons: true,
|
||||||
|
padding: '2rem',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Preset untuk Notifikasi Sukses
|
||||||
|
const Toast = Swal.mixin({
|
||||||
|
toast: true,
|
||||||
|
position: 'top-end',
|
||||||
|
showConfirmButton: false,
|
||||||
|
timer: 3000,
|
||||||
|
timerProgressBar: true,
|
||||||
|
customClass: {
|
||||||
|
popup: 'rounded-3 shadow-sm border-0 bg-white'
|
||||||
|
},
|
||||||
|
didOpen: (toast) => {
|
||||||
|
toast.addEventListener('mouseenter', Swal.stopTimer)
|
||||||
|
toast.addEventListener('mouseleave', Swal.resumeTimer)
|
||||||
|
}
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@stack('scripts')
|
@stack('scripts')
|
||||||
|
|
|
||||||
|
|
@ -44,6 +44,8 @@ class="badge bg-primary-subtle text-primary-emphasis rounded-pill">{{ $unreadNot
|
||||||
if (isset($item['type'])) {
|
if (isset($item['type'])) {
|
||||||
if ($item['type'] === 'riwayat_peminjaman') {
|
if ($item['type'] === 'riwayat_peminjaman') {
|
||||||
$url = route('riwayat.offline');
|
$url = route('riwayat.offline');
|
||||||
|
} elseif ($item['type'] === 'denda_active') {
|
||||||
|
$url = route('riwayat.offline');
|
||||||
} elseif ($item['type'] === 'rekomendasi' && isset($item['link_id'])) {
|
} elseif ($item['type'] === 'rekomendasi' && isset($item['link_id'])) {
|
||||||
$url = route('rekomendasi.show', $item['link_id']);
|
$url = route('rekomendasi.show', $item['link_id']);
|
||||||
} elseif ($item['type'] === 'katalog_kategori' && isset($item['link_id'])) {
|
} elseif ($item['type'] === 'katalog_kategori' && isset($item['link_id'])) {
|
||||||
|
|
|
||||||
|
|
@ -39,6 +39,10 @@ class="bi bi-book-fill"></i><span class="nav-text ms-2">Manajemen Buku</span></a
|
||||||
class="nav-link {{ request()->routeIs('admin.peminjaman.*') ? 'active' : '' }}"> <i
|
class="nav-link {{ request()->routeIs('admin.peminjaman.*') ? 'active' : '' }}"> <i
|
||||||
class="bi bi-arrow-left-right"></i><span class="nav-text ms-2">Manajemen Pinjaman</span> </a>
|
class="bi bi-arrow-left-right"></i><span class="nav-text ms-2">Manajemen Pinjaman</span> </a>
|
||||||
</li>
|
</li>
|
||||||
|
<li class="nav-item"> <a href="{{ route('admin.denda.index') }}"
|
||||||
|
class="nav-link {{ request()->routeIs('admin.denda.*') ? 'active' : '' }}"> <i
|
||||||
|
class="bi-exclamation-octagon"></i><span class="nav-text ms-2">Manajemen Denda</span> </a>
|
||||||
|
</li>
|
||||||
<li class="nav-item"><a href="{{ route('admin.pengumuman.index') }}"
|
<li class="nav-item"><a href="{{ route('admin.pengumuman.index') }}"
|
||||||
class="nav-link {{ request()->routeIs('admin.pengumuman.*') ? 'active' : '' }}"><i
|
class="nav-link {{ request()->routeIs('admin.pengumuman.*') ? 'active' : '' }}"><i
|
||||||
class="bi bi-megaphone-fill"></i><span class="nav-text ms-2">Pengumuman</span></a>
|
class="bi bi-megaphone-fill"></i><span class="nav-text ms-2">Pengumuman</span></a>
|
||||||
|
|
|
||||||
|
|
@ -18,7 +18,8 @@
|
||||||
<div class="card border-0 shadow-sm">
|
<div class="card border-0 shadow-sm">
|
||||||
<div class="card-header bg-white py-3 d-flex justify-content-between align-items-center">
|
<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>
|
<h5 class="fw-bold m-0">Informasi Peminjam</h5>
|
||||||
<a href="{{ route('profile.edit') }}" class="btn btn-sm btn-outline-secondary ">Edit Profil</a>
|
<a href="{{ route('profile.edit') }}" class="btn btn-sm btn-outline-secondary ">Edit
|
||||||
|
Profil</a>
|
||||||
</div>
|
</div>
|
||||||
<div class="card-body p-4">
|
<div class="card-body p-4">
|
||||||
<div class="row g-3">
|
<div class="row g-3">
|
||||||
|
|
@ -95,8 +96,6 @@ class="rounded me-3 form-book-cover">
|
||||||
value="{{ \Carbon\Carbon::now()->addDays(7)->format('d F Y') }}">
|
value="{{ \Carbon\Carbon::now()->addDays(7)->format('d F Y') }}">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- Peraturan Peminjaman --}}
|
{{-- Peraturan Peminjaman --}}
|
||||||
|
|
@ -105,7 +104,7 @@ class="rounded me-3 form-book-cover">
|
||||||
<div class="alert alert-info border-0 bg-info-subtle">
|
<div class="alert alert-info border-0 bg-info-subtle">
|
||||||
<ol class="mb-0 ps-3">
|
<ol class="mb-0 ps-3">
|
||||||
<li>Perpustakaan buka pada jam operasional sekolah.</li>
|
<li>Perpustakaan buka pada jam operasional sekolah.</li>
|
||||||
<li>Setiap siswa hanya dapat meminjam sebanyak 2-3 buku dalam satu waktu.</li>
|
<li>Setiap siswa hanya dapat meminjam sebanyak 1-2 buku dalam satu waktu.</li>
|
||||||
<li>Buku yang dipinjam harus dikembalikan dalam jangka waktu yang telah ditentukan.
|
<li>Buku yang dipinjam harus dikembalikan dalam jangka waktu yang telah ditentukan.
|
||||||
</li>
|
</li>
|
||||||
<li>Jika buku tidak dikembalikan tepat waktu, akan dikenakan denda atau sanksi
|
<li>Jika buku tidak dikembalikan tepat waktu, akan dikenakan denda atau sanksi
|
||||||
|
|
@ -147,8 +146,8 @@ class="rounded me-3 form-book-cover">
|
||||||
<div class="modal-body">
|
<div class="modal-body">
|
||||||
<div class="alert alert-info border-0 bg-info-subtle mb-4 d-flex align-items-center">
|
<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>
|
<i class="bi bi-info-circle-fill me-2"></i>
|
||||||
<span>Anda dapat memilih maksimal <strong><span id="sisaSlot">2</span> buku</strong> lagi.
|
<span>Anda dapat memilih maksimal <strong><span id="sisaSlot">1</span> buku</strong> lagi.
|
||||||
Total maksimal 3 buku.</span>
|
Total maksimal 2 buku.</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mb-3">
|
<div class="mb-3">
|
||||||
|
|
@ -206,20 +205,20 @@ class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
||||||
@endforeach
|
@endforeach
|
||||||
</div>
|
</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>
|
</div>
|
||||||
|
<!-- Counter Buku Terpilih -->
|
||||||
|
<div class="p-3 bg-light">
|
||||||
|
<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>/2
|
||||||
|
</span>
|
||||||
|
<ul>
|
||||||
|
<li id="selectedBooks" class="text-muted small"></li>
|
||||||
|
</ul>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<!-- Footer -->
|
<!-- Footer -->
|
||||||
<div class="modal-footer bg-light">
|
<div class="modal-footer bg-light">
|
||||||
|
|
@ -252,6 +251,23 @@ class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
||||||
<div id="ringkasanBuku" class="mt-2"></div>
|
<div id="ringkasanBuku" class="mt-2"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="alert alert-warning border-0 border-start border-4 border-warning shadow-sm mb-4"
|
||||||
|
role="alert">
|
||||||
|
<div class="d-flex">
|
||||||
|
<div class="fs-1 me-3 text-warning">
|
||||||
|
<i class="bi bi-exclamation-circle-fill"></i>
|
||||||
|
</div>
|
||||||
|
<div>
|
||||||
|
<h6 class="fw-bold text-dark mb-1">PENTING: Aturan Peminjaman!</h6>
|
||||||
|
<p class="mb-0 text-muted small">
|
||||||
|
Sesuai peraturan perpustakaan, durasi peminjaman buku maksimal adalah
|
||||||
|
<strong class="text-dark bg-warning-subtle px-2 py-1 rounded">2 HARI</strong>.
|
||||||
|
<br>
|
||||||
|
Mohon kembalikan tepat waktu untuk menghindari denda (Rp 1.000/hari).
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="modal-footer border-0 justify-content-center">
|
<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 type="button" class="btn btn-secondary px-4" data-bs-dismiss="modal">Batal</button>
|
||||||
|
|
||||||
|
|
@ -268,30 +284,41 @@ class="bi bi-star-fill me-1"></i>Buku Utama</span>
|
||||||
</div>
|
</div>
|
||||||
<script>
|
<script>
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
const tglPinjam = flatpickr("#tanggalPinjam", {
|
|
||||||
|
// (Default Hari Ini + 2 Hari)
|
||||||
|
// Simpan instance-nya ke variabel
|
||||||
|
const fpKembali = flatpickr("#tanggalKembali", {
|
||||||
dateFormat: "d F Y",
|
dateFormat: "d F Y",
|
||||||
altInput: true,
|
altInput: true,
|
||||||
altFormat: "d F Y",
|
altFormat: "d F Y",
|
||||||
defaultDate: "{{ \Carbon\Carbon::now()->format('Y-m-d') }}",
|
defaultDate: new Date().fp_incr(2),
|
||||||
locale: "id",
|
locale: "id",
|
||||||
minDate: "today",
|
minDate: new Date().fp_incr(1),
|
||||||
onChange: function(selectedDates, dateStr) {
|
maxDate: new Date().fp_incr(2)
|
||||||
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", {
|
// Inisialisasi Tanggal Pinjam
|
||||||
|
flatpickr("#tanggalPinjam", {
|
||||||
dateFormat: "d F Y",
|
dateFormat: "d F Y",
|
||||||
altInput: true,
|
altInput: true,
|
||||||
altFormat: "d F Y",
|
altFormat: "d F Y",
|
||||||
defaultDate: "{{ \Carbon\Carbon::now()->addDays(7)->format('Y-m-d') }}",
|
defaultDate: "today",
|
||||||
locale: "id",
|
locale: "id",
|
||||||
minDate: new Date().fp_incr(1)
|
minDate: "today",
|
||||||
|
|
||||||
|
// LOGIC : Saat Tanggal Pinjam Berubah
|
||||||
|
onChange: function(selectedDates, dateStr) {
|
||||||
|
if (selectedDates.length > 0) {
|
||||||
|
const tglMulai = selectedDates[0];
|
||||||
|
const maxDateBaru = new Date(tglMulai).fp_incr(2);
|
||||||
|
const minDateBaru = new Date(tglMulai).fp_incr(1);
|
||||||
|
|
||||||
|
fpKembali.set("minDate", minDateBaru);
|
||||||
|
fpKembali.set("maxDate", maxDateBaru);
|
||||||
|
|
||||||
|
fpKembali.setDate(maxDateBaru);
|
||||||
|
}
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
|
|
@ -21,58 +21,81 @@
|
||||||
</thead>
|
</thead>
|
||||||
<tbody>
|
<tbody>
|
||||||
@php $counter = 1; @endphp
|
@php $counter = 1; @endphp
|
||||||
@forelse ($riwayatOffline as $transaksi)
|
@if (count($riwayatOffline) > 0)
|
||||||
@foreach ($transaksi['books'] as $buku)
|
@foreach ($riwayatOffline as $transaksi)
|
||||||
<tr>
|
@foreach ($transaksi['books'] as $buku)
|
||||||
<td>{{ $counter++ }}</td>
|
@php
|
||||||
<td>{{ $transaksi['id_peminjaman'] }}</td>
|
try {
|
||||||
<td>{{ $buku['kode_buku'] }}</td>
|
$tglKembali = \Carbon\Carbon::createFromFormat(
|
||||||
<td>{{ $buku['judul'] }}</td>
|
'd/m/Y',
|
||||||
<td>{{ $transaksi['tanggal_pinjam'] }}</td>
|
$transaksi['tanggal_kembali'],
|
||||||
<td>{{ $transaksi['tanggal_kembali'] }}</td>
|
)->startOfDay();
|
||||||
<td>
|
} catch (\Exception $e) {
|
||||||
@if ($transaksi['status'] == 'Dikembalikan')
|
$tglKembali = \Carbon\Carbon::parse(
|
||||||
<span
|
$transaksi['tanggal_kembali'],
|
||||||
class="badge rounded-pill bg-success-subtle text-success-emphasis">{{ $transaksi['status'] }}</span>
|
)->startOfDay();
|
||||||
@else
|
}
|
||||||
<span
|
|
||||||
class="badge rounded-pill bg-warning-subtle text-warning-emphasis">{{ $transaksi['status'] }}</span>
|
$today = now()->startOfDay();
|
||||||
@endif
|
$isTelat = $today->gt($tglKembali) && $transaksi['status'] == 'Dipinjam';
|
||||||
</td>
|
|
||||||
<td>
|
$hariTelat = 0;
|
||||||
<button class="btn btn-primary btn-sm text-white" data-bs-toggle="modal"
|
$denda = 0;
|
||||||
data-bs-target="#detailModal" data-transaksi-id="{{ $transaksi['id'] }}"
|
|
||||||
data-buku-id="{{ $buku['id'] }}">
|
if ($isTelat) {
|
||||||
Detail
|
$hariTelat = $tglKembali->diffInDays($today);
|
||||||
</button>
|
$denda = $hariTelat * 1000;
|
||||||
</td>
|
}
|
||||||
</tr>
|
@endphp
|
||||||
|
|
||||||
|
<tr>
|
||||||
|
<td>{{ $counter++ }}</td>
|
||||||
|
<td>{{ $transaksi['id_peminjaman'] }}</td>
|
||||||
|
<td>{{ $buku['kode_buku'] }}</td>
|
||||||
|
<td>{{ $buku['judul'] }}</td>
|
||||||
|
<td>{{ $transaksi['tanggal_pinjam'] }}</td>
|
||||||
|
<td>{{ $transaksi['tanggal_kembali'] }}</td>
|
||||||
|
<td>
|
||||||
|
@if ($transaksi['status'] == 'Dikembalikan')
|
||||||
|
<span
|
||||||
|
class="badge rounded-pill bg-success-subtle text-success-emphasis">Dikembalikan</span>
|
||||||
|
@elseif($isTelat)
|
||||||
|
<span class="badge rounded-pill bg-danger text-white">Terlambat</span>
|
||||||
|
@else
|
||||||
|
<span
|
||||||
|
class="badge rounded-pill bg-warning-subtle text-warning-emphasis">Dipinjam</span>
|
||||||
|
@endif
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<button class="btn btn-primary btn-sm text-white" data-bs-toggle="modal"
|
||||||
|
data-bs-target="#detailModal" data-transaksi-id="{{ $transaksi['id'] }}"
|
||||||
|
data-buku-id="{{ $buku['id'] }}"
|
||||||
|
data-is-telat="{{ $isTelat ? 'true' : 'false' }}"
|
||||||
|
data-hari-telat="{{ $hariTelat }}"
|
||||||
|
data-denda="{{ number_format($denda, 0, ',', '.') }}">
|
||||||
|
Detail
|
||||||
|
</button>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
@endforeach
|
@endforeach
|
||||||
@empty
|
@endif
|
||||||
<tr>
|
|
||||||
<td colspan="7" class="text-center">Tidak ada riwayat peminjaman.</td> </tr>
|
|
||||||
@endforelse
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{{-- MODAL DETAIL RIWAYAT --}}
|
{{-- MODAL DETAIL --}}
|
||||||
<div class="modal fade" id="detailModal" tabindex="-1" aria-labelledby="detailModalLabel" aria-hidden="true">
|
<div class="modal fade" id="detailModal" tabindex="-1" aria-hidden="true">
|
||||||
<div class="modal-dialog modal-lg modal-dialog-centered modal-dialog-scrollable">
|
<div class="modal-dialog modal-lg modal-dialog-centered">
|
||||||
<div class="modal-content border-0 shadow-lg">
|
<div class="modal-content border-0 shadow-lg">
|
||||||
<div class="modal-header bg-light">
|
<div class="modal-header bg-light">
|
||||||
<h5 class="modal-title fw-bold" id="detailModalLabel"><i
|
<h5 class="modal-title fw-bold"><i class="bi bi-book-half me-2 text-primary"></i>Detail Riwayat</h5>
|
||||||
class="bi bi-book-half me-2 text-primary"></i>Detail Riwayat</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||||
</div>
|
</div>
|
||||||
<div class="modal-body p-4">
|
<div class="modal-body p-4">
|
||||||
<div id="modal-content-placeholder" class="text-center">
|
<div id="modal-content-placeholder" class="text-center">Loading...</div>
|
||||||
<div class="spinner-border text-primary" role="status">
|
|
||||||
<span class="visually-hidden">Loading...</span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
@ -90,9 +113,20 @@ class="bi bi-book-half me-2 text-primary"></i>Detail Riwayat</h5>
|
||||||
order: [
|
order: [
|
||||||
[0, 'asc']
|
[0, 'asc']
|
||||||
],
|
],
|
||||||
|
|
||||||
|
language: {
|
||||||
|
emptyTable: `
|
||||||
|
<div class="text-center py-5 text-muted">
|
||||||
|
<i class="bi bi-inbox fs-1 d-block mb-2 opacity-50"></i>
|
||||||
|
Belum ada riwayat peminjaman.
|
||||||
|
</div>
|
||||||
|
`,
|
||||||
|
zeroRecords: "Tidak ada data yang cocok"
|
||||||
|
},
|
||||||
|
|
||||||
columnDefs: [{
|
columnDefs: [{
|
||||||
responsivePriority: 1,
|
responsivePriority: 1,
|
||||||
targets: 2
|
targets: 3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
responsivePriority: 2,
|
responsivePriority: 2,
|
||||||
|
|
@ -106,74 +140,106 @@ class="bi bi-book-half me-2 text-primary"></i>Detail Riwayat</h5>
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Modal Logic
|
||||||
// Modal Detail
|
|
||||||
const detailModal = document.getElementById('detailModal');
|
const detailModal = document.getElementById('detailModal');
|
||||||
|
|
||||||
detailModal.addEventListener('show.bs.modal', event => {
|
detailModal.addEventListener('show.bs.modal', event => {
|
||||||
const button = event.relatedTarget;
|
const button = event.relatedTarget;
|
||||||
const transaksiId = button.getAttribute('data-transaksi-id');
|
const transaksiId = button.getAttribute('data-transaksi-id');
|
||||||
const bukuId = button.getAttribute('data-buku-id');
|
const bukuId = button.getAttribute('data-buku-id');
|
||||||
const modalBody = detailModal.querySelector('#modal-content-placeholder');
|
const isTelat = button.getAttribute('data-is-telat') === 'true';
|
||||||
const modalTitle = detailModal.querySelector('#detailModalLabel');
|
const hariTelat = button.getAttribute('data-hari-telat');
|
||||||
|
const denda = button.getAttribute('data-denda');
|
||||||
|
|
||||||
|
const modalBody = detailModal.querySelector('#modal-content-placeholder');
|
||||||
const transaksiItem = riwayatOfflineData.find(item => item.id == transaksiId);
|
const transaksiItem = riwayatOfflineData.find(item => item.id == transaksiId);
|
||||||
if (!transaksiItem) return;
|
if (!transaksiItem) return;
|
||||||
|
|
||||||
const buku = transaksiItem.books.find(b => b.id == bukuId);
|
const buku = transaksiItem.books.find(b => b.id == bukuId);
|
||||||
if (!buku) return;
|
if (!buku) return;
|
||||||
|
|
||||||
modalTitle.textContent = `Detail Buku`;
|
const dendaHtml = isTelat ? `
|
||||||
|
<div class="card border-0 border-start border-4 border-danger bg-danger-subtle mb-3 shadow-sm">
|
||||||
const keteranganHtml = buku.keterangan ?
|
<div class="card-body p-3 d-flex align-items-center">
|
||||||
`
|
<div class="flex-shrink-0 me-3">
|
||||||
<hr class="my-3">
|
<i class="bi bi-exclamation-octagon-fill text-danger fs-1"></i>
|
||||||
<div class="alert alert-warning border-0 bg-warning-subtle mb-0">
|
</div>
|
||||||
<h6 class="fw-bold mb-1 text-warning-emphasis"><i class="bi bi-info-circle-fill me-2"></i>Catatan Petugas</h6>
|
<div class="text-start">
|
||||||
<p class="mb-0">${buku.keterangan}</p>
|
<h6 class="fw-bold text-danger mb-1">Terlambat Pengembalian!</h6>
|
||||||
|
<p class="mb-0 small text-danger-emphasis">
|
||||||
|
Anda terlambat <span class="badge bg-danger text-white">${hariTelat} Hari</span>.
|
||||||
|
Denda yang harus dibayar:
|
||||||
|
<span class="fw-bold fs-6 d-block mt-1">Rp ${denda}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
` :
|
</div>` : '';
|
||||||
'';
|
|
||||||
|
|
||||||
|
const keteranganHtml = buku.keterangan ? `
|
||||||
|
<div class="card border-0 border-start border-4 border-warning bg-warning-subtle mb-4 shadow-sm">
|
||||||
|
<div class="card-body p-3 d-flex align-items-start">
|
||||||
|
<div class="flex-shrink-0 me-3">
|
||||||
|
<i class="bi bi-journal-bookmark-fill text-warning-emphasis fs-3"></i>
|
||||||
|
</div>
|
||||||
|
<div class="text-start">
|
||||||
|
<h6 class="fw-bold text-warning-emphasis mb-1">Catatan Petugas</h6>
|
||||||
|
<p class="mb-0 small text-dark opacity-75 fst-italic">
|
||||||
|
"${buku.keterangan}"
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>` : '';
|
||||||
|
|
||||||
const contentHTML = `
|
// RENDER HTML
|
||||||
|
modalBody.innerHTML = `
|
||||||
<div class="text-center mb-4">
|
<div class="text-center mb-4">
|
||||||
<img src="{{ asset('${buku.cover}') }}" alt="Cover ${buku.judul}" class="img-fluid rounded shadow-sm" style="max-width: 150px;">
|
<img src="{{ asset('') }}${buku.cover}" class="img-fluid rounded shadow-sm" style="max-width: 140px;">
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<h4 class="fw-bold text-center">${buku.judul}</h4>
|
<h5 class="fw-bold text-center mb-1">${buku.judul}</h5>
|
||||||
<p class="text-muted text-center">${buku.deskripsi}</p>
|
<p class="text-muted text-center small mb-4">${buku.deskripsi}</p>
|
||||||
|
|
||||||
<hr class="my-4">
|
${dendaHtml}
|
||||||
|
${keteranganHtml}
|
||||||
|
|
||||||
<table class="table table-borderless table-sm">
|
<div class="card bg-light border-0 rounded-3 p-3">
|
||||||
<tbody>
|
<table class="table table-borderless table-sm mb-0">
|
||||||
<tr>
|
<tbody>
|
||||||
<td class="fw-bold text-start" style="width: 35%;">ID Peminjaman</td>
|
<tr>
|
||||||
<td style="width: 5%;">:</td>
|
<td class="fw-bold text-start" style="width: 35%;">ID Peminjaman</td>
|
||||||
<td class="text-start">${transaksiItem.id_peminjaman}</td>
|
<td style="width: 1%;">:</td>
|
||||||
</tr>
|
<td class="text-start">${transaksiItem.id_peminjaman}</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td class="fw-bold text-start">Kode Buku</td>
|
<tr>
|
||||||
<td>:</td>
|
<td class="fw-bold text-start">Kode Buku</td>
|
||||||
<td class="text-start">${buku.kode_buku}</td>
|
<td>:</td>
|
||||||
</tr>
|
<td class="text-start fw-medium">${buku.kode_buku}</td>
|
||||||
<tr>
|
</tr>
|
||||||
<td class="fw-bold text-start">Kategori Buku</td>
|
<tr>
|
||||||
<td>:</td>
|
<td class="fw-bold text-start align-middle">Kategori</td>
|
||||||
<td class="text-start"><span class="badge bg-primary-subtle text-primary-emphasis rounded-pill px-3 py-2">${buku.kategori}</span></td>
|
<td class="align-middle">:</td>
|
||||||
</tr>
|
<td class="text-start">
|
||||||
<tr>
|
<span class="badge bg-primary-subtle text-primary-emphasis rounded-pill px-3 py-2">
|
||||||
<td class="fw-bold text-start">Tahun Terbit</td>
|
${buku.kategori}
|
||||||
<td>:</td>
|
</span>
|
||||||
<td class="text-start">${buku.tahun}</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
</tbody>
|
<tr>
|
||||||
</table>
|
<td class="fw-bold text-start">Tahun Terbit</td>
|
||||||
|
<td>:</td>
|
||||||
${keteranganHtml} `;
|
<td class="text-start">${buku.tahun}</td>
|
||||||
|
</tr>
|
||||||
modalBody.innerHTML = contentHTML;
|
<tr>
|
||||||
|
<td class="fw-bold text-start">Tgl Pinjam</td>
|
||||||
|
<td>:</td>
|
||||||
|
<td class="text-start">${transaksiItem.tanggal_pinjam}</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class="fw-bold text-start">Tenggat</td>
|
||||||
|
<td>:</td>
|
||||||
|
<td class="text-start">${transaksiItem.tanggal_kembali}</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>`;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
@endpush
|
@endpush
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,9 @@
|
||||||
|
|
||||||
Route::get('/peminjaman', [AdminPeminjamanController::class, 'index'])->name('peminjaman.index');
|
Route::get('/peminjaman', [AdminPeminjamanController::class, 'index'])->name('peminjaman.index');
|
||||||
Route::get('/peminjaman/tambah', [AdminPeminjamanController::class, 'create'])->name('peminjaman.create');
|
Route::get('/peminjaman/tambah', [AdminPeminjamanController::class, 'create'])->name('peminjaman.create');
|
||||||
|
|
||||||
|
Route::get('/denda', [AdminPeminjamanController::class, 'dendaIndex'])->name('denda.index');
|
||||||
|
Route::post('/denda/sanksi', [AdminPeminjamanController::class, 'berikanSanksi'])->name('denda.sanksi');
|
||||||
});
|
});
|
||||||
|
|
||||||
// --- RUTE LOGIN KHUSUS ADMIN ---
|
// --- RUTE LOGIN KHUSUS ADMIN ---
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue