2026-01-30 04:11:58 +00:00
|
|
|
"use client";
|
|
|
|
|
|
|
|
|
|
import Image from "next/image";
|
|
|
|
|
|
|
|
|
|
interface ProductCardProps {
|
|
|
|
|
name: string;
|
|
|
|
|
category: string;
|
2026-01-30 05:35:08 +00:00
|
|
|
categoryColor: "blue" | "green" | "purple";
|
|
|
|
|
iconType: "us-flag-1" | "hk-flag" | "us-flag-2";
|
2026-01-30 04:11:58 +00:00
|
|
|
yieldAPY: string;
|
|
|
|
|
poolCap: string;
|
|
|
|
|
maturity: string;
|
|
|
|
|
risk: string;
|
|
|
|
|
riskLevel: 1 | 2 | 3;
|
|
|
|
|
lockUp: string;
|
|
|
|
|
circulatingSupply: string;
|
|
|
|
|
poolCapacityPercent: number;
|
|
|
|
|
onInvest?: () => void;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export default function ProductCard({
|
|
|
|
|
name,
|
|
|
|
|
category,
|
2026-01-30 05:35:08 +00:00
|
|
|
categoryColor,
|
|
|
|
|
iconType,
|
2026-01-30 04:11:58 +00:00
|
|
|
yieldAPY,
|
|
|
|
|
poolCap,
|
|
|
|
|
maturity,
|
|
|
|
|
risk,
|
|
|
|
|
riskLevel,
|
|
|
|
|
lockUp,
|
|
|
|
|
circulatingSupply,
|
|
|
|
|
poolCapacityPercent,
|
|
|
|
|
onInvest,
|
|
|
|
|
}: ProductCardProps) {
|
2026-01-30 05:35:08 +00:00
|
|
|
const getCategoryStyle = () => {
|
|
|
|
|
switch (categoryColor) {
|
|
|
|
|
case "blue":
|
|
|
|
|
return "bg-[rgba(59,130,246,0.1)] border-[rgba(59,130,246,0.3)]";
|
|
|
|
|
case "green":
|
|
|
|
|
return "bg-[rgba(34,197,94,0.1)] border-[rgba(34,197,94,0.3)]";
|
|
|
|
|
case "purple":
|
|
|
|
|
return "bg-[rgba(168,85,247,0.1)] border-[rgba(168,85,247,0.3)]";
|
|
|
|
|
default:
|
|
|
|
|
return "bg-[rgba(59,130,246,0.1)] border-[rgba(59,130,246,0.3)]";
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
const getRiskBarColor = () => {
|
|
|
|
|
switch (riskLevel) {
|
2026-01-30 04:11:58 +00:00
|
|
|
case 1:
|
2026-01-30 05:35:08 +00:00
|
|
|
return "#10b981"; // green
|
2026-01-30 04:11:58 +00:00
|
|
|
case 2:
|
2026-01-30 05:35:08 +00:00
|
|
|
return "#f59e0b"; // yellow/orange
|
2026-01-30 04:11:58 +00:00
|
|
|
case 3:
|
2026-01-30 05:35:08 +00:00
|
|
|
return "#ef4444"; // red
|
2026-01-30 04:11:58 +00:00
|
|
|
default:
|
2026-01-30 05:35:08 +00:00
|
|
|
return "#9ca3af";
|
2026-01-30 04:11:58 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
2026-01-30 05:35:08 +00:00
|
|
|
const getIconSrc = () => {
|
|
|
|
|
switch (iconType) {
|
|
|
|
|
case "us-flag-1":
|
|
|
|
|
return "/frame-9230.svg";
|
|
|
|
|
case "hk-flag":
|
|
|
|
|
return "/hk0.svg";
|
|
|
|
|
case "us-flag-2":
|
|
|
|
|
return "/frame-9231.svg";
|
|
|
|
|
default:
|
|
|
|
|
return "/frame-9230.svg";
|
2026-01-30 04:11:58 +00:00
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
return (
|
2026-01-30 05:35:08 +00:00
|
|
|
<div
|
|
|
|
|
className="rounded-3xl border border-[rgba(255,255,255,0.6)] p-6 flex-1 relative overflow-hidden"
|
|
|
|
|
style={{
|
|
|
|
|
background: `
|
|
|
|
|
radial-gradient(closest-side, rgba(186, 230, 253, 0.15) 0%, rgba(0, 0, 0, 0) 50%),
|
|
|
|
|
radial-gradient(closest-side, rgba(199, 210, 254, 0.15) 0%, rgba(0, 0, 0, 0) 50%),
|
|
|
|
|
linear-gradient(to left, rgba(255, 255, 255, 0.4), rgba(255, 255, 255, 0.4))
|
|
|
|
|
`,
|
|
|
|
|
boxShadow: "0px 8px 32px 0px rgba(0, 0, 0, 0.03)",
|
|
|
|
|
}}
|
|
|
|
|
>
|
2026-01-30 04:11:58 +00:00
|
|
|
{/* Product Header */}
|
2026-01-30 05:35:08 +00:00
|
|
|
<div className="pb-6 border-b-0">
|
|
|
|
|
<div className="flex items-center gap-4">
|
|
|
|
|
{/* Icon Container */}
|
2026-01-30 04:11:58 +00:00
|
|
|
<div
|
2026-01-30 05:35:08 +00:00
|
|
|
className="flex items-center justify-center w-16 h-16 rounded-2xl border border-[rgba(255,255,255,0.8)]"
|
|
|
|
|
style={{
|
|
|
|
|
background: "rgba(255, 255, 255, 0.4)",
|
|
|
|
|
boxShadow: "0px 0px 0px 4px rgba(255, 255, 255, 0.1)",
|
|
|
|
|
}}
|
2026-01-30 04:11:58 +00:00
|
|
|
>
|
2026-01-30 05:35:08 +00:00
|
|
|
<div className="relative w-12 h-12">
|
|
|
|
|
<Image
|
|
|
|
|
src={getIconSrc()}
|
|
|
|
|
alt={name}
|
|
|
|
|
width={48}
|
|
|
|
|
height={48}
|
|
|
|
|
className="w-full h-full object-contain"
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Title and Category */}
|
|
|
|
|
<div className="flex flex-col gap-0">
|
|
|
|
|
<h3 className="text-lg font-bold text-[#111827] dark:text-white leading-[150%]">
|
|
|
|
|
{name}
|
|
|
|
|
</h3>
|
|
|
|
|
<div
|
|
|
|
|
className={`inline-flex self-start px-3 py-1 rounded-full border mt-1 ${getCategoryStyle()}`}
|
|
|
|
|
>
|
|
|
|
|
<span className="text-xs font-medium text-[#111827] dark:text-white">
|
|
|
|
|
{category}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
2026-01-30 04:11:58 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-01-30 05:35:08 +00:00
|
|
|
{/* Metrics Section */}
|
|
|
|
|
<div className="py-6 flex gap-8">
|
|
|
|
|
<div className="flex flex-col gap-1">
|
|
|
|
|
<span className="text-sm text-[#6b7280] dark:text-gray-400">
|
|
|
|
|
Yield APY
|
|
|
|
|
</span>
|
|
|
|
|
<span className="text-base font-bold text-[#111827] dark:text-white">
|
|
|
|
|
{yieldAPY}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-col gap-1">
|
|
|
|
|
<span className="text-sm text-[#6b7280] dark:text-gray-400">
|
|
|
|
|
Pool CaP
|
|
|
|
|
</span>
|
|
|
|
|
<span className="text-base font-bold text-[#111827] dark:text-white">
|
|
|
|
|
{poolCap}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
{/* Details Grid */}
|
|
|
|
|
<div className="flex gap-6 pb-6">
|
|
|
|
|
<div className="flex flex-col gap-4 flex-1">
|
2026-01-30 04:11:58 +00:00
|
|
|
<div className="flex flex-col gap-1">
|
2026-01-30 05:35:08 +00:00
|
|
|
<span className="text-sm text-[#6b7280] dark:text-gray-400">
|
2026-01-30 04:11:58 +00:00
|
|
|
Maturity
|
|
|
|
|
</span>
|
2026-01-30 05:35:08 +00:00
|
|
|
<span className="text-sm font-medium text-[#111827] dark:text-white">
|
2026-01-30 04:11:58 +00:00
|
|
|
{maturity}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-col gap-1">
|
2026-01-30 05:35:08 +00:00
|
|
|
<span className="text-sm text-[#6b7280] dark:text-gray-400">
|
2026-01-30 04:11:58 +00:00
|
|
|
Lock-Up
|
|
|
|
|
</span>
|
2026-01-30 05:35:08 +00:00
|
|
|
<span className="text-sm font-medium text-[#111827] dark:text-white">
|
2026-01-30 04:11:58 +00:00
|
|
|
{lockUp}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-01-30 05:35:08 +00:00
|
|
|
<div className="flex flex-col gap-4 flex-1">
|
2026-01-30 04:11:58 +00:00
|
|
|
<div className="flex flex-col gap-1">
|
2026-01-30 05:35:08 +00:00
|
|
|
<span className="text-sm text-[#6b7280] dark:text-gray-400">
|
2026-01-30 04:11:58 +00:00
|
|
|
Risk
|
|
|
|
|
</span>
|
|
|
|
|
<div className="flex items-center gap-2">
|
2026-01-30 05:35:08 +00:00
|
|
|
<span className="text-sm font-medium text-[#111827] dark:text-white">
|
2026-01-30 04:11:58 +00:00
|
|
|
{risk}
|
|
|
|
|
</span>
|
|
|
|
|
<div className="flex items-center gap-1">
|
|
|
|
|
{[1, 2, 3].map((level) => (
|
|
|
|
|
<div
|
|
|
|
|
key={level}
|
2026-01-30 05:35:08 +00:00
|
|
|
className="w-1 h-3 rounded-sm"
|
|
|
|
|
style={{
|
|
|
|
|
backgroundColor:
|
|
|
|
|
level <= riskLevel ? getRiskBarColor() : "#d1d5db",
|
|
|
|
|
}}
|
2026-01-30 04:11:58 +00:00
|
|
|
/>
|
|
|
|
|
))}
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="flex flex-col gap-1">
|
2026-01-30 05:35:08 +00:00
|
|
|
<span className="text-sm text-[#6b7280] dark:text-gray-400">
|
2026-01-30 04:11:58 +00:00
|
|
|
Circulating supply
|
|
|
|
|
</span>
|
2026-01-30 05:35:08 +00:00
|
|
|
<span className="text-sm font-medium text-[#111827] dark:text-white">
|
2026-01-30 04:11:58 +00:00
|
|
|
{circulatingSupply}
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
|
2026-01-30 05:35:08 +00:00
|
|
|
{/* Pool Capacity & Button */}
|
|
|
|
|
<div className="pt-6 border-t border-[rgba(0,0,0,0.05)]">
|
|
|
|
|
<div className="flex items-end gap-6">
|
|
|
|
|
<div className="flex-1 flex flex-col gap-2">
|
|
|
|
|
<div className="flex items-center justify-between">
|
|
|
|
|
<span className="text-sm text-[#6b7280] dark:text-gray-400">
|
|
|
|
|
Pool Capacity
|
|
|
|
|
</span>
|
|
|
|
|
<span className="text-sm font-medium text-[#111827] dark:text-white">
|
|
|
|
|
{poolCapacityPercent}% Filled
|
|
|
|
|
</span>
|
|
|
|
|
</div>
|
|
|
|
|
<div className="w-full h-2 bg-[#e5e7eb] dark:bg-gray-700 rounded-full overflow-hidden">
|
|
|
|
|
<div
|
|
|
|
|
className="h-full bg-[#111827] dark:bg-blue-500 rounded-full transition-all"
|
|
|
|
|
style={{ width: `${poolCapacityPercent}%` }}
|
|
|
|
|
/>
|
|
|
|
|
</div>
|
2026-01-30 04:11:58 +00:00
|
|
|
</div>
|
2026-01-30 05:35:08 +00:00
|
|
|
<button
|
|
|
|
|
onClick={onInvest}
|
|
|
|
|
className="px-6 py-3 bg-[#111827] dark:bg-blue-600 text-white font-bold text-sm rounded-xl hover:bg-gray-800 dark:hover:bg-blue-700 transition-colors whitespace-nowrap"
|
|
|
|
|
>
|
|
|
|
|
Invest
|
|
|
|
|
</button>
|
2026-01-30 04:11:58 +00:00
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
|
|
|
|
);
|
|
|
|
|
}
|