大更新
This commit is contained in:
186
components/lending/BorrowMarket.tsx
Normal file
186
components/lending/BorrowMarket.tsx
Normal file
@@ -0,0 +1,186 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@heroui/react";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import BorderedButton from "@/components/common/BorderedButton";
|
||||
|
||||
interface BorrowMarketItem {
|
||||
icon: string;
|
||||
iconBg: string;
|
||||
name: string;
|
||||
nameEn?: string;
|
||||
category: string;
|
||||
badge?: string;
|
||||
yourBalance: string;
|
||||
yourInterest: string;
|
||||
borrowed: string;
|
||||
ltv: string;
|
||||
ltvColor: string;
|
||||
ltvProgress: number;
|
||||
}
|
||||
|
||||
export default function BorrowMarket() {
|
||||
const { t } = useApp();
|
||||
const router = useRouter();
|
||||
|
||||
const items: BorrowMarketItem[] = [
|
||||
{
|
||||
icon: "GY",
|
||||
iconBg: "linear-gradient(135deg, #FF8904 0%, #F54900 100%)",
|
||||
name: "高盈美股量化策略",
|
||||
category: "Quant Strategy • RWA-042",
|
||||
yourBalance: "$25,000",
|
||||
yourInterest: "+$1,250",
|
||||
borrowed: "$12,500",
|
||||
ltv: "50%",
|
||||
ltvColor: "text-[#ff6900]",
|
||||
ltvProgress: 50,
|
||||
},
|
||||
{
|
||||
icon: "LOGO",
|
||||
iconBg: "linear-gradient(135deg, #00BBA7 0%, #007A55 100%)",
|
||||
name: "HK Commercial RE",
|
||||
nameEn: "PI Only",
|
||||
category: "Real Estate • RWA-109",
|
||||
yourBalance: "$25,000",
|
||||
yourInterest: "+$1,250",
|
||||
borrowed: "$12,500",
|
||||
ltv: "40%",
|
||||
ltvColor: "text-[#ff6900]",
|
||||
ltvProgress: 40,
|
||||
},
|
||||
{
|
||||
icon: "LOGO",
|
||||
iconBg: "linear-gradient(135deg, #00BBA7 0%, #007A55 100%)",
|
||||
name: "HK Commercial RE",
|
||||
category: "Real Estate • RWA-109",
|
||||
yourBalance: "$25,000",
|
||||
yourInterest: "+$1,250",
|
||||
borrowed: "$12,500",
|
||||
ltv: "0%",
|
||||
ltvColor: "text-text-tertiary",
|
||||
ltvProgress: 0,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
{/* Title */}
|
||||
<h2 className="text-heading-h3 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.005em]">
|
||||
{t("lending.borrowMarket")}
|
||||
</h2>
|
||||
|
||||
{/* Cards Grid */}
|
||||
<div className="flex flex-col gap-3">
|
||||
{items.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-6 flex items-center gap-8"
|
||||
>
|
||||
{/* Left Section - Token Info */}
|
||||
<div className="flex items-center gap-4 w-[280px]">
|
||||
{/* Token Icon */}
|
||||
<div
|
||||
className="w-10 h-10 rounded-full flex items-center justify-center text-white text-sm font-bold shadow-md"
|
||||
style={{ background: item.iconBg }}
|
||||
>
|
||||
{item.icon}
|
||||
</div>
|
||||
|
||||
{/* Token Name */}
|
||||
<div className="flex flex-col h-10">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-body-default font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
{item.name}
|
||||
</span>
|
||||
{item.nameEn && (
|
||||
<span className="bg-bg-subtle dark:bg-gray-700 rounded px-1.5 py-0.5 text-[10px] font-medium text-text-tertiary dark:text-gray-400">
|
||||
{item.nameEn}
|
||||
</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{item.category}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Middle Section - Stats */}
|
||||
<div className="flex items-center justify-between flex-1">
|
||||
{/* Your Balance */}
|
||||
<div className="flex flex-col w-[112.9px]">
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("lending.yourBalance")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
{item.yourBalance}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Your Interest */}
|
||||
<div className="flex flex-col w-[112.9px]">
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("lending.yourInterest")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-[#10b981] dark:text-green-400 leading-[150%]">
|
||||
{item.yourInterest}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Borrowed */}
|
||||
<div className="flex flex-col w-[112.9px]">
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("lending.borrowed")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
{item.borrowed}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* LTV */}
|
||||
<div className="flex flex-col gap-2 w-[112.9px]">
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("lending.ltv")}
|
||||
</span>
|
||||
<span className={`text-caption-tiny font-bold leading-[150%] tracking-[0.01em] ${item.ltvColor} dark:text-orange-400`}>
|
||||
{item.ltv}
|
||||
</span>
|
||||
</div>
|
||||
{/* Progress Bar */}
|
||||
{item.ltvProgress > 0 && (
|
||||
<div className="w-full h-2 bg-fill-secondary-click dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-[#ff6900] dark:bg-orange-500 rounded-full"
|
||||
style={{ width: `${item.ltvProgress}%` }}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Section - Buttons */}
|
||||
<div className="flex items-center gap-3">
|
||||
<Button
|
||||
className="rounded-xl h-10 px-6 text-body-small font-bold bg-foreground text-background"
|
||||
isDisabled={index === 2}
|
||||
onPress={() => router.push("/repay")}
|
||||
>
|
||||
{t("lending.repay")}
|
||||
</Button>
|
||||
|
||||
<BorderedButton
|
||||
size="md"
|
||||
isTheme
|
||||
className="whitespace-nowrap"
|
||||
>
|
||||
{t("lending.borrow")}
|
||||
</BorderedButton>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
56
components/lending/LendingHeader.tsx
Normal file
56
components/lending/LendingHeader.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
"use client";
|
||||
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function LendingHeader() {
|
||||
const { t } = useApp();
|
||||
|
||||
const stats = [
|
||||
{
|
||||
label: t("lending.totalUsdcSupply"),
|
||||
value: "$200.4M",
|
||||
valueColor: "text-text-primary dark:text-white",
|
||||
},
|
||||
{
|
||||
label: t("lending.utilization"),
|
||||
value: "65%",
|
||||
valueColor: "text-[#10b981] dark:text-green-400",
|
||||
},
|
||||
{
|
||||
label: t("lending.activeLoans"),
|
||||
value: "3",
|
||||
valueColor: "text-text-primary dark:text-white",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-8 flex flex-col gap-6">
|
||||
{/* Title Section */}
|
||||
<div className="flex flex-col gap-0">
|
||||
<h1 className="text-heading-h2 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.01em]">
|
||||
{t("lending.title")}
|
||||
</h1>
|
||||
<p className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("lending.subtitle")}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{/* Stats Cards */}
|
||||
<div className="flex gap-4 w-full">
|
||||
{stats.map((stat, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex-1 bg-bg-subtle dark:bg-gray-700 rounded-2xl border border-border-gray dark:border-gray-600 p-4 flex flex-col gap-2"
|
||||
>
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{stat.label}
|
||||
</span>
|
||||
<span className={`text-heading-h2 font-bold leading-[130%] tracking-[-0.01em] ${stat.valueColor}`}>
|
||||
{stat.value}
|
||||
</span>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
62
components/lending/LendingPlaceholder.tsx
Normal file
62
components/lending/LendingPlaceholder.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useRouter } from "next/navigation";
|
||||
import { Button } from "@heroui/react";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import { buttonStyles } from "@/lib/buttonStyles";
|
||||
|
||||
export default function LendingPlaceholder() {
|
||||
const { t } = useApp();
|
||||
const router = useRouter();
|
||||
|
||||
return (
|
||||
<div className="relative rounded-2xl h-[180px] overflow-hidden">
|
||||
{/* Dark Background */}
|
||||
<div className="absolute inset-0 bg-[#0f172b]" />
|
||||
|
||||
{/* Green Glow Effect */}
|
||||
<div
|
||||
className="absolute w-32 h-32 rounded-full right-0 top-[-64px]"
|
||||
style={{
|
||||
background: "rgba(0, 188, 125, 0.2)",
|
||||
filter: "blur(40px)",
|
||||
}}
|
||||
/>
|
||||
|
||||
{/* Content - Centered */}
|
||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 flex flex-col gap-4 w-[90%]">
|
||||
{/* Your Portfolio Section */}
|
||||
<div className="flex flex-col gap-2">
|
||||
{/* Label Row */}
|
||||
<div className="flex items-center justify-between h-[21px]">
|
||||
<span className="text-[10px] font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("lending.yourPortfolio")}
|
||||
</span>
|
||||
<span className="text-[10px] font-bold text-[#10b981] dark:text-green-400 leading-[150%] tracking-[0.01em]">
|
||||
+$1,240 {t("lending.earned")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Amount */}
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-heading-h2 font-bold text-white leading-[130%] tracking-[-0.01em]">
|
||||
$15,500
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Supply USDC Button */}
|
||||
<Button
|
||||
color="default"
|
||||
variant="solid"
|
||||
className="h-11 rounded-xl px-6 text-body-small font-bold bg-[#282E3F] dark:bg-white dark:text-[#282E3F] text-background"
|
||||
onPress={() => router.push("/supply")}
|
||||
endContent={<Image src="/arrow-right-icon.svg" alt="" width={20} height={20} />}
|
||||
>
|
||||
{t("lending.supplyUsdc")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
73
components/lending/LendingStats.tsx
Normal file
73
components/lending/LendingStats.tsx
Normal file
@@ -0,0 +1,73 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function LendingStats() {
|
||||
const { t } = useApp();
|
||||
|
||||
// Mini bar chart data (heights in percentage)
|
||||
const chartBars = [
|
||||
{ height: 40, color: "#f2fcf7" },
|
||||
{ height: 55, color: "#e1f8ec" },
|
||||
{ height: 45, color: "#cef3e0" },
|
||||
{ height: 65, color: "#b8ecd2" },
|
||||
{ height: 80, color: "#00ad76" },
|
||||
{ height: 95, color: "#10b981" },
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-8 flex items-center gap-6 h-[180px]">
|
||||
{/* Left Section - USDC Borrowed and Avg. APY */}
|
||||
<div className="flex items-center gap-12 flex-1">
|
||||
{/* USDC Borrowed */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("lending.usdcBorrowed")}
|
||||
</span>
|
||||
<span className="text-heading-h2 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.01em]">
|
||||
$125.2M
|
||||
</span>
|
||||
<div className="flex items-center gap-1">
|
||||
<Image src="/icon0.svg" alt="" width={14} height={14} />
|
||||
<span className="text-[12px] font-medium text-[#10b981] dark:text-green-400 leading-[16px]">
|
||||
+12% {t("lending.vsLastMonth")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Divider */}
|
||||
<div className="w-px h-12 bg-border-gray dark:bg-gray-600" />
|
||||
|
||||
{/* Avg. APY */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("lending.avgApy")}
|
||||
</span>
|
||||
<span className="text-heading-h2 font-bold text-[#10b981] dark:text-green-400 leading-[130%] tracking-[-0.01em]">
|
||||
20.5%
|
||||
</span>
|
||||
<div className="flex items-center h-4">
|
||||
<span className="text-[12px] font-regular text-text-tertiary dark:text-gray-400 leading-[16px]">
|
||||
{t("lending.stableYield")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Section - Mini Chart */}
|
||||
<div className="flex items-end gap-1 w-48 h-16">
|
||||
{chartBars.map((bar, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex-1 rounded-t-md transition-all"
|
||||
style={{
|
||||
backgroundColor: bar.color,
|
||||
height: `${bar.height}%`,
|
||||
}}
|
||||
/>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
62
components/lending/repay/RepayBorrowDebt.tsx
Normal file
62
components/lending/repay/RepayBorrowDebt.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@heroui/react";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import { buttonStyles } from "@/lib/buttonStyles";
|
||||
|
||||
export default function RepayBorrowDebt() {
|
||||
const { t } = useApp();
|
||||
|
||||
return (
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-8 flex flex-col gap-8 flex-1 shadow-md">
|
||||
{/* Title */}
|
||||
<h3 className="text-body-large font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
{t("repay.borrowDebt")}
|
||||
</h3>
|
||||
|
||||
{/* Token Info and APR */}
|
||||
<div className="flex items-center justify-between h-[50px]">
|
||||
{/* Left - Token Info */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Token Icon */}
|
||||
<div
|
||||
className="w-10 h-10 rounded-full flex items-center justify-center text-white text-[10px] font-bold shadow-md"
|
||||
style={{ background: "linear-gradient(135deg, #00BBA7 0%, #007A55 100%)" }}
|
||||
>
|
||||
LOGO
|
||||
</div>
|
||||
|
||||
{/* Amount */}
|
||||
<div className="flex flex-col">
|
||||
<span className="text-heading-h3 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.005em]">
|
||||
1,000 USDC
|
||||
</span>
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
$1,000.00
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - APR */}
|
||||
<div className="flex flex-col items-end">
|
||||
<span className="text-heading-h3 font-bold text-[#10b981] dark:text-green-400 leading-[130%] tracking-[-0.005em]">
|
||||
6.1%
|
||||
</span>
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("repay.apr")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Buttons */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<Button className={buttonStyles({ intent: "theme" })}>
|
||||
{t("repay.borrow")}
|
||||
</Button>
|
||||
<Button className="rounded-xl h-11 w-full px-6 text-body-small font-bold bg-content2 text-foreground">
|
||||
{t("repay.repay")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
66
components/lending/repay/RepayHeader.tsx
Normal file
66
components/lending/repay/RepayHeader.tsx
Normal file
@@ -0,0 +1,66 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function RepayHeader() {
|
||||
const { t } = useApp();
|
||||
|
||||
return (
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 px-6 py-8 flex items-center justify-between">
|
||||
{/* Left Section - Token Icons and Title */}
|
||||
<div className="flex items-center gap-2">
|
||||
{/* Overlapping Token Icons */}
|
||||
<div className="flex items-center relative">
|
||||
<Image
|
||||
src="/component-70.svg"
|
||||
alt="YTGY"
|
||||
width={52}
|
||||
height={52}
|
||||
className="relative z-10"
|
||||
/>
|
||||
<Image
|
||||
src="/usd-coin-usdc-logo-10.svg"
|
||||
alt="USDC"
|
||||
width={52}
|
||||
height={52}
|
||||
className="relative -ml-3"
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Title and Subtitle */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<h1 className="text-heading-h2 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.01em]">
|
||||
GY / USDC
|
||||
</h1>
|
||||
<p className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
{t("repay.supplyToBorrow")}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Section - Stats */}
|
||||
<div className="flex items-center justify-between w-[262px]">
|
||||
{/* Price */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("repay.price")}
|
||||
</span>
|
||||
<span className="text-heading-h3 font-bold text-[#10b981] dark:text-green-400 leading-[130%] tracking-[-0.005em]">
|
||||
$1.29
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Available */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("repay.available")}
|
||||
</span>
|
||||
<span className="text-heading-h3 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.005em]">
|
||||
14.2M
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
63
components/lending/repay/RepayPoolStats.tsx
Normal file
63
components/lending/repay/RepayPoolStats.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
"use client";
|
||||
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function RepayPoolStats() {
|
||||
const { t } = useApp();
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-2 gap-6">
|
||||
{/* Left Card - Total Value Locked and Utilization */}
|
||||
<div className="bg-white/50 dark:bg-gray-800/50 rounded-2xl border border-border-normal dark:border-gray-700 px-6 flex items-center justify-between h-[98px]">
|
||||
{/* Total Value Locked */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[12px] font-bold text-[#90a1b9] dark:text-gray-400 leading-4 uppercase">
|
||||
{t("repay.totalValueLocked")}
|
||||
</span>
|
||||
<span className="text-[20px] font-bold text-[#0f172b] dark:text-white leading-7 tracking-[-0.45px]">
|
||||
$124,592,102
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Utilization */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[12px] font-bold text-[#90a1b9] dark:text-gray-400 leading-4 uppercase text-right">
|
||||
{t("repay.utilization")}
|
||||
</span>
|
||||
<span className="text-[20px] font-bold text-[#0f172b] dark:text-white leading-7 tracking-[-0.45px] text-right">
|
||||
42.8%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right Card - Reward Multiplier */}
|
||||
<div className="bg-white/50 dark:bg-gray-800/50 rounded-2xl border border-border-normal dark:border-gray-700 px-6 flex items-center justify-between h-[98px]">
|
||||
{/* Reward Multiplier */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[12px] font-bold text-[#90a1b9] dark:text-gray-400 leading-4 uppercase">
|
||||
{t("repay.rewardMultiplier")}
|
||||
</span>
|
||||
<span className="text-[20px] font-bold text-[#0f172b] dark:text-white leading-7 tracking-[-0.45px]">
|
||||
2.5x
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Overlapping Circles */}
|
||||
<div className="relative w-20 h-8">
|
||||
{/* Green Circle */}
|
||||
<div className="absolute left-0 top-0 w-8 h-8 rounded-full bg-[#00bc7d] border-2 border-white dark:border-gray-900" />
|
||||
|
||||
{/* Blue Circle */}
|
||||
<div className="absolute left-6 top-0 w-8 h-8 rounded-full bg-[#2b7fff] border-2 border-white dark:border-gray-900" />
|
||||
|
||||
{/* Gray Circle with +3 */}
|
||||
<div className="absolute left-12 top-0 w-8 h-8 rounded-full bg-[#e2e8f0] dark:bg-gray-600 border-2 border-white dark:border-gray-900 flex items-center justify-center">
|
||||
<span className="text-[10px] font-bold text-[#45556c] dark:text-gray-300 leading-[15px] tracking-[0.12px]">
|
||||
+3
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
69
components/lending/repay/RepayStats.tsx
Normal file
69
components/lending/repay/RepayStats.tsx
Normal file
@@ -0,0 +1,69 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function RepayStats() {
|
||||
const { t } = useApp();
|
||||
|
||||
return (
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-8 flex flex-col gap-8 flex-1 h-[249px] shadow-md">
|
||||
{/* Stats Info */}
|
||||
<div className="flex flex-col gap-6 h-[120px]">
|
||||
{/* NET APR */}
|
||||
<div className="flex items-center justify-between h-7">
|
||||
<div className="flex items-center gap-2">
|
||||
<Image src="/icon0.svg" alt="" width={18} height={18} />
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
{t("repay.netApr")}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-body-small font-bold text-[#10b981] dark:text-green-400 leading-[150%]">
|
||||
3%
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Liq.price/offset */}
|
||||
<div className="flex items-center justify-between h-7">
|
||||
<div className="flex items-center gap-2">
|
||||
<Image src="/icon1.svg" alt="" width={18} height={18} />
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
{t("repay.liqPriceOffset")}
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-1">
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
$0.938
|
||||
</span>
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
/ 20%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Position Health */}
|
||||
<div className="flex items-center justify-between h-7">
|
||||
<div className="flex items-center gap-2">
|
||||
<Image src="/icon2.svg" alt="" width={18} height={18} />
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
{t("repay.positionHealth")}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-body-small font-bold text-[#10b981] dark:text-green-400 leading-[150%]">
|
||||
Safe 50%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Progress Bar */}
|
||||
<div className="w-full">
|
||||
<div className="w-full h-2 bg-fill-secondary-click dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="h-full bg-[#10b981] dark:bg-green-500 rounded-full"
|
||||
style={{ width: "50%" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
62
components/lending/repay/RepaySupplyCollateral.tsx
Normal file
62
components/lending/repay/RepaySupplyCollateral.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
"use client";
|
||||
|
||||
import { Button } from "@heroui/react";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import { buttonStyles } from "@/lib/buttonStyles";
|
||||
|
||||
export default function RepaySupplyCollateral() {
|
||||
const { t } = useApp();
|
||||
|
||||
return (
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-8 flex flex-col gap-8 flex-1 shadow-md">
|
||||
{/* Title */}
|
||||
<h3 className="text-body-large font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
{t("repay.supplyCollateral")}
|
||||
</h3>
|
||||
|
||||
{/* Token Info and APR */}
|
||||
<div className="flex items-center justify-between h-[50px]">
|
||||
{/* Left - Token Info */}
|
||||
<div className="flex items-center gap-4">
|
||||
{/* Token Icon */}
|
||||
<div
|
||||
className="w-10 h-10 rounded-full flex items-center justify-center text-white text-sm font-bold shadow-md"
|
||||
style={{ background: "linear-gradient(135deg, #FF8904 0%, #F54900 100%)" }}
|
||||
>
|
||||
GY
|
||||
</div>
|
||||
|
||||
{/* Amount */}
|
||||
<div className="flex flex-col">
|
||||
<span className="text-heading-h3 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.005em]">
|
||||
1,000 YTGY
|
||||
</span>
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
$10,000.00
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - APR */}
|
||||
<div className="flex flex-col items-end">
|
||||
<span className="text-heading-h3 font-bold text-[#10b981] dark:text-green-400 leading-[130%] tracking-[-0.005em]">
|
||||
9.1%
|
||||
</span>
|
||||
<span className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("repay.apr")}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Buttons */}
|
||||
<div className="grid grid-cols-2 gap-3">
|
||||
<Button className={buttonStyles({ intent: "theme" })}>
|
||||
{t("repay.deposit")}
|
||||
</Button>
|
||||
<Button className="rounded-xl h-11 w-full px-6 text-body-small font-bold bg-content2 text-foreground">
|
||||
{t("repay.withdraw")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
226
components/lending/supply/SupplyContent.tsx
Normal file
226
components/lending/supply/SupplyContent.tsx
Normal file
@@ -0,0 +1,226 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import Image from "next/image";
|
||||
import { Button } from "@heroui/react";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
export default function SupplyContent() {
|
||||
const { t } = useApp();
|
||||
const [selectedPeriod, setSelectedPeriod] = useState<"1W" | "1M" | "1Y">("1W");
|
||||
const chartRef = useRef<HTMLDivElement>(null);
|
||||
const chartInstance = useRef<echarts.ECharts | null>(null);
|
||||
|
||||
// 模拟 APY 数据
|
||||
const generateChartData = (period: "1W" | "1M" | "1Y") => {
|
||||
const dataPoints = period === "1W" ? 7 : period === "1M" ? 30 : 365;
|
||||
const data = [];
|
||||
let baseValue = 18 + Math.random() * 4;
|
||||
|
||||
for (let i = 0; i < dataPoints; i++) {
|
||||
const change = (Math.random() - 0.45) * 2;
|
||||
baseValue = Math.max(15, Math.min(25, baseValue + change));
|
||||
data.push(parseFloat(baseValue.toFixed(2)));
|
||||
}
|
||||
return data;
|
||||
};
|
||||
|
||||
const chartData = generateChartData(selectedPeriod);
|
||||
|
||||
// 根据周期生成 X 轴标签
|
||||
const getXAxisLabels = (period: "1W" | "1M" | "1Y") => {
|
||||
if (period === "1W") {
|
||||
return ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"];
|
||||
} else if (period === "1M") {
|
||||
return Array.from({ length: 7 }, (_, i) => `${i * 4 + 1}d`);
|
||||
} else {
|
||||
return Array.from({ length: 7 }, (_, i) => `${i * 50 + 1}d`);
|
||||
}
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (chartRef.current) {
|
||||
chartInstance.current = echarts.init(chartRef.current);
|
||||
updateChart();
|
||||
}
|
||||
|
||||
const handleResize = () => {
|
||||
chartInstance.current?.resize();
|
||||
};
|
||||
window.addEventListener("resize", handleResize);
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("resize", handleResize);
|
||||
chartInstance.current?.dispose();
|
||||
};
|
||||
}, [selectedPeriod]);
|
||||
|
||||
const updateChart = () => {
|
||||
if (!chartInstance.current) return;
|
||||
|
||||
const option: echarts.EChartsOption = {
|
||||
grid: {
|
||||
left: 0,
|
||||
right: 0,
|
||||
top: 10,
|
||||
bottom: 0,
|
||||
},
|
||||
tooltip: {
|
||||
trigger: "axis",
|
||||
show: true,
|
||||
confine: true,
|
||||
backgroundColor: "rgba(17, 24, 39, 0.9)",
|
||||
borderColor: "#374151",
|
||||
textStyle: {
|
||||
color: "#f9fafb",
|
||||
fontSize: 12,
|
||||
fontWeight: 500,
|
||||
},
|
||||
formatter: function(params: any) {
|
||||
const data = params[0];
|
||||
return `<div style="padding: 4px 8px;">
|
||||
<span style="color: #9ca3af; font-size: 11px;">${data.axisValueLabel}</span><br/>
|
||||
<span style="color: #10b981; font-weight: 600; font-size: 14px;">${data.value}%</span>
|
||||
</div>`;
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: getXAxisLabels(selectedPeriod),
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: selectedPeriod === "1W",
|
||||
color: "#9ca3af",
|
||||
fontSize: 10,
|
||||
fontWeight: 500,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: chartData,
|
||||
type: "line",
|
||||
smooth: true,
|
||||
symbol: "circle",
|
||||
symbolSize: 6,
|
||||
lineStyle: {
|
||||
color: "#10b981",
|
||||
width: 2,
|
||||
},
|
||||
itemStyle: {
|
||||
color: "#10b981",
|
||||
},
|
||||
areaStyle: {
|
||||
color: {
|
||||
type: "linear",
|
||||
x: 0,
|
||||
y: 0,
|
||||
x2: 0,
|
||||
y2: 1,
|
||||
colorStops: [
|
||||
{ offset: 0, color: "rgba(16, 185, 129, 0.3)" },
|
||||
{ offset: 1, color: "rgba(16, 185, 129, 0)" },
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
||||
|
||||
chartInstance.current.setOption(option);
|
||||
};
|
||||
|
||||
return (
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-8 flex flex-col h-full w-full shadow-md">
|
||||
{/* Header - USDC Lend Pool */}
|
||||
<div className="flex items-center gap-3 flex-shrink-0">
|
||||
<Image
|
||||
src="/usd-coin-usdc-logo-10.svg"
|
||||
alt="USDC"
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<h1 className="text-heading-h2 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.01em]">
|
||||
{t("supply.usdcLendPool")}
|
||||
</h1>
|
||||
</div>
|
||||
|
||||
{/* Historical APY Section */}
|
||||
<div className="flex items-start justify-between flex-shrink-0">
|
||||
{/* Left - APY Display */}
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[12px] font-bold text-text-tertiary dark:text-gray-400 leading-[16px] tracking-[1.2px] uppercase">
|
||||
{t("supply.historicalApy")}
|
||||
</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-heading-h2 font-bold text-[#10b981] dark:text-green-400 leading-[130%] tracking-[-0.01em]">
|
||||
20.5%
|
||||
</span>
|
||||
<div className="bg-[#e1f8ec] dark:bg-green-900/30 rounded-full px-2 py-0.5 flex items-center justify-center">
|
||||
<span className="text-caption-tiny font-bold text-[#10b981] dark:text-green-400 leading-[150%] tracking-[0.01em]">
|
||||
+2.4%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - Period Selector */}
|
||||
<div className="bg-[#F9FAFB] dark:bg-gray-700 rounded-xl p-1 flex items-center gap-1">
|
||||
<Button
|
||||
size="sm"
|
||||
variant={selectedPeriod === "1W" ? "solid" : "light"}
|
||||
onPress={() => setSelectedPeriod("1W")}
|
||||
>
|
||||
1W
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={selectedPeriod === "1M" ? "solid" : "light"}
|
||||
onPress={() => setSelectedPeriod("1M")}
|
||||
>
|
||||
1M
|
||||
</Button>
|
||||
<Button
|
||||
size="sm"
|
||||
variant={selectedPeriod === "1Y" ? "solid" : "light"}
|
||||
onPress={() => setSelectedPeriod("1Y")}
|
||||
>
|
||||
1Y
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Chart Section */}
|
||||
<div className="flex-1 min-h-0 w-full">
|
||||
{/* ECharts Chart */}
|
||||
<div
|
||||
ref={chartRef}
|
||||
className="w-full h-full"
|
||||
style={{
|
||||
background: "linear-gradient(0deg, rgba(16, 185, 129, 0.1) 0%, transparent 100%)",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
159
components/lending/supply/SupplyPanel.tsx
Normal file
159
components/lending/supply/SupplyPanel.tsx
Normal file
@@ -0,0 +1,159 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { Button } from "@heroui/react";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import { buttonStyles } from "@/lib/buttonStyles";
|
||||
export default function SupplyPanel() {
|
||||
const { t } = useApp();
|
||||
const [amount, setAmount] = useState("");
|
||||
|
||||
return (
|
||||
<div className="p-6 flex flex-col gap-6 flex-1">
|
||||
{/* Token Balance & Supplied */}
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Token Balance */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-3 flex flex-col gap-1">
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.tokenBalance")}
|
||||
</span>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-large font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
45,230.00
|
||||
</span>
|
||||
<span className="text-caption-tiny font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
JLP
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
$45,230.00
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Supplied */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-3 flex flex-col gap-1">
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.supplied")}
|
||||
</span>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-large font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
0.00
|
||||
</span>
|
||||
<span className="text-caption-tiny font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
USDC
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
$0.00
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Deposit Section */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-4 flex flex-col gap-4">
|
||||
{/* Deposit Label and Available */}
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-caption-tiny font-medium text-text-secondary dark:text-gray-300 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.deposit")}
|
||||
</span>
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Image src="/wallet-icon.svg" alt="" width={12} height={12} />
|
||||
<span className="text-caption-tiny font-medium text-text-secondary dark:text-gray-300 leading-[150%] tracking-[0.01em]">
|
||||
45,230.00 USDC
|
||||
</span>
|
||||
</div>
|
||||
<Button size="sm" color="default" variant="solid" className={buttonStyles({ intent: "max" })}>
|
||||
{t("supply.max")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Input Row */}
|
||||
<div className="flex items-center justify-between h-12">
|
||||
{/* USDC Token Button */}
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-full border border-border-normal dark:border-gray-600 p-2 flex items-center gap-2 h-12">
|
||||
<Image
|
||||
src="/usd-coin-usdc-logo-10.svg"
|
||||
alt="USDC"
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<span className="text-body-default font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
USDC
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Amount Input */}
|
||||
<div className="flex flex-col items-end">
|
||||
<input
|
||||
type="text"
|
||||
value={amount}
|
||||
onChange={(e) => setAmount(e.target.value)}
|
||||
placeholder="0.00"
|
||||
className="text-heading-h3 font-bold text-text-input-box dark:text-gray-500 leading-[130%] tracking-[-0.005em] text-right bg-transparent outline-none w-24"
|
||||
/>
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
--
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Health Factor */}
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.healthFactor")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
0% {t("supply.utilization")}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-caption-tiny font-bold text-[#10b981] dark:text-green-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.safe")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Progress Bar */}
|
||||
<div className="w-full h-2 bg-fill-secondary-click dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="h-full rounded-full"
|
||||
style={{
|
||||
background: "linear-gradient(90deg, #10b981 0%, #ffb933 100%)",
|
||||
width: "0%",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Estimated Returns */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-2xl p-4 flex flex-col gap-2">
|
||||
<span className="text-body-small font-medium text-text-secondary dark:text-gray-300 leading-[150%]">
|
||||
{t("supply.estimatedReturns")}
|
||||
</span>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
{t("supply.estApy")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-[#ff6900] dark:text-orange-400 leading-[150%]">
|
||||
22%
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
{t("supply.estReturnsYear")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-[#10b981] dark:text-green-400 leading-[150%]">
|
||||
~ $0.50
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Supply Button */}
|
||||
<Button color="default" variant="solid" className={`${buttonStyles({ intent: "theme" })} mt-auto`} endContent={<Image src="/arrow-right-icon.svg" alt="" width={20} height={20} />}>
|
||||
{t("supply.supply")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
159
components/lending/supply/WithdrawPanel.tsx
Normal file
159
components/lending/supply/WithdrawPanel.tsx
Normal file
@@ -0,0 +1,159 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { Button } from "@heroui/react";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import { buttonStyles } from "@/lib/buttonStyles";
|
||||
export default function WithdrawPanel() {
|
||||
const { t } = useApp();
|
||||
const [amount, setAmount] = useState("45230");
|
||||
|
||||
return (
|
||||
<div className="p-6 flex flex-col gap-6 flex-1">
|
||||
{/* Token Balance & Supplied */}
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* Token Balance */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-3 flex flex-col gap-1">
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.tokenBalance")}
|
||||
</span>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-large font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
45,230.00
|
||||
</span>
|
||||
<span className="text-caption-tiny font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
JLP
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
$45,230.00
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Supplied */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-3 flex flex-col gap-1">
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.supplied")}
|
||||
</span>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-large font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
0.00
|
||||
</span>
|
||||
<span className="text-caption-tiny font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
USDC
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
$0.00
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Withdraw Section */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600 p-4 flex flex-col gap-4">
|
||||
{/* Withdraw Label and Available */}
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-caption-tiny font-medium text-text-secondary dark:text-gray-300 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.withdraw")}
|
||||
</span>
|
||||
<div className="flex items-center gap-2 ml-auto">
|
||||
<Image src="/wallet-icon.svg" alt="" width={12} height={12} />
|
||||
<span className="text-caption-tiny font-medium text-text-secondary dark:text-gray-300 leading-[150%] tracking-[0.01em]">
|
||||
45,230.00 USDC
|
||||
</span>
|
||||
</div>
|
||||
<Button size="sm" className={buttonStyles({ intent: "max" })}>
|
||||
{t("supply.max")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Input Row */}
|
||||
<div className="flex items-center justify-between h-12">
|
||||
{/* USDC Token Button */}
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-full border border-border-normal dark:border-gray-600 p-2 flex items-center gap-2 h-12">
|
||||
<Image
|
||||
src="/usd-coin-usdc-logo-10.svg"
|
||||
alt="USDC"
|
||||
width={32}
|
||||
height={32}
|
||||
/>
|
||||
<span className="text-body-default font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
USDC
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Amount Input */}
|
||||
<div className="flex flex-col items-end">
|
||||
<input
|
||||
type="text"
|
||||
value={amount}
|
||||
onChange={(e) => setAmount(e.target.value)}
|
||||
placeholder="0"
|
||||
className="text-heading-h3 font-bold text-text-primary dark:text-white leading-[130%] tracking-[-0.005em] text-right bg-transparent outline-none w-24"
|
||||
/>
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
≈ $1233.00 USD
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Health Factor */}
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="flex flex-col gap-1">
|
||||
<span className="text-[10px] font-medium text-text-tertiary dark:text-gray-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.healthFactor")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white leading-[150%]">
|
||||
0% {t("supply.utilization")}
|
||||
</span>
|
||||
</div>
|
||||
<span className="text-caption-tiny font-bold text-[#10b981] dark:text-green-400 leading-[150%] tracking-[0.01em]">
|
||||
{t("supply.safe")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Progress Bar */}
|
||||
<div className="w-full h-2 bg-fill-secondary-click dark:bg-gray-700 rounded-full overflow-hidden">
|
||||
<div
|
||||
className="h-full rounded-full"
|
||||
style={{
|
||||
background: "linear-gradient(90deg, #10b981 0%, #ffb933 100%)",
|
||||
width: "0%",
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Estimated Returns */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-2xl p-4 flex flex-col gap-2">
|
||||
<span className="text-body-small font-medium text-text-secondary dark:text-gray-300 leading-[150%]">
|
||||
{t("supply.estimatedReturns")}
|
||||
</span>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
{t("supply.estApy")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-[#ff6900] dark:text-orange-400 leading-[150%]">
|
||||
22%
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400 leading-[150%]">
|
||||
{t("supply.estReturnsYear")}
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-[#10b981] dark:text-green-400 leading-[150%]">
|
||||
~ $0.50
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Withdraw Button */}
|
||||
<Button className={`${buttonStyles({ intent: "theme" })} mt-auto`} endContent={<Image src="/arrow-right-icon.svg" alt="" width={20} height={20} />}>
|
||||
{t("supply.withdraw")}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user