Files
Investidor-V2/resources/js/components/territory-geometry-preview.tsx
T
nala 01405cbf8a
tests / ci (push) Canceled after 0s
oportunidades 5
2026-10-10 14:15:28 +02:00

106 lines
4.0 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,
}: {
territoryId?: string;
management?: boolean;
endpoint?: 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="Cobertura cartográfica da seleção"
>
<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>
<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} · Fonte:{' '}
{area.source_reference ?? 'Não indicada'} ·
Edição: {area.source_date ?? 'Não indicada'}
</li>
))}
</ul>
</>
)}
</section>
);
}