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, getInventoryStructureOptions, listCompaniesForInventoryArea, listInventoryStructureParents, } from '../lib/inventoryStructureApi'; import type { InventoryAreaCompanyOption, InventoryFamily, 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 [areaCompanies, setAreaCompanies] = useState([]); const [operatorCompanyId, setOperatorCompanyId] = useState(''); const [name, setName] = useState(''); const [code, setCode] = 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 requiresCompany = 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]); useEffect(() => { if (kind !== 'YACIMIENTO' || !parentId) { setAreaCompanies([]); setOperatorCompanyId(''); return; } setOperatorCompanyId(''); listCompaniesForInventoryArea(parentId) .then(setAreaCompanies) .catch((requestError) => setError(errorMessage(requestError))); }, [kind, parentId]); 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]); useEffect(() => { if (!requiresFamily) setFamilyId(''); if (kind === 'SUBINSTALACION' && familyId && !families.some((item) => item.id === familyId)) setFamilyId(''); }, [kind, requiresFamily, families, familyId]); const changeKind = (next: InventoryStructureKind) => { setKind(next); setParentId(''); setParentSearch(''); setFamilyId(''); setAreaCompanies([]); setOperatorCompanyId(''); setError(''); }; const save = async (event: FormEvent) => { event.preventDefault(); if (requiresParent && !parentId) { setError(`Seleccioná ${parentLabel}.`); return; } if (requiresCompany && !operatorCompanyId) { setError('Seleccioná la Empresa que opera este 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, code: code.trim() || null, }); navigate(`/inventarios/${created.id}`, { replace: true }); } catch (requestError) { setError(errorMessage(requestError)); } finally { setSaving(false); } }; if (loading) return ; const disableSave = saving || !name.trim() || (requiresParent && !parentId) || (requiresCompany && !operatorCompanyId) || (requiresFamily && !familyId); return
ALTA RÁPIDA

Agregar al Inventario

Elegí qué querés crear, dónde está y completá sólo los datos necesarios.

{error && {error}}

¿Qué querés crear?

Departamento → Área → Yacimiento → Instalación → Subinstalación.

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

¿Dónde está?

Seleccioná el {parentLabel.toLowerCase()} al que pertenece.

} {requiresCompany &&

Empresa operadora

Un Área puede tener varias Empresas. Cada Yacimiento queda asociado a una sola de ellas.

{!parentId ? Primero seleccioná el Área. : areaCompanies.length === 0 ? El Área elegida todavía no tiene Empresas operadoras vinculadas. : }
} {requiresFamily &&

{kind === 'INSTALACION' ? 'Tipo de instalación' : 'Tipo / función'}

{kind === 'SUBINSTALACION' ? 'Sólo aparecen tipos permitidos dentro de la Instalación seleccionada.' : 'Elegí la clasificación simple que corresponda.'}

{kind === 'SUBINSTALACION' && !selectedParent?.inventoryFamily ? La Instalación elegida todavía no tiene un tipo configurado. : } {kind === 'SUBINSTALACION' && selectedParent?.inventoryFamily && families.length === 0 && No hay tipos de Subinstalación configurados para esta Instalación.}
}

Datos básicos

El nombre alcanza para identificar el registro. El código puede generarse automáticamente.

Cancelar
; }