Files
Investidor-V2/resources/js/components/territory-geometry-preview.tsx
T

113 lines
4.5 KiB
TypeScript

import { useEffect, useState } from 'react';
import InteractiveInvestmentMap, {
type InvestmentMapArea,
} from './interactive-investment-map';
const noPoints: [] = [];
type Context = {
selected_geometry_available: boolean;
context_geometry_count: number;
areas: InvestmentMapArea[];
truncated: boolean;
};
export default function TerritoryGeometryPreview({
territoryId,
management = false,
endpoint: suppliedEndpoint,
label = 'Cobertura cartográfica da seleção',
}: {
territoryId?: string;
management?: boolean;
endpoint?: string;
label?: string;
}) {
const [context, setContext] = useState<Context | null>(null);
const [error, setError] = useState('');
useEffect(() => {
setContext(null);
setError('');
if (!territoryId) return;
const controller = new AbortController();
const endpoint =
suppliedEndpoint ??
(management
? '/management/territory-geometries'
: '/api/v1/investment/territory-geometries');
void fetch(
`${endpoint}?${new URLSearchParams({ territory_id: territoryId })}`,
{
signal: controller.signal,
headers: { Accept: 'application/json' },
},
)
.then(async (response) => {
if (!response.ok)
throw new Error(
'Não foi possível consultar os limites administrativos.',
);
return response.json() as Promise<Context>;
})
.then((data) => {
if (!controller.signal.aborted) setContext(data);
})
.catch((e: unknown) => {
if (!controller.signal.aborted)
setError(
e instanceof Error ? e.message : 'Erro de ligação.',
);
});
return () => controller.abort();
}, [territoryId, management, suppliedEndpoint]);
if (!territoryId) return null;
return (
<section className="space-y-2 md:col-span-full" aria-label={label}>
<p>Território selecionado no cadastro.</p>
{error && <p role="alert">{error}</p>}
{!context && !error && <p role="status">A consultar geometria…</p>}
{context && (
<>
<p role="status">
{context.selected_geometry_available
? 'Limite administrativo disponível para este território.'
: 'Sem limite administrativo acessível para este território neste perfil.'}
</p>
{!context.selected_geometry_available && context.areas.length > 0 && (
<p role="note">
O mapa mostra apenas limites dos níveis superiores como contexto.
Estes limites não representam o território seleccionado.
</p>
)}
<p>
{context.context_geometry_count} limites disponíveis na
hierarquia selecionada. São contexto administrativo, não
perímetro nem disponibilidade de investimento. A edição
e a atualidade jurídica são informações distintas.
</p>
{context.truncated && (
<p role="alert">
Exibidos os primeiros 100 limites; cobertura
incompleta.
</p>
)}
{context.areas.length > 0 && (
<InteractiveInvestmentMap
points={noPoints}
areas={context.areas}
contextOnly
/>
)}
<ul>
{context.areas.map((area, index) => (
<li key={index}>
{area.title} · {area.selected_territory ? 'Território seleccionado' : 'Contexto de nível superior'} · Fonte:{' '}
{area.source_reference ?? 'Não indicada'} ·
Edição: {area.source_date ?? 'Não indicada'}
</li>
))}
</ul>
</>
)}
</section>
);
}