diff --git a/resources/js/components/transactions/bulk-actions-bar.tsx b/resources/js/components/transactions/bulk-actions-bar.tsx index e9d8e9bc..5085c941 100644 --- a/resources/js/components/transactions/bulk-actions-bar.tsx +++ b/resources/js/components/transactions/bulk-actions-bar.tsx @@ -1,8 +1,15 @@ import { BulkCategorySelect } from '@/components/transactions/bulk-category-select'; import { Button } from '@/components/ui/button'; import { ButtonGroup } from '@/components/ui/button-group'; +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuGroup, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/ui/dropdown-menu'; import { type Category } from '@/types/category'; -import { RefreshCw, Trash2, X } from 'lucide-react'; +import { MoreHorizontal, RefreshCw, Trash2, X } from 'lucide-react'; interface BulkActionsBarProps { selectedCount: number; @@ -30,7 +37,7 @@ export function BulkActionsBar({ return (
-
+
{selectedCount} transaction{selectedCount !== 1 ? 's' : ''}{' '} selected
@@ -42,29 +49,39 @@ export function BulkActionsBar({ onCategoryChange={onCategoryChange} disabled={isUpdating} /> - - - - + + + + + + - - + + + Re-evaluate rules + + + + + Delete + + + + diff --git a/resources/js/components/transactions/bulk-category-select.tsx b/resources/js/components/transactions/bulk-category-select.tsx index bf6208f7..45021459 100644 --- a/resources/js/components/transactions/bulk-category-select.tsx +++ b/resources/js/components/transactions/bulk-category-select.tsx @@ -1,14 +1,6 @@ +import { CategorySelect } from '@/components/transactions/category-select'; +import { type Category } from '@/types/category'; import { useState } from 'react'; -import { Badge } from '@/components/ui/badge'; -import * as Icons from 'lucide-react'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select'; -import { type Category, getCategoryColorClasses } from '@/types/category'; interface BulkCategorySelectProps { categories: Category[]; @@ -30,31 +22,14 @@ export function BulkCategorySelect({ } return ( - + ); } - diff --git a/resources/js/components/transactions/category-cell.tsx b/resources/js/components/transactions/category-cell.tsx index 821adac5..a766fd49 100644 --- a/resources/js/components/transactions/category-cell.tsx +++ b/resources/js/components/transactions/category-cell.tsx @@ -1,19 +1,11 @@ -import { useState } from 'react'; -import { Badge } from '@/components/ui/badge'; -import * as Icons from 'lucide-react'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select'; -import { type Category, getCategoryColorClasses } from '@/types/category'; -import { type DecryptedTransaction } from '@/types/transaction'; -import { type Account, type Bank } from '@/types/account'; -import { transactionSyncService } from '@/services/transaction-sync'; +import { CategorySelect } from '@/components/transactions/category-select'; import { encrypt, importKey } from '@/lib/crypto'; import { getStoredKey } from '@/lib/key-storage'; +import { transactionSyncService } from '@/services/transaction-sync'; +import { type Account, type Bank } from '@/types/account'; +import { type Category } from '@/types/category'; +import { type DecryptedTransaction } from '@/types/transaction'; +import { useState } from 'react'; interface CategoryCellProps { transaction: DecryptedTransaction; @@ -58,11 +50,13 @@ export function CategoryCell({ await transactionSyncService.update(transaction.id, updateData); - const updatedCategory = categoryId + const updatedCategory = categoryId ? categories.find((c) => c.id === categoryId) || null : null; - const account = accounts.find((a) => a.id === transaction.account_id); + const account = accounts.find( + (a) => a.id === transaction.account_id, + ); const bank = account?.bank?.id ? banks.find((b) => b.id === account.bank.id) : undefined; @@ -83,54 +77,19 @@ export function CategoryCell({ } } - const currentCategory = transaction.category; - const colorClasses = currentCategory - ? getCategoryColorClasses(currentCategory.color) - : null; - const CurrentCategoryIconComponent = (currentCategory ? Icons[currentCategory.icon as keyof typeof Icons] : "CircleQuestionMark") as Icons.LucideIcon; - return ( - + placeholder="Uncategorized" + triggerClassName="h-auto w-auto border-0 bg-transparent p-0 shadow-none focus:ring-0" + showUncategorized={true} + /> ); } - diff --git a/resources/js/components/transactions/category-select.tsx b/resources/js/components/transactions/category-select.tsx new file mode 100644 index 00000000..24def989 --- /dev/null +++ b/resources/js/components/transactions/category-select.tsx @@ -0,0 +1,106 @@ +import { Badge } from '@/components/ui/badge'; +import { + Select, + SelectContent, + SelectItem, + SelectTrigger, + SelectValue, +} from '@/components/ui/select'; +import { type Category, getCategoryColorClasses } from '@/types/category'; +import * as Icons from 'lucide-react'; + +interface CategorySelectProps { + value: string | null; + onValueChange: (value: string) => void; + categories: Category[]; + disabled?: boolean; + placeholder?: string; + className?: string; + triggerClassName?: string; + showUncategorized?: boolean; +} + +export function CategorySelect({ + value, + onValueChange, + categories, + disabled = false, + placeholder = 'Select category', + className, + triggerClassName, + showUncategorized = true, +}: CategorySelectProps) { + const selectedCategory = + value && value !== 'null' + ? categories.find((c) => c.id === parseInt(value)) + : null; + + const colorClasses = selectedCategory + ? getCategoryColorClasses(selectedCategory.color) + : null; + + const SelectedIconComponent = selectedCategory + ? (Icons[ + selectedCategory.icon as keyof typeof Icons + ] as Icons.LucideIcon) + : Icons.CircleQuestionMark; + + return ( + + ); +} diff --git a/resources/js/components/transactions/edit-transaction-dialog.tsx b/resources/js/components/transactions/edit-transaction-dialog.tsx index a33282c4..3b3c7b50 100644 --- a/resources/js/components/transactions/edit-transaction-dialog.tsx +++ b/resources/js/components/transactions/edit-transaction-dialog.tsx @@ -1,4 +1,4 @@ -import { useState, useEffect } from 'react'; +import { CategorySelect } from '@/components/transactions/category-select'; import { Button } from '@/components/ui/button'; import { Dialog, @@ -8,22 +8,15 @@ import { DialogHeader, DialogTitle, } from '@/components/ui/dialog'; -import { - Select, - SelectContent, - SelectItem, - SelectTrigger, - SelectValue, -} from '@/components/ui/select'; import { Label } from '@/components/ui/label'; import { Textarea } from '@/components/ui/textarea'; -import { Badge } from '@/components/ui/badge'; -import { type Category, getCategoryColorClasses } from '@/types/category'; -import { type DecryptedTransaction } from '@/types/transaction'; -import { transactionSyncService } from '@/services/transaction-sync'; import { encrypt, importKey } from '@/lib/crypto'; import { getStoredKey } from '@/lib/key-storage'; +import { transactionSyncService } from '@/services/transaction-sync'; +import { type Category } from '@/types/category'; +import { type DecryptedTransaction } from '@/types/transaction'; import { format, parseISO } from 'date-fns'; +import { useEffect, useState } from 'react'; interface EditTransactionDialogProps { transaction: DecryptedTransaction | null; @@ -47,7 +40,9 @@ export function EditTransactionDialog({ useEffect(() => { if (transaction) { setCategoryId( - transaction.category_id ? String(transaction.category_id) : 'null', + transaction.category_id + ? String(transaction.category_id) + : 'null', ); setNotes(transaction.decryptedNotes || ''); } @@ -116,10 +111,6 @@ export function EditTransactionDialog({ return null; } - const selectedCategory = categories.find( - (c) => c.id === parseInt(categoryId), - ); - return ( @@ -133,16 +124,19 @@ export function EditTransactionDialog({
-
-
); } - diff --git a/resources/js/components/transactions/transaction-columns.tsx b/resources/js/components/transactions/transaction-columns.tsx index 091e3732..c703a191 100644 --- a/resources/js/components/transactions/transaction-columns.tsx +++ b/resources/js/components/transactions/transaction-columns.tsx @@ -213,7 +213,7 @@ export function createTransactionColumns({ onReEvaluateRules(transaction)} > - Re-evaluate Rules + Re-evaluate rules