'use client'; import { useState, useTransition } from 'react'; import { Table, TableBody, TableCaption, TableCell, TableHead, TableHeader, TableRow, } from '@/components/ui/table'; import { Button } from '@/components/ui/button'; import { Dialog, DialogContent, DialogDescription, DialogFooter, DialogHeader, DialogTitle, } from '@/components/ui/dialog'; import { Form, FormControl, FormField, FormItem, FormLabel, FormMessage, } from '@/components/ui/form'; import { Input } from '@/components/ui/input'; import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue, } from '@/components/ui/select'; import { zodResolver } from '@hookform/resolvers/zod'; import { useForm } from 'react-hook-form'; import { z } from 'zod'; import { Edit, Trash2 } from 'lucide-react'; import { formatAmount, formatQuantity } from '@/lib/formatters'; import { deleteTransaction, updateTransaction } from '@/actions/transaction'; import { AddTransactionDialog } from '@/components/transactions/add-transaction-dialog'; interface Asset { id: string; symbol: string; name: string | null; type: string; baseCurrency: string; } interface Transaction { id: string; assetId: string; txType: string; quantity: string; price: string; fee: string; txCurrency: string; executedAt: Date; } export default function TransactionsPageClient({ assets, transactions, }: { assets: Asset[]; transactions: Transaction[]; }) { const [isPending, startTransition] = useTransition(); const [deleteTarget, setDeleteTarget] = useState(null); const [editTarget, setEditTarget] = useState(null); const typeLabels: Record = { BUY: '买入', SELL: '卖出', DIVIDEND: '分红', AIRDROP: '空投', FEE: '手续费', }; const assetMap = new Map(assets.map((a) => [a.id, { symbol: a.symbol, name: a.name, type: a.type }])); const editForm = useForm<{ quantity: string; price: string; fee: string; txCurrency: string; executedAt: string }>({ resolver: zodResolver(z.object({ quantity: z.string().regex(/^-?\d+(\.\d+)?$/, '数量必须是数字'), price: z.string().regex(/^-?\d+(\.\d+)?$/, '价格必须是数字'), fee: z.string().regex(/^-?\d+(\.\d+)?$/, '手续费必须是有效数字'), txCurrency: z.string().min(1, '交易币种不能为空'), executedAt: z.string(), })), defaultValues: { quantity: '', price: '', fee: '0', txCurrency: 'USD', executedAt: '' }, }); function handleEditClick(tx: Transaction) { setEditTarget(tx); editForm.reset({ quantity: tx.quantity.toString(), price: tx.price.toString(), fee: tx.fee.toString(), txCurrency: tx.txCurrency, executedAt: tx.executedAt ? new Date(tx.executedAt).toISOString().slice(0, 16) : '', }); } function handleEditSubmit(values: { quantity: string; price: string; fee: string; txCurrency: string; executedAt: string }) { if (!editTarget) return; startTransition(async () => { const result = await updateTransaction({ id: editTarget.id, quantity: values.quantity, price: values.price, fee: values.fee, txCurrency: values.txCurrency, executedAt: new Date(values.executedAt), }); if (result.success) { setEditTarget(null); editForm.reset(); window.location.reload(); } }); } function handleDelete(tx: Transaction) { startTransition(async () => { await deleteTransaction(tx.id); setDeleteTarget(null); window.location.reload(); }); } return (

交易流水

共 {transactions.length} 条交易记录 名称 标的 类型 数量 价格 手续费 币种 执行时间 操作 {transactions.length === 0 ? ( 暂无流水,点击"添加流水"按钮录入第一笔交易 ) : ( transactions.map((tx) => { const assetInfo = assetMap.get(tx.assetId); const symbol = assetInfo?.symbol || tx.assetId; const name = assetInfo?.name || null; const assetType = assetInfo?.type || 'CASH'; return ( {name || '-'} {symbol} {typeLabels[tx.txType] || tx.txType} {formatQuantity(tx.quantity, assetType)} {formatAmount(tx.price)} {formatAmount(tx.fee)} {tx.txCurrency} {tx.executedAt ? new Date(tx.executedAt).toLocaleString('zh-CN') : '-'}
); }) )}
!open && setEditTarget(null)}> 编辑交易 修改交易记录详情
( 数量 )} /> ( 价格 )} />
( 手续费 )} /> ( 交易币种 )} />
( 执行时间 )} />
!open && setDeleteTarget(null)}> 确认删除 确定要删除这笔交易记录吗?此操作不可撤销。
); }