Files
assetx/webapp/components/points/TeamTVLCard.tsx

105 lines
3.8 KiB
TypeScript
Raw Normal View History

"use client";
import Image from "next/image";
import { useApp } from "@/contexts/AppContext";
interface RoleIndicator {
icon: string;
label: string;
current: number;
target: number;
}
interface TeamTVLCardProps {
currentTVL: string;
targetTVL?: string;
progressPercent: number;
members: number;
roles: RoleIndicator[];
loading?: boolean;
}
export default function TeamTVLCard({
currentTVL = "$8.5M",
targetTVL = "$10M",
progressPercent = 85,
members = 12,
roles = [],
loading = false,
}: TeamTVLCardProps) {
const { t } = useApp();
return (
<div className="flex-[32] bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-8 flex flex-col gap-6 relative">
{/* Header */}
<div className="flex items-center gap-3">
<Image src="/components/card/icon3.svg" alt="" width={24} height={24} />
<span className="text-body-default font-bold text-text-primary dark:text-white leading-[150%]">
{t("points.teamTVLReward")}
</span>
</div>
{/* Description */}
<p className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
{t("points.buildYourTeam")}
</p>
{/* Progress Section */}
<div className="flex flex-col gap-4">
{/* TVL Info */}
<div className="flex flex-col gap-1">
<div className="flex items-start justify-between">
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
{t("points.currentTeamTVL")}
</span>
{loading ? (
<div className="h-3 bg-gray-300 dark:bg-gray-600 rounded w-20 animate-pulse" />
) : (
<span className="text-caption-tiny font-bold text-text-primary dark:text-white leading-[150%] tracking-[0.01em]">
{currentTVL} / {targetTVL}
</span>
)}
</div>
{/* Progress Bar */}
<div className="relative w-full h-2 bg-[#f3f4f6] dark:bg-gray-700 rounded-full overflow-hidden">
<div
className="absolute left-0 top-0 h-full rounded-full"
style={{
width: `${progressPercent}%`,
background: "linear-gradient(90deg, rgba(20, 71, 230, 1) 0%, rgba(3, 43, 189, 1) 100%)"
}}
/>
</div>
</div>
{/* Role Indicators */}
<div className="flex items-center gap-2">
{roles.map((role, index) => (
<div
key={index}
className="flex-1 bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 px-4 py-2 flex flex-col items-center justify-center gap-0"
>
<div className="flex items-center justify-center h-4">
<Image src={role.icon} alt={role.label} width={16} height={16} />
</div>
<span className="text-[10px] font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
{role.label}
</span>
<span className="text-caption-tiny font-bold text-text-primary dark:text-white leading-[150%] tracking-[0.01em]">
{role.current}/{role.target}
</span>
</div>
))}
</div>
</div>
{/* Members Badge */}
<div className="absolute right-6 top-8 bg-[#e1f8ec] dark:bg-green-900/30 border border-[#b8ecd2] dark:border-green-700 rounded-full px-3 py-1 flex items-center">
<span className="text-[10px] font-bold text-[#10b981] dark:text-green-400 leading-[100%] tracking-[0.01em]">
{t("points.membersCount").replace("{count}", members.toString())}
</span>
</div>
</div>
);
}