21 lines
2.2 KiB
JavaScript
21 lines
2.2 KiB
JavaScript
/** Guard navigation between functions without saving or repeating a business command. */
|
|
export function installPurchasingExit(doc,win){
|
|
const dirty=new Map();let pending=0,active=null;
|
|
const message=text=>{const target=doc.querySelector('#status')??doc.querySelector('#message');if(target)target.textContent=text;};
|
|
const prune=()=>{for(const form of dirty.keys())if(!form.isConnected)dirty.delete(form);};
|
|
doc.addEventListener('input',event=>{const form=event.target.closest('form');if(event.isTrusted&&form&&form.id!=='filters'&&form.closest('main'))dirty.set(form,(dirty.get(form)??0)+1);});
|
|
doc.addEventListener('click',event=>{
|
|
active=event.target.closest('form');if(event.isTrusted&&active&&/^(Adicionar linha|Retirar linha)$/.test(event.target.textContent))dirty.set(active,(dirty.get(active)??0)+1);const link=event.target.closest('a[href]');if(!link)return;prune();
|
|
if(pending){event.preventDefault();message('Aguarde a conclusão da conferência ou confirmação antes de sair.');return;}
|
|
if(dirty.size){if(!win.confirm('Existem campos por confirmar. Sair descarta esses campos. Continuar?'))event.preventDefault();else dirty.clear();}
|
|
},true);
|
|
win.addEventListener('beforeunload',event=>{prune();if(dirty.size||pending){event.preventDefault();event.returnValue='';}});
|
|
const fetch=win.fetch.bind(win);win.fetch=async(url,options={})=>{
|
|
const writing=options.method==='POST'&&typeof url==='string'&&url.startsWith('/api/purchasing-'),final=writing&&/\/(confirm|issue)$/.test(url),form=active,version=form&&dirty.get(form),fields=final&&form?[...form.querySelectorAll('input,select,textarea,button')].map(e=>[e,e.disabled]):[];if(writing)pending++;for(const [field]of fields)field.disabled=true;
|
|
try{const response=await fetch(url,options);let complete=false;if(writing){try{await response.clone().json();complete=true;}catch{/* Uncertain response keeps the fields/preview available for manual recovery. */}}if(final&&complete&&response.ok&&form&&dirty.get(form)===version)dirty.delete(form);return response;}
|
|
finally{for(const [field,disabled]of fields)field.disabled=disabled;if(writing)pending--;}
|
|
};
|
|
return {dirty,pending:()=>pending};
|
|
}
|
|
if(typeof document!=='undefined'&&typeof window!=='undefined')installPurchasingExit(document,window);
|