diff --git a/backend/app/Http/Controllers/Api/TransactionController.php b/backend/app/Http/Controllers/Api/TransactionController.php index 39a3bcf..59671ea 100755 --- a/backend/app/Http/Controllers/Api/TransactionController.php +++ b/backend/app/Http/Controllers/Api/TransactionController.php @@ -25,7 +25,11 @@ public function index(Request $request): JsonResponse } if ($request->has('category_id')) { - $query->ofCategory($request->category_id); + if ($request->category_id === 'uncategorized') { + $query->whereNull('category_id'); + } else { + $query->ofCategory($request->category_id); + } } if ($request->has('cost_center_id')) { @@ -409,7 +413,11 @@ public function byWeek(Request $request): JsonResponse } if ($request->has('category_id')) { - $query->ofCategory($request->category_id); + if ($request->category_id === 'uncategorized') { + $query->whereNull('category_id'); + } else { + $query->ofCategory($request->category_id); + } } if ($request->has('cost_center_id')) { diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 1dfa57b..24fad39 100755 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -61,7 +61,6 @@ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.28.5.tgz", "integrity": "sha512-e7jT4DxYvIDLk1ZHmU/m/mB19rex9sv0c2ftBtjSBv+kVM/902eh0fINUzD7UwLLNR+jU585GxUJ8/EBfAM5fw==", "dev": true, - "peer": true, "dependencies": { "@babel/code-frame": "^7.27.1", "@babel/generator": "^7.28.5", @@ -918,7 +917,6 @@ "resolved": "https://registry.npmjs.org/@types/react/-/react-19.2.7.tgz", "integrity": "sha512-MWtvHrGZLFttgeEj28VXHxpmwYbor/ATPYbBfSFZEIRK0ecCFLl2Qo55z52Hss+UV9CRN7trSeq1zbgx7YDWWg==", "dev": true, - "peer": true, "dependencies": { "csstype": "^3.2.2" } @@ -957,7 +955,6 @@ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", "dev": true, - "peer": true, "bin": { "acorn": "bin/acorn" }, @@ -1111,7 +1108,6 @@ "url": "https://github.com/sponsors/ai" } ], - "peer": true, "dependencies": { "baseline-browser-mapping": "^2.9.0", "caniuse-lite": "^1.0.30001759", @@ -1187,7 +1183,6 @@ "version": "4.5.1", "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.5.1.tgz", "integrity": "sha512-GIjfiT9dbmHRiYi6Nl2yFCq7kkwdkp1W/lp2J99rX0yo9tgJGn3lKQATztIjb5tVtevcBtIdICNWqlq5+E8/Pw==", - "peer": true, "dependencies": { "@kurkle/color": "^0.3.0" }, @@ -1394,7 +1389,6 @@ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.1.tgz", "integrity": "sha512-BhHmn2yNOFA9H9JmmIVKJmd288g9hrVRDkdoIgRCRuSySRUHH7r/DI6aAXW9T1WwUuY3DFgrcaqB+deURBLR5g==", "dev": true, - "peer": true, "dependencies": { "@eslint-community/eslint-utils": "^4.8.0", "@eslint-community/regexpp": "^4.12.1", @@ -1878,7 +1872,6 @@ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project" } ], - "peer": true, "dependencies": { "@babel/runtime": "^7.28.4" }, @@ -2502,7 +2495,6 @@ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", "dev": true, - "peer": true, "engines": { "node": ">=12" }, @@ -2575,7 +2567,6 @@ "version": "19.2.1", "resolved": "https://registry.npmjs.org/react/-/react-19.2.1.tgz", "integrity": "sha512-DGrYcCWK7tvYMnWh79yrPHt+vdx9tY+1gPZa7nJQtO/p8bLTDaHp4dzwEhQB7pZ4Xe3ok4XKuEPrVuc+wlpkmw==", - "peer": true, "engines": { "node": ">=0.10.0" } @@ -2593,7 +2584,6 @@ "version": "19.2.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.2.1.tgz", "integrity": "sha512-ibrK8llX2a4eOskq1mXKu/TGZj9qzomO+sNfO98M6d9zIPOEhlBkMkBUBLd1vgS0gQsLDBzA+8jJBVXDnfHmJg==", - "peer": true, "dependencies": { "scheduler": "^0.27.0" }, @@ -2899,7 +2889,6 @@ "resolved": "https://registry.npmjs.org/rolldown-vite/-/rolldown-vite-7.2.5.tgz", "integrity": "sha512-u09tdk/huMiN8xwoiBbig197jKdCamQTtOruSalOzbqGje3jdHiV0njQlAW0YvzoahkirFePNQ4RYlfnRQpXZA==", "dev": true, - "peer": true, "dependencies": { "@oxc-project/runtime": "0.97.0", "fdir": "^6.5.0", @@ -3025,7 +3014,6 @@ "resolved": "https://registry.npmjs.org/zod/-/zod-4.1.13.tgz", "integrity": "sha512-AvvthqfqrAhNH9dnfmrfKzX5upOdjUVJYFqNSlkmGf64gRaTzlPwz99IHYnVs28qYAybvAlBV+H7pn0saFY4Ig==", "dev": true, - "peer": true, "funding": { "url": "https://github.com/sponsors/colinhacks" } diff --git a/frontend/src/components/CategorySelector.jsx b/frontend/src/components/CategorySelector.jsx index 9783aa8..7c5948f 100755 --- a/frontend/src/components/CategorySelector.jsx +++ b/frontend/src/components/CategorySelector.jsx @@ -18,7 +18,8 @@ export default function CategorySelector({ onChange, onAddNew, placeholder, - disabled = false + disabled = false, + showUncategorized = false }) { const { t } = useTranslation(); const [isOpen, setIsOpen] = useState(false); @@ -125,6 +126,7 @@ export default function CategorySelector({ // Obtener nombre completo de la categoría seleccionada const getSelectedCategoryName = () => { + if (value === 'uncategorized') return t('transactions.uncategorized'); const category = getCategoryById(value); if (!category) return placeholder || t('common.none'); @@ -262,6 +264,21 @@ export default function CategorySelector({ {t('common.none')} + {/* Opción "Sin categoría" para filtros */} + {showUncategorized && ( + <> + +
+ > + )} + {/* Lista de categorías */} diff --git a/frontend/src/pages/TransactionsByWeek.jsx b/frontend/src/pages/TransactionsByWeek.jsx index d4abc71..91851c2 100755 --- a/frontend/src/pages/TransactionsByWeek.jsx +++ b/frontend/src/pages/TransactionsByWeek.jsx @@ -1233,6 +1233,7 @@ export default function Transactions() { value={filters.category_id} onChange={handleFilterChange} placeholder={t('common.all')} + showUncategorized={true} />