Files
SGF/public/sgf-module-context.js
2026-11-02 08:06:45 +02:00

50 lines
3.2 KiB
JavaScript

// SGF host wrapper only; the shared purchasing package remains unchanged.
document.addEventListener('DOMContentLoaded', () => {
const dirty = new Set();
let pending=0;
for(const form of document.querySelectorAll('form[data-action]')){
const submit=form.onsubmit;
if(typeof submit!=='function')continue;
form.onsubmit=async e=>{
pending++;
try{await submit.call(form,e);if(!document.querySelector('#error')?.textContent.trim())dirty.delete(form);}
finally{pending--;}
};
}
document.addEventListener('input', e => { const form=e.target.closest('form');if(form)dirty.add(form); });
window.addEventListener('beforeunload', e => { if(dirty.size||pending){e.preventDefault();e.returnValue='';} });
const back=document.querySelector('[data-sgf-module-back]');
back?.addEventListener('click', e => {
if(pending){e.preventDefault();document.querySelector('#error').textContent='Aguarde a conclusão da operação antes de sair.';return;}
if(!dirty.size)return;
e.preventDefault();
const dialog=document.createElement('dialog');
dialog.setAttribute('aria-label','Alterações por guardar');
dialog.innerHTML='<h2>Alterações por guardar</h2><p>Guarde, descarte ou cancele a saída deste percurso.</p><p role="alert"></p><button data-save>Guardar e continuar</button> <button data-discard>Descartar e continuar</button> <button data-cancel>Cancelar</button>';
document.body.append(dialog);dialog.showModal();
const close=()=>{dialog.close();dialog.remove();back.focus();};
dialog.querySelector('[data-cancel]').onclick=close;
dialog.addEventListener('cancel',e=>{e.preventDefault();close();});
dialog.querySelector('[data-discard]').onclick=()=>{dirty.clear();location.assign(back.href);};
dialog.querySelector('[data-save]').onclick=async()=>{
for(const b of dialog.querySelectorAll('button'))b.disabled=true;
try{
if(dirty.size>1)throw Error('Guarde cada formulário no percurso original antes de sair. O contexto foi mantido.');
for(const form of [...dirty]){
if(!form.isConnected){dirty.delete(form);continue;}
if(!form.reportValidity())throw Error('Corrija os campos. O contexto foi mantido.');
if(typeof form.onsubmit!=='function')throw Error('Guarde no formulário original antes de sair.');
// Existing package handlers validate, post and report errors in #error.
// Successful handlers reload their own page; this destination supersedes
// that reload only after the original promise has completed successfully.
await form.onsubmit({preventDefault(){}});
if(document.querySelector('#error')?.textContent.trim())throw Error('A gravação falhou. O contexto foi mantido.');
dirty.delete(form);
}
location.assign(back.href);
}catch(error){dialog.querySelector('[role=alert]').textContent=error.message;}
finally{for(const b of dialog.querySelectorAll('button'))b.disabled=false;}
};
});
});