Files
ladill-events/resources/views/public/qr/document-viewer.blade.php
T
isaaccladandCursor 2c1c3cdd3e
Deploy Ladill Events / deploy (push) Successful in 30s
Enforce Events favicon everywhere and fix deploy pipeline failures.
Add favicon partial to all standalone pages, regenerate the Events icon asset, and stop marking deploys failed when the nginx vhost step cannot sudo.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-07 11:56:27 +00:00

179 lines
5.3 KiB
PHP

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
@include('partials.favicon')
<title>{{ $qrCode->label }}</title>
<style>
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html, body { height: 100%; }
body {
background: #f1f5f9;
font-family: system-ui, -apple-system, sans-serif;
display: flex;
flex-direction: column;
height: 100dvh;
color: #1e293b;
}
#toolbar {
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 1.25rem;
height: 3.25rem;
background: #fff;
border-bottom: 1px solid #e2e8f0;
flex-shrink: 0;
z-index: 20;
}
.tb-label {
font-size: 0.8rem;
font-weight: 600;
color: #64748b;
max-width: 65%;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.tb-download {
display: flex;
align-items: center;
gap: 0.375rem;
padding: 0.375rem 0.9rem;
border-radius: 9999px;
background: #f1f5f9;
border: 1px solid #cbd5e1;
color: #334155;
font-size: 0.75rem;
font-weight: 500;
text-decoration: none;
transition: background 0.15s;
}
.tb-download:hover { background: #e2e8f0; }
.tb-download svg { width: 0.875rem; height: 0.875rem; flex-shrink: 0; }
#scroll {
flex: 1;
overflow-y: auto;
display: flex;
flex-direction: column;
align-items: center;
padding: 1.25rem 0.75rem;
gap: 0.75rem;
}
#loading {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
gap: 0.875rem;
color: #94a3b8;
font-size: 0.8125rem;
padding: 4rem 0;
width: 100%;
}
.spinner {
width: 2rem; height: 2rem;
border: 2px solid #e2e8f0;
border-top-color: #94a3b8;
border-radius: 50%;
animation: spin 0.75s linear infinite;
}
@keyframes spin { to { transform: rotate(360deg); } }
.pdf-page {
display: block;
max-width: 100%;
border-radius: 4px;
box-shadow: 0 2px 12px rgba(0,0,0,0.12);
background: #fff;
}
#bottom {
flex-shrink: 0;
height: 2rem;
display: flex;
align-items: center;
justify-content: center;
font-size: 0.72rem;
color: #94a3b8;
letter-spacing: 0.04em;
}
</style>
</head>
<body>
<div id="toolbar">
<span class="tb-label">{{ $qrCode->label }}</span>
@if($allowDownload)
<a href="{{ route('qr.public.file', $qrCode->short_code) }}" download class="tb-download">
<svg fill="none" stroke="currentColor" stroke-width="2" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" d="M3 16.5v2.25A2.25 2.25 0 0 0 5.25 21h13.5A2.25 2.25 0 0 0 21 18.75V16.5M16.5 12 12 16.5m0 0L7.5 12m4.5 4.5V3"/>
</svg>
Download
</a>
@else
<span></span>
@endif
</div>
<div id="scroll">
<div id="loading">
<div class="spinner"></div>
Loading document…
</div>
</div>
<div id="bottom"><span id="page-info"></span></div>
<script type="module">
import * as pdfjsLib from 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.min.mjs';
pdfjsLib.GlobalWorkerOptions.workerSrc = 'https://cdnjs.cloudflare.com/ajax/libs/pdf.js/4.0.379/pdf.worker.min.mjs';
const fileUrl = @json($fileUrl);
const scroll = document.getElementById('scroll');
const loading = document.getElementById('loading');
const pageInfo = document.getElementById('page-info');
async function main() {
const pdf = await pdfjsLib.getDocument(fileUrl).promise;
const n = pdf.numPages;
pageInfo.textContent = n + ' page' + (n !== 1 ? 's' : '');
loading.remove();
const maxW = scroll.clientWidth - 24;
for (let i = 1; i <= n; i++) {
const pg = await pdf.getPage(i);
const vp0 = pg.getViewport({ scale: 1 });
const scale = Math.min(maxW / vp0.width, 2);
const vp = pg.getViewport({ scale });
const dpr = window.devicePixelRatio || 1;
const canvas = document.createElement('canvas');
canvas.className = 'pdf-page';
canvas.width = vp.width * dpr;
canvas.height = vp.height * dpr;
canvas.style.width = vp.width + 'px';
canvas.style.height = vp.height + 'px';
scroll.appendChild(canvas);
await pg.render({ canvasContext: canvas.getContext('2d'), viewport: pg.getViewport({ scale: scale * dpr }) }).promise;
}
}
main().catch(err => {
loading.innerHTML = '<p style="color:#ef4444;text-align:center;padding:1rem">Failed to load document.</p>';
console.error(err);
});
</script>
</body>
</html>