50 lines
2.0 KiB
TypeScript
50 lines
2.0 KiB
TypeScript
"use client";
|
|
|
|
import { useState, useEffect } from "react";
|
|
import { getLevelInfo } from "@/lib/level-config";
|
|
import { UserLevel } from "@prisma/client";
|
|
import MemberBadge from "@/components/common/MemberBadge";
|
|
import { TrendingUp, BarChart3, Activity } from "lucide-react";
|
|
|
|
interface LevelProgressProps {
|
|
level: UserLevel;
|
|
points: number;
|
|
}
|
|
|
|
export default function LevelProgress({ level, points }: LevelProgressProps) {
|
|
const info = getLevelInfo(points);
|
|
|
|
return (
|
|
<div className="rounded-xl border border-border/50 bg-white p-5 shadow-[0_1px_2px_rgba(0,0,0,0.04)]">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<div className="flex items-center gap-2">
|
|
<div className={`flex h-8 w-8 items-center justify-center rounded-lg ${info.bgColor}`}>
|
|
<TrendingUp className={`w-4 h-4 ${info.color}`} />
|
|
</div>
|
|
<MemberBadge level={info.level} points={info.points} size="md" />
|
|
</div>
|
|
<span className={`text-lg font-bold ${info.color}`}>{info.points}分</span>
|
|
</div>
|
|
|
|
{info.nextLevel && (
|
|
<div className="space-y-2">
|
|
<div className="flex items-center justify-between text-xs">
|
|
<span className="text-muted-foreground">距离 {info.nextLevel.label} 还差</span>
|
|
<span className="font-medium text-foreground">{info.nextLevel.remaining}分</span>
|
|
</div>
|
|
<div className="h-2 rounded-full bg-muted/50 overflow-hidden">
|
|
<div
|
|
className={`h-full rounded-full transition-all duration-500 ${parseInt(info.nextLevel.level.replace("LV", "")) >= 15 ? "bg-amber-500" : parseInt(info.nextLevel.level.replace("LV", "")) >= 10 ? "bg-violet-500" : "bg-slate-400"}`}
|
|
style={{ width: `${info.progress}%` }}
|
|
/>
|
|
</div>
|
|
</div>
|
|
)}
|
|
|
|
{!info.nextLevel && (
|
|
<p className="text-sm text-center text-muted-foreground">🎉 已达到最高等级!</p>
|
|
)}
|
|
</div>
|
|
);
|
|
}
|