208 lines
7.8 KiB
TypeScript
208 lines
7.8 KiB
TypeScript
'use client';
|
||
|
||
import { useState } from 'react';
|
||
import { usePlantingLedger } from '../hooks/use-users';
|
||
import { formatDecimal, formatNumber } from '@/lib/utils/format';
|
||
import { formatDateTime } from '@/lib/utils/date';
|
||
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
|
||
import { Button } from '@/components/ui/button';
|
||
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '@/components/ui/table';
|
||
import { Skeleton } from '@/components/ui/skeleton';
|
||
import { Badge } from '@/components/ui/badge';
|
||
import { ChevronLeft, ChevronRight, TreePine, Calendar, DollarSign } from 'lucide-react';
|
||
|
||
interface PlantingLedgerProps {
|
||
accountSequence: string;
|
||
}
|
||
|
||
// 认种状态标签
|
||
const plantingStatusLabels: Record<string, string> = {
|
||
CREATED: '已创建',
|
||
PAID: '已支付',
|
||
FUND_ALLOCATED: '资金已分配',
|
||
MINING_ENABLED: '已开始挖矿',
|
||
CANCELLED: '已取消',
|
||
EXPIRED: '已过期',
|
||
};
|
||
|
||
// 状态对应的样式
|
||
const getStatusVariant = (status: string): 'default' | 'secondary' | 'destructive' | 'outline' => {
|
||
switch (status) {
|
||
case 'MINING_ENABLED':
|
||
case 'PAID':
|
||
case 'FUND_ALLOCATED':
|
||
return 'default';
|
||
case 'CREATED':
|
||
return 'secondary';
|
||
case 'CANCELLED':
|
||
case 'EXPIRED':
|
||
return 'destructive';
|
||
default:
|
||
return 'outline';
|
||
}
|
||
};
|
||
|
||
export function PlantingLedger({ accountSequence }: PlantingLedgerProps) {
|
||
const [page, setPage] = useState(1);
|
||
const pageSize = 10;
|
||
|
||
const { data, isLoading } = usePlantingLedger(accountSequence, { page, pageSize });
|
||
|
||
if (isLoading) {
|
||
return (
|
||
<div className="space-y-6">
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-lg">认种汇总</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
|
||
{[...Array(6)].map((_, i) => (
|
||
<Skeleton key={i} className="h-16 w-full" />
|
||
))}
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
<Card>
|
||
<CardContent className="p-0">
|
||
<Skeleton className="h-64 w-full" />
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
);
|
||
}
|
||
|
||
if (!data) {
|
||
return (
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-lg">认种信息</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<p className="text-muted-foreground text-center py-8">暂无认种数据</p>
|
||
</CardContent>
|
||
</Card>
|
||
);
|
||
}
|
||
|
||
return (
|
||
<div className="space-y-6">
|
||
{/* 认种汇总 */}
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-lg flex items-center gap-2">
|
||
<TreePine className="h-5 w-5 text-green-600" />
|
||
认种汇总
|
||
</CardTitle>
|
||
</CardHeader>
|
||
<CardContent>
|
||
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-6 gap-4">
|
||
<div className="text-center p-4 bg-muted rounded-lg">
|
||
<p className="text-sm text-muted-foreground">总订单数</p>
|
||
<p className="text-2xl font-bold">{formatNumber(data.summary.totalOrders)}</p>
|
||
</div>
|
||
<div className="text-center p-4 bg-muted rounded-lg">
|
||
<p className="text-sm text-muted-foreground">总认种量</p>
|
||
<p className="text-2xl font-bold text-green-600">{formatNumber(data.summary.totalTreeCount)}</p>
|
||
</div>
|
||
<div className="text-center p-4 bg-muted rounded-lg">
|
||
<p className="text-sm text-muted-foreground">总金额</p>
|
||
<p className="text-2xl font-bold text-primary">{formatDecimal(data.summary.totalAmount, 2)}</p>
|
||
</div>
|
||
<div className="text-center p-4 bg-muted rounded-lg">
|
||
<p className="text-sm text-muted-foreground">有效认种量</p>
|
||
<p className="text-2xl font-bold text-blue-600">{formatNumber(data.summary.effectiveTreeCount)}</p>
|
||
</div>
|
||
<div className="text-center p-4 bg-muted rounded-lg">
|
||
<p className="text-sm text-muted-foreground">首次认种</p>
|
||
<p className="text-sm font-medium">
|
||
{data.summary.firstPlantingAt ? formatDateTime(data.summary.firstPlantingAt) : '-'}
|
||
</p>
|
||
</div>
|
||
<div className="text-center p-4 bg-muted rounded-lg">
|
||
<p className="text-sm text-muted-foreground">最近认种</p>
|
||
<p className="text-sm font-medium">
|
||
{data.summary.lastPlantingAt ? formatDateTime(data.summary.lastPlantingAt) : '-'}
|
||
</p>
|
||
</div>
|
||
</div>
|
||
</CardContent>
|
||
</Card>
|
||
|
||
{/* 认种分类账明细 */}
|
||
<Card>
|
||
<CardHeader>
|
||
<CardTitle className="text-lg">认种分类账明细</CardTitle>
|
||
</CardHeader>
|
||
<CardContent className="p-0">
|
||
<Table>
|
||
<TableHeader>
|
||
<TableRow>
|
||
<TableHead>订单号</TableHead>
|
||
<TableHead className="text-right">认种数量</TableHead>
|
||
<TableHead className="text-right">金额</TableHead>
|
||
<TableHead>省市</TableHead>
|
||
<TableHead>状态</TableHead>
|
||
<TableHead>创建时间</TableHead>
|
||
<TableHead>支付时间</TableHead>
|
||
</TableRow>
|
||
</TableHeader>
|
||
<TableBody>
|
||
{data.items.length === 0 ? (
|
||
<TableRow>
|
||
<TableCell colSpan={7} className="text-center py-8 text-muted-foreground">
|
||
暂无认种记录
|
||
</TableCell>
|
||
</TableRow>
|
||
) : (
|
||
data.items.map((item) => (
|
||
<TableRow key={item.orderId}>
|
||
<TableCell className="font-mono text-sm">{item.orderNo}</TableCell>
|
||
<TableCell className="text-right font-mono">{formatNumber(item.treeCount)}</TableCell>
|
||
<TableCell className="text-right font-mono">{formatDecimal(item.totalAmount, 2)}</TableCell>
|
||
<TableCell className="text-sm">
|
||
{item.selectedProvince || '-'} / {item.selectedCity || '-'}
|
||
</TableCell>
|
||
<TableCell>
|
||
<Badge variant={getStatusVariant(item.status)}>
|
||
{plantingStatusLabels[item.status] || item.status}
|
||
</Badge>
|
||
</TableCell>
|
||
<TableCell className="text-sm text-muted-foreground">
|
||
{formatDateTime(item.createdAt)}
|
||
</TableCell>
|
||
<TableCell className="text-sm text-muted-foreground">
|
||
{item.paidAt ? formatDateTime(item.paidAt) : '-'}
|
||
</TableCell>
|
||
</TableRow>
|
||
))
|
||
)}
|
||
</TableBody>
|
||
</Table>
|
||
|
||
{data.totalPages > 1 && (
|
||
<div className="flex items-center justify-between p-4 border-t">
|
||
<p className="text-sm text-muted-foreground">
|
||
共 {formatNumber(data.total)} 条,第 {page} / {data.totalPages} 页
|
||
</p>
|
||
<div className="flex items-center gap-2">
|
||
<Button variant="outline" size="sm" onClick={() => setPage(page - 1)} disabled={page <= 1}>
|
||
<ChevronLeft className="h-4 w-4" />
|
||
</Button>
|
||
<Button
|
||
variant="outline"
|
||
size="sm"
|
||
onClick={() => setPage(page + 1)}
|
||
disabled={page >= data.totalPages}
|
||
>
|
||
<ChevronRight className="h-4 w-4" />
|
||
</Button>
|
||
</div>
|
||
</div>
|
||
)}
|
||
</CardContent>
|
||
</Card>
|
||
</div>
|
||
);
|
||
}
|