276 lines
13 KiB
TypeScript
276 lines
13 KiB
TypeScript
import type {
|
|
PartnershipEditor,
|
|
PartnershipSection,
|
|
} from '@/lib/partnership-edit';
|
|
import { labels, type Catalogues } from '@/pages/partnerships/shared';
|
|
|
|
const fields: Record<PartnershipSection, string> = {
|
|
title: 'Título',
|
|
offer: 'Recursos que oferece',
|
|
seeking: 'Colaboração que procura',
|
|
organization_id: 'Organização representada',
|
|
sector_id: 'Sector',
|
|
kind: 'Oferta ou procura',
|
|
partnership_type: 'Tipo de parceria',
|
|
deadline: 'Prazo para manifestações de interesse',
|
|
summary: 'Resumo',
|
|
requirements: 'Requisitos desejáveis',
|
|
mandatory: 'Critérios obrigatórios',
|
|
confidentiality: 'Visibilidade',
|
|
consent: 'Autorização de divulgação',
|
|
availability: 'Disponibilidade dos recursos ou colaboração',
|
|
locations: 'Localizações e respectivas fontes',
|
|
origins: 'Origens documentais',
|
|
};
|
|
export default function PartnershipEditComparison({
|
|
editor,
|
|
catalogues,
|
|
}: {
|
|
editor: PartnershipEditor;
|
|
catalogues: Catalogues;
|
|
}) {
|
|
function display(
|
|
key: PartnershipSection,
|
|
value: PartnershipEditor['values'][PartnershipSection],
|
|
): string {
|
|
if (typeof value === 'boolean')
|
|
return value ? 'Autorização indicada' : 'Sem autorização indicada';
|
|
if (Array.isArray(value))
|
|
return value.length
|
|
? value
|
|
.map((item) => {
|
|
if (typeof item === 'string')
|
|
return (
|
|
catalogues.criteria[item] ??
|
|
'Critério anterior fora da configuração actual'
|
|
);
|
|
if ('geo_location_id' in item)
|
|
return `${catalogues.territories.find((place) => place.id === item.geo_location_id)?.name ?? 'Localização anteriormente indicada'} · ${{ primary: 'Principal', operating: 'Operação', coverage: 'Cobertura' }[item.role] ?? item.role} · ${item.source_reference}`;
|
|
return (
|
|
catalogues.sources?.find(
|
|
(source) =>
|
|
source.type === item.type &&
|
|
source.target_id === item.target_id,
|
|
)?.title ??
|
|
'Origem documental anteriormente associada'
|
|
);
|
|
})
|
|
.join('\n')
|
|
: 'Nenhuma selecção';
|
|
if (!value) return 'Não indicado';
|
|
if (key === 'organization_id')
|
|
return (
|
|
catalogues.organizations.find(
|
|
(item) => String(item.id) === value,
|
|
)?.name ?? 'Organização anteriormente indicada'
|
|
);
|
|
if (key === 'sector_id')
|
|
return (
|
|
catalogues.sectors.find((item) => String(item.id) === value)
|
|
?.name ?? 'Sector anteriormente indicado'
|
|
);
|
|
if (key === 'partnership_type')
|
|
return (
|
|
catalogues.types[value] ??
|
|
'Tipo anterior fora da configuração actual'
|
|
);
|
|
if (key === 'kind')
|
|
return value === 'offering'
|
|
? 'Oferta'
|
|
: value === 'seeking'
|
|
? 'Procura'
|
|
: value;
|
|
if (key === 'confidentiality')
|
|
return value === 'private'
|
|
? 'Privada'
|
|
: value === 'public'
|
|
? 'Pública'
|
|
: value;
|
|
return value;
|
|
}
|
|
return (
|
|
<section
|
|
aria-label="Comparação da parceria"
|
|
className="space-y-3 rounded border p-4"
|
|
>
|
|
{editor.problem && <p role="alert">{editor.problem}</p>}
|
|
{editor.invalid && (
|
|
<p role="alert">
|
|
Os dados desta edição não foram reconhecidos. Reabra a
|
|
parceria correcta antes de guardar; a edição actual foi
|
|
conservada.
|
|
</p>
|
|
)}
|
|
{editor.retryingCreation && (
|
|
<p>
|
|
Repita a criação anterior para recuperar o registo. O pedido
|
|
anterior será reutilizado, sem substituir as suas edições
|
|
posteriores nem criar outra parceria.
|
|
</p>
|
|
)}
|
|
{editor.retryingSave && (
|
|
<div className="space-y-2">
|
|
<p>
|
|
A edição anterior não foi confirmada. Recuperar repete
|
|
exactamente a mesma tentativa e conserva o que preparou
|
|
depois de enviar.
|
|
</p>
|
|
<button
|
|
type="button"
|
|
className="underline"
|
|
disabled={!editor.canRecoverSave}
|
|
onClick={editor.recoverSave}
|
|
>
|
|
Recuperar a mesma gravação
|
|
</button>
|
|
</div>
|
|
)}
|
|
{editor.mustRefresh && (
|
|
<p>
|
|
Consulte os dados actuais antes de adoptar uma versão para
|
|
uma nova tentativa.
|
|
</p>
|
|
)}
|
|
{editor.refreshing && (
|
|
<p role="status">
|
|
A recuperar os dados actuais. As suas edições são
|
|
conservadas.
|
|
</p>
|
|
)}
|
|
<button
|
|
type="button"
|
|
className="underline"
|
|
disabled={editor.refreshing || editor.form.processing}
|
|
onClick={editor.refresh}
|
|
>
|
|
Comparar com os dados actuais
|
|
</button>
|
|
{editor.current && !editor.editable && (
|
|
<p role="status">
|
|
Estado actual:{' '}
|
|
{labels[editor.current.status] ?? 'Estado por confirmar'}. A
|
|
parceria está disponível para consulta; a edição por guardar
|
|
foi conservada e não pode ser gravada neste estado.
|
|
</p>
|
|
)}
|
|
{editor.current?.status === 'published' && (
|
|
<p>
|
|
Ao guardar esta revisão, a proposta volta a rascunho e
|
|
requer nova submissão e revisão pelo percurso existente.
|
|
</p>
|
|
)}
|
|
{(editor.stale || editor.retryingSave) && (
|
|
<>
|
|
<p role="alert">
|
|
A proposta mudou desde{' '}
|
|
{editor.baseVersion === null
|
|
? 'a preparação inicial'
|
|
: `a versão ${editor.baseVersion}`}
|
|
. Compare com a versão {editor.current?.version} e
|
|
escolha como conservar os seus dados.
|
|
</p>
|
|
<div className="overflow-x-auto">
|
|
<table className="w-full text-left text-sm">
|
|
<thead>
|
|
<tr>
|
|
<th>Campo</th>
|
|
<th>Actualmente guardado</th>
|
|
<th>Sua edição</th>
|
|
<th>Escolha</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{editor.changed.map((key) => (
|
|
<tr key={key} className="border-t">
|
|
<th
|
|
scope="row"
|
|
className="p-2 align-top"
|
|
>
|
|
{fields[key]}
|
|
</th>
|
|
<td className="max-w-md p-2 align-top break-words whitespace-pre-wrap">
|
|
{editor.current &&
|
|
display(
|
|
key,
|
|
editor.current.values[key],
|
|
)}
|
|
</td>
|
|
<td className="max-w-md p-2 align-top break-words whitespace-pre-wrap">
|
|
{display(key, editor.values[key])}
|
|
</td>
|
|
<td className="space-y-2 p-2 align-top">
|
|
{editor.conflicts.includes(key) ? (
|
|
<>
|
|
<button
|
|
type="button"
|
|
className="block underline"
|
|
disabled={
|
|
editor.refreshing ||
|
|
editor.form
|
|
.processing
|
|
}
|
|
onClick={() =>
|
|
editor.choose(
|
|
key,
|
|
'current',
|
|
)
|
|
}
|
|
>
|
|
Usar valor actual
|
|
</button>
|
|
<button
|
|
type="button"
|
|
className="block underline"
|
|
disabled={
|
|
editor.refreshing ||
|
|
editor.form
|
|
.processing
|
|
}
|
|
onClick={() =>
|
|
editor.choose(
|
|
key,
|
|
'mine',
|
|
)
|
|
}
|
|
>
|
|
Manter minha alteração
|
|
</button>
|
|
{editor.unresolved.includes(
|
|
key,
|
|
) && (
|
|
<p>
|
|
Escolha o valor a
|
|
conservar neste
|
|
campo.
|
|
</p>
|
|
)}
|
|
</>
|
|
) : (
|
|
'Actualização compatível com a sua edição'
|
|
)}
|
|
</td>
|
|
</tr>
|
|
))}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
<button
|
|
type="button"
|
|
className="underline"
|
|
disabled={
|
|
editor.invalid ||
|
|
editor.refreshing ||
|
|
editor.form.processing ||
|
|
editor.mustRefresh ||
|
|
editor.unresolved.length > 0
|
|
}
|
|
onClick={editor.adopt}
|
|
>
|
|
Usar esta versão e conservar as alterações escolhidas
|
|
</button>
|
|
</>
|
|
)}
|
|
</section>
|
|
);
|
|
}
|