diff --git a/src/app/page.tsx b/src/app/page.tsx index 38713cd..11d34a0 100644 --- a/src/app/page.tsx +++ b/src/app/page.tsx @@ -9,6 +9,7 @@ import { Funcionario, PayloadBusqueda } from '@/types/Funcionarios'; export default function Home() { const [resultados, setResultados] = useState([]); + const [currentAreaLabel, setCurrentAreaLabel] = useState(''); // Zoom / Pan state const imgRef = useRef(null); const [scale, setScale] = useState(1); @@ -93,10 +94,13 @@ export default function Home() { return (
- + { setCurrentAreaLabel(label); buscarPorArea(id); }} onClear={() => { setCurrentAreaLabel(''); setResultados([]); }} />

Directorio de Funcionarios

+ {currentAreaLabel &&

{currentAreaLabel}

} + +
{resultados.length === 0 ? ( @@ -133,7 +137,7 @@ export default function Home() { touchAction: 'none', }} > - buscarPorArea(id)} isPanningRef={isPanning} /> + { buscarPorArea(id); }} isPanningRef={isPanning} onAreaLabel={(id, label) => setCurrentAreaLabel(label)} />
diff --git a/src/components/BuscarFuncionario.tsx b/src/components/BuscarFuncionario.tsx index 6c00b03..ab8d6e1 100644 --- a/src/components/BuscarFuncionario.tsx +++ b/src/components/BuscarFuncionario.tsx @@ -5,12 +5,15 @@ import axios from 'axios'; import { Funcionario } from '../types/Funcionarios'; import { PayloadBusqueda } from '../types/Funcionarios'; import { errorBuscar, funcionarioNoEncontrado } from '@/utils/alerts'; +import AREAS from '@/data/areas'; interface BuscarFuncionarioProps { onResultados: (data: Funcionario[]) => void; + onAreaSelected?: (id: number, label: string) => void; + onClear?: () => void; } -export default function BuscarFuncionario({ onResultados }: BuscarFuncionarioProps) { +export default function BuscarFuncionario({ onResultados, onAreaSelected, onClear }: BuscarFuncionarioProps) { const [nombre, setNombre] = useState(''); const [apellidos, setApellidos] = useState(''); const [area, setArea] = useState('0'); @@ -25,6 +28,11 @@ export default function BuscarFuncionario({ onResultados }: BuscarFuncionarioPro return; } + // Si es búsqueda manual, limpiar etiqueta de área en el padre + if (tipo === 'manual') { + onClear?.(); + } + // Tipo de búsqueda if (area !== '0') { payload.tipoBusqueda = 'area'; @@ -50,7 +58,7 @@ export default function BuscarFuncionario({ onResultados }: BuscarFuncionarioPro //Limpiar campos después de buscar setNombre(''); setApellidos(''); - setArea('0'); + //setArea('0'); } catch (error) { console.error('Error al buscar funcionario:', error); @@ -115,82 +123,32 @@ export default function BuscarFuncionario({ onResultados }: BuscarFuncionarioPro name="bus_depid" className="form-select" value={area} - onChange={(e) => setArea(e.target.value)} + onChange={(e) => { + const val = e.target.value; + const label = e.target.options[e.target.selectedIndex]?.text || ''; + setArea(val); + if (val !== '0' && label) { + onAreaSelected?.(parseInt(val, 10), label); + } + }} > - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {AREAS.map((a) => ( + + ))} {/* Botón de buscar (sin limpiar) */}
- +
+ + +
diff --git a/src/components/OrganigramaInteractivo.tsx b/src/components/OrganigramaInteractivo.tsx index f693965..c1c7c5a 100644 --- a/src/components/OrganigramaInteractivo.tsx +++ b/src/components/OrganigramaInteractivo.tsx @@ -1,47 +1,19 @@ import React from 'react'; +import AREAS from '@/data/areas'; interface Props { onAreaSelect: (areaId: number) => void; className?: string; style?: React.CSSProperties; isPanningRef?: React.MutableRefObject; + onAreaLabel?: (id: number, label: string) => void; } // Map display substrings (lowercase) to the area id used in BuscarFuncionario -const areaMap: Record = { - 'coordinación de actividades deportivas y recreativas': 128, - 'coordinación de comunicación social': 122, - 'coordinación de cuerpos colegiados': 9, - 'coordinación de derecho del sistema de universidad abierta y educación a distancia': 126, - 'coordinación de especializaciones': 206, - 'coordinación de estudios de posgrado': 120, - 'coordinación de la unidad de investigación multidisciplinaria aplicada': 182, - 'coordinación de licel sistema de universidad abierta y educación a distancia': 174, - 'coordinación de maestrías y doctorados': 221, - 'coordinación de relaciones internacionales del sistema de universidad abierta y educación a distancia': 152, - 'coordinación de servicios académicos': 121, - 'coordinación del centro de difusión cultural': 125, - 'coordinación del centro de educación continua': 124, - 'coordinación del centro de enseñanza de idiomas': 129, - 'coordinación del centro de estudios municipales y metropolitanos': 214, - 'coordinación del centro tecnológico para la educación a distancia': 176, - 'dirección': 72, - 'división de ciencias jurídicas': 80, - 'división de ciencias socioeconómicas': 79, - 'división de diseño y edificación': 78, - 'división de humanidades': 77, - 'división de matemáticas e ingeniería': 76, - 'secretaría de asuntos académicos estudiantiles': 181, - 'secretaría de extensión universitaria y vinculación institucional': 177, - 'secretaría de posgrado e investigación': 119, - 'secretaría general': 8, - 'unidad de administración escolar': 6, - 'unidad de servicios editoriales': 2, - 'unidad de talleres, laboratorios y audiovisuales': 1, - 'unidad del centro de desarrollo tecnológico': 130, - 'unidad del centro de información y documentación': 123, - // add more mappings as needed -}; +const areaMap: Record = AREAS.reduce((acc, cur) => { + acc[cur.label.toLowerCase()] = cur.id; + return acc; +}, {} as Record); const svgContent = ` ${ @@ -52,7 +24,7 @@ const svgContent = ` // Instead of inlining the full SVG string here (long), we'll import it via require at runtime by fetching the file relative to the app. // But to keep this component self-contained, we'll render an fallback and then query inside it. -export default function OrganigramaInteractivo({ onAreaSelect, className, style, isPanningRef }: Props) { +export default function OrganigramaInteractivo({ onAreaSelect, className, style, isPanningRef, onAreaLabel }: Props) { const containerRef = React.useRef(null); const normalize = (s: string) => @@ -63,9 +35,9 @@ export default function OrganigramaInteractivo({ onAreaSelect, className, style, .replace(/\s+/g, ' ') .trim(); - const normalizedAreaEntries = React.useMemo(() => { - return Object.keys(areaMap).map((k) => ({ key: normalize(k), id: areaMap[k] })); - }, []); + const normalizedAreaEntries = React.useMemo(() => { + return Object.keys(areaMap).map((k) => ({ key: normalize(k), id: areaMap[k], label: k })); + }, []); React.useEffect(() => { const container = containerRef.current; @@ -123,24 +95,26 @@ export default function OrganigramaInteractivo({ onAreaSelect, className, style, const normalized = normalize(textContent); // Try to match any normalized key in areaMap - for (const entry of normalizedAreaEntries) { - if (normalized.includes(entry.key) || entry.key.includes(normalized)) { - onAreaSelect(entry.id); - return; - } - } + for (const entry of normalizedAreaEntries) { + if (normalized.includes(entry.key) || entry.key.includes(normalized)) { + onAreaSelect(entry.id); + onAreaLabel?.(entry.id, entry.label); + return; + } + } // If target element directly has a title or id if (target) { const el = target as HTMLElement; const title = (el.getAttribute('title') || el.getAttribute('id') || '').toString(); const n = normalize(title); - for (const entry of normalizedAreaEntries) { - if (n.includes(entry.key) || entry.key.includes(n)) { - onAreaSelect(entry.id); - return; - } - } + for (const entry of normalizedAreaEntries) { + if (n.includes(entry.key) || entry.key.includes(n)) { + onAreaSelect(entry.id); + onAreaLabel?.(entry.id, entry.label); + return; + } + } } }; diff --git a/src/data/areas.ts b/src/data/areas.ts new file mode 100644 index 0000000..9ee72c9 --- /dev/null +++ b/src/data/areas.ts @@ -0,0 +1,72 @@ +export const AREAS: Array<{ id: number; label: string }> = [ + { id: 0, label: '-- Selecciona un área --' }, + { id: 128, label: 'Coordinación de Actividades Deportivas y Recreativas' }, + { id: 122, label: 'Coordinación de Comunicación Social' }, + { id: 9, label: 'Coordinación de Cuerpos Colegiados' }, + { id: 126, label: 'Coordinación de Derecho del Sistema de Universidad Abierta y Educación a Distancia' }, + { id: 206, label: 'Coordinación de Especializaciones' }, + { id: 120, label: 'Coordinación de Estudios de Posgrado' }, + { id: 182, label: 'Coordinación de la Unidad de Investigación Multidisciplinaria Aplicada' }, + { id: 174, label: 'Coordinación de LICEL Sistema de Universidad Abierta y Educación a Distancia' }, + { id: 221, label: 'Coordinación de Maestrías y Doctorados' }, + { id: 152, label: 'Coordinación de Relaciones Internacionales del Sistema de Universidad Abierta y Educación a Distancia' }, + { id: 121, label: 'Coordinación de Servicios Académicos' }, + { id: 125, label: 'Coordinación del Centro de Difusión Cultural' }, + { id: 124, label: 'Coordinación del Centro de Educación Continua' }, + { id: 129, label: 'Coordinación del Centro de Enseñanza de Idiomas' }, + { id: 214, label: 'Coordinación del Centro de Estudios Municipales y Metropolitanos' }, + { id: 176, label: 'Coordinación del Centro Tecnológico para la Educación a Distancia' }, + { id: 58, label: 'Coordinación del Programa de Actuaría' }, + { id: 57, label: 'Coordinación del Programa de Arquitectura' }, + { id: 46, label: 'Coordinación del Programa de Comunicación' }, + { id: 56, label: 'Coordinación del Programa de Derecho' }, + { id: 55, label: 'Coordinación del Programa de Diseño Gráfico' }, + { id: 54, label: 'Coordinación del Programa de Economía' }, + { id: 49, label: 'Coordinación del Programa de Enseñanza de Inglés' }, + { id: 52, label: 'Coordinación del Programa de Humanidades' }, + { id: 51, label: 'Coordinación del Programa de Ingeniería Civil' }, + { id: 48, label: 'Coordinación del Programa de Matemáticas Aplicadas y Computación' }, + { id: 47, label: 'Coordinación del Programa de Pedagogía' }, + { id: 44, label: 'Coordinación del Programa de Sociología' }, + { id: 43, label: 'Coordinación del Programa Político' }, + { id: 194, label: 'Departamento de Intendencia' }, + { id: 193, label: 'Departamento de Investigación en Comunicación y Estudios Culturales' }, + { id: 222, label: 'Departamento de Orientación Académica del Sistema de Universidad Abierta y Educación a Distancia' }, + { id: 204, label: 'Departamento de Proyectos Administrativos' }, + { id: 86, label: 'Departamento de Talleres y Laboratorios' }, + { id: 72, label: 'Dirección' }, + { id: 80, label: 'División de Ciencias Jurídicas' }, + { id: 79, label: 'División de Ciencias Socioeconómicas' }, + { id: 78, label: 'División de Diseño y Edificación' }, + { id: 77, label: 'División de Humanidades' }, + { id: 76, label: 'División de Matemáticas e Ingeniería' }, + { id: 74, label: 'División del Sistema de Universidad Abierta y Educación a Distancia' }, + { id: 70, label: 'Especialización en Costos en la Construcción' }, + { id: 69, label: 'Especialización en Finanzas Públicas' }, + { id: 68, label: 'Especialización en Geotecnia' }, + { id: 71, label: 'Especialización en Sistemas de Calidad' }, + { id: 220, label: 'Especialización en Tecnología Digital para la Enseñanza de Matemáticas' }, + { id: 207, label: 'Grupo de Trabajo de Educación para Adultos (GTEA)' }, + { id: 173, label: 'Maestría en Docencia para la Educación Media Superior' }, + { id: 224, label: 'Posgrado en Ciencias Políticas y Sociales' }, + { id: 62, label: 'Posgrado en Derecho' }, + { id: 164, label: 'Posgrado en Economía' }, + { id: 197, label: 'Posgrado en Pedagogía' }, + { id: 63, label: 'Posgrado en Urbanismo' }, + { id: 226, label: 'Programa Único de Especializaciones en Derecho' }, + { id: 127, label: 'Secretaría Administrativa' }, + { id: 181, label: 'Secretaría de Asuntos Académicos Estudiantiles' }, + { id: 177, label: 'Secretaría de Extensión Universitaria y Vinculación Institucional' }, + { id: 119, label: 'Secretaría de Posgrado e Investigación' }, + { id: 8, label: 'Secretaría General' }, + { id: 6, label: 'Unidad de Administración Escolar' }, + { id: 5, label: 'Unidad de Administración y Recursos' }, + { id: 4, label: 'Unidad de Planeación' }, + { id: 3, label: 'Unidad de Servicios a la Comunidad' }, + { id: 2, label: 'Unidad de Servicios Editoriales' }, + { id: 1, label: 'Unidad de Talleres, Laboratorios y Audiovisuales' }, + { id: 130, label: 'Unidad del Centro de Desarrollo Tecnológico' }, + { id: 123, label: 'Unidad del Centro de Información y Documentación' }, +]; + +export default AREAS;