Feat Widgets 1540

This commit is contained in:
2025-09-02 15:39:01 -03:00
parent 271a86b632
commit da581d9714
17 changed files with 742 additions and 258 deletions

View File

@@ -104,11 +104,11 @@ export const ConfiguracionGeneral = () => {
</p> </p>
</div> </div>
<div className="form-group" style={{ marginTop: '2rem' }}> <div className="form-group" style={{ marginTop: '2rem' }}>
<label htmlFor="ticker-cantidad">Cantidad en Ticker (Dip/Sen)</label> <label htmlFor="ticker-cantidad">Cantidad en Ticker (Dip/Sen) (Sumar 1 para "Otros")</label>
<input id="ticker-cantidad" type="number" value={tickerCantidad} onChange={e => setTickerCantidad(e.target.value)} /> <input id="ticker-cantidad" type="number" value={tickerCantidad} onChange={e => setTickerCantidad(e.target.value)} />
</div> </div>
<div className="form-group" style={{ marginTop: '2rem' }}> <div className="form-group" style={{ marginTop: '2rem' }}>
<label htmlFor="concejales-cantidad">Cantidad en Widget Concejales</label> <label htmlFor="concejales-cantidad">Cantidad en Widget Concejales (Sumar 1 para "Otros")</label>
<input <input
id="concejales-cantidad" id="concejales-cantidad"
type="number" type="number"

View File

@@ -18,6 +18,7 @@
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"react-pdf": "^10.1.0", "react-pdf": "^10.1.0",
"react-select": "^5.10.2",
"react-simple-maps": "github:ozimmortal/react-simple-maps#feat/react-19-support", "react-simple-maps": "github:ozimmortal/react-simple-maps#feat/react-19-support",
"react-tooltip": "^5.29.1" "react-tooltip": "^5.29.1"
}, },
@@ -26,6 +27,7 @@
"@types/geojson": "^7946.0.16", "@types/geojson": "^7946.0.16",
"@types/react": "^19.1.10", "@types/react": "^19.1.10",
"@types/react-dom": "^19.1.7", "@types/react-dom": "^19.1.7",
"@types/react-select": "^5.0.0",
"@vitejs/plugin-react": "^5.0.0", "@vitejs/plugin-react": "^5.0.0",
"eslint": "^9.33.0", "eslint": "^9.33.0",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",
@@ -54,7 +56,6 @@
"version": "7.27.1", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.27.1.tgz",
"integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==", "integrity": "sha512-cjQ7ZlQ0Mv3b47hABuTevyTuYN4i+loJKGeV9flcCgIK37cCXRh+L1bd3iBHlynerhQ7BhCkn2BPbQUL+rGqFg==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-validator-identifier": "^7.27.1", "@babel/helper-validator-identifier": "^7.27.1",
@@ -110,7 +111,6 @@
"version": "7.28.3", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.28.3.tgz",
"integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==", "integrity": "sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/parser": "^7.28.3", "@babel/parser": "^7.28.3",
@@ -144,7 +144,6 @@
"version": "7.28.0", "version": "7.28.0",
"resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
"integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==", "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -154,7 +153,6 @@
"version": "7.27.1", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.27.1.tgz",
"integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==", "integrity": "sha512-0gSFWUPNXNopqtIPQvlD5WgXYI5GY2kP2cCvoT8kczjbfcfuIljTbcWrulD1CIPIX2gt1wghbDy08yE1p+/r3w==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/traverse": "^7.27.1", "@babel/traverse": "^7.27.1",
@@ -196,7 +194,6 @@
"version": "7.27.1", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
"integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==", "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -206,7 +203,6 @@
"version": "7.27.1", "version": "7.27.1",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.27.1.tgz",
"integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==", "integrity": "sha512-D2hP9eA+Sqx1kBZgzxZh0y1trbuU+JoDkiEwqhQ36nodYqJwyEIhPSdMNd7lOm/4io72luTPWH20Yda0xOuUow==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.9.0" "node": ">=6.9.0"
@@ -240,7 +236,6 @@
"version": "7.28.3", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.3.tgz",
"integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==", "integrity": "sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/types": "^7.28.2" "@babel/types": "^7.28.2"
@@ -284,11 +279,19 @@
"@babel/core": "^7.0.0-0" "@babel/core": "^7.0.0-0"
} }
}, },
"node_modules/@babel/runtime": {
"version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.3.tgz",
"integrity": "sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template": { "node_modules/@babel/template": {
"version": "7.27.2", "version": "7.27.2",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.27.2.tgz",
"integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==", "integrity": "sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
@@ -303,7 +306,6 @@
"version": "7.28.3", "version": "7.28.3",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.28.3.tgz",
"integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==", "integrity": "sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/code-frame": "^7.27.1", "@babel/code-frame": "^7.27.1",
@@ -322,7 +324,6 @@
"version": "7.28.2", "version": "7.28.2",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.2.tgz",
"integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==", "integrity": "sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@babel/helper-string-parser": "^7.27.1", "@babel/helper-string-parser": "^7.27.1",
@@ -332,6 +333,126 @@
"node": ">=6.9.0" "node": ">=6.9.0"
} }
}, },
"node_modules/@emotion/babel-plugin": {
"version": "11.13.5",
"resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.13.5.tgz",
"integrity": "sha512-pxHCpT2ex+0q+HH91/zsdHkw/lXd468DIN2zvfvLtPKLLMo6gQj7oLObq8PhkrxOZb/gGCq03S3Z7PDhS8pduQ==",
"license": "MIT",
"dependencies": {
"@babel/helper-module-imports": "^7.16.7",
"@babel/runtime": "^7.18.3",
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/serialize": "^1.3.3",
"babel-plugin-macros": "^3.1.0",
"convert-source-map": "^1.5.0",
"escape-string-regexp": "^4.0.0",
"find-root": "^1.1.0",
"source-map": "^0.5.7",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
"version": "1.9.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
"integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
"license": "MIT"
},
"node_modules/@emotion/cache": {
"version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.14.0.tgz",
"integrity": "sha512-L/B1lc/TViYk4DcpGxtAVbx0ZyiKM5ktoIyafGkH6zg/tj+mA+NE//aPYKG0k8kCHSHVJrpLpcAlOBEXQ3SavA==",
"license": "MIT",
"dependencies": {
"@emotion/memoize": "^0.9.0",
"@emotion/sheet": "^1.4.0",
"@emotion/utils": "^1.4.2",
"@emotion/weak-memoize": "^0.4.0",
"stylis": "4.2.0"
}
},
"node_modules/@emotion/hash": {
"version": "0.9.2",
"resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
"integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g==",
"license": "MIT"
},
"node_modules/@emotion/memoize": {
"version": "0.9.0",
"resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
"integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ==",
"license": "MIT"
},
"node_modules/@emotion/react": {
"version": "11.14.0",
"resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.14.0.tgz",
"integrity": "sha512-O000MLDBDdk/EohJPFUqvnp4qnHeYkVP5B0xEG0D/L7cOKP9kefu2DXn8dj74cQfsEzUqh+sr1RzFqiL1o+PpA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.13.5",
"@emotion/cache": "^11.14.0",
"@emotion/serialize": "^1.3.3",
"@emotion/use-insertion-effect-with-fallbacks": "^1.2.0",
"@emotion/utils": "^1.4.2",
"@emotion/weak-memoize": "^0.4.0",
"hoist-non-react-statics": "^3.3.1"
},
"peerDependencies": {
"react": ">=16.8.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/@emotion/serialize": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.3.tgz",
"integrity": "sha512-EISGqt7sSNWHGI76hC7x1CksiXPahbxEOrC5RjmFRJTqLyEK9/9hZvBbiYn70dw4wuwMKiEMCUlR6ZXTSWQqxA==",
"license": "MIT",
"dependencies": {
"@emotion/hash": "^0.9.2",
"@emotion/memoize": "^0.9.0",
"@emotion/unitless": "^0.10.0",
"@emotion/utils": "^1.4.2",
"csstype": "^3.0.2"
}
},
"node_modules/@emotion/sheet": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
"integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg==",
"license": "MIT"
},
"node_modules/@emotion/unitless": {
"version": "0.10.0",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
"integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg==",
"license": "MIT"
},
"node_modules/@emotion/use-insertion-effect-with-fallbacks": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.2.0.tgz",
"integrity": "sha512-yJMtVdH59sxi/aVJBpk9FQq+OR8ll5GT8oWd57UpeaKEVGab41JWaCFA7FRLoMLloOZF/c/wsPoe+bfGmRKgDg==",
"license": "MIT",
"peerDependencies": {
"react": ">=16.8.0"
}
},
"node_modules/@emotion/utils": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.2.tgz",
"integrity": "sha512-3vLclRofFziIa3J2wDh9jjbkUz9qk5Vi3IZ/FSTKViB0k+ef0fPV7dYrUIugbgupYDx7v9ud/SjrtEP8Y4xLoA==",
"license": "MIT"
},
"node_modules/@emotion/weak-memoize": {
"version": "0.4.0",
"resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
"integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg==",
"license": "MIT"
},
"node_modules/@esbuild/aix-ppc64": { "node_modules/@esbuild/aix-ppc64": {
"version": "0.25.9", "version": "0.25.9",
"resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz",
@@ -1023,7 +1144,6 @@
"version": "0.3.13", "version": "0.3.13",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
"integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==", "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/sourcemap-codec": "^1.5.0", "@jridgewell/sourcemap-codec": "^1.5.0",
@@ -1034,7 +1154,6 @@
"version": "3.1.2", "version": "3.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
"integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6.0.0" "node": ">=6.0.0"
@@ -1057,14 +1176,12 @@
"version": "1.5.5", "version": "1.5.5",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
"integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==", "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/@jridgewell/trace-mapping": { "node_modules/@jridgewell/trace-mapping": {
"version": "0.3.30", "version": "0.3.30",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz",
"integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==", "integrity": "sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/resolve-uri": "^3.1.0",
@@ -2026,11 +2143,16 @@
"undici-types": "~7.10.0" "undici-types": "~7.10.0"
} }
}, },
"node_modules/@types/parse-json": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
"integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
"license": "MIT"
},
"node_modules/@types/react": { "node_modules/@types/react": {
"version": "19.1.10", "version": "19.1.10",
"resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz", "resolved": "https://registry.npmjs.org/@types/react/-/react-19.1.10.tgz",
"integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==", "integrity": "sha512-EhBeSYX0Y6ye8pNebpKrwFJq7BoQ8J5SO6NlvNwwHjSj6adXJViPQrKlsyPw7hLBLvckEMO1yxeGdR82YBBlDg==",
"devOptional": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"csstype": "^3.0.2" "csstype": "^3.0.2"
@@ -2046,6 +2168,25 @@
"@types/react": "^19.0.0" "@types/react": "^19.0.0"
} }
}, },
"node_modules/@types/react-select": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/@types/react-select/-/react-select-5.0.0.tgz",
"integrity": "sha512-vddLcBpzUMVpVNmnBtpC5cyZ2ajaHx/g6SHUo6lmMw0FIiOzrtmoSQ4UI6TRl+sm8TGGT+Oir8NRMZfYQtgr8Q==",
"dev": true,
"license": "MIT",
"dependencies": {
"react-select": "*"
}
},
"node_modules/@types/react-transition-group": {
"version": "4.4.12",
"resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.12.tgz",
"integrity": "sha512-8TV6R3h2j7a91c+1DXdJi3Syo69zzIZbz7Lg5tORM5LEJG7X/E6a1V3drRyBRZq7/utz7A+c4OgYLiLcYGHG6w==",
"license": "MIT",
"peerDependencies": {
"@types/react": "*"
}
},
"node_modules/@typescript-eslint/eslint-plugin": { "node_modules/@typescript-eslint/eslint-plugin": {
"version": "8.40.0", "version": "8.40.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz", "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.40.0.tgz",
@@ -2418,6 +2559,21 @@
"proxy-from-env": "^1.1.0" "proxy-from-env": "^1.1.0"
} }
}, },
"node_modules/babel-plugin-macros": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
"integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.5",
"cosmiconfig": "^7.0.0",
"resolve": "^1.19.0"
},
"engines": {
"node": ">=10",
"npm": ">=6"
}
},
"node_modules/balanced-match": { "node_modules/balanced-match": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
@@ -2508,7 +2664,6 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=6" "node": ">=6"
@@ -2613,6 +2768,31 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/cosmiconfig": {
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
"integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"license": "MIT",
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
"parse-json": "^5.0.0",
"path-type": "^4.0.0",
"yaml": "^1.10.0"
},
"engines": {
"node": ">=10"
}
},
"node_modules/cosmiconfig/node_modules/yaml": {
"version": "1.10.2",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
"integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
"license": "ISC",
"engines": {
"node": ">= 6"
}
},
"node_modules/cross-spawn": { "node_modules/cross-spawn": {
"version": "7.0.6", "version": "7.0.6",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
@@ -2632,7 +2812,6 @@
"version": "3.1.3", "version": "3.1.3",
"resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
"devOptional": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/d3-array": { "node_modules/d3-array": {
@@ -2851,7 +3030,6 @@
"version": "4.4.1", "version": "4.4.1",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz", "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
"integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==", "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"ms": "^2.1.3" "ms": "^2.1.3"
@@ -2890,6 +3068,16 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/dom-helpers": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
"integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.8.7",
"csstype": "^3.0.2"
}
},
"node_modules/dunder-proto": { "node_modules/dunder-proto": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -2911,6 +3099,15 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/error-ex": {
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
"license": "MIT",
"dependencies": {
"is-arrayish": "^0.2.1"
}
},
"node_modules/es-define-property": { "node_modules/es-define-property": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
@@ -3012,7 +3209,6 @@
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
"integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=10" "node": ">=10"
@@ -3286,6 +3482,12 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/find-root": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
"integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
"license": "MIT"
},
"node_modules/find-up": { "node_modules/find-up": {
"version": "5.0.0", "version": "5.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
@@ -3525,6 +3727,15 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/hoist-non-react-statics": {
"version": "3.3.2",
"resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
"integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
"license": "BSD-3-Clause",
"dependencies": {
"react-is": "^16.7.0"
}
},
"node_modules/ignore": { "node_modules/ignore": {
"version": "5.3.2", "version": "5.3.2",
"resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
@@ -3539,7 +3750,6 @@
"version": "3.3.1", "version": "3.3.1",
"resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
"integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==", "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"parent-module": "^1.0.0", "parent-module": "^1.0.0",
@@ -3571,6 +3781,27 @@
"node": ">=12" "node": ">=12"
} }
}, },
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"license": "MIT"
},
"node_modules/is-core-module": {
"version": "2.16.1",
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
"integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
"license": "MIT",
"dependencies": {
"hasown": "^2.0.2"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/is-extglob": { "node_modules/is-extglob": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
@@ -3634,7 +3865,6 @@
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
"integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==", "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
"license": "MIT", "license": "MIT",
"bin": { "bin": {
"jsesc": "bin/jsesc" "jsesc": "bin/jsesc"
@@ -3650,6 +3880,12 @@
"dev": true, "dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
"license": "MIT"
},
"node_modules/json-schema-traverse": { "node_modules/json-schema-traverse": {
"version": "0.4.1", "version": "0.4.1",
"resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
@@ -3701,6 +3937,12 @@
"node": ">= 0.8.0" "node": ">= 0.8.0"
} }
}, },
"node_modules/lines-and-columns": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
"license": "MIT"
},
"node_modules/locate-path": { "node_modules/locate-path": {
"version": "6.0.0", "version": "6.0.0",
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
@@ -3779,6 +4021,12 @@
"node": ">= 0.4" "node": ">= 0.4"
} }
}, },
"node_modules/memoize-one": {
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
"integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw==",
"license": "MIT"
},
"node_modules/merge-refs": { "node_modules/merge-refs": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-2.0.0.tgz", "resolved": "https://registry.npmjs.org/merge-refs/-/merge-refs-2.0.0.tgz",
@@ -3858,7 +4106,6 @@
"version": "2.1.3", "version": "2.1.3",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
"dev": true,
"license": "MIT" "license": "MIT"
}, },
"node_modules/nanoid": { "node_modules/nanoid": {
@@ -3899,7 +4146,6 @@
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
"integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
"license": "MIT", "license": "MIT",
"peer": true,
"engines": { "engines": {
"node": ">=0.10.0" "node": ">=0.10.0"
} }
@@ -3958,7 +4204,6 @@
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"callsites": "^3.0.0" "callsites": "^3.0.0"
@@ -3967,6 +4212,24 @@
"node": ">=6" "node": ">=6"
} }
}, },
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
"json-parse-even-better-errors": "^2.3.0",
"lines-and-columns": "^1.1.6"
},
"engines": {
"node": ">=8"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/path-exists": { "node_modules/path-exists": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
@@ -3987,6 +4250,21 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/path-parse": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
"integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
"license": "MIT"
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/pdfjs-dist": { "node_modules/pdfjs-dist": {
"version": "5.3.93", "version": "5.3.93",
"resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.3.93.tgz", "resolved": "https://registry.npmjs.org/pdfjs-dist/-/pdfjs-dist-5.3.93.tgz",
@@ -4003,7 +4281,6 @@
"version": "1.1.1", "version": "1.1.1",
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
"dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/picomatch": { "node_modules/picomatch": {
@@ -4063,7 +4340,6 @@
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
"integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==", "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
"license": "MIT", "license": "MIT",
"peer": true,
"dependencies": { "dependencies": {
"loose-envify": "^1.4.0", "loose-envify": "^1.4.0",
"object-assign": "^4.1.1", "object-assign": "^4.1.1",
@@ -4132,8 +4408,7 @@
"version": "16.13.1", "version": "16.13.1",
"resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
"integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==",
"license": "MIT", "license": "MIT"
"peer": true
}, },
"node_modules/react-pdf": { "node_modules/react-pdf": {
"version": "10.1.0", "version": "10.1.0",
@@ -4174,6 +4449,27 @@
"node": ">=0.10.0" "node": ">=0.10.0"
} }
}, },
"node_modules/react-select": {
"version": "5.10.2",
"resolved": "https://registry.npmjs.org/react-select/-/react-select-5.10.2.tgz",
"integrity": "sha512-Z33nHdEFWq9tfnfVXaiM12rbJmk+QjFEztWLtmXqQhz6Al4UZZ9xc0wiatmGtUOCCnHN0WizL3tCMYRENX4rVQ==",
"license": "MIT",
"dependencies": {
"@babel/runtime": "^7.12.0",
"@emotion/cache": "^11.4.0",
"@emotion/react": "^11.8.1",
"@floating-ui/dom": "^1.0.1",
"@types/react-transition-group": "^4.4.0",
"memoize-one": "^6.0.0",
"prop-types": "^15.6.0",
"react-transition-group": "^4.3.0",
"use-isomorphic-layout-effect": "^1.2.0"
},
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0",
"react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
}
},
"node_modules/react-simple-maps": { "node_modules/react-simple-maps": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "git+ssh://git@github.com/ozimmortal/react-simple-maps.git#f2b342ae277569b751fa1c9b6638e06ad05ab617", "resolved": "git+ssh://git@github.com/ozimmortal/react-simple-maps.git#f2b342ae277569b751fa1c9b6638e06ad05ab617",
@@ -4206,6 +4502,22 @@
"react-dom": ">=16.14.0" "react-dom": ">=16.14.0"
} }
}, },
"node_modules/react-transition-group": {
"version": "4.4.5",
"resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
"integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
"license": "BSD-3-Clause",
"dependencies": {
"@babel/runtime": "^7.5.5",
"dom-helpers": "^5.0.1",
"loose-envify": "^1.4.0",
"prop-types": "^15.6.2"
},
"peerDependencies": {
"react": ">=16.6.0",
"react-dom": ">=16.6.0"
}
},
"node_modules/react-virtualized-auto-sizer": { "node_modules/react-virtualized-auto-sizer": {
"version": "1.0.26", "version": "1.0.26",
"resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.26.tgz", "resolved": "https://registry.npmjs.org/react-virtualized-auto-sizer/-/react-virtualized-auto-sizer-1.0.26.tgz",
@@ -4216,11 +4528,30 @@
"react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0" "react-dom": "^15.3.0 || ^16.0.0-alpha || ^17.0.0 || ^18.0.0 || ^19.0.0"
} }
}, },
"node_modules/resolve": {
"version": "1.22.10",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz",
"integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==",
"license": "MIT",
"dependencies": {
"is-core-module": "^2.16.0",
"path-parse": "^1.0.7",
"supports-preserve-symlinks-flag": "^1.0.0"
},
"bin": {
"resolve": "bin/resolve"
},
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/resolve-from": { "node_modules/resolve-from": {
"version": "4.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
"license": "MIT", "license": "MIT",
"engines": { "engines": {
"node": ">=4" "node": ">=4"
@@ -4340,6 +4671,15 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/source-map": {
"version": "0.5.7",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
"integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
"license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/source-map-js": { "node_modules/source-map-js": {
"version": "1.2.1", "version": "1.2.1",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
@@ -4388,6 +4728,12 @@
"url": "https://github.com/sponsors/sindresorhus" "url": "https://github.com/sponsors/sindresorhus"
} }
}, },
"node_modules/stylis": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
"integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw==",
"license": "MIT"
},
"node_modules/supports-color": { "node_modules/supports-color": {
"version": "7.2.0", "version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
@@ -4401,6 +4747,18 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/supports-preserve-symlinks-flag": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
"integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
"license": "MIT",
"engines": {
"node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/terser": { "node_modules/terser": {
"version": "5.43.1", "version": "5.43.1",
"resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz", "resolved": "https://registry.npmjs.org/terser/-/terser-5.43.1.tgz",
@@ -4644,6 +5002,20 @@
"react": "*" "react": "*"
} }
}, },
"node_modules/use-isomorphic-layout-effect": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.2.1.tgz",
"integrity": "sha512-tpZZ+EX0gaghDAiFR37hj5MgY6ZN55kLiPkJsKxBMZ6GZdOSPJXiOzPM984oPYZ5AnehYx5WQp1+ME8I/P/pRA==",
"license": "MIT",
"peerDependencies": {
"react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0"
},
"peerDependenciesMeta": {
"@types/react": {
"optional": true
}
}
},
"node_modules/vite": { "node_modules/vite": {
"version": "7.1.3", "version": "7.1.3",
"resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz", "resolved": "https://registry.npmjs.org/vite/-/vite-7.1.3.tgz",
@@ -4792,6 +5164,21 @@
"dev": true, "dev": true,
"license": "ISC" "license": "ISC"
}, },
"node_modules/yaml": {
"version": "2.8.1",
"resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.1.tgz",
"integrity": "sha512-lcYcMxX2PO9XMGvAJkJ3OsNMw+/7FKes7/hgerGUYWIoWu5j/+YQqcZr5JnPZWzOsEBgMbSbiSTn/dv/69Mkpw==",
"dev": true,
"license": "ISC",
"optional": true,
"peer": true,
"bin": {
"yaml": "bin.mjs"
},
"engines": {
"node": ">= 14.6"
}
},
"node_modules/yocto-queue": { "node_modules/yocto-queue": {
"version": "0.1.0", "version": "0.1.0",
"resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",

View File

@@ -20,6 +20,7 @@
"react": "^19.1.1", "react": "^19.1.1",
"react-dom": "^19.1.1", "react-dom": "^19.1.1",
"react-pdf": "^10.1.0", "react-pdf": "^10.1.0",
"react-select": "^5.10.2",
"react-simple-maps": "github:ozimmortal/react-simple-maps#feat/react-19-support", "react-simple-maps": "github:ozimmortal/react-simple-maps#feat/react-19-support",
"react-tooltip": "^5.29.1" "react-tooltip": "^5.29.1"
}, },
@@ -28,6 +29,7 @@
"@types/geojson": "^7946.0.16", "@types/geojson": "^7946.0.16",
"@types/react": "^19.1.10", "@types/react": "^19.1.10",
"@types/react-dom": "^19.1.7", "@types/react-dom": "^19.1.7",
"@types/react-select": "^5.0.0",
"@vitejs/plugin-react": "^5.0.0", "@vitejs/plugin-react": "^5.0.0",
"eslint": "^9.33.0", "eslint": "^9.33.0",
"eslint-plugin-react-hooks": "^5.2.0", "eslint-plugin-react-hooks": "^5.2.0",

View File

@@ -65,6 +65,7 @@ export interface ResultadoDetalleSeccion {
nombre: string; nombre: string;
votos: number; votos: number;
porcentaje: number; porcentaje: number;
color: string | null;
} }
export const getResumenProvincial = async (): Promise<CategoriaResumen[]> => { export const getResumenProvincial = async (): Promise<CategoriaResumen[]> => {
@@ -142,3 +143,15 @@ export const getDetalleSeccion = async (seccionId: string, categoriaId: number):
const response = await apiClient.get(`/resultados/seccion/${seccionId}?categoriaId=${categoriaId}`); const response = await apiClient.get(`/resultados/seccion/${seccionId}?categoriaId=${categoriaId}`);
return response.data; return response.data;
}; };
export const getResultadosConcejalesPorMunicipio = async (municipioId: string): Promise<ResultadoTicker[]> => {
// Usamos el endpoint 'partido' que, según la aclaración de la API, busca por municipio
const response = await apiClient.get(`/resultados/partido/${municipioId}`);
// La API devuelve un objeto, nosotros extraemos el array de resultados
return response.data.resultados;
};
export const getMunicipios = async (): Promise<MunicipioSimple[]> => {
const response = await apiClient.get('/catalogos/municipios');
return response.data;
};

View File

@@ -1,88 +1,104 @@
// src/components/ConcejalesWidget.tsx // src/components/ConcejalesWidget.tsx
import { useState, useEffect, useMemo } from 'react'; import { useState, useMemo, useEffect } from 'react';
import { useQuery } from '@tanstack/react-query'; import { useQuery } from '@tanstack/react-query';
import { getSeccionesElectorales, getResultadosConcejales, getConfiguracionPublica } from '../apiService'; import Select from 'react-select'; // <-- 1. Importar react-select
import { getMunicipios, getResultadosConcejalesPorMunicipio, getConfiguracionPublica } from '../apiService';
import type { MunicipioSimple, ResultadoTicker } from '../types/types'; import type { MunicipioSimple, ResultadoTicker } from '../types/types';
import { ImageWithFallback } from './ImageWithFallback'; import { ImageWithFallback } from './ImageWithFallback';
import './TickerWidget.css'; // Reutilizamos los estilos del ticker import './TickerWidget.css';
const formatPercent = (num: number) => `${(num || 0).toFixed(2).replace('.', ',')}%`; const formatPercent = (num: number) => `${(num || 0).toFixed(2).replace('.', ',')}%`;
export const ConcejalesWidget = () => { // Estilos personalizados para que el selector se vea bien
const [secciones, setSecciones] = useState<MunicipioSimple[]>([]); const customSelectStyles = {
const [seccionActualId, setSeccionActualId] = useState<string>(''); control: (base: any) => ({ ...base, minWidth: '220px', border: '1px solid #ced4da' }),
menu: (base: any) => ({ ...base, zIndex: 10 }), // Para que el menú se superponga
};
export const ConcejalesWidget = () => {
// 2. Cambiamos el estado para que se adapte a react-select
const [selectedMunicipio, setSelectedMunicipio] = useState<{ value: string; label: string } | null>(null);
// Query para la configuración (para saber cuántos resultados mostrar)
const { data: configData } = useQuery({ const { data: configData } = useQuery({
queryKey: ['configuracionPublica'], queryKey: ['configuracionPublica'],
queryFn: getConfiguracionPublica, queryFn: getConfiguracionPublica,
staleTime: 0, staleTime: 0,
}); });
// Calculamos la cantidad a mostrar desde la configuración // Usamos la clave de configuración correcta
const cantidadAMostrar = useMemo(() => { const cantidadAMostrar = parseInt(configData?.ConcejalesResultadosCantidad || '5', 10);
return parseInt(configData?.TickerResultadosCantidad || '5', 10) + 1;
}, [configData]);
// 3. Query para obtener la lista de MUNICIPIOS
const { data: municipios = [], isLoading: isLoadingMunicipios } = useQuery<MunicipioSimple[]>({
queryKey: ['municipios'],
queryFn: getMunicipios,
});
// Este useEffect se encarga de establecer el valor por defecto
useEffect(() => { useEffect(() => {
getSeccionesElectorales().then(seccionesData => { // Se ejecuta solo si tenemos la lista de municipios y aún no hemos seleccionado nada
if (seccionesData && seccionesData.length > 0) { if (municipios.length > 0 && !selectedMunicipio) {
const orden = new Map([ // Buscamos "LA PLATA" en la lista (insensible a mayúsculas/minúsculas)
['Capital', 0], ['Primera', 1], ['Segunda', 2], ['Tercera', 3], const laPlata = municipios.find(m => m.nombre.toUpperCase() === 'LA PLATA');
['Cuarta', 4], ['Quinta', 5], ['Sexta', 6], ['Séptima', 7]
]); // Si lo encontramos, lo establecemos como el municipio seleccionado
const getOrden = (nombre: string) => { if (laPlata) {
const match = nombre.match(/Capital|Primera|Segunda|Tercera|Cuarta|Quinta|Sexta|Séptima/); setSelectedMunicipio({ value: laPlata.id, label: laPlata.nombre });
return match ? orden.get(match[0]) ?? 99 : 99;
};
seccionesData.sort((a, b) => getOrden(a.nombre) - getOrden(b.nombre));
setSecciones(seccionesData);
// Al estar los datos ya ordenados, el [0] será "Sección Capital"
setSeccionActualId(seccionesData[0].id);
} }
}); }
}, []); // El array de dependencias vacío asegura que esto solo se ejecute una vez }, [municipios, selectedMunicipio]); // Se ejecuta cuando 'municipios' o 'selectedMunicipio' cambian
// Query para obtener los resultados de la sección seleccionada // 4. Transformamos los datos para react-select
const { data: resultados, isLoading } = useQuery<ResultadoTicker[]>({ const municipioOptions = useMemo(() =>
queryKey: ['resultadosConcejales', seccionActualId], municipios
queryFn: () => getResultadosConcejales(seccionActualId), .map(m => ({ value: m.id, label: m.nombre }))
enabled: !!seccionActualId, .sort((a, b) => a.label.localeCompare(b.label)), // Orden alfabético
[municipios]);
// 5. Query para obtener los resultados del MUNICIPIO seleccionado
const { data: resultados, isLoading: isLoadingResultados } = useQuery<ResultadoTicker[]>({
queryKey: ['resultadosConcejalesPorMunicipio', selectedMunicipio?.value],
queryFn: () => getResultadosConcejalesPorMunicipio(selectedMunicipio!.value),
enabled: !!selectedMunicipio,
}); });
// --- INICIO DE LA LÓGICA DE PROCESAMIENTO "OTROS" --- // 6. Lógica para "Otros" (sin cambios funcionales)
let displayResults: ResultadoTicker[] = resultados || []; let displayResults: ResultadoTicker[] = resultados || [];
if (resultados && resultados.length > cantidadAMostrar) { if (resultados && resultados.length > cantidadAMostrar) {
const topParties = resultados.slice(0, cantidadAMostrar - 1); const topParties = resultados.slice(0, cantidadAMostrar - 1);
const otherParties = resultados.slice(cantidadAMostrar - 1); const otherParties = resultados.slice(cantidadAMostrar - 1);
const otrosPorcentaje = otherParties.reduce((sum, party) => sum + party.votosPorcentaje, 0); const otrosPorcentaje = otherParties.reduce((sum, party) => sum + (party.porcentaje || 0), 0);
const otrosEntry: ResultadoTicker = { const otrosEntry: ResultadoTicker = {
id: `otros-concejales-${seccionActualId}`, id: `otros-concejales-${selectedMunicipio?.value}`,
nombre: 'Otros', nombre: 'Otros',
nombreCorto: 'Otros', nombreCorto: 'Otros',
color: '#888888', color: '#888888',
logoUrl: null, logoUrl: null,
votos: 0, // No es relevante para la visualización del porcentaje votos: 0,
votosPorcentaje: otrosPorcentaje, porcentaje: otrosPorcentaje,
}; };
displayResults = [...topParties, otrosEntry]; displayResults = [...topParties, otrosEntry];
} else if (resultados) { } else if (resultados) {
displayResults = resultados.slice(0, cantidadAMostrar); displayResults = resultados.slice(0, cantidadAMostrar);
} }
// --- FIN DE LA LÓGICA DE PROCESAMIENTO "OTROS" ---
return ( return (
<div className="ticker-card" style={{ gridColumn: '1 / -1' }}> <div className="ticker-card" style={{ gridColumn: '1 / -1' }}>
<div className="ticker-header"> <div className="ticker-header">
<h3>CONCEJALES POR SECCIÓN ELECTORAL</h3> <h3>CONCEJALES POR MUNICIPIO</h3>
<select value={seccionActualId} onChange={e => setSeccionActualId(e.target.value)} disabled={secciones.length === 0}> <Select
{secciones.map(s => <option key={s.id} value={s.id}>{s.nombre}</option>)} options={municipioOptions}
</select> value={selectedMunicipio}
onChange={(option) => setSelectedMunicipio(option)}
isLoading={isLoadingMunicipios}
placeholder="Buscar y seleccionar un municipio..."
styles={customSelectStyles}
/>
</div> </div>
<div className="ticker-results"> <div className="ticker-results">
{isLoading ? <p>Cargando...</p> : {(isLoadingMunicipios || (isLoadingResultados && selectedMunicipio)) && <p>Cargando...</p>}
displayResults.map(partido => ( {!selectedMunicipio && !isLoadingMunicipios && <p style={{textAlign: 'center', color: '#666'}}>Seleccione un municipio.</p>}
{displayResults.map(partido => (
<div key={partido.id} className="ticker-party"> <div key={partido.id} className="ticker-party">
<div className="party-logo"> <div className="party-logo">
<ImageWithFallback src={partido.logoUrl || undefined} fallbackSrc="/default-avatar.png" alt={`Logo de ${partido.nombre}`} /> <ImageWithFallback src={partido.logoUrl || undefined} fallbackSrc="/default-avatar.png" alt={`Logo de ${partido.nombre}`} />
@@ -90,15 +106,14 @@ export const ConcejalesWidget = () => {
<div className="party-details"> <div className="party-details">
<div className="party-info"> <div className="party-info">
<span className="party-name">{partido.nombreCorto || partido.nombre}</span> <span className="party-name">{partido.nombreCorto || partido.nombre}</span>
<span className="party-percent">{formatPercent(partido.votosPorcentaje)}</span> <span className="party-percent">{formatPercent(partido.porcentaje)}</span>
</div> </div>
<div className="party-bar-background"> <div className="party-bar-background">
<div className="party-bar-foreground" style={{ width: `${partido.votosPorcentaje}%`, backgroundColor: partido.color || '#888' }}></div> <div className="party-bar-foreground" style={{ width: `${partido.porcentaje}%`, backgroundColor: partido.color || '#888' }}></div>
</div> </div>
</div> </div>
</div> </div>
)) ))}
}
</div> </div>
</div> </div>
); );

View File

@@ -23,7 +23,7 @@ interface ResultadoDetalladoMunicipio {
ultimaActualizacion: string; ultimaActualizacion: string;
porcentajeEscrutado: number; porcentajeEscrutado: number;
porcentajeParticipacion: number; porcentajeParticipacion: number;
resultados: { id: string; nombre: string; votos: number; porcentaje: number }[]; resultados: { id: string; nombre: string; votos: number; porcentaje: number; color: string | null; }[];
votosAdicionales: { enBlanco: number; nulos: number; recurridos: number }; votosAdicionales: { enBlanco: number; nulos: number; recurridos: number };
} }
@@ -275,18 +275,24 @@ const DetalleMunicipio = ({ ambitoId, onReset, categoriaId }: { ambitoId: number
<button className="reset-button-panel" onClick={onReset}> VOLVER</button> <button className="reset-button-panel" onClick={onReset}> VOLVER</button>
<h3>{data?.municipioNombre}</h3> <h3>{data?.municipioNombre}</h3>
<div className="detalle-metricas"> <div className="detalle-metricas">
<span><strong>Escrutado:</strong> {data?.porcentajeEscrutado.toFixed(2)}%</span> <span><strong>Escrutado:</strong> {(data?.porcentajeEscrutado ?? 0).toFixed(2)}%</span>
<span><strong>Participación:</strong> {data?.porcentajeParticipacion.toFixed(2)}%</span> <span><strong>Participación:</strong> {(data?.porcentajeParticipacion ?? 0).toFixed(2)}%</span>
</div> </div>
<ul className="resultados-lista"> <ul className="resultados-lista">
{data?.resultados.map((r, index) => ( {(data?.resultados ?? []).map((r, index) => (
<li key={`${r.nombre}-${index}`}> <li key={`${r.nombre}-${index}`}>
<div className="resultado-info"> <div className="resultado-info">
<span className="partido-nombre">{r.nombre}</span> <span className="partido-nombre">{r.nombre}</span>
<span className="partido-votos">{r.votos.toLocaleString('es-AR')} ({r.porcentaje.toFixed(2)}%)</span> <span className="partido-votos">{r.votos.toLocaleString('es-AR')} ({r.porcentaje.toFixed(2)}%)</span>
</div> </div>
<div className="progress-bar"> <div className="progress-bar">
<div className="progress-fill" style={{ width: `${r.porcentaje}%` }}></div> <div
className="progress-fill"
style={{
width: `${r.porcentaje}%`,
backgroundColor: r.color || DEFAULT_MAP_COLOR
}}
></div>
</div> </div>
</li> </li>
))} ))}

View File

@@ -22,7 +22,7 @@ export const TickerWidget = () => {
}); });
const cantidadAMostrar = useMemo(() => { const cantidadAMostrar = useMemo(() => {
return parseInt(configData?.TickerResultadosCantidad || '5', 10) + 1; return parseInt(configData?.TickerResultadosCantidad || '5', 10);
}, [configData]); }, [configData]);
if (isLoading) return <div className="ticker-wrapper loading">Cargando resumen...</div>; if (isLoading) return <div className="ticker-wrapper loading">Cargando resumen...</div>;
@@ -39,7 +39,7 @@ export const TickerWidget = () => {
if (categoria.resultados.length > cantidadAMostrar) { if (categoria.resultados.length > cantidadAMostrar) {
const topParties = categoria.resultados.slice(0, cantidadAMostrar - 1); const topParties = categoria.resultados.slice(0, cantidadAMostrar - 1);
const otherParties = categoria.resultados.slice(cantidadAMostrar - 1); const otherParties = categoria.resultados.slice(cantidadAMostrar - 1);
const otrosPorcentaje = otherParties.reduce((sum, party) => sum + party.votosPorcentaje, 0); const otrosPorcentaje = otherParties.reduce((sum, party) => sum + party.porcentaje, 0);
const otrosEntry: ResultadoTicker = { const otrosEntry: ResultadoTicker = {
id: `otros-${categoria.categoriaId}`, id: `otros-${categoria.categoriaId}`,
@@ -48,7 +48,7 @@ export const TickerWidget = () => {
color: '#888888', color: '#888888',
logoUrl: null, logoUrl: null,
votos: 0, votos: 0,
votosPorcentaje: otrosPorcentaje, porcentaje: otrosPorcentaje,
}; };
displayResults = [...topParties, otrosEntry]; displayResults = [...topParties, otrosEntry];
@@ -78,10 +78,10 @@ export const TickerWidget = () => {
<div className="party-details"> <div className="party-details">
<div className="party-info"> <div className="party-info">
<span className="party-name">{partido.nombreCorto || partido.nombre}</span> <span className="party-name">{partido.nombreCorto || partido.nombre}</span>
<span className="party-percent">{formatPercent(partido.votosPorcentaje)}</span> <span className="party-percent">{formatPercent(partido.porcentaje)}</span>
</div> </div>
<div className="party-bar-background"> <div className="party-bar-background">
<div className="party-bar-foreground" style={{ width: `${partido.votosPorcentaje}%`, backgroundColor: partido.color || '#888' }}></div> <div className="party-bar-foreground" style={{ width: `${partido.porcentaje}%`, backgroundColor: partido.color || '#888' }}></div>
</div> </div>
</div> </div>
</div> </div>

View File

@@ -48,7 +48,7 @@ export interface ResultadoTicker {
color: string | null; color: string | null;
logoUrl: string | null; logoUrl: string | null;
votos: number; votos: number;
votosPorcentaje: number; porcentaje: number;
} }
export interface EstadoRecuentoTicker { export interface EstadoRecuentoTicker {

View File

@@ -22,13 +22,11 @@ public class ResultadosController : ControllerBase
_configuration = configuration; _configuration = configuration;
} }
[HttpGet("partido/{seccionId}")] [HttpGet("partido/{seccionId}")] // 'seccionId' es el ID del municipio
public async Task<IActionResult> GetResultadosPorPartido(string seccionId) public async Task<IActionResult> GetResultadosPorPartido(string seccionId)
{ {
// 1. Buscamos el ámbito geográfico correspondiente al PARTIDO (Nivel 30)
var ambito = await _dbContext.AmbitosGeograficos var ambito = await _dbContext.AmbitosGeograficos
.AsNoTracking() .AsNoTracking()
// CAMBIO CLAVE: Buscamos por SeccionId y NivelId para ser precisos
.FirstOrDefaultAsync(a => a.SeccionId == seccionId && a.NivelId == 30); .FirstOrDefaultAsync(a => a.SeccionId == seccionId && a.NivelId == 30);
if (ambito == null) if (ambito == null)
@@ -36,14 +34,12 @@ public class ResultadosController : ControllerBase
return NotFound(new { message = $"No se encontró el partido con ID {seccionId}" }); return NotFound(new { message = $"No se encontró el partido con ID {seccionId}" });
} }
// 2. Buscamos el estado del recuento para ese ámbito
var estadoRecuento = await _dbContext.EstadosRecuentos var estadoRecuento = await _dbContext.EstadosRecuentos
.AsNoTracking() .AsNoTracking()
.FirstOrDefaultAsync(e => e.AmbitoGeograficoId == ambito.Id); .FirstOrDefaultAsync(e => e.AmbitoGeograficoId == ambito.Id);
if (estadoRecuento == null) if (estadoRecuento == null)
{ {
// Devolvemos una respuesta vacía pero válida para el frontend
return Ok(new MunicipioResultadosDto return Ok(new MunicipioResultadosDto
{ {
MunicipioNombre = ambito.Nombre, MunicipioNombre = ambito.Nombre,
@@ -55,28 +51,57 @@ public class ResultadosController : ControllerBase
}); });
} }
// 3. Buscamos todos los votos para ese ámbito // 1. Obtenemos los IDs de las agrupaciones que tienen resultados en este municipio
var agrupacionIds = await _dbContext.ResultadosVotos
.Where(rv => rv.AmbitoGeograficoId == ambito.Id)
.Select(rv => rv.AgrupacionPoliticaId)
.Distinct()
.ToListAsync();
// 2. Buscamos TODOS los logos relevantes en una sola consulta:
// - Los que son para la categoría Concejales (7)
// - Y pertenecen a los partidos que compiten aquí
// - Y son genéricos (sin ámbito) O específicos para ESTE municipio
var logosRelevantes = await _dbContext.LogosAgrupacionesCategorias
.AsNoTracking()
.Where(l => l.CategoriaId == 7 &&
agrupacionIds.Contains(l.AgrupacionPoliticaId) &&
(l.AmbitoGeograficoId == null || l.AmbitoGeograficoId == ambito.Id))
.ToListAsync();
var resultadosVotos = await _dbContext.ResultadosVotos var resultadosVotos = await _dbContext.ResultadosVotos
.AsNoTracking() .AsNoTracking()
.Include(rv => rv.AgrupacionPolitica) .Include(rv => rv.AgrupacionPolitica)
.Where(rv => rv.AmbitoGeograficoId == ambito.Id) .Where(rv => rv.AmbitoGeograficoId == ambito.Id)
.ToListAsync(); .ToListAsync();
// 4. Calculamos el total de votos positivos
long totalVotosPositivos = resultadosVotos.Sum(r => r.CantidadVotos); long totalVotosPositivos = resultadosVotos.Sum(r => r.CantidadVotos);
// 5. Mapeamos al DTO de respuesta
var respuestaDto = new MunicipioResultadosDto var respuestaDto = new MunicipioResultadosDto
{ {
MunicipioNombre = ambito.Nombre, MunicipioNombre = ambito.Nombre,
UltimaActualizacion = estadoRecuento.FechaTotalizacion, UltimaActualizacion = estadoRecuento.FechaTotalizacion,
PorcentajeEscrutado = estadoRecuento.MesasTotalizadasPorcentaje, PorcentajeEscrutado = estadoRecuento.MesasTotalizadasPorcentaje,
PorcentajeParticipacion = estadoRecuento.ParticipacionPorcentaje, PorcentajeParticipacion = estadoRecuento.ParticipacionPorcentaje,
Resultados = resultadosVotos.Select(rv => new AgrupacionResultadoDto Resultados = resultadosVotos.Select(rv =>
{ {
// --- LÓGICA DE FALLBACK ---
var logoUrl =
// 1. Buscamos primero el logo específico para este municipio.
logosRelevantes.FirstOrDefault(l => l.AgrupacionPoliticaId == rv.AgrupacionPoliticaId && l.AmbitoGeograficoId == ambito.Id)?.LogoUrl
// 2. Si no lo encontramos, buscamos el logo genérico (sin ámbito).
?? logosRelevantes.FirstOrDefault(l => l.AgrupacionPoliticaId == rv.AgrupacionPoliticaId && l.AmbitoGeograficoId == null)?.LogoUrl;
return new AgrupacionResultadoDto
{
Id = rv.AgrupacionPolitica.Id,
Nombre = rv.AgrupacionPolitica.Nombre, Nombre = rv.AgrupacionPolitica.Nombre,
NombreCorto = rv.AgrupacionPolitica.NombreCorto,
Color = rv.AgrupacionPolitica.Color,
LogoUrl = logoUrl, // Asignamos el logo encontrado
Votos = rv.CantidadVotos, Votos = rv.CantidadVotos,
Porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos * 100.0m / totalVotosPositivos) : 0 Porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos * 100.0m / totalVotosPositivos) : 0
};
}).OrderByDescending(r => r.Votos).ToList(), }).OrderByDescending(r => r.Votos).ToList(),
VotosAdicionales = new VotosAdicionalesDto VotosAdicionales = new VotosAdicionalesDto
{ {
@@ -95,15 +120,10 @@ public class ResultadosController : ControllerBase
var provincia = await _dbContext.AmbitosGeograficos.AsNoTracking() var provincia = await _dbContext.AmbitosGeograficos.AsNoTracking()
.FirstOrDefaultAsync(a => a.DistritoId == distritoId && a.NivelId == 10); .FirstOrDefaultAsync(a => a.DistritoId == distritoId && a.NivelId == 10);
var todosLosResumenes = await _dbContext.ResumenesVotos.AsNoTracking() if (provincia == null)
.Include(r => r.AgrupacionPolitica) {
.ToListAsync(); return NotFound($"No se encontró la provincia con distritoId {distritoId}");
}
// OBTENER TODOS LOS LOGOS EN UNA SOLA CONSULTA
var logosLookup = (await _dbContext.LogosAgrupacionesCategorias.AsNoTracking().ToListAsync())
.ToLookup(l => $"{l.AgrupacionPoliticaId}-{l.CategoriaId}");
if (provincia == null) return NotFound($"No se encontró la provincia con distritoId {distritoId}");
var estadosPorCategoria = await _dbContext.EstadosRecuentosGenerales.AsNoTracking() var estadosPorCategoria = await _dbContext.EstadosRecuentosGenerales.AsNoTracking()
.Include(e => e.CategoriaElectoral) .Include(e => e.CategoriaElectoral)
@@ -113,43 +133,50 @@ public class ResultadosController : ControllerBase
var resultadosPorMunicipio = await _dbContext.ResultadosVotos var resultadosPorMunicipio = await _dbContext.ResultadosVotos
.AsNoTracking() .AsNoTracking()
.Include(r => r.AgrupacionPolitica) .Include(r => r.AgrupacionPolitica)
.Where(r => r.AmbitoGeografico.NivelId == 30) .Where(r => r.AmbitoGeografico.NivelId == 30) // Nivel 30 = Municipio
.ToListAsync(); .ToListAsync();
var logos = await _dbContext.LogosAgrupacionesCategorias.AsNoTracking().ToListAsync();
var resultadosAgrupados = resultadosPorMunicipio var resultadosAgrupados = resultadosPorMunicipio
.GroupBy(r => r.CategoriaId) .GroupBy(r => r.CategoriaId)
.Select(g => new .Select(g => new
{ {
CategoriaId = g.Key, CategoriaId = g.Key,
CategoriaNombre = estadosPorCategoria.ContainsKey(g.Key) ? estadosPorCategoria[g.Key].CategoriaElectoral.Nombre : "Desconocido",
EstadoRecuento = estadosPorCategoria.GetValueOrDefault(g.Key),
TotalVotosCategoria = g.Sum(r => r.CantidadVotos), TotalVotosCategoria = g.Sum(r => r.CantidadVotos),
// Agrupamos por el ID de la agrupación, no por el objeto Resultados = g
Resultados = g.GroupBy(r => r.AgrupacionPoliticaId) .GroupBy(r => r.AgrupacionPolitica)
.Select(partidoGroup => new .Select(partidoGroup => new
{ {
// El objeto Agrupacion lo tomamos del primer elemento del grupo Agrupacion = partidoGroup.Key,
Agrupacion = partidoGroup.First().AgrupacionPolitica,
Votos = partidoGroup.Sum(r => r.CantidadVotos) Votos = partidoGroup.Sum(r => r.CantidadVotos)
}) })
.OrderByDescending(r => r.Votos)
.ToList() .ToList()
}) })
.Select(g => new .Select(g => new
{ {
g.CategoriaId, g.CategoriaId,
CategoriaNombre = estadosPorCategoria.ContainsKey(g.CategoriaId) ? estadosPorCategoria[g.CategoriaId].CategoriaElectoral.Nombre : "Desconocido", g.CategoriaNombre,
EstadoRecuento = estadosPorCategoria.GetValueOrDefault(g.CategoriaId), g.EstadoRecuento,
Resultados = g.Resultados Resultados = g.Resultados.Select(r =>
.Select(r => new
{ {
r.Agrupacion.Id, var logoUrl = logos.FirstOrDefault(l => l.AgrupacionPoliticaId == r.Agrupacion.Id && l.CategoriaId == g.CategoriaId && l.AmbitoGeograficoId != null)?.LogoUrl
?? logos.FirstOrDefault(l => l.AgrupacionPoliticaId == r.Agrupacion.Id && l.CategoriaId == g.CategoriaId && l.AmbitoGeograficoId == null)?.LogoUrl;
return new
{
Id = r.Agrupacion.Id,
r.Agrupacion.Nombre, r.Agrupacion.Nombre,
r.Agrupacion.NombreCorto, r.Agrupacion.NombreCorto,
r.Agrupacion.Color, r.Agrupacion.Color,
LogoUrl = logosLookup[$"{r.Agrupacion.Id}-{g.CategoriaId}"].FirstOrDefault()?.LogoUrl, LogoUrl = logoUrl,
r.Votos, r.Votos,
VotosPorcentaje = g.TotalVotosCategoria > 0 ? ((decimal)r.Votos * 100 / g.TotalVotosCategoria) : 0 Porcentaje = g.TotalVotosCategoria > 0 ? ((decimal)r.Votos * 100 / g.TotalVotosCategoria) : 0
}) };
.OrderByDescending(r => r.Votos) }).ToList()
.ToList()
}) })
.OrderBy(c => c.CategoriaId) .OrderBy(c => c.CategoriaId)
.ToList(); .ToList();
@@ -238,10 +265,21 @@ public class ResultadosController : ControllerBase
[HttpGet("municipio/{ambitoId}")] [HttpGet("municipio/{ambitoId}")]
public async Task<IActionResult> GetResultadosPorMunicipio(int ambitoId, [FromQuery] int categoriaId) public async Task<IActionResult> GetResultadosPorMunicipio(int ambitoId, [FromQuery] int categoriaId)
{ {
_logger.LogInformation("Buscando resultados para AmbitoGeograficoId: {AmbitoId}, CategoriaId: {CategoriaId}", ambitoId, categoriaId);
// Validamos que el ámbito exista // Validamos que el ámbito exista
var ambito = await _dbContext.AmbitosGeograficos.AsNoTracking() var ambito = await _dbContext.AmbitosGeograficos.AsNoTracking()
.FirstOrDefaultAsync(a => a.Id == ambitoId && a.NivelId == 30); .FirstOrDefaultAsync(a => a.Id == ambitoId && a.NivelId == 30);
if (ambito == null) return NotFound($"No se encontró el municipio con ID {ambitoId}"); if (ambito == null)
{
_logger.LogWarning("No se encontró el municipio con ID: {AmbitoId}", ambitoId);
return NotFound($"No se encontró el municipio con ID {ambitoId}");
}
// Obtenemos el estado del recuento para el ámbito
var estadoRecuento = await _dbContext.EstadosRecuentos
.AsNoTracking()
.FirstOrDefaultAsync(e => e.AmbitoGeograficoId == ambito.Id);
// Obtenemos los votos para ESE municipio y ESA categoría // Obtenemos los votos para ESE municipio y ESA categoría
var resultadosVotos = await _dbContext.ResultadosVotos var resultadosVotos = await _dbContext.ResultadosVotos
@@ -253,18 +291,35 @@ public class ResultadosController : ControllerBase
// Calculamos el total de votos solo para esta selección // Calculamos el total de votos solo para esta selección
var totalVotosPositivos = (decimal)resultadosVotos.Sum(r => r.CantidadVotos); var totalVotosPositivos = (decimal)resultadosVotos.Sum(r => r.CantidadVotos);
// Mapeamos a la respuesta final que espera el frontend // Mapeamos los resultados de los partidos
var respuesta = resultadosVotos var resultadosPartidosDto = resultadosVotos
.OrderByDescending(r => r.CantidadVotos) .OrderByDescending(r => r.CantidadVotos)
.Select(rv => new .Select(rv => new AgrupacionResultadoDto // Assuming AgrupacionResultadoDto is the correct DTO for individual party results
{ {
id = rv.AgrupacionPolitica.Id, Id = rv.AgrupacionPolitica.Id,
nombre = rv.AgrupacionPolitica.NombreCorto ?? rv.AgrupacionPolitica.Nombre, Nombre = rv.AgrupacionPolitica.NombreCorto ?? rv.AgrupacionPolitica.Nombre,
votos = rv.CantidadVotos, Color = rv.AgrupacionPolitica.Color,
porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos / totalVotosPositivos) * 100 : 0 Votos = rv.CantidadVotos,
Porcentaje = totalVotosPositivos > 0 ? (rv.CantidadVotos / totalVotosPositivos) * 100 : 0
}).ToList(); }).ToList();
return Ok(respuesta); // Construimos la respuesta completa del DTO
var respuestaDto = new MunicipioResultadosDto
{
MunicipioNombre = ambito.Nombre,
UltimaActualizacion = estadoRecuento?.FechaTotalizacion ?? DateTime.UtcNow, // Use null-conditional operator
PorcentajeEscrutado = estadoRecuento?.MesasTotalizadasPorcentaje ?? 0,
PorcentajeParticipacion = estadoRecuento?.ParticipacionPorcentaje ?? 0,
Resultados = resultadosPartidosDto,
VotosAdicionales = new VotosAdicionalesDto // Assuming default constructor is fine
{
EnBlanco = estadoRecuento?.VotosEnBlanco ?? 0,
Nulos = estadoRecuento?.VotosNulos ?? 0,
Recurridos = estadoRecuento?.VotosRecurridos ?? 0
}
};
return Ok(respuestaDto);
} }
[HttpGet("composicion-congreso")] [HttpGet("composicion-congreso")]
@@ -616,12 +671,13 @@ public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccio
.ToListAsync(); .ToListAsync();
var totalVotosSeccion = (decimal)resultadosMunicipales.Sum(r => r.CantidadVotos); var totalVotosSeccion = (decimal)resultadosMunicipales.Sum(r => r.CantidadVotos);
var resultadosFinales = resultadosMunicipales var resultadosFinales = resultadosMunicipales
// 1. Agrupamos por el ID del partido, que es un valor único y estable // 1. Agrupamos por el ID del partido para evitar duplicados.
.GroupBy(r => r.AgrupacionPoliticaId) .GroupBy(r => r.AgrupacionPoliticaId)
.Select(g => new .Select(g => new
{ {
// 2. Obtenemos el objeto Agrupacion del primer elemento del grupo // 2. Tomamos la entidad completa del primer elemento del grupo.
Agrupacion = g.First().AgrupacionPolitica, Agrupacion = g.First().AgrupacionPolitica,
Votos = g.Sum(r => r.CantidadVotos) Votos = g.Sum(r => r.CantidadVotos)
}) })
@@ -631,7 +687,9 @@ public async Task<IActionResult> GetResultadosConcejalesPorSeccion(string seccio
id = r.Agrupacion.Id, id = r.Agrupacion.Id,
nombre = r.Agrupacion.NombreCorto ?? r.Agrupacion.Nombre, nombre = r.Agrupacion.NombreCorto ?? r.Agrupacion.Nombre,
votos = r.Votos, votos = r.Votos,
porcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0 porcentaje = totalVotosSeccion > 0 ? ((decimal)r.Votos * 100 / totalVotosSeccion) : 0,
// 3. Añadimos el color a la respuesta.
color = r.Agrupacion.Color
}) })
.ToList(); .ToList();

View File

@@ -1,6 +1,5 @@
@Elecciones.Api_HostAddress = http://localhost:5217 @Elecciones.Api_HostAddress = http://localhost:5217
GET {{Elecciones.Api_HostAddress}}/weatherforecast/
Accept: application/json Accept: application/json
### ###

View File

@@ -14,7 +14,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Api")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+12860f24067a7de29ec937e18f314f2f24059f47")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+271a86b63211dff88fb7188d1db7b390e6c53efb")]
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Api")]
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Api")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","eeoSVF\u002BzWQgGKOM9hSCzmc0CNSUCyP/f6aJxLHiJ4A8=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","nt6JdXgYN0sYJ/7di0B2aSGDokBPJnFqtwyBcMkycYI="],"CachedAssets":{},"CachedCopyCandidates":{}} {"GlobalPropertiesHash":"b5T/+ta4fUd8qpIzUTm3KyEwAYYUsU5ASo+CSFM3ByE=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","PmrFmFQepAv9NhtsO0l45PPk3BWugccwJ3ysTKcw7bM=","6CAjHexjcmVc1caYyfNvMfhJRU6qtmi57Siv1ysirg0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","\u002BgTea2HWyPcSQvQyVe0ghcDwqBGkKZIDd2\u002BlGKdxL2U="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -1 +1 @@
{"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","ywKm3DCyXg4YCbZAIx3JUlT8N4Irff3GswYUVDST\u002BjQ=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","eeoSVF\u002BzWQgGKOM9hSCzmc0CNSUCyP/f6aJxLHiJ4A8=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","nt6JdXgYN0sYJ/7di0B2aSGDokBPJnFqtwyBcMkycYI="],"CachedAssets":{},"CachedCopyCandidates":{}} {"GlobalPropertiesHash":"tJTBjV/i0Ihkc6XuOu69wxL8PBac9c9Kak6srMso4pU=","FingerprintPatternsHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","PropertyOverridesHash":"8ZRc1sGeVrPBx4lD717BgRaQekyh78QKV9SKsdt638U=","InputHashes":["BNGxWTPjjFD1Fj56FltRDUvsBzgMlQvuqV\u002BraH2IhwQ=","t631p0kaOa0gMRIcaPzz1ZVPZ1kuq4pq4kYPWQgoPcM=","PA/Beu9jJpOBY5r5Y1CiSyqrARA2j7LHeWYUnEZpQO8=","E2ODTAlJxzsXY1iP1eB/02NIUK\u002BnQveGlWAOHY1cpgA=","6WTvWQ72AaZBYOVSmaxaci9tc1dW5p7IK9Kscjj2cb0=","vAy46VJ9Gp8QqG/Px4J1mj8jL6ws4/A01UKRmMYfYek=","cdgbHR/E4DJsddPc\u002BTpzoUMOVNaFJZm33Pw7AxU9Ees=","4r4JGR4hS5m4rsLfuCSZxzrknTBxKFkLQDXc\u002B2KbqTU=","yVoZ4UnBcSOapsJIi046hnn7ylD3jAcEBUxQ\u002Brkvj/4=","/GfbpJthEWmsuz0uFx1QLHM7gyM1wLLeQgAIl4SzUD4=","i5\u002B5LcfxQD8meRAkQbVf4wMvjxSE4\u002BjCd2/FdPtMpms=","AvSkxVPIg0GjnB1RJ4hDNyo9p9GONrzDs8uVuixH\u002BOE=","IgT9pOgRnK37qfILj2QcjFoBZ180HMt\u002BScgje2iYOo4=","ezUlOMzNZmyKDIe1wwXqvX\u002BvhwfB992xNVts7r2zcTc=","y2BV4WpkQuLfqQhfOQBtmuzh940c3s4LAopGKfztfTE=","lHTUEsMkDu8nqXtfTwl7FRfgocyyc7RI5O/edTHN1\u002B0=","A7nz7qgOtQ1CwZZLvNnr0b5QZB3fTi3y4i6y7rBIcxQ=","znnuRi2tsk7AACuYo4WSgj7NcLriG4PKVaF4L35SvDk=","GelE32odx/vTului267wqi6zL3abBnF9yvwC2Q66LoM=","PmrFmFQepAv9NhtsO0l45PPk3BWugccwJ3ysTKcw7bM=","6CAjHexjcmVc1caYyfNvMfhJRU6qtmi57Siv1ysirg0=","P8JRhYPpULTLMAydvl3Ky\u002B92/tYDIjui0l66En4aXuQ=","\u002BgTea2HWyPcSQvQyVe0ghcDwqBGkKZIDd2\u002BlGKdxL2U="],"CachedAssets":{},"CachedCopyCandidates":{}}

View File

@@ -3,7 +3,11 @@ namespace Elecciones.Core.DTOs.ApiResponses;
public class AgrupacionResultadoDto public class AgrupacionResultadoDto
{ {
public required string? Id { get; set; }
public string Nombre { get; set; } = null!; public string Nombre { get; set; } = null!;
public string? NombreCorto { get; set; } = null!;
public string? Color { get; set; } = null!;
public string? LogoUrl { get; set; } = null!;
public long Votos { get; set; } public long Votos { get; set; }
public decimal Porcentaje { get; set; } public decimal Porcentaje { get; set; }
} }

View File

@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Core")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+12860f24067a7de29ec937e18f314f2f24059f47")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+271a86b63211dff88fb7188d1db7b390e6c53efb")]
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Core")]
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Core")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Database")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+12860f24067a7de29ec937e18f314f2f24059f47")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+271a86b63211dff88fb7188d1db7b390e6c53efb")]
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Database")]
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Database")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]

View File

@@ -13,7 +13,7 @@ using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyCompanyAttribute("Elecciones.Infrastructure")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")] [assembly: System.Reflection.AssemblyConfigurationAttribute("Debug")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyFileVersionAttribute("1.0.0.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+12860f24067a7de29ec937e18f314f2f24059f47")] [assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.0.0+271a86b63211dff88fb7188d1db7b390e6c53efb")]
[assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyProductAttribute("Elecciones.Infrastructure")]
[assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")] [assembly: System.Reflection.AssemblyTitleAttribute("Elecciones.Infrastructure")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")] [assembly: System.Reflection.AssemblyVersionAttribute("1.0.0.0")]