import { useId, useState } from 'react'; export type QuantitativeMapContext = { state: 'available' | 'unavailable' | 'not_included' | 'error'; records: { id: string; zone_id: string; zone_name: string; zone_version: number; url: string; theme: 'workforce' | 'economic_potential'; indicator: string; label?: string | null; description?: string | null; value: string | null; unit?: string | null; period_start?: string | null; period_end?: string | null; scope?: string | null; population?: string | null; methodology?: string | null; source_reference?: string | null; source_date?: string | null; knowledge: string; missing_metadata: string[]; }[]; zones_consulted?: number; zone_limit?: number; record_limit?: number; truncated: boolean; }; const labels: Record = { employment: 'Emprego', investment: 'Investimento', production: 'Produção', exports: 'Exportações', local_procurement: 'Compras locais', }; const metadataLabels: Record = { unit: 'unidade', period_start: 'início do período', period_end: 'fim do período', scope: 'âmbito', population: 'população/base', methodology: 'metodologia', source_reference: 'fonte', source_date: 'data da fonte', }; const text = (value?: string | null) => value?.trim() || 'Não indicado'; const completeDate = (value?: string | null) => Boolean( value && /^\d{4}-\d{2}-\d{2}$/.test(value) && !Number.isNaN(Date.parse(value)) && new Date(value).toISOString().slice(0, 10) === value, ); export function filterMapIndicators( records: QuantitativeMapContext['records'], indicator: string, start: string, end: string, ) { if (start && end && start > end) return []; return records.filter((row) => { if (indicator !== 'all' && row.indicator !== indicator) return false; if (!start && !end) return true; // Incomplete or inverted source periods cannot establish overlap. if ( !completeDate(row.period_start) || !completeDate(row.period_end) || !row.period_start || !row.period_end || row.period_start > row.period_end ) return false; return ( (!start || row.period_end >= start) && (!end || row.period_start <= end) ); }); } export default function InvestmentMapIndicators({ context, theme, }: { context: QuantitativeMapContext | null; theme: string; }) { const filterId = useId(); const [indicator, setIndicator] = useState('all'); const [start, setStart] = useState(''); const [end, setEnd] = useState(''); if (!['all', 'workforce', 'economic_potential'].includes(theme)) return null; const themeRows = context?.records.filter( (row) => theme === 'all' || row.theme === theme, ) ?? []; const rows = filterMapIndicators(themeRows, indicator, start, end); const invalidPeriod = Boolean(start && end && start > end); const filtered = indicator !== 'all' || Boolean(start || end); return (

Indicadores quantitativos do contexto territorial

Observações públicas das zonas e parques devolvidos como contexto territorial, independentes das evidências das oportunidades. Emprego não mede trabalhadores disponíveis; investimento, produção e exportações não constituem um índice de potencial ou garantia de retorno. A natureza prevista ou efectiva de cada valor depende da descrição da fonte, não é determinada automaticamente.

{!context ? (

A carregar indicadores quantitativos…

) : context.state === 'error' ? (

Não foi possível consultar os indicadores. Pode repetir a consulta do mapa.

) : context.state === 'not_included' ? (

O conjunto de zonas não está incluído com estes filtros específicos de oportunidades. Não foi feita uma medição quantitativa neste âmbito.

) : context.state === 'unavailable' ? (

Observações quantitativas indisponíveis nesta versão do cadastro; os restantes dados do mapa mantêm-se.

) : ( <>
Filtrar observações do contexto territorial

O período selecciona observações com sobreposição de datas, incluindo os limites. Datas incompletas ou invertidas na fonte ficam fora do filtro temporal. A data da fonte não substitui o período de referência. Estes filtros actuam apenas nas observações recebidas; não alteram oportunidades ou limites de cobertura.

{invalidPeriod && (

O início do período deve ser anterior ou igual ao fim.

)}

{rows.length}{' '} {rows.length === 1 ? 'observação' : 'observações'} nesta camada, de {themeRows.length} recebidas, em{' '} {context.zones_consulted}{' '} {context.zones_consulted === 1 ? 'ficha territorial consultada.' : 'fichas territoriais consultadas.'}{' '} A contagem não mede cobertura nacional.

{context.truncated && (

Cobertura incompleta: consulta limitada a{' '} {context.zone_limit} fichas e {context.record_limit}{' '} observações. Refine a localização.

)} {rows.length === 0 ? (

{filtered ? 'Nenhuma observação corresponde aos filtros dos indicadores.' : 'Sem observações públicas destes indicadores na resposta.'}{' '} Valor desconhecido não equivale a zero.

) : (
Consultar valores, unidades e fontes ( {rows.length})
{rows.map((row) => ( ))}
Cada linha conserva o âmbito da fonte. Sem somas, conversões de unidade ou moeda, médias ou comparação automática entre períodos e populações.
Ficha e indicador Valor e unidade Período e base Fonte e metodologia
{row.zone_name}

{labels[ row.indicator ] ?? row.indicator} : {text(row.label)}

{text(row.description)}

Versão pública{' '} {row.zone_version}

{row.value ?? 'Por determinar'}{' '} · {text(row.unit)}

{row.knowledge === 'documented' ? 'Documentado na fonte' : row.knowledge === 'disputed' ? 'Em divergência' : 'Desconhecido'}

{text(row.period_start)}{' '} a {text(row.period_end)}

Âmbito:{' '} {text(row.scope)}

População/base:{' '} {text(row.population)}

Fonte:{' '} {text( row.source_reference, )}{' '} · Data:{' '} {text(row.source_date)}

Metodologia:{' '} {text(row.methodology)}

{row.missing_metadata .length > 0 && (

Informação em falta:{' '} {row.missing_metadata .map( (key) => metadataLabels[ key ] ?? key, ) .join(', ')} . Não agregar ou comparar como se estivesse completa.

)}
)} )}
); }