Files
users/components/dashboard/dashboard-overview.tsx
v0 2408d50cb0 refactor: overhaul UI for streamlined user experience
Redesign navigation, home overview, user portrait, and valuation pages
with improved functionality and responsive design.

Co-authored-by: null <4804959+fnvtk@users.noreply.github.com>
2025-07-18 13:47:12 +00:00

180 lines
7.5 KiB
TypeScript

import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card"
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"
import { formatNumber, getGrowthClass } from "@/lib/utils"
import { ArrowDown, ArrowUp } from "lucide-react"
export function DashboardOverview() {
// 这里应该从API获取实际数据
const overviewData = {
userAcquisition: {
total: 12458,
growth: 12.5,
sources: [
{ name: "微信", value: 4523, growth: 15.2 },
{ name: "抖音", value: 3254, growth: 24.3 },
{ name: "小红书", value: 2145, growth: 8.7 },
{ name: "公众号", value: 1536, growth: -3.2 },
{ name: "官网", value: 1000, growth: 5.6 },
],
},
userRetention: {
rate: 68.5,
growth: 2.3,
periods: [
{ name: "7天", value: 85.2, growth: 1.2 },
{ name: "30天", value: 68.5, growth: 2.3 },
{ name: "90天", value: 42.3, growth: 3.5 },
{ name: "180天", value: 28.7, growth: -1.2 },
{ name: "365天", value: 15.4, growth: -2.5 },
],
},
userConversion: {
rate: 12.5,
growth: 3.2,
stages: [
{ name: "浏览", value: 100, growth: 0 },
{ name: "注册", value: 35.2, growth: 2.1 },
{ name: "首次购买", value: 12.5, growth: 3.2 },
{ name: "复购", value: 8.3, growth: 5.4 },
{ name: "会员", value: 4.2, growth: 1.8 },
],
},
}
return (
<Tabs defaultValue="acquisition" className="w-full">
<TabsList className="grid w-full grid-cols-3">
<TabsTrigger value="acquisition"></TabsTrigger>
<TabsTrigger value="retention"></TabsTrigger>
<TabsTrigger value="conversion"></TabsTrigger>
</TabsList>
<TabsContent value="acquisition">
<Card className="border shadow-sm">
<CardHeader>
<CardTitle></CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium"></p>
<p className="text-2xl font-bold">{formatNumber(overviewData.userAcquisition.total)}</p>
</div>
<div className={`flex items-center ${getGrowthClass(overviewData.userAcquisition.growth)}`}>
{overviewData.userAcquisition.growth > 0 ? (
<ArrowUp className="h-4 w-4 mr-1" />
) : (
<ArrowDown className="h-4 w-4 mr-1" />
)}
<span>{Math.abs(overviewData.userAcquisition.growth)}%</span>
</div>
</div>
<div className="space-y-2">
{overviewData.userAcquisition.sources.map((source) => (
<div key={source.name} className="flex items-center justify-between">
<div className="flex items-center">
<span className="text-sm">{source.name}</span>
</div>
<div className="flex items-center space-x-2">
<span className="text-sm">{formatNumber(source.value)}</span>
<span className={`text-xs ${getGrowthClass(source.growth)}`}>
{source.growth > 0 ? "+" : ""}
{source.growth}%
</span>
</div>
</div>
))}
</div>
</div>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="retention">
<Card className="border shadow-sm">
<CardHeader>
<CardTitle></CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium">30</p>
<p className="text-2xl font-bold">{overviewData.userRetention.rate}%</p>
</div>
<div className={`flex items-center ${getGrowthClass(overviewData.userRetention.growth)}`}>
{overviewData.userRetention.growth > 0 ? (
<ArrowUp className="h-4 w-4 mr-1" />
) : (
<ArrowDown className="h-4 w-4 mr-1" />
)}
<span>{Math.abs(overviewData.userRetention.growth)}%</span>
</div>
</div>
<div className="space-y-2">
{overviewData.userRetention.periods.map((period) => (
<div key={period.name} className="flex items-center justify-between">
<div className="flex items-center">
<span className="text-sm">{period.name}</span>
</div>
<div className="flex items-center space-x-2">
<span className="text-sm">{period.value}%</span>
<span className={`text-xs ${getGrowthClass(period.growth)}`}>
{period.growth > 0 ? "+" : ""}
{period.growth}%
</span>
</div>
</div>
))}
</div>
</div>
</CardContent>
</Card>
</TabsContent>
<TabsContent value="conversion">
<Card className="border shadow-sm">
<CardHeader>
<CardTitle></CardTitle>
<CardDescription></CardDescription>
</CardHeader>
<CardContent>
<div className="space-y-4">
<div className="flex items-center justify-between">
<div>
<p className="text-sm font-medium"></p>
<p className="text-2xl font-bold">{overviewData.userConversion.rate}%</p>
</div>
<div className={`flex items-center ${getGrowthClass(overviewData.userConversion.growth)}`}>
{overviewData.userConversion.growth > 0 ? (
<ArrowUp className="h-4 w-4 mr-1" />
) : (
<ArrowDown className="h-4 w-4 mr-1" />
)}
<span>{Math.abs(overviewData.userConversion.growth)}%</span>
</div>
</div>
<div className="space-y-2">
{overviewData.userConversion.stages.map((stage) => (
<div key={stage.name} className="flex items-center justify-between">
<div className="flex items-center">
<span className="text-sm">{stage.name}</span>
</div>
<div className="flex items-center space-x-2">
<span className="text-sm">{stage.value}%</span>
<span className={`text-xs ${getGrowthClass(stage.growth)}`}>
{stage.growth > 0 ? "+" : ""}
{stage.growth}%
</span>
</div>
</div>
))}
</div>
</div>
</CardContent>
</Card>
</TabsContent>
</Tabs>
)
}