Files
Investidor-V2/resources/js/components/partnership-edit-comparison.tsx
T

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>
);
}