From faf76ae53c1b7ea8b9ba6102b08d9c9476f5d334 Mon Sep 17 00:00:00 2001 From: ram Date: Thu, 7 Nov 2024 20:41:19 +0530 Subject: [PATCH 01/11] Changes for the new asset page --- .../DigitalAssets/components/AssetsCards.js | 117 +++++++++++------- .../DigitalAssets/components/AssetsList.js | 33 +++-- .../DigitalAssets/components/AssetsRow.js | 18 ++- .../DigitalAssets/components/AssetsWrapper.js | 2 +- 4 files changed, 107 insertions(+), 63 deletions(-) diff --git a/web/src/containers/DigitalAssets/components/AssetsCards.js b/web/src/containers/DigitalAssets/components/AssetsCards.js index 56bb76f0a5..0bbe99518d 100644 --- a/web/src/containers/DigitalAssets/components/AssetsCards.js +++ b/web/src/containers/DigitalAssets/components/AssetsCards.js @@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useState } from 'react'; import { connect } from 'react-redux'; import { isMobile } from 'react-device-detect'; import { browserHistory } from 'react-router'; -import { Card, Switch } from 'antd'; +import { Card, Spin, Switch } from 'antd'; import { CaretDownOutlined, CaretUpOutlined, @@ -15,6 +15,7 @@ import icons from 'config/icons/dark'; import { Coin, EditWrapper, IconTitle } from 'components'; import { quicktradePairSelector } from 'containers/QuickTrade/components/utils'; import { Loading } from './utils'; +import { formatCurrencyByIncrementalUnit } from 'utils/currency'; const cardTypes = ['gainers', 'losers', 'newAssets']; const cardTitles = [ @@ -94,56 +95,72 @@ const goToCoinInfo = (symbol, features, quicktradePairs) => { } }; -const renderCards = (data, coins, type, loading, features, quicktradePairs) => - data.map( - ( - { - symbol, - lastPrice, - oneDayPriceDifferencePercent, - oneDayPriceDifferencePercenVal, - }, - index - ) => - loading ? ( - - ) : ( -
goToCoinInfo(symbol, features, quicktradePairs)} - > -
- -
- - {coins[symbol].fullname} - - {symbol.toUpperCase()} -
-
-
-
- - {lastPrice ? `$${lastPrice}` : '-'} - - {renderPercentage( - type === 'newAssets' - ? oneDayPriceDifferencePercenVal - : oneDayPriceDifferencePercent, - type - )} +const renderCards = (data, coins, type, loading, features, quicktradePairs) => { + return data?.length >= 1 ? ( + data?.map( + ( + { + symbol, + lastPrice, + oneDayPriceDifferencePercent, + oneDayPriceDifferencePercenVal, + increment_unit, + }, + index + ) => { + const roundPrice = lastPrice?.split(',')?.join(''); + + return loading ? ( + + ) : ( +
goToCoinInfo(symbol, features, quicktradePairs)} + > +
+ +
+ + {coins[symbol]?.fullname} + + {symbol?.toUpperCase()} +
-
- +
+
+ + {lastPrice + ? `$${formatCurrencyByIncrementalUnit( + roundPrice, + increment_unit + )}` + : '-'} + + {renderPercentage( + type === 'newAssets' + ? oneDayPriceDifferencePercenVal + : oneDayPriceDifferencePercent, + type + )} +
+
+ +
-
- ) + ); + } + ) + ) : ( + + + ); +}; const AssetsCards = ({ coins, @@ -258,6 +275,10 @@ const AssetsCards = ({ : cardTypes[currentIndex] === 'losers' ? 'losers-asset-card' : 'new-asset-card' + } ${ + sortedCoinsData[cardTypes[currentIndex]]?.length === 0 + ? 'text-center' + : '' }`} > {renderCards( @@ -327,7 +348,7 @@ const AssetsCards = ({ : type === 'losers' ? 'losers-asset-card' : 'new-asset-card' - }`} + } ${sortedCoinsData[type]?.length === 0 ? 'text-center' : ''}`} > {renderCards( sortedCoinsData[type], diff --git a/web/src/containers/DigitalAssets/components/AssetsList.js b/web/src/containers/DigitalAssets/components/AssetsList.js index a8de876ef9..1df97480e1 100644 --- a/web/src/containers/DigitalAssets/components/AssetsList.js +++ b/web/src/containers/DigitalAssets/components/AssetsList.js @@ -15,6 +15,7 @@ import { EditWrapper } from 'components'; import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import AssetsRow from './AssetsRow'; +import { Spin } from 'antd'; const AssetsList = ({ coinsListData, @@ -246,18 +247,26 @@ const AssetsList = ({ - {getSortedList().map((coinData, index) => ( - - ))} + {getSortedList()?.length >= 1 ? ( + getSortedList()?.map((coinData, index) => ( + + )) + ) : ( + + + + + + )}
diff --git a/web/src/containers/DigitalAssets/components/AssetsRow.js b/web/src/containers/DigitalAssets/components/AssetsRow.js index 09add0c719..a777e2c9da 100644 --- a/web/src/containers/DigitalAssets/components/AssetsRow.js +++ b/web/src/containers/DigitalAssets/components/AssetsRow.js @@ -10,6 +10,7 @@ import { MiniSparkLine } from 'containers/TradeTabs/components/MiniSparkLine'; import { getLastValuesFromParts } from 'utils/array'; import { unique } from 'utils/data'; import { Loading } from './utils'; +import { formatCurrencyByIncrementalUnit } from 'utils/currency'; const AssetsRow = ({ coinData, @@ -32,6 +33,7 @@ const AssetsRow = ({ oneDayPriceDifferencePercent, lastPrice, key, + increment_unit, } = coinData; const getAllAvailableMarkets = (key) => { @@ -94,6 +96,7 @@ const AssetsRow = ({ }; const markets = getAllAvailableMarkets(symbol); + const roundPrice = lastPrice?.split(',')?.join(''); return ( @@ -137,7 +140,12 @@ const AssetsRow = ({ {lastPrice && '$'} - {lastPrice ? lastPrice : '-'} + {lastPrice + ? formatCurrencyByIncrementalUnit( + roundPrice, + increment_unit + ) + : '-'}
{(oneDayPriceDifferencePercent && oneDayPriceDifference) || @@ -200,6 +208,8 @@ const AssetsRow = ({ coins[symbol].market_cap.toLocaleString('en-US', { style: 'currency', currency: 'USD', + minimumFractionDigits: 0, + maximumFractionDigits: 0, }) ) : ( 0 @@ -218,7 +228,9 @@ const AssetsRow = ({ {lastPrice && '$'} - {lastPrice ? lastPrice : '-'} + {lastPrice + ? formatCurrencyByIncrementalUnit(roundPrice, increment_unit) + : '-'}
) : ( @@ -291,6 +303,8 @@ const AssetsRow = ({ coins[symbol].market_cap.toLocaleString('en-US', { style: 'currency', currency: 'USD', + minimumFractionDigits: 0, + maximumFractionDigits: 0, }) ) : ( 0 diff --git a/web/src/containers/DigitalAssets/components/AssetsWrapper.js b/web/src/containers/DigitalAssets/components/AssetsWrapper.js index ef4d74dc05..179d8442b7 100644 --- a/web/src/containers/DigitalAssets/components/AssetsWrapper.js +++ b/web/src/containers/DigitalAssets/components/AssetsWrapper.js @@ -31,7 +31,7 @@ class AssetsWrapper extends Component { data: [], chartData: {}, coinsData: [], - pageSize: 100, + pageSize: 50, page: 0, count: 0, searchValue: '', From 2ea20d0477872a92397e4d94dfa621cad8c6403f Mon Sep 17 00:00:00 2001 From: ram Date: Fri, 8 Nov 2024 21:45:31 +0530 Subject: [PATCH 02/11] Fixed the market chart issue and favourite asset bar expansion issue --- web/src/components/AppBar/PairTabs.js | 27 +++++++++++++++++++++++---- web/src/containers/App/App.js | 2 +- 2 files changed, 24 insertions(+), 5 deletions(-) diff --git a/web/src/components/AppBar/PairTabs.js b/web/src/components/AppBar/PairTabs.js index ab898047ef..b12ea5ecbb 100644 --- a/web/src/components/AppBar/PairTabs.js +++ b/web/src/components/AppBar/PairTabs.js @@ -1,5 +1,6 @@ import React, { Component } from 'react'; import { connect } from 'react-redux'; +import { bindActionCreators } from 'redux'; import classnames from 'classnames'; import { browserHistory } from 'react-router'; import { Dropdown } from 'antd'; @@ -14,7 +15,10 @@ import withConfig from 'components/ConfigProvider/withConfig'; import { formatToCurrency } from 'utils/currency'; import { MarketsSelector } from 'containers/Trade/utils'; import SparkLine from 'containers/TradeTabs/components/SparkLine'; +import { getSparklines } from 'actions/chartAction'; +import { changeSparkLineChartData } from 'actions/appActions'; +let isMounted = false; class PairTabs extends Component { state = { activePairTab: '', @@ -29,9 +33,6 @@ class PairTabs extends Component { } this.setState({ activePairTab: active }); this.initTabs(pairs, active); - // getSparklines(Object.keys(pairs)).then((chartData) => - // this.props.changeSparkLineChartData(chartData) - // ); } UNSAFE_componentWillReceiveProps(nextProps) { @@ -98,6 +99,7 @@ class PairTabs extends Component { markets, quicktrade, sparkLineChartData, + pairs, } = this.props; const market = markets.find(({ key }) => key === activePairTab) || {}; const { @@ -107,6 +109,13 @@ class PairTabs extends Component { display_name, } = market; + if (activePairTab && !isMounted) { + isMounted = true; + getSparklines(Object.keys(pairs)).then((chartData) => + this.props.changeSparkLineChartData(chartData) + ); + } + const filterQuickTrade = quicktrade.filter(({ type }) => type !== 'pro'); return (
@@ -278,4 +287,14 @@ const mapStateToProps = (state) => { }; }; -export default connect(mapStateToProps)(withConfig(PairTabs)); +const mapDispatchToProps = (dispatch) => ({ + changeSparkLineChartData: bindActionCreators( + changeSparkLineChartData, + dispatch + ), +}); + +export default connect( + mapStateToProps, + mapDispatchToProps +)(withConfig(PairTabs)); diff --git a/web/src/containers/App/App.js b/web/src/containers/App/App.js index e2f5f73687..d0ee8c3f4e 100644 --- a/web/src/containers/App/App.js +++ b/web/src/containers/App/App.js @@ -799,7 +799,7 @@ class App extends Component { onClick={this.resetTimer} onKeyPress={this.resetTimer} /> -
+
{!isChartEmbed && ( Date: Sun, 10 Nov 2024 00:10:02 +0900 Subject: [PATCH 03/11] remove category restriction in transfer from hollaex network utils --- server/utils/hollaex-network-lib/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/utils/hollaex-network-lib/index.js b/server/utils/hollaex-network-lib/index.js index 627b879b28..ff91d3f01d 100644 --- a/server/utils/hollaex-network-lib/index.js +++ b/server/utils/hollaex-network-lib/index.js @@ -1754,7 +1754,7 @@ class HollaExNetwork { data.email = true; } - if (opts.category && ['stake', 'referral', 'internal'].includes(opts.category)) { + if (opts.category) { data.category = opts.category; } From a6aa8a49d9a37bd8b40cf5515c04bd2894e200d1 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Mon, 11 Nov 2024 20:46:21 +0300 Subject: [PATCH 04/11] User Deletion By Admin --- web/src/containers/Admin/User/AboutData.js | 9 ++++ .../Admin/User/DeleteConfirmation.js | 33 +++++++++++++++ web/src/containers/Admin/User/UserContent.js | 41 ++++++++++++++++++- web/src/containers/Admin/User/actions.js | 9 ++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 web/src/containers/Admin/User/DeleteConfirmation.js diff --git a/web/src/containers/Admin/User/AboutData.js b/web/src/containers/Admin/User/AboutData.js index d462b95268..8c51428e1e 100644 --- a/web/src/containers/Admin/User/AboutData.js +++ b/web/src/containers/Admin/User/AboutData.js @@ -461,6 +461,7 @@ const AboutData = ({ freezeAccount, verifyEmail, recoverUser, + deleteUser, onChangeSuccess, allIcons = {}, userTiers, @@ -639,6 +640,14 @@ const AboutData = ({
Account is active
+
{ + deleteUser(); + }} + > + Delete user +
( + +
+
+
+ +
+

+ User Delete +

+
+
+
+ Email: + {userData.email} +
+
Are you sure you want to delete this user?
+
+
+ +
+
+
+); + +export default DeletionConfirmation; diff --git a/web/src/containers/Admin/User/UserContent.js b/web/src/containers/Admin/User/UserContent.js index 3db46b0b4b..93b305922f 100644 --- a/web/src/containers/Admin/User/UserContent.js +++ b/web/src/containers/Admin/User/UserContent.js @@ -30,10 +30,12 @@ import { activateUser, verifyUser, recoverUser, + deleteUser, requestTiers, } from './actions'; import UserMetaForm from './UserMetaForm'; import PaymentMethods from './PaymentMethods'; +import DeletionConfirmation from './DeleteConfirmation'; // import Flagger from '../Flaguser'; // import Notes from './Notes'; @@ -45,6 +47,7 @@ class UserContent extends Component { state = { showVerifyEmailModal: false, showRecoverModal: false, + showDeleteModal: false, userTiers: {}, }; @@ -218,6 +221,24 @@ class UserContent extends Component { }); }; + handleDeleteUser = () => { + const { userInformation = {}, refreshData } = this.props; + const postValues = { + user_id: parseInt(userInformation.id, 10), + }; + + deleteUser(postValues) + .then((res) => { + refreshData({ ...postValues, activated: false }); + this.setState({ showDeleteModal: false }); + }) + .catch((err) => { + const _error = + err.data && err.data.message ? err.data.message : err.message; + message.error(_error); + }); + }; + openVerifyEmailModal = () => { this.setState({ showVerifyEmailModal: true, @@ -230,6 +251,12 @@ class UserContent extends Component { }); }; + openDeleteUserModel = () => { + this.setState({ + showDeleteModal: true, + }); + }; + renderTabBar = (props, DefaultTabBar) => { if (this.props.isConfigure) return
; return ; @@ -252,7 +279,12 @@ class UserContent extends Component { referral_history_config, } = this.props; - const { showVerifyEmailModal, showRecoverModal, userTiers } = this.state; + const { + showVerifyEmailModal, + showRecoverModal, + showDeleteModal, + userTiers, + } = this.state; const { id, @@ -354,6 +386,7 @@ class UserContent extends Component { freezeAccount={this.freezeAccount} verifyEmail={this.openVerifyEmailModal} recoverUser={this.openRecoverUserModel} + deleteUser={this.openDeleteUserModel} kycPluginName={kycPluginName} requestUserData={requestUserData} refreshAllData={refreshAllData} @@ -470,6 +503,12 @@ class UserContent extends Component { onConfirm={this.handleRecoverUser} userData={userInformation} /> + this.setState({ showRecoverModal: false })} + onConfirm={this.handleDeleteUser} + userData={userInformation} + />
); } diff --git a/web/src/containers/Admin/User/actions.js b/web/src/containers/Admin/User/actions.js index 3dee3d6e04..764ed70048 100644 --- a/web/src/containers/Admin/User/actions.js +++ b/web/src/containers/Admin/User/actions.js @@ -214,6 +214,15 @@ export const recoverUser = (values) => { return requestAuthenticated('/admin/user/restore', options); }; +export const deleteUser = (values) => { + const options = { + method: 'DELETE', + body: JSON.stringify(values), + }; + + return requestAuthenticated('/admin/user', options); +}; + export const performVerificationLevelUpdate = (values) => { const options = { method: 'POST', From 0381e7edcfc2fed29469a71fb74356d5b377b9b4 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Thu, 14 Nov 2024 14:41:08 +0300 Subject: [PATCH 05/11] fix p2p payment details query --- server/utils/hollaex-tools-lib/tools/user.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/server/utils/hollaex-tools-lib/tools/user.js b/server/utils/hollaex-tools-lib/tools/user.js index 0bc5a20917..a2c9650b8b 100644 --- a/server/utils/hollaex-tools-lib/tools/user.js +++ b/server/utils/hollaex-tools-lib/tools/user.js @@ -3403,7 +3403,7 @@ const getPaymentDetails = async (user_id, opts = { const query = { where: { created_at: timeframe, - user_id, + ...(user_id && { user_id }), ...(opts.is_p2p && { is_p2p: opts.is_p2p }), ...(opts.is_fiat_control && { is_fiat_control: opts.is_fiat_control }), ...(opts.status && { status: opts.status }) From f8652330ea72e7ba666c2c5be14a3cc5d59d0006 Mon Sep 17 00:00:00 2001 From: fetok12 Date: Thu, 14 Nov 2024 15:03:57 +0300 Subject: [PATCH 06/11] fix p2p cache after update --- server/utils/hollaex-tools-lib/tools/p2p.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/server/utils/hollaex-tools-lib/tools/p2p.js b/server/utils/hollaex-tools-lib/tools/p2p.js index 6aff25db5d..5074cda368 100644 --- a/server/utils/hollaex-tools-lib/tools/p2p.js +++ b/server/utils/hollaex-tools-lib/tools/p2p.js @@ -117,7 +117,7 @@ const fetchP2PDeals = async (opts = { } }); } else { - const p2pDeals = await client.getAsync(`p2p-deals${opts.user_id}`); + const p2pDeals = await client.getAsync(`p2p-deals${opts.user_id || 'all'}`); if (p2pDeals) return JSON.parse(p2pDeals); else { @@ -138,7 +138,7 @@ const fetchP2PDeals = async (opts = { } } - await client.setexAsync(`p2p-deals${opts.user_id}`, 30, JSON.stringify(deals)); + await client.setexAsync(`p2p-deals${opts.user_id || 'all'}`, 30, JSON.stringify(deals)); return deals; } @@ -352,6 +352,7 @@ const updateP2PDeal = async (data) => { } }); await client.delAsync(`p2p-deals${merchant_id}`); + await client.delAsync(`p2p-dealsall`); await getModel('p2pDeal').update({ status }, { where : { id : edited_ids }}); return { message : 'success' }; } @@ -410,7 +411,7 @@ const updateP2PDeal = async (data) => { }; await client.delAsync(`p2p-deals${merchant_id}`); - + await client.delAsync(`p2p-dealsall`); return p2pDeal.update(data, { fields: [ 'merchant_id', @@ -446,6 +447,8 @@ const deleteP2PDeal = async (removed_ids, user_id) => { }; await client.delAsync(`p2p-deals${user_id}`); + await client.delAsync(`p2p-dealsall`); + const promises = deals.map(async (deal) => { return await deal.destroy(); }); From d91b20c21c8a9f855990cb958c186660fb45ca7c Mon Sep 17 00:00:00 2001 From: ram Date: Thu, 14 Nov 2024 23:28:01 +0530 Subject: [PATCH 07/11] Changes for the P2P refinements --- web/src/config/lang/en.json | 12 +- web/src/containers/Admin/Trades/index.css | 28 + web/src/containers/Admin/Trades/p2p.js | 16 +- web/src/containers/Admin/Trades/p2pActive.js | 226 ++++++++ .../containers/Admin/Trades/p2pDisputes.js | 13 +- .../containers/Admin/Trades/p2pSettings.js | 2 +- .../Admin/Trades/p2punverifiedPayments.js | 87 +++ web/src/containers/App/Socket.js | 79 ++- web/src/containers/App/_App.scss | 16 +- web/src/containers/P2P/P2PDash.js | 52 +- web/src/containers/P2P/P2PDashMobile.js | 68 ++- web/src/containers/P2P/P2POrder/P2POrder.js | 478 +++++++++-------- .../containers/P2P/P2POrder/P2POrderChat.js | 32 +- .../P2P/P2POrder/P2POrderDetails.js | 30 +- web/src/containers/P2P/P2POrders.js | 507 +++++++++++++----- web/src/containers/P2P/P2PPostDeal.js | 29 +- web/src/containers/P2P/P2PProfile.js | 95 ++-- web/src/containers/P2P/Utilis.js | 149 ++++- web/src/containers/P2P/_P2P.scss | 240 ++++++++- web/src/containers/P2P/index.js | 21 +- web/src/index.css | 190 ++++++- 21 files changed, 1817 insertions(+), 553 deletions(-) create mode 100644 web/src/containers/Admin/Trades/p2pActive.js create mode 100644 web/src/containers/Admin/Trades/p2punverifiedPayments.js diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index abf32c8328..e48f04990d 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -2092,6 +2092,8 @@ "USER_NAME": "Buyer name:", "ORDER_INITIATED_VENDOR": "Order has been initiated by", "CONFIRM_PAYMENT_VENDOR": "Please communicate with the buyer to confirm this transaction.", + "CONFIRM_PAYMENT_RELEASE": "You must confirm and release the crypto.", + "CONFIRM_PAYMENT_TRANSFER": "You must confirm that you've transferred the money", "ORDER_INITIATED": "You've initiated and created an order with", "CONFIRM_PAYMENT": "Please communicate with the seller to confirm your incoming payment.", "YOU": "You", @@ -2244,7 +2246,7 @@ "INPUT_PAYMENT_DETAIL_TEXT": "Input the payment detail name", "UNVERIFIED": "Unverified", "VERIFIED": "Verified", - "AMOUNT_RECEIVE": "will be released from your balance", + "AMOUNT_RECEIVE": "{0} {1} was released from your wallet balance.", "DELETE_WARNING": "Are you sure you want to delete this payment method?", "STEP_1": "Step 1/3", "STEP_2": "Step 2/3", @@ -2278,7 +2280,13 @@ "CANCEL_WARNING_TEXT": "Please note that frequent order cancellations may negatively affect your public P2P profile and could result in your account being suspended.", "UPDATE": "Update", "TERMS_ERROR_TEXT": "Please Input Terms field", - "RESPONSE_ERROR_TEXT": "Please Input Response field" + "RESPONSE_ERROR_TEXT": "Please Input Response field", + "CHECK_CONFIRM_TITLE": "Check, confirm and release", + "CHECK_CONFIRM_PAYMENT_DESC_1": "Check that you have indeed received the payment: {0} {1}", + "CHECK_CONFIRM_PAYMENT_DESC_2": "After confirming below the crypto ({0} {1}) will be released.", + "CHECK_CONFIRM_DECLARATION": "I confirm that I have received the correct payment", + "P2P_ORDER_COMPLETE": "P2P Order Complete", + "EXIST_PAYMENT_METHOD_DESC": "You’ve already added a payment method for {0}" }, "VOLUME": { "VOLUME": "VOLUME", diff --git a/web/src/containers/Admin/Trades/index.css b/web/src/containers/Admin/Trades/index.css index 87e35983e7..2b541ee076 100644 --- a/web/src/containers/Admin/Trades/index.css +++ b/web/src/containers/Admin/Trades/index.css @@ -791,3 +791,31 @@ .p2p-admin-select-asset .ant-select-item { cursor: text; } + +.p2p-admin-confirm-warning-popup-wrapper .ant-modal-body { + background-color: #27339d; + color: white; +} + +.p2p-admin-confirm-warning-popup-wrapper .p2p-admin-confirm-popup .title { + font-size: 18px; +} + +.p2p-admin-confirm-warning-popup-wrapper + .p2p-admin-confirm-popup + .confirm-button-container { + margin-top: 5%; + display: flex; + gap: 5%; +} + +.p2p-admin-confirm-warning-popup-wrapper + .p2p-admin-confirm-popup + .confirm-button-container + .green-btn { + border: none; +} + +.p2p-admin-confirm-warning-popup-wrapper .ant-modal-close-x { + color: white; +} diff --git a/web/src/containers/Admin/Trades/p2p.js b/web/src/containers/Admin/Trades/p2p.js index b7bebe550a..1d104c1978 100644 --- a/web/src/containers/Admin/Trades/p2p.js +++ b/web/src/containers/Admin/Trades/p2p.js @@ -1,14 +1,16 @@ /* eslint-disable */ import React, { useState } from 'react'; -import { Tabs } from 'antd'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; +import { Tabs } from 'antd'; + +import './index.css'; import P2PDeals from './p2pDeals'; import P2PDisputes from './p2pDisputes'; import P2PSettings from './p2pSettings'; - +import P2PActive from './p2pActive'; +import P2PUnverifiedPayments from './p2punverifiedPayments'; import { setExchange } from 'actions/assetActions'; -import './index.css'; const TabPane = Tabs.TabPane; @@ -39,9 +41,15 @@ const P2P = () => { - + + + + + + +
); diff --git a/web/src/containers/Admin/Trades/p2pActive.js b/web/src/containers/Admin/Trades/p2pActive.js new file mode 100644 index 0000000000..de82c1be00 --- /dev/null +++ b/web/src/containers/Admin/Trades/p2pActive.js @@ -0,0 +1,226 @@ +import React, { useEffect, useState } from 'react'; +import { connect } from 'react-redux'; +import { Table, Button, Modal } from 'antd'; +import { CloseOutlined } from '@ant-design/icons'; + +import { + fetchTransactions, + updateTransaction, +} from 'containers/P2P/actions/p2pActions'; +import { getToken } from 'utils/token'; +import { WS_URL } from 'config/constants'; + +const dataSource = (setIsConfirmWarning, setUserData) => { + return [ + { title: 'Order Id', dataIndex: 'id', key: 'id' }, + { + title: 'Buyer Name', + render: (data) => + data?.buyer?.full_name ? data?.buyer?.full_name : 'Anonymous', + }, + { + title: 'Seller Name', + render: (data) => + data?.merchant?.full_name ? data?.merchant?.full_name : 'Anonymous', + }, + { + title: 'Payment Method', + render: (data) => data?.payment_method_used?.system_name, + }, + { + title: 'Buying Asset', + render: (data) => data?.deal?.buying_asset?.toUpperCase(), + }, + { + title: 'Selling Asset', + render: (data) => data?.deal?.spending_asset?.toUpperCase(), + }, + { + title: 'Cancel', + render: (data) => { + return ( + + ); + }, + }, + ]; +}; + +const P2PActive = ({ user }) => { + const [getOrders, setGetOrders] = useState(); + const [selectedTransaction, setSelectedTransaction] = useState(); + const [webSocket, setWebSocket] = useState(); + const [isConfirmWarning, setIsConfirmWarning] = useState(false); + const [userData, setUserData] = useState(); + + const fetchData = async () => { + try { + const orders = await fetchTransactions(); + setGetOrders(orders); + } catch (error) { + console.error(error); + } + }; + + useEffect(() => { + let pingInterval; + + const connectWebSocket = () => { + const url = `${WS_URL}/stream?authorization=Bearer ${getToken()}`; + const p2pWebSocket = new WebSocket(url); + + p2pWebSocket.onopen = () => { + setWebSocket(p2pWebSocket); + + if (selectedTransaction?.first_created) { + p2pWebSocket.send( + JSON.stringify({ + op: 'p2pChat', + args: [ + { + action: 'getStatus', + data: { + id: selectedTransaction?.id, + status: 'created', + title: 'p2p', + receiver_id: + user?.id === selectedTransaction?.merchant_id + ? selectedTransaction?.user_id + : selectedTransaction?.merchant_id, + }, + }, + ], + }) + ); + } + + pingInterval = setInterval(() => { + if (p2pWebSocket.readyState === WebSocket.OPEN) { + p2pWebSocket.send(JSON.stringify({ op: 'ping' })); + } + }, 55000); + }; + + p2pWebSocket.onclose = (event) => { + clearInterval(pingInterval); + setTimeout(connectWebSocket, 3000); + }; + + p2pWebSocket.onerror = (error) => { + clearInterval(pingInterval); + p2pWebSocket.close(); + }; + + return p2pWebSocket; + }; + + const p2pWebSocket = connectWebSocket(); + + fetchData(); + + return () => { + clearInterval(pingInterval); + p2pWebSocket.close(); + }; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const onHandleCancel = async (data) => { + try { + await updateTransaction({ + id: data?.id, + user_status: 'cancelled', + }); + fetchData(); + notificationStatus('cancelled'); + setSelectedTransaction(data); + } catch (error) { + console.error(error); + } + }; + + const notificationStatus = (status, title = '') => { + webSocket.send( + JSON.stringify({ + op: 'p2pChat', + args: [ + { + action: 'getStatus', + data: { + id: selectedTransaction?.id, + status, + title, + receiver_id: + user?.id === selectedTransaction?.merchant_id + ? selectedTransaction?.user_id + : selectedTransaction?.merchant_id, + }, + }, + ], + }) + ); + }; + + const filteredOrders = getOrders?.data?.filter( + (data) => data?.transaction_status === 'active' + ); + + return ( +
+ } + visible={isConfirmWarning} + footer={null} + onCancel={() => { + setIsConfirmWarning(false); + }} + width={400} + className="p2p-admin-confirm-warning-popup-wrapper" + > +
+
+ {' '} + Are you sure you want to cancel this order? +
+
+ + +
+
+
+ + + ); +}; + +const mapStateToProps = (state) => ({ + user: state.user, +}); + +export default connect(mapStateToProps)(P2PActive); diff --git a/web/src/containers/Admin/Trades/p2pDisputes.js b/web/src/containers/Admin/Trades/p2pDisputes.js index ea8399827e..5296012167 100644 --- a/web/src/containers/Admin/Trades/p2pDisputes.js +++ b/web/src/containers/Admin/Trades/p2pDisputes.js @@ -1,12 +1,12 @@ import React, { useState, useEffect } from 'react'; +import { connect } from 'react-redux'; +import { Link } from 'react-router'; +import { ClockCircleOutlined, CloseOutlined } from '@ant-design/icons'; import { Table, Button, Spin, Input, Modal, message } from 'antd'; import { requestDisputes, editDispute } from './actions'; import moment from 'moment'; // import BigNumber from 'bignumber.js'; // import { ExclamationCircleFilled } from '@ant-design/icons'; -import { connect } from 'react-redux'; -import { CloseOutlined } from '@ant-design/icons'; -import { Link } from 'react-router'; const P2PDisputes = ({ coins }) => { const [userData, setUserData] = useState([]); @@ -83,7 +83,12 @@ const P2PDisputes = ({ coins }) => { render: (user_id, data) => { return (
- {data?.resolution?.toUpperCase() || 'Not adjudicated'} + {data?.resolution?.toUpperCase() || ( + + Not adjudicated + + + )}
); }, diff --git a/web/src/containers/Admin/Trades/p2pSettings.js b/web/src/containers/Admin/Trades/p2pSettings.js index 2df7aa36a5..66f34de34f 100644 --- a/web/src/containers/Admin/Trades/p2pSettings.js +++ b/web/src/containers/Admin/Trades/p2pSettings.js @@ -103,7 +103,7 @@ const P2PSettings = ({ coins, pairs, p2p_config, features, constants }) => { getAllUserData({ id: p2p_config?.source_account }).then((res) => { let emailData = {}; res && - res.forEach((item) => { + res?.forEach((item) => { if (item.value === p2p_config?.source_account) { emailData = item; } diff --git a/web/src/containers/Admin/Trades/p2punverifiedPayments.js b/web/src/containers/Admin/Trades/p2punverifiedPayments.js new file mode 100644 index 0000000000..6fcec5b3d9 --- /dev/null +++ b/web/src/containers/Admin/Trades/p2punverifiedPayments.js @@ -0,0 +1,87 @@ +import React, { useEffect, useState } from 'react'; +import { Link } from 'react-router'; +import { Table, Button } from 'antd'; + +import { fetchP2PPaymentMethods } from '../User/actions'; + +const users = [ + { + title: 'User ID', + dataIndex: 'user_id', + key: 'user_id', + render: (user_id, data) => { + return ( +
+ +
+ ); + }, + }, + { + title: 'Payment Method', + dataIndex: 'payment_method', + key: 'payment_method', + render: (user_id, data) => { + return
{data?.name}
; + }, + }, + { + title: 'Details', + dataIndex: 'details', + key: 'details', + render: (user_id, data) => { + return ( +
+
    + {data?.details?.fields.map((field) => ( +
  • + {field?.name}: {field?.value} +
  • + ))} +
+
+ ); + }, + }, + { + title: 'Status', + dataIndex: 'status', + key: 'status', + render: (user_id, data) => { + return
{data?.status === 0 && 'Unverified'}
; + }, + }, +]; + +const P2PUnverifiedPayments = () => { + const [userList, setUserList] = useState([]); + + const fetchPayment = async () => { + try { + const payment = await fetchP2PPaymentMethods(); + setUserList(payment); + } catch (err) { + console.error('err', err); + } + }; + + useEffect(() => { + fetchPayment(); + }, []); + + const filterByPayment = userList?.data?.filter((data) => data?.status === 0); + + return ( +
+
+ + ); +}; + +export default P2PUnverifiedPayments; diff --git a/web/src/containers/App/Socket.js b/web/src/containers/App/Socket.js index abf004a300..7c5c473dfa 100644 --- a/web/src/containers/App/Socket.js +++ b/web/src/containers/App/Socket.js @@ -455,23 +455,39 @@ class Container extends Component { const notificationDetails = { key, - message: - data.action === 'getStatus' && data?.data?.status === 'appeal' - ? STRINGS['P2P.APPEAL_STATUS_MESSAGE'] - : data?.action === 'getStatus' && - data?.data?.status === 'cancelled' - ? STRINGS['P2P.CANCEL_STATUS_MESSAGE'] - : data?.action === 'getStatus' && - data?.data?.status === 'confirmed' && - data?.data?.title === 'crypto' - ? STRINGS['P2P.CRYPTO_RELEASE_STATUS_MESSAGE'] - : data?.data?.status === 'confirmed' - ? STRINGS['P2P.CONFIRM_STATUS_MESSAGE'] - : data?.data?.status === 'created' - ? STRINGS['P2P.NEW_ORDER_CREATED'] - : data?.action === 'getStatus' - ? STRINGS['P2P.STATUS_UPDATE'] - : STRINGS['P2P.NEW_MESSAGE'], + message: ( +
+ + {data.action === 'getStatus' && + data?.data?.status === 'appeal' + ? STRINGS['P2P.APPEAL_STATUS_MESSAGE'] + : data?.action === 'getStatus' && + data?.data?.status === 'cancelled' + ? STRINGS['P2P.CANCEL_STATUS_MESSAGE'] + : data?.action === 'getStatus' && + data?.data?.status === 'confirmed' && + data?.data?.title === 'crypto' + ? STRINGS['P2P.CRYPTO_RELEASE_STATUS_MESSAGE'] + : data?.data?.status === 'confirmed' + ? STRINGS['P2P.CONFIRM_STATUS_MESSAGE'] + : data?.data?.status === 'created' + ? STRINGS['P2P.NEW_ORDER_CREATED'] + : data?.action === 'getStatus' + ? STRINGS['P2P.STATUS_UPDATE'] + : STRINGS['P2P.NEW_MESSAGE']} + + {data?.data?.message && ( + + + {data?.data?.sender_name}:{' '} + + + {data?.data?.message} + + + )} +
+ ), description: (
- ) : previousMessage === STRINGS['P2P.NEW_MESSAGE'] ? ( + ) : previousNotificationMessage === + STRINGS['P2P.NEW_MESSAGE'] ? ( ) : ( diff --git a/web/src/containers/App/_App.scss b/web/src/containers/App/_App.scss index 60f2a120cf..a6ba2a6d7d 100644 --- a/web/src/containers/App/_App.scss +++ b/web/src/containers/App/_App.scss @@ -354,7 +354,7 @@ $inner_container-border: 1px solid $colors-super-pale-black; border-top: 2px solid $colors-notifications-blue; box-shadow: 4px 4px 15px $app-bar-background-color; padding: 10px 10px !important; - width: 100%; + width: 27rem; .ant-notification-notice-description, .ant-notification-notice-message, @@ -366,6 +366,17 @@ $inner_container-border: 1px solid $colors-super-pale-black; .ant-notification-notice-description { margin-left: 40px; font-size: 13px; + max-width: 85%; + .sender-name { + color: $chat-own-message--color; + } + .chat-message { + color: $chat-message-color; + display: inline-block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + } } .ant-notification-notice-close { top: 10px; @@ -384,6 +395,9 @@ $inner_container-border: 1px solid $colors-super-pale-black; margin-left: 0px !important; width: 100% !important; max-width: unset !important; + .p2p-chat-notification-wrapper { + width: 100% !important; + } } .layout-mobile { diff --git a/web/src/containers/P2P/P2PDash.js b/web/src/containers/P2P/P2PDash.js index 6f6a952a4e..ae0ed6286c 100644 --- a/web/src/containers/P2P/P2PDash.js +++ b/web/src/containers/P2P/P2PDash.js @@ -54,6 +54,7 @@ const P2PDash = ({ changeProfileTab, tab, }) => { + const isBuySell = JSON.parse(localStorage.getItem('isBuySelected')); const [expandRow, setExpandRow] = useState(false); const [selectedDeal, setSelectedDeal] = useState(); const [selectedMethod, setSelectedMethod] = useState(); @@ -75,7 +76,7 @@ const P2PDash = ({ const [selectedProfile, setSelectedProfile] = useState(); const [myMethods, setMyMethods] = useState([]); // const inputRef = useRef(null); - const [isBuySelected, setIsBuySelected] = useState(true); + const [isBuySelected, setIsBuySelected] = useState(isBuySell); const [buyValue, setBuyValue] = useState([]); const [selectedCoin, setSelectedCoin] = useState('USDT'); const [isFilter, setIsFilter] = useState(false); @@ -86,7 +87,9 @@ const P2PDash = ({ fetchDeals({ status: true }) .then((res) => { setDeals(res.data); - const buyDeals = res.data?.filter((deal) => deal?.side === 'sell'); + const buyDeals = res.data?.filter((deal) => + !isBuySelected ? deal?.side === 'buy' : deal?.side === 'sell' + ); const filteredDeals = buyDeals?.filter((deal) => selectedCoin?.includes(deal?.buying_asset?.toUpperCase()) ); @@ -141,6 +144,7 @@ const P2PDash = ({ const cryptoAsset = filteredDeals?.filter((deal) => selectedCoin?.includes(deal?.buying_asset?.toUpperCase()) ); + localStorage.setItem('isBuySelected', newIsBuySelected); setIsBuySelected(newIsBuySelected); setBuyValue(cryptoAsset); }; @@ -816,6 +820,14 @@ const P2PDash = ({
{filteredDeals?.map((deal) => { + const isDisabled = + loading || + !user?.id || + !amountFiat || + amountFiat <= 0 || + !selectedMethod?.system_name || + deal?.min_order_value > amountFiat || + deal?.max_order_value < amountFiat; return ( <>
- - - - - - - - {userFeedback.map((deal) => { - return ( - - - - - ); - })} - -
- - {STRINGS['P2P.COMMENT']} - - - - {STRINGS['P2P.RATING']} - -
{deal.comment} - -
- )} -
-
- - - )} + {displayUserFeedback && + renderFeedback( + displayUserFeedback, + setDisplayUserFeedback, + selectedProfile, + userProfile, + userFeedback + )} {displayFeedbackModal && ( { setDisplayConfirmWarning(false); + setIsDecalred(false); }} >
-
- - {STRINGS['P2P.CONFIRM_WARNING']} - +
+ + +
-
-
- {userReceiveAmount()} - - {selectedOrder?.deal?.buying_asset?.toUpperCase()}{' '} - - - - {STRINGS['P2P.AMOUNT_RECEIVE']} +
+ + {STRINGS['P2P.CHECK_CONFIRM_TITLE']} - +
+
+ + + {STRINGS.formatString( + STRINGS['P2P.CHECK_CONFIRM_PAYMENT_DESC_1'], + + {selectedOrder?.amount_fiat} + , + + {selectedOrder?.deal?.spending_asset?.toUpperCase()} + + )} + + + + + {STRINGS.formatString( + STRINGS['P2P.CHECK_CONFIRM_PAYMENT_DESC_2'], + + {userReceiveAmount()} + , + + {selectedOrder?.deal?.buying_asset?.toUpperCase()} + + )} + + +
+ setIsDecalred(!isDecalred)} + /> + +
+
-
)} - {!isChat && ( + setDisplayReleasedAmountPopup(false)} + className="release-amount-popup-wrapper feedback-submit-popup-wrapper" + > +
+
+ + {STRINGS['P2P.P2P_ORDER_COMPLETE']} + +
+
+ + + + {STRINGS.formatString( + STRINGS['P2P.AMOUNT_RECEIVE'], + + {userReceiveAmount()} + , + + {selectedOrder?.deal?.buying_asset?.toUpperCase()} + + )} + + +
+
+ +
+
+
+ + {((isMobile && !isChat) || !isMobile) && (
{ @@ -795,84 +772,87 @@ const P2POrder = ({
)} - {(isOrderCreated || isOrderVerified || isOrderConfirmed) && !isChat && ( -
-
-
- {(isOrderCreated || isOrderVerified || isOrderConfirmed) && ( - - )} -
-
-
- - {STRINGS['P2P.STEP_1']}: - + {(isOrderCreated || isOrderVerified || isOrderConfirmed) && + ((isMobile && !isChat) || !isMobile) && ( +
+
+
+ {(isOrderCreated || isOrderVerified || isOrderConfirmed) && ( + + )}
-
- - {STRINGS['P2P.P2P_ORDER_CREATED']} - +
+
+ + {STRINGS['P2P.STEP_1']}: + +
+
+ + {STRINGS['P2P.P2P_ORDER_CREATED']} + +
-
-
-
-
- {(isOrderVerified || isOrderConfirmed) && } -
-
-
- - {STRINGS['P2P.STEP_2']}: - +
+
+
+ {(isOrderVerified || isOrderConfirmed) && ( + + )}
-
- - {STRINGS['P2P.VENDOR_CHECKS_TITLE']} - +
+
+ + {STRINGS['P2P.STEP_2']}: + +
+
+ + {STRINGS['P2P.VENDOR_CHECKS_TITLE']} + +
-
-
-
-
- {isOrderConfirmed && } -
-
-
- - {STRINGS['P2P.STEP_3']}: - +
+
+
+ {isOrderConfirmed && }
-
- - {STRINGS['P2P.FUND_RELEASED']} - +
+
+ + {STRINGS['P2P.STEP_3']}: + +
+
+ + {STRINGS['P2P.FUND_RELEASED']} + +
-
- )} + )}
-
+
@@ -901,7 +881,13 @@ const P2POrder = ({ {selectedOrder.transaction_id}
-
+ {user.id === selectedOrder.merchant_id ? ( {STRINGS['P2P.SELL_COIN']} @@ -912,7 +898,7 @@ const P2POrder = ({ )}{' '} {coin?.fullname} ({coin?.symbol?.toUpperCase()}) -
+
{/*
{ - try { - setDisplayAppealModel(true); - setAppealSide('merchant'); - } catch (error) { - message.error(error.data.message); + if (selectedOrder?.user_status === 'confirmed') { + try { + setDisplayAppealModel(true); + setAppealSide('merchant'); + } catch (error) { + message.error(error.data.message); + } } }} > @@ -1581,7 +1573,7 @@ const P2POrder = ({ )}
-
+
{user.id === selectedOrder?.user_id && (
@@ -1651,6 +1643,15 @@ const P2POrder = ({
)} + {user?.id === selectedOrder?.user_id && + selectedOrder?.transaction_status === 'active' && + selectedOrder?.user_status === 'pending' && ( +
+ + {STRINGS['P2P.CONFIRM_PAYMENT_TRANSFER']} + +
+ )}
@@ -1676,7 +1677,7 @@ const P2POrder = ({ } else { if (message.type === 'notification') { return ( -
+
{message.message === 'BUYER_PAID_ORDER' && user.id === selectedOrder.user_id ? ( selectedOrder?.deal?.side === 'sell' ? ( @@ -1706,6 +1707,15 @@ const P2POrder = ({ ).format('DD/MMM/YYYY, hh:mmA')} ) + {user?.id === selectedOrder?.merchant_id && + selectedOrder?.merchant_status === + 'pending' && ( +
+ + {STRINGS['P2P.CONFIRM_PAYMENT_RELEASE']} + +
+ )}
); } else { diff --git a/web/src/containers/P2P/P2POrder/P2POrderChat.js b/web/src/containers/P2P/P2POrder/P2POrderChat.js index 035f72880a..2268d13e45 100644 --- a/web/src/containers/P2P/P2POrder/P2POrderChat.js +++ b/web/src/containers/P2P/P2POrder/P2POrderChat.js @@ -154,7 +154,7 @@ const P2POrderChat = ({
)}
-
+
{user?.id === selectedOrder?.user_id && (
@@ -217,9 +217,27 @@ const P2POrderChat = ({
)} + {user?.id === selectedOrder?.user_id && + selectedOrder?.transaction_status === 'active' && + selectedOrder?.user_status === 'pending' && ( +
+ + {STRINGS['P2P.CONFIRM_PAYMENT_TRANSFER']} + +
+ )}
-
+
{selectedOrder?.messages?.map((message, index) => { if (index === 0) { @@ -244,7 +262,7 @@ const P2POrderChat = ({ } else { if (message.type === 'notification') { return ( -
+
{message.message === 'BUYER_PAID_ORDER' && user?.id === selectedOrder?.user_id ? ( @@ -262,6 +280,14 @@ const P2POrderChat = ({ )} ) + {user?.id === selectedOrder?.merchant_id && + selectedOrder?.merchant_status === 'pending' && ( +
+ + {STRINGS['P2P.CONFIRM_PAYMENT_RELEASE']} + +
+ )}
); } else { diff --git a/web/src/containers/P2P/P2POrder/P2POrderDetails.js b/web/src/containers/P2P/P2POrder/P2POrderDetails.js index 136a314beb..b55ba8b250 100644 --- a/web/src/containers/P2P/P2POrder/P2POrderDetails.js +++ b/web/src/containers/P2P/P2POrder/P2POrderDetails.js @@ -46,7 +46,7 @@ const P2POrderDetails = ({ >
-
+
{STRINGS['P2P.ORDER']}: @@ -55,7 +55,13 @@ const P2POrderDetails = ({ {selectedOrder?.transaction_id} -
+ {user?.id === selectedOrder?.merchant_id ? ( {STRINGS['P2P.SELL_COIN']} @@ -66,7 +72,7 @@ const P2POrderDetails = ({ )}{' '} {coin?.fullname} ({coin?.symbol?.toUpperCase()}) -
+
{isMobile && (
@@ -574,14 +580,20 @@ const P2POrderDetails = ({ >
{ - try { - setDisplayAppealModel(true); - setAppealSide('merchant'); - } catch (error) { - message.error(error.data.message); + if (selectedOrder?.user_status === 'confirmed') { + try { + setDisplayAppealModel(true); + setAppealSide('merchant'); + } catch (error) { + message.error(error.data.message); + } } }} - className="appeal-link blue-link" + className={ + selectedOrder?.user_status !== 'confirmed' + ? 'appeal-link blue-link disable-link' + : 'appeal-link blue-link' + } > {STRINGS['P2P.APPEAL']} diff --git a/web/src/containers/P2P/P2POrders.js b/web/src/containers/P2P/P2POrders.js index 19256c33ec..bf3e6d766b 100644 --- a/web/src/containers/P2P/P2POrders.js +++ b/web/src/containers/P2P/P2POrders.js @@ -2,7 +2,7 @@ import React, { useEffect, useState } from 'react'; import { withRouter } from 'react-router'; import { connect } from 'react-redux'; import { isMobile } from 'react-device-detect'; -import { Button } from 'antd'; +import { Button, Card } from 'antd'; import { CheckCircleTwoTone, PlaySquareTwoTone } from '@ant-design/icons'; import './_P2P.scss'; @@ -10,9 +10,13 @@ import classnames from 'classnames'; import STRINGS from 'config/localizedStrings'; import withConfig from 'components/ConfigProvider/withConfig'; import Filter from './Filters'; -import NoDealsData from './Utilis'; +import NoDealsData, { renderFeedback } from './Utilis'; import { Coin, EditWrapper } from 'components'; -import { fetchTransactions } from './actions/p2pActions'; +import { + fetchFeedback, + fetchP2PProfile, + fetchTransactions, +} from './actions/p2pActions'; import { formatToCurrency } from 'utils/currency'; const P2POrders = ({ @@ -31,6 +35,14 @@ const P2POrders = ({ router, changeProfileTab, tab, + displayUserFeedback, + setDisplayUserFeedback, + selectedProfile, + userProfile, + userFeedback, + setSelectedProfile, + setUserFeedback, + setUserProfile, }) => { const [transactions, setTransactions] = useState([]); const [filter, setFilter] = useState(); @@ -74,6 +86,32 @@ const P2POrders = ({ setFilter(); } }; + + const onHandleFeedback = async (transaction) => { + const isMerchant = + transaction?.user_id === user?.id + ? transaction?.merchant + : transaction?.buyer; + const isMerchantId = + transaction?.user_id === user?.id + ? transaction?.merchant_id + : transaction?.buyer?.id; + try { + setSelectedProfile(isMerchant); + const feedbacks = await fetchFeedback({ + merchant_id: isMerchantId, + }); + const profile = await fetchP2PProfile({ + user_id: isMerchantId, + }); + setUserFeedback(feedbacks?.data); + setUserProfile(profile); + setDisplayUserFeedback(true); + } catch (error) { + console.error(error); + } + }; + return (
+ {displayUserFeedback && + renderFeedback( + displayUserFeedback, + setDisplayUserFeedback, + selectedProfile, + userProfile, + userFeedback + )}
{orderStatus?.map((status) => { return ( @@ -136,47 +182,202 @@ const P2POrders = ({ )}
{transactions?.length > 0 ? ( - - - - - - - - - - - - - + !isMobile ? ( +
- - {STRINGS['P2P.TYPE_COIN']} - - - - {STRINGS['P2P.FIAT_AMOUNT']} - - - - {STRINGS['P2P.PRICE']} - - - - {STRINGS['P2P.CRYPTO_AMOUNT']} - - - - {STRINGS['P2P.COUNTERPARTY']} - - - - {STRINGS['P2P.STATUS']} - - - - {STRINGS['P2P.OPERATION']} - -
+ + + + + + + + + + + + + {transactions + ?.filter((x) => + filter + ? ['active', 'appealed']?.includes(x?.transaction_status) + : true + ) + ?.map((transaction) => { + const statusClassMap = { + complete: 'active-green', + appealed: 'active-orange', + active: 'active-yellow', + }; + + const transactionStatusClass = + statusClassMap[transaction?.transaction_status] || + 'inactive-text'; + const isDisabled = [ + 'expired', + 'cancelled', + 'closed', + ].includes(transaction?.transaction_status); + return ( + + + + + + + + + + + + ); + })} + +
+ + {STRINGS['P2P.TYPE_COIN']} + + + + {STRINGS['P2P.FIAT_AMOUNT']} + + + + {STRINGS['P2P.PRICE']} + + + + {STRINGS['P2P.CRYPTO_AMOUNT']} + + + + {STRINGS['P2P.COUNTERPARTY']} + + + + {STRINGS['P2P.STATUS']} + + + + {STRINGS['P2P.OPERATION']} + +
+ {transaction?.user_id === user?.id ? ( + + ) : ( + + )} + + {transaction?.amount_fiat} + + {transaction?.deal?.spending_asset?.toUpperCase()} + + + + {formatAmount( + transaction?.deal?.buying_asset, + transaction?.price + )} + + + {transaction?.deal?.buying_asset?.toUpperCase()} + + +
+ + {formatAmount( + transaction?.deal?.buying_asset, + transaction?.amount_digital_currency + )} + + + {transaction?.deal?.buying_asset?.toUpperCase()} + + +
+
+ {transaction?.user_id === user?.id ? ( + { + onHandleFeedback(transaction); + }} + > + {transaction?.merchant?.full_name || ( + + {STRINGS['P2P.ANONYMOUS']} + + )} + + ) : ( + { + onHandleFeedback(transaction); + }} + > + {transaction?.buyer?.full_name || ( + + {STRINGS['P2P.ANONYMOUS']} + + )} + + )} + +
+ + {transaction?.transaction_status} + + {transaction?.transaction_status === 'complete' && ( + + + + )} + {transaction?.transaction_status === 'active' && ( + + + + )} +
+
+
{ + setDisplayOrder(true); + setSelectedTransaction(transaction); + router.replace(`/p2p/order/${transaction?.id}`); + }} + > + + + {STRINGS['P2P.VIEW_ORDER']} + + +
+
+ ) : ( +
{transactions ?.filter((x) => filter @@ -197,135 +398,145 @@ const P2POrders = ({ 'expired', 'cancelled', 'closed', - ].includes(transaction?.transaction_status); + ]?.includes(transaction?.transaction_status); return ( - - - {transaction?.user_id === user?.id ? ( - - ) : ( - - )} - - - - {transaction?.amount_fiat} - - {transaction?.deal?.spending_asset?.toUpperCase()} - - - - - {formatAmount( - transaction?.deal?.buying_asset, - transaction?.price )} - - - {transaction?.deal?.buying_asset?.toUpperCase()} - - - -
- - {formatAmount( - transaction?.deal?.buying_asset, - transaction?.amount_digital_currency - )} +
+
+ + + {STRINGS['P2P.FIAT_AMOUNT']}: + - - {transaction?.deal?.buying_asset?.toUpperCase()} + + {transaction?.amount_fiat} + + {transaction?.deal?.spending_asset?.toUpperCase()} + -
- - - {transaction?.user_id === user?.id ? ( - { - changeProfileTab(transaction?.merchant); - }} - > - {transaction?.merchant?.full_name || ( - - {STRINGS['P2P.ANONYMOUS']} - - )} - - ) : ( +
- {transaction?.buyer?.full_name || ( - - {STRINGS['P2P.ANONYMOUS']} - - )} + + {STRINGS['P2P.CRYPTO_AMOUNT']}: + - )} - - -
- - {transaction?.transaction_status} - - {transaction?.transaction_status === 'complete' && ( - - +
+ + {formatAmount( + transaction?.deal?.buying_asset, + transaction?.amount_digital_currency + )} - )} - {transaction?.transaction_status === 'active' && ( - - + + {transaction?.deal?.buying_asset?.toUpperCase()} - )} + +
- - -
{ - setDisplayOrder(true); - setSelectedTransaction(transaction); - router.replace(`/p2p/order/${transaction?.id}`); - }} - > - - - {STRINGS['P2P.VIEW_ORDER']} +
+
+ + + {STRINGS['P2P.STATUS']}: + - +
+ + {transaction?.transaction_status} + + {transaction?.transaction_status === + 'complete' && ( + + + + )} + {transaction?.transaction_status === 'active' && ( + + + + )} +
+
+
+
{ + setDisplayOrder(true); + setSelectedTransaction(transaction); + router.replace(`/p2p/order/${transaction?.id}`); + }} + > + + + {STRINGS['P2P.VIEW_ORDER']} + + +
+
- - +
+ ); })} - - +
+ ) ) : ( )} diff --git a/web/src/containers/P2P/P2PPostDeal.js b/web/src/containers/P2P/P2PPostDeal.js index 6330e024b4..173ca7f7f4 100644 --- a/web/src/containers/P2P/P2PPostDeal.js +++ b/web/src/containers/P2P/P2PPostDeal.js @@ -18,7 +18,11 @@ import P2PPostDealMobile from './P2PPostDealMobile'; import { Coin, Dialog, EditWrapper } from 'components'; import { COUNTRIES_OPTIONS } from 'utils/countries'; import { createTestBroker } from 'containers/Admin/Trades/actions'; -import { editDeal, postDeal } from './actions/p2pActions'; +import { + editDeal, + fetchP2PPaymentMethods, + postDeal, +} from './actions/p2pActions'; const P2PPostDeal = ({ data, @@ -65,6 +69,7 @@ const P2PPostDeal = ({ stepTwo: false, stepThree: false, }); + const [myMethods, setMyMethods] = useState([]); useEffect(() => { if (selectedDealEdit) { @@ -96,6 +101,28 @@ const P2PPostDeal = ({ }; }, [tab]); + useEffect(() => { + try { + fetchP2PPaymentMethods({ is_p2p: true }) + .then((res) => { + setMyMethods(res.data); + }) + .catch((err) => err); + } catch (error) { + console.error(error); + } + if (!selectedDealEdit) { + setPaymentMethods(() => + p2p_config?.bank_payment_methods?.filter((method) => + myMethods?.map( + (payment) => method?.system_name === payment?.system_name + ) + ) + ); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [step]); + const getBrokerData = async () => { try { const res = broker; diff --git a/web/src/containers/P2P/P2PProfile.js b/web/src/containers/P2P/P2PProfile.js index 9f60cc1eca..dcff9e1a85 100644 --- a/web/src/containers/P2P/P2PProfile.js +++ b/web/src/containers/P2P/P2PProfile.js @@ -114,6 +114,11 @@ const P2PProfile = ({ }); } }; + + const isPaymentMethod = myMethods?.filter((method) => { + return method?.name === paymentMethod?.system_name; + }); + return (
{ - const payload = { - system_name: paymentMethod.system_name, - fields: customFields, - }; - paymentMethods.push(payload); - - if (!payload.system_name) { - message.error(STRINGS['P2P.INPUT_METHOD_NAME_TEXT']); - return; - } - - let hasValidation = true; - payload.fields?.forEach((field) => { - if (!field.name || !field.value) { - message.error(STRINGS['P2P.FIELD_VALIDATION_TEXT']); - hasValidation = false; + if (isPaymentMethod?.length === 0) { + const payload = { + system_name: paymentMethod.system_name, + fields: customFields, + }; + paymentMethods.push(payload); + + if (!payload.system_name) { + message.error(STRINGS['P2P.INPUT_METHOD_NAME_TEXT']); + return; } - }); - if (!hasValidation) return; - await createP2PPaymentMethod({ - name: payload.system_name, - details: payload, - is_p2p: true, - }); - message.success(STRINGS['P2P.PAYMENT_METHOD_CREATED']); + let hasValidation = true; + payload.fields?.forEach((field) => { + if (!field.name || !field.value) { + message.error(STRINGS['P2P.FIELD_VALIDATION_TEXT']); + hasValidation = false; + } + }); + if (!hasValidation) return; + await createP2PPaymentMethod({ + name: payload.system_name, + details: payload, + is_p2p: true, + }); - fetchP2PPaymentMethods({ is_p2p: true }) - .then((res) => { - setMyMethods(res.data); - }) - .catch((err) => err); + message.success(STRINGS['P2P.PAYMENT_METHOD_CREATED']); - setPaymentMethods(paymentMethods); - setDisplayNewPayment(false); - setDefaultPaymentMethod(); - setCustomFields([ - { - id: 1, - name: null, - required: true, - }, - ]); - setRefresh(!refresh); + fetchP2PPaymentMethods({ is_p2p: true }) + .then((res) => { + setMyMethods(res.data); + }) + .catch((err) => err); + + setPaymentMethods(paymentMethods); + setDisplayNewPayment(false); + setDefaultPaymentMethod(); + setCustomFields([ + { + id: 1, + name: null, + required: true, + }, + ]); + setRefresh(!refresh); + } else { + message.error( + STRINGS.formatString( + STRINGS['P2P.EXIST_PAYMENT_METHOD_DESC'], + paymentMethod?.system_name + ) + ); + setDisplayNewPayment(false); + } }} className="purpleButtonP2P add-btn" type="default" diff --git a/web/src/containers/P2P/Utilis.js b/web/src/containers/P2P/Utilis.js index 8877a95d5d..51c3d2d6f0 100644 --- a/web/src/containers/P2P/Utilis.js +++ b/web/src/containers/P2P/Utilis.js @@ -1,9 +1,10 @@ import React from 'react'; +import { Rate } from 'antd'; import icons from 'config/icons/dark'; -import strings from 'config/localizedStrings'; +import STRINGS from 'config/localizedStrings'; import { IconTitle } from 'hollaex-web-lib'; -import { EditWrapper } from 'components'; +import { Dialog, EditWrapper } from 'components'; const NoDealsData = ({ trade }) => { return ( @@ -12,16 +13,16 @@ const NoDealsData = ({ trade }) => { stringId="ACCOUNTS.P2P" textType="title" iconPath={icons['TAB_P2P']} - iconId={strings['ACCOUNTS.P2P']} + iconId={STRINGS['ACCOUNTS.P2P']} /> {trade === 'deals' ? ( - {strings['P2P.NO_DEALS_DESC']} + {STRINGS['P2P.NO_DEALS_DESC']} ) : ( - {strings['P2P.NO_ORDERS_DESC']} + {STRINGS['P2P.NO_ORDERS_DESC']} )} @@ -29,4 +30,142 @@ const NoDealsData = ({ trade }) => { ); }; +export const renderFeedback = ( + displayUserFeedback, + setDisplayUserFeedback, + selectedProfile, + userProfile, + userFeedback +) => { + return ( + { + setDisplayUserFeedback(false); + }} + > +
+
+
+ {selectedProfile?.full_name || ( + + {STRINGS['P2P.ANONYMOUS']} + + )} + + ( + + {STRINGS['P2P.TAB_PROFILE']} + + ) + +
+
+
+
+
+
+ + {STRINGS['P2P.TOTAL_ORDERS']} + +
+
+ {userProfile?.totalTransactions} + + + {STRINGS['P2P.TIMES']} + + +
+
+
+
+ + {STRINGS['P2P.COMPLETION_RATE']} + +
+
+ {(userProfile?.completionRate || 0).toFixed(2)}% +
+
+
+
+ + {STRINGS['P2P.POSITIVE_FEEDBACK']} + +
+
+ {(userProfile?.positiveFeedbackRate || 0).toFixed(2)}% +
+
+ + {STRINGS['P2P.POSITIVE']} + + {userProfile?.positiveFeedbackCount} / + + {STRINGS['P2P.NEGATIVE']} + + {userProfile?.negativeFeedbackCount} +
+
+
+
+
+ + + {STRINGS['P2P.FEEDBACK']} + + + ({userFeedback?.length || 0}) +
+ {userFeedback?.length === 0 ? ( +
+ + {STRINGS['P2P.NO_FEEDBACK']} + +
+ ) : ( + + + + + + + + + {userFeedback?.map((deal) => { + return ( + + + + + ); + })} + +
+ + {STRINGS['P2P.COMMENT']} + + + + {STRINGS['P2P.RATING']} + +
{deal?.comment} + +
+ )} +
+
+
+
+ ); +}; + export default NoDealsData; diff --git a/web/src/containers/P2P/_P2P.scss b/web/src/containers/P2P/_P2P.scss index 9c77e88ce2..fa127c8fbb 100644 --- a/web/src/containers/P2P/_P2P.scss +++ b/web/src/containers/P2P/_P2P.scss @@ -387,6 +387,10 @@ margin-top: 15px; gap: 10px; + .inactive-btn { + background-color: var(--labels_inactive-button) !important; + } + .greyButtonP2P { color: var( --labels_important-active-labels-text-graphics @@ -695,6 +699,9 @@ tbody { tr { + .transaction-user-name:hover { + cursor: pointer; + } .trade-button, .transaction-fiat-amount, .transaction-currency-amount, @@ -1686,6 +1693,19 @@ .asset-name { font-weight: bold; } + + .asset-buy, + .asset-sell { + padding: 0.5% 2%; + background-color: var(--specials_checks-okay-done); + width: max-content; + } + + .asset-sell { + background-color: var( + --trading_selling-related-elements + ) !important; + } } .transaction-container, @@ -1813,6 +1833,10 @@ cursor: pointer; } + .disable-link { + cursor: not-allowed !important; + } + .appeal-confirm-button-container-active { display: flex; align-items: center; @@ -1822,7 +1846,6 @@ } .appeal-confirm-button-container { - pointer-events: none; opacity: 0.5; } } @@ -2686,6 +2709,51 @@ } } +.confirm-popup-wrapper { + .feedback-submit-popup-container { + align-items: center; + } + .submit-transaction-button-container { + .inactive-btn { + background-color: var(--labels_inactive-button) !important; + } + } +} + +.release-amount-popup-wrapper { + .ReactModal__Content { + width: 30%; + .release-amount-details-container { + .user-receive-amount-detail { + font-size: 14px; + display: flex; + align-items: flex-start; + } + .order-complete-title { + font-size: 22px; + } + .check-icon { + svg { + height: 2rem; + width: 2rem; + + path:nth-child(1) { + fill: transparent; + } + + path:nth-child(2) { + fill: var(--specials_checks-okay-done); + } + + path:nth-child(3) { + fill: #ffffff; + } + } + } + } + } +} + .cancel-popup-wrapper, .confirm-popup-wrapper, .confirmation-remove-deal-popup-wrapper { @@ -2697,6 +2765,43 @@ font-size: 18px !important; } + .warning-icon { + background-color: #ffffff; + display: flex; + align-items: center; + justify-content: center; + border-radius: 25px; + + svg { + width: 6rem; + height: 6rem; + path { + fill: var(--specials_pending-waiting-caution); + } + } + } + + .confirm-payment-description { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 5px; + .payment-declaration-text { + margin-top: 5%; + display: flex; + .ant-checkbox-inner { + background-color: var(--base_wallet-sidebar-and-popup); + } + + .ant-checkbox-checked { + .ant-checkbox-inner::after { + border-color: var(--labels_important-active-labels-text-graphics); + } + } + } + } + .cancel-warning-text { padding: 3%; background-color: var(--base_secondary-navigation-bar); @@ -2715,11 +2820,6 @@ } } - .user-receive-amount-detail { - margin-top: 3%; - font-size: 14px; - } - .submit-transaction-button-container { margin-top: 5% !important; } @@ -3579,6 +3679,82 @@ overflow-x: scroll; text-wrap: nowrap; + .p2p-orders-details-card-wrapper { + display: flex; + flex-direction: column; + gap: 15px; + + .active-green { + color: var(--specials_checks-okay-done); + } + + .active-orange { + color: var(--specials_pending-waiting-caution); + } + + .active-yellow { + color: var(--specials_my-username-in-chat); + } + + .inactive-text { + color: var(--labels_secondary-inactive-label-text-graphics); + } + + .p2p-orders-card-details { + background-color: var(--base_wallet-sidebar-and-popup) !important; + border: none; + font-size: 24px; + border-bottom: 5px solid var(--base_background); + .p2p-orders-details-inactive { + opacity: 0.5; + } + .p2p-orders-details { + display: flex; + flex-direction: column; + gap: 10px; + + .p2p-sell-order-button, + .p2p-buy-order-button { + background-color: var(--trading_selling-related-elements); + padding: 1% 2%; + font-size: 24px; + } + + .p2p-buy-order-button { + background-color: var(--specials_checks-okay-done) !important; + } + + .transaction-user-name { + font-size: 26px; + } + + .transaction-fiat-amount-wrapper { + display: flex; + gap: 2%; + align-items: center; + + .edit-wrapper__container { + color: var(--labels_important-active-labels-text-graphics); + } + } + + .transaction-status { + display: flex; + justify-content: space-between; + gap: 4%; + font-weight: normal; + + .transaction-status-detail { + display: flex; + gap: 4%; + font-weight: bold; + text-transform: capitalize; + } + } + } + } + } + .p2p-order-table { thead { tr { @@ -3672,7 +3848,7 @@ .order-title, .asset-name { .edit-wrapper__container { - font-size: 18px; + font-size: 24px; } } @@ -3751,6 +3927,10 @@ height: 65%; } + .chat-area-wrapper { + height: 60% !important; + } + .message-input-field { .ant-input { font-size: 24px; @@ -3837,11 +4017,34 @@ gap: 10px; padding: 5% 0; + .active-payment-field { + border-color: var(--specials_buttons-links-and-highlights) !important; + } + + .active-focus { + border: 2px solid #5d63ff !important; + + .amount-spent-field, + .amount-receive-field { + background-color: var(--base_background) !important; + border: none; + box-shadow: inset 1px 1px 3px #00000029; + border-radius: 5px; + border-bottom: 1px solid + var(--labels_important-active-labels-text-graphics) !important; + } + } + + .p2p-amount-spent:hover, + .p2p-amount-receive:hover { + border: 2px solid var(--labels_important-active-labels-text-graphics); + } + .p2p-amount-spent, .p2p-amount-receive { - border: 1px solid var(--calculated_secondary-border); + border: 2px solid var(--calculated_secondary-border); border-radius: 10px; - padding: 8% 6%; + padding: 6%; display: flex; flex-direction: column; gap: 10px; @@ -3870,6 +4073,7 @@ margin-top: 3%; display: flex; width: 100%; + gap: 5%; justify-content: space-between; align-items: center; @@ -3894,15 +4098,13 @@ .amount-spent-field, .amount-receive-field { - background-color: var(--base_background) !important; + background-color: transparent; border: none; - box-shadow: inset 1px 1px 3px #00000029; + box-shadow: none; border-radius: 5px; color: var( --labels_important-active-labels-text-graphics ) !important; - border-bottom: 1px solid - var(--labels_important-active-labels-text-graphics); .ant-input-number-input { text-align: right; @@ -3925,6 +4127,14 @@ border-bottom: 1px solid var(--labels_important-active-labels-text-graphics); } + .amount-receive-field:focus { + background-color: var(--base_background) !important; + border: none; + box-shadow: inset 1px 1px 3px #00000029; + border-radius: 5px; + border-bottom: 1px solid + var(--labels_important-active-labels-text-graphics) !important; + } } } @@ -3940,6 +4150,10 @@ justify-content: space-between; width: 100%; + .inactive-btn { + background-color: var(--labels_inactive-button) !important; + } + .payment-method-field { .ant-select-selector { background-color: transparent; diff --git a/web/src/containers/P2P/index.js b/web/src/containers/P2P/index.js index 1f3736f07d..a8c60d8077 100644 --- a/web/src/containers/P2P/index.js +++ b/web/src/containers/P2P/index.js @@ -35,6 +35,9 @@ const P2P = ({ const [refresh, setRefresh] = useState(false); const [selectedDealEdit, setSelectedDealEdit] = useState(); const [selectedProfile, setSelectedProfile] = useState(); + const [displayUserFeedback, setDisplayUserFeedback] = useState(false); + const [userFeedback, setUserFeedback] = useState([]); + const [userProfile, setUserProfile] = useState(); useEffect(() => { const arr = window.location.pathname.split('/'); @@ -102,6 +105,14 @@ const P2P = ({ setSelectedTransaction={setSelectedTransaction} selectedTransaction={selectedTransaction} changeProfileTab={changeProfileTab} + displayUserFeedback={displayUserFeedback} + setDisplayUserFeedback={setDisplayUserFeedback} + userProfile={userProfile} + setUserProfile={setUserProfile} + userFeedback={userFeedback} + setUserFeedback={setUserFeedback} + selectedProfile={selectedProfile} + setSelectedProfile={setSelectedProfile} /> )} {!displayOrder && ( @@ -151,7 +162,15 @@ const P2P = ({ setDisplayOrder={setDisplayOrder} setSelectedTransaction={setSelectedTransaction} refresh={refresh} - changeProfileTab={changeProfileTab} + // changeProfileTab={changeProfileTab} + displayUserFeedback={displayUserFeedback} + setDisplayUserFeedback={setDisplayUserFeedback} + userFeedback={userFeedback} + setUserFeedback={setUserFeedback} + selectedProfile={selectedProfile} + setSelectedProfile={setSelectedProfile} + userProfile={userProfile} + setUserProfile={setUserProfile} tab={tab} /> diff --git a/web/src/index.css b/web/src/index.css index 110b92ffe1..f81ddea12f 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -611,7 +611,7 @@ table th { border-top: 2px solid var(--specials_buttons-links-and-highlights); box-shadow: 4px 4px 15px var(--base_top-bar-navigation); padding: 10px 10px !important; - width: 100%; } + width: 27rem; } .p2p-chat-notification-wrapper .ant-notification-notice-description, .p2p-chat-notification-wrapper .ant-notification-notice-message, .p2p-chat-notification-wrapper .ant-notification-notice-content, @@ -620,7 +620,18 @@ table th { .p2p-chat-notification-wrapper .ant-notification-notice-message, .p2p-chat-notification-wrapper .ant-notification-notice-description { margin-left: 40px; - font-size: 13px; } + font-size: 13px; + max-width: 85%; } + .p2p-chat-notification-wrapper .ant-notification-notice-message .sender-name, + .p2p-chat-notification-wrapper .ant-notification-notice-description .sender-name { + color: var(--specials_my-username-in-chat); } + .p2p-chat-notification-wrapper .ant-notification-notice-message .chat-message, + .p2p-chat-notification-wrapper .ant-notification-notice-description .chat-message { + color: var(--specials_chat-messages); + display: inline-block; + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; } .p2p-chat-notification-wrapper .ant-notification-notice-close { top: 10px; right: 12px; } @@ -631,6 +642,8 @@ table th { margin-left: 0px !important; width: 100% !important; max-width: unset !important; } + .ant-notification-bottomLeft .p2p-chat-notification-wrapper { + width: 100% !important; } .layout-mobile .footer-bar-more-options-container { display: flex; @@ -10931,6 +10944,11 @@ table th { justify-content: flex-end; margin-top: 15px; gap: 10px; } + .p2p-summary-container .p2p-tab-container .p2p-table-container .p2p-stake-table .p2p-expendable-row .payment-details-container .payment-details .trade-button-container .inactive-btn, + .p2p-summary-container .p2p-order-tab-container .p2p-table-container .p2p-stake-table .p2p-expendable-row .payment-details-container .payment-details .trade-button-container .inactive-btn, + .p2p-summary-container .p2p-post-deal-container .p2p-table-container .p2p-stake-table .p2p-expendable-row .payment-details-container .payment-details .trade-button-container .inactive-btn, + .p2p-summary-container .p2p-order-wrapper .p2p-table-container .p2p-stake-table .p2p-expendable-row .payment-details-container .payment-details .trade-button-container .inactive-btn { + background-color: var(--labels_inactive-button) !important; } .p2p-summary-container .p2p-tab-container .p2p-table-container .p2p-stake-table .p2p-expendable-row .payment-details-container .payment-details .trade-button-container .greyButtonP2P, .p2p-summary-container .p2p-order-tab-container .p2p-table-container .p2p-stake-table .p2p-expendable-row .payment-details-container .payment-details .trade-button-container .greyButtonP2P, .p2p-summary-container .p2p-post-deal-container .p2p-table-container .p2p-stake-table .p2p-expendable-row .payment-details-container .payment-details .trade-button-container .greyButtonP2P, @@ -11161,6 +11179,8 @@ table th { padding-bottom: 0.5%; } .p2p-summary-container .p2p-order-tab-container .p2p-order-table-wrapper .p2p-order-table .table-row-inactive td:not(:last-child) { opacity: 0.5; } + .p2p-summary-container .p2p-order-tab-container .p2p-order-table-wrapper .p2p-order-table tbody tr .transaction-user-name:hover { + cursor: pointer; } .p2p-summary-container .p2p-order-tab-container .p2p-order-table-wrapper .p2p-order-table tbody tr .trade-button, .p2p-summary-container .p2p-order-tab-container .p2p-order-table-wrapper .p2p-order-table tbody tr .transaction-fiat-amount, .p2p-summary-container .p2p-order-tab-container .p2p-order-table-wrapper .p2p-order-table tbody tr .transaction-currency-amount, @@ -11841,6 +11861,13 @@ table th { .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .trade-assets-container .order-title, .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .trade-assets-container .asset-name { font-weight: bold; } + .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .trade-assets-container .asset-buy, + .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .trade-assets-container .asset-sell { + padding: 0.5% 2%; + background-color: var(--specials_checks-okay-done); + width: max-content; } + .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .trade-assets-container .asset-sell { + background-color: var(--trading_selling-related-elements) !important; } .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .transaction-container, .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .release-amount-container, .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .asset-price-container, @@ -11925,6 +11952,8 @@ table th { .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-cancel-container .appeal-link:hover, .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-cancel-container .cancel-link:hover { cursor: pointer; } + .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-cancel-container .disable-link { + cursor: not-allowed !important; } .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-cancel-container .appeal-confirm-button-container-active { display: flex; align-items: center; @@ -11932,7 +11961,6 @@ table th { pointer-events: all; opacity: 1; } .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-cancel-container .appeal-confirm-button-container { - pointer-events: none; opacity: 0.5; } .p2p-summary-container .p2p-order-wrapper .user-chat-container .message-time { font-size: 10px; } @@ -12510,6 +12538,30 @@ table th { .feedback-submit-popup-wrapper .ReactModal__Content .submit-transaction-button-container .cancel-btn:active { color: var(--calculated_base_top-bar-navigation_text); } +.confirm-popup-wrapper .feedback-submit-popup-container { + align-items: center; } + +.confirm-popup-wrapper .submit-transaction-button-container .inactive-btn { + background-color: var(--labels_inactive-button) !important; } + +.release-amount-popup-wrapper .ReactModal__Content { + width: 30%; } + .release-amount-popup-wrapper .ReactModal__Content .release-amount-details-container .user-receive-amount-detail { + font-size: 14px; + display: flex; + align-items: flex-start; } + .release-amount-popup-wrapper .ReactModal__Content .release-amount-details-container .order-complete-title { + font-size: 22px; } + .release-amount-popup-wrapper .ReactModal__Content .release-amount-details-container .check-icon svg { + height: 2rem; + width: 2rem; } + .release-amount-popup-wrapper .ReactModal__Content .release-amount-details-container .check-icon svg path:nth-child(1) { + fill: transparent; } + .release-amount-popup-wrapper .ReactModal__Content .release-amount-details-container .check-icon svg path:nth-child(2) { + fill: var(--specials_checks-okay-done); } + .release-amount-popup-wrapper .ReactModal__Content .release-amount-details-container .check-icon svg path:nth-child(3) { + fill: #FFFFFF; } + .cancel-popup-wrapper .ReactModal__Content, .confirm-popup-wrapper .ReactModal__Content, .confirmation-remove-deal-popup-wrapper .ReactModal__Content { @@ -12518,6 +12570,44 @@ table th { .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .submit-feedback-title, .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .submit-feedback-title { font-size: 18px !important; } + .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon, + .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon, + .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon { + background-color: #FFFFFF; + display: flex; + align-items: center; + justify-content: center; + border-radius: 25px; } + .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon svg, + .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon svg, + .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon svg { + width: 6rem; + height: 6rem; } + .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon svg path, + .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon svg path, + .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon svg path { + fill: var(--specials_pending-waiting-caution); } + .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description, + .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description, + .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + gap: 5px; } + .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text, + .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text, + .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text { + margin-top: 5%; + display: flex; } + .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text .ant-checkbox-inner, + .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text .ant-checkbox-inner, + .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text .ant-checkbox-inner { + background-color: var(--base_wallet-sidebar-and-popup); } + .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text .ant-checkbox-checked .ant-checkbox-inner::after, + .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text .ant-checkbox-checked .ant-checkbox-inner::after, + .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .confirm-payment-description .payment-declaration-text .ant-checkbox-checked .ant-checkbox-inner::after { + border-color: var(--labels_important-active-labels-text-graphics); } .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .cancel-warning-text, .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .cancel-warning-text, .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .cancel-warning-text { @@ -12534,11 +12624,6 @@ table th { .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .cancel-warning-text .edit-wrapper__container { font-size: 12px; color: var(--labels_secondary-inactive-label-text-graphics); } - .cancel-popup-wrapper .ReactModal__Content .user-receive-amount-detail, - .confirm-popup-wrapper .ReactModal__Content .user-receive-amount-detail, - .confirmation-remove-deal-popup-wrapper .ReactModal__Content .user-receive-amount-detail { - margin-top: 3%; - font-size: 14px; } .cancel-popup-wrapper .ReactModal__Content .submit-transaction-button-container, .confirm-popup-wrapper .ReactModal__Content .submit-transaction-button-container, .confirmation-remove-deal-popup-wrapper .ReactModal__Content .submit-transaction-button-container { @@ -13152,6 +13237,54 @@ table th { .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper { overflow-x: scroll; text-wrap: nowrap; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper { + display: flex; + flex-direction: column; + gap: 15px; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .active-green { + color: var(--specials_checks-okay-done); } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .active-orange { + color: var(--specials_pending-waiting-caution); } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .active-yellow { + color: var(--specials_my-username-in-chat); } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .inactive-text { + color: var(--labels_secondary-inactive-label-text-graphics); } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details { + background-color: var(--base_wallet-sidebar-and-popup) !important; + border: none; + font-size: 24px; + border-bottom: 5px solid var(--base_background); } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details-inactive { + opacity: 0.5; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details { + display: flex; + flex-direction: column; + gap: 10px; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details .p2p-sell-order-button, + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details .p2p-buy-order-button { + background-color: var(--trading_selling-related-elements); + padding: 1% 2%; + font-size: 24px; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details .p2p-buy-order-button { + background-color: var(--specials_checks-okay-done) !important; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details .transaction-user-name { + font-size: 26px; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details .transaction-fiat-amount-wrapper { + display: flex; + gap: 2%; + align-items: center; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details .transaction-fiat-amount-wrapper .edit-wrapper__container { + color: var(--labels_important-active-labels-text-graphics); } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details .transaction-status { + display: flex; + justify-content: space-between; + gap: 4%; + font-weight: normal; } + .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-orders-details-card-wrapper .p2p-orders-card-details .p2p-orders-details .transaction-status .transaction-status-detail { + display: flex; + gap: 4%; + font-weight: bold; + text-transform: capitalize; } .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-order-table thead tr { font-size: 24px; } .layout-mobile .p2p-summary-container .ant-tabs-mobile .p2p-order-tab-container .p2p-order-table-wrapper .p2p-order-table thead th div { @@ -13230,7 +13363,7 @@ table th { .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .asset-name .edit-wrapper__container, .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .confirm-notify-button-container .order-title .edit-wrapper__container, .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .confirm-notify-button-container .asset-name .edit-wrapper__container { - font-size: 18px; } + font-size: 24px; } .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .trade-assets-container .asset-name, .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .release-amount-container .asset-name, .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .asset-price-container .asset-name, @@ -13294,6 +13427,8 @@ table th { font-size: 14px; } .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .user-chat-container .chat-field .chat-area { height: 65%; } + .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .user-chat-container .chat-field .chat-area-wrapper { + height: 60% !important; } .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .user-chat-container .chat-field .message-input-field .ant-input { font-size: 24px; padding: 1%; } @@ -13339,11 +13474,25 @@ table th { flex-direction: column; gap: 10px; padding: 5% 0; } + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .active-payment-field { + border-color: var(--specials_buttons-links-and-highlights) !important; } + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .active-focus { + border: 2px solid #5d63ff !important; } + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .active-focus .amount-spent-field, + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .active-focus .amount-receive-field { + background-color: var(--base_background) !important; + border: none; + box-shadow: inset 1px 1px 3px #00000029; + border-radius: 5px; + border-bottom: 1px solid var(--labels_important-active-labels-text-graphics) !important; } + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-spent:hover, + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-receive:hover { + border: 2px solid var(--labels_important-active-labels-text-graphics); } .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-spent, .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-receive { - border: 1px solid var(--calculated_secondary-border); + border: 2px solid var(--calculated_secondary-border); border-radius: 10px; - padding: 8% 6%; + padding: 6%; display: flex; flex-direction: column; gap: 10px; @@ -13371,6 +13520,7 @@ table th { margin-top: 3%; display: flex; width: 100%; + gap: 5%; justify-content: space-between; align-items: center; } .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-spent .amount-spent-field-container .ant-input-number-input-wrap, @@ -13407,12 +13557,11 @@ table th { .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-receive .amount-spent-field-container .amount-receive-field, .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-receive .amount-receive-field-container .amount-spent-field, .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-receive .amount-receive-field-container .amount-receive-field { - background-color: var(--base_background) !important; + background-color: transparent; border: none; - box-shadow: inset 1px 1px 3px #00000029; + box-shadow: none; border-radius: 5px; - color: var(--labels_important-active-labels-text-graphics) !important; - border-bottom: 1px solid var(--labels_important-active-labels-text-graphics); } + color: var(--labels_important-active-labels-text-graphics) !important; } .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-spent .amount-spent-field-container .amount-spent-field .ant-input-number-input, .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-spent .amount-spent-field-container .amount-receive-field .ant-input-number-input, .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-spent .amount-receive-field-container .amount-spent-field .ant-input-number-input, @@ -13447,12 +13596,23 @@ table th { background-color: var(--base_secondary-navigation-bar) !important; border-radius: 5px; border-bottom: 1px solid var(--labels_important-active-labels-text-graphics); } + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-spent .amount-spent-field-container .amount-receive-field:focus, + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-spent .amount-receive-field-container .amount-receive-field:focus, + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-receive .amount-spent-field-container .amount-receive-field:focus, + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .p2p-amount-receive .amount-receive-field-container .amount-receive-field:focus { + background-color: var(--base_background) !important; + border: none; + box-shadow: inset 1px 1px 3px #00000029; + border-radius: 5px; + border-bottom: 1px solid var(--labels_important-active-labels-text-graphics) !important; } .trading-popup-wrapper .trading-popup-container .trading-payment-detail .payment-method-error-field .ant-select-selector { border-color: var(--specials_notifications-alerts-warnings) !important; } .trading-popup-wrapper .trading-popup-container .trading-payment-detail .payment-method-field { display: flex; justify-content: space-between; width: 100%; } + .trading-popup-wrapper .trading-popup-container .trading-payment-detail .payment-method-field .inactive-btn { + background-color: var(--labels_inactive-button) !important; } .trading-popup-wrapper .trading-popup-container .trading-payment-detail .payment-method-field .payment-method-field .ant-select-selector { background-color: transparent; box-shadow: none; From 5e75972a428bbeb876ffa5a6be67443b706699f8 Mon Sep 17 00:00:00 2001 From: ram Date: Fri, 15 Nov 2024 00:20:08 +0530 Subject: [PATCH 08/11] Fixed some minor issue in the P2P Admin page --- web/src/containers/Admin/Trades/p2pActive.js | 36 ++++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/web/src/containers/Admin/Trades/p2pActive.js b/web/src/containers/Admin/Trades/p2pActive.js index de82c1be00..fb42a2034e 100644 --- a/web/src/containers/Admin/Trades/p2pActive.js +++ b/web/src/containers/Admin/Trades/p2pActive.js @@ -133,20 +133,6 @@ const P2PActive = ({ user }) => { // eslint-disable-next-line react-hooks/exhaustive-deps }, []); - const onHandleCancel = async (data) => { - try { - await updateTransaction({ - id: data?.id, - user_status: 'cancelled', - }); - fetchData(); - notificationStatus('cancelled'); - setSelectedTransaction(data); - } catch (error) { - console.error(error); - } - }; - const notificationStatus = (status, title = '') => { webSocket.send( JSON.stringify({ @@ -155,13 +141,13 @@ const P2PActive = ({ user }) => { { action: 'getStatus', data: { - id: selectedTransaction?.id, + id: userData?.id, status, title, receiver_id: - user?.id === selectedTransaction?.merchant_id - ? selectedTransaction?.user_id - : selectedTransaction?.merchant_id, + user?.id === userData?.merchant_id + ? userData?.user_id + : userData?.merchant_id, }, }, ], @@ -169,6 +155,20 @@ const P2PActive = ({ user }) => { ); }; + const onHandleCancel = async (data) => { + try { + await updateTransaction({ + id: data?.id, + user_status: 'cancelled', + }); + fetchData(); + notificationStatus('cancelled'); + setSelectedTransaction(data); + } catch (error) { + console.error(error); + } + }; + const filteredOrders = getOrders?.data?.filter( (data) => data?.transaction_status === 'active' ); From 7cc8fcd1d5bdd568c98da2d717065ba1e322dac8 Mon Sep 17 00:00:00 2001 From: Ali Beikverdi Date: Fri, 15 Nov 2024 16:01:59 +0900 Subject: [PATCH 09/11] version update --- server/api/swagger/swagger.js | 2 +- server/package.json | 2 +- version | 2 +- web/package.json | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/server/api/swagger/swagger.js b/server/api/swagger/swagger.js index 474d96dd68..7aa39ffc94 100644 --- a/server/api/swagger/swagger.js +++ b/server/api/swagger/swagger.js @@ -4,7 +4,7 @@ const definition = { swagger: '2.0', info: { title: 'HollaEx Kit', - version: '2.13.0' + version: '2.13.1' }, host: 'api.hollaex.com', basePath: '/v2', diff --git a/server/package.json b/server/package.json index 7d772248cc..c5280c0e23 100644 --- a/server/package.json +++ b/server/package.json @@ -1,5 +1,5 @@ { - "version": "2.13.0", + "version": "2.13.1", "private": false, "description": "HollaEx Kit", "keywords": [ diff --git a/version b/version index fb2c0766b7..94f15e9cc3 100644 --- a/version +++ b/version @@ -1 +1 @@ -2.13.0 +2.13.1 diff --git a/web/package.json b/web/package.json index a70e5ce5fd..e8d2546003 100644 --- a/web/package.json +++ b/web/package.json @@ -1,6 +1,6 @@ { "name": "hollaex-kit", - "version": "2.13.0", + "version": "2.13.1", "private": true, "dependencies": { "@ant-design/compatible": "1.0.5", From f9f97104ab77abf90a5b16a9180dac3182376ed3 Mon Sep 17 00:00:00 2001 From: ram Date: Fri, 15 Nov 2024 20:05:29 +0530 Subject: [PATCH 10/11] Changes for the P2P refinements --- web/src/config/lang/en.json | 4 +- web/src/containers/Admin/Trades/index.css | 23 ++++ web/src/containers/Admin/Trades/p2pActive.js | 110 +++++++++++++++++- web/src/containers/App/Socket.js | 50 ++++---- web/src/containers/P2P/P2POrder/P2POrder.js | 16 +-- .../P2P/P2POrder/P2POrderDetails.js | 14 ++- web/src/containers/P2P/P2POrders.js | 18 ++- web/src/containers/P2P/Utilis.js | 83 ++++++++++++- web/src/containers/P2P/_P2P.scss | 38 ++++++ web/src/index.css | 26 ++++- 10 files changed, 339 insertions(+), 43 deletions(-) diff --git a/web/src/config/lang/en.json b/web/src/config/lang/en.json index e48f04990d..d1b992edc3 100644 --- a/web/src/config/lang/en.json +++ b/web/src/config/lang/en.json @@ -2286,7 +2286,9 @@ "CHECK_CONFIRM_PAYMENT_DESC_2": "After confirming below the crypto ({0} {1}) will be released.", "CHECK_CONFIRM_DECLARATION": "I confirm that I have received the correct payment", "P2P_ORDER_COMPLETE": "P2P Order Complete", - "EXIST_PAYMENT_METHOD_DESC": "You’ve already added a payment method for {0}" + "EXIST_PAYMENT_METHOD_DESC": "You’ve already added a payment method for {0}", + "ADMIN_ORDER_CANCELLATION_MESSAGE": "An exchange operator has cancelled this order. The transaction is closed.", + "TIME_LIMIT_REACHED": "0:00 (Please contact your counter-party)" }, "VOLUME": { "VOLUME": "VOLUME", diff --git a/web/src/containers/Admin/Trades/index.css b/web/src/containers/Admin/Trades/index.css index 2b541ee076..1ff30ecbba 100644 --- a/web/src/containers/Admin/Trades/index.css +++ b/web/src/containers/Admin/Trades/index.css @@ -819,3 +819,26 @@ .p2p-admin-confirm-warning-popup-wrapper .ant-modal-close-x { color: white; } + +.p2p-admin-order-details-popup-wrapper + .p2p-admin-order-details-container + .title { + font-size: 22px; + margin-bottom: 3%; +} + +.p2p-admin-order-details-popup-wrapper + .p2p-admin-order-details-container + .order-details { + margin-top: 2%; + display: flex; + align-items: center; +} + +.p2p-admin-order-details-popup-wrapper + .p2p-admin-order-details-container + .order-details + .asset-icon { + position: relative; + top: 3px; +} diff --git a/web/src/containers/Admin/Trades/p2pActive.js b/web/src/containers/Admin/Trades/p2pActive.js index fb42a2034e..a8815b7712 100644 --- a/web/src/containers/Admin/Trades/p2pActive.js +++ b/web/src/containers/Admin/Trades/p2pActive.js @@ -9,8 +9,9 @@ import { } from 'containers/P2P/actions/p2pActions'; import { getToken } from 'utils/token'; import { WS_URL } from 'config/constants'; +import { Coin } from 'components'; -const dataSource = (setIsConfirmWarning, setUserData) => { +const dataSource = (setIsConfirmWarning, setUserData, setIsOrderDetails) => { return [ { title: 'Order Id', dataIndex: 'id', key: 'id' }, { @@ -51,15 +52,32 @@ const dataSource = (setIsConfirmWarning, setUserData) => { ); }, }, + { + title: 'View More', + render: (data) => { + return ( + + ); + }, + }, ]; }; -const P2PActive = ({ user }) => { +const P2PActive = ({ user, coins }) => { const [getOrders, setGetOrders] = useState(); const [selectedTransaction, setSelectedTransaction] = useState(); const [webSocket, setWebSocket] = useState(); const [isConfirmWarning, setIsConfirmWarning] = useState(false); const [userData, setUserData] = useState(); + const [isOrderDetails, setIsOrderDetails] = useState(false); const fetchData = async () => { try { @@ -162,7 +180,7 @@ const P2PActive = ({ user }) => { user_status: 'cancelled', }); fetchData(); - notificationStatus('cancelled'); + notificationStatus('cancelled', 'admin cancel'); setSelectedTransaction(data); } catch (error) { console.error(error); @@ -210,8 +228,91 @@ const P2PActive = ({ user }) => {
+ } + visible={isOrderDetails} + footer={null} + onCancel={() => { + setIsOrderDetails(false); + }} + width={450} + className="p2p-admin-order-details-popup-wrapper p2p-admin-confirm-warning-popup-wrapper" + > +
+
Order Details
+
+ + Transaction Id : + + {userData?.transaction_id} +
+
+ Fiat Amount: + {userData?.amount_fiat} + + {userData?.deal?.spending_asset?.toUpperCase()} + + + + +
+ +
+ Price: + {userData?.price} + + {userData?.deal?.spending_asset?.toUpperCase()} + + + + + (per coin) + + {userData?.deal?.buying_asset?.toUpperCase()} + + + + +
+
+ Crypto Amount: + {userData?.amount_digital_currency} + + {userData?.deal?.buying_asset?.toUpperCase()} + + + + +
+
+ + Payment Method: + + + {userData?.payment_method_used?.system_name} + +
+
+
@@ -221,6 +322,7 @@ const P2PActive = ({ user }) => { const mapStateToProps = (state) => ({ user: state.user, + coins: state.app.coins, }); export default connect(mapStateToProps)(P2PActive); diff --git a/web/src/containers/App/Socket.js b/web/src/containers/App/Socket.js index 7c5c473dfa..095c848059 100644 --- a/web/src/containers/App/Socket.js +++ b/web/src/containers/App/Socket.js @@ -461,6 +461,10 @@ class Container extends Component { {data.action === 'getStatus' && data?.data?.status === 'appeal' ? STRINGS['P2P.APPEAL_STATUS_MESSAGE'] + : data?.action === 'getStatus' && + data?.data?.status === 'cancelled' && + data?.data?.title === 'admin cancel' + ? STRINGS['P2P.ADMIN_ORDER_CANCELLATION_MESSAGE'] : data?.action === 'getStatus' && data?.data?.status === 'cancelled' ? STRINGS['P2P.CANCEL_STATUS_MESSAGE'] @@ -541,17 +545,18 @@ class Container extends Component { notification.close(newLastNotification?.key); notification.open({ ...newLastNotification, - icon: - newLastNotificationMessage === - (STRINGS['P2P.CANCEL_STATUS_MESSAGE'] || - STRINGS['P2P.APPEAL_STATUS_MESSAGE']) ? ( - - ) : newLastNotificationMessage === - STRINGS['P2P.NEW_MESSAGE'] ? ( - - ) : ( - - ), + icon: [ + STRINGS['P2P.CANCEL_STATUS_MESSAGE'], + STRINGS['P2P.ADMIN_ORDER_CANCELLATION_MESSAGE'], + STRINGS['P2P.APPEAL_STATUS_MESSAGE'], + ]?.includes(newLastNotificationMessage) ? ( + + ) : newLastNotificationMessage === + STRINGS['P2P.NEW_MESSAGE'] ? ( + + ) : ( + + ), className: isMobile ? 'p2p-chat-notification-wrapper p2p-chat-notification-wrapper-mobile' : 'p2p-chat-notification-wrapper', @@ -583,17 +588,18 @@ class Container extends Component { notification.close(previousNotification?.key); notification.open({ ...previousNotification, - icon: - previousNotificationMessage === - (STRINGS['P2P.CANCEL_STATUS_MESSAGE'] || - STRINGS['P2P.APPEAL_STATUS_MESSAGE']) ? ( - - ) : previousNotificationMessage === - STRINGS['P2P.NEW_MESSAGE'] ? ( - - ) : ( - - ), + icon: [ + STRINGS['P2P.CANCEL_STATUS_MESSAGE'], + STRINGS['P2P.ADMIN_ORDER_CANCELLATION_MESSAGE'], + STRINGS['P2P.APPEAL_STATUS_MESSAGE'], + ]?.includes(previousNotificationMessage) ? ( + + ) : previousNotificationMessage === + STRINGS['P2P.NEW_MESSAGE'] ? ( + + ) : ( + + ), className: isMobile ? 'p2p-chat-notification-wrapper p2p-chat-notification-wrapper-mobile p2p-chat-notification' : 'p2p-chat-notification-wrapper p2p-chat-notification', diff --git a/web/src/containers/P2P/P2POrder/P2POrder.js b/web/src/containers/P2P/P2POrder/P2POrder.js index 40c445032a..de6ce58334 100644 --- a/web/src/containers/P2P/P2POrder/P2POrder.js +++ b/web/src/containers/P2P/P2POrder/P2POrder.js @@ -26,7 +26,7 @@ import { import { formatToCurrency } from 'utils/currency'; import { getToken } from 'utils/token'; import { WS_URL } from 'config/constants'; -import { renderFeedback } from '../Utilis'; +import { renderFeedback, Timer } from '../Utilis'; import classnames from 'classnames'; import BigNumber from 'bignumber.js'; import '../_P2P.scss'; @@ -1168,12 +1168,14 @@ const P2POrder = ({
-
- - {STRINGS['P2P.EXPECTED_TIME']} - -
- + {selectedOrder?.user_status === 'pending' && ( +
+ + {STRINGS['P2P.EXPECTED_TIME']} + + +
+ )} {user.id === selectedOrder?.user_id && ( <> {selectedOrder.user_status === 'pending' && ( diff --git a/web/src/containers/P2P/P2POrder/P2POrderDetails.js b/web/src/containers/P2P/P2POrder/P2POrderDetails.js index b55ba8b250..ddf3976a67 100644 --- a/web/src/containers/P2P/P2POrder/P2POrderDetails.js +++ b/web/src/containers/P2P/P2POrder/P2POrderDetails.js @@ -9,6 +9,7 @@ import { CheckCircleTwoTone } from '@ant-design/icons'; import STRINGS from 'config/localizedStrings'; import { Coin, EditWrapper, Image } from 'components'; import { setIsChat } from 'actions/appActions'; +import { Timer } from '../Utilis'; const P2POrderDetails = ({ user, @@ -321,11 +322,14 @@ const P2POrderDetails = ({
- {/*
- - {STRINGS['P2P.EXPECTED_TIME']} - -
*/} + {selectedOrder?.user_status === 'pending' && ( +
+ + {STRINGS['P2P.EXPECTED_TIME']} + + +
+ )} {user?.id === selectedOrder?.user_id && ( <> diff --git a/web/src/containers/P2P/P2POrders.js b/web/src/containers/P2P/P2POrders.js index bf3e6d766b..53c0650346 100644 --- a/web/src/containers/P2P/P2POrders.js +++ b/web/src/containers/P2P/P2POrders.js @@ -466,6 +466,22 @@ const P2POrders = ({
+
+ + + {STRINGS['P2P.PRICE']}: + + + + {formatAmount( + transaction?.deal?.buying_asset, + transaction?.price + )} + + + {transaction?.deal?.buying_asset?.toUpperCase()} + +
@@ -479,7 +495,7 @@ const P2POrders = ({ transaction?.amount_digital_currency )} - + {transaction?.deal?.buying_asset?.toUpperCase()} { + const orderCreatedDate = new Date(order?.created_at)?.getTime(); + const [time, setTime] = useState({ min: 30, sec: 0 }); + const [startTime] = useState(orderCreatedDate); + const [timeLimitReached, setTimeLimitReached] = useState(false); + const frameIdRef = useRef(); + + const cancelTimer = () => { + if (frameIdRef.current) { + cancelAnimationFrame(frameIdRef.current); + frameIdRef.current = null; + } + }; + + useEffect(() => { + const update = () => { + const now = Date.now(); + const elapsed = Math.floor((now - startTime) / 1000); + const totalSeconds = 30 * 60 - elapsed; + + if (totalSeconds <= 0) { + setTime({ min: 0, sec: 0 }); + setTimeLimitReached(true); + cancelTimer(); + } else { + const min = Math.floor(totalSeconds / 60); + const sec = totalSeconds % 60; + setTime({ min, sec }); + setTimeLimitReached(false); + frameIdRef.current = requestAnimationFrame(update); + if ( + order?.user_status === 'confirmed' || + order?.transaction_status === 'expired' + ) { + setTime({ min: 0, sec: 0 }); + setTimeLimitReached(true); + cancelTimer(); + } + } + }; + + frameIdRef.current = requestAnimationFrame(update); + + return () => cancelTimer(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [startTime, order]); + + const totalSeconds = 30 * 60; + const elapsedSeconds = Math.floor((Date.now() - startTime) / 1000); + const percentage = (elapsedSeconds / totalSeconds) * 100; + + return ( +
+
+ {!timeLimitReached && ( +
+ )} +
+ {timeLimitReached ? ( +
+ + {STRINGS['P2P.TIME_LIMIT_REACHED']} + +
+ ) : ( +
+ {time?.min < 10 ? `0${time?.min}` : time?.min}: + {time?.sec < 10 ? `0${time?.sec}` : time?.sec} +
+ )} +
+
+
+ ); +}; + export default NoDealsData; diff --git a/web/src/containers/P2P/_P2P.scss b/web/src/containers/P2P/_P2P.scss index fa127c8fbb..ab42e97809 100644 --- a/web/src/containers/P2P/_P2P.scss +++ b/web/src/containers/P2P/_P2P.scss @@ -1792,6 +1792,37 @@ } .order-verification-container { + .order-timer-wrapper { + .timer-container { + display: flex; + + .timer-details { + padding: 2% 0; + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + border-radius: 25px; + } + + .timer-circle { + width: 20px; + height: 20px; + border-radius: 50%; + background: conic-gradient( + var(--labels_important-active-labels-text-graphics) 0%, + var(--base_background) 0% + ); + display: flex; + justify-content: center; + align-items: center; + position: relative; + border: 1px solid + var(--labels_important-active-labels-text-graphics); + } + } + } + .order-confirmed-container { .order-complete-title, .go-to-deposit-link, @@ -3870,6 +3901,13 @@ } .order-verification-container { + .order-timer-wrapper { + .timer-circle { + width: 30px; + height: 30px; + } + } + .order-confirmed-container { .order-complete-title { .edit-wrapper__container { diff --git a/web/src/index.css b/web/src/index.css index f81ddea12f..d9d478e51c 100644 --- a/web/src/index.css +++ b/web/src/index.css @@ -11928,6 +11928,25 @@ table th { border-left: 5px solid var(--specials_checks-okay-done); } .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .amount-transfer-container .active-sell { border-left: 5px solid var(--trading_selling-related-elements); } + .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-timer-wrapper .timer-container { + display: flex; } + .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-timer-wrapper .timer-container .timer-details { + padding: 2% 0; + display: flex; + justify-content: center; + align-items: center; + gap: 10px; + border-radius: 25px; } + .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-timer-wrapper .timer-container .timer-circle { + width: 20px; + height: 20px; + border-radius: 50%; + background: conic-gradient(var(--labels_important-active-labels-text-graphics) 0%, var(--base_background) 0%); + display: flex; + justify-content: center; + align-items: center; + position: relative; + border: 1px solid var(--labels_important-active-labels-text-graphics); } .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-confirmed-container .order-complete-title, .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-confirmed-container .go-to-deposit-link, .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-confirmed-container .go-to-withdraw-link { @@ -12560,7 +12579,7 @@ table th { .release-amount-popup-wrapper .ReactModal__Content .release-amount-details-container .check-icon svg path:nth-child(2) { fill: var(--specials_checks-okay-done); } .release-amount-popup-wrapper .ReactModal__Content .release-amount-details-container .check-icon svg path:nth-child(3) { - fill: #FFFFFF; } + fill: #ffffff; } .cancel-popup-wrapper .ReactModal__Content, .confirm-popup-wrapper .ReactModal__Content, @@ -12573,7 +12592,7 @@ table th { .cancel-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon, .confirm-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon, .confirmation-remove-deal-popup-wrapper .ReactModal__Content .feedback-submit-popup-container .warning-icon { - background-color: #FFFFFF; + background-color: #ffffff; display: flex; align-items: center; justify-content: center; @@ -13398,6 +13417,9 @@ table th { .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .confirm-notify-button-container .chat-link-container .chat-link { color: var(--specials_buttons-links-and-highlights); font-size: 24px; } + .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-timer-wrapper .timer-circle { + width: 30px; + height: 30px; } .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-confirmed-container .order-complete-title .edit-wrapper__container { font-size: 20px; } .layout-mobile .p2p-summary-container .p2p-order-wrapper .p2p-order-container .p2p-order-details-container .order-verification-container .order-confirmed-container .go-to-deposit-link, From a02e9a1b4df13569f1259c61377eff5ca8696eb5 Mon Sep 17 00:00:00 2001 From: ram Date: Fri, 15 Nov 2024 20:39:09 +0530 Subject: [PATCH 11/11] Updated the pulgins in the mobile view more page --- .../containers/App/MobileBarMoreOptions.js | 43 ++++++++++++++----- 1 file changed, 33 insertions(+), 10 deletions(-) diff --git a/web/src/containers/App/MobileBarMoreOptions.js b/web/src/containers/App/MobileBarMoreOptions.js index 9a3f3e873a..622a840a52 100644 --- a/web/src/containers/App/MobileBarMoreOptions.js +++ b/web/src/containers/App/MobileBarMoreOptions.js @@ -38,6 +38,7 @@ const MobileBarMoreOptions = ({ pinnedAsset, getMarkets, quickTrade, + getRemoteRoutes, }) => { const [search, setSearch] = useState(''); const [isDialogOpen, setIsDialogOpen] = useState(false); @@ -274,10 +275,8 @@ const MobileBarMoreOptions = ({ STRINGS['MORE_OPTIONS_LABEL.OTHER_FUNCTIONS.SECURITY'], ], }, - { - icon_id: 'BUY_CRYPTO_OPTION', - iconText: 'MORE_OPTIONS_LABEL.ICONS.BUY_CRYPTO', - path: '/buy-crypto', + ...getRemoteRoutes?.map((route, index) => ({ + ...route, isDisplay: true, searchContent: [ STRINGS['MARKET_OPTIONS.CARD'], @@ -293,7 +292,7 @@ const MobileBarMoreOptions = ({ STRINGS['MORE_OPTIONS_LABEL.OTHER_FUNCTIONS.BUY_COIN'], STRINGS['MORE_OPTIONS_LABEL.OTHER_FUNCTIONS.BUY_TOKEN'], ], - }, + })), { icon_id: 'DEFI_STAKE_OPTION_ICON', iconText: 'MORE_OPTIONS_LABEL.ICONS.DEFI_STAKE', @@ -731,7 +730,9 @@ const MobileBarMoreOptions = ({ const filterOptions = (options) => { return options?.filter((option) => { - const iconTextMatch = (STRINGS[option?.iconText] || '') + const iconTextMatch = ( + STRINGS[option?.iconText ? option?.iconText : option?.string_id] || '' + ) ?.toLowerCase() .includes(search?.toLowerCase()); const searchContentMatch = option?.searchContent?.some((content) => @@ -753,7 +754,12 @@ const MobileBarMoreOptions = ({
onHandleRoute(data?.iconText, data?.path)} + onClick={() => + onHandleRoute( + data?.iconText ? data?.iconText : data?.string_id, + data?.path + ) + } > {fieldHasCoinIcon?.includes(data?.iconText) ? (
@@ -769,13 +775,29 @@ const MobileBarMoreOptions = ({ ) : ( )}
- - {STRINGS[data?.iconText]} + + { + STRINGS[ + data?.iconText ? data?.iconText : data?.string_id + ] + }
@@ -919,6 +941,7 @@ const mapStateToProps = (store) => ({ pinnedAsset: store.app.pinned_assets, getMarkets: MarketsSelector(store), quickTrade: store.app.quicktrade, + getRemoteRoutes: store.app.remoteRoutes, }); const mapDispatchToProps = (dispatch) => ({