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 }> = [ { kind: 'DEPARTAMENTO', label: 'Departamento' }, { kind: 'AREA', label: 'Área' }, { kind: 'YACIMIENTO', label: 'Yacimiento' }, { kind: 'INSTALACION', label: 'Instalación' }, { kind: 'SUBINSTALACION', label: 'Subinstalación' }, { kind: 'EMPRESA', label: 'Empresa' }, ]; const childKindByParentType: Record = { departamento: 'AREA', area: 'YACIMIENTO', yacimiento: 'INSTALACION', instalacion: 'SUBINSTALACION', }; const parentLabelByKind: Partial> = { AREA:'Departamento', YACIMIENTO:'Área', INSTALACION:'Yacimiento', SUBINSTALACION:'Instalación', }; function kindLabel(kind: InventoryStructureKind) { 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('DEPARTAMENTO'); const [parents, setParents] = useState([]); const [parentSearch, setParentSearch] = useState(''); const [parentId, setParentId] = useState(''); const [familyId, setFamilyId] = useState(''); const [operatorCompanyId, setOperatorCompanyId] = useState(''); const [concessionTypeId, setConcessionTypeId] = useState(''); const [familyFindings, setFamilyFindings] = useState(null); const [name, setName] = useState(''); const [code, setCode] = 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]); const requiresParent = Boolean(parentLabelByKind[kind]); const requiresFamily = kind === 'INSTALACION' || kind === 'SUBINSTALACION'; const requiresYacimientoContext = kind === 'YACIMIENTO'; const parentLabel = parentLabelByKind[kind] ?? ''; useEffect(() => { if (!requiresParent) { 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))); },150); return () => window.clearTimeout(timer); }, [kind,parentSearch,contextParentId,requiresParent]); 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.parentFamilyIds.includes(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 (!requiresFamily) setFamilyId(''); if (kind==='SUBINSTALACION' && familyId && !families.some((item)=>item.id===familyId)) setFamilyId(''); },[kind,requiresFamily,families,familyId]); useEffect(() => { if (!requiresYacimientoContext) { setOperatorCompanyId(''); setConcessionTypeId(''); } },[requiresYacimientoContext]); const changeKind=(next:InventoryStructureKind) => { setKind(next); setParentId(''); setParentSearch(''); setFamilyId(''); setFamilyFindings(null); setOperatorCompanyId(''); setConcessionTypeId(''); setError(''); }; const save=async(event:FormEvent) => { event.preventDefault(); if (requiresParent && !parentId) { setError(`Seleccioná ${parentLabel}.`); return; } if (requiresYacimientoContext && !operatorCompanyId) { setError('Seleccioná la Empresa relacionada del Yacimiento.'); return; } if (requiresYacimientoContext && !concessionTypeId) { setError('Seleccioná el Tipo de concesión del Yacimiento.'); return; } if (requiresFamily && !familyId) { setError(`Seleccioná el tipo de ${kindLabel(kind).toLowerCase()}.`); return; } setSaving(true); setError(''); try { const created=await createInventoryStructure({ kind,name:name.trim(),parentId:parentId || null,familyId:familyId || null, operatorCompanyId:operatorCompanyId || null,concessionTypeId:concessionTypeId || null, code:code.trim() || null,commonName:commonName.trim() || null,description:description.trim() || null, }); navigate(`/inventarios/${created.id}`,{replace:true}); } catch(requestError) { setError(errorMessage(requestError)); } finally { setSaving(false); } }; if (loading) return ; return
CARGA MANUAL

Nuevo registro

Modelo fijo: Departamento → Área → Yacimiento → Instalación → Subinstalación. La Empresa y el Tipo de concesión pertenecen al Yacimiento.

{error && {error}}

1. ¿Qué querés crear?

Área sólo depende de Departamento. Yacimiento define Área, Empresa relacionada y Tipo de concesión.

{requiresParent &&

2. Ubicación

Elegí el {parentLabel.toLowerCase()} concreto.

} {requiresYacimientoContext &&

3. Contexto del Yacimiento

Estas relaciones pertenecen directamente al Yacimiento y no al Área.

} {requiresFamily &&

3. Clasificación técnica

Define los datos técnicos y Hallazgos aplicables. En Subinstalaciones sólo aparecen clasificaciones compatibles con la Instalación elegida.

{kind==='SUBINSTALACION' && !selectedParent?.inventoryFamily ? La Instalación elegida todavía no tiene clasificación técnica. : }{kind==='SUBINSTALACION' && selectedParent?.inventoryFamily && families.length===0 && No hay tipos de Subinstalación compatibles con {selectedParent.inventoryFamily.name}.}{selectedFamily &&
{selectedFamily.name}{familyFindings ? `${familyFindings.count} Hallazgo${familyFindings.count===1?'':'s'} asociado${familyFindings.count===1?'':'s'}` : 'Cargando Hallazgos asociados…'}{familyFindings && familyFindings.items.length>0 &&
    {familyFindings.items.slice(0,6).map((item)=>
  • {item.title}
  • )}{familyFindings.items.length>6 &&
  • + {familyFindings.items.length-6} más
  • }
}
}
}

{requiresYacimientoContext ? '4' : requiresFamily ? '4' : requiresParent ? '3' : '2'}. Nombre

El nombre es el dato propio principal de este nivel. Los datos técnicos se completan después, cuando corresponda.

Datos opcionales