import { useEffect, useMemo, useState } from 'react'; import type { FormEvent } from 'react'; import { Link, useNavigate, useSearchParams } from 'react-router'; import { Alert, LoadingBlock, errorMessage } from '../components/Feedback'; import { Icon } from '../components/Icon'; import { getAsset } from '../lib/api'; import { createInventoryStructure, getInventoryFamilyFindings, getInventoryStructureOptions, listInventoryStructureParents, } from '../lib/inventoryStructureApi'; import type { InventoryFamily, InventoryFamilyFindings, InventoryStructureKind, InventoryStructureOptions, InventoryStructureParent, } from '../lib/inventoryStructureApi'; const KINDS: Array<{ kind: InventoryStructureKind; label: string; help: string; step: number }> = [ { kind: 'AREA', label: 'Área', help: 'Nivel territorial raíz.', step: 1 }, { kind: 'YACIMIENTO', label: 'Yacimiento', help: 'Debe pertenecer a un Área.', step: 2 }, { kind: 'INSTALACION', label: 'Instalación', help: 'Debe pertenecer a un Yacimiento.', step: 3 }, { kind: 'SUBINSTALACION', label: 'Subinstalación', help: 'Debe pertenecer a una Instalación.', step: 4 }, ]; const childKindByParentType: Record = { area: 'YACIMIENTO', yacimiento: 'INSTALACION', instalacion: 'SUBINSTALACION', }; function kindLabel(kind: InventoryStructureKind): string { return KINDS.find((item) => item.kind === kind)?.label ?? kind; } export function InventoryCreatePage() { const navigate = useNavigate(); const [searchParams] = useSearchParams(); const contextParentId = searchParams.get('parentId'); const [options, setOptions] = useState(null); const [kind, setKind] = useState('AREA'); const [parents, setParents] = useState([]); const [parentSearch, setParentSearch] = useState(''); const [parentId, setParentId] = useState(''); const [familyId, setFamilyId] = useState(''); const [familyFindings, setFamilyFindings] = useState(null); const [code, setCode] = useState(''); const [name, setName] = useState(''); const [commonName, setCommonName] = useState(''); const [description, setDescription] = useState(''); const [loading, setLoading] = useState(true); const [saving, setSaving] = useState(false); const [error, setError] = useState(''); useEffect(() => { getInventoryStructureOptions() .then(async (loaded) => { setOptions(loaded); if (contextParentId) { const parent = await getAsset(contextParentId); const inferred = childKindByParentType[parent.type.code.toLowerCase()]; if (inferred) { setKind(inferred); setParentId(parent.id); } } }) .catch((requestError) => setError(errorMessage(requestError))) .finally(() => setLoading(false)); }, [contextParentId]); useEffect(() => { if (kind === 'AREA') { setParents([]); setParentId(''); return; } const timer = window.setTimeout(() => { listInventoryStructureParents(kind, parentSearch) .then((loaded) => { setParents(loaded); if (contextParentId && loaded.some((item) => item.id === contextParentId)) { setParentId(contextParentId); } }) .catch((requestError) => setError(errorMessage(requestError))); }, 180); return () => window.clearTimeout(timer); }, [kind, parentSearch, contextParentId]); const selectedParent = parents.find((item) => item.id === parentId) ?? null; const families = useMemo(() => { if (!options) return [] as InventoryFamily[]; if (kind === 'INSTALACION') return options.installationFamilies; if (kind === 'SUBINSTALACION') { const parentFamilyId = selectedParent?.inventoryFamily?.id; return parentFamilyId ? options.subinstallationFamilies.filter((item) => item.parentFamilyId === parentFamilyId) : []; } return []; }, [options, kind, selectedParent]); const selectedFamily = families.find((item) => item.id === familyId) ?? null; useEffect(() => { if (!familyId) { setFamilyFindings(null); return; } getInventoryFamilyFindings(familyId) .then(setFamilyFindings) .catch((requestError) => setError(errorMessage(requestError))); }, [familyId]); useEffect(() => { if (kind !== 'INSTALACION' && kind !== 'SUBINSTALACION') setFamilyId(''); if (kind === 'SUBINSTALACION' && familyId && !families.some((item) => item.id === familyId)) setFamilyId(''); }, [kind, familyId, families]); const chooseKind = (next: InventoryStructureKind) => { setKind(next); setParentId(''); setParentSearch(''); setFamilyId(''); setFamilyFindings(null); setError(''); }; const save = async (event: FormEvent) => { event.preventDefault(); const requiresParent = kind !== 'AREA'; const requiresFamily = kind === 'INSTALACION' || kind === 'SUBINSTALACION'; if (requiresParent && !parentId) { setError(`Seleccioná el ${kind === 'YACIMIENTO' ? 'Área' : kind === 'INSTALACION' ? 'Yacimiento' : 'Instalación'} padre.`); return; } if (requiresFamily && !familyId) { setError(`Seleccioná la familia de ${kindLabel(kind).toLowerCase()}.`); return; } setSaving(true); setError(''); try { const created = await createInventoryStructure({ kind, code: code.trim() || null, name: name.trim(), commonName: commonName.trim() || null, parentId: parentId || null, familyId: familyId || null, description: description.trim() || null, }); navigate(`/inventarios/${created.id}`, { replace: true }); } catch (requestError) { setError(errorMessage(requestError)); } finally { setSaving(false); } }; if (loading) return ; const parentLabel = kind === 'YACIMIENTO' ? 'Área' : kind === 'INSTALACION' ? 'Yacimiento' : 'Instalación'; const currentStep = KINDS.find((item) => item.kind === kind)?.step ?? 1; return
INVENTARIO

Agregar a la estructura

La estructura oficial es Área → Yacimiento → Instalación → Subinstalación. Elegí el nivel y el sistema te guía con los vínculos válidos.

{error && {error}}

1. ¿Qué querés crear?

Sólo se pueden crear los cuatro niveles estructurales definidos para DH.

{KINDS.map((item) => )}

Ruta: {KINDS.slice(0, currentStep).map((item) => item.label).join(' → ')}

{kind !== 'AREA' &&

2. Ubicación en la estructura

Primero elegí el {parentLabel} al que pertenece este registro.

} {(kind === 'INSTALACION' || kind === 'SUBINSTALACION') &&

3. Familia técnica

La familia no crea otro nivel. Sirve para aplicar exactamente los Hallazgos del Excel que corresponden.

{kind === 'SUBINSTALACION' && !selectedParent?.inventoryFamily ? La Instalación seleccionada todavía no tiene una familia técnica F3.1. Revisala antes de crear una Subinstalación. : } {selectedFamily &&
Hallazgos asociados automáticamente {familyFindings ? `${familyFindings.count} controles del Excel para ${selectedFamily.name}` : 'Cargando catálogo asociado…'} {familyFindings && familyFindings.items.length > 0 &&
    {familyFindings.items.slice(0, 7).map((item) =>
  • {item.title}
  • )} {familyFindings.items.length > 7 &&
  • + {familyFindings.items.length - 7} hallazgos más
  • }
}
} {selectedFamily && selectedFamily.informationLabels.length > 0 &&

Información técnica esperada: {selectedFamily.informationLabels.join(' · ')}

}
}

{kind === 'AREA' ? '2' : kind === 'YACIMIENTO' ? '3' : '4'}. Identificación

Usá el nombre real de campo. El código DH puede generarse automáticamente.