13 lines
5.0 KiB
JavaScript
13 lines
5.0 KiB
JavaScript
import {mountLogo} from './ds/logo.js';
|
|||
|
|
import {startNavScroll} from './ds/header.js';
|
||
|
|
import {link,mountAppChrome} from './ds/frame.js';
|
||
|
|
import {npubFrom,prod} from './ds/env.js';
|
||
|
|
const app=document.querySelector('#app');
|
||
|
|
const npub=npubFrom();
|
||
|
|
const esc=value=>String(value??'').replace(/[&<>"']/g,char=>({'&':'&','<':'<','>':'>','"':'"',"'":'''}[char]));
|
||
|
|
function fail(message){app.innerHTML=`<section class="failure"><span>∩</span><p>Business profile</p><h1>${esc(message)}</h1><a href="${link('business')}">Back to Business</a></section>`}
|
||
|
|
function field(label,id,value,type='text',extra=''){return `<label>${label}<input id="${id}" type="${type}" value="${esc(value)}" ${extra}></label>`}
|
||
|
|
function render(data){const profile=data.profile||{},image=profile.banner||data.images[0]||'';document.title=`${data.merchant.name} · Business profile`;app.innerHTML=`<header><a class="brand" href="${link('business')}"><span data-logo="icon"></span><b>Just Works<small>Business profile</small></b></a><a href="${link('business')}">Back to modules ↙</a></header><section class="profile-hero" ${image?`style="--hero:url('${esc(image)}')"`:''}><div class="wash"></div><div><p>Nostr merchant identity</p><h1>${esc(data.merchant.name)}</h1><span>${esc(npub)}</span></div></section><form id="profileForm"><section class="form-head"><div><p>Public profile</p><h2>What customers see.</h2></div><span>Saving republishes the signed Nostr profile and nsite.</span></section><div class="fields"><section><h3>Identity</h3>${field('Display name','displayName',profile.display_name||data.merchant.name)}<label>About<textarea id="about" rows="5">${esc(profile.about||'')}</textarea></label>${field('Nostr name','nostrName',profile.name||'','text','readonly')}${field('Public website','website',profile.website||data.links.justworks,'url','readonly')}</section><section><h3>Images</h3>${field('Profile picture URL','picture',profile.picture||'','url')}${field('Banner image URL','banner',profile.banner||'','url')}<p class="hint">Use public HTTPS image URLs. These images appear in the signed Nostr profile.</p></section><section id="lightning" class="lightning"><h3>Payments</h3>${field('Lightning address','lud16',profile.lud16||'','email','placeholder="merchant@example.com" required')}<p class="hint">Pay Bill and Just Pay remain locked while this uses the default <code>@npub.cash</code> address.</p></section><section class="owner"><h3>Owner authorization</h3>${field('Owner login','ownerIdentifier',prod?'':'demo','text','autocomplete="username"')}${field('Owner password','ownerPassword',prod?'':'demo','password','autocomplete="current-password"')}<div class="or"><span>or</span></div>${field('Owner key','ownerKey','','password','placeholder="nsec1… or ncryptsec1…" autocomplete="off"')}<p class="hint">Credentials are used only for this save and publish request. Just Works Business does not store them.</p></section></div><div class="submit-row"><p id="status">Ready to update the signed merchant profile.</p><button id="save" type="submit">Save & publish <span>→</span></button></div></form>`;document.querySelector('#profileForm').onsubmit=save;document.querySelectorAll('[data-logo]').forEach(host=>mountLogo(host,{icon:true}))}
|
||
|
|
async function save(event){event.preventDefault();const button=document.querySelector('#save'),status=document.querySelector('#status');button.disabled=true;status.textContent='Signing and publishing the Nostr profile…';const profile={display_name:document.querySelector('#displayName').value,about:document.querySelector('#about').value,picture:document.querySelector('#picture').value,banner:document.querySelector('#banner').value,lud16:document.querySelector('#lud16').value};const body={npub,profile,ownerIdentifier:document.querySelector('#ownerIdentifier').value,ownerPassword:document.querySelector('#ownerPassword').value,ownerKey:document.querySelector('#ownerKey').value};try{const response=await fetch('/api/business-profile',{method:'POST',headers:{'content-type':'application/json'},body:JSON.stringify(body)}),data=await response.json();if(!response.ok)throw new Error(data.error||'Could not publish');document.querySelector('#ownerPassword').value='';document.querySelector('#ownerKey').value='';status.textContent='Published. Pay Bill and Just Pay are now available.';button.innerHTML='Published ✓';setTimeout(()=>location.href=link('business'),1200)}catch(error){status.textContent=error.message;status.classList.add('error');button.disabled=false;button.innerHTML='Try again <span>↻</span>'}finally{document.querySelector('#ownerPassword').value='';document.querySelector('#ownerKey').value=''}}
|
||
|
|
if(!npub)fail('Add the merchant npub.');else fetch(`/api/business?npub=${encodeURIComponent(npub)}`,{cache:'no-store'}).then(async response=>{const data=await response.json();if(!response.ok)throw new Error(data.error||'Profile unavailable');render(data);app.querySelector(':scope > header')?.remove();mountAppChrome(app,{label:'Business profile',endHtml:`<a class="profile-back" href="${link('business')}">Back to modules ↙</a>`})}).catch(error=>fail(error.message));
|