Files
archy/docker/justworks/business/public/assets/qr-sheet.js
T
yaya 94899e69d3 feat: integrate Just Works app and native business setup
Preserve hosted website UX inside Archipelago, add isolated Business and owner-authorized native wallet setup, and include deployment handoff. Based on main with native signer import already accepted.
2026-10-08 19:39:38 +01:00

67 lines
3.3 KiB
JavaScript

import { qrImageUrl } from './module-qr.js?v=3';
import { businessUrl, sheetDestinations, validNpub } from './business-destinations.js?v=1';
const status = document.querySelector('#status');
const sheet = document.querySelector('#sheet');
const print = document.querySelector('#print');
const labels = document.querySelector('#labels');
const npub = new URLSearchParams(location.search).get('npub')?.trim();
const fail = message => {
status.textContent = message;
status.classList.add('error');
print.disabled = true;
};
async function openSheet() {
if (!validNpub(npub)) throw new Error('Open this QR sheet from your Business dashboard with a valid merchant npub.');
// Do not propagate unrelated URL parameters or fragments into links or prints.
history.replaceState(null, '', `${location.pathname}?npub=${encodeURIComponent(npub)}`);
document.querySelector('#back').href = businessUrl(npub);
const response = await fetch(`/api/business?npub=${encodeURIComponent(npub)}`, {cache: 'no-store'});
if (!response.ok) throw new Error('The merchant could not be loaded. Return to Business or reload to try again.');
const data = await response.json();
if (data.merchant?.npub !== npub) throw new Error('Merchant identity could not be verified. Open the sheet again from Business.');
const destinations = sheetDestinations(data, npub);
document.title = `${data.merchant.name} · QR in DIN A4 · Just Works`;
document.querySelector('#merchant-name').textContent = data.merchant.name;
document.querySelector('#label-count').textContent = `${destinations.length} merchant links · Print & cut`;
const loading = destinations.map(({id, title, url}) => {
const target = new URL(url, location.origin);
if (!['https:', 'http:'].includes(target.protocol) || target.username || target.password) throw new Error('A merchant link is unavailable. Return to Business to check the links.');
const card = document.createElement('article');
card.className = 'qr-label';
card.dataset.destination = id;
const name = document.createElement('p');
name.className = 'label-merchant';
name.textContent = data.merchant.name;
const heading = document.createElement('h2');
heading.textContent = title;
const anchor = document.createElement('a');
anchor.href = target.href;
anchor.setAttribute('aria-label', `Open ${title}`);
const image = document.createElement('img');
image.alt = `${title} QR code for ${data.merchant.name}`;
image.width = image.height = 320;
const ready = new Promise((resolve, reject) => {
image.onload = resolve;
image.onerror = () => reject(new Error('Some QR codes could not load. Reload this page before printing.'));
});
image.src = qrImageUrl(target.href);
anchor.append(image);
const caption = document.createElement('p');
caption.className = 'label-caption';
caption.textContent = ['business', 'pos', 'stats'].includes(id) ? 'Team access · Just Works' : 'Scan to open · Just Works';
card.append(name, heading, anchor, caption);
labels.append(card);
return ready;
});
sheet.hidden = false;
await Promise.all(loading);
await document.fonts.ready;
status.textContent = 'Ready to print. All QR codes loaded.';
print.disabled = false;
sheet.dataset.ready = 'true';
}
print.addEventListener('click', () => { if (!print.disabled) window.print(); });
openSheet().catch(fail);