11 lines
5.3 KiB
JavaScript
11 lines
5.3 KiB
JavaScript
export function mountSupplierDocuments({id,revision,canUpload,root,detail,active,reload,message,basePath=null,receipt=false}){
|
|
const node=(tag,text)=>{const e=document.createElement(tag);if(text!==undefined)e.textContent=text;return e;},base=basePath||'/api/purchasing-suppliers/'+id+'/documents',headers=()=>({Accept:'application/json','X-SGF-Context':root.dataset.context,'X-CSRF-TOKEN':root.dataset.csrf});
|
|
async function request(path,body){const r=await fetch(base+path,{method:body?'POST':'GET',headers:headers(),body});const d=await r.json();if(!r.ok)throw Error(Object.values(d.errors||{}).flat().join(' ')||d.message||'Não foi possível conferir o anexo.');return d;}
|
|
const section=node('section'),listing=node('div');section.append(node('h2','Anexos documentais privados'),node('p',receipt?'Anexar conserva a evidência na recepção. Não altera quantidades, qualidade, aceitação ou stock. Não certifica autenticidade.':'Anexar conserva o ficheiro e coloca a ficha em revisão pendente. Não certifica autenticidade, validade fiscal ou aprovação documental.'),listing);detail.append(section);let listSerial=0;
|
|
async function load(page=1){const turn=++listSerial;try{const d=await request('?page='+page);if(!active()||turn!==listSerial)return;listing.replaceChildren();for(const doc of d.data){const row=node('article');row.append(node('h3',doc.original_name),node('p',doc.document_type+' · '+doc.mime_type+' · '+doc.size+' bytes'),node('p','Autor #'+doc.uploaded_by+' · '+doc.created_at),node('p','SHA-256: '+doc.sha256));const download=node('button','Descarregar cópia conferida');download.type='button';download.onclick=async()=>{download.disabled=true;try{const r=await fetch(base+'/'+doc.id+'/download',{headers:headers()});if(!r.ok){const error=await r.json();throw Error(error.message||'Anexo indisponível.');}const blob=await r.blob();if(!active())return;const url=URL.createObjectURL(blob),a=node('a');a.href=url;a.download=doc.original_name;a.click();setTimeout(()=>URL.revokeObjectURL(url),1000);}catch(e){if(active())message(e.message);}finally{download.disabled=false;}};row.append(download);listing.append(row);}if(!d.data.length)listing.append(node('p','Sem anexos nesta página.'));listing.append(node('p','Página '+d.current_page+' de '+d.last_page));for(const [enabled,target,label]of [[d.current_page>1,d.current_page-1,'Anterior'],[d.current_page<d.last_page,d.current_page+1,'Seguinte']])if(enabled){const b=node('button',label);b.type='button';b.onclick=()=>load(target);listing.append(b);}}catch(e){if(active())message(e.message);}}
|
|
load();if(!canUpload)return;
|
|
const form=node('form'),typeLabel=node('label','Tipo documental'),type=node('select'),fileLabel=node('label','Ficheiro PDF, PNG ou JPEG — até 2 MB'),file=node('input'),reasonLabel=node('label','Fundamento deste anexo'),reason=node('textarea'),prepare=node('button','Conferir ficheiro e impacto'),confirm=node('button',receipt?'Confirmar este anexo':'Anexar e submeter a nova revisão'),impact=node('section');type.required=true;for(const [v,t]of (receipt?[['','Seleccione explicitamente'],['delivery_note','Guia de entrega'],['quality','Relatório de qualidade'],['other','Outro documento']]:[['','Seleccione explicitamente'],['license','Licença'],['tax','Documento fiscal'],['conflict','Conflito de interesses'],['other','Outro documento']]))type.append(new Option(t,v));file.type='file';file.accept='.pdf,.png,.jpg,.jpeg';file.required=true;reason.required=true;reason.minLength=10;reason.maxLength=2000;typeLabel.append(type);fileLabel.append(file);reasonLabel.append(reason);prepare.type='submit';confirm.type='button';confirm.disabled=true;impact.hidden=true;form.append(node('h3','Preparar anexo'),typeLabel,fileLabel,reasonLabel,prepare,impact,confirm);section.append(form);let busy=false,cut=null,key=crypto.randomUUID(),version=0;
|
|
form.oninput=()=>{version++;key=crypto.randomUUID();cut=null;confirm.disabled=true;impact.hidden=true;};form.onsubmit=async e=>{e.preventDefault();if(busy)return;busy=true;prepare.disabled=true;const observed=version;try{const body=new FormData;body.append('operation_key',key);body.append('revision',revision);body.append('document_type',type.value);body.append('reason',reason.value);body.append('file',file.files[0]);const d=await request('/preview',body);if(!active()||observed!==version)return;cut=d.preview;const doc=d.impact.document;impact.replaceChildren(node('h4','Impacto conferido'),node('p',doc.original_name+' · '+doc.mime_type+' · '+doc.size+' bytes'),node('p','SHA-256: '+doc.sha256),node('p',receipt?(d.impact.reused?'Documento existente será reutilizado, sem outra cópia.':'Novo documento privado será ligado à recepção.')+' Quantidades, aceitação e stock permanecem intactos.':'Ficha ficará pendente, versão '+d.impact.supplier_version+'. A revisão anterior deixa de ser suficiente.'),node('p','Fundamento: '+d.impact.reason));impact.hidden=false;confirm.disabled=false;}catch(e){if(active())message(e.message);}finally{busy=false;prepare.disabled=false;}};
|
|
confirm.onclick=async()=>{if(busy||!cut)return;busy=true;confirm.disabled=true;try{const body=new FormData;body.append('preview',cut);body.append('file',file.files[0]);await request('/confirm',body);if(active())await reload();}catch(e){if(active())message(e.message+' Se perdeu a resposta, repita a mesma confirmação com o mesmo ficheiro.');confirm.disabled=false;}finally{busy=false;}};
|
|
}
|