feat: adicionar filtro 'Sem Categoria' nas transações
- Backend: suporte para category_id=uncategorized nos endpoints index e byWeek - Frontend: opção 'Sem Categoria' no CategorySelector com prop showUncategorized - Permite filtrar 525 transações importadas que ainda não foram categorizadas
This commit is contained in:
parent
54cccdd095
commit
f2e032f002
@ -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')) {
|
||||
|
||||
12
frontend/package-lock.json
generated
12
frontend/package-lock.json
generated
@ -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"
|
||||
}
|
||||
|
||||
@ -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({
|
||||
<span className="text-muted">{t('common.none')}</span>
|
||||
</button>
|
||||
|
||||
{/* Opción "Sin categoría" para filtros */}
|
||||
{showUncategorized && (
|
||||
<>
|
||||
<button
|
||||
type="button"
|
||||
className={`dropdown-item ${value === 'uncategorized' ? 'active' : ''}`}
|
||||
onClick={(e) => handleSelect('uncategorized', e)}
|
||||
>
|
||||
<i className="bi bi-question-circle text-warning me-2"></i>
|
||||
<span>{t('transactions.uncategorized')}</span>
|
||||
</button>
|
||||
<div className="dropdown-divider my-1"></div>
|
||||
</>
|
||||
)}
|
||||
|
||||
<div className="dropdown-divider my-1"></div>
|
||||
|
||||
{/* Lista de categorías */}
|
||||
|
||||
@ -1233,6 +1233,7 @@ export default function Transactions() {
|
||||
value={filters.category_id}
|
||||
onChange={handleFilterChange}
|
||||
placeholder={t('common.all')}
|
||||
showUncategorized={true}
|
||||
/>
|
||||
</div>
|
||||
<div className="col-6 col-md-2">
|
||||
|
||||
Loading…
Reference in New Issue
Block a user