Skip to content

Commit

Permalink
Merge pull request #423 from djeck1432/feature/add-deposit
Browse files Browse the repository at this point in the history
wip: deposit page
  • Loading branch information
djeck1432 authored Dec 23, 2024
2 parents 80b2741 + e001218 commit fa76c77
Show file tree
Hide file tree
Showing 12 changed files with 651 additions and 115 deletions.
3 changes: 3 additions & 0 deletions frontend/.eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
"react-hooks/exhaustive-deps": "warn",
"@tanstack/query/exhaustive-deps": "error"
},
"parserOptions": {
"sourceType": "module"
},
"settings": {
"react": {
"version": "detect"
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import { useCheckMobile } from './hooks/useCheckMobile';
import PositionHistory from './pages/position-history/PositionHistory';
import WithdrawAll from 'pages/spotnet/dashboard/withdraw-all/WithdrawAll';
import { DefiSpringPage } from 'pages/spotnet/defi-spring/DefiSpring';
import { AddDeposit } from 'pages/add-deposit/AddDeposit';

function App() {
const { setWalletId, removeWalletId } = useWalletStore();
Expand Down Expand Up @@ -100,7 +101,8 @@ function App() {
<Route index element={<SpotnetApp onConnectWallet={handleConnectWallet} onLogout={handleLogout} />} />
<Route path="/dashboard" element={<Dashboard telegramId={window?.Telegram?.WebApp?.initData?.user?.id} />} />
<Route path="/dashboard/position-history" element={<PositionHistory />} />
<Route path="/dashboard/withdraw-all" element={<WithdrawAll />} />
<Route path="/dashboard/withdraw" element={<WithdrawAll />} />
<Route path="/dashboard/deposit" element={<AddDeposit />} />
<Route path="/withdraw" element={<Withdraw />} />
<Route path="/overview" element={<OverviewPage />} />
<Route path="/form" element={<Form />} />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,14 @@ const NavigationLinks = ({ onNavClick }) => (
<NavLink to="/" end className={({ isActive }) => (isActive ? 'active-link' : '')} onClick={onNavClick}>
Home
</NavLink>
<div className="nav-divider"></div>
<div className="nav-divider" />
<NavLink to="/dashboard" className={({ isActive }) => (isActive ? 'active-link' : '')} onClick={onNavClick}>
Dashboard
</NavLink>
<div className="nav-divider" />
<NavLink to="/form" className={({ isActive }) => (isActive ? 'active-link' : '')} onClick={onNavClick}>
Form
</NavLink>
{/* <div className="nav-divider"></div> */}
{/* <NavLink to="/stake" className={({ isActive }) => (isActive ? 'active-link' : '')} onClick={onNavClick}> */}
{/* Vault */}
Expand Down
52 changes: 33 additions & 19 deletions frontend/src/components/ui/token-selector/TokenSelector.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import React 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.css';

const Tokens = [
{ id: 'ethOption', component: <ETH />, label: 'ETH' },
Expand All @@ -10,27 +11,40 @@ const Tokens = [
];

const TokenSelector = ({ selectedToken, setSelectedToken }) => {
const handleTokenChange = (token) => {
setSelectedToken(token.label);
};

return (
<div className="form-token">
{Tokens.map((token) => (
<div className="token-card" key={token?.id}>
<div className="token-container">
<input
type="radio"
id={token.id}
checked={selectedToken === token.label}
name="token-options"
value={token.label}
onChange={() => setSelectedToken(token?.label)}
/>
<label htmlFor={token?.id}>
<h5>
<span className="token-icon">{token?.component}</span> {token?.label}
</h5>
</label>
<div className="token-selector-container">
<span className="token-select-label">Select Token</span>
<div className="token-options">
{Tokens.map((token) => (
<div
className={`token-card-btn ${selectedToken === token.label ? 'selected' : ''}`}
key={token.id}
onClick={() => handleTokenChange(token)}
>
<div className="token-container-deposit">
<input
type="radio"
id={token.id}
checked={selectedToken === token.label}
name="token-options"
value={token.label}
onChange={() => handleTokenChange(token)}
className="token-radio"
/>
<label htmlFor={token.id}>
<h5>
<span className="token-icon-deposit">{token.component}</span>
{token.label}
</h5>
</label>
</div>
</div>
</div>
))}
))}
</div>
</div>
);
};
Expand Down
155 changes: 155 additions & 0 deletions frontend/src/components/ui/token-selector/tokenSelector.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,155 @@
.token-selector-container {
display: flex;
flex-direction: column;
gap: 8px;
}

.token-options {
display: flex;
justify-content: center;
align-items: center;
gap: 8px;
}

.token-card-btn {
width: 100%;
text-align: center;
border: 1px solid var(--secondary);
border-radius: 8px;
padding: 8px;
}

.token-card-btn.selected {
border-image: linear-gradient(to right, #74d6fd, #e01dee) 1;
}

.token-container-deposit {
background: var(--dark-purple);
transition: background 1.3s ease;
padding: 1px;
height: 100%;
}

.token-container:has(input[type='radio']:checked) {
background: var(--button-gradient);
}

.token-icon-deposit {
display: flex;
align-items: center;
justify-content: center;
padding: 5px;
border-radius: 100px;
background-color: hsla(261, 49%, 15%, 1);
}

.token-label {
display: flex;
flex-direction: column;
gap: 5px;
margin-top: 60px;
}

.token-label input {
background-color: transparent;
border: 1px solid var(--light-purple);
border-radius: 50px;
padding: 20px 30px;
color: var(--gray);
}

.token-select {
margin: 8px 0 8px 0;
}

.token-amount {
margin: 20px 0 12px 0;
}

.token-card-btn h5 {
margin-top: 9px;
font-size: 16px;
font-size: 16px;
color: var(--primary);
display: flex;
align-items: center;
justify-content: center;
gap: 6px;
}

.token-card-btn svg {
width: 20px;
height: 20px;
width: 20px;
height: 20px;
}

@media (max-width: 768px) {
.token-card-btn label {
width: 79.5px;
height: 36px;
padding: 4px 8px;
}
}

.token-icon {
display: grid;
gap: 4px;
}

.token-icon-deposit {
margin-right: 5px;
position: relative;
z-index: 1;
}

.token-card-btn {
width: auto;
height: auto;
}

.token-card-btn h5 {
margin: 0;
font-size: 14px;
gap: 0;
}

.token-card-btn svg {
width: 15px;
height: 15px;
}

.token-label input {
border-radius: 16px;
font-size: 14px;
}

.token-container {
max-width: fit-content;
position: relative;
}

.token-label {
margin-top: 0;
}

.token-amount {
margin: 25px 0 12px 0;
}

@media (min-width: 768px) {
.token-card-btn label {
width: 208.67px;
height: 40px;
padding: 4px 8px;
}
}

input[type='radio'] {
display: none;
padding: 2px;
border: 1px solid #ccc;
border-radius: 4px;
width: 100%;
box-sizing: border-box;
}
30 changes: 30 additions & 0 deletions frontend/src/hooks/useAddDeposit.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { useMutation } from '@tanstack/react-query';
import { axiosInstance } from 'utils/axios';
import { notify } from 'components/layout/notifier/Notifier';
import useDashboardData from './useDashboardData';

export const useAddDeposit = () => {
const { data: dashboardData } = useDashboardData();
const mutation = useMutation({
mutationFn: async ({ positionId, amount, tokenSymbol }) => {
if (!dashboardData?.position_id) {
return notify('No position found', 'error');
}

const { data } = await axiosInstance.post(`/api/add-extra-deposit/${positionId}`, {
position_id: dashboardData.position_id,
amount: parseFloat(amount),
token_symbol: tokenSymbol,
});
return data;
},
onSuccess: () => {
notify('Successfully deposited!', 'success');
},
onError: (error) => {
notify(error.response?.data?.message || 'Failed to process deposit', 'error');
},
});

return mutation;
};
84 changes: 84 additions & 0 deletions frontend/src/pages/add-deposit/AddDeposit.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
import React, { useState } from 'react';
import { ReactComponent as HealthIcon } from 'assets/icons/health.svg';
import { ReactComponent as EthIcon } from 'assets/icons/ethereum.svg';
import { useAddDeposit } from 'hooks/useAddDeposit';
import './addDeposit.css';
import Card from 'components/ui/card/Card';
import TokenSelector from 'components/ui/token-selector/TokenSelector';
import { NUMBER_REGEX } from 'utils/regex';

export const AddDeposit = () => {
const [amount, setAmount] = useState('0');
const [selectedToken, setSelectedToken] = useState('STRK');

const { mutate: addDeposit, isLoading } = useAddDeposit();

const handleAmountChange = (e) => {
const value = e.target.value;
if (NUMBER_REGEX.test(value)) {
setAmount(value);
}
};

const handleCancel = () => {
setAmount('0');
setSelectedToken('STRK');
};

const handleDeposit = () => {
addDeposit(
{
amount,
tokenSymbol: selectedToken,
},
{
onSuccess: () => {
setAmount('0');
setSelectedToken('STRK');
},
}
);
};

return (
<div className="deposit-wrapper">
<div className="deposit-container">
<h1 className="deposit-title1">zkLend Deposit</h1>
<div className="main-container-deposit">
<div className="top-cards-deposit">
<Card label="Health Factor" value="1.47570678" icon={<HealthIcon className="icon" />} />
<Card label="Borrow Balance" value="$-55.832665" icon={<EthIcon className="icon" />} />
</div>
</div>
<h1 className="deposit-title2">Pls make a deposit</h1>
<TokenSelector selectedToken={selectedToken} setSelectedToken={setSelectedToken} />

<div className="amount-input-deposit" aria-labelledby="amount-input-label">
<input
type="text"
id="amount-field"
value={amount}
onChange={handleAmountChange}
pattern="^\d*\.?\d*$"
className="amount-field-deposit"
aria-describedby="currency-symbol"
placeholder="0.00"
disabled={isLoading}
/>
<span id="currency-symbol" className="currency-deposit">
{selectedToken}
</span>
</div>

<div className="dep-button">
<button className="deposit-cancel-button" onClick={handleCancel} disabled={isLoading}>
Cancel
</button>
<button className="deposit-button" onClick={handleDeposit} disabled={isLoading || amount === '0'}>
{isLoading ? 'Processing...' : 'Deposit'}
</button>
</div>
</div>
</div>
);
};
Loading

0 comments on commit fa76c77

Please sign in to comment.