| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116 |
- 'use client'
- import useSWR from 'swr'
- import { Card, CardContent } from '@/components/ui/card'
- import { Badge } from '@/components/ui/badge'
- import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table'
- const fetcher = (url: string) => fetch(url).then((r) => r.json())
- export default function HistoryPage() {
- const { data } = useSWR('/api/history?limit=100', fetcher, { refreshInterval: 5000 })
- const rows = data || []
- const statusBadge = (status: string) => {
- switch (status) {
- case 'success':
- return <Badge variant="success">{status}</Badge>
- case 'failed':
- return <Badge variant="destructive">{status}</Badge>
- case 'executing':
- return <Badge variant="warning">{status}</Badge>
- case 'skipped':
- default:
- return <Badge variant="secondary">{status}</Badge>
- }
- }
- return (
- <div className="space-y-6">
- <h2 className="text-lg font-semibold">Copy Trade History</h2>
- <Card>
- <CardContent className="p-4">
- {rows.length === 0 ? (
- <p className="text-xs text-muted-foreground">No history yet</p>
- ) : (
- <div className="overflow-x-auto">
- <Table className="text-xs">
- <TableHeader>
- <TableRow>
- <TableHead>Time</TableHead>
- <TableHead>Operation</TableHead>
- <TableHead>Target</TableHead>
- <TableHead>Target TX</TableHead>
- <TableHead>Our TX</TableHead>
- <TableHead>Amount A</TableHead>
- <TableHead>Amount B</TableHead>
- <TableHead>Status</TableHead>
- <TableHead>Error</TableHead>
- </TableRow>
- </TableHeader>
- <TableBody>
- {rows.map(
- (row: {
- id: number
- created_at: string
- operation: string
- target_address: string
- target_tx_sig: string
- our_tx_sig: string | null
- our_amount_a: string | null
- our_amount_b: string | null
- status: string
- error_message: string | null
- }) => (
- <TableRow key={row.id}>
- <TableCell className="text-muted-foreground whitespace-nowrap">
- {new Date(row.created_at + 'Z').toLocaleString()}
- </TableCell>
- <TableCell className="whitespace-nowrap">{row.operation}</TableCell>
- <TableCell className="text-muted-foreground">
- {row.target_address.slice(0, 4)}...{row.target_address.slice(-4)}
- </TableCell>
- <TableCell>
- <a
- href={`https://solscan.io/tx/${row.target_tx_sig}`}
- target="_blank"
- rel="noopener noreferrer"
- className="text-primary hover:underline"
- >
- {row.target_tx_sig.slice(0, 8)}...
- </a>
- </TableCell>
- <TableCell>
- {row.our_tx_sig ? (
- <a
- href={`https://solscan.io/tx/${row.our_tx_sig}`}
- target="_blank"
- rel="noopener noreferrer"
- className="text-primary hover:underline"
- >
- {row.our_tx_sig.slice(0, 8)}...
- </a>
- ) : (
- <span className="text-muted-foreground">-</span>
- )}
- </TableCell>
- <TableCell className="text-muted-foreground">{row.our_amount_a || '-'}</TableCell>
- <TableCell className="text-muted-foreground">{row.our_amount_b || '-'}</TableCell>
- <TableCell>{statusBadge(row.status)}</TableCell>
- <TableCell className="text-destructive text-[10px] max-w-[200px] truncate">
- {row.error_message || ''}
- </TableCell>
- </TableRow>
- ),
- )}
- </TableBody>
- </Table>
- </div>
- )}
- </CardContent>
- </Card>
- </div>
- )
- }
|