大改变
This commit is contained in:
63
components/common/BorderedButton.tsx
Normal file
63
components/common/BorderedButton.tsx
Normal file
@@ -0,0 +1,63 @@
|
||||
"use client";
|
||||
|
||||
import { Button, ButtonProps } from "@heroui/react";
|
||||
import { tv } from "tailwind-variants";
|
||||
|
||||
const borderedButtonStyles = tv({
|
||||
slots: {
|
||||
base: "rounded-xl border border-[#E5E7EB] dark:border-gray-600 flex items-center justify-center",
|
||||
button: "w-full h-full rounded-xl px-6 text-body-small font-bold border-none",
|
||||
},
|
||||
variants: {
|
||||
size: {
|
||||
md: {
|
||||
base: "h-10",
|
||||
},
|
||||
lg: {
|
||||
base: "h-11",
|
||||
},
|
||||
},
|
||||
fullWidth: {
|
||||
true: {
|
||||
base: "w-full",
|
||||
},
|
||||
},
|
||||
isTheme: {
|
||||
true: {
|
||||
button: "bg-white dark:bg-gray-800 text-text-primary dark:text-white",
|
||||
},
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
size: "md",
|
||||
isTheme: false,
|
||||
},
|
||||
});
|
||||
|
||||
interface BorderedButtonProps extends ButtonProps {
|
||||
size?: "md" | "lg";
|
||||
fullWidth?: boolean;
|
||||
isTheme?: boolean;
|
||||
}
|
||||
|
||||
export default function BorderedButton({
|
||||
size = "md",
|
||||
fullWidth = false,
|
||||
isTheme = false,
|
||||
className,
|
||||
...props
|
||||
}: BorderedButtonProps) {
|
||||
const { base, button } = borderedButtonStyles({ size, fullWidth, isTheme });
|
||||
|
||||
return (
|
||||
<div className={base({ className })}>
|
||||
<Button
|
||||
className={button()}
|
||||
{...props}
|
||||
>
|
||||
{props.children}
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
155
components/common/ConfirmModal.tsx
Normal file
155
components/common/ConfirmModal.tsx
Normal file
@@ -0,0 +1,155 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { Modal, ModalContent, Button } from "@heroui/react";
|
||||
import { buttonStyles } from "@/lib/buttonStyles";
|
||||
|
||||
interface ConfirmModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
}
|
||||
|
||||
export default function ConfirmModal({ isOpen, onClose }: ConfirmModalProps) {
|
||||
const [activeTab, setActiveTab] = useState<"buy" | "sell">("buy");
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
size="lg"
|
||||
classNames={{
|
||||
base: "bg-transparent shadow-none",
|
||||
wrapper: "items-center justify-center",
|
||||
}}
|
||||
>
|
||||
<ModalContent className="bg-bg-surface dark:bg-gray-800 rounded-3xl p-6 max-w-[494px]">
|
||||
<div className="flex flex-col gap-6">
|
||||
{/* Header - Buy/Sell Tabs */}
|
||||
<div className="flex items-center gap-8">
|
||||
<button
|
||||
onClick={() => setActiveTab("buy")}
|
||||
className={`text-heading-h4 leading-[140%] ${
|
||||
activeTab === "buy"
|
||||
? "font-bold text-text-primary dark:text-white"
|
||||
: "font-medium text-text-tertiary dark:text-gray-400"
|
||||
}`}
|
||||
>
|
||||
Buy
|
||||
</button>
|
||||
<button
|
||||
onClick={() => setActiveTab("sell")}
|
||||
className={`text-heading-h4 leading-[140%] ${
|
||||
activeTab === "sell"
|
||||
? "font-bold text-text-primary dark:text-white"
|
||||
: "font-medium text-text-tertiary dark:text-gray-400"
|
||||
}`}
|
||||
>
|
||||
Sell
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* PAY Section */}
|
||||
<div className="flex flex-col gap-2">
|
||||
{/* PAY Label and MAX Button */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-bold text-text-secondary dark:text-gray-400">
|
||||
PAY
|
||||
</span>
|
||||
<Button size="sm" className="rounded-lg h-7 px-3 text-caption-tiny font-medium bg-content2 text-foreground hover:bg-content3">
|
||||
MAX
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{/* Payment Input Box */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-2xl p-6">
|
||||
<div className="flex items-center justify-between">
|
||||
{/* Left - Amount */}
|
||||
<div className="flex flex-col gap-3">
|
||||
<div className="text-[32px] font-bold leading-[130%] tracking-[-0.01em] text-text-primary dark:text-white">
|
||||
1,000
|
||||
</div>
|
||||
<div className="text-body-small font-medium text-text-tertiary dark:text-gray-400">
|
||||
$10,000.00 USD
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Right - Token Selector and Balance */}
|
||||
<div className="flex flex-col gap-3 items-end">
|
||||
<button className="bg-bg-surface dark:bg-gray-600 rounded-full border border-border-normal dark:border-gray-500 px-2 h-[46px] flex items-center gap-2">
|
||||
<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">
|
||||
USDC
|
||||
</span>
|
||||
<Image src="/icon0.svg" alt="" width={20} height={20} />
|
||||
</button>
|
||||
<div className="flex items-center gap-1">
|
||||
<Image src="/icon1.svg" alt="" width={12} height={12} />
|
||||
<span className="text-caption-tiny font-medium text-text-secondary dark:text-gray-400">
|
||||
45,230.00 USDC
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Transaction Summary */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-2xl p-4 flex flex-col gap-2">
|
||||
<div className="text-body-small font-medium text-text-secondary dark:text-gray-400">
|
||||
Transaction Summary
|
||||
</div>
|
||||
|
||||
{/* You Get */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400">
|
||||
You Get
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-[#ff6900] dark:text-orange-400">
|
||||
9652.2 GYUS
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Market Price */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400">
|
||||
Market Price
|
||||
</span>
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white">
|
||||
$1.03 USDC
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Price vs Mint */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400">
|
||||
Price vs Mint
|
||||
</span>
|
||||
<div className="flex items-center gap-1">
|
||||
<Image src="/icon2.svg" alt="" width={20} height={20} />
|
||||
<span className="text-body-small font-bold text-[#10b981] dark:text-green-400">
|
||||
+2.53%
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Confirm Button */}
|
||||
<Button
|
||||
color="default"
|
||||
variant="solid"
|
||||
className={buttonStyles({ intent: "theme" })}
|
||||
onPress={onClose}
|
||||
>
|
||||
Buy from SWAP
|
||||
</Button>
|
||||
</div>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
429
components/common/ReviewModal.tsx
Normal file
429
components/common/ReviewModal.tsx
Normal file
@@ -0,0 +1,429 @@
|
||||
"use client";
|
||||
|
||||
import Image from "next/image";
|
||||
import { Modal, ModalContent, Button } from "@heroui/react";
|
||||
import { buttonStyles } from "@/lib/buttonStyles";
|
||||
|
||||
interface ReviewModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
amount: string;
|
||||
productName?: string;
|
||||
}
|
||||
|
||||
export default function ReviewModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
amount,
|
||||
productName = "High-Yield US Equity",
|
||||
}: ReviewModalProps) {
|
||||
const gyusAmount = amount ? (parseFloat(amount) * 0.9852).toFixed(0) : "0";
|
||||
const usdValue = amount ? (parseFloat(amount) * 1.00045).toFixed(2) : "0.00";
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
size="lg"
|
||||
classNames={{
|
||||
base: "bg-transparent shadow-none",
|
||||
backdrop: "bg-black/50",
|
||||
}}
|
||||
>
|
||||
<ModalContent>
|
||||
<div
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
borderRadius: "24px",
|
||||
padding: "24px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "24px",
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
{/* Header */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "446px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "20px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "140%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Review
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
style={{
|
||||
width: "24px",
|
||||
height: "24px",
|
||||
cursor: "pointer",
|
||||
background: "none",
|
||||
border: "none",
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src="/vuesax-linear-close-circle1.svg"
|
||||
alt="Close"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Product Info */}
|
||||
<div
|
||||
style={{
|
||||
background: "#f9fafb",
|
||||
borderRadius: "12px",
|
||||
padding: "16px",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "12px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
background: "#fff7ed",
|
||||
borderRadius: "6px",
|
||||
border: "0.75px solid rgba(0, 0, 0, 0.1)",
|
||||
width: "40px",
|
||||
height: "30px",
|
||||
boxShadow: "inset 0px 1.5px 3px 0px rgba(0, 0, 0, 0.05)",
|
||||
overflow: "hidden",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src="/lr0.svg"
|
||||
alt="Product"
|
||||
width={43}
|
||||
height={30}
|
||||
style={{ width: "107.69%", height: "100%", objectFit: "cover" }}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "18px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
{productName}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Amount Section */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "16px",
|
||||
width: "446px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#4b5563",
|
||||
fontSize: "14px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Deposit
|
||||
</div>
|
||||
<div style={{ textAlign: "center" }}>
|
||||
<span
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "48px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "120%",
|
||||
letterSpacing: "-0.01em",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
{amount || "0"}
|
||||
</span>
|
||||
<span
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "20px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "140%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
marginLeft: "8px",
|
||||
}}
|
||||
>
|
||||
USDC
|
||||
</span>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#4b5563",
|
||||
fontSize: "18px",
|
||||
fontWeight: 500,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
≈ ${usdValue}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Transaction Details */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "16px",
|
||||
width: "446px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "0px",
|
||||
}}
|
||||
>
|
||||
{/* Deposit Row */}
|
||||
<div
|
||||
style={{
|
||||
borderRadius: "16px",
|
||||
padding: "16px",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "12px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Image src="/icon0.svg" alt="" width={20} height={20} />
|
||||
<div
|
||||
style={{
|
||||
color: "#4b5563",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Deposit (USDC)
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "14px",
|
||||
fontWeight: 500,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
{amount ? parseFloat(amount).toLocaleString() : "0"}
|
||||
</div>
|
||||
<Image src="/icon3.svg" alt="" width={14} height={14} />
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 500,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Get GYUS Row */}
|
||||
<div
|
||||
style={{
|
||||
borderRadius: "16px",
|
||||
padding: "16px",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
height: "54px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "12px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Image src="/icon2.svg" alt="" width={20} height={20} />
|
||||
<div
|
||||
style={{
|
||||
color: "#4b5563",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
GET(GYUS)
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 500,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
0.00
|
||||
</div>
|
||||
<Image src="/icon3.svg" alt="" width={14} height={14} />
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "14px",
|
||||
fontWeight: 500,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
{gyusAmount}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* APY Info */}
|
||||
<div
|
||||
style={{
|
||||
background: "#f2fcf7",
|
||||
borderRadius: "16px",
|
||||
border: "1px solid #cef3e0",
|
||||
padding: "16px",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
overflow: "hidden",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<Image src="/icon4.svg" alt="" width={20} height={20} />
|
||||
<div
|
||||
style={{
|
||||
color: "#10b981",
|
||||
fontSize: "14px",
|
||||
fontWeight: 600,
|
||||
lineHeight: "20px",
|
||||
letterSpacing: "-0.15px",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
APY
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "4px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#10b981",
|
||||
fontSize: "18px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "28px",
|
||||
letterSpacing: "-0.44px",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
22.0%
|
||||
</div>
|
||||
<Image src="/icon5.svg" alt="" width={16} height={16} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Confirm Button */}
|
||||
<Button
|
||||
color="default"
|
||||
variant="solid"
|
||||
className={buttonStyles({ intent: "theme" })}
|
||||
onPress={() => {
|
||||
console.log("Transaction confirmed");
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
Confirm Transaction
|
||||
</Button>
|
||||
</div>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
192
components/common/TradePanel.tsx
Normal file
192
components/common/TradePanel.tsx
Normal file
@@ -0,0 +1,192 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { Button } from "@heroui/react";
|
||||
import { useApp } from "@/contexts/AppContext";
|
||||
import ConfirmModal from "@/components/common/ConfirmModal";
|
||||
import { buttonVariants, disabledButtonClasses } from "@/lib/buttonStyles";
|
||||
import { cn } from "@/lib/cn";
|
||||
interface TradePanelProps {
|
||||
showHeader?: boolean;
|
||||
title?: string;
|
||||
subtitle?: string;
|
||||
}
|
||||
|
||||
export default function TradePanel({
|
||||
showHeader = false,
|
||||
title = "",
|
||||
subtitle = "",
|
||||
}: TradePanelProps) {
|
||||
const { t } = useApp();
|
||||
const [sellAmount, setSellAmount] = useState<string>("");
|
||||
const [buyAmount, setBuyAmount] = useState<string>("");
|
||||
const [isConfirmModalOpen, setIsConfirmModalOpen] = useState(false);
|
||||
|
||||
return (
|
||||
<div className={`flex flex-col gap-6 ${showHeader ? "w-full max-w-[600px]" : "w-full"}`}>
|
||||
{/* Header Section - Optional */}
|
||||
{showHeader && (
|
||||
<div className="flex flex-col gap-2">
|
||||
<h1 className="text-heading-h2 font-bold text-text-primary dark:text-white text-center">
|
||||
{title}
|
||||
</h1>
|
||||
<p className="text-body-default font-medium text-text-secondary dark:text-gray-400 text-center">
|
||||
{subtitle}
|
||||
</p>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Trade Panel */}
|
||||
<div className="bg-bg-surface dark:bg-gray-800 rounded-3xl border border-border-gray dark:border-gray-700 p-6">
|
||||
<div className="flex flex-col gap-4">
|
||||
{/* SELL and BUY Container with Exchange Icon */}
|
||||
<div className="flex flex-col gap-2 relative">
|
||||
{/* SELL Section */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-2xl p-4 flex flex-col gap-4">
|
||||
{/* Label and Buttons */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white">
|
||||
{t("alp.sell")}
|
||||
</span>
|
||||
<div className="flex items-center gap-2">
|
||||
<Button size="sm" color="default" className="rounded-full px-3 h-[24px] min-w-0 text-[12px] font-bold">
|
||||
25%
|
||||
</Button>
|
||||
<Button size="sm" color="default" className="rounded-full px-3 h-[24px] min-w-0 text-[12px] font-bold">
|
||||
50%
|
||||
</Button>
|
||||
<Button size="sm" color="default" className="rounded-full px-3 h-[24px] min-w-0 text-[12px] font-bold">
|
||||
75%
|
||||
</Button>
|
||||
<Button size="sm" color="default" className={cn(buttonVariants.max)}>
|
||||
{t("mintSwap.max")}
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Input Row */}
|
||||
<div className="flex items-center justify-between gap-2 h-[70px]">
|
||||
<div className="flex flex-col items-start justify-between flex-1 h-full">
|
||||
<input
|
||||
type="number"
|
||||
placeholder="1,000"
|
||||
value={sellAmount}
|
||||
onChange={(e) => setSellAmount(e.target.value)}
|
||||
className="w-full text-left text-[32px] font-bold leading-[130%] tracking-[-0.01em] text-text-primary dark:text-white placeholder:text-[#d1d5db] dark:placeholder:text-gray-500 bg-transparent border-none outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
||||
/>
|
||||
<span className="text-body-small font-medium text-text-tertiary dark:text-gray-400">
|
||||
$10,000.00 USD
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-end justify-between gap-1 h-full">
|
||||
<button className="bg-bg-surface dark:bg-gray-600 rounded-full border border-border-normal dark:border-gray-500 px-3 h-[40px] flex items-center gap-2">
|
||||
<Image
|
||||
src="/usd-coin-usdc-logo-10.svg"
|
||||
alt="USDC"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white">USDC</span>
|
||||
<Image src="/icon8.svg" alt="" width={12} height={12} />
|
||||
</button>
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400">
|
||||
45,230.00 USDC
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Exchange Icon */}
|
||||
<div className="absolute left-1/2 top-1/2 -translate-x-1/2 -translate-y-1/2 z-10">
|
||||
<div className="bg-bg-surface dark:bg-gray-700 rounded-full w-10 h-10 flex items-center justify-center border border-border-gray dark:border-gray-600 shadow-sm">
|
||||
<Image
|
||||
src="/icon4.svg"
|
||||
alt="Exchange"
|
||||
width={18}
|
||||
height={18}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* BUY Section */}
|
||||
<div className="bg-bg-subtle dark:bg-gray-700 rounded-2xl p-4 flex flex-col gap-4">
|
||||
{/* Label */}
|
||||
<div className="flex items-center justify-between">
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white">
|
||||
{t("alp.buy")}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
{/* Input Row */}
|
||||
<div className="flex items-center justify-between gap-2 h-[70px]">
|
||||
<div className="flex flex-col items-start justify-between flex-1 h-full">
|
||||
<input
|
||||
type="number"
|
||||
placeholder="1,000"
|
||||
value={buyAmount}
|
||||
onChange={(e) => setBuyAmount(e.target.value)}
|
||||
className="w-full text-left text-[32px] font-bold leading-[130%] tracking-[-0.01em] text-text-primary dark:text-white placeholder:text-[#d1d5db] dark:placeholder:text-gray-500 bg-transparent border-none outline-none [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
|
||||
/>
|
||||
<span className="text-body-small font-medium text-text-tertiary dark:text-gray-400">
|
||||
$10,000.00 USD
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex flex-col items-end justify-between gap-1 h-full">
|
||||
<button className="bg-bg-surface dark:bg-gray-600 rounded-full border border-border-normal dark:border-gray-500 px-3 h-[40px] flex items-center gap-2">
|
||||
<Image
|
||||
src="/component-70.svg"
|
||||
alt="YTGY"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
<span className="text-body-small font-bold text-text-primary dark:text-white">YTGY</span>
|
||||
<Image src="/icon8.svg" alt="" width={12} height={12} />
|
||||
</button>
|
||||
<span className="text-caption-tiny font-regular text-text-tertiary dark:text-gray-400">
|
||||
45,230.00 USDC
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Submit Button */}
|
||||
<Button
|
||||
isDisabled={!sellAmount && !buyAmount}
|
||||
color="default"
|
||||
className="rounded-xl h-12 px-6 text-body-small font-bold"
|
||||
onPress={() => setIsConfirmModalOpen(true)}
|
||||
>
|
||||
{t("alp.buyUsdc")}
|
||||
</Button>
|
||||
|
||||
{/* Rate Info */}
|
||||
<div className="flex items-center justify-between px-4 py-3 bg-bg-subtle dark:bg-gray-700 rounded-xl border border-border-gray dark:border-gray-600">
|
||||
<div className="flex items-center gap-2">
|
||||
<span className="text-body-small font-regular text-black dark:text-white">
|
||||
1 USDC = 0.99 YTGY
|
||||
</span>
|
||||
<span className="text-body-small font-regular text-text-tertiary dark:text-gray-400">
|
||||
($1.00)
|
||||
</span>
|
||||
</div>
|
||||
<div className="flex items-center gap-2">
|
||||
<Image src="/icon7.svg" alt="" width={16} height={16} />
|
||||
<span className="text-body-small font-bold text-[#dc2626] dark:text-red-400">
|
||||
-$5.30
|
||||
</span>
|
||||
<Image src="/icon8.svg" alt="" width={12} height={12} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Confirm Modal */}
|
||||
<ConfirmModal
|
||||
isOpen={isConfirmModalOpen}
|
||||
onClose={() => setIsConfirmModalOpen(false)}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
576
components/common/WithdrawModal.tsx
Normal file
576
components/common/WithdrawModal.tsx
Normal file
@@ -0,0 +1,576 @@
|
||||
"use client";
|
||||
|
||||
import { useState } from "react";
|
||||
import Image from "next/image";
|
||||
import { Modal, ModalContent, Button } from "@heroui/react";
|
||||
import { buttonStyles } from "@/lib/buttonStyles";
|
||||
|
||||
interface WithdrawModalProps {
|
||||
isOpen: boolean;
|
||||
onClose: () => void;
|
||||
amount: string;
|
||||
}
|
||||
|
||||
export default function WithdrawModal({
|
||||
isOpen,
|
||||
onClose,
|
||||
amount,
|
||||
}: WithdrawModalProps) {
|
||||
const [showDetails, setShowDetails] = useState(true);
|
||||
|
||||
const alpAmount = amount ? (parseFloat(amount) * 0.098).toFixed(0) : "0";
|
||||
const usdValue = amount ? (parseFloat(amount) * 1.00045).toFixed(2) : "0.00";
|
||||
const fee = amount ? (parseFloat(amount) * 0.005).toFixed(2) : "0.00";
|
||||
const minReceive = amount ? (parseFloat(amount) * 0.098 * 0.995).toFixed(0) : "0";
|
||||
|
||||
return (
|
||||
<Modal
|
||||
isOpen={isOpen}
|
||||
onClose={onClose}
|
||||
size="lg"
|
||||
classNames={{
|
||||
base: "bg-transparent shadow-none",
|
||||
backdrop: "bg-black/50",
|
||||
}}
|
||||
>
|
||||
<ModalContent>
|
||||
<div
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
borderRadius: "24px",
|
||||
padding: "24px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "24px",
|
||||
position: "relative",
|
||||
overflow: "hidden",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
{/* Header */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "446px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "20px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "140%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Review
|
||||
</div>
|
||||
<button
|
||||
onClick={onClose}
|
||||
style={{
|
||||
width: "24px",
|
||||
height: "24px",
|
||||
cursor: "pointer",
|
||||
background: "none",
|
||||
border: "none",
|
||||
padding: 0,
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src="/vuesax-linear-close-circle1.svg"
|
||||
alt="Close"
|
||||
width={24}
|
||||
height={24}
|
||||
/>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
{/* Exchange Section */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "12px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
background: "#f9fafb",
|
||||
borderRadius: "16px",
|
||||
padding: "24px 16px",
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "0px",
|
||||
alignItems: "center",
|
||||
width: "446px",
|
||||
}}
|
||||
>
|
||||
{/* From USDC */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "4px",
|
||||
alignItems: "flex-start",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "24px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "130%",
|
||||
letterSpacing: "-0.005em",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
{amount || "0"} USDC
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#4b5563",
|
||||
fontSize: "16px",
|
||||
fontWeight: 500,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
≈ ${usdValue}
|
||||
</div>
|
||||
</div>
|
||||
<Image
|
||||
src="/usd-coin-usdc-logo-10.svg"
|
||||
alt="USDC"
|
||||
width={36}
|
||||
height={36}
|
||||
/>
|
||||
</div>
|
||||
|
||||
{/* Exchange Icon */}
|
||||
<div
|
||||
style={{
|
||||
background: "#ffffff",
|
||||
borderRadius: "999px",
|
||||
width: "40px",
|
||||
height: "40px",
|
||||
display: "flex",
|
||||
alignItems: "center",
|
||||
justifyContent: "center",
|
||||
boxShadow:
|
||||
"0px 1px 2px -1px rgba(0, 0, 0, 0.1), 0px 1px 3px 0px rgba(0, 0, 0, 0.1)",
|
||||
overflow: "visible",
|
||||
}}
|
||||
>
|
||||
<div style={{ width: "16px", height: "16px", position: "relative" }}>
|
||||
<Image
|
||||
src="/group-9280.svg"
|
||||
alt="Exchange"
|
||||
width={16}
|
||||
height={16}
|
||||
style={{ width: "100%", height: "100%", objectFit: "contain" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* To ALP */}
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
width: "100%",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "4px",
|
||||
alignItems: "flex-start",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "24px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "130%",
|
||||
letterSpacing: "-0.005em",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
{alpAmount} ALP
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
width: "36px",
|
||||
height: "36px",
|
||||
position: "relative",
|
||||
}}
|
||||
>
|
||||
<Image
|
||||
src="/vector0.svg"
|
||||
alt=""
|
||||
width={36}
|
||||
height={36}
|
||||
style={{ position: "absolute" }}
|
||||
/>
|
||||
<Image
|
||||
src="/vector1.svg"
|
||||
alt=""
|
||||
width={36}
|
||||
height={36}
|
||||
style={{ position: "absolute" }}
|
||||
/>
|
||||
<Image
|
||||
src="/vector2.svg"
|
||||
alt=""
|
||||
width={36}
|
||||
height={36}
|
||||
style={{ position: "absolute" }}
|
||||
/>
|
||||
<Image
|
||||
src="/component-10.svg"
|
||||
alt=""
|
||||
width={36}
|
||||
height={36}
|
||||
style={{ position: "absolute" }}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#4b5563",
|
||||
fontSize: "16px",
|
||||
fontWeight: 500,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
≈ ${usdValue}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{/* Show More/Less Button */}
|
||||
<button
|
||||
onClick={() => setShowDetails(!showDetails)}
|
||||
style={{
|
||||
background: "transparent",
|
||||
border: "none",
|
||||
cursor: "pointer",
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
gap: "8px",
|
||||
alignItems: "center",
|
||||
padding: "8px",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "14px",
|
||||
fontWeight: 500,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
{showDetails ? "Show less" : "Show more"}
|
||||
</div>
|
||||
<Image
|
||||
src="/icon1.svg"
|
||||
alt=""
|
||||
width={20}
|
||||
height={20}
|
||||
style={{
|
||||
transform: showDetails ? "rotate(180deg)" : "rotate(0deg)",
|
||||
transition: "transform 0.2s ease-in-out",
|
||||
}}
|
||||
/>
|
||||
</button>
|
||||
|
||||
{/* Transaction Details */}
|
||||
{showDetails && (
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "column",
|
||||
gap: "12px",
|
||||
width: "446px",
|
||||
animation: "fadeIn 0.3s ease-in-out",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Fee(0.5%)
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#ef4444",
|
||||
fontSize: "14px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
-${fee}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Network cost
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#ef4444",
|
||||
fontSize: "14px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
-$0.09
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Rate
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "14px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
1USDC=0.98ALP ($1.02)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Spread
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "14px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
0
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Price Impact
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#10b981",
|
||||
fontSize: "14px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
+$0.60 (+0.065%)
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Max slippage
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "14px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
0.5%
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div
|
||||
style={{
|
||||
display: "flex",
|
||||
flexDirection: "row",
|
||||
alignItems: "center",
|
||||
justifyContent: "space-between",
|
||||
padding: "12px 0",
|
||||
}}
|
||||
>
|
||||
<div
|
||||
style={{
|
||||
color: "#9ca1af",
|
||||
fontSize: "14px",
|
||||
fontWeight: 400,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
Min Receive
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
color: "#111827",
|
||||
fontSize: "14px",
|
||||
fontWeight: 700,
|
||||
lineHeight: "150%",
|
||||
fontFamily: "var(--font-inter)",
|
||||
}}
|
||||
>
|
||||
{minReceive} ALP
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{/* Confirm Button */}
|
||||
<Button
|
||||
color="default"
|
||||
variant="solid"
|
||||
className={buttonStyles({ intent: "theme" })}
|
||||
onPress={() => {
|
||||
console.log("Withdraw confirmed");
|
||||
onClose();
|
||||
}}
|
||||
>
|
||||
Confirm
|
||||
</Button>
|
||||
</div>
|
||||
</ModalContent>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user