Files
Investidor-V2/resources/js/components/organization-country-editor.tsx
T

234 lines
9.7 KiB
TypeScript

import { useEffect, useId } from 'react';
import CountrySelect, { type Country } from './country-select';
import { Field, input, button, card } from '@/pages/investment/shared';
import {
useInvestmentProfileEditor,
type OrganizationRecord,
} from '@/lib/investment-profile-editor';
export default function OrganizationCountryEditor({
organization,
countries,
actorId,
reportDirty,
}: {
organization: OrganizationRecord;
countries: Country[];
actorId: number;
reportDirty: (id: string, dirty: boolean) => void;
}) {
const fields = ['country', 'source_reference'];
const editor = useInvestmentProfileEditor(
{
id: organization.id,
version: organization.version,
payload: {
country: organization.country ?? '',
source_reference: organization.provenance?.reference ?? '',
},
},
fields,
false,
actorId,
'organization-' + organization.id,
reportDirty,
organization,
);
const id = useId(),
disabled =
!editor.mayEdit ||
editor.busy ||
editor.uncertain ||
editor.blocked;
useEffect(() => {
if (Object.keys(editor.errors).length)
document
.getElementById(id)
?.querySelector<HTMLElement>('[aria-invalid="true"]')
?.focus();
}, [editor.errors, id]);
return (
<section
className={card}
aria-label={'País de constituição: ' + organization.name}
>
<h3 className="text-xl font-bold">{organization.name}</h3>
<p>
Versão guardada: {organization.version}.{' '}
{organization.provenance?.kind === 'representative_declaration'
? 'País declarado pelo representante.'
: 'Fonte do país ainda não informada.'}
</p>
{!editor.mayEdit && (
<p role="status">
Consulta do país de constituição. A sua representação actual
não permite alterar esta informação.
</p>
)}
<form
id={id}
className="mt-4 space-y-4"
aria-label={'País da organização: ' + organization.name}
onSubmit={(event) => {
event.preventDefault();
void editor.save();
}}
>
<Field label="País de constituição da organização">
<CountrySelect
id={id + '-country'}
label="País de constituição da organização"
required
countries={countries}
value={editor.draft.country}
disabled={disabled}
error={editor.errors.country}
onChange={(country) =>
editor.change('country', country)
}
/>
</Field>
<label htmlFor={id + '-source'}>
Fonte ou referência deste país
</label>
<textarea
id={id + '-source'}
aria-label="Fonte ou referência deste país"
className={input}
value={editor.draft.source_reference}
disabled={disabled}
required
minLength={5}
maxLength={2000}
rows={3}
aria-invalid={!!editor.errors.source_reference}
aria-describedby={
editor.errors.source_reference
? id + '-source-error'
: undefined
}
onChange={(event) =>
editor.change('source_reference', event.target.value)
}
/>
{editor.errors.source_reference && (
<p id={id + '-source-error'} role="alert">
{editor.errors.source_reference}
</p>
)}
{Object.entries(editor.errors)
.filter(([key]) => !fields.includes(key))
.map(([key, value]) => (
<p role="alert" key={key}>
{value}
</p>
))}
{editor.error && <p role="alert">{editor.error}</p>}
{editor.notice && <p role="status">{editor.notice}</p>}
{editor.stale && (
<p role="alert">
O país ou outra informação da organização foi alterado.
A sua preparação foi conservada; consulte e compare
antes de guardar.
</p>
)}
<div className="flex flex-wrap gap-3">
{editor.mayEdit && (
<button
className={button}
disabled={
editor.busy ||
editor.reading ||
editor.blocked ||
(editor.stale && !editor.uncertain)
}
>
{editor.uncertain
? 'Repetir o mesmo pedido'
: 'Guardar país da organização'}
</button>
)}
<button
className={button}
type="button"
disabled={editor.busy || editor.reading}
onClick={() => void editor.refresh()}
>
Consultar país guardado
</button>
</div>
{editor.remote && (
<section
aria-label="Comparação do país da organização"
className="space-y-3 rounded border p-3"
>
<p>
Versão guardada: {editor.remote.version}; versão da
preparação: {editor.base.version}.
</p>
<table className="w-full text-left text-sm">
<thead>
<tr>
<th>Campo</th>
<th>Preparação nesta página</th>
<th>Registo guardado</th>
</tr>
</thead>
<tbody>
{fields
.filter(
(key) =>
editor.draft[key] !==
editor.remote?.payload[key],
)
.map((key) => (
<tr key={key}>
<th>
{key === 'country'
? 'País de constituição'
: 'Fonte ou referência'}
</th>
<td className="break-words">
{editor.draft[key] ||
'Não informado'}
</td>
<td className="break-words">
{editor.remote?.payload[key] ||
'Não informado'}
</td>
</tr>
))}
</tbody>
</table>
{editor.mayEdit && !editor.uncertain && (
<div className="flex flex-wrap gap-3">
<button
type="button"
className={button}
onClick={() => editor.adopt(true)}
>
Usar versão actual e manter a preparação
</button>
<button
type="button"
className={button}
onClick={() => {
if (
window.confirm(
'Substituir a preparação desta organização pelos valores guardados?',
)
)
editor.adopt(false);
}}
>
Carregar os valores guardados
</button>
</div>
)}
</section>
)}
</form>
</section>
);
}