|
|
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8" /> <title>VPH Booking Summary</title> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <link href="https://fonts.googleapis.com/css?family=Montserrat:400,600&display=swap" rel="stylesheet" /> <script src="https://code.jquery.com/jquery-3.6.4.min.js" integrity="sha256-oP6HI9z1XaZNBrJURtCoUT5SUnxFr8s3BzRl+cbzUq8=" crossorigin="anonymous"></script>
<style> :root { --ink:#1f2937; --muted:#6b7280; --bg1:#eff6ff; --bg2:#f0fdfa; --brand:#3b82f6; } *{box-sizing:border-box} body{ font-family:'Montserrat',system-ui,Arial; background:linear-gradient(135deg,var(--bg1) 0%, var(--bg2) 100%); min-height:100vh; margin:0; padding:2rem 1rem; color:var(--ink); } .container{ max-width:64rem; margin:0 auto; } .header{ text-align:center; margin-bottom:1.5rem; } .header h1{ font-size:2rem; margin:.25rem 0; } .confirmation-header{ text-align:center; margin:1.25rem 0 1rem; } .success-icon{ font-size:3rem; margin-bottom:.75rem; } .confirmation-header h2{ margin:.25rem 0 .25rem; } .confirmation-header p{ color:var(--muted); margin:0; }
.card{ background:#fff; border-radius:12px; padding:1.25rem; box-shadow:0 10px 15px -3px rgba(0,0,0,.1); } .booking-summary h3{ margin:0 0 .75rem; font-size:1.1rem;text-align:center; }
/* table layout (rock-solid for html2pdf) */ .summary-table{ width: 80%; margin-left: 100px; border-collapse:collapse; background:#f9fafb; border-radius:8px; overflow:hidden; } .summary-table th, .summary-table td{ padding:12px 10px; border-bottom:1px solid #e5e7eb; text-align:left; vertical-align:top; } .summary-table th{ width:450px; color:var(--muted); font-weight:600; } .summary-table tr:last-child th, .summary-table tr:last-child td{ border-bottom:0; }
.important-note{ background:#eff6ff; padding:1rem; border-radius:8px; font-size:.95rem; color:#1e40af; margin-top:1rem; }
.actions{ display:flex; justify-content:center; gap:12px; margin-top:1.25rem; } .btn{ border:0; border-radius:8px; padding:.75rem 1.25rem; font-weight:600; cursor:pointer; } .btn-secondary{ background:#e5e7eb; color:#111827; } .btn-secondary:hover{ background:#d1d5db; } .btn[disabled]{ opacity:.6; cursor:not-allowed; }
.muted{ text-align:center; color:var(--muted); margin-top:.5rem; font-size:.9rem; }
body.pdf-export { padding: 0 !important; }body.pdf-export .header { display: none !important; }body.pdf-export #bookingSummary { margin: 0 !important; }body.pdf-export .confirmation-header { margin: .5rem 0 !important; }body.pdf-export .summary-table { width: 100% !important; margin-left: 0 !important; }
</style></head><body><div class="container"> <div class="header"> <h1>Victoria Public Hall — Experiential Museum</h1> </div>
<div id="bookingSummary" class="card"> <div class="confirmation-header"> <div class="success-icon">✅</div> <h2>Booking Confirmed!</h2> <p>Your VPH visit has been successfully booked</p> </div>
<div class="booking-summary"> <h3>Booking Summary</h3>
<table class="summary-table"> <tr><th>Contact Person</th><td id="summaryName"></td></tr> <tr><th>Phone</th><td id="summaryPhone"></td></tr> <tr><th>Number of Persons</th><td id="summaryMembers"></td></tr> <tr><th>Visit Date</th><td id="summaryDate"></td></tr> <tr><th>Time Slot</th><td id="summaryTimeSlot"></td></tr> <tr><th>Selected Slots</th><td id="summarySlots"></td></tr> </table> </div>
<div class="important-note"> <strong>Important:</strong> Please arrive 15 minutes before your scheduled time. Bring a valid ID proof for verification. </div> </div>
<div class="actions"> <button id="downloadBtn" class="btn btn-secondary" disabled>Preparing…</button> <a href="/victoriapublichall" class="btn btn-secondary">Book Another Visit</a> </div>
</div>
<script> async function ensureHtml2pdf() { if (window.html2pdf) return; try { await new Promise((resolve, reject) => { const s = document.createElement('script'); s.src = 'https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js'; s.onload = resolve; s.onerror = reject; document.head.appendChild(s); }); } catch (e) { await new Promise((resolve, reject) => { const s = document.createElement('script'); s.src = 'https://cdn.jsdelivr.net/npm/html2pdf.js@0.10.1/dist/html2pdf.bundle.min.js'; s.onload = resolve; s.onerror = reject; document.head.appendChild(s); }); } }
(function () { const $btn = $('#downloadBtn'); let summaryLoaded = false;
const qs = new URLSearchParams(location.search); const refId = qs.get('refId') || ''; if (!refId) { alert('Missing refId. Open this page as booking-summary.html?refId=YOUR_REF_ID'); return; }
// build API URL — default uses @GetMapping("/summary/{refId}") const apiUrl = `/victoriapublichall/api/summary/${encodeURIComponent(refId)}`; // if your controller uses @RequestParam instead, switch to: // const apiUrl = `/victoriapublichall/api/summary?refId=${encodeURIComponent(refId)}`;
$.getJSON(apiUrl) .done(function (data) { $('#summaryName').text(data.name || ''); $('#summaryPhone').text(data.mobileno || ''); $('#summaryMembers').text(data.noofpersons ?? '');if (data.booking_date) { const d = new Date(data.booking_date); const day = String(d.getDate()).padStart(2,'0'); const month = String(d.getMonth()+1).padStart(2,'0'); // months are 0-indexed const year = d.getFullYear(); $('#summaryDate').text(`${day}-${month}-${year}`);} else { $('#summaryDate').text('-');} $('#summaryTimeSlot').text(data.slot_timing || '');
// seats -> "G1: n, G2: n" (10 per group) const seatsRaw = (data.seats || '').toString(); const numbers = seatsRaw.split(',').map(s => parseInt(s.trim(), 10)).filter(n => !isNaN(n)); const groupCounts = {}; numbers.forEach(n => { const g = Math.ceil(n / 10); groupCounts[g] = (groupCounts[g] || 0) + 1; }); const lines = Object.keys(groupCounts).sort((a,b)=>a-b).map(g => `G${g}: ${groupCounts[g]}`).join(', '); $('#summarySlots').text(lines || seatsRaw || '-');
summaryLoaded = true; $btn.prop('disabled', false).text('Download PDF'); }) .fail(function (xhr) { alert(xhr?.responseJSON?.message || 'No booking found for this refId.'); });
$btn.on('click', async function () { if (!summaryLoaded) { alert('Please wait, loading details…'); return; }
await ensureHtml2pdf(); if (!window.html2pdf) { alert('PDF engine failed to load.'); return; }
// Enter "PDF export" layout to reduce spacing document.body.classList.add('pdf-export');
// Make sure fonts/layout are ready before capture if (document.fonts?.ready) { try { await document.fonts.ready; } catch {} } await new Promise(r => requestAnimationFrame(r)); await new Promise(r => setTimeout(r, 30)); // tiny extra paint buffer
const element = document.getElementById('bookingSummary'); window.html2pdf().set({ margin: 10, filename: 'VPH_booking_summary.pdf', image: { type: 'jpeg', quality: 0.98 }, html2canvas: { scale: 2, useCORS: true, backgroundColor: null, scrollY: 0 }, jsPDF: { unit: 'mm', format: 'a4', orientation: 'portrait' }, // let it paginate instead of clipping the bottom pagebreak: { mode: ['css', 'legacy'] } }) .from(element) .save() .then(() => { // restore normal layout document.body.classList.remove('pdf-export'); }) .catch(() => { document.body.classList.remove('pdf-export'); });});
})(); </script></body></html>
|