24 lines
5.6 KiB
React
24 lines
5.6 KiB
React
import React,{useEffect,useRef,useState} from 'react';
|
|
import {moduleGuides,overviewSources,overviewPage} from './workspace-overview.js';
|
|
|
|
export function OverviewRecords({source,result,navigate}){
|
|
return <>{result.facts?.length>0&&<dl className="overview-definitions">{result.facts.map(f=><div key={f.label}><dt>{f.label}</dt><dd>{f.value}</dd></div>)}</dl>}<p role="status">{result.total} registo(s) nesta fonte autorizada · página {result.page} de {result.last}.{result.observed&&` Referência da fonte: ${result.observed}.`}</p><div className="table-scroll"><table><thead><tr><th>Referência e descrição</th><th>Estado ou entidade</th><th>Valor ou identificação</th><th>Evidência</th></tr></thead><tbody>{result.rows.map((r,i)=><tr key={i}><td><strong>{r.reference}</strong><small>{r.detail}</small></td><td>{r.state}</td><td>{r.value}</td><td>{r.evidence}</td></tr>)}</tbody></table></div>{!result.rows.length&&<p>Nenhum registo nesta página e fonte autorizadas.</p>}<p>{source.href?<a href={source.href}>Abrir consulta completa, documentos e histórico</a>:<button onClick={()=>navigate(source.target)}>Abrir consulta completa, documentos e histórico</button>}</p></>;
|
|
}
|
|
export default function WorkspaceHome({context,groups=[],can=()=>false,api,navigate=()=>{},openPage=()=>{}}) {
|
|
const sources=overviewSources(context,can),guide=moduleGuides[context.module_id];
|
|
const [selection,setSelection]=useState(''),[result,setResult]=useState(null),[error,setError]=useState(''),[loading,setLoading]=useState(false);const generation=useRef(0);
|
|
useEffect(()=>{generation.current++;setSelection('');setResult(null);setError('');setLoading(false);return()=>{generation.current++;};},[context.token]);
|
|
const source=sources.find(s=>s.id===selection);
|
|
async function load(s,page=1){const current=++generation.current;setSelection(s.id);setResult(null);setError('');setLoading(true);try{const r=await api(s.path+(s.path.includes('?')?'&':'?')+'page='+page);const value=overviewPage(s,r);if(current===generation.current)setResult(value);}catch(e){if(current===generation.current)setError(e.message);}finally{if(current===generation.current)setLoading(false);}}
|
|
const activeGroups=groups.filter(g=>!['start','admin'].includes(g.id));
|
|
return <div className="workspace-overview">
|
|
<div className="page-title"><p className="eyebrow">ÁREA DE TRABALHO</p><h1>{guide?guide.label:'Início do SGF'}</h1><p>{guide?.purpose??'Escolha um módulo e uma função autorizada para trabalhar com os seus documentos.'}</p><p>{context.company.name}{context.unit&&` / ${context.unit.name}`}. Informação limitada ao contexto e à função actuais.</p></div>
|
|
{!context.unit&&<p className="alert home-notice" role="status">Seleccione uma unidade para consultar os percursos de trabalho dessa unidade.</p>}
|
|
{guide&&<section className="panel"><h2>Do primeiro registo à evidência final</h2><ol className="overview-steps">{guide.steps.map(s=><li key={s}>{s}</li>)}</ol><dl className="overview-definitions"><div><dt>O que comprova o percurso</dt><dd>{guide.evidence}</dd></div><div><dt>Como interpretar a informação</dt><dd>{guide.boundary}</dd></div><div><dt>Ligação à etapa seguinte</dt><dd>{guide.next}</dd></div></dl></section>}
|
|
{!!sources.length&&<section className="panel"><h2>Informação existente neste módulo</h2><p>Escolha a fonte a consultar. A leitura não prepara nem repete operações; cada página traz até25 registos (requisições:15). Os valores são apresentados individualmente.</p><div className="actions">{sources.map(s=><button key={s.id} aria-pressed={s.id===selection} disabled={loading} onClick={()=>load(s)}>{s.label}</button>)}</div>{loading&&<p role="status">A consultar a fonte autorizada…</p>}{error&&<div role="alert"><p>{error}</p><p>Não é possível concluir que existem zero registos ou saldo zero.</p><button onClick={()=>source&&load(source)}>Tentar novamente</button></div>}{source&&result&&<><h3>{source.label}</h3><OverviewRecords source={source} result={result} navigate={navigate}/><div className="actions"><button disabled={loading||result.page<=1} onClick={()=>load(source,result.page-1)}>Anterior</button><button disabled={loading||result.page>=result.last} onClick={()=>load(source,result.page+1)}>Seguinte</button><button disabled={loading} onClick={()=>load(source)}>Actualizar a partir da primeira página</button></div><p className="help">Leitura actual por página, sem fotografia global entre páginas. Eventos de preparação/revisão não são movimentos financeiros; não se somam os valores desta lista.</p></>}</section>}
|
|
{activeGroups.length>0&&<section className="panel"><h2>Funções disponíveis para o seu trabalho</h2><div className="overview-grid">{activeGroups.map(g=><article key={g.id}><h3>{g.label}</h3>{g.items.map(i=><button key={i.id} onClick={()=>navigate(i.id)}>{i.label} →</button>)}</article>)}</div></section>}
|
|
<section className="panel"><h2>Continuidade entre módulos</h2><p>A mudança de módulo é explícita e conserva os controlos de acesso. Cada entrada abaixo oferece apenas as funções já autorizadas para a sua conta.</p><div className="overview-grid">{(context.modules??[]).map(m=>{const g=moduleGuides[m.id];return <article key={m.id}><h3>{m.label}</h3><p>{g?.purpose}</p><p>{g?.next}</p><button disabled={m.id===context.module_id} onClick={()=>openPage(m.id,'home')}>{m.id===context.module_id?'Módulo actual':'Abrir início de '+m.label}</button></article>;})}</div></section>
|
|
{context.single_installation&&<p className="help">Instalação local com dados fictícios. As consultas mostram os registos existentes; mapas fiscais internos e indicadores de ensaio não comprovam conformidade legal ou operação real.</p>}
|
|
</div>;
|
|
}
|