+
+
-
Loading...
+
+
Loading...
);
diff --git a/src/components/UI/ContentPreloader/types.ts b/src/components/UI/ContentPreloader/types.ts
new file mode 100644
index 0000000..8b3523d
--- /dev/null
+++ b/src/components/UI/ContentPreloader/types.ts
@@ -0,0 +1,6 @@
+import { CSSProperties } from 'react';
+
+export interface ContentPreloaderProps {
+ className?: string;
+ style?: CSSProperties;
+}
diff --git a/src/components/UI/EmptyMessage/index.tsx b/src/components/UI/EmptyMessage/index.tsx
new file mode 100644
index 0000000..e046819
--- /dev/null
+++ b/src/components/UI/EmptyMessage/index.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+import { ReactComponent as NoOffersIcon } from '@/assets/images/UI/no_offers.svg';
+import { classes } from '@/utils/utils';
+import styles from './styles.module.scss';
+import { EmptyMessageProps } from './types';
+
+const EmptyMessage = ({ text, customIcon }: EmptyMessageProps) => {
+ return (
+
+ {!customIcon ? : customIcon}
+
{text}
+
+ );
+};
+
+export default EmptyMessage;
diff --git a/src/components/UI/EmptyMessage/styles.module.scss b/src/components/UI/EmptyMessage/styles.module.scss
new file mode 100644
index 0000000..8533ba5
--- /dev/null
+++ b/src/components/UI/EmptyMessage/styles.module.scss
@@ -0,0 +1,17 @@
+.empty {
+ width: 100%;
+ margin-top: 40px;
+ display: flex;
+ flex-direction: column;
+ align-items: center;
+ justify-content: center;
+ gap: 20px;
+
+ &__text {
+ color: var(--font-dimmed-color);
+ }
+
+ &__icon {
+ transform: scale(0.8);
+ }
+}
diff --git a/src/components/UI/EmptyMessage/types.ts b/src/components/UI/EmptyMessage/types.ts
new file mode 100644
index 0000000..17d350a
--- /dev/null
+++ b/src/components/UI/EmptyMessage/types.ts
@@ -0,0 +1,6 @@
+import { ReactNode } from 'react';
+
+export interface EmptyMessageProps {
+ text: string;
+ customIcon?: ReactNode;
+}
diff --git a/src/components/UI/RangeInput/RangeInput.module.scss b/src/components/UI/RangeInput/RangeInput.module.scss
index 75bd42c..b68e15e 100644
--- a/src/components/UI/RangeInput/RangeInput.module.scss
+++ b/src/components/UI/RangeInput/RangeInput.module.scss
@@ -9,7 +9,7 @@
background: none;
outline: none;
border: none;
- z-index: 5;
+ z-index: 2;
cursor: pointer;
}
@@ -81,18 +81,4 @@
border: 2px solid var(--window-bg-color);
transition: background 0.3s ease-in-out;
}
-
- // .input__range::-webkit-slider-runnable-track::-webkit-slider-thumb {
- // background-color: #fff;
- // border: 2px solid #555;
- // }
-
- // .input__range::-webkit-slider-runnable-track {
- // -webkit-appearance: none;
- // height: 20px;
- // background-color: #1F8FEB;
- // border: 1px solid #ffffff;
- // box-shadow: none;
- // background: transparent;
- // }
}
diff --git a/src/components/default/Header/Header.module.scss b/src/components/default/Header/Header.module.scss
index 8c4d5ec..2560849 100644
--- a/src/components/default/Header/Header.module.scss
+++ b/src/components/default/Header/Header.module.scss
@@ -11,11 +11,14 @@
position: relative;
&.lg {
- padding: 0 60px;
+ padding-inline: 60px;
- @media screen and (max-width: 1060px) {
- padding-right: 20px;
- padding-left: 20px;
+ @media screen and (max-width: 1600px) {
+ padding-inline: 40px;
+ }
+
+ @media screen and (max-width: 1200px) {
+ padding-inline: 20px;
}
}
diff --git a/src/constants/index.ts b/src/constants/index.ts
new file mode 100644
index 0000000..89d2759
--- /dev/null
+++ b/src/constants/index.ts
@@ -0,0 +1,36 @@
+import PeriodState from '@/interfaces/states/pages/dex/trading/InputPanelItem/PeriodState';
+import SelectValue from '@/interfaces/states/pages/dex/trading/InputPanelItem/SelectValue';
+
+export const periods: PeriodState[] = [
+ {
+ name: '1H',
+ code: '1h',
+ },
+ {
+ name: '1D',
+ code: '1d',
+ },
+ {
+ name: '1W',
+ code: '1w',
+ },
+ {
+ name: '1M',
+ code: '1m',
+ },
+];
+
+export const buySellValues: SelectValue[] = [
+ {
+ name: 'All',
+ code: 'all',
+ },
+ {
+ name: 'Buy',
+ code: 'buy',
+ },
+ {
+ name: 'Sell',
+ code: 'sell',
+ },
+];
diff --git a/src/hook/useAlert.ts b/src/hook/useAlert.ts
new file mode 100644
index 0000000..dd282cc
--- /dev/null
+++ b/src/hook/useAlert.ts
@@ -0,0 +1,22 @@
+import AlertType from '@/interfaces/common/AlertType';
+import { Store } from '@/store/store-reducer';
+import { useContext } from 'react';
+
+export const useAlert = () => {
+ const { state, dispatch } = useContext(Store);
+
+ const setAlertState = (state: AlertType) => {
+ dispatch({ type: 'ALERT_STATE_UPDATED', payload: state });
+ };
+
+ const setAlertSubtitle = (subtitle: string) => {
+ dispatch({ type: 'ALERT_SUBTITLE_UPDATED', payload: subtitle });
+ };
+
+ return {
+ alertState: state.alertState,
+ alertSubtitle: state.alertSubtitle,
+ setAlertState,
+ setAlertSubtitle,
+ };
+};
diff --git a/src/hook/useMouseLeave.ts b/src/hook/useMouseLeave.ts
new file mode 100644
index 0000000..dc284ec
--- /dev/null
+++ b/src/hook/useMouseLeave.ts
@@ -0,0 +1,21 @@
+import { ForwardedRef, useEffect } from 'react';
+
+const useMouseLeave = (ref: ForwardedRef
, callbackFn: () => void) => {
+ useEffect(() => {
+ const targetEl = (event: MouseEvent) => {
+ if (ref && typeof ref !== 'function' && ref.current) {
+ if (ref?.current && !ref?.current.contains(event.target as Node)) {
+ callbackFn();
+ }
+ }
+ };
+
+ window.addEventListener('mousemove', targetEl);
+
+ return () => {
+ window.removeEventListener('mousemove', targetEl);
+ };
+ }, []);
+};
+
+export default useMouseLeave;
diff --git a/src/hook/useScroll.ts b/src/hook/useScroll.ts
new file mode 100644
index 0000000..baf2f2c
--- /dev/null
+++ b/src/hook/useScroll.ts
@@ -0,0 +1,20 @@
+import { useCallback, useRef } from 'react';
+
+function useScroll() {
+ const elementRef = useRef(null);
+
+ const scrollToElement = useCallback((options?: ScrollIntoViewOptions) => {
+ if (elementRef.current) {
+ elementRef.current.scrollIntoView({
+ behavior: 'smooth',
+ block: 'center',
+ inline: 'nearest',
+ ...options,
+ });
+ }
+ }, []);
+
+ return { elementRef, scrollToElement };
+}
+
+export default useScroll;
diff --git a/src/interfaces/common/ContextValue.ts b/src/interfaces/common/ContextValue.ts
index 43ed69e..4ca5496 100644
--- a/src/interfaces/common/ContextValue.ts
+++ b/src/interfaces/common/ContextValue.ts
@@ -1,6 +1,7 @@
import { Dispatch } from 'react';
import { GetUserResData } from '../responses/user/GetUserRes';
import { GetConfigResData } from '../responses/config/GetConfigRes';
+import AlertType from './AlertType';
export interface Asset {
name: string;
@@ -50,6 +51,8 @@ interface ContextState {
offers: number;
};
closed_notifications: number[];
+ alertState: AlertType;
+ alertSubtitle: string;
}
type ContextAction =
@@ -75,6 +78,14 @@ type ContextAction =
| {
type: 'CLOSED_NOTIFICATIONS_UPDATED';
payload: number[];
+ }
+ | {
+ type: 'ALERT_STATE_UPDATED';
+ payload: AlertType;
+ }
+ | {
+ type: 'ALERT_SUBTITLE_UPDATED';
+ payload: string;
};
interface ContextValue {
diff --git a/src/interfaces/common/MatrixAddress.ts b/src/interfaces/common/MatrixAddress.ts
new file mode 100644
index 0000000..23f6451
--- /dev/null
+++ b/src/interfaces/common/MatrixAddress.ts
@@ -0,0 +1,6 @@
+interface MatrixAddress {
+ address: string;
+ registered: boolean;
+}
+
+export default MatrixAddress;
diff --git a/src/interfaces/common/orderFormOutput.ts b/src/interfaces/common/orderFormOutput.ts
new file mode 100644
index 0000000..e31124a
--- /dev/null
+++ b/src/interfaces/common/orderFormOutput.ts
@@ -0,0 +1,24 @@
+import { Dispatch, SetStateAction } from 'react';
+
+interface OrderFormOutput {
+ price: string;
+ amount: string;
+ total: string;
+ priceValid: boolean;
+ amountValid: boolean;
+ totalValid: boolean;
+ totalUsd: string | undefined;
+ rangeInputValue: string;
+ setRangeInputValue: Dispatch>;
+ onPriceChange: (_inputValue: string) => void;
+ onAmountChange: (_inputValue: string) => void;
+ resetForm: () => void;
+ setTotal: Dispatch>;
+ setPrice: Dispatch>;
+ setAmount: Dispatch>;
+ setPriceValid: Dispatch>;
+ setAmountValid: Dispatch>;
+ setTotalValid: Dispatch>;
+}
+
+export default OrderFormOutput;
diff --git a/src/interfaces/props/pages/dex/trading/InputPanelItem/InputPanelItemProps.ts b/src/interfaces/props/pages/dex/trading/InputPanelItem/InputPanelItemProps.ts
index 89e795b..d3897ea 100644
--- a/src/interfaces/props/pages/dex/trading/InputPanelItem/InputPanelItemProps.ts
+++ b/src/interfaces/props/pages/dex/trading/InputPanelItem/InputPanelItemProps.ts
@@ -1,22 +1,20 @@
-import AlertType from '@/interfaces/common/AlertType';
import SelectValue from '@/interfaces/states/pages/dex/trading/InputPanelItem/SelectValue';
import { Dispatch, SetStateAction } from 'react';
interface InputPanelItemProps {
+ currencyNames: {
+ firstCurrencyName: string;
+ secondCurrencyName: string;
+ };
priceState: string;
amountState: string;
totalState: string;
buySellValues: SelectValue[];
buySellState: SelectValue;
- // setBuySellState: Dispatch>;
setPriceFunction: (_value: string) => void;
setAmountFunction: (_value: string) => void;
- setAlertState: Dispatch>;
- setAlertSubtitle: Dispatch>;
setRangeInputValue: Dispatch>;
rangeInputValue: string;
- firstCurrencyName: string;
- secondCurrencyName: string;
balance: number | undefined;
amountValid: boolean;
priceValid: boolean;
diff --git a/src/interfaces/props/pages/dex/trading/StatItemProps.ts b/src/interfaces/props/pages/dex/trading/StatItemProps.ts
index cf99aeb..20f0ec3 100644
--- a/src/interfaces/props/pages/dex/trading/StatItemProps.ts
+++ b/src/interfaces/props/pages/dex/trading/StatItemProps.ts
@@ -5,6 +5,7 @@ interface StatItemProps {
title: string;
value: string;
coefficient?: number;
+ className?: string;
}
export default StatItemProps;
diff --git a/src/pages/_app.tsx b/src/pages/_app.tsx
index bce9305..dc7bb30 100644
--- a/src/pages/_app.tsx
+++ b/src/pages/_app.tsx
@@ -1,5 +1,6 @@
import '@/styles/globals.scss';
import '@/styles/themes/light.scss';
+import '@/styles/themes/dark.scss';
import Head from 'next/head';
import { StoreProvider } from '@/store/store-reducer';
import NextApp, { AppContext, AppProps } from 'next/app';
diff --git a/src/pages/dex/trading/InputPanelItem/InputPanelItem.module.scss b/src/pages/dex/trading/InputPanelItem/InputPanelItem.module.scss
deleted file mode 100644
index 5ad992f..0000000
--- a/src/pages/dex/trading/InputPanelItem/InputPanelItem.module.scss
+++ /dev/null
@@ -1,243 +0,0 @@
-.input_panel__item {
- width: 100%;
-
- &_header {
- display: flex;
- justify-content: space-between;
- align-items: center;
- padding-bottom: 10px;
- border-bottom: 1px solid rgba(255, 255, 255, 0.1);
- margin-bottom: 10px;
-
- h5 {
- font-size: 16px;
- font-weight: 600;
- }
-
- .input_panel__fees {
- display: flex;
- justify-content: space-between;
- font-weight: 400;
- font-size: 12px;
-
- p {
- color: var(--table-th-color);
- font-weight: 400;
- font-size: 12px;
- }
-
- span {
- font-weight: 400;
- font-size: 12px;
- }
- }
- }
-
- &_body {
- display: flex;
- flex-direction: column;
- gap: 10px;
-
- button {
- margin-top: 10px;
- }
-
- > .buy_btn {
- background-color: #16d1d6;
-
- &:hover {
- background-color: #45dade;
- }
- }
-
- > .sell_btn {
- background-color: #ff6767;
-
- &:hover {
- background-color: #ff8585;
- }
- }
-
- .input_panel__range {
- margin-top: 10px;
- }
-
- .input_panel__expiration {
- display: flex;
- justify-content: space-between;
- gap: 20px;
-
- h6 {
- white-space: nowrap;
- }
-
- .expiration__dropdown {
- width: 100%;
- }
-
- > div:first-child {
- display: flex;
- align-items: center;
- gap: 6px;
- }
-
- @media screen and (max-width: 1500px) {
- flex-wrap: wrap;
- }
-
- @media screen and (max-width: 1000px) {
- flex-wrap: nowrap;
- }
-
- @media screen and (max-width: 530px) {
- flex-wrap: wrap;
- }
- }
-
- .labeled_input {
- display: flex;
- flex-direction: column;
- gap: 8px;
-
- h6 {
- font-size: 11px;
- font-family: 700;
- color: var(--table-th-color);
- }
-
- > div {
- width: 100%;
- position: relative;
- background-color: var(--bordered-input-bg);
- border: 1px solid var(--window-border-color);
- border-radius: 8px;
- display: flex;
- overflow: hidden;
-
- input {
- width: 100%;
- padding: 13px 15px;
- background-color: transparent;
- border: none;
- font-size: 16px;
- font-weight: 400;
- }
-
- .labeled_input__value {
- padding-right: 10px;
- display: flex;
- align-items: center;
-
- > p {
- color: var(--table-th-color);
- font-size: 12px;
- font-weight: 400;
- }
- }
-
- .labeled_input__currency {
- min-width: 82px;
- max-width: 150px;
- padding: 0 15px;
- background-color: var(--dex-input-currency);
- display: flex;
- align-items: center;
- justify-content: center;
-
- > p {
- white-space: nowrap;
- overflow: hidden;
- text-overflow: ellipsis;
- }
- }
- }
-
- &.labeled_input__invalid > div {
- border-color: #ff6767;
- }
-
- @media screen and (max-width: 430px) {
- > div {
- input,
- .labeled_input__value > p,
- .labeled_input__currency > p {
- font-size: 13px;
- }
-
- input {
- padding: 19px 15px;
- }
-
- .labeled_input__currency {
- min-width: 70px;
- }
- }
- }
- }
- }
-}
-
-.buy-sell-switch {
- padding: 3px;
- height: 30px;
- display: flex;
- align-items: center;
- border-radius: 100px;
- border: 1px solid var(--dex-buy-sell-border);
-
- .buy-sell-switch__item {
- width: 50px;
- height: 100%;
- background-color: transparent;
- cursor: pointer;
- font-size: 14px;
- font-weight: 600;
- border-radius: 100px;
-
- &.item_selected-buy {
- background-color: #16d1d6;
- color: #ffffff;
- }
-
- &.item_selected-sell {
- background-color: #ff6767;
- color: #ffffff;
- }
- }
-}
-
-.apply__alert {
- display: flex;
- gap: 20px;
- align-items: center;
-
- &__content {
- display: flex;
- flex-direction: column;
- gap: 10px;
- }
-
- &__button {
- max-width: 125px;
- background-color: var(--alert-btn-bg);
- color: #1f8feb;
- padding: 7px 32px;
- font-size: 12px;
- font-weight: 500;
-
- &:hover {
- background-color: var(--alert-btn-hover);
- }
- }
-
- h2 {
- font-size: 16px;
- font-weight: 600;
- }
-
- p {
- font-size: 14px;
- opacity: 0.7;
- margin-bottom: 5px;
- }
-}
diff --git a/src/pages/dex/trading/OrdersBuySellSwitch/OrdersBuySellSwitch.module.scss b/src/pages/dex/trading/OrdersBuySellSwitch/OrdersBuySellSwitch.module.scss
deleted file mode 100644
index aac0fd1..0000000
--- a/src/pages/dex/trading/OrdersBuySellSwitch/OrdersBuySellSwitch.module.scss
+++ /dev/null
@@ -1,31 +0,0 @@
-.orders-buy-sell-switch {
- display: flex;
- align-items: center;
- gap: 8px;
- background-color: transparent !important;
- cursor: pointer;
-
- &:hover {
- opacity: 0.7;
- }
-
- > p {
- font-size: 16px;
- font-weight: 600;
- color: #16d1d6;
- }
-
- > svg > * {
- fill: transparent;
- }
-
- &.orders-buy-sell-switch_sell {
- > p {
- color: #ff6767;
- }
-
- > svg > * {
- stroke: #ff6767;
- }
- }
-}
diff --git a/src/pages/dex/trading/OrdersBuySellSwitch/OrdersBuySellSwitch.tsx b/src/pages/dex/trading/OrdersBuySellSwitch/OrdersBuySellSwitch.tsx
deleted file mode 100644
index fbe8d93..0000000
--- a/src/pages/dex/trading/OrdersBuySellSwitch/OrdersBuySellSwitch.tsx
+++ /dev/null
@@ -1,33 +0,0 @@
-import HorizontalSelectProps from '@/interfaces/props/components/UI/HorizontalSelect/HorizontalSelectProps';
-import { ReactComponent as ArrowIcon } from '@/assets/images/UI/trade_arrow.svg';
-import SelectValue from '@/interfaces/states/pages/dex/trading/InputPanelItem/SelectValue';
-import { classes } from '@/utils/utils';
-import styles from './OrdersBuySellSwitch.module.scss';
-
-export default function OrdersBuySellSwitch({
- body,
- value,
- setValue,
- className,
-}: HorizontalSelectProps) {
- const defaultValue = body[0];
-
- const buyValue = body.find((e) => e.code === 'buy');
- const sellValue = body.find((e) => e.code === 'sell');
-
- const isBuy = value.code === 'buy';
-
- return (
-
- );
-}
diff --git a/src/pages/dex/trading/[id].tsx b/src/pages/dex/trading/[id].tsx
index 5cfb914..7ef62e0 100644
--- a/src/pages/dex/trading/[id].tsx
+++ b/src/pages/dex/trading/[id].tsx
@@ -1,45 +1,12 @@
import styles from '@/styles/Trading.module.scss';
import Footer from '@/components/default/Footer/Footer';
import Header from '@/components/default/Header/Header';
-import { ReactComponent as ClockIcon } from '@/assets/images/UI/clock_icon.svg';
-import { ReactComponent as UpIcon } from '@/assets/images/UI/up_icon.svg';
-import { ReactComponent as DownIcon } from '@/assets/images/UI/down_icon.svg';
-import { ReactComponent as VolumeIcon } from '@/assets/images/UI/volume_icon.svg';
-import { ReactComponent as NoOffersIcon } from '@/assets/images/UI/no_offers.svg';
import Dropdown from '@/components/UI/Dropdown/Dropdown';
import HorizontalSelect from '@/components/UI/HorizontalSelect/HorizontalSelect';
-import { useContext, useEffect, useRef, useState } from 'react';
-import { Store } from '@/store/store-reducer';
-import { useRouter } from 'next/router';
-import {
- applyOrder,
- cancelOrder,
- getOrdersPage,
- confirmTransaction,
- getPair,
- getPairStats,
- getUserOrdersPage,
- getCandles,
- getTrades,
-} from '@/utils/methods';
+import { useCallback, useState } from 'react';
+import { cancelOrder } from '@/utils/methods';
import ContentPreloader from '@/components/UI/ContentPreloader/ContentPreloader';
-import Link from 'next/link';
-import { nanoid } from 'nanoid';
-import {
- classes,
- cutAddress,
- formatDollarValue,
- formatTime,
- isPositiveFloatStr,
- notationToString,
- roundTo,
- shortenAddress,
- tradingKnownCurrencies,
-} from '@/utils/utils';
import Alert from '@/components/UI/Alert/Alert';
-import socket from '@/utils/socket';
-import SelectValue from '@/interfaces/states/pages/dex/trading/InputPanelItem/SelectValue';
-import AlertType from '@/interfaces/common/AlertType';
import PeriodState from '@/interfaces/states/pages/dex/trading/InputPanelItem/PeriodState';
import OrderRow from '@/interfaces/common/OrderRow';
import ApplyTip from '@/interfaces/common/ApplyTip';
@@ -47,1183 +14,112 @@ import { PageOrderData } from '@/interfaces/responses/orders/GetOrdersPageRes';
import { PairStats } from '@/interfaces/responses/orders/GetPairStatsRes';
import PairData from '@/interfaces/common/PairData';
import CandleRow from '@/interfaces/common/CandleRow';
-import StatItemProps from '@/interfaces/props/pages/dex/trading/StatItemProps';
-import { confirmIonicSwap, ionicSwap } from '@/utils/wallet';
-import Decimal from 'decimal.js';
-import Tooltip from '@/components/UI/Tooltip/Tooltip';
-import { updateAutoClosedNotification } from '@/store/actions';
-import useUpdateUser from '@/hook/useUpdateUser';
-import LightningImg from '@/assets/images/UI/lightning.png';
-import RocketImg from '@/assets/images/UI/rocket.png';
-import { ReactComponent as ConnectionIcon } from '@/assets/images/UI/connection.svg';
-import Image from 'next/image';
-import BackButton from '@/components/default/BackButton/BackButton';
import { Trade } from '@/interfaces/responses/trades/GetTradeRes';
-import CandleChart from './CandleChart/CandleChart';
-import InputPanelItem from './InputPanelItem/InputPanelItem';
-import { validateTokensInput } from '../../../../shared/utils';
+import { periods, buySellValues } from '@/constants';
+import { useAlert } from '@/hook/useAlert';
+import useScroll from '@/hook/useScroll';
+import CandleChart from './components/CandleChart';
+import InputPanelItem from './components/InputPanelItem';
+import TradingHeader from './components/TradingHeader';
+import UserOrders from './components/UserOrders';
+import AllTrades from './components/AllTrades';
+import OrdersPool from './components/OrdersPool';
+import { useSocketListeners } from './hooks/useSocketListeners';
+import { useTradingData } from './hooks/useTradingData';
+import takeOrderClick from './helpers/takeOrderClick';
+import useFilteredData from './hooks/useFilteredData';
+import useTradeInit from './hooks/useTradeInit';
+import useMatrixAddresses from './hooks/useMatrixAddresses';
-function BadgeStatus({ type = 'instant', icon }: { type?: 'instant' | 'high'; icon?: boolean }) {
- return (
-
-
- {!icon && {type === 'instant' ? 'instant' : 'high volume'}}
-
- );
-}
+const CHART_OPTIONS = [{ name: 'Zano Chart' }, { name: 'Trading View', disabled: true }];
+const DEFAULT_CHART = CHART_OPTIONS[0];
function Trading() {
- const router = useRouter();
- const fetchUser = useUpdateUser();
+ const { alertState, alertSubtitle, setAlertState } = useAlert();
+ const { elementRef: orderListRef, scrollToElement: scrollToOrdersList } =
+ useScroll();
+ const { elementRef: orderFormRef, scrollToElement: scrollToOrderForm } =
+ useScroll();
const [ordersHistory, setOrdersHistory] = useState([]);
-
- const orderFormRef = useRef(null);
- const orderListRef = useRef(null);
-
- const pairId = typeof router.query.id === 'string' ? router.query.id : '';
-
- const periods: PeriodState[] = [
- {
- name: '1H',
- code: '1h',
- },
- {
- name: '1D',
- code: '1d',
- },
- {
- name: '1W',
- code: '1w',
- },
- {
- name: '1M',
- code: '1m',
- },
- ];
-
- const buySellValues: SelectValue[] = [
- {
- name: 'All',
- code: 'all',
- },
- {
- name: 'Buy',
- code: 'buy',
- },
- {
- name: 'Sell',
- code: 'sell',
- },
- ];
-
- const { state, dispatch } = useContext(Store);
-
const [userOrders, setUserOrders] = useState([]);
-
const [periodsState, setPeriodsState] = useState(periods[0]);
-
const [pairData, setPairData] = useState(null);
-
const [candles, setCandles] = useState([]);
-
- const [candlesLoaded, setCandlesLoaded] = useState(false);
-
- const [ordersLoading, setOrdersLoading] = useState(true);
-
const [trades, setTrades] = useState([]);
- const [tradesLoading, setTradesLoading] = useState(true);
-
const [myOrdersLoading, setMyOrdersLoading] = useState(true);
-
const [ordersBuySell, setOrdersBuySell] = useState(buySellValues[0]);
-
const [tradesType, setTradesType] = useState<'all' | 'my'>('all');
-
const [ordersType, setOrdersType] = useState<'opened' | 'history'>('opened');
-
const [pairStats, setPairStats] = useState(null);
-
const [applyTips, setApplyTips] = useState([]);
+ const matrixAddresses = useMatrixAddresses(ordersHistory);
- const [alertState, setAlertState] = useState(null);
+ const {
+ buyForm,
+ sellForm,
+ currencyNames,
+ firstAssetLink,
+ secondAssetLink,
+ secondAssetUsdPrice,
+ balance,
+ loggedIn,
+ pairRateUsd,
+ } = useTradeInit({ pairData, pairStats });
- const [alertSubtitle, setAlertSubtitle] = useState('');
+ const {
+ fetchTrades,
+ updateOrders,
+ updateUserOrders,
+ candlesLoaded,
+ ordersLoading,
+ tradesLoading,
+ } = useTradingData({
+ periodsState,
+ setApplyTips,
+ setCandles,
+ setMyOrdersLoading,
+ setOrdersHistory,
+ setPairData,
+ setPairStats,
+ setTrades,
+ setUserOrders,
+ });
- const [ordersInfoTooltip, setOrdersInfoTooltip] = useState(null);
- const ordersInfoRef = useRef(null);
- const [infoTooltipPos, setInfoTooltipPos] = useState({ x: 0, y: 0 });
+ useSocketListeners({
+ setUserOrders,
+ ordersHistory,
+ setApplyTips,
+ setOrdersHistory,
+ setPairStats,
+ updateOrders,
+ });
- async function fetchTrades() {
- setTradesLoading(true);
- const result = await getTrades(pairId);
-
- if (result.success) {
- setTrades(result.data);
- }
-
- setTradesLoading(false);
- }
-
- useEffect(() => {
- (async () => {
- await fetchTrades();
- })();
- }, [pairId]);
-
- const filteredTrades =
- tradesType === 'my'
- ? trades.filter(
- (trade) =>
- trade.buyer.address === state.wallet?.address ||
- trade.seller.address === state.wallet?.address,
- )
- : trades;
-
- useEffect(() => {
- const targetEl = (event: MouseEvent) => {
- if (ordersInfoRef.current && !ordersInfoRef.current.contains(event.target as Node)) {
- setOrdersInfoTooltip(null);
- }
- };
-
- window.addEventListener('mousemove', targetEl);
-
- return () => {
- window.removeEventListener('mousemove', targetEl);
- };
- }, []);
-
- const moveInfoTooltip = (event: React.MouseEvent) => {
- setInfoTooltipPos({ x: event.clientX, y: event.clientY });
- };
-
- const [matrixAddresses, setMatrixAddresses] = useState([]);
-
- async function updateOrders() {
- setOrdersLoading(true);
- const result = await getOrdersPage(pairId);
- if (!result.success) return;
- setOrdersHistory(result?.data || []);
- setOrdersLoading(false);
- }
-
- async function socketUpdateOrders() {
- const result = await getUserOrdersPage(pairId);
-
- if (result.success) {
- setUserOrders(result?.data?.orders || []);
- setApplyTips(result?.data?.applyTips || []);
- }
- }
-
- useEffect(() => {
- socket.emit('in-trading', { id: router.query.id });
-
- return () => {
- socket.emit('out-trading', { id: router.query.id });
- };
- }, []);
-
- useEffect(() => {
- socket.on('new-order', async (data) => {
- setOrdersHistory([data.orderData, ...ordersHistory]);
- await socketUpdateOrders();
- });
-
- socket.on('delete-order', async () => {
- await updateOrders();
- await socketUpdateOrders();
- });
-
- return () => {
- socket.off('new-order');
- socket.off('delete-order');
- };
- }, [ordersHistory]);
-
- useEffect(() => {
- function onUpdateStats({ pairStats }: { pairStats: PairStats }) {
- setPairStats(pairStats);
- }
-
- socket.on('update-pair-stats', onUpdateStats);
-
- return () => {
- socket.off('update-pair-stats', onUpdateStats);
- };
- }, []);
-
- useEffect(() => {
- socket.on('update-orders', async () => {
- await socketUpdateOrders();
- });
-
- return () => {
- socket.off('update-orders');
- };
- }, []);
-
- // Detect registered addresses
- const hasConnection = (address: string) =>
- matrixAddresses.some(
- (item: { address: string; registered: boolean }) =>
- item.address === address && item.registered,
- );
-
- const filteredOrdersHistory = ordersHistory
- ?.filter((e) => (ordersBuySell.code === 'all' ? e : e.type === ordersBuySell.code))
- ?.filter((e) => e.user.address !== state.wallet?.address)
- ?.sort((a, b) => {
- if (ordersBuySell.code === 'buy') {
- return parseFloat(b.price.toString()) - parseFloat(a.price.toString());
- }
- return parseFloat(a.price.toString()) - parseFloat(b.price.toString());
- });
-
- // Get registered addresses from matrix
- useEffect(() => {
- const fetchConnections = async () => {
- const filteredAddresses = ordersHistory?.map((e) => e?.user?.address);
- if (!filteredAddresses.length) return;
- const response = await fetch('https://messenger.zano.org/api/get-addresses', {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- },
- body: JSON.stringify({
- addresses: filteredAddresses,
- }),
+ // Take order from trades
+ const onHandleTakeOrder = useCallback(
+ (
+ event:
+ | React.MouseEvent
+ | React.MouseEvent,
+ e: PageOrderData,
+ ) => {
+ takeOrderClick({
+ event,
+ PageOrderData: e,
+ balance,
+ buyForm,
+ pairData,
+ scrollToOrderForm,
+ sellForm,
});
+ },
+ [balance, buyForm, pairData, scrollToOrderForm, sellForm],
+ );
- const data = await response.json();
- setMatrixAddresses(data.addresses);
- };
+ // Cancel all user orders
+ const handleCancelAllOrders = useCallback(async () => {
+ if (!userOrders.length) return;
- fetchConnections();
- }, [ordersHistory]);
-
- const firstCurrencyName = pairData?.first_currency?.name || '';
- const secondCurrencyName = pairData?.second_currency?.name || '';
-
- const firstAssetId = pairData ? pairData.first_currency?.asset_id : undefined;
- const secondAssetId = pairData ? pairData.second_currency?.asset_id : undefined;
- const firstAssetLink = firstAssetId
- ? `https://explorer.zano.org/assets?asset_id=${encodeURIComponent(firstAssetId)}`
- : undefined;
- const secondAssetLink = secondAssetId
- ? `https://explorer.zano.org/assets?asset_id=${encodeURIComponent(secondAssetId)}`
- : undefined;
-
- const secondAssetUsdPrice = state.assetsRates.get(secondAssetId || '');
- const secondCurrencyDP = pairData?.second_currency.asset_info?.decimal_point || 12;
-
- useEffect(() => {
- async function fetchPairStats() {
- const result = await getPairStats(pairId);
- if (!result.success) return;
- setPairStats(result.data);
- }
-
- fetchPairStats();
- }, []);
-
- useEffect(() => {
- async function fetchCandles() {
- setCandlesLoaded(false);
- setCandles([]);
- const result = await getCandles(pairId, periodsState.code);
- if (result.success) {
- setCandles(result.data);
- } else {
- setCandles([]);
- }
- setCandlesLoaded(true);
- }
-
- fetchCandles();
- }, [periodsState]);
-
- useEffect(() => {
- async function getPairData() {
- const result = await getPair(pairId);
- if (!result.success) {
- router.push('/404');
- return;
- }
- setPairData(result.data);
- }
-
- getPairData();
- }, []);
-
- async function updateUserOrders() {
- setMyOrdersLoading(true);
- const result = await getUserOrdersPage(pairId);
- console.log('result getuserorderspage', result);
- await fetchUser();
-
- if (!result.success) return;
- setUserOrders(result?.data?.orders || []);
- setApplyTips(result?.data?.applyTips || []);
- setMyOrdersLoading(false);
- }
-
- const loggedIn = !!state.wallet?.connected;
-
- useEffect(() => {
- if (!loggedIn) return;
- setUserOrders([]);
- updateUserOrders();
- }, [state.wallet?.connected && state.wallet?.address]);
-
- useEffect(() => {
- updateOrders();
- }, []);
-
- // useEffect(() => {
- // socket.on
- // }, []);
-
- const [priceState, setPriceState] = useState('');
- const [amountState, setAmountState] = useState('');
- const [totalState, setTotalState] = useState('');
-
- const [priceSellState, setPriceSellState] = useState('');
- const [amountSellState, setAmountSellState] = useState('');
- const [totalSellState, setTotalSellState] = useState('');
-
- const [totalUsd, setTotalUsd] = useState(undefined);
- const [totalSellUsd, setTotalSellUsd] = useState(undefined);
-
- const [priceValid, setPriceValid] = useState(false);
- const [amountValid, setAmountValid] = useState(false);
- const [totalValid, setTotalValid] = useState(false);
- const [priceSellValid, setPriceSellValid] = useState(false);
- const [amountSellValid, setAmountSellValid] = useState(false);
- const [totalSellValid, setTotalSellValid] = useState(false);
-
- const [buySellState, setBuySellState] = useState(buySellValues[0]);
-
- const [rangeInputValue, setRangeInputValue] = useState('50');
- const [rangeInputSellValue, setRangeInputSellValue] = useState('50');
-
- useEffect(() => {
- let totalDecimal: Decimal | undefined;
-
- try {
- totalDecimal = new Decimal(totalState);
- } catch (err) {
- console.log(err);
- }
-
- const zanoPrice = state.assetsRates.get(pairData?.second_currency?.asset_id || '');
-
- setTotalUsd(zanoPrice && totalDecimal ? totalDecimal.mul(zanoPrice).toFixed(2) : undefined);
- }, [totalState, state.assetsRates, pairData?.second_currency?.asset_id]);
-
- useEffect(() => {
- let totalSellDecimal: Decimal | undefined;
-
- try {
- totalSellDecimal = new Decimal(totalSellState);
- } catch (error) {
- console.log(error);
- }
-
- const zanoPrice = state.assetsRates.get(pairData?.second_currency?.asset_id || '');
-
- setTotalSellUsd(
- zanoPrice && totalSellDecimal ? totalSellDecimal.mul(zanoPrice).toFixed(2) : undefined,
- );
- }, [totalSellState, state.assetsRates, pairData?.second_currency?.asset_id]);
-
- function setPriceFunction(inputValue: string) {
- if (inputValue !== '' && !isPositiveFloatStr(inputValue)) {
- return;
- }
-
- try {
- const value = new Decimal(inputValue || NaN);
-
- if (value.toString().replace('.', '').length > 18) {
- console.log('TOO MANY DECIMALS');
- return;
- }
- } catch (error) {
- console.log(error);
- }
-
- setPriceState(inputValue);
-
- if (!inputValue) {
- setTotalState('');
- setTotalValid(false);
- setPriceValid(false);
- return;
- }
-
- const valueDecimal = new Decimal(inputValue || NaN);
- const amountDecimal = new Decimal(amountState || NaN);
-
- const validationResult = validateTokensInput(inputValue, secondCurrencyDP);
-
- if (!validationResult.valid) {
- setTotalState('');
- setTotalValid(false);
- setPriceValid(false);
- return;
- }
-
- setPriceValid(true);
-
- if (!valueDecimal.isNaN() && !amountDecimal.isNaN() && amountState !== '') {
- const totalDecimal = valueDecimal.mul(amountDecimal);
- setTotalState(totalDecimal.toString());
- const total = totalDecimal.toFixed(secondCurrencyDP);
-
- const totalValidationResult = validateTokensInput(total, secondCurrencyDP);
-
- setTotalValid(totalValidationResult.valid);
- } else {
- setTotalState('');
- setTotalValid(false);
- }
- }
-
- function setPriceSellFunction(inputValue: string) {
- if (inputValue !== '' && !isPositiveFloatStr(inputValue)) {
- return;
- }
-
- try {
- const value = new Decimal(inputValue || NaN);
-
- if (value.toString().replace('.', '').length > 18) {
- console.log('TOO MANY DECIMALS');
- return;
- }
- } catch (error) {
- console.log(error);
- }
-
- setPriceSellState(inputValue);
-
- if (!inputValue) {
- setTotalSellState('');
- setTotalSellValid(false);
- setPriceSellValid(false);
- return;
- }
-
- const valueDecimal = new Decimal(inputValue || NaN);
- const amountDecimal = new Decimal(amountSellState || NaN);
-
- const secondCurrencyDP = pairData?.second_currency.asset_info?.decimal_point || 12;
-
- const validationResult = validateTokensInput(inputValue, secondCurrencyDP);
-
- if (!validationResult.valid) {
- setTotalSellState('');
- setTotalSellValid(false);
- setPriceSellValid(false);
- return;
- }
-
- setPriceSellValid(true);
-
- if (!valueDecimal.isNaN() && !amountDecimal.isNaN() && amountSellState !== '') {
- const total = valueDecimal.mul(amountDecimal).toFixed();
- setTotalSellState(total);
-
- const totalValidationResult = validateTokensInput(total, secondCurrencyDP);
-
- setTotalSellValid(totalValidationResult.valid);
- } else {
- setTotalSellState('');
- setTotalSellValid(false);
- }
- }
-
- const assets = state.wallet?.connected ? state.wallet?.assets || [] : [];
-
- const balance = assets.find((e) => e.ticker === firstCurrencyName)?.balance;
-
- function setAmountFunction(inputValue: string) {
- if (inputValue !== '' && !isPositiveFloatStr(inputValue)) {
- return;
- }
-
- try {
- const value = new Decimal(inputValue || NaN);
-
- if (value.toString().replace('.', '').length > 18) {
- console.log('TOO MANY DECIMALS');
- return;
- }
- } catch (error) {
- console.log(error);
- }
-
- setAmountState(inputValue);
-
- if (!inputValue) {
- setTotalState('');
- setTotalValid(false);
- setAmountValid(false);
- return;
- }
-
- const value = new Decimal(inputValue || NaN);
- const price = new Decimal(priceState || NaN);
-
- const validationResult = validateTokensInput(
- inputValue,
- pairData?.first_currency.asset_info?.decimal_point || 12,
- );
- console.log(validationResult);
-
- if (!validationResult.valid) {
- setTotalState('');
- setTotalValid(false);
- setAmountValid(false);
- return;
- }
-
- setAmountValid(true);
-
- if (balance) setRangeInputValue(value.div(balance).mul(100).toFixed());
-
- if (!price.isNaN() && !value.isNaN() && priceState !== '') {
- const totalDecimal = value.mul(price);
- setTotalState(totalDecimal.toString());
- const total = totalDecimal.toFixed(secondCurrencyDP);
- const totalValidationResult = validateTokensInput(total, secondCurrencyDP);
-
- setTotalValid(totalValidationResult.valid);
- } else {
- setTotalState('');
- setTotalValid(false);
- }
- }
-
- function setAmountSellFunction(inputValue: string) {
- if (inputValue !== '' && !isPositiveFloatStr(inputValue)) {
- return;
- }
-
- try {
- const value = new Decimal(inputValue || NaN);
-
- if (value.toString().replace('.', '').length > 18) {
- console.log('TOO MANY DECIMALS');
- return;
- }
- } catch (error) {
- console.log(error);
- }
-
- setAmountSellState(inputValue);
-
- if (!inputValue) {
- setTotalSellState('');
- setTotalSellValid(false);
- setAmountSellValid(false);
- return;
- }
-
- const value = new Decimal(inputValue || NaN);
- const price = new Decimal(priceSellState || NaN);
-
- const validationResult = validateTokensInput(
- inputValue,
- pairData?.first_currency.asset_info?.decimal_point || 12,
- );
- console.log(validationResult);
-
- if (!validationResult.valid) {
- setTotalSellState('');
- setTotalSellValid(false);
- setAmountSellValid(false);
- return;
- }
-
- setAmountSellValid(true);
-
- if (balance) setRangeInputSellValue(value.div(balance).mul(100).toFixed());
-
- if (!price.isNaN() && !value.isNaN() && priceSellState !== '') {
- const total = value.mul(price).toFixed();
- setTotalSellState(total);
-
- const totalValidationResult = validateTokensInput(
- total,
- pairData?.second_currency.asset_info?.decimal_point || 12,
- );
-
- setTotalSellValid(totalValidationResult.valid);
- } else {
- setTotalSellState('');
- setTotalSellValid(false);
- }
- }
-
- function setCorrespondingOrder(price: number, amount: number) {
- const priceDecimal = new Decimal(price || 0);
- const amountDecimal = new Decimal(amount || 0);
- const totalDecimal = priceDecimal.mul(amountDecimal);
-
- setPriceFunction(notationToString(priceDecimal.toString()) || '');
- setAmountFunction(notationToString(amountDecimal.toString()) || '');
- setTotalState(notationToString(totalDecimal.toString()) || '');
-
- if (balance) {
- const balanceDecimal = new Decimal(balance);
-
- const percentageDecimal = amountDecimal.div(balanceDecimal).mul(100);
- setRangeInputValue(percentageDecimal.toFixed() || '');
- }
-
- const total = priceDecimal.mul(amountDecimal).toFixed(secondCurrencyDP);
-
- const totalValidationResult = validateTokensInput(
- total,
- pairData?.second_currency.asset_info?.decimal_point || 12,
- );
-
- setTotalValid(totalValidationResult.valid);
- }
-
- function setCorrespondingSellOrder(price: number, amount: number) {
- const priceDecimal = new Decimal(price || 0);
- const amountDecimal = new Decimal(amount || 0);
- const totalDecimal = priceDecimal.mul(amountDecimal);
-
- setPriceSellFunction(notationToString(priceDecimal.toString()) || '');
- setAmountSellFunction(notationToString(amountDecimal.toString()) || '');
- setTotalSellState(notationToString(totalDecimal.toString()) || '');
-
- if (balance) {
- const balanceDecimal = new Decimal(balance);
-
- const percentageDecimal = amountDecimal.div(balanceDecimal).mul(100);
- setRangeInputSellValue(percentageDecimal.toFixed() || '');
- }
-
- const total = priceDecimal.mul(amountDecimal).toFixed();
-
- const totalValidationResult = validateTokensInput(
- total,
- pairData?.second_currency.asset_info?.decimal_point || 12,
- );
-
- setTotalSellValid(totalValidationResult.valid);
- }
-
- function StatItem(props: StatItemProps) {
- const { Img } = props;
-
- return (
-
-
-
![]()
-
{props.title}
-
-
-
{props.value}
- {props.coefficient !== undefined && (
-
= 0
- ? styles.coefficient__green
- : styles.coefficient__red,
- )}
- >
- {props.coefficient >= 0 ? '+' : ''}
- {props.coefficient?.toFixed(2)}%
-
- )}
-
-
- );
- }
-
- function takeOrderClick(
- event:
- | React.MouseEvent
- | React.MouseEvent,
- e: PageOrderData,
- ) {
- event.preventDefault();
-
- if (e.type === 'buy') {
- setCorrespondingOrder(e.price, e.amount);
- setBuySellState(buySellValues[1]);
- } else {
- setCorrespondingSellOrder(e.price, e.amount);
- setBuySellState(buySellValues[2]);
- }
-
- if (!orderFormRef.current) return;
-
- orderFormRef.current.scrollIntoView({ behavior: 'smooth' });
- }
-
- //* * FOR USAGE IN THIS PAGE TABLES ONLY */
- function OrderRowTooltipCell({
- style,
- children,
- sideText,
- sideTextColor,
- noTooltip,
- }: {
- style?: React.CSSProperties;
- children: string | React.ReactNode;
- sideText?: string;
- sideTextColor?: string;
- noTooltip?: boolean;
- }) {
- const [showTooltip, setShowTooltip] = useState(false);
-
- const tooltipText = `${children}${sideText ? ` ~${sideText}` : ''}`;
-
- const isLongContent = tooltipText.length > 14;
-
- return (
-
- setShowTooltip(true)}
- onMouseLeave={() => setShowTooltip(false)}
- >
- {children}
- {sideText && (
-
- {sideText}
-
- )}
-
- {isLongContent && !noTooltip && (
-
- {tooltipText}
-
- )}
- |
- );
- }
-
- function MatrixConnectionBadge({
- userAdress,
- userAlias,
- }: {
- userAdress?: string;
- userAlias?: string;
- }) {
- const [connectionTooltip, setConnectionTooltip] = useState(false);
- return userAdress && hasConnection(userAdress) ? (
- <>
- setConnectionTooltip(true)}
- onMouseLeave={() => setConnectionTooltip(false)}
- style={{ marginTop: '4px', cursor: 'pointer', position: 'relative' }}
- >
-
-
-
- Matrix connection
-
- >
- ) : (
- <>>
- );
- }
-
- function OrdersRow(props: { orderData: PageOrderData; percentage: number }) {
- const e = props?.orderData || {};
- const percentage = props?.percentage;
-
- const totalDecimal = new Decimal(e.left).mul(new Decimal(e.price));
-
- return (
- setOrdersInfoTooltip(e)}
- onClick={(event) => takeOrderClick(event, e)}
- className={e.type === 'sell' ? styles.sell_section : ''}
- style={{ '--line-width': `${percentage}%` } as React.CSSProperties}
- key={nanoid(16)}
- >
-
- {notationToString(e.price)}
-
- {notationToString(e.amount)}
- {/* {notationToString(e.left)} */}
-
- {notationToString(totalDecimal.toString())}
-
-
- );
- }
-
- function MyOrdersRow(props: { orderData: OrderRow }) {
- const e = props?.orderData || {};
- const [cancellingState, setCancellingState] = useState(false);
-
- const totalDecimal = new Decimal(e.left).mul(new Decimal(e.price));
- const totalValue = secondAssetUsdPrice
- ? totalDecimal.mul(secondAssetUsdPrice).toFixed(2)
- : undefined;
-
- const [showTooltip, setShowTooltip] = useState(false);
-
- async function cancelClick(event: React.MouseEvent) {
- event.preventDefault();
-
- setCancellingState(true);
- const result = await cancelOrder(e.id);
-
- setCancellingState(false);
-
- if (!result.success) {
- setAlertState('error');
- setAlertSubtitle('Error while cancelling order');
- setTimeout(() => {
- setAlertState(null);
- setAlertSubtitle('');
- }, 3000);
- return;
- }
-
- await updateOrders();
- await updateUserOrders();
- await fetchUser();
- }
-
- return (
-
- |
- setShowTooltip(true)}
- onMouseLeave={() => setShowTooltip(false)}
- >
- @
- {cutAddress(
- state.wallet?.connected && state.wallet?.alias
- ? state.wallet.alias
- : 'no alias',
- 12,
- )}
-
- {e.isInstant && (
-
-
-
- )}
-
-
- {(state.wallet?.connected && state.wallet?.alias ? state.wallet?.alias : '')
- ?.length > 12 && (
-
- {state.wallet?.connected && state.wallet?.alias}
-
- )}
- {/* High volume */}
- {/* */}
- |
-
- {notationToString(e.price)}
-
- {notationToString(e.amount)}
-
-
- {notationToString(totalDecimal.toString())}{' '}
- ~ ${totalValue && formatDollarValue(totalValue)}
-
-
- {/* {localeTimeLeft(now, parseInt(e.expiration_timestamp, 10))} | */}
-
-
-
- {applyTips?.filter((tip) => tip.connected_order_id === e.id)?.length || 0}
-
- |
-
-
- {cancellingState ? 'Process' : 'Cancel'}
-
- |
-
- );
- }
-
- function MyOrdersApplyRow(props: { orderData: ApplyTip }) {
- const e = props?.orderData || {};
-
- const [applyingState, setApplyingState] = useState(false);
-
- const connectedOrder = userOrders.find((order) => order.id === e.connected_order_id);
-
- const totalDecimal = new Decimal(e.left).mul(new Decimal(e.price));
- const totalValue = secondAssetUsdPrice
- ? totalDecimal.mul(secondAssetUsdPrice).toFixed(2)
- : undefined;
-
- const [showTooltip, setShowTooltip] = useState(false);
-
- async function applyClick(event: React.MouseEvent) {
- event.preventDefault();
-
- if (e.id) {
- updateAutoClosedNotification(dispatch, [
- ...state.closed_notifications,
- parseInt(e.id, 10),
- ]);
- }
-
- function alertErr(subtitle: string) {
- setAlertState('error');
- setAlertSubtitle(subtitle);
- setTimeout(() => {
- setAlertState(null);
- setAlertSubtitle('');
- }, 3000);
- }
-
- setApplyingState(true);
- interface SwapOperationResult {
- success: boolean;
- message?: string;
- errorCode?: number;
- data?: unknown;
- }
-
- let result: SwapOperationResult | null = null;
-
- await (async () => {
- if (e.transaction) {
- if (!e.hex_raw_proposal) {
- alertErr('Invalid transaction data received');
- return;
- }
-
- console.log(e.hex_raw_proposal);
-
- const confirmSwapResult = await confirmIonicSwap(e.hex_raw_proposal);
-
- console.log(confirmSwapResult);
-
- if (confirmSwapResult.data?.error?.code === -7) {
- alertErr('Insufficient funds');
- return;
- }
- if (!confirmSwapResult.data?.result) {
- alertErr('Companion responded with an error');
- return;
- }
-
- result = await confirmTransaction(e.id);
- } else {
- const firstCurrencyId = pairData?.first_currency.asset_id;
- const secondCurrencyId = pairData?.second_currency.asset_id;
-
- console.log(firstCurrencyId, secondCurrencyId);
-
- if (!(firstCurrencyId && secondCurrencyId)) {
- alertErr('Invalid transaction data received');
- return;
- }
-
- if (!connectedOrder) return;
-
- const leftDecimal = new Decimal(e.left);
- const priceDecimal = new Decimal(e.price);
-
- const params = {
- destinationAssetID: e.type === 'buy' ? secondCurrencyId : firstCurrencyId,
- destinationAssetAmount: notationToString(
- e.type === 'buy'
- ? leftDecimal.mul(priceDecimal).toString()
- : leftDecimal.toString(),
- ),
- currentAssetID: e.type === 'buy' ? firstCurrencyId : secondCurrencyId,
- currentAssetAmount: notationToString(
- e.type === 'buy'
- ? leftDecimal.toString()
- : leftDecimal.mul(priceDecimal).toString(),
- ),
-
- destinationAddress: e.user.address,
- };
-
- console.log(params);
-
- const createSwapResult = await ionicSwap(params);
-
- console.log(createSwapResult);
-
- const hex = createSwapResult?.data?.result?.hex_raw_proposal;
-
- if (createSwapResult?.data?.error?.code === -7) {
- alertErr('Insufficient funds');
- return;
- }
- if (!hex) {
- alertErr('Companion responded with an error');
- return;
- }
-
- result = await applyOrder({
- ...e,
- hex_raw_proposal: hex,
- });
- }
- })();
-
- setApplyingState(false);
-
- if (!result) {
- return;
- }
-
- if (!(result as { success: boolean }).success) {
- alertErr('Server responded with an error');
- return;
- }
-
- await updateOrders();
- await updateUserOrders();
- await fetchUser();
- await fetchTrades();
- }
-
- return (
-
- |
- setShowTooltip(true)}
- onMouseLeave={() => setShowTooltip(false)}
- >
- @{cutAddress(e.user.alias, 12) || 'no alias'}
-
- {e.isInstant && (
-
-
-
- )}
-
-
- {(e.isInstant || e.transaction) && }
-
- {e.user?.alias.length > 12 && (
-
- {e.user?.alias}
-
- )}
- |
-
-
- {notationToString(e.price)}
-
- {notationToString(e.left)}
-
-
- {notationToString(totalDecimal.toString())}{' '}
- ~ ${totalValue && formatDollarValue(totalValue)}
-
-
- |
-
-
- {applyingState ? 'Process' : 'Apply'}
-
- |
-
- );
- }
-
- const imgCode =
- pairData && tradingKnownCurrencies.includes(pairData.first_currency?.code)
- ? pairData.first_currency?.code
- : 'tsds';
-
- const imgCode2 =
- pairData && tradingKnownCurrencies.includes(pairData.second_currency?.code)
- ? pairData.second_currency?.code
- : 'tsds';
-
- const coefficient = pairStats?.coefficient || 0;
- const coefficientOutput =
- parseFloat(coefficient?.toFixed(2) || '0') === -100
- ? -99.99
- : parseFloat(coefficient?.toFixed(2) || '0');
-
- const pairRateUsd =
- pairStats?.rate !== undefined && secondAssetUsdPrice !== undefined
- ? new Decimal(pairStats.rate)
- .mul(secondAssetUsdPrice)
- .toFixed(pairStats.rate < 0.1 ? 6 : 2)
- : undefined;
-
- const scrollToOrderList = () => {
- if (!orderListRef.current) return;
-
- orderListRef.current.scrollIntoView({ behavior: 'smooth' });
- };
-
- const handleCancelAllOrders = async () => {
setMyOrdersLoading(true);
try {
@@ -1234,295 +130,43 @@ function Trading() {
} finally {
setMyOrdersLoading(false);
}
- };
+ }, [userOrders, updateUserOrders]);
+
+ const { filteredOrdersHistory, filteredTrades } = useFilteredData({
+ ordersBuySell,
+ ordersHistory,
+ trades,
+ tradesType,
+ });
return (
<>
-
-
-
-
-
-
-
-
-
- {!(
- pairData &&
- pairData.first_currency?.name &&
- pairData.second_currency?.name
- ) ? (
- '...'
- ) : (
- <>
- {firstCurrencyName}
- /{secondCurrencyName}
- >
- )}
-
-
-
- {notationToString(pairStats?.rate || 0)}{' '}
- {secondCurrencyName}
-
- {pairRateUsd && (
-
- ~ ${pairRateUsd}
-
- )}
-
-
-
-
-
- {pairData && firstAssetLink && secondAssetLink && (
-
-
-
- {' '}
- {firstCurrencyName}:
-
-
- {shortenAddress(firstAssetId || '')}
-
-
-
-
- {' '}
- {secondCurrencyName}:
-
-
- {shortenAddress(firstAssetId || '')}
-
-
-
- )}
-
-
-
-
-
+
+
-
-
+
+
-
-
-
-
- Orders pool
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | Price ({secondCurrencyName}) |
- Amount ({firstCurrencyName}) |
- Total ({secondCurrencyName}) |
-
-
-
- {!ordersLoading && !!filteredOrdersHistory.length && (
- setOrdersInfoTooltip(null)}
- className="orders-scroll"
- >
- {filteredOrdersHistory?.map((e) => {
- const maxValue = Math.max(
- ...filteredOrdersHistory.map((order) =>
- parseFloat(String(order.left)),
- ),
- );
- const percentage = (
- (parseFloat(String(e.left)) / maxValue) *
- 100
- ).toFixed(2);
-
- return (
-
- );
- })}
-
- )}
-
-
- {!filteredOrdersHistory.length && !ordersLoading && (
-
-
-
No orders
-
- )}
- {ordersLoading && (
-
- )}
-
- {ordersInfoTooltip &&
- (() => {
- const totalDecimal = new Decimal(ordersInfoTooltip?.left).mul(
- new Decimal(ordersInfoTooltip?.price),
- );
- const totalValue = secondAssetUsdPrice
- ? totalDecimal.mul(secondAssetUsdPrice).toFixed(2)
- : undefined;
-
- return (
-
-
-
Alias
-
- @
- {cutAddress(
- ordersInfoTooltip?.user?.alias ||
- 'no alias',
- 12,
- )}{' '}
- {ordersInfoTooltip?.isInstant && (
-
- )}
-
-
-
Price ({secondCurrencyName})
-
- {notationToString(ordersInfoTooltip?.price)}
-
-
- ~
- {secondAssetUsdPrice &&
- ordersInfoTooltip?.price !== undefined
- ? (() => {
- const total =
- secondAssetUsdPrice *
- ordersInfoTooltip.price;
- const formatted =
- ordersInfoTooltip.price < 0.9
- ? `$${total.toFixed(5)}`
- : `$${total.toFixed(2)}`;
- return formatted;
- })()
- : 'undefined'}
-
-
-
Amount ({firstCurrencyName})
-
{notationToString(ordersInfoTooltip?.amount)}
-
-
Total ({secondCurrencyName})
-
{notationToString(totalDecimal.toString())}
-
- ~{' '}
- {totalValue
- ? `$${formatDollarValue(totalValue)}`
- : 'undefined'}
-
-
-
- );
- })()}
-
-
-
-
-
+
+
undefined}
/>
@@ -1544,241 +185,64 @@ function Trading() {
{candlesLoaded ? (
) : (
-
+
)}
-
-
-
-
-
-
-
-
-
-
-
- | Price ({secondCurrencyName}) |
- Amount ({firstCurrencyName}) |
- Time |
-
-
-
- {!tradesLoading && !!filteredTrades.length && (
-
- {filteredTrades.map((trade) => (
-
- |
-
- {trade.price}
-
- |
-
- {trade.amount}
- |
-
- {formatTime(trade.timestamp)}
- |
-
- ))}
-
- )}
-
-
- {!filteredTrades.length && !tradesLoading && (
-
-
-
No trades
-
- )}
-
- {tradesLoading && (
-
- )}
-
-
+
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- | Alias |
-
- Price ({secondCurrencyName})
- |
-
- Amount ({firstCurrencyName})
- |
-
- Total ({secondCurrencyName})
- |
- Offers |
- |
-
-
-
-
- {!myOrdersLoading && loggedIn && !!userOrders.length && (
-
-
-
- {userOrders.map((e) => (
-
- ))}
-
-
- {!!applyTips.length && (
-
-
- {applyTips.map((e) => (
-
- ))}
-
-
- )}
-
- )}
-
- {myOrdersLoading && loggedIn && (
-
- )}
-
- {!loggedIn && (
-
-
-
Connect wallet to see your orders
-
- )}
-
- {loggedIn && !userOrders.length && !myOrdersLoading && (
-
-
-
No orders
-
- )}
-
-
+
-
-
-
+ {['buy', 'sell'].map((type) => {
+ const isBuy = type === 'buy';
+ const form = isBuy ? buyForm : sellForm;
-
-
-
+ return (
+
+ );
+ })}
diff --git a/src/pages/dex/trading/components/AllTrades/index.tsx b/src/pages/dex/trading/components/AllTrades/index.tsx
new file mode 100644
index 0000000..8e9a3cb
--- /dev/null
+++ b/src/pages/dex/trading/components/AllTrades/index.tsx
@@ -0,0 +1,82 @@
+import React from 'react';
+import { classes, formatTime } from '@/utils/utils';
+import ContentPreloader from '@/components/UI/ContentPreloader/ContentPreloader';
+import EmptyMessage from '@/components/UI/EmptyMessage';
+import styles from './styles.module.scss';
+import { AllTradesProps } from './types';
+
+const AllTrades = ({
+ setTradesType,
+ tradesType,
+ filteredTrades,
+ tradesLoading,
+ currencyNames,
+}: AllTradesProps) => {
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ | Price ({currencyNames.secondCurrencyName}) |
+ Amount ({currencyNames.firstCurrencyName}) |
+ Time |
+
+
+
+ {!tradesLoading && !!filteredTrades.length && (
+
+ {filteredTrades.map((trade) => (
+
+ |
+
+ {trade.price}
+
+ |
+
+ {trade.amount}
+ |
+
+ {formatTime(trade.timestamp)}
+ |
+
+ ))}
+
+ )}
+
+
+ {!filteredTrades.length && !tradesLoading &&
}
+
+ {tradesLoading &&
}
+
+
+ );
+};
+
+export default AllTrades;
diff --git a/src/pages/dex/trading/components/AllTrades/styles.module.scss b/src/pages/dex/trading/components/AllTrades/styles.module.scss
new file mode 100644
index 0000000..aae3f21
--- /dev/null
+++ b/src/pages/dex/trading/components/AllTrades/styles.module.scss
@@ -0,0 +1,116 @@
+.allTrades {
+ max-width: 415px;
+ width: 100%;
+ padding: 5px;
+ background: var(--window-bg-color);
+ border: 1px solid var(--delimiter-color);
+ border-radius: 10px;
+
+ @media screen and (max-width: 1480px) {
+ max-width: 340px;
+ }
+
+ &__header {
+ border-bottom: 1px solid var(--delimiter-color);
+ display: flex;
+ align-items: center;
+ gap: 22px;
+ padding: 10px;
+ padding-bottom: 0;
+
+ &_btn {
+ padding-bottom: 7px;
+ border-top-left-radius: 10px;
+ border-top-right-radius: 10px;
+ font-size: 16px;
+ border-bottom: 2px solid transparent;
+ font-weight: 600;
+ background-color: transparent !important;
+ cursor: pointer;
+
+ &.active {
+ border-color: #1f8feb;
+ }
+
+ &:hover {
+ color: #1f8feb;
+ }
+ }
+ }
+
+ &__content {
+ display: flex;
+ flex-direction: column;
+ padding-top: 10px;
+
+ table {
+ width: 100%;
+
+ thead {
+ display: flex;
+ width: 100%;
+ padding-inline: 10px;
+ margin-bottom: 9px;
+
+ tr {
+ width: 100%;
+ display: flex;
+ justify-content: space-between;
+
+ th {
+ min-width: 80px;
+ font-size: 11px;
+ font-weight: 700;
+ text-align: start;
+ color: var(--table-th-color);
+
+ &:last-child {
+ text-align: right;
+ }
+ }
+ }
+ }
+
+ tbody {
+ height: 29dvh;
+ min-height: 265px;
+ max-height: 380px;
+ display: flex;
+ flex-direction: column;
+ overflow: auto;
+ padding: 10px;
+ padding-bottom: 20px;
+
+ tr {
+ position: relative;
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ width: 100%;
+ padding: 4px 0;
+
+ &:nth-child(even) {
+ background-color: var(--table-even-bg);
+ }
+
+ td {
+ position: relative;
+
+ &:last-child {
+ > p {
+ text-align: right;
+ }
+ }
+
+ > p {
+ min-width: 80px;
+ width: 100%;
+ font-size: 12px;
+ font-weight: 400;
+ }
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/src/pages/dex/trading/components/AllTrades/types.ts b/src/pages/dex/trading/components/AllTrades/types.ts
new file mode 100644
index 0000000..1fb3096
--- /dev/null
+++ b/src/pages/dex/trading/components/AllTrades/types.ts
@@ -0,0 +1,15 @@
+import { Trade } from '@/interfaces/responses/trades/GetTradeRes';
+import { Dispatch, SetStateAction } from 'react';
+
+type tradeType = 'all' | 'my';
+
+export interface AllTradesProps {
+ setTradesType: Dispatch
>;
+ tradesType: tradeType;
+ filteredTrades: Trade[];
+ tradesLoading: boolean;
+ currencyNames: {
+ firstCurrencyName: string;
+ secondCurrencyName: string;
+ };
+}
diff --git a/src/pages/dex/trading/components/BadgeStatus/index.tsx b/src/pages/dex/trading/components/BadgeStatus/index.tsx
new file mode 100644
index 0000000..d2690e0
--- /dev/null
+++ b/src/pages/dex/trading/components/BadgeStatus/index.tsx
@@ -0,0 +1,26 @@
+import { classes } from '@/utils/utils';
+import React from 'react';
+import Image from 'next/image';
+import LightningImg from '@/assets/images/UI/lightning.png';
+import RocketImg from '@/assets/images/UI/rocket.png';
+import styles from './styles.module.scss';
+import { BadgeStatusProps } from './types';
+
+function BadgeStatus({ type, icon }: BadgeStatusProps) {
+ return (
+
+
+ {!icon && (
+
+ {type === 'instant' ? 'instant' : 'high volume'}
+
+ )}
+
+ );
+}
+
+export default BadgeStatus;
diff --git a/src/pages/dex/trading/components/BadgeStatus/styles.module.scss b/src/pages/dex/trading/components/BadgeStatus/styles.module.scss
new file mode 100644
index 0000000..03d821e
--- /dev/null
+++ b/src/pages/dex/trading/components/BadgeStatus/styles.module.scss
@@ -0,0 +1,39 @@
+.badge {
+ width: fit-content;
+ padding: 1px 4px;
+ padding-right: 8px;
+ display: flex;
+ align-items: center;
+ gap: 2px;
+ border-radius: 100px;
+ background: radial-gradient(100% 246.57% at 0% 0%, #a366ff 0%, #601fff 100%);
+
+ &.high {
+ padding: 2px 4px;
+ background: radial-gradient(100% 188.88% at 0% 0%, #16d1d6 0%, #274cff 100%);
+ }
+
+ &.icon {
+ min-width: 15px;
+ height: 15px;
+ border-radius: 50%;
+ justify-content: center;
+ padding: 0;
+
+ .badge__img {
+ width: 11px;
+ height: 11px;
+ }
+ }
+
+ &__img {
+ height: 13px;
+ width: auto;
+ }
+
+ &__text {
+ font-size: 10px;
+ font-weight: 600;
+ color: #fff;
+ }
+}
diff --git a/src/pages/dex/trading/components/BadgeStatus/types.ts b/src/pages/dex/trading/components/BadgeStatus/types.ts
new file mode 100644
index 0000000..a375313
--- /dev/null
+++ b/src/pages/dex/trading/components/BadgeStatus/types.ts
@@ -0,0 +1,4 @@
+export interface BadgeStatusProps {
+ type?: 'instant' | 'high';
+ icon?: boolean;
+}
diff --git a/src/pages/dex/trading/CandleChart/CandleChart.tsx b/src/pages/dex/trading/components/CandleChart/index.tsx
similarity index 96%
rename from src/pages/dex/trading/CandleChart/CandleChart.tsx
rename to src/pages/dex/trading/components/CandleChart/index.tsx
index c8dccc0..d9f19ef 100644
--- a/src/pages/dex/trading/CandleChart/CandleChart.tsx
+++ b/src/pages/dex/trading/components/CandleChart/index.tsx
@@ -6,7 +6,7 @@ import Decimal from 'decimal.js';
import * as echarts from 'echarts';
import CandleRow from '@/interfaces/common/CandleRow';
import testCandles from './testCandles.json';
-import styles from './CandleChart.module.scss';
+import styles from './styles.module.scss';
const TESTING_MODE = false;
@@ -214,7 +214,7 @@ function CandleChart(props: CandleChartProps) {
console.log('option', option);
return (
-
+
- {!candles?.length && isLoaded &&
[ Low volume ]
}
+ {!candles?.length && isLoaded && (
+ [ Low volume ]
+ )}
);
}
diff --git a/src/pages/dex/trading/CandleChart/CandleChart.module.scss b/src/pages/dex/trading/components/CandleChart/styles.module.scss
similarity index 93%
rename from src/pages/dex/trading/CandleChart/CandleChart.module.scss
rename to src/pages/dex/trading/components/CandleChart/styles.module.scss
index 447d07f..b2e1950 100644
--- a/src/pages/dex/trading/CandleChart/CandleChart.module.scss
+++ b/src/pages/dex/trading/components/CandleChart/styles.module.scss
@@ -1,4 +1,4 @@
-.candle__chart__wrapper {
+.chart {
position: relative;
width: auto;
height: auto;
@@ -12,7 +12,7 @@
cursor: crosshair;
}
- h1 {
+ &__lowVolume {
font-size: 72px;
color: var(--font-dimmed-color);
white-space: nowrap;
diff --git a/src/pages/dex/trading/CandleChart/testCandles.json b/src/pages/dex/trading/components/CandleChart/testCandles.json
similarity index 100%
rename from src/pages/dex/trading/CandleChart/testCandles.json
rename to src/pages/dex/trading/components/CandleChart/testCandles.json
diff --git a/src/pages/dex/trading/components/InputPanelItem/components/LabeledInput/index.tsx b/src/pages/dex/trading/components/InputPanelItem/components/LabeledInput/index.tsx
new file mode 100644
index 0000000..5c0cb27
--- /dev/null
+++ b/src/pages/dex/trading/components/InputPanelItem/components/LabeledInput/index.tsx
@@ -0,0 +1,52 @@
+import LabeledInputProps from '@/interfaces/props/pages/dex/trading/InputPanelItem/LabeledInputProps';
+import { classes, formatDollarValue } from '@/utils/utils';
+import { useRef } from 'react';
+import Input from '@/components/UI/Input/Input';
+import styles from './styles.module.scss';
+
+function LabeledInput(props: LabeledInputProps) {
+ const labelRef = useRef
(null);
+ const {
+ label = '',
+ placeholder = '',
+ currency = '',
+ value,
+ readonly,
+ usd,
+ setValue,
+ invalid,
+ } = props;
+
+ const handleInput = (e: React.FormEvent) => {
+ if (!readonly && setValue) {
+ setValue(e.currentTarget.value);
+ }
+ };
+
+ return (
+
+
{label}
+
+
+
+ {usd && (
+
+
~${formatDollarValue(usd)}
+
+ )}
+
+
+
+
+ );
+}
+
+export default LabeledInput;
diff --git a/src/pages/dex/trading/components/InputPanelItem/components/LabeledInput/styles.module.scss b/src/pages/dex/trading/components/InputPanelItem/components/LabeledInput/styles.module.scss
new file mode 100644
index 0000000..80c2834
--- /dev/null
+++ b/src/pages/dex/trading/components/InputPanelItem/components/LabeledInput/styles.module.scss
@@ -0,0 +1,62 @@
+.labeledInput {
+ display: flex;
+ flex-direction: column;
+ gap: 8px;
+
+ &__label {
+ font-size: 11px;
+ font-family: 700;
+ color: var(--table-th-color);
+ }
+
+ &__wrapper {
+ width: 100%;
+ position: relative;
+ background-color: var(--bordered-input-bg);
+ border: 1px solid var(--window-border-color);
+ border-radius: 8px;
+ display: flex;
+ overflow: hidden;
+
+ &.invalid {
+ border-color: #ff6767;
+ }
+
+ input {
+ width: 100%;
+ padding: 13px 15px;
+ background-color: transparent;
+ border: none;
+ font-size: 16px;
+ font-weight: 400;
+ }
+ }
+
+ &__value {
+ padding-right: 10px;
+ display: flex;
+ align-items: center;
+
+ > p {
+ color: var(--table-th-color);
+ font-size: 12px;
+ font-weight: 400;
+ }
+ }
+
+ &__currency {
+ min-width: 82px;
+ max-width: 150px;
+ padding: 0 15px;
+ background-color: var(--dex-input-currency);
+ display: flex;
+ align-items: center;
+ justify-content: center;
+
+ > p {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ }
+ }
+}
diff --git a/src/pages/dex/trading/InputPanelItem/InputPanelItem.tsx b/src/pages/dex/trading/components/InputPanelItem/index.tsx
similarity index 65%
rename from src/pages/dex/trading/InputPanelItem/InputPanelItem.tsx
rename to src/pages/dex/trading/components/InputPanelItem/index.tsx
index 44d2eb2..1176bc4 100644
--- a/src/pages/dex/trading/InputPanelItem/InputPanelItem.tsx
+++ b/src/pages/dex/trading/components/InputPanelItem/index.tsx
@@ -1,26 +1,22 @@
import { Store } from '@/store/store-reducer';
import { createOrder } from '@/utils/methods';
-import { ChangeEvent, useContext, useRef, useState } from 'react';
-import Input from '@/components/UI/Input/Input';
+import { ChangeEvent, useContext, useState } from 'react';
import RangeInput from '@/components/UI/RangeInput/RangeInput';
import ConnectButton from '@/components/UI/ConnectButton/ConnectButton';
import Button from '@/components/UI/Button/Button';
import { useRouter } from 'next/router';
-import { classes, formatDollarValue } from '@/utils/utils';
+import { classes } from '@/utils/utils';
import InputPanelItemProps from '@/interfaces/props/pages/dex/trading/InputPanelItem/InputPanelItemProps';
-import LabeledInputProps from '@/interfaces/props/pages/dex/trading/InputPanelItem/LabeledInputProps';
import CreateOrderData from '@/interfaces/fetch-data/create-order/CreateOrderData';
import Decimal from 'decimal.js';
import Alert from '@/components/UI/Alert/Alert';
import infoIcon from '@/assets/images/UI/info_alert_icon.svg';
import Image from 'next/image';
-import styles from './InputPanelItem.module.scss';
+import { useAlert } from '@/hook/useAlert';
+import styles from './styles.module.scss';
+import LabeledInput from './components/LabeledInput';
function InputPanelItem(props: InputPanelItemProps) {
- const { state } = useContext(Store);
-
- const router = useRouter();
-
const {
priceState = '',
amountState = '',
@@ -29,71 +25,32 @@ function InputPanelItem(props: InputPanelItemProps) {
buySellState = buySellValues[0],
setPriceFunction,
setAmountFunction,
- setAlertState,
- setAlertSubtitle,
setRangeInputValue,
rangeInputValue = '50',
- firstCurrencyName = '',
- secondCurrencyName = '',
balance = 0,
amountValid,
priceValid,
totalValid,
totalUsd,
scrollToOrderList,
+ currencyNames,
} = props;
+ const { state } = useContext(Store);
+ const router = useRouter();
+ const { setAlertState, setAlertSubtitle } = useAlert();
const [creatingState, setCreatingState] = useState(false);
+ const { firstCurrencyName, secondCurrencyName } = currencyNames;
const [hasImmediateMatch, setHasImmediateMatch] = useState(false);
-
- function LabeledInput(props: LabeledInputProps) {
- const labelRef = useRef(null);
- const {
- label = '',
- placeholder = '',
- currency = '',
- value,
- readonly,
- usd,
- setValue,
- invalid,
- } = props;
-
- const handleInput = (e: React.FormEvent) => {
- if (!readonly && setValue) {
- setValue(e.currentTarget.value);
- }
- };
-
- return (
-
-
{label}
-
-
- {usd && (
-
-
~${formatDollarValue(usd)}
-
- )}
-
-
-
- );
- }
-
const isBuy = buySellState?.code === 'buy';
+ function resetForm() {
+ setPriceFunction('');
+ setAmountFunction('');
+ setRangeInputValue('50');
+ }
+
async function postOrder() {
const price = new Decimal(priceState);
const amount = new Decimal(amountState);
@@ -122,6 +79,8 @@ function InputPanelItem(props: InputPanelItemProps) {
if (result.data?.immediateMatch) {
setHasImmediateMatch(true);
}
+
+ resetForm();
} else {
setAlertState('error');
if (result.data === 'Same order') {
@@ -139,35 +98,30 @@ function InputPanelItem(props: InputPanelItemProps) {
function onRangeInput(e: ChangeEvent) {
setRangeInputValue(e.target.value);
- if (balance) {
+ if (balance > 0) {
const rangeValue = new Decimal(e.target.value || '0');
- const balanceDecimal = new Decimal(balance || '0');
+ const balanceDecimal = new Decimal(balance);
const calculatedAmount = balanceDecimal.mul(rangeValue.div(100)).toString();
setAmountFunction(calculatedAmount || '');
}
}
- let buttonText;
-
- if (creatingState) {
- buttonText = 'Creating...';
- } else {
- buttonText = 'Create Order';
- }
+ const buttonText = creatingState ? 'Creating...' : 'Create Order';
+ const isButtonDisabled = !priceValid || !amountValid || !totalValid || creatingState;
return (
-
+
{hasImmediateMatch && (
+
-
+
Apply the order
You have to apply the order