initial commit
This commit is contained in:
48
components/alp/ALPStatsCards.tsx
Normal file
48
components/alp/ALPStatsCards.tsx
Normal file
@@ -0,0 +1,48 @@
|
||||
"use client";
|
||||
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function ALPStatsCards() {
|
||||
const { t } = useApp();
|
||||
|
||||
const stats = [
|
||||
{
|
||||
label: t("stats.totalValueLocked"),
|
||||
value: "$465.0M",
|
||||
isGreen: false,
|
||||
},
|
||||
{
|
||||
label: t("alp.price"),
|
||||
value: "$1.23",
|
||||
isGreen: false,
|
||||
},
|
||||
{
|
||||
label: t("alp.poolAPR"),
|
||||
value: "27.36%",
|
||||
isGreen: true,
|
||||
},
|
||||
{
|
||||
label: t("alp.rewardAPR"),
|
||||
value: "8.23%",
|
||||
isGreen: true,
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="grid grid-cols-[1fr_1fr_1fr_1fr] gap-4">
|
||||
{stats.map((stat, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="bg-bg-subtle dark:bg-gray-800 rounded-2xl border border-border-gray dark:border-gray-700 px-6 py-4 flex flex-col gap-2"
|
||||
>
|
||||
<div className="text-caption-tiny font-bold text-text-tertiary dark:text-gray-400">
|
||||
{stat.label}
|
||||
</div>
|
||||
<div className={`text-[32px] font-bold leading-[130%] tracking-[-0.01em] ${stat.isGreen ? 'text-[#10b981]' : 'text-text-primary dark:text-white'}`}>
|
||||
{stat.value}
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
135
components/alp/LiquidityAllocationTable.tsx
Normal file
135
components/alp/LiquidityAllocationTable.tsx
Normal file
@@ -0,0 +1,135 @@
|
||||
"use client";
|
||||
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
|
||||
export default function LiquidityAllocationTable() {
|
||||
const { t } = useApp();
|
||||
|
||||
const allocations = [
|
||||
{
|
||||
icon: "GY",
|
||||
iconBg: "linear-gradient(135deg, #FF8904 0%, #F54900 100%)",
|
||||
name: "YT-GY",
|
||||
category: t("alp.quantStrategy"),
|
||||
poolSize: "$25,000",
|
||||
poolAmount: "24,1938 YTGY",
|
||||
currentWeight: "47%",
|
||||
targetWeight: "33%",
|
||||
currentPrice: "$1.03",
|
||||
},
|
||||
{
|
||||
icon: "LOGO",
|
||||
iconBg: "linear-gradient(135deg, #00BBA7 0%, #007A55 100%)",
|
||||
name: "YT-GY",
|
||||
category: t("alp.quantStrategy"),
|
||||
poolSize: "$25,000",
|
||||
poolAmount: "24,1938 YTGY",
|
||||
currentWeight: "47%",
|
||||
targetWeight: "33%",
|
||||
currentPrice: "$1.03",
|
||||
},
|
||||
{
|
||||
icon: "LOGO",
|
||||
iconBg: "linear-gradient(135deg, #1447E6 0%, #032BBD 100%)",
|
||||
name: "YT-GY",
|
||||
category: t("alp.quantStrategy"),
|
||||
poolSize: "$25,000",
|
||||
poolAmount: "24,1938 YTGY",
|
||||
currentWeight: "47%",
|
||||
targetWeight: "33%",
|
||||
currentPrice: "$1.03",
|
||||
},
|
||||
];
|
||||
|
||||
return (
|
||||
<div className="flex flex-col gap-3">
|
||||
{/* Title */}
|
||||
<h2 className="text-heading-h3 font-bold text-text-primary dark:text-white">
|
||||
{t("alp.liquidityAllocation")}
|
||||
</h2>
|
||||
|
||||
{/* Table */}
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 overflow-hidden">
|
||||
<div className="flex flex-col">
|
||||
{/* Header */}
|
||||
<div className="flex border-b border-border-gray dark:border-gray-700 flex-shrink-0">
|
||||
<div className="flex-1 px-6 py-4">
|
||||
<div className="text-caption-tiny font-medium text-[#4b5563] dark:text-gray-400">
|
||||
{t("alp.token")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 px-6 py-4">
|
||||
<div className="text-caption-tiny font-medium text-[#4b5563] dark:text-gray-400">
|
||||
{t("alp.poolSize")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 px-6 py-4">
|
||||
<div className="text-caption-tiny font-medium text-[#4b5563] dark:text-gray-400">
|
||||
{t("alp.currentTargetWeight")}
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex-1 px-6 py-4">
|
||||
<div className="text-caption-tiny font-medium text-[#4b5563] dark:text-gray-400">
|
||||
{t("alp.currentPrice")}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Body */}
|
||||
{allocations.map((item, index) => (
|
||||
<div
|
||||
key={index}
|
||||
className="flex items-center border-b border-border-gray dark:border-gray-700"
|
||||
>
|
||||
{/* Token Column */}
|
||||
<div className="flex-1 px-6 py-4 flex items-center gap-3">
|
||||
<div
|
||||
className="w-8 h-8 rounded-full flex items-center justify-center text-white text-[13.57px] font-bold"
|
||||
style={{ background: item.iconBg }}
|
||||
>
|
||||
{item.icon}
|
||||
</div>
|
||||
<div className="flex flex-col">
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white">
|
||||
{item.name}
|
||||
</span>
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400">
|
||||
{item.category}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Pool Size Column */}
|
||||
<div className="flex-1 px-6 py-4">
|
||||
<div className="flex flex-col">
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white">
|
||||
{item.poolSize}
|
||||
</span>
|
||||
<span className="text-caption-tiny font-regular text-[#6b7280] dark:text-gray-400">
|
||||
{item.poolAmount}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Weight Column */}
|
||||
<div className="flex-1 px-6 py-4">
|
||||
<span className="text-body-small font-bold">
|
||||
<span className="text-text-primary dark:text-white">{item.currentWeight}</span>
|
||||
<span className="text-text-tertiary dark:text-gray-400"> / </span>
|
||||
<span className="text-text-primary dark:text-white">{item.targetWeight}</span>
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Price Column */}
|
||||
<div className="flex-1 px-6 py-4">
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white">
|
||||
{item.currentPrice}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
185
components/alp/PriceHistoryCard.tsx
Normal file
185
components/alp/PriceHistoryCard.tsx
Normal file
@@ -0,0 +1,185 @@
|
||||
"use client";
|
||||
|
||||
import { useState, useEffect, useRef } from "react";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import * as echarts from "echarts";
|
||||
|
||||
export default function PriceHistoryCard() {
|
||||
const { t } = useApp();
|
||||
const chartRef = useRef<HTMLDivElement>(null);
|
||||
const chartInstance = useRef<echarts.ECharts | null>(null);
|
||||
|
||||
// 模拟价格数据
|
||||
const priceData = [1.01, 1.02, 1.03, 1.02, 1.04, 1.03, 1.05, 1.04, 1.03];
|
||||
|
||||
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();
|
||||
};
|
||||
}, []);
|
||||
|
||||
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;">Day ${data.dataIndex + 1}</span><br/>
|
||||
<span style="color: #10b981; font-weight: 600; font-size: 14px;">${data.value} USDC</span>
|
||||
</div>`;
|
||||
},
|
||||
},
|
||||
xAxis: {
|
||||
type: "category",
|
||||
data: priceData.map((_, i) => i + 1),
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
yAxis: {
|
||||
type: "value",
|
||||
axisLine: {
|
||||
show: false,
|
||||
},
|
||||
axisTick: {
|
||||
show: false,
|
||||
},
|
||||
axisLabel: {
|
||||
show: false,
|
||||
},
|
||||
splitLine: {
|
||||
show: false,
|
||||
},
|
||||
},
|
||||
series: [
|
||||
{
|
||||
data: priceData,
|
||||
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);
|
||||
};
|
||||
|
||||
// 计算统计数据
|
||||
const highest = Math.max(...priceData).toFixed(2);
|
||||
const lowest = Math.min(...priceData).toFixed(2);
|
||||
const current = priceData[priceData.length - 1].toFixed(2);
|
||||
const avg = (priceData.reduce((a, b) => a + b, 0) / priceData.length).toFixed(2);
|
||||
|
||||
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 flex-col gap-6">
|
||||
{/* Header */}
|
||||
<div className="text-body-large font-bold text-text-primary dark:text-white">
|
||||
{t("alp.priceHistory")}
|
||||
</div>
|
||||
|
||||
{/* Content */}
|
||||
<div className="flex flex-col gap-6">
|
||||
{/* Info Row */}
|
||||
<div className="flex items-center justify-between">
|
||||
<div className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400">
|
||||
{t("alp.lastDays")}
|
||||
</div>
|
||||
<div className="text-caption-tiny font-bold text-[#10b981] dark:text-green-400">
|
||||
{t("alp.avg")}: {avg} USDC
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* ECharts Chart */}
|
||||
<div
|
||||
ref={chartRef}
|
||||
className="w-full border-b border-border-gray dark:border-gray-600"
|
||||
style={{ height: "200px" }}
|
||||
/>
|
||||
|
||||
{/* Stats - Vertical Layout */}
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400">
|
||||
{t("alp.highest")}
|
||||
</div>
|
||||
<div className="text-caption-tiny font-bold text-text-primary dark:text-white tabular-nums">
|
||||
{highest} USDC
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400">
|
||||
{t("alp.lowest")}
|
||||
</div>
|
||||
<div className="text-caption-tiny font-bold text-text-primary dark:text-white tabular-nums">
|
||||
{lowest} USDC
|
||||
</div>
|
||||
</div>
|
||||
<div className="flex items-start justify-between">
|
||||
<div className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400">
|
||||
{t("alp.current")}
|
||||
</div>
|
||||
<div className="text-caption-tiny font-bold text-text-primary dark:text-white tabular-nums">
|
||||
{current} USDC
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user