import { useEffect, useRef, useState } from 'react'; import { router } from '@inertiajs/react'; import { control, button } from '@/pages/management/shared'; import { valueText } from '@/lib/value-text'; type Classification = { target_type: string; purpose: string; requested_state: string; disclosure: string; criteria?: string; justification?: string; source_reference?: string; citation?: string; authority_id?: string | null; document_id?: string | null; external_status?: string; external_act_reference?: string; production_stage?: string; valid_from?: string | null; valid_until?: string | null; }; export type ClassificationRelation = { related_id: string; relation_type: string; classification?: Classification; [key: string]: unknown; }; export type ClassificationOptions = { dimensions: Record; types: Record; purposes: Record; targets: Record; externalStates: string[]; }; const typeLabels: Record = { park: 'Parque industrial — organização produtiva', corridor: 'Corredor', location: 'Localização', cluster: 'Cluster', project: 'Projeto âncora', chain: 'Cadeia de valor', zone: 'Zona ou parque', sector: 'Setor', activity: 'Subsector ou atividade', }; export const classificationStates: Record = { draft: 'Rascunho', preliminary: 'Preliminar', in_validation: 'Em validação', confirmed: 'Confirmado', rejected: 'Rejeitado', archived: 'Arquivado', revoked: 'Revogado', }; const externalLabels: Record = { not_assessed: 'Não determinado', pending: 'Pendente', documented_granted: 'Ato de concessão documentado', documented_denied: 'Ato de recusa documentado', expired: 'Caducado', }; const help = 'Associação, publicação e ato externo têm estados separados. Localização ou proximidade não concedem licença, benefício, terreno ou capacidade. Dados ausentes permanecem por determinar. Os elos identificados como Modelo editorial não confirmam operadores, capacidade ou relações comerciais. O recorte CAE conserva cinco níveis; 600/579 permanece documentalmente aberto.'; export function ClassificationEditor({ rows, onChange, options, documents, authorities, errors = {}, }: { rows: ClassificationRelation[]; onChange: (rows: ClassificationRelation[]) => void; options: ClassificationOptions; documents: { id: string; payload: { title?: string }; file?: { file_name: string }; }[]; authorities: { id: string; label_pt_mz: string }[]; errors?: Record; }) { const container = useRef(null); useEffect(() => { const key = Object.keys(errors).find((k) => k.startsWith('canonical.relations.'), ); const index = key?.match(/^canonical\.relations\.(\d+)/)?.[1]; if (index) container.current ?.querySelector( `[data-association-index="${index}"]`, ) ?.focus(); }, [errors]); const patch = ( index: number, fields: Partial, related?: string, ) => onChange( rows.map((row, i) => i === index ? { ...row, related_id: related ?? row.related_id, classification: { ...row.classification!, ...fields }, } : row, ), ); return (

Quatro dimensões da oportunidade

{help}

{Object.entries(options.dimensions).map(([dimension, label]) => (
{label} {rows.map((row, index) => row.classification && options.types[row.classification.target_type] === dimension ? (
Associação {index + 1}
{( [ 'criteria', 'justification', 'source_reference', 'citation', 'external_act_reference', 'production_stage', ] as const ).map((key) => (