## 📋 Ringkasan Implementasi penuh fitur Daftar Pustaka dengan peningkatan UI/UX, dukungan gesture swipe di PDF viewer mobile, serta integrasi breadcrumb untuk navigasi yang lebih intuitif. ## 🔄 Perubahan Utama - app/Services/DaftarPustakaService.php • Refactor method getDaftarPustaka(), hapus handleUpload_() • Optimasi filtering & perbaiki format kode - resources/views/daftar-pustaka/create.blade.php • Aktifkan breadcrumb navigation dengan {{ Breadcrumbs::render() }} - resources/views/daftar-pustaka/index.blade.php • Konsolidasi class CSS, perbaikan flex & pagination styling - resources/views/daftar-pustaka/show.blade.php • Tambah gesture swipe (touchstart, touchend) untuk PDF viewer • Implementasi handleSwipe() & threshold swipe 50px - routes/breadcrumbs.php • Tambah route breadcrumbs daftar-pustaka (index, show, create)
167 lines
6.3 KiB
PHP
167 lines
6.3 KiB
PHP
@extends('layouts.main')
|
|
|
|
@section('breadcrumbs')
|
|
{{ Breadcrumbs::render(request()->route()->getName(), $daftarPustaka) }}
|
|
@endsection
|
|
|
|
@section('content')
|
|
<div class="grid gap-5 mx-auto w-full lg:gap-7.5">
|
|
<form
|
|
action="{{ isset($daftarPustaka->id) ? route('daftar-pustaka.update', $daftarPustaka->id) : route('daftar-pustaka.store') }}"
|
|
method="POST">
|
|
@csrf
|
|
<div class="pb-2.5 border card border-agi-100">
|
|
<div class="card-header bg-agi-50" id="basic_settings">
|
|
<h3 class="card-title">
|
|
{{ $daftarPustaka->judul ?? '' }}
|
|
</h3>
|
|
<div class="flex gap-2 items-center">
|
|
<a href="{{ route('daftar-pustaka.index') }}" class="btn btn-xs btn-info">
|
|
<i class="ki-filled ki-exit-left"></i> Back
|
|
</a>
|
|
</div>
|
|
</div>
|
|
<div class="grid gap-5 card-body">
|
|
<div class="min-w-3xl">
|
|
<div class="flex flex-col p-4 h-full">
|
|
<div class="flex justify-between items-center mb-4">
|
|
<a href="{{ asset('storage/' . $daftarPustaka->attachment) }}" class="btn btn-primary btn-sm">
|
|
<i class="ki-duotone ki-cloud-download me-1"></i>
|
|
Download File
|
|
</a>
|
|
</div>
|
|
|
|
@php
|
|
$fileExtension = pathinfo($daftarPustaka->attachment, PATHINFO_EXTENSION);
|
|
$isPdf = strtolower($fileExtension) == 'pdf';
|
|
$imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp'];
|
|
$isImage = in_array(strtolower($fileExtension), $imageExtensions);
|
|
$fileUrl = asset('storage/' . $daftarPustaka->attachment);
|
|
@endphp
|
|
|
|
@if ($isPdf)
|
|
<canvas id="pdfViewer" class="w-full rounded border touch-pan-y"></canvas>
|
|
<div class="flex gap-3 justify-center mt-3">
|
|
<button type="button" id="prevPage" class="btn btn-primary btn-sm">Previous</button>
|
|
<span>Page: <span id="pageNum">1</span> / <span id="pageCount">0</span></span>
|
|
<button type="button" id="nextPage" class="btn btn-primary btn-sm">Next</button>
|
|
</div>
|
|
@elseif ($isImage)
|
|
<img src="{{ $fileUrl }}" class="object-contain w-full rounded" />
|
|
@else
|
|
<p class="text-red-500">File tidak bisa ditampilkan, silakan
|
|
<a href="{{ $fileUrl }}" class="text-blue-500 underline" download>unduh di sini</a>.
|
|
</p>
|
|
@endif
|
|
</div>
|
|
</div>
|
|
|
|
<div class="border border-t"></div>
|
|
<div>
|
|
{{ $daftarPustaka->deskripsi ?? '' }}
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
@endsection
|
|
|
|
@push('scripts')
|
|
<!-- PDF.js CDN -->
|
|
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.min.js"></script>
|
|
<script>
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
const url = @json($fileUrl);
|
|
|
|
if (url.endsWith('.pdf')) {
|
|
const pdfjsLib = window['pdfjs-dist/build/pdf'];
|
|
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/3.11.174/pdf.worker.min.js';
|
|
|
|
let pdfDoc = null;
|
|
let pageNum = 1;
|
|
let pageRendering = false;
|
|
let pageNumPending = null;
|
|
const scale = 1.3;
|
|
const canvas = document.getElementById('pdfViewer');
|
|
const ctx = canvas.getContext('2d');
|
|
|
|
function renderPage(num) {
|
|
pageRendering = true;
|
|
pdfDoc.getPage(num).then(function (page) {
|
|
const viewport = page.getViewport({ scale: scale });
|
|
canvas.height = viewport.height;
|
|
canvas.width = viewport.width;
|
|
|
|
const renderContext = {
|
|
canvasContext: ctx,
|
|
viewport: viewport
|
|
};
|
|
const renderTask = page.render(renderContext);
|
|
|
|
renderTask.promise.then(function () {
|
|
pageRendering = false;
|
|
document.getElementById('pageNum').textContent = num;
|
|
|
|
if (pageNumPending !== null) {
|
|
renderPage(pageNumPending);
|
|
pageNumPending = null;
|
|
}
|
|
});
|
|
});
|
|
}
|
|
|
|
function queueRenderPage(num) {
|
|
if (pageRendering) {
|
|
pageNumPending = num;
|
|
} else {
|
|
renderPage(num);
|
|
}
|
|
}
|
|
|
|
function onPrevPage() {
|
|
if (pageNum <= 1) return;
|
|
pageNum--;
|
|
queueRenderPage(pageNum);
|
|
}
|
|
|
|
function onNextPage() {
|
|
if (pageNum >= pdfDoc.numPages) return;
|
|
pageNum++;
|
|
queueRenderPage(pageNum);
|
|
}
|
|
|
|
document.getElementById('prevPage').addEventListener('click', onPrevPage);
|
|
document.getElementById('nextPage').addEventListener('click', onNextPage);
|
|
|
|
// Swipe gesture
|
|
let touchStartX = 0;
|
|
let touchEndX = 0;
|
|
|
|
canvas.addEventListener('touchstart', function (e) {
|
|
touchStartX = e.changedTouches[0].screenX;
|
|
});
|
|
|
|
canvas.addEventListener('touchend', function (e) {
|
|
touchEndX = e.changedTouches[0].screenX;
|
|
handleSwipe();
|
|
});
|
|
|
|
function handleSwipe() {
|
|
const swipeThreshold = 50; // min distance for swipe
|
|
if (touchEndX < touchStartX - swipeThreshold) {
|
|
onNextPage();
|
|
} else if (touchEndX > touchStartX + swipeThreshold) {
|
|
onPrevPage();
|
|
}
|
|
}
|
|
|
|
pdfjsLib.getDocument(url).promise.then(function (pdfDoc_) {
|
|
pdfDoc = pdfDoc_;
|
|
document.getElementById('pageCount').textContent = pdfDoc.numPages;
|
|
renderPage(pageNum);
|
|
});
|
|
}
|
|
});
|
|
</script>
|
|
@endpush
|