- {balances.map((balance) =>
- isMobile ? (
-
-
-
+
);
};
-export default BalanceCards;
\ No newline at end of file
+export default BalanceCards;
diff --git a/frontend/src/components/ui/balance-cards/balanceCards.css b/frontend/src/components/ui/balance-cards/balanceCards.css
new file mode 100644
index 00000000..5e15ed7b
--- /dev/null
+++ b/frontend/src/components/ui/balance-cards/balanceCards.css
@@ -0,0 +1,157 @@
+.balance-card {
+ max-width: 100%;
+ margin-top: 20px;
+}
+
+.balance-container {
+ display: flex;
+ justify-content: space-between;
+ max-width: 100%;
+ gap: 16px;
+}
+
+.balance-item {
+ display: flex;
+ flex-direction: column;
+ width: 198px;
+ height: 101px;
+ align-items: center;
+ border-radius: 8px;
+ border: 1px solid var(--light-purple);
+ justify-content: center;
+ background-color: var(--dark-purple);
+ padding: 16px 24px;
+}
+
+.balance-item label:nth-child(1) {
+ font-size: 14px;
+ color: var(--secondary);
+ display: flex;
+ gap: 4px;
+}
+
+.balance-item label:nth-child(2) {
+ font-size: 24px;
+ color: var(--secondary);
+ line-height: 32.68px;
+}
+
+.balance-title {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
+
+.balance-title span {
+ font-size: 14px;
+}
+
+.balance-title .balance-icon-wrapper {
+ background-color: #201338;
+ border-radius: 12px;
+ display: block;
+ width: 24px;
+ height: 24px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ margin-right: 10px;
+ margin-bottom: 0;
+}
+
+.balance-title svg {
+ height: 18px;
+ width: 18px;
+ height: 18px;
+ width: 18px;
+}
+
+.balance-title.blend svg {
+ filter: grayscale(1);
+}
+
+.balance-text {
+ color: #83919F;
+}
+
+.balance-amount {
+ font-weight: 600;
+}
+
+.token-icon {
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ padding: 5px;
+ border-radius: 2000px;
+ background-color: hsla(261, 49%, 15%, 1);
+}
+
+
+/* Responsiveness */
+/* Mobile */
+@media (max-width: 768px) {
+
+ .balance-container {
+ flex-direction: row;
+ justify-content: flex-start;
+ gap: 1rem;
+ align-items: center;
+ margin-bottom: 0;
+ overflow-x: auto;
+ scroll-snap-type: x mandatory;
+ gap: 20px;
+ max-width: 100%;
+ scrollbar-width: none;
+ -ms-overflow-style: none;
+ }
+
+ .balance-item {
+ height: fit-content;
+ padding: 16px 8px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ margin-right: 0;
+ border-radius: 16px;
+ }
+
+ .balance-item:first-child {
+ margin-left: 20px;
+ }
+
+ .balance-item:last-child {
+ margin-right: 20px;
+ }
+
+ .balance-item .balance-title {
+ font-size: 1rem;
+ display: flex;
+ align-items: center;
+ }
+
+ .balance-item .title-container + label:nth-of-type(1) {
+ font-size: 20px;
+ font-weight: 600;
+ }
+
+ .balance-item label:nth-child(2) {
+ color: var(--secondary);
+ font-size: 14px;
+ }
+
+ .title-container {
+ display: flex;
+ flex-direction: row;
+ align-items: center;
+ justify-content: center;
+ width: max-content;
+ }
+
+ .token-icon {
+ margin-right: 5px;
+ position: relative;
+ z-index: 1;
+ }
+
+}
\ No newline at end of file
diff --git a/frontend/src/globals.css b/frontend/src/globals.css
index 844d104d..a2cc6c25 100644
--- a/frontend/src/globals.css
+++ b/frontend/src/globals.css
@@ -67,6 +67,9 @@
--light-dark-background: #130713;
--text-gray: #798795;
--modal-border: #170f2e;
+ --warning-colour:#BDC000;
+ --warning-colour-alt: #272A0A;
+ --warning-text-colour: #F0F0F0;
}
body {
diff --git a/frontend/src/hooks/useScrollTracker.js b/frontend/src/hooks/useScrollTracker.js
deleted file mode 100644
index 6f323711..00000000
--- a/frontend/src/hooks/useScrollTracker.js
+++ /dev/null
@@ -1,27 +0,0 @@
-import { useRef, useState, useEffect } from "react";
-
-const useScrollTracker = () => {
- const scrollRef = useRef(null);
- const [activeIndex, setActiveIndex] = useState(0);
-
- const handleScroll = () => {
- if (scrollRef.current) {
- const { scrollLeft, scrollWidth, clientWidth } = scrollRef.current;
- const scrollPercentage = scrollLeft / (scrollWidth - clientWidth);
- const index = Math.round(scrollPercentage);
- setActiveIndex(index);
- }
- };
-
- useEffect(() => {
- const scrollContainer = scrollRef.current;
- if (scrollContainer) {
- scrollContainer.addEventListener("scroll", handleScroll);
- return () => scrollContainer.removeEventListener("scroll", handleScroll);
- }
- }, []);
-
- return { scrollRef, activeIndex, setActiveIndex };
-};
-
-export default useScrollTracker;
diff --git a/frontend/src/hooks/useWithdrawAll.js b/frontend/src/hooks/useWithdrawAll.js
new file mode 100644
index 00000000..6af89c9e
--- /dev/null
+++ b/frontend/src/hooks/useWithdrawAll.js
@@ -0,0 +1,26 @@
+import { useMutation } from "@tanstack/react-query";
+import { axiosInstance } from "utils/axios";
+import { notify } from "components/layout/notifier/Notifier";
+
+const useWithdrawAll = () => {
+ const mutation = useMutation({
+ mutationFn: async (walletId) => {
+ await new Promise((resolve) => setTimeout(resolve, 5000));
+ if (!walletId) throw new Error("Wallet ID is required.");
+ await axiosInstance.get(`/api/withdraw-all?wallet_id=${walletId}`);
+ },
+ onSuccess: () => {
+ notify("Withdraw All operation completed successfully!", "success");
+ },
+ onError: (error) => {
+ notify(error?.message || "Failed to complete the Withdraw All operation.", "error");
+ },
+ });
+
+ return {
+ withdrawAll: mutation.mutate,
+ isLoading: mutation.isPending,
+ };
+};
+
+export default useWithdrawAll;
diff --git a/frontend/src/pages/dashboard/Dashboard.jsx b/frontend/src/pages/dashboard/Dashboard.jsx
index 65aba60c..4144594a 100644
--- a/frontend/src/pages/dashboard/Dashboard.jsx
+++ b/frontend/src/pages/dashboard/Dashboard.jsx
@@ -8,7 +8,7 @@ import { ReactComponent as TelegramIcon } from '../../assets/icons/telegram_dash
import Spinner from '../../components/ui/spinner/Spinner';
import useDashboardData from '../../hooks/useDashboardData';
import { useClosePosition, useCheckPosition } from '../../hooks/useClosePosition';
-import Button from 'components/ui/button/Button';
+import Button from 'components/ui/Button/Button';
import { useWalletStore } from '../../stores/useWalletStore';
import { ActionModal } from '../../components/ui/action-modal';
import useTelegramNotification from '../../hooks/useTelegramNotification';
diff --git a/frontend/src/pages/form/Form.jsx b/frontend/src/pages/form/Form.jsx
index 8f1872ba..bebba123 100644
--- a/frontend/src/pages/form/Form.jsx
+++ b/frontend/src/pages/form/Form.jsx
@@ -1,17 +1,14 @@
import React, { useState } from 'react';
-import { ReactComponent as ETH } from '../../assets/icons/ethereum.svg';
-import { ReactComponent as USDC } from '../../assets/icons/borrow_usdc.svg';
-import { ReactComponent as STRK } from '../../assets/icons/strk.svg';
-import TokenSelector from '../../components/ui/token-selector/TokenSelector';
-import BalanceCards from '../../components/ui/balance-cards/BalanceCards';
-import MultiplierSelector from '../../components/ui/multiplier-selector/MultiplierSelector';
-import { handleTransaction } from '../../services/transaction';
-import Spinner from '../../components/ui/spinner/Spinner';
+import TokenSelector from 'components/ui/token-selector/TokenSelector';
+import BalanceCards from 'components/ui/balance-cards/BalanceCards';
+import MultiplierSelector from 'components/ui/multiplier-selector/MultiplierSelector';
+import { handleTransaction } from 'services/transaction';
+import Spinner from 'components/ui/spinner/Spinner';
import './form.css';
import { createPortal } from 'react-dom';
import useLockBodyScroll from '../../hooks/useLockBodyScroll';
import CongratulationsModal from '../../components/layout/congratulations-modal/CongratulationsModal';
-import Button from 'components/ui/button/Button';
+import Button from 'components/ui/Button/Button';
import { useWalletStore } from '../../stores/useWalletStore';
import { useConnectWallet } from '../../hooks/useConnectWallet';
import { useCheckPosition } from '../../hooks/useClosePosition';
@@ -46,12 +43,6 @@ const Form = () => {
}
};
- const [balances, setBalances] = useState([
- { icon:
, title: 'ETH', balance: '0.00' },
- { icon:
, title: 'USDC', balance: '0.00' },
- { icon:
, title: 'STRK', balance: '0.00' },
- ]);
-
const handleSubmit = async (e) => {
e.preventDefault();
@@ -91,7 +82,7 @@ const Form = () => {
return (
-
+
{successful && createPortal(
, document.body)}
{isClosePositionOpen && (
{
+ const { walletId } = useWalletStore();
+
+ const { withdrawAll, isLoading } = useWithdrawAll();
+ const handleWithdrawAll = () => {
+ withdrawAll(walletId);
+ };
+
+ return (
+
+
+
+
+
+
Please take special note
+
+
+
+ Clicking on the `Withdraw All` button means you are agreeing to close all positions and get all tokens
+ transferred to your wallet.
+
+
+
+
+
+ );
+};
+
+export default WithdrawAll;
diff --git a/frontend/src/pages/spotnet/dashboard/withdraw-all/withdraw_all.css b/frontend/src/pages/spotnet/dashboard/withdraw-all/withdraw_all.css
new file mode 100644
index 00000000..a68fbb92
--- /dev/null
+++ b/frontend/src/pages/spotnet/dashboard/withdraw-all/withdraw_all.css
@@ -0,0 +1,191 @@
+ .withdrawall-wrapper {
+ position: relative;
+ background: url('../../../../../public/Form-bg.png') no-repeat;
+ background-size: cover;
+ background-position: center left;
+ min-height: 100vh;
+ display: flex;
+ justify-content: center;
+ align-items: flex-start;
+ padding: 1rem 0;
+ }
+
+ .withdrawall-container {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+ gap: 10px;
+ padding-top: 20px;
+ }
+
+ .withdrawall-content {
+ width: 642px;
+ gap: 24px;
+ border-radius: 8px;
+ padding: 1rem 0;
+ color: var(--second-primary);
+ text-align: center;
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ align-items: center;
+ }
+
+ .withdrawall-info-card {
+ background: var(--warning-colour-alt);
+ border: 1px solid var(--warning-colour);
+ color: var(--second-primary);
+ font-family: 'Open Sans';
+ font-weight: 400;
+ text-align: center;
+ border-radius: 8px;
+ width: 642px;
+ height: 98px;
+ padding: 8px 16px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ flex-direction: column;
+ gap: 20px;
+ margin-top: 52px;
+ margin-bottom: 52px;
+ }
+ .withdrawall-btn {
+ border-radius: 4px;
+ }
+
+ .withdrawall-title h1 {
+ text-align: center;
+ font-weight: normal;
+ font-size: 20px;
+ margin-bottom: 10px;
+ }
+
+ @media (max-width: 768px) {
+ .withdrawall-wrapper {
+ padding: 1rem 0;
+ }
+
+ .withdrawall-container {
+ width: 100%;
+ max-width: 100%;
+ margin: 0 auto;
+ box-sizing: border-box;
+ }
+
+ .withdrawall-content {
+ width: 100%;
+ max-width: 100%;
+ padding: 0.5rem 24px;
+ gap: 16px;
+ }
+
+ .withdrawall-btn {
+ border-radius: 8px;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ width: 100%;
+ height: 55px;
+ }
+
+ .withdrawall-info-card {
+ height: 98px;
+ border-radius: 8px;
+ width: 100%;
+ margin-top: 52px;
+ margin-bottom: 52px;
+ }
+
+ .withdrawall-title h1 {
+ text-align: center;
+ font-weight: normal;
+ font-size: 1rem;
+ margin-bottom: 20px;
+ }
+ }
+
+ @media (max-width: 550px) {
+ .withdrawall-wrapper {
+ background: url('../../../../../public/dashboardmobile.png') no-repeat;
+ background-size: cover;
+ background-position: 50% 40%;
+ height: 100%;
+ }
+ .withdrawall-content {
+ gap: 40px;
+ display: flex;
+ justify-content: center;
+ flex-direction: column;
+ align-items: center;
+ }
+ .withdrawall-info-container {
+ display: grid;
+ gap: 30px;
+ padding-bottom: 40px;
+ }
+ .withdrawall-info-container {
+ width: 100%;
+ }
+ .withdrawall-info-card {
+ padding: 16px 24px;
+ height: 168px;
+ font-size: 400;
+ width: 100%;
+ border-radius: 8px;
+ gap: 0;
+ }
+
+ .withdrawall-btn {
+ width: 100%;
+ }
+ }
+
+ @media (max-width: 480px) {
+ .withdrawall-info-container {
+ width: 100%;
+ }
+ .withdrawall-info-card {
+ padding: 32px 8px;
+ width: 100%;
+ }
+
+ .withdrawall-btn {
+ width: 100%;
+ font-size: 14px;
+ height: 50px;
+ }
+
+ .tab {
+ padding: 6px 0px;
+ font-size: 12px;
+ }
+ }
+
+ @media (max-width: 400px) {
+ .withdrawall-info-container {
+ width: 100%;
+ }
+
+ .withdrawall-btn {
+ width: 100%;
+ height: 45px;
+ }
+
+ .withdrawall-info-card {
+ padding: 16px 24px;
+ width: 100%;
+ }
+ }
+
+ @media (max-width: 350px) {
+
+ .withdrawall-btn {
+ width: 100%;
+ height: 45px;
+ }
+
+ .withdrawall-info-card {
+ width: 100%;
+ }
+ }
\ No newline at end of file
diff --git a/frontend/src/pages/stake/Stake.jsx b/frontend/src/pages/stake/Stake.jsx
index 943a14b6..af4b95b2 100644
--- a/frontend/src/pages/stake/Stake.jsx
+++ b/frontend/src/pages/stake/Stake.jsx
@@ -1,14 +1,10 @@
import React, { useState } from 'react';
-import { ReactComponent as ETH } from '../../assets/icons/ethereum.svg';
-import { ReactComponent as USDC } from '../../assets/icons/borrow_usdc.svg';
-import { ReactComponent as DAI } from '../../assets/icons/dai.svg';
-import { ReactComponent as STTRK } from '../../assets/icons/strk.svg';
import MetricCard from '../../components/vault/stake-card/StakeCard';
import STRK from '../../assets/icons/strk.svg';
import USDCc from '../../assets/icons/apy_icon.svg';
import './stake.css';
import { VaultLayout } from '../../components/vault/VaultLayout';
-import { Button } from 'components/ui/button';
+import { Button } from 'components/ui/Button';
import GasFee from '../../components/vault/gas-fee/GasFee';
import BalanceCards from '../../components/ui/balance-cards/BalanceCards';
@@ -17,12 +13,6 @@ function Stake() {
const [amount, setAmount] = useState('0');
const [showDrop, setShowDrop] = useState(false);
- const [balances, setBalances] = useState([
- { icon: , title: 'STRK', balance: '0.046731' },
- { icon: , title: 'APY', balance: '0.046731' },
- { icon: , title: 'ETH', balance: '0.046731' },
- { icon: , title: 'DAI', balance: '0.046731' },
- ]);
const networks = [{ name: 'Starknet', image: STRK }];
const handleChange = (network) => {
setSelectedNetwork(network.name);
@@ -49,7 +39,7 @@ function Stake() {