Files
SGF/public/obligation-evidence.mjs
2026-11-04 09:37:20 +02:00

14 lines
3.6 KiB
JavaScript

import {evidence as renderEvidence,purchasingStatus} from './purchasing-presenter.mjs';
/** Evidence browsing never rebuilds a selected decision or executes a command. */
export function mountObligationEvidence({id,data,container,api,active,makeDecision,onStale,refresh,message,canSelect=()=>true}){
const node=(tag,text)=>{const element=document.createElement(tag);if(text!==undefined)element.textContent=text;return element;},signature=value=>JSON.stringify([value.revision,value.current_actor,value.permissions.prepare===true,value.permissions.validate===true]),initial=signature(data),proposals=node('section'),decision=node('section'),events=node('section'),refreshButton=node('button','Actualizar origem e conferências');refreshButton.type='button';refreshButton.onclick=refresh;container.append(refreshButton,proposals,decision,events);let pages={proposals:data.pagination.proposals.page,events:data.pagination.events.page},serial=0,stale=false,selected=null;
function invalidate(){if(stale)return;stale=true;for(const button of container.querySelectorAll('button'))if(button!==refreshButton)button.disabled=true;onStale();message('A origem ou as permissões mudaram. Actualize a origem antes de continuar a decisão.');}
async function load(kind,page){if(stale)return;pages={...pages,[kind]:page};const request=++serial,query=new URLSearchParams({proposal_page:String(pages.proposals),event_page:String(pages.events)});try{const value=await api('/'+id+'?'+query);if(!active()||request!==serial||stale)return;if(signature(value)!==initial){invalidate();return;}data=value;render();}catch(error){if(!active()||request!==serial)return;if([403,409].includes(error.status))invalidate();else message(error.message+' Pode repetir a consulta sem perder o fundamento.');}}
function pagination(box,key){const meta=data.pagination[key];box.append(node('p',(key==='events'?'Histórico':'Propostas')+' · página '+meta.page+' de '+meta.last_page));for(const [enabled,target,text]of [[meta.page>1,meta.page-1,'Anterior'],[meta.page<meta.last_page,meta.page+1,'Seguinte']])if(enabled){const button=node('button',text);button.type='button';button.onclick=()=>load(key,target);box.append(button);}}
function render(){
proposals.replaceChildren(node('h2','Propostas preservadas'));for(const proposal of data.proposals){const card=node('article');card.append(node('h3','Proposta #'+proposal.id+' · versão '+proposal.capture_version),node('p','Preparador #'+proposal.prepared_by+' · '+proposal.created_at),node('p',proposal.reason),renderEvidence(proposal.missing));if(data.permissions.validate&&proposal.prepared_by!==data.current_actor&&!data.obligations.length){const choose=node('button','Conferir proposta #'+proposal.id);choose.type='button';choose.onclick=()=>{if(stale||!active()||selected===proposal.id)return;if(!canSelect()){message('Aguarde a operação em curso antes de mudar de proposta.');return;}selected=proposal.id;decision.replaceChildren(node('h2','Decisão seleccionada: proposta #'+proposal.id),node('p','Paginar a evidência conserva este fundamento. Seleccionar outra proposta inicia uma decisão distinta.'));makeDecision(proposal,decision);};card.append(choose);}proposals.append(card);}if(!data.proposals.length)proposals.append(node('p','Sem propostas nesta página.'));pagination(proposals,'proposals');
events.replaceChildren(node('h2','Histórico'));for(const event of data.events){const row=node('details');row.append(node('summary',event.created_at+' · '+event.kind+' · autor #'+event.actor_id),renderEvidence(event.payload));events.append(row);}if(!data.events.length)events.append(node('p','Sem eventos nesta página.'));pagination(events,'events');
}
render();
}