diff --git a/package-lock.json b/package-lock.json index 0cd4780..a378a00 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1387,6 +1387,7 @@ "version": "2.5.1", "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.5.1.tgz", "integrity": "sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==", + "dev": true, "hasInstallScript": true, "license": "MIT", "optional": true, @@ -1426,6 +1427,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1446,6 +1448,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1466,6 +1469,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1486,6 +1490,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1506,6 +1511,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1526,6 +1532,7 @@ "cpu": [ "arm" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1546,6 +1553,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1566,6 +1574,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1586,6 +1595,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1606,6 +1616,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1626,6 +1637,7 @@ "cpu": [ "arm64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1646,6 +1658,7 @@ "cpu": [ "ia32" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -1666,6 +1679,7 @@ "cpu": [ "x64" ], + "dev": true, "license": "MIT", "optional": true, "os": [ @@ -2879,7 +2893,7 @@ "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" @@ -3392,6 +3406,7 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==", + "dev": true, "license": "Apache-2.0", "optional": true, "bin": { @@ -4174,7 +4189,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" @@ -4859,7 +4874,7 @@ "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" @@ -4905,7 +4920,7 @@ "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" @@ -4944,7 +4959,7 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" @@ -5384,7 +5399,7 @@ "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", @@ -5542,6 +5557,7 @@ "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", + "dev": true, "license": "MIT", "optional": true }, @@ -5817,7 +5833,7 @@ "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", - "devOptional": true, + "dev": true, "license": "MIT", "engines": { "node": ">=8.6" @@ -6818,7 +6834,7 @@ "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", - "devOptional": true, + "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" diff --git a/src/app/(Administrador)/reportes_graficas_perifericos/page.tsx b/src/app/(Administrador)/reportes_graficas_perifericos/page.tsx new file mode 100644 index 0000000..dc42953 --- /dev/null +++ b/src/app/(Administrador)/reportes_graficas_perifericos/page.tsx @@ -0,0 +1,19 @@ +"use client"; + + +import "../../styles/layout/reporte.scss"; +import ReportePerifericos from "@/components/reporte_graficas_perifericos/reporte"; + +export default function Page() { + + + return ( +
+
+
+
+
+
+
+ ); +} diff --git a/src/components/reporte_graficas_perifericos/Graficas/Antiguedad.tsx b/src/components/reporte_graficas_perifericos/Graficas/Antiguedad.tsx new file mode 100644 index 0000000..9fc4761 --- /dev/null +++ b/src/components/reporte_graficas_perifericos/Graficas/Antiguedad.tsx @@ -0,0 +1,138 @@ +'use client' + +import axios from "axios"; +import { useEffect, useState } from "react"; +import { + Bar, + BarChart, + CartesianGrid, + Legend, + ResponsiveContainer, + Tooltip, + XAxis, + YAxis +} from "recharts"; +import Cookies from "js-cookie"; + +interface Props { + filtros: any +} + +interface AntiguedadData { + adscripcion: string + antiguedad: string + total: number +} + +const colores = [ + "#818CF8", + "#34D399", + "#FBBF24", + "#F87171", + "#67E8F9", + "#C084FC" +] + +const api_url = process.env.NEXT_PUBLIC_API_URL; + +export default function Antiguedad({ filtros }: Props) { + + const [data, setData] = useState([]) + + useEffect(() => { + const token = Cookies.get("token"); + const headers = { Authorization: `Bearer ${token}` }; + + const getAntiguedad = async () => { + + const response = await axios.post( + `${api_url}/equipos/graficaPerifericos/antiguedad`, + filtros, + { headers } + ) + + setData(response.data) + + } + + getAntiguedad() + + }, [filtros]) + + const tieneAdscripciones = data.some(d => d.adscripcion) + + let dataTransformada = data + let adscripciones: string[] = [] + + if (tieneAdscripciones) { + + adscripciones = [...new Set(data.map(d => d.adscripcion))] + + dataTransformada = Object.values( + data.reduce((acc: any, item: any) => { + + if (!acc[item.antiguedad]) { + acc[item.antiguedad] = { antiguedad: item.antiguedad } + } + + acc[item.antiguedad][item.adscripcion] = Number(item.total) + + return acc + + }, {}) + ) + + } + + return ( +
+ +

Antigüedad por equipo

+ + + + + + + + + + [`${value}`]} + /> + + {tieneAdscripciones ? ( + + adscripciones.map((ads, i) => ( + + )) + + ) : ( + + + + )} + + + +
+ ) +} \ No newline at end of file diff --git a/src/components/reporte_graficas_perifericos/Graficas/Procesador.tsx b/src/components/reporte_graficas_perifericos/Graficas/Procesador.tsx new file mode 100644 index 0000000..8f491a0 --- /dev/null +++ b/src/components/reporte_graficas_perifericos/Graficas/Procesador.tsx @@ -0,0 +1,105 @@ +'use client' + +import axios from "axios"; +import { useEffect, useState } from "react"; +import { Bar, BarChart, CartesianGrid, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; + +interface Props { + filtros: any +} + +interface procesador { + adscripcion: string + procesador: string; + total: number; +} + +const colores = [ + "#818CF8", + "#34D399", + "#FBBF24", + "#F87171", + "#67E8F9", + "#C084FC" +] + +const api_url = process.env.NEXT_PUBLIC_API_URL; + +export default function Procesador({ filtros }: Props) { + const [data, setData] = useState([]) + + useEffect(() => { + const getAntiguedad = async () => { + const response = await axios.post(`${api_url}/equipos/graficaPerifericos/procesador`, filtros) + + setData(response.data) + } + getAntiguedad() + }, [filtros]) + + const tieneAdscripciones = data.some(d => d.adscripcion) + + let dataTransformada = data + let adscripciones: string[] = [] + + if (tieneAdscripciones) { + + adscripciones = [...new Set(data.map(d => d.adscripcion))] + + dataTransformada = Object.values( + data.reduce((acc: any, item: any) => { + + if (!acc[item.procesador]) { + acc[item.procesador] = { procesador: item.procesador } + } + + acc[item.procesador][item.adscripcion] = Number(item.total) + + return acc + + }, {}) + ) + } + + return ( +
+

Procesador por equipo

+ + + + + + [`${value}`]} + /> + + {tieneAdscripciones ? ( + + adscripciones.map((ads, i) => ( + + )) + + ) : ( + + + + )} + + +
+ ) +} \ No newline at end of file diff --git a/src/components/reporte_graficas_perifericos/Graficas/SistemaOperativo.tsx b/src/components/reporte_graficas_perifericos/Graficas/SistemaOperativo.tsx new file mode 100644 index 0000000..f7840e3 --- /dev/null +++ b/src/components/reporte_graficas_perifericos/Graficas/SistemaOperativo.tsx @@ -0,0 +1,104 @@ +'use client' + +import axios from "axios"; +import { useEffect, useState } from "react"; +import { Bar, BarChart, CartesianGrid, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; + +interface Props { + filtros: any +} + +interface so { + adscripcion: string + so: string; + total: number; +} + +const colores = [ + "#818CF8", + "#34D399", + "#FBBF24", + "#F87171", + "#67E8F9", + "#C084FC" +] + +const api_url = process.env.NEXT_PUBLIC_API_URL; + +export default function SistemaOperativo({ filtros }: Props) { + const [data, setData] = useState([]) + + useEffect(() => { + const getAntiguedad = async () => { + const response = await axios.post(`${api_url}/equipos/graficaPerifericos/so`, filtros) + + setData(response.data) + } + getAntiguedad() + }, [filtros]) + + const tieneAdscripciones = data.some(d => d.adscripcion) + + let dataTransformada = data + let adscripciones: string[] = [] + + if (tieneAdscripciones) { + + adscripciones = [...new Set(data.map(d => d.adscripcion))] + + dataTransformada = Object.values( + data.reduce((acc: any, item: any) => { + + if (!acc[item.so]) { + acc[item.so] = { so: item.so } + } + + acc[item.so][item.adscripcion] = Number(item.total) + + return acc + + }, {}) + ) + } + + return ( +
+

SistemaOperativo por equipo

+ + + + + + [`${value}`]} + /> + + {tieneAdscripciones ? ( + + adscripciones.map((ads, i) => ( + + )) + + ) : ( + + + + )} + + +
+ ) +} \ No newline at end of file diff --git a/src/components/reporte_graficas_perifericos/Graficas/Uso.tsx b/src/components/reporte_graficas_perifericos/Graficas/Uso.tsx new file mode 100644 index 0000000..16f99ce --- /dev/null +++ b/src/components/reporte_graficas_perifericos/Graficas/Uso.tsx @@ -0,0 +1,107 @@ +'use client' + +import axios from "axios"; +import { useEffect, useState } from "react"; +import { Bar, BarChart, CartesianGrid, Legend, ResponsiveContainer, Tooltip, XAxis, YAxis } from "recharts"; + +interface Props { + filtros: any +} + +interface UsoData { + uso: string + adscripcion: string + total: number +} + +const colores = [ + "#818CF8", + "#34D399", + "#FBBF24", + "#F87171", + "#67E8F9", + "#C084FC" +] + +const api_url = process.env.NEXT_PUBLIC_API_URL; + +export default function Uso({ filtros }: Props) { + const [data, setData] = useState([]) + + useEffect(() => { + const getUso = async () => { + const response = await axios.post( + `${api_url}/equipos/graficaPerifericos/uso`, filtros + ) + setData(response.data) + } + getUso() + + }, [filtros]) + + const tieneAdscripciones = data.some(d => d.adscripcion) + + let dataTransformada = data + let adscripciones: string[] = [] + + if (tieneAdscripciones) { + + adscripciones = [...new Set(data.map(d => d.adscripcion))] + + dataTransformada = Object.values( + data.reduce((acc: any, item: any) => { + + if (!acc[item.uso]) { + acc[item.uso] = { uso: item.uso } + } + + acc[item.uso][item.adscripcion] = Number(item.total) + + return acc + + }, {}) + ) + } + + return ( +
+

Uso por equipo

+ + + + + + [`${value}`]} + /> + + {tieneAdscripciones ? ( + + adscripciones.map((ads, i) => ( + + )) + + ) : ( + + + + )} + + +
+ ) +} +//IO \ No newline at end of file diff --git a/src/components/reporte_graficas_perifericos/Reporte.module.css b/src/components/reporte_graficas_perifericos/Reporte.module.css new file mode 100644 index 0000000..f0cff8d --- /dev/null +++ b/src/components/reporte_graficas_perifericos/Reporte.module.css @@ -0,0 +1,122 @@ +.container { + width: 100%; + margin: 0 auto; + padding: 20px; + background: white; + border-radius: 10px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08); + font-family: Arial, Helvetica, sans-serif; + font-size: 14px; +} + +.title { + font-size: 18px; + margin-bottom: 15px; +} + +.label { + font-size: 13px; + color: #444; +} + +.listaContainer { + margin-top: 20px; +} + +.subtitle { + font-size: 14px; + margin-bottom: 10px; +} + +.empty { + font-size: 13px; + color: #777; +} + +.lista { + display: flex; + flex-wrap: wrap; + gap: 8px; +} + +.chip { + display: flex; + align-items: center; + background: linear-gradient(135deg, #2563eb, #7c3aed); + border-radius: 6px; + padding: 5px 10px; + font-size: 13px; + text-align: start; + color: white; +} + +.remove { + border: none; + background: rgba(255,255,255,0.2); + margin-left: 8px; + cursor: pointer; + color: white; + border-radius: 50%; + width: 18px; + height: 18px; + display: flex; + align-items: center; + justify-content: center; + font-size: 12px; + transition: all 0.2s ease; +} + +.remove:hover { + background: rgba(255,255,255,0.4); +} + +.button { + margin-top: 20px; + padding: 12px 20px; + border: none; + border-radius: 10px; + background: linear-gradient(135deg, #2563eb, #4f46e5); + color: white; + font-size: 14px; + font-weight: 600; + cursor: pointer; + transition: all 0.25s ease; + box-shadow: 0 6px 15px rgba(37, 99, 235, 0.3); +} + +.button:hover { + transform: translateY(-2px); + box-shadow: 0 10px 25px rgba(37, 99, 235, 0.4); +} +.graficas { + display: flex; + flex-wrap: wrap; + justify-content: space-between; + gap: 1rem; +} + +.graficas > div { + background: white; + border-radius: 16px !important; + padding: 15px !important; + box-shadow: 0 10px 25px rgba(0,0,0,0.08); + transition: all 0.3s ease; +} + +.graficas > div:hover { + transform: translateY(-5px); + box-shadow: 0 15px 35px rgba(0,0,0,0.12); +} + +.filtro { + display: flex; + gap: 10px; + flex-wrap: wrap; + align-items: start; + justify-content: space-between; +} + +.containerSelection { + width: 100%; + width: 200px +} \ No newline at end of file diff --git a/src/components/reporte_graficas_perifericos/Tablas/Antiguedad.tsx b/src/components/reporte_graficas_perifericos/Tablas/Antiguedad.tsx new file mode 100644 index 0000000..5e97454 --- /dev/null +++ b/src/components/reporte_graficas_perifericos/Tablas/Antiguedad.tsx @@ -0,0 +1,83 @@ +'use client' + +import { useEffect, useState } from 'react' +import styles from './TableAntiguedad.module.css' +import axios from 'axios' +import DownloadTable from '@/components/Dowload/tabla' + +interface Props { + filtros: any + count: boolean +} + +const api_url = process.env.NEXT_PUBLIC_API_URL; + +export default function TableAntiguedad({ filtros, count }: Props) { + + const [data, setData] = useState([]) + + useEffect(() => { + const getUso = async () => { + const endpoint = count + ? `${api_url}/equipos/tabla/count` + : `${api_url}/equipos/tabla` + + const response = await axios.post(endpoint, filtros) + setData(response.data) + } + + getUso() + }, [filtros, count]) + + const columnas = data.length > 0 ? Object.keys(data[0]) : [] + + return ( +
+ {count ? : } + + + + + {columnas.map((col) => ( + + ))} + + + + + {data.length === 0 ? ( + + + + ) : ( + data.map((item, index) => ( + + {columnas.map((col) => ( + + ))} + + )) + )} + + +
{formatearTitulo(col)}
+ No hay datos +
+ {item[col] ?? '-'} +
+
+ ) +} + +function formatearTitulo(col: string) { + const nombres: any = { + inventario: 'No. Inventario', + adscripcion: 'Adscripción', + antiguedad: 'Antigüedad', + procesador: 'Procesador', + sistema_operativo: 'Sistema Operativo', + uso: 'Uso' + } + + return nombres[col] || col +} \ No newline at end of file diff --git a/src/components/reporte_graficas_perifericos/Tablas/TableAntiguedad.module.css b/src/components/reporte_graficas_perifericos/Tablas/TableAntiguedad.module.css new file mode 100644 index 0000000..1da810f --- /dev/null +++ b/src/components/reporte_graficas_perifericos/Tablas/TableAntiguedad.module.css @@ -0,0 +1,44 @@ +.container { + width: 100%; + overflow-x: auto; +} + +.table { + width: 100%; + border-collapse: collapse; + font-size: 14px; + background: #ffffff; + border-radius: 12px; + overflow: hidden; +} + +.table thead { + background: linear-gradient(135deg, #a5a5a5, #878787); + color: white; +} + +.table th { + padding: 12px; + text-align: center; +} + +.table td { + padding: 10px 12px; + border-bottom: 1px solid #eee; +} + +.table tbody tr:hover { + background-color: #f5f8ff; + transition: 0.2s; +} + +.total { + font-weight: bold; + color: #095bd6; +} + +.empty { + text-align: center; + padding: 20px; + color: #999; +} \ No newline at end of file diff --git a/src/components/reporte_graficas_perifericos/reporte.tsx b/src/components/reporte_graficas_perifericos/reporte.tsx new file mode 100644 index 0000000..a2b1905 --- /dev/null +++ b/src/components/reporte_graficas_perifericos/reporte.tsx @@ -0,0 +1,393 @@ +"use client" + +import Select from "react-select" +import { useEffect, useState } from "react" +import styles from "./Reporte.module.css" +import axios from "axios" + +import Antiguedad from "./Graficas/Antiguedad" +import Procesador from "./Graficas/Procesador" +import SistemaOperativo from "./Graficas/SistemaOperativo" +import Uso from "./Graficas/Uso" + +import Cookies from "js-cookie"; +import TableAntiguedad from "./Tablas/Antiguedad" +const api_url = process.env.NEXT_PUBLIC_API_URL; + +type AdscripcionOption = { + id_adscripcion: string + adscripcion: string +} + +type UsoOption = { + id_uso: string + tipo_uso: string +} + +type SoOption = { + id_sistema_operativo: string + sistema_operativo: string +} + +type ProcesadorOption = { + id_procesador: string + procesador: string +} + +type AntiguedadOption = { + antiguedad: string +} + +export default function ReportePerifericos() { + + const [adscripciones, setAdscripciones] = useState([]) + const [adscripcionesSeleccionadas, setAdscripcionesSeleccionadas] = useState([]) + + const [procesadores, setProcesadores] = useState([]) + const [procesadorSeleccionado, setProcesadorSeleccionado] = useState([]) + + const [sistemasOperativos, setSistemasOperativos] = useState([]) + const [soSeleccionado, setSoSeleccionado] = useState([]) + + const [usos, setUsos] = useState([{ id_uso: "0", tipo_uso: "Todos" }]) + const [usoSeleccionado, setUsoSeleccionado] = useState([]) + + const [antiguedad, setAntiguedad] = useState([{ antiguedad: "Todos" }, { antiguedad: "Menor a 2 años" }, { antiguedad: "Entre 2 y 3 años" }, { antiguedad: "Entre 4 y 5 años" }, { antiguedad: "Mayor a 6 años" }]) + const [antiguedadSeleccionada, setAntiguedadSeleccionada] = useState([]) + + const [filtros, setFiltros] = useState(null) + const [filtrosTable, setFiltrosTable] = useState(null) + + useEffect(() => { + + const cargarDatos = async () => { + const token = Cookies.get("token"); + const headers = { Authorization: `Bearer ${token}` }; + const [ + adscripcionRes, + procesadorRes, + usoRes, + soRes, + ] = await Promise.all([ + axios.get(`${api_url}/equipos/adscripciones`, { headers }), + axios.get(`${api_url}/equipos/procesador-tipo-equipos`, { headers }), + axios.get(`${api_url}/equipos/usos`, { headers }), + axios.get(`${api_url}/equipos/sistemas-operativos`, { headers }), + ]) + + setAdscripciones([ + { id_adscripcion: "0", adscripcion: "Todos" }, + ...adscripcionRes.data + ]) + + setProcesadores([ + { id_procesador: "0", procesador: "Todos" }, + ...procesadorRes.data + ]) + + setUsos([ + { id_uso: "0", tipo_uso: "Todos" }, + ...usoRes.data + ]) + + setSistemasOperativos([ + { id_sistema_operativo: "0", sistema_operativo: "Todos" }, + ...soRes.data + ]) + } + + cargarDatos() + + }, []) + + function agregar(option: T | null, lista: T[], setLista: (v: T[]) => void, key: keyof T) { + + if (!option) return + + const existe = lista.some((item) => item[key] === option[key]) + + if (!existe) { + setLista([...lista, option]) + } + + } + + function eliminar(id: string, lista: T[], setLista: (v: T[]) => void, key: keyof T) { + + setLista( + lista.filter((item) => item[key] !== id) + ) + + } + + const generarReporte = () => { + + const limpiar = (arr: string[]) => { + if (arr.includes("0")) return [] + return arr + } + + const filtrosTable = { + adscripciones: adscripcionesSeleccionadas.map(a => String(a.id_adscripcion)), + procesadores: procesadorSeleccionado.map(p => String(p.id_procesador)), + sistemas: soSeleccionado.map(s => String(s.id_sistema_operativo)), + usos: usoSeleccionado.map(u => String(u.id_uso)), + antiguedad: antiguedadSeleccionada.map(u => String(u.antiguedad)) + } + + const filtros = { + adscripciones: limpiar(adscripcionesSeleccionadas.map(a => String(a.id_adscripcion))), + procesadores: limpiar(procesadorSeleccionado.map(p => String(p.id_procesador))), + sistemas: limpiar(soSeleccionado.map(s => String(s.id_sistema_operativo))), + usos: limpiar(usoSeleccionado.map(u => String(u.id_uso))), + antiguedad: limpiar(antiguedadSeleccionada.map(a => String(a.antiguedad))) + } + + setFiltros(filtros) + setFiltrosTable(filtrosTable) + + } + + return ( + <> +
+ +
+ + {/* ADSCRIPCION */} + +
+ + + o.procesador} + getOptionValue={(o) => o.id_procesador} + onChange={(o) => + agregar(o, procesadorSeleccionado, setProcesadorSeleccionado, "id_procesador") + } + /> + +
+ + {procesadorSeleccionado.map((p) => ( + +
+ + {p.procesador} + + + +
+ + ))} + +
+ +
+ + {/* SISTEMA OPERATIVO */} + +
+ + + + o.tipo_uso} + getOptionValue={(o) => o.id_uso} + onChange={(o) => + agregar(o, usoSeleccionado, setUsoSeleccionado, "id_uso") + } + /> + +
+ + {usoSeleccionado.map((u) => ( + +
+ + {u.tipo_uso} + + + +
+ + ))} + +
+ +
+ + +
+ + + +