const venuesEl = document.getElementById('venues'); const seedBtn = document.getElementById('seed'); const addBtn = document.getElementById('v-add'); const nameIn = document.getElementById('v-name'); const slugIn = document.getElementById('v-slug'); const makeBtn = document.getElementById('session-make'); const slugSessionIn = document.getElementById('session-slug'); const qrArea = document.getElementById('qr-area'); const crmSee = document.getElementById('crm-see'); const crmJson = document.getElementById('crm-json'); async function listVenues(){ const r = await fetch('/api/admin/venues', {cache:'no-store'}); const items = await r.json(); if (!Array.isArray(items) || items.length === 0){ venuesEl.textContent = '(登録なし)'; return; } venuesEl.innerHTML = ''; } async function seedDemo(){ const r = await fetch('/api/admin/seed', {method:'POST'}); const j = await r.json(); alert(j.created ? 'デモ店舗を作成しました' : 'デモ店舗は既に存在します'); await listVenues(); } async function addVenue(){ const name = nameIn.value.trim(); const slug = slugIn.value.trim(); if (!name || !slug){ alert('店名とslugを入力してください'); return; } const r = await fetch('/api/admin/venues', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({name, slug}) }); if (r.ok){ nameIn.value=''; slugIn.value=''; await listVenues(); } else { const e = await r.json().catch(()=>({})); alert('登録失敗: ' + (e.detail || r.status)); } } async function fetchQRObjectURL(sessionId){ const url = `/qrcode/${sessionId}`; const r = await fetch(url, {cache:'no-store'}); if (!r.ok) throw new Error(`QR取得失敗: ${r.status}`); const blob = await r.blob(); return URL.createObjectURL(blob); } async function makeSession(){ const slug = slugSessionIn.value.trim(); if (!slug){ alert('店舗slugを入力してください'); return; } const r = await fetch('/api/checkin/session', { method:'POST', headers:{'Content-Type':'application/json'}, body: JSON.stringify({venue_slug: slug}) }); const j = await r.json(); if (!r.ok){ alert('発行失敗: ' + (j.detail || r.status)); return; } const checkinUrl = `/checkin/${j.session_id}`; // QRはBlob→ObjectURLで確実に表示 let qrObjectUrl = ''; try { qrObjectUrl = await fetchQRObjectURL(j.session_id); } catch (e) { console.error(e); } qrArea.innerHTML = `
QR
セッション: ${j.session_id}
チェックインページを開く

画像が表示されない場合は、右のボタンでページを開き、URLを手元のQR生成アプリに貼ってください。

※ QRは5分で失効します。必要に応じて再発行してください。

`; } async function seeCRM(){ const r = await fetch('/api/crm/segments', {cache:'no-store'}); const j = await r.json(); crmJson.textContent = JSON.stringify(j, null, 2); } seedBtn.onclick = seedDemo; addBtn.onclick = addVenue; makeBtn.onclick = makeSession; crmSee.onclick = seeCRM; listVenues();