mirror of
https://github.com/marcogll/TaxHacker_s23.git
synced 2026-01-13 21:35:19 +00:00
feat: cache ai results on server + show success banner
This commit is contained in:
@@ -2,22 +2,9 @@
|
||||
|
||||
import { bulkDeleteTransactionsAction } from "@/app/(app)/transactions/actions"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { DropdownMenu, DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger } from "@/components/ui/dropdown-menu"
|
||||
import { ChevronUp, Trash2 } from "lucide-react"
|
||||
import { Trash2 } from "lucide-react"
|
||||
import { useState } from "react"
|
||||
|
||||
const bulkActions = [
|
||||
{
|
||||
id: "delete",
|
||||
label: "Bulk Delete",
|
||||
icon: Trash2,
|
||||
variant: "destructive" as const,
|
||||
action: bulkDeleteTransactionsAction,
|
||||
confirmMessage:
|
||||
"Are you sure you want to delete these transactions and all their files? This action cannot be undone.",
|
||||
},
|
||||
]
|
||||
|
||||
interface BulkActionsMenuProps {
|
||||
selectedIds: string[]
|
||||
onActionComplete?: () => void
|
||||
@@ -26,24 +13,21 @@ interface BulkActionsMenuProps {
|
||||
export function BulkActionsMenu({ selectedIds, onActionComplete }: BulkActionsMenuProps) {
|
||||
const [isLoading, setIsLoading] = useState(false)
|
||||
|
||||
const handleAction = async (actionId: string) => {
|
||||
const action = bulkActions.find((a) => a.id === actionId)
|
||||
if (!action) return
|
||||
|
||||
if (action.confirmMessage) {
|
||||
if (!confirm(action.confirmMessage)) return
|
||||
}
|
||||
const handleDelete = async () => {
|
||||
const confirmMessage =
|
||||
"Are you sure you want to delete these transactions and all their files? This action cannot be undone."
|
||||
if (!confirm(confirmMessage)) return
|
||||
|
||||
try {
|
||||
setIsLoading(true)
|
||||
const result = await action.action(selectedIds)
|
||||
const result = await bulkDeleteTransactionsAction(selectedIds)
|
||||
if (!result.success) {
|
||||
throw new Error(result.error)
|
||||
}
|
||||
onActionComplete?.()
|
||||
} catch (error) {
|
||||
console.error(`Failed to execute bulk action ${actionId}:`, error)
|
||||
alert(`Failed to execute action: ${error}`)
|
||||
console.error("Failed to delete transactions:", error)
|
||||
alert(`Failed to delete transactions: ${error}`)
|
||||
} finally {
|
||||
setIsLoading(false)
|
||||
}
|
||||
@@ -51,27 +35,10 @@ export function BulkActionsMenu({ selectedIds, onActionComplete }: BulkActionsMe
|
||||
|
||||
return (
|
||||
<div className="fixed bottom-4 right-4 z-50">
|
||||
<DropdownMenu>
|
||||
<DropdownMenuTrigger asChild>
|
||||
<Button className="min-w-48" disabled={isLoading}>
|
||||
{selectedIds.length} transactions
|
||||
<ChevronUp className="h-4 w-4" />
|
||||
</Button>
|
||||
</DropdownMenuTrigger>
|
||||
<DropdownMenuContent align="end">
|
||||
{bulkActions.map((action) => (
|
||||
<DropdownMenuItem
|
||||
key={action.id}
|
||||
onClick={() => handleAction(action.id)}
|
||||
className="gap-2"
|
||||
disabled={isLoading}
|
||||
>
|
||||
<action.icon className="h-4 w-4" />
|
||||
{action.label}
|
||||
</DropdownMenuItem>
|
||||
))}
|
||||
</DropdownMenuContent>
|
||||
</DropdownMenu>
|
||||
<Button variant="destructive" className="min-w-48 gap-2" disabled={isLoading} onClick={handleDelete}>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
Delete {selectedIds.length} transactions
|
||||
</Button>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -10,7 +10,7 @@ import { FormInput, FormTextarea } from "@/components/forms/simple"
|
||||
import { Button } from "@/components/ui/button"
|
||||
import { Category, Currency, Field, Project, Transaction } from "@/prisma/client"
|
||||
import { format } from "date-fns"
|
||||
import { Loader2 } from "lucide-react"
|
||||
import { Loader2, Save, Trash2 } from "lucide-react"
|
||||
import { useRouter } from "next/navigation"
|
||||
import { startTransition, useActionState, useEffect, useMemo, useState } from "react"
|
||||
|
||||
@@ -212,17 +212,23 @@ export default function TransactionEditForm({
|
||||
|
||||
<div className="flex justify-between space-x-4 pt-6">
|
||||
<Button type="button" onClick={handleDelete} variant="destructive" disabled={isDeleting}>
|
||||
{isDeleting ? "⏳ Deleting..." : "Delete "}
|
||||
<>
|
||||
<Trash2 className="h-4 w-4" />
|
||||
{isDeleting ? "⏳ Deleting..." : "Delete "}
|
||||
</>
|
||||
</Button>
|
||||
|
||||
<Button type="submit" disabled={isSaving}>
|
||||
{isSaving ? (
|
||||
<>
|
||||
<Loader2 className="mr-2 h-4 w-4 animate-spin" />
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
Saving...
|
||||
</>
|
||||
) : (
|
||||
"Save Transaction"
|
||||
<>
|
||||
<Save className="h-4 w-4" />
|
||||
Save Transaction
|
||||
</>
|
||||
)}
|
||||
</Button>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user