From 32bc244898bdb1a00270115930ba53342f7e073e Mon Sep 17 00:00:00 2001 From: Farrah Mae Ochoa <82315152+farrah-deriv@users.noreply.github.com> Date: Mon, 18 Sep 2023 19:49:10 +0800 Subject: [PATCH] refactor: p2p structure, styles and components (#8696) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * refactor: refactor p2p styles * refactor: refactor styles * fix: classname typo * fix: fix broken style * refactor: update based on pr comments * fix: failed tests * fix: import error * refactor: rename datatest id * refactor: remove unused styles and refactor text components * refactor: restructure the p2p package * refactor: update translations imports * refactor: update modal-manager import * fix: pr review comments * fix: fix some broken styles * fix: review comments * chore: change in failed test file and remove change from unrelated file * fix: review comments * Henry/fix: navigate to accu trade type in reports page after purchasing a c… (#8684) * fix: navigate to accu trade type in reports page after purchasing a contract * fix: circle CI error * fix: codecov * fix: circle CI issue * refactor: refactor dpep-blocked components * fix: failed test * fix: review comments * refactor: test descriptions changes * refactor: import localize from p2p i18n instead of shared translations package * fix: review components * chore: refactored temporarily barred hint component * refactor: rearrange imports to follow guidelines * refactor: standardise react imports * chore: refactored p2p-empty component * chore: added default value for has_tabs * feat: unit test added for page return component * refactor: recommended-by component * fix: updated index file * chore: added test cases for star rating * chore: changed describe * refactor: add new test cases to increase coverage * refactor: add comment in empty arrow function * refactor: refactor trade-badge component * fix: review comments fixed * refactor: remove prop-types import * refactor: update react import * refactor: refactor form-submit-error-message, table-error * refactor: nickname form * refactor: review comments * fix: tests * chore: refactored user avatar component * refactor: refactor toggle-container component * chore: added suggestions * refactor: delete the type and use propswithchildren * chore: refactored FloatingRate component * refactor: refactor block-user-empty component * refactor: online status component refactoring * refactor: review comments * refactor: add margin-top * refactor: udpated test description * refactor: change test cases descriptions * refactor: review comment * refactor: refactored verification component * chore: refactored recommend user component * chore: removed fireEvent, used userEvent * refactor: updated tests * refactor: review comment fix * refactor: added type checking for modal manager in test case * translations: 📚 sync translations with crowdin (#8881) Co-authored-by: DerivFE <80095553+DerivFE@users.noreply.github.com> * thisyahlen/fix: change algo for realAccountSignup (#8656) * fix: change algo for realAccountSignup * fix: refactor * redeploy: vercel * translations: 📚 sync translations with crowdin (#8885) Co-authored-by: DerivFE <80095553+DerivFE@users.noreply.github.com> * translations: 📚 sync translations with crowdin (#8890) Co-authored-by: DerivFE <80095553+DerivFE@users.noreply.github.com> * likhith/fix: :bug: resolved required field error (#8886) * fix: :bug: resolved required field error * feat: fixed issue with Citizen field * refactor: removed unused code * refactor: updated test * fix: code smells * fix: tests * refactor: reduce code complexity to remove code smell * refactor: updated return * refactor: udpated test * refactor: delete text component and use default button text styles instead * fix: raised subtasks * fix: advertiser buy/sell row * fix: style fix in edit/add payment method form in my profile * fix: notification issue * fix: block banned user bug * fix: issue for popup not showing when rate updated before selecting form * fix: removed console * fix: added todo * fix: added undefined check * fix: subtasks raised * fix: daily limit notification * fix: tests failed * fix: notification popup issue not shown in responsive * fix: filter button spacing * fix: failing tests * fix: get server hits bump error when in advertiser page and block it from BO * fix: revert unwanted changes from master * fix: remove unnecessary changes * fix: remove unnecessary changes * fix: tests --------- Co-authored-by: Farhan Ahmad Nurzi Co-authored-by: henry-deriv <118344354+henry-deriv@users.noreply.github.com> Co-authored-by: ameerul hady Co-authored-by: nada-deriv Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: DerivFE <80095553+DerivFE@users.noreply.github.com> Co-authored-by: thisyahlen <104053934+thisyahlen-deriv@users.noreply.github.com> Co-authored-by: Likhith Kolayari <98398322+likhith-deriv@users.noreply.github.com> --- .../core/src/Stores/notification-store.js | 1 - packages/p2p/@deriv-stores.d.ts | 10 + packages/p2p/jest.config.js | 1 + packages/p2p/package.json | 1 + .../components/__tests__/app-content.spec.js | 36 +- packages/p2p/src/components/app-content.jsx | 24 +- .../currency-selector/currency-selector.scss | 67 -- .../dp2p-blocked-description.spec.tsx | 62 ++ .../__tests__/dp2p-blocked.spec.tsx | 10 + .../__tests__/dp2p-blocked-checklist.spec.tsx | 55 ++ .../dp2p-blocked-checklist.scss | 13 + .../dp2p-blocked-checklist.tsx} | 12 +- .../dp2p-blocked-checklist/index.ts | 4 + ...ption.jsx => dp2p-blocked-description.tsx} | 10 +- .../components/dp2p-blocked/dp2p-blocked.scss | 14 - .../{dp2p-blocked.jsx => dp2p-blocked.tsx} | 12 +- .../dp2p-blocked/{index.js => index.ts} | 2 +- .../__test__/floating-rate.spec.js | 34 - .../__test__/floating-rate.spec.tsx | 72 ++ .../floating-rate/floating-rate.scss | 6 + .../{floating-rate.jsx => floating-rate.tsx} | 96 +-- .../floating-rate/{index.js => index.ts} | 2 +- packages/p2p/src/components/form/error.jsx | 16 - packages/p2p/src/components/form/form.scss | 4 - .../components/i18next/{index.js => index.ts} | 8 +- .../misc/__test__/animation-wrapper.spec.js | 39 - .../src/components/misc/animation-wrapper.jsx | 32 - .../components/misc/animation-wrapper.scss | 22 - .../src/components/misc/toggle-container.jsx | 11 - .../ad-error-tooltip-modal.jsx | 2 +- .../ad-error-tooltip-modal.scss | 17 + .../modals/ad-error-tooltip-modal/index.js | 1 + .../ad-visibility-error-modal.jsx | 6 +- .../ad-visibility-error-modal.scss | 17 + .../modals/ad-visibility-error-modal/index.js | 1 + .../block-user-modal/block-user-modal.jsx | 2 +- .../modals/buy-sell-modal/buy-sell-modal.jsx | 38 +- .../modals/buy-sell-modal/buy-sell-modal.scss | 110 ++- .../cancel-add-payment-method-modal.jsx | 2 +- .../cancel-edit-payment-method-modal.jsx | 2 +- .../create-ad-add-payment-method-modal.jsx | 20 +- .../create-ad-add-payment-method-modal.scss | 75 +- .../create-ad-error-modal.jsx | 6 +- .../create-ad-error-modal.scss | 17 + .../modals/create-ad-error-modal/index.js | 1 + .../currency-selector-modal.jsx | 2 +- .../modals/currency-selector-modal/index.js | 1 - .../email-link-blocked-modal.jsx | 4 +- .../email-link-blocked-modal.scss | 2 +- .../email-link-expired-modal.jsx | 6 +- .../email-link-expired-modal.scss | 6 +- .../email-link-verified-modal.jsx | 6 +- .../email-link-verified-modal.scss | 4 +- .../email-verification-modal.jsx | 24 +- .../email-verification-modal.scss | 8 +- .../filter-modal/filter-modal-header.jsx | 2 +- .../filter-modal/filter-modal-no-results.jsx | 4 +- .../invalid-verification-link-modal.jsx | 6 +- .../invalid-verification-link-modal.scss | 4 +- .../my-ads-delete-error-modal.jsx | 2 +- .../my-ads-delete-modal.jsx | 2 +- .../modals/nickname-modal/index.ts | 3 + .../modals/nickname-modal/nickname-modal.tsx | 26 + .../order-details-cancel-modal.jsx | 10 +- .../order-details-cancel-modal.scss | 4 +- .../order-details-confirm-modal.jsx | 2 +- .../quick-add-modal/quick-add-modal.jsx | 34 +- .../quick-add-modal/quick-add-modal.scss | 52 +- .../rate-change-modal/rate-change-modal.jsx | 6 +- .../rate-change-modal/rate-change-modal.scss | 2 +- .../modals/rating-modal/rating-modal.jsx | 10 +- .../modals/rating-modal/rating-modal.scss | 6 +- .../modals/recommended-modal/index.js | 1 - .../recommended-modal/recommended-modal.jsx | 2 +- .../recommended-modal/recommended-modal.scss | 4 - .../p2p/src/components/my-ads/my-ads.scss | 775 ------------------ .../__test__/nickname-form-wrapper.spec.js | 47 -- .../__test__/nickname-form.spec.js | 76 -- .../__tests__/nickname-form.spec.tsx | 183 +++++ .../nickname-form/{index.js => index.ts} | 2 +- .../nickname-form/nickname-form-wrapper.jsx | 26 - .../nickname-form/nickname-form.jsx | 124 --- .../nickname-form/nickname-form.scss | 95 +-- .../nickname-form/nickname-form.tsx | 107 +++ .../__tests__/online-status-avatar.spec.tsx | 17 + .../__tests__/online-status-icon.spec.tsx | 19 + .../__tests__/online-status-label.spec.tsx | 121 ++- .../online-status/{index.js => index.ts} | 0 ...us-avatar.jsx => online-status-avatar.tsx} | 22 +- ...status-icon.jsx => online-status-icon.tsx} | 14 +- .../online-status/online-status-label.jsx | 22 - .../online-status/online-status-label.tsx | 92 +++ .../online-status/online-status.scss | 5 +- .../__test__/order-details-footer.spec.js | 31 +- .../__test__/order-details.spec.js | 111 ++- .../__tests__/order-details-wrapper.spec.js | 4 +- ...der-details-complain-modal-radio-group.jsx | 4 +- ...er-details-complain-modal-radio-group.scss | 37 + .../order-details-complain-modal.jsx | 6 +- .../order-details-complain-modal.scss | 38 - .../order-details/order-details-footer.jsx | 17 +- .../order-details/order-details-footer.scss | 19 + .../order-details/order-details-timer.jsx | 12 +- .../order-details/order-details-timer.scss | 11 + .../order-details/order-details-wrapper.jsx | 4 +- .../order-details/order-details.jsx | 29 +- .../order-details/order-details.scss | 83 +- .../order-details/order-info-block.jsx | 7 +- .../order-details/order-info-block.scss | 10 + .../payment-method-accordion-header.jsx | 9 +- .../payment-method-accordion-header.scss | 34 + .../p2p/src/components/orders/orders.scss | 269 ------ .../__test__/p2p-empty.spec.tsx} | 8 +- .../p2p/src/components/p2p-empty/index.ts | 4 + .../empty.scss => p2p-empty/p2p-empty.scss} | 8 +- .../empty.jsx => p2p-empty/p2p-empty.tsx} | 26 +- .../page-return/__test__/page-return.spec.tsx | 11 + .../p2p/src/components/page-return/index.ts | 4 + .../components/page-return/page-return.scss | 6 +- .../{page-return.jsx => page-return.tsx} | 20 +- .../rating-cell-renderer.jsx | 4 +- .../rating-cell-renderer.scss | 2 +- .../__test__/recommend-user.spec.tsx | 91 ++ .../recommend-user/{index.js => index.ts} | 2 +- .../recommend-user/recommend-user.scss | 6 +- ...{recommend-user.jsx => recommend-user.tsx} | 35 +- .../__tests__/recommended-by.spec.tsx | 50 ++ .../recommended-by/{index.js => index.ts} | 2 +- .../recommended-by/recommended-by.scss | 4 +- ...{recommended-by.jsx => recommended-by.tsx} | 25 +- .../__tests__/section-error.spec.tsx | 10 + .../p2p/src/components/section-error/index.ts | 4 + .../section-error/section-error.scss | 22 + .../section-error/section-error.tsx | 16 + .../star-rating/__test__/star-rating.spec.tsx | 44 + .../p2p/src/components/star-rating/index.js | 3 - .../p2p/src/components/star-rating/index.ts | 3 + .../{star-rating.jsx => star-rating.tsx} | 62 +- .../table/__test__/table-error.spec.js | 11 - .../p2p/src/components/table/table-error.jsx | 14 - packages/p2p/src/components/table/table.scss | 12 - .../__test__/temporarily-barred-hint.spec.tsx | 31 + .../{index.js => index.ts} | 2 +- .../temporarily-barred-hint.scss | 17 + ...d-hint.jsx => temporarily-barred-hint.tsx} | 4 +- .../__tests__/toggle-container.spec.tsx} | 3 +- .../src/components/toggle-container/index.ts | 4 + .../toggle-container.scss | 4 +- .../toggle-container/toggle-container.tsx | 9 + .../__tests__/trade-badge.spec.tsx | 37 + .../trade-badge/{index.js => index.ts} | 2 +- .../{trade-badge.jsx => trade-badge.tsx} | 43 +- ...er-avatar.spec.js => user-avatar.spec.tsx} | 5 +- .../user/user-avatar/{index.js => index.ts} | 2 +- .../user/user-avatar/user-avatar.scss | 2 +- .../{user-avatar.jsx => user-avatar.tsx} | 22 +- .../__tests__/verification.spec.js | 75 -- .../__tests__/verification.spec.tsx | 163 ++++ .../p2p/src/components/verification/index.ts | 4 + .../components/verification/verification.scss | 20 +- .../{verification.jsx => verification.tsx} | 78 +- packages/p2p/src/constants/modals.js | 3 + packages/p2p/src/constants/routes-config.js | 10 +- packages/p2p/src/index.js | 4 +- .../__tests__/advertiser-page.spec.jsx | 0 .../advertiser-page-adverts.jsx | 18 +- .../advertiser-page-adverts.scss | 82 ++ .../advertiser-page-dropdown-menu.jsx | 10 +- .../advertiser-page-dropdown-menu.scss | 51 ++ .../advertiser-page/advertiser-page-row.jsx | 35 +- .../advertiser-page/advertiser-page-row.scss | 2 + .../advertiser-page/advertiser-page-stats.jsx | 100 +-- .../advertiser-page-stats.scss | 75 ++ .../advertiser-page/advertiser-page.jsx | 44 +- .../advertiser-page/advertiser-page.scss | 208 +---- .../block-user/block-user-count.jsx | 2 +- .../block-user/block-user-count.scss | 0 .../block-user-overlay/block-user-overlay.jsx | 2 +- .../block-user-overlay.scss | 2 +- .../block-user/block-user-overlay/index.js | 0 .../advertiser-page/index.js | 0 .../p2p/src/{components => pages}/app.jsx | 14 +- .../p2p/src/{components => pages}/app.scss | 55 +- .../buy-sell-form-receive-amount.spec.js | 2 +- .../buy-sell/__tests__/buy-sell.spec.jsx | 19 +- .../buy-sell/__tests__/sort-dropdown.spec.js | 0 .../buy-sell/buy-sell-form-receive-amount.jsx | 7 +- .../buy-sell-form-receive-amount.scss | 7 + .../buy-sell/buy-sell-form.jsx | 71 +- .../p2p/src/pages/buy-sell/buy-sell-form.scss | 245 ++++++ .../buy-sell/buy-sell-header.jsx | 28 +- .../buy-sell/buy-sell-header.scss | 17 +- .../buy-sell/buy-sell-row.jsx | 30 +- .../buy-sell/buy-sell-row.scss | 1 - .../buy-sell/buy-sell-table.jsx | 21 +- .../src/pages/buy-sell/buy-sell-table.scss | 46 ++ .../buy-sell/buy-sell.jsx | 8 +- .../buy-sell/buy-sell.scss | 38 - .../buy-sell/currency-dropdown.jsx | 2 +- .../buy-sell/currency-dropdown.scss | 0 .../currency-selector/currency-selector.jsx | 2 +- .../currency-selector}/currency-selector.scss | 2 +- .../buy-sell/currency-selector/index.js | 0 .../{components => pages}/buy-sell/index.js | 1 + .../buy-sell/no-ads/__tests__/no-ads.spec.jsx | 0 .../buy-sell/no-ads/index.js | 1 + .../buy-sell/no-ads/no-ads.jsx | 4 +- .../buy-sell/no-ads/no-ads.scss | 0 .../buy-sell/sort-dropdown.jsx | 2 +- .../buy-sell/sort-dropdown.scss | 0 .../my-ads/__tests__/ad-status.spec.js | 0 .../my-ads/__tests__/my-ads-table.spec.jsx | 0 .../my-ads/ad-status.jsx | 0 .../my-ads/ad-status.scss | 0 .../{components => pages}/my-ads/ad-type.jsx | 11 +- .../{components => pages}/my-ads/ad-type.scss | 0 .../my-ads/buy-ad-payment-methods-list.jsx | 6 +- .../my-ads/buy-ad-payment-methods-list.scss | 0 .../my-ads/create-ad-form-payment-methods.jsx | 6 +- .../my-ads/create-ad-form.jsx | 72 +- .../p2p/src/pages/my-ads/create-ad-form.scss | 211 +++++ .../my-ads/create-ad-summary.jsx | 61 +- .../src/pages/my-ads/create-ad-summary.scss | 7 + .../my-ads/create-ad.jsx | 2 +- .../my-ads/edit-ad-form-payment-methods.jsx | 8 +- .../my-ads/edit-ad-form.jsx | 47 +- .../p2p/src/pages/my-ads/edit-ad-form.scss | 239 ++++++ .../my-ads/edit-ad-summary.jsx | 61 +- .../p2p/src/pages/my-ads/edit-ad-summary.scss | 7 + .../{components => pages}/my-ads/edit-ad.jsx | 0 .../filter-payment-methods-results.jsx | 0 .../filter-payment-methods-results.scss | 0 .../filter-payment-method-results/index.js | 0 .../filter-payment-methods.jsx | 0 .../filter-payment-methods.scss | 0 .../my-ads/filter-payment-methods/index.js | 0 .../src/{components => pages}/my-ads/index.js | 0 .../my-ads/my-ads-row-renderer.jsx | 101 ++- .../my-ads/my-ads-table.jsx | 27 +- .../p2p/src/pages/my-ads/my-ads-table.scss | 262 ++++++ .../{components => pages}/my-ads/my-ads.jsx | 16 +- packages/p2p/src/pages/my-ads/my-ads.scss | 122 +++ .../my-ads/sell-ad-payment-methods-list.jsx | 6 +- .../my-ads/sell-ad-payment-methods-list.scss | 2 +- .../my-ads/toggle-ads.jsx | 2 +- packages/p2p/src/pages/my-ads/toggle-ads.scss | 9 + .../block-user-dropdown.jsx | 0 .../block-user-dropdown.scss | 0 .../block-user/block-user-dropdown/index.js | 0 .../__tests__/block-user-empty.spec.tsx | 25 + .../block-user-empty/block-user-empty.scss | 10 + .../block-user-empty/block-user-empty.tsx} | 24 +- .../block-user/block-user-empty/index.ts} | 2 +- .../block-user-filter-modal.jsx | 6 +- .../block-user-filter-modal/index.js | 0 .../block-user-list/block-user-list.jsx | 0 .../block-user-list/block-user-list.scss | 0 .../block-user/block-user-list/index.js | 0 .../block-user-row/block-user-row.jsx | 4 +- .../block-user-row/block-user-row.scss | 0 .../block-user-table/block-user-row/index.js | 0 .../block-user-table-error.jsx | 16 +- .../block-user-table-error.scss | 0 .../block-user-table-error/index.js | 0 .../block-user-table/block-user-table.jsx | 10 +- .../block-user-table/block-user-table.scss | 0 .../block-user/block-user-table/index.js | 0 .../my-profile/block-user/block-user.jsx | 0 .../my-profile/block-user/block-user.scss | 1 - .../my-profile/block-user/index.js | 0 .../{components => pages}/my-profile/index.js | 0 .../my-profile/my-profile-content.jsx | 0 .../my-profile/my-profile-form/index.js | 0 .../my-profile-form/my-profile-form.jsx | 2 +- .../my-profile-form/my-profile-form.scss | 0 .../my-profile/my-profile-header/index.js | 0 .../my-profile-header/my-profile-header.jsx | 2 +- .../my-profile-header/my-profile-header.scss | 0 .../my-profile-separator-container/index.js | 0 .../my-profile-separator-container.jsx | 0 .../my-profile-separator-container.scss | 0 .../my-profile/my-profile-stats/index.js | 0 .../my-profile-balance/index.js | 0 .../my-profile-balance/my-profile-balance.jsx | 10 +- .../my-profile-balance.scss | 6 +- .../my-profile-details-container/index.js | 0 .../my-profile-details-container.jsx | 2 +- .../my-profile-details-container.scss | 2 +- .../my-profile-details-table/index.js | 0 .../my-profile-details-table.jsx | 16 +- .../my-profile-details-table.scss | 6 +- .../my-profile-stats/my-profile-name/index.js | 0 .../my-profile-name/my-profile-name.jsx | 32 +- .../my-profile-name/my-profile-name.scss | 6 +- .../my-profile-privacy/index.js | 0 .../my-profile-privacy/my-profile-privacy.jsx | 7 +- .../my-profile-privacy.scss | 0 .../my-profile-stats-table/index.js | 0 .../my-profile-stats-table.jsx | 56 +- .../my-profile-stats-table.scss | 0 .../my-profile-stats/my-profile-stats.jsx | 0 .../my-profile-stats/my-profile-stats.scss | 0 .../my-profile/my-profile.jsx | 0 .../my-profile/my-profile.scss | 0 .../add-payment-method-form.jsx | 1 + .../add-payment-method-form.scss | 65 ++ .../add-payment-method/add-payment-method.jsx | 2 +- .../add-payment-method.scss | 30 + .../add-payment-method/index.js | 0 .../select-payment-method.jsx | 7 +- .../select-payment-method.scss | 11 + .../my-profile/payment-methods/index.js | 0 .../payment-method-card/index.js | 0 .../payment-method-card-menu.jsx | 8 +- .../payment-method-card-menu.scss | 12 + .../payment-method-card.jsx | 0 .../payment-method-card.scss | 27 +- .../payment-methods-empty/index.js | 0 .../payment-methods-empty.jsx | 14 +- .../payment-methods-empty.scss | 6 +- .../edit-payment-method-form.jsx | 19 +- .../edit-payment-method-form.scss | 63 ++ .../payment-methods-list/index.js | 0 .../payment-methods-list.jsx | 0 .../payment-methods-list.scss | 1 + .../payment-methods/payment-methods.jsx | 0 .../orders/__tests__/orders.spec.js | 2 +- .../chat/__tests__/chat-header.spec.tsx | 0 .../chat/__tests__/chat-messages.spec.jsx | 2 +- .../orders/chat/__tests__/chat.spec.tsx | 0 .../orders/chat/chat-footer-icon.jsx | 6 +- .../orders/chat/chat-footer.jsx | 13 +- .../orders/chat/chat-footer.scss | 4 +- .../orders/chat/chat-header.jsx | 21 +- .../orders/chat/chat-header.scss | 2 +- .../orders/chat/chat-message-receipt.jsx | 3 +- .../orders/chat/chat-message-receipt.scss | 3 + .../orders/chat/chat-message-text.jsx | 3 +- .../pages/orders/chat/chat-message-text.scss | 11 + .../orders/chat/chat-messages.jsx | 21 +- .../orders/chat/chat-messages.scss | 21 +- .../orders/chat/chat-wrapper.jsx | 4 +- .../orders/chat/chat.jsx | 22 +- .../orders/chat/chat.scss | 6 +- .../src/{components => pages}/orders/index.js | 0 .../order-table/__test__/order-table.spec.js | 4 +- .../order-table/order-table-content.jsx | 14 +- .../orders/order-table/order-table-header.jsx | 9 +- .../order-table/order-table-header.scss | 5 + .../orders/order-table/order-table-row.jsx | 33 +- .../orders/order-table/order-table-row.scss | 26 + .../orders/order-table/order-table.jsx | 9 +- .../pages/orders/order-table/order-table.scss | 77 ++ .../{components => pages}/orders/orders.jsx | 1 - packages/p2p/src/pages/orders/orders.scss | 107 +++ .../{components => pages}/orders/popup.jsx | 12 +- .../p2p/src/stores/advertiser-page-store.js | 14 +- packages/p2p/src/stores/buy-sell-store.js | 56 +- packages/p2p/src/stores/general-store.js | 11 +- packages/p2p/tsconfig.json | 3 +- packages/p2p/webpack.config.js | 3 +- 361 files changed, 4694 insertions(+), 3657 deletions(-) create mode 100644 packages/p2p/@deriv-stores.d.ts delete mode 100644 packages/p2p/src/components/buy-sell/currency-selector/currency-selector.scss create mode 100644 packages/p2p/src/components/dp2p-blocked/__tests__/dp2p-blocked-description.spec.tsx create mode 100644 packages/p2p/src/components/dp2p-blocked/__tests__/dp2p-blocked.spec.tsx create mode 100644 packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/__tests__/dp2p-blocked-checklist.spec.tsx create mode 100644 packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/dp2p-blocked-checklist.scss rename packages/p2p/src/components/dp2p-blocked/{dp2p-blocked-checklist.jsx => dp2p-blocked-checklist/dp2p-blocked-checklist.tsx} (71%) create mode 100644 packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/index.ts rename packages/p2p/src/components/dp2p-blocked/{dp2p-blocked-description.jsx => dp2p-blocked-description.tsx} (83%) rename packages/p2p/src/components/dp2p-blocked/{dp2p-blocked.jsx => dp2p-blocked.tsx} (57%) rename packages/p2p/src/components/dp2p-blocked/{index.js => index.ts} (56%) delete mode 100644 packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.js create mode 100644 packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.tsx rename packages/p2p/src/components/floating-rate/{floating-rate.jsx => floating-rate.tsx} (72%) rename packages/p2p/src/components/floating-rate/{index.js => index.ts} (55%) delete mode 100644 packages/p2p/src/components/form/error.jsx delete mode 100644 packages/p2p/src/components/form/form.scss rename packages/p2p/src/components/i18next/{index.js => index.ts} (89%) delete mode 100644 packages/p2p/src/components/misc/__test__/animation-wrapper.spec.js delete mode 100644 packages/p2p/src/components/misc/animation-wrapper.jsx delete mode 100644 packages/p2p/src/components/misc/animation-wrapper.scss delete mode 100644 packages/p2p/src/components/misc/toggle-container.jsx create mode 100644 packages/p2p/src/components/modal-manager/modals/ad-error-tooltip-modal/ad-error-tooltip-modal.scss create mode 100644 packages/p2p/src/components/modal-manager/modals/ad-visibility-error-modal/ad-visibility-error-modal.scss create mode 100644 packages/p2p/src/components/modal-manager/modals/create-ad-error-modal/create-ad-error-modal.scss create mode 100644 packages/p2p/src/components/modal-manager/modals/nickname-modal/index.ts create mode 100644 packages/p2p/src/components/modal-manager/modals/nickname-modal/nickname-modal.tsx delete mode 100644 packages/p2p/src/components/modal-manager/modals/recommended-modal/recommended-modal.scss delete mode 100644 packages/p2p/src/components/my-ads/my-ads.scss delete mode 100644 packages/p2p/src/components/nickname-form/__test__/nickname-form-wrapper.spec.js delete mode 100644 packages/p2p/src/components/nickname-form/__test__/nickname-form.spec.js create mode 100644 packages/p2p/src/components/nickname-form/__tests__/nickname-form.spec.tsx rename packages/p2p/src/components/nickname-form/{index.js => index.ts} (55%) delete mode 100644 packages/p2p/src/components/nickname-form/nickname-form-wrapper.jsx delete mode 100644 packages/p2p/src/components/nickname-form/nickname-form.jsx create mode 100644 packages/p2p/src/components/nickname-form/nickname-form.tsx create mode 100644 packages/p2p/src/components/online-status/__tests__/online-status-avatar.spec.tsx create mode 100644 packages/p2p/src/components/online-status/__tests__/online-status-icon.spec.tsx rename packages/p2p/src/components/online-status/{index.js => index.ts} (100%) rename packages/p2p/src/components/online-status/{online-status-avatar.jsx => online-status-avatar.tsx} (73%) rename packages/p2p/src/components/online-status/{online-status-icon.jsx => online-status-icon.tsx} (63%) delete mode 100644 packages/p2p/src/components/online-status/online-status-label.jsx create mode 100644 packages/p2p/src/components/online-status/online-status-label.tsx create mode 100644 packages/p2p/src/components/order-details/order-details-complain-modal-radio-group.scss create mode 100644 packages/p2p/src/components/order-details/order-details-footer.scss create mode 100644 packages/p2p/src/components/order-details/order-details-timer.scss create mode 100644 packages/p2p/src/components/order-details/order-info-block.scss create mode 100644 packages/p2p/src/components/order-details/payment-method-accordion-header.scss delete mode 100644 packages/p2p/src/components/orders/orders.scss rename packages/p2p/src/components/{empty/__test__/p2p-empty.spec.js => p2p-empty/__test__/p2p-empty.spec.tsx} (58%) create mode 100644 packages/p2p/src/components/p2p-empty/index.ts rename packages/p2p/src/components/{empty/empty.scss => p2p-empty/p2p-empty.scss} (76%) rename packages/p2p/src/components/{empty/empty.jsx => p2p-empty/p2p-empty.tsx} (50%) create mode 100644 packages/p2p/src/components/page-return/__test__/page-return.spec.tsx create mode 100644 packages/p2p/src/components/page-return/index.ts rename packages/p2p/src/components/page-return/{page-return.jsx => page-return.tsx} (54%) create mode 100644 packages/p2p/src/components/recommend-user/__test__/recommend-user.spec.tsx rename packages/p2p/src/components/recommend-user/{index.js => index.ts} (55%) rename packages/p2p/src/components/recommend-user/{recommend-user.jsx => recommend-user.tsx} (76%) create mode 100644 packages/p2p/src/components/recommended-by/__tests__/recommended-by.spec.tsx rename packages/p2p/src/components/recommended-by/{index.js => index.ts} (55%) rename packages/p2p/src/components/recommended-by/{recommended-by.jsx => recommended-by.tsx} (79%) create mode 100644 packages/p2p/src/components/section-error/__tests__/section-error.spec.tsx create mode 100644 packages/p2p/src/components/section-error/index.ts create mode 100644 packages/p2p/src/components/section-error/section-error.scss create mode 100644 packages/p2p/src/components/section-error/section-error.tsx create mode 100644 packages/p2p/src/components/star-rating/__test__/star-rating.spec.tsx delete mode 100644 packages/p2p/src/components/star-rating/index.js create mode 100644 packages/p2p/src/components/star-rating/index.ts rename packages/p2p/src/components/star-rating/{star-rating.jsx => star-rating.tsx} (50%) delete mode 100644 packages/p2p/src/components/table/__test__/table-error.spec.js delete mode 100644 packages/p2p/src/components/table/table-error.jsx delete mode 100644 packages/p2p/src/components/table/table.scss create mode 100644 packages/p2p/src/components/temporarily-barred-hint/__test__/temporarily-barred-hint.spec.tsx rename packages/p2p/src/components/temporarily-barred-hint/{index.js => index.ts} (54%) rename packages/p2p/src/components/temporarily-barred-hint/{temporarily-barred-hint.jsx => temporarily-barred-hint.tsx} (89%) rename packages/p2p/src/components/{misc/__test__/toggle-container.spec.js => toggle-container/__tests__/toggle-container.spec.tsx} (74%) create mode 100644 packages/p2p/src/components/toggle-container/index.ts rename packages/p2p/src/components/{misc => toggle-container}/toggle-container.scss (80%) create mode 100644 packages/p2p/src/components/toggle-container/toggle-container.tsx create mode 100644 packages/p2p/src/components/trade-badge/__tests__/trade-badge.spec.tsx rename packages/p2p/src/components/trade-badge/{index.js => index.ts} (56%) rename packages/p2p/src/components/trade-badge/{trade-badge.jsx => trade-badge.tsx} (65%) rename packages/p2p/src/components/user/user-avatar/__test__/{user-avatar.spec.js => user-avatar.spec.tsx} (73%) rename packages/p2p/src/components/user/user-avatar/{index.js => index.ts} (56%) rename packages/p2p/src/components/user/user-avatar/{user-avatar.jsx => user-avatar.tsx} (70%) delete mode 100644 packages/p2p/src/components/verification/__tests__/verification.spec.js create mode 100644 packages/p2p/src/components/verification/__tests__/verification.spec.tsx create mode 100644 packages/p2p/src/components/verification/index.ts rename packages/p2p/src/components/verification/{verification.jsx => verification.tsx} (50%) rename packages/p2p/src/{components => pages}/advertiser-page/__tests__/advertiser-page.spec.jsx (100%) rename packages/p2p/src/{components => pages}/advertiser-page/advertiser-page-adverts.jsx (89%) create mode 100644 packages/p2p/src/pages/advertiser-page/advertiser-page-adverts.scss rename packages/p2p/src/{components => pages}/advertiser-page/advertiser-page-dropdown-menu.jsx (86%) create mode 100644 packages/p2p/src/pages/advertiser-page/advertiser-page-dropdown-menu.scss rename packages/p2p/src/{components => pages}/advertiser-page/advertiser-page-row.jsx (80%) create mode 100644 packages/p2p/src/pages/advertiser-page/advertiser-page-row.scss rename packages/p2p/src/{components => pages}/advertiser-page/advertiser-page-stats.jsx (77%) create mode 100644 packages/p2p/src/pages/advertiser-page/advertiser-page-stats.scss rename packages/p2p/src/{components => pages}/advertiser-page/advertiser-page.jsx (95%) rename packages/p2p/src/{components => pages}/advertiser-page/advertiser-page.scss (51%) rename packages/p2p/src/{components => pages}/advertiser-page/block-user/block-user-count.jsx (96%) rename packages/p2p/src/{components => pages}/advertiser-page/block-user/block-user-count.scss (100%) rename packages/p2p/src/{components => pages}/advertiser-page/block-user/block-user-overlay/block-user-overlay.jsx (96%) rename packages/p2p/src/{components => pages}/advertiser-page/block-user/block-user-overlay/block-user-overlay.scss (94%) rename packages/p2p/src/{components => pages}/advertiser-page/block-user/block-user-overlay/index.js (100%) rename packages/p2p/src/{components => pages}/advertiser-page/index.js (100%) rename packages/p2p/src/{components => pages}/app.jsx (95%) rename packages/p2p/src/{components => pages}/app.scss (71%) rename packages/p2p/src/{components => pages}/buy-sell/__tests__/buy-sell-form-receive-amount.spec.js (95%) rename packages/p2p/src/{components => pages}/buy-sell/__tests__/buy-sell.spec.jsx (74%) rename packages/p2p/src/{components => pages}/buy-sell/__tests__/sort-dropdown.spec.js (100%) rename packages/p2p/src/{components => pages}/buy-sell/buy-sell-form-receive-amount.jsx (80%) create mode 100644 packages/p2p/src/pages/buy-sell/buy-sell-form-receive-amount.scss rename packages/p2p/src/{components => pages}/buy-sell/buy-sell-form.jsx (92%) create mode 100644 packages/p2p/src/pages/buy-sell/buy-sell-form.scss rename packages/p2p/src/{components => pages}/buy-sell/buy-sell-header.jsx (79%) rename packages/p2p/src/{components => pages}/buy-sell/buy-sell-header.scss (93%) rename packages/p2p/src/{components => pages}/buy-sell/buy-sell-row.jsx (92%) rename packages/p2p/src/{components => pages}/buy-sell/buy-sell-row.scss (99%) rename packages/p2p/src/{components => pages}/buy-sell/buy-sell-table.jsx (87%) create mode 100644 packages/p2p/src/pages/buy-sell/buy-sell-table.scss rename packages/p2p/src/{components => pages}/buy-sell/buy-sell.jsx (92%) rename packages/p2p/src/{components => pages}/buy-sell/buy-sell.scss (74%) rename packages/p2p/src/{components => pages}/buy-sell/currency-dropdown.jsx (96%) rename packages/p2p/src/{components => pages}/buy-sell/currency-dropdown.scss (100%) rename packages/p2p/src/{components => pages}/buy-sell/currency-selector/currency-selector.jsx (97%) rename packages/p2p/src/{components/modal-manager/modals/currency-selector-modal => pages/buy-sell/currency-selector}/currency-selector.scss (98%) rename packages/p2p/src/{components => pages}/buy-sell/currency-selector/index.js (100%) rename packages/p2p/src/{components => pages}/buy-sell/index.js (70%) rename packages/p2p/src/{components => pages}/buy-sell/no-ads/__tests__/no-ads.spec.jsx (100%) rename packages/p2p/src/{components => pages}/buy-sell/no-ads/index.js (70%) rename packages/p2p/src/{components => pages}/buy-sell/no-ads/no-ads.jsx (100%) rename packages/p2p/src/{components => pages}/buy-sell/no-ads/no-ads.scss (100%) rename packages/p2p/src/{components => pages}/buy-sell/sort-dropdown.jsx (96%) rename packages/p2p/src/{components => pages}/buy-sell/sort-dropdown.scss (100%) rename packages/p2p/src/{components => pages}/my-ads/__tests__/ad-status.spec.js (100%) rename packages/p2p/src/{components => pages}/my-ads/__tests__/my-ads-table.spec.jsx (100%) rename packages/p2p/src/{components => pages}/my-ads/ad-status.jsx (100%) rename packages/p2p/src/{components => pages}/my-ads/ad-status.scss (100%) rename packages/p2p/src/{components => pages}/my-ads/ad-type.jsx (69%) rename packages/p2p/src/{components => pages}/my-ads/ad-type.scss (100%) rename packages/p2p/src/{components => pages}/my-ads/buy-ad-payment-methods-list.jsx (99%) rename packages/p2p/src/{components => pages}/my-ads/buy-ad-payment-methods-list.scss (100%) rename packages/p2p/src/{components => pages}/my-ads/create-ad-form-payment-methods.jsx (92%) rename packages/p2p/src/{components => pages}/my-ads/create-ad-form.jsx (92%) create mode 100644 packages/p2p/src/pages/my-ads/create-ad-form.scss rename packages/p2p/src/{components => pages}/my-ads/create-ad-summary.jsx (62%) create mode 100644 packages/p2p/src/pages/my-ads/create-ad-summary.scss rename packages/p2p/src/{components => pages}/my-ads/create-ad.jsx (91%) rename packages/p2p/src/{components => pages}/my-ads/edit-ad-form-payment-methods.jsx (91%) rename packages/p2p/src/{components => pages}/my-ads/edit-ad-form.jsx (96%) create mode 100644 packages/p2p/src/pages/my-ads/edit-ad-form.scss rename packages/p2p/src/{components => pages}/my-ads/edit-ad-summary.jsx (62%) create mode 100644 packages/p2p/src/pages/my-ads/edit-ad-summary.scss rename packages/p2p/src/{components => pages}/my-ads/edit-ad.jsx (100%) rename packages/p2p/src/{components => pages}/my-ads/filter-payment-methods/filter-payment-method-results/filter-payment-methods-results.jsx (100%) rename packages/p2p/src/{components => pages}/my-ads/filter-payment-methods/filter-payment-method-results/filter-payment-methods-results.scss (100%) rename packages/p2p/src/{components => pages}/my-ads/filter-payment-methods/filter-payment-method-results/index.js (100%) rename packages/p2p/src/{components => pages}/my-ads/filter-payment-methods/filter-payment-methods.jsx (100%) rename packages/p2p/src/{components => pages}/my-ads/filter-payment-methods/filter-payment-methods.scss (100%) rename packages/p2p/src/{components => pages}/my-ads/filter-payment-methods/index.js (100%) rename packages/p2p/src/{components => pages}/my-ads/index.js (100%) rename packages/p2p/src/{components => pages}/my-ads/my-ads-row-renderer.jsx (78%) rename packages/p2p/src/{components => pages}/my-ads/my-ads-table.jsx (86%) create mode 100644 packages/p2p/src/pages/my-ads/my-ads-table.scss rename packages/p2p/src/{components => pages}/my-ads/my-ads.jsx (83%) create mode 100644 packages/p2p/src/pages/my-ads/my-ads.scss rename packages/p2p/src/{components => pages}/my-ads/sell-ad-payment-methods-list.jsx (90%) rename packages/p2p/src/{components => pages}/my-ads/sell-ad-payment-methods-list.scss (93%) rename packages/p2p/src/{components => pages}/my-ads/toggle-ads.jsx (98%) create mode 100644 packages/p2p/src/pages/my-ads/toggle-ads.scss rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-dropdown/block-user-dropdown.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-dropdown/block-user-dropdown.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-dropdown/index.js (100%) create mode 100644 packages/p2p/src/pages/my-profile/block-user/block-user-empty/__tests__/block-user-empty.spec.tsx rename packages/p2p/src/{components => pages/my-profile}/block-user/block-user-empty/block-user-empty.scss (54%) rename packages/p2p/src/{components/block-user/block-user-empty/block-user-empty.jsx => pages/my-profile/block-user/block-user-empty/block-user-empty.tsx} (50%) rename packages/p2p/src/{components/block-user/block-user-empty/index.js => pages/my-profile/block-user/block-user-empty/index.ts} (55%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-filter-modal/block-user-filter-modal.jsx (83%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-filter-modal/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-list/block-user-list.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-list/block-user-list.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-list/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/block-user-row/block-user-row.jsx (95%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/block-user-row/block-user-row.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/block-user-row/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/block-user-table-error/block-user-table-error.jsx (78%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/block-user-table-error/block-user-table-error.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/block-user-table-error/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/block-user-table.jsx (90%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/block-user-table.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user-table/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/block-user/block-user.scss (92%) rename packages/p2p/src/{components => pages}/my-profile/block-user/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-content.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-form/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-form/my-profile-form.jsx (99%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-form/my-profile-form.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-header/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-header/my-profile-header.jsx (95%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-header/my-profile-header.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-separator-container/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-separator-container/my-profile-separator-container.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-separator-container/my-profile-separator-container.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-balance/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-balance/my-profile-balance.jsx (86%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-balance/my-profile-balance.scss (90%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-details-container/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-details-container/my-profile-details-container.jsx (89%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-details-container/my-profile-details-container.scss (96%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-details-table/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-details-table/my-profile-details-table.jsx (96%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-details-table/my-profile-details-table.scss (96%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-name/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-name/my-profile-name.jsx (88%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-name/my-profile-name.scss (97%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-privacy/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-privacy/my-profile-privacy.jsx (83%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-privacy/my-profile-privacy.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-stats-table/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-stats-table/my-profile-stats-table.jsx (89%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-stats-table/my-profile-stats-table.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-stats.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile-stats/my-profile-stats.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/my-profile.scss (100%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/add-payment-method/add-payment-method-form.jsx (99%) create mode 100644 packages/p2p/src/pages/my-profile/payment-methods/add-payment-method/add-payment-method-form.scss rename packages/p2p/src/{components => pages}/my-profile/payment-methods/add-payment-method/add-payment-method.jsx (97%) create mode 100644 packages/p2p/src/pages/my-profile/payment-methods/add-payment-method/add-payment-method.scss rename packages/p2p/src/{components => pages}/my-profile/payment-methods/add-payment-method/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/add-payment-method/select-payment-method.jsx (94%) create mode 100644 packages/p2p/src/pages/my-profile/payment-methods/add-payment-method/select-payment-method.scss rename packages/p2p/src/{components => pages}/my-profile/payment-methods/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-method-card/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-method-card/payment-method-card-menu.jsx (76%) create mode 100644 packages/p2p/src/pages/my-profile/payment-methods/payment-method-card/payment-method-card-menu.scss rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-method-card/payment-method-card.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-method-card/payment-method-card.scss (89%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-methods-empty/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-methods-empty/payment-methods-empty.jsx (83%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-methods-empty/payment-methods-empty.scss (82%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-methods-list/edit-payment-method-form.jsx (91%) create mode 100644 packages/p2p/src/pages/my-profile/payment-methods/payment-methods-list/edit-payment-method-form.scss rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-methods-list/index.js (100%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-methods-list/payment-methods-list.jsx (100%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-methods-list/payment-methods-list.scss (99%) rename packages/p2p/src/{components => pages}/my-profile/payment-methods/payment-methods.jsx (100%) rename packages/p2p/src/{components => pages}/orders/__tests__/orders.spec.js (94%) rename packages/p2p/src/{components => pages}/orders/chat/__tests__/chat-header.spec.tsx (100%) rename packages/p2p/src/{components => pages}/orders/chat/__tests__/chat-messages.spec.jsx (97%) rename packages/p2p/src/{components => pages}/orders/chat/__tests__/chat.spec.tsx (100%) rename packages/p2p/src/{components => pages}/orders/chat/chat-footer-icon.jsx (68%) rename packages/p2p/src/{components => pages}/orders/chat/chat-footer.jsx (89%) rename packages/p2p/src/{components => pages}/orders/chat/chat-footer.scss (97%) rename packages/p2p/src/{components => pages}/orders/chat/chat-header.jsx (71%) rename packages/p2p/src/{components => pages}/orders/chat/chat-header.scss (98%) rename packages/p2p/src/{components => pages}/orders/chat/chat-message-receipt.jsx (90%) create mode 100644 packages/p2p/src/pages/orders/chat/chat-message-receipt.scss rename packages/p2p/src/{components => pages}/orders/chat/chat-message-text.jsx (89%) create mode 100644 packages/p2p/src/pages/orders/chat/chat-message-text.scss rename packages/p2p/src/{components => pages}/orders/chat/chat-messages.jsx (88%) rename packages/p2p/src/{components => pages}/orders/chat/chat-messages.scss (80%) rename packages/p2p/src/{components => pages}/orders/chat/chat-wrapper.jsx (92%) rename packages/p2p/src/{components => pages}/orders/chat/chat.jsx (75%) rename packages/p2p/src/{components => pages}/orders/chat/chat.scss (83%) rename packages/p2p/src/{components => pages}/orders/index.js (100%) rename packages/p2p/src/{components => pages}/orders/order-table/__test__/order-table.spec.js (78%) rename packages/p2p/src/{components => pages}/orders/order-table/order-table-content.jsx (88%) rename packages/p2p/src/{components => pages}/orders/order-table/order-table-header.jsx (79%) create mode 100644 packages/p2p/src/pages/orders/order-table/order-table-header.scss rename packages/p2p/src/{components => pages}/orders/order-table/order-table-row.jsx (88%) create mode 100644 packages/p2p/src/pages/orders/order-table/order-table-row.scss rename packages/p2p/src/{components => pages}/orders/order-table/order-table.jsx (86%) create mode 100644 packages/p2p/src/pages/orders/order-table/order-table.scss rename packages/p2p/src/{components => pages}/orders/orders.jsx (98%) create mode 100644 packages/p2p/src/pages/orders/orders.scss rename packages/p2p/src/{components => pages}/orders/popup.jsx (94%) diff --git a/packages/core/src/Stores/notification-store.js b/packages/core/src/Stores/notification-store.js index c7026ae0fd39..6caa8cba6257 100644 --- a/packages/core/src/Stores/notification-store.js +++ b/packages/core/src/Stores/notification-store.js @@ -840,7 +840,6 @@ export default class NotificationStore extends BaseStore { /> ), platform: 'P2P', - should_show_again: false, type: 'announce', }; }, diff --git a/packages/p2p/@deriv-stores.d.ts b/packages/p2p/@deriv-stores.d.ts new file mode 100644 index 000000000000..8979a64c6fc0 --- /dev/null +++ b/packages/p2p/@deriv-stores.d.ts @@ -0,0 +1,10 @@ +import type { TCoreStores } from '@deriv/stores/types'; +import type P2PStore from './src/stores'; + +declare module '@deriv/stores' { + export function useStore(): TCoreStores & { + modules: { + p2p: P2PStore; + }; + }; +} diff --git a/packages/p2p/jest.config.js b/packages/p2p/jest.config.js index 49aafa5bfc3f..8ee673a11aaa 100644 --- a/packages/p2p/jest.config.js +++ b/packages/p2p/jest.config.js @@ -9,6 +9,7 @@ module.exports = { '^Assets/(.*)$': '/src/assets/$1', '^Components/(.*)$': '/src/components/$1', '^Constants/(.*)$': '/src/constants/$1', + '^Pages/(.*)$': '/src/pages/$1', '^Stores/(.*)$': '/src/stores/$1', '^Stores$': '/src/stores/index', '^Translations/(.*)$': '/src/translations/$1', diff --git a/packages/p2p/package.json b/packages/p2p/package.json index 09d6fc19ded5..76bad9966094 100644 --- a/packages/p2p/package.json +++ b/packages/p2p/package.json @@ -38,6 +38,7 @@ "@deriv/translations": "^1.0.0", "@deriv/api-types": "^1.0.118", "@testing-library/react": "^12.0.0", + "@testing-library/user-event": "^13.5.0", "classnames": "^2.2.6", "commander": "^3.0.2", "crc-32": "^1.2.0", diff --git a/packages/p2p/src/components/__tests__/app-content.spec.js b/packages/p2p/src/components/__tests__/app-content.spec.js index 433c82fad51d..af2c930c22fd 100644 --- a/packages/p2p/src/components/__tests__/app-content.spec.js +++ b/packages/p2p/src/components/__tests__/app-content.spec.js @@ -25,25 +25,18 @@ jest.mock('@deriv/components', () => ({ Loading: () =>
Loading
, })); +jest.mock('@deriv/shared', () => ({ + ...jest.requireActual('@deriv/shared'), + isMobile: jest.fn(() => false), +})); + // jest.mock('Components/dp2p-blocked', () => jest.fn(() => 'Dp2pBlocked')); jest.mock('Components/nickname-form', () => jest.fn(() => 'NicknameForm')); jest.mock('Components/verification/verification', () => jest.fn(() => 'Verification')); -jest.mock('Components/my-ads/my-ads', () => jest.fn(() => 'MyAds')); -jest.mock('Components/orders/orders', () => jest.fn(() => 'Orders')); -jest.mock('Components/buy-sell/buy-sell', () => jest.fn(() => 'BuySell')); -jest.mock('Components/my-profile', () => jest.fn(() => 'MyProfile')); - -jest.mock('@sendbird/chat', () => ({ - SendbirdChat: jest.fn().mockReturnValue({}), -})); - -jest.mock('@sendbird/chat/groupChannel', () => ({ - SendbirdChat: jest.fn().mockReturnValue({}), -})); - -jest.mock('@sendbird/chat/message', () => ({ - SendbirdChat: jest.fn().mockReturnValue({}), -})); +jest.mock('Pages/my-ads/my-ads', () => jest.fn(() => 'MyAds')); +jest.mock('Pages/orders/orders', () => jest.fn(() => 'Orders')); +jest.mock('Pages/buy-sell/buy-sell', () => jest.fn(() => 'BuySell')); +jest.mock('Pages/my-profile', () => jest.fn(() => 'MyProfile')); describe('', () => { const mocked_store_values = { @@ -93,17 +86,6 @@ describe('', () => { // expect(screen.getByText('Dp2pBlocked')).toBeInTheDocument(); // }); - it('should render the nick-name form component when should_show_popup state is true', () => { - useStores.mockImplementation(() => ({ - general_store: { ...mocked_store_values, should_show_popup: true }, - })); - render(, { - wrapper: ({ children }) => {children}, - }); - - expect(screen.getByText('NicknameForm')).toBeInTheDocument(); - }); - // it('should render only the first notification component when multiple error status is set', () => { // useStores.mockImplementation(() => ({ // general_store: { ...mocked_store_values, should_show_popup: true, should_show_dp2p_blocked: true }, diff --git a/packages/p2p/src/components/app-content.jsx b/packages/p2p/src/components/app-content.jsx index e364e5e5268a..18779b4c164d 100644 --- a/packages/p2p/src/components/app-content.jsx +++ b/packages/p2p/src/components/app-content.jsx @@ -1,16 +1,16 @@ +import classNames from 'classnames'; import React from 'react'; -import { isAction, reaction } from 'mobx'; import { useHistory } from 'react-router-dom'; -import { useStores } from 'Stores'; -import { isMobile } from '@deriv/shared'; +import { isAction, reaction } from 'mobx'; +import { observer } from 'mobx-react-lite'; import { Loading, Tabs } from '@deriv/components'; -import { useStore, observer } from '@deriv/stores'; -import classNames from 'classnames'; -import { localize } from './i18next'; -import NicknameForm from './nickname-form'; -import TemporarilyBarredHint from './temporarily-barred-hint'; -import { useModalManagerContext } from 'Components/modal-manager/modal-manager-context'; import { useP2PNotificationCount } from '@deriv/hooks'; +import { isMobile } from '@deriv/shared'; +import { useStore } from '@deriv/stores'; +import TemporarilyBarredHint from 'Components/temporarily-barred-hint'; +import { useModalManagerContext } from 'Components/modal-manager/modal-manager-context'; +import { useStores } from 'Stores'; +import { localize } from './i18next'; const AppContent = ({ order_id }) => { const { buy_sell_store, general_store } = useStores(); @@ -47,10 +47,6 @@ const AppContent = ({ order_id }) => { return ; } - if (general_store.should_show_popup) { - return ; - } - // return empty or else the tabs will be shown above when displaying the advertiser page if ( (buy_sell_store?.show_advertiser_page && !buy_sell_store.should_show_verification) || @@ -62,7 +58,7 @@ const AppContent = ({ order_id }) => { return ( ({ + ...jest.requireActual('Stores'), + useStores: jest.fn(), +})); + +describe('', () => { + it('it should return `P2P transactions are locked. This feature is not available for payment agents.`', () => { + (useStores as jest.Mock).mockReturnValue({ + general_store: { + is_p2p_blocked_for_pa: true, + is_high_risk: true, + is_blocked: false, + }, + }); + render(); + expect( + screen.getByText('P2P transactions are locked. This feature is not available for payment agents.') + ).toBeInTheDocument(); + }); + + it('it should return `To enable this feature you must complete the following:`', () => { + (useStores as jest.Mock).mockReturnValue({ + general_store: { + is_p2p_blocked_for_pa: false, + is_high_risk: true, + is_blocked: false, + }, + }); + render(); + expect(screen.getByText('To enable this feature you must complete the following:')).toBeInTheDocument(); + }); + + it('it should return `Please use live chat to contact our Customer Support team for help.` and open live chat when clicking on the `live chat`', () => { + (useStores as jest.Mock).mockReturnValue({ + general_store: { + is_p2p_blocked_for_pa: false, + is_high_risk: false, + is_blocked: false, + }, + }); + + window.LC_API = { + open_chat_window: jest.fn(), + on_chat_ended: jest.fn(), + }; + + render(); + expect(screen.getByText(/to contact our Customer Support team for help./)).toBeInTheDocument(); + + const live_chat_text = screen.getByText(/live chat/i); + expect(live_chat_text).toBeInTheDocument(); + + userEvent.click(live_chat_text); + expect(window.LC_API.open_chat_window).toHaveBeenCalledTimes(1); + }); +}); diff --git a/packages/p2p/src/components/dp2p-blocked/__tests__/dp2p-blocked.spec.tsx b/packages/p2p/src/components/dp2p-blocked/__tests__/dp2p-blocked.spec.tsx new file mode 100644 index 000000000000..7e24f92610d8 --- /dev/null +++ b/packages/p2p/src/components/dp2p-blocked/__tests__/dp2p-blocked.spec.tsx @@ -0,0 +1,10 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import Dp2pBlocked from '../dp2p-blocked'; + +describe('', () => { + it('it should render component', () => { + render(); + expect(screen.getByText('Your Deriv P2P cashier is blocked')).toBeInTheDocument(); + }); +}); diff --git a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/__tests__/dp2p-blocked-checklist.spec.tsx b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/__tests__/dp2p-blocked-checklist.spec.tsx new file mode 100644 index 000000000000..e2ec019dc182 --- /dev/null +++ b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/__tests__/dp2p-blocked-checklist.spec.tsx @@ -0,0 +1,55 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import { useStores } from 'Stores/index'; +import Dp2pBlockedChecklist from '..'; + +const mockHistoryPush = jest.fn(); + +jest.mock('Stores', () => ({ + ...jest.requireActual('Stores'), + useStores: jest.fn(), +})); + +jest.mock('react-router-dom', () => ({ + ...jest.requireActual('react-router-dom'), + useHistory: () => ({ + push: mockHistoryPush, + }), +})); + +describe('', () => { + it('it should render component if client is high risk and not blocked', () => { + (useStores as jest.Mock).mockReturnValue({ + general_store: { + is_high_risk: true, + is_blocked: false, + }, + }); + render(); + expect(screen.getByText('Complete the financial assessment form')).toBeInTheDocument(); + }); + + it('it should redirect to `/account/financial-assessment` while clicking on checklist button if client is high risk and not blocked', () => { + (useStores as jest.Mock).mockReturnValue({ + general_store: { + is_high_risk: true, + is_blocked: false, + }, + }); + render(); + userEvent.click(screen.getByTestId('dt_checklist_item_status_action')); + expect(mockHistoryPush).toHaveBeenCalledWith({ pathname: '/account/financial-assessment' }); + }); + + it('it should return null when client is not high risk', () => { + (useStores as jest.Mock).mockReturnValue({ + general_store: { + is_high_risk: false, + is_blocked: false, + }, + }); + const { container } = render(); + expect(container).toBeEmptyDOMElement(); + }); +}); diff --git a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/dp2p-blocked-checklist.scss b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/dp2p-blocked-checklist.scss new file mode 100644 index 000000000000..d86686bfde69 --- /dev/null +++ b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/dp2p-blocked-checklist.scss @@ -0,0 +1,13 @@ +.dp2p-blocked-checklist { + &__container { + margin-top: 2.4rem; + } + + .dc-checklist__item { + width: 40rem; + + @include mobile { + width: 100%; + } + } +} diff --git a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist.jsx b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/dp2p-blocked-checklist.tsx similarity index 71% rename from packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist.jsx rename to packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/dp2p-blocked-checklist.tsx index f25f66522340..f7259c2867c5 100644 --- a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist.jsx +++ b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/dp2p-blocked-checklist.tsx @@ -1,10 +1,10 @@ -import * as React from 'react'; +import React from 'react'; import { useHistory } from 'react-router-dom'; +import { observer } from 'mobx-react-lite'; import { Checklist } from '@deriv/components'; import { routes } from '@deriv/shared'; -import { observer } from 'mobx-react-lite'; -import { useStores } from 'Stores'; -import { localize } from '../i18next'; +import { localize } from 'Components/i18next'; +import { useStores } from 'Stores/index'; // remove index when store migration to ts is done const Dp2pBlockedChecklist = () => { const { general_store } = useStores(); @@ -23,8 +23,8 @@ const Dp2pBlockedChecklist = () => { ]; return ( -
- +
+
); } diff --git a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/index.ts b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/index.ts new file mode 100644 index 000000000000..d404fc802cbf --- /dev/null +++ b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-checklist/index.ts @@ -0,0 +1,4 @@ +import Dp2pBlockedChecklist from './dp2p-blocked-checklist'; +import './dp2p-blocked-checklist.scss'; + +export default Dp2pBlockedChecklist; diff --git a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.jsx b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.tsx similarity index 83% rename from packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.jsx rename to packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.tsx index fedfff82b7b1..a5a64e9a9522 100644 --- a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.jsx +++ b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked-description.tsx @@ -1,8 +1,8 @@ -import * as React from 'react'; -import { Text } from '@deriv/components'; +import React from 'react'; import { observer } from 'mobx-react-lite'; -import { useStores } from 'Stores'; -import { Localize } from '../i18next'; +import { Text } from '@deriv/components'; +import { Localize } from 'Components/i18next'; +import { useStores } from 'Stores/index'; //remove index when store migration to ts is done const Dp2pBlockedDescription = () => { const { general_store } = useStores(); @@ -26,7 +26,7 @@ const Dp2pBlockedDescription = () => { }; return ( - + {getBlockedDescription()} ); diff --git a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked.scss b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked.scss index cd7594a0625d..112da8c6055a 100644 --- a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked.scss +++ b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked.scss @@ -9,18 +9,4 @@ &__title { margin: 2.4rem 0 1rem; } - - &__checklist { - &-container { - margin-top: 2.4rem; - } - - .dc-checklist__item { - width: 40rem; - - @include mobile { - width: 100%; - } - } - } } diff --git a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked.jsx b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked.tsx similarity index 57% rename from packages/p2p/src/components/dp2p-blocked/dp2p-blocked.jsx rename to packages/p2p/src/components/dp2p-blocked/dp2p-blocked.tsx index 3f31bf95d68e..2ebee7300ca9 100644 --- a/packages/p2p/src/components/dp2p-blocked/dp2p-blocked.jsx +++ b/packages/p2p/src/components/dp2p-blocked/dp2p-blocked.tsx @@ -1,14 +1,14 @@ -import * as React from 'react'; +import React from 'react'; import { Icon, Text } from '@deriv/components'; -import Dp2pBlockedChecklist from './dp2p-blocked-checklist.jsx'; -import Dp2pBlockedDescription from './dp2p-blocked-description.jsx'; -import { Localize } from '../i18next'; +import { Localize } from 'Components/i18next'; +import Dp2pBlockedChecklist from './dp2p-blocked-checklist'; +import Dp2pBlockedDescription from './dp2p-blocked-description'; const Dp2pBlocked = () => { return ( -
+
- + diff --git a/packages/p2p/src/components/dp2p-blocked/index.js b/packages/p2p/src/components/dp2p-blocked/index.ts similarity index 56% rename from packages/p2p/src/components/dp2p-blocked/index.js rename to packages/p2p/src/components/dp2p-blocked/index.ts index 78c8d0c17443..5de1075dddc8 100644 --- a/packages/p2p/src/components/dp2p-blocked/index.js +++ b/packages/p2p/src/components/dp2p-blocked/index.ts @@ -1,4 +1,4 @@ -import Dp2pLocked from './dp2p-blocked.jsx'; +import Dp2pLocked from './dp2p-blocked'; import './dp2p-blocked.scss'; export default Dp2pLocked; diff --git a/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.js b/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.js deleted file mode 100644 index dbba08886a5b..000000000000 --- a/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.js +++ /dev/null @@ -1,34 +0,0 @@ -import React from 'react'; -import { render, screen } from '@testing-library/react'; -import FloatingRate from '../floating-rate.jsx'; -import { mockStore, StoreProvider } from '@deriv/stores'; -import { APIProvider } from '@deriv/api'; - -const wrapper = ({ children }) => ( - - {children} - -); - -describe('FloatingRate component', () => { - it('should render default state of the component with hint message and increment, decrement buttons', () => { - render(, { wrapper }); - expect(screen.getByText('of the market rate')).toBeInTheDocument(); - expect(screen.getAllByRole('button')).toHaveLength(2); - }); - - it('should display error messages when error is passed as props', () => { - render(, { wrapper }); - expect(screen.getByText('Floating rate error')).toBeInTheDocument(); - }); - - it('should render market rate feed based on the floating rate value passed', () => { - render(, { wrapper }); - expect(screen.getByText('Your rate is = 1.02')).toBeInTheDocument(); - }); - - it('should render the exchange rate in hint', () => { - render(, { wrapper }); - expect(screen.getByText('1 AED = 1.00')).toBeInTheDocument(); - }); -}); diff --git a/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.tsx b/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.tsx new file mode 100644 index 000000000000..388053116f15 --- /dev/null +++ b/packages/p2p/src/components/floating-rate/__test__/floating-rate.spec.tsx @@ -0,0 +1,72 @@ +import React from 'react'; +import { render, screen, fireEvent } from '@testing-library/react'; +import { mockStore, StoreProvider } from '@deriv/stores'; +import FloatingRate from '../floating-rate'; +import { APIProvider } from '@deriv/api'; + +const wrapper = ({ children }) => ( + + {children} + +); + +describe('', () => { + const floating_rate_props = { + change_handler: jest.fn(), + className: 'floating-rate', + data_testid: 'dt_floating_rate', + error_messages: '', + fiat_currency: 'AED', + local_currency: 'INR', + onChange: jest.fn(), + offset: {}, + }; + + it('should render default state of the component with hint message and increment, decrement buttons', () => { + render(, { wrapper }); + + expect(screen.getByText('of the market rate')).toBeInTheDocument(); + expect(screen.getAllByRole('button')).toHaveLength(2); + }); + + it('should display error messages when error is passed as props', () => { + render(, { wrapper }); + + expect(screen.getByText('Floating rate error')).toBeInTheDocument(); + }); + + it('should render market rate feed based on the floating rate value passed', () => { + render(, { wrapper }); + + expect(screen.getByText('Your rate is = 1.02 INR')).toBeInTheDocument(); + }); + + it('should render the exchange rate in hint', () => { + render(, { wrapper }); + + expect(screen.getByText('1 AED = 1.00')).toBeInTheDocument(); + }); + + it('should call onChange with the modified event object on blur', () => { + const onChangeMock = jest.fn(); + render(, { wrapper }); + + // Case 1: Value meets conditions with '+' symbol + const inputElement = screen.getByLabelText('Floating rate'); + inputElement.value = '10'; + fireEvent.blur(inputElement); + + expect(onChangeMock).toHaveBeenCalledTimes(1); + expect(onChangeMock).toHaveBeenCalledWith( + expect.objectContaining({ target: expect.objectContaining({ value: '+10.00' }) }) + ); + + // Case 2: Value does not meet conditions without '+' symbol + inputElement.value = '-5'; + fireEvent.blur(inputElement); + expect(onChangeMock).toHaveBeenCalledTimes(2); + expect(onChangeMock).toHaveBeenCalledWith( + expect.objectContaining({ target: expect.objectContaining({ value: '-5.00' }) }) + ); + }); +}); diff --git a/packages/p2p/src/components/floating-rate/floating-rate.scss b/packages/p2p/src/components/floating-rate/floating-rate.scss index dc25ed21dbdb..7914fe2a684f 100644 --- a/packages/p2p/src/components/floating-rate/floating-rate.scss +++ b/packages/p2p/src/components/floating-rate/floating-rate.scss @@ -218,3 +218,9 @@ button.dc-input-wrapper__button { display: flex; flex-direction: column; } + +.my-ads__form-field { + @include mobile { + height: auto !important; + } +} diff --git a/packages/p2p/src/components/floating-rate/floating-rate.jsx b/packages/p2p/src/components/floating-rate/floating-rate.tsx similarity index 72% rename from packages/p2p/src/components/floating-rate/floating-rate.jsx rename to packages/p2p/src/components/floating-rate/floating-rate.tsx index 014199af302a..758d1b615491 100644 --- a/packages/p2p/src/components/floating-rate/floating-rate.jsx +++ b/packages/p2p/src/components/floating-rate/floating-rate.tsx @@ -1,25 +1,39 @@ import React from 'react'; import classNames from 'classnames'; -import PropTypes from 'prop-types'; +import { setDecimalPlaces, removeTrailingZeros, percentOf, roundOffDecimal } from 'Utils/format-value'; import { InputField, Text } from '@deriv/components'; +import { useExchangeRate, useP2PConfig } from '@deriv/hooks'; import { formatMoney, isMobile, mobileOSDetect } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; -import { useExchangeRate, useP2PConfig } from '@deriv/hooks'; import { localize } from 'Components/i18next'; -import { setDecimalPlaces, removeTrailingZeros, percentOf, roundOffDecimal } from 'Utils/format-value'; -import './floating-rate.scss'; + +type TFloatingRate = { + change_handler?: () => void; + className?: string; + data_testid: string; + error_messages: string; + fiat_currency: string; + local_currency: string; + name?: string; + offset: object; + onChange: (event: React.ChangeEvent) => void; + required?: boolean; + value?: string; +}; const FloatingRate = ({ change_handler, className, + data_testid, error_messages, fiat_currency, local_currency, - onChange, + name, offset, - data_testid, - ...props -}) => { + onChange, + required, + value, +}: TFloatingRate) => { const { ui: { current_focus, setCurrentFocus }, } = useStore(); @@ -29,28 +43,28 @@ const FloatingRate = ({ const override_exchange_rate = p2p_config?.override_exchange_rate; const market_rate = override_exchange_rate ? Number(override_exchange_rate) : getRate(local_currency); const os = mobileOSDetect(); - const { name, value, required } = props; const market_feed = value ? percentOf(market_rate, value) : market_rate; const decimal_place = setDecimalPlaces(market_feed, 6); // Input mask for formatting value on blur of floating rate field - const onBlurHandler = e => { - let float_rate = e.target.value; - if (!isNaN(float_rate) && float_rate.trim().length) { + const onBlurHandler = (event: React.FocusEvent) => { + let float_rate = event.target.value; + if (!isNaN(parseFloat(float_rate)) && float_rate.trim().length) { float_rate = parseFloat(float_rate).toFixed(2); - if (/^\d+/.test(float_rate) && float_rate > 0) { + if (/^\d+/.test(float_rate) && parseFloat(float_rate) > 0) { // Assign + symbol for positive rate - e.target.value = `+${float_rate}`; + event.target.value = `+${float_rate}`; } else { - e.target.value = float_rate; + event.target.value = float_rate; } } - onChange(e); + onChange(event); }; + return (
- + {localize('at')}
{localize('of the market rate')} 1 {fiat_currency} = {removeTrailingZeros(formatMoney(local_currency, market_rate, true, 6))}
{error_messages ? ( - + {error_messages} ) : ( - + {localize('Your rate is')} ={' '} {removeTrailingZeros( formatMoney(local_currency, roundOffDecimal(market_feed, decimal_place), true, decimal_place) @@ -133,18 +131,4 @@ const FloatingRate = ({ ); }; -FloatingRate.propTypes = { - change_handler: PropTypes.func, - className: PropTypes.string, - data_testid: PropTypes.string, - error_messages: PropTypes.string, - fiat_currency: PropTypes.string, - local_currency: PropTypes.string, - name: PropTypes.string, - onChange: PropTypes.func, - offset: PropTypes.object, - required: PropTypes.bool, - value: PropTypes.string, -}; - export default observer(FloatingRate); diff --git a/packages/p2p/src/components/floating-rate/index.js b/packages/p2p/src/components/floating-rate/index.ts similarity index 55% rename from packages/p2p/src/components/floating-rate/index.js rename to packages/p2p/src/components/floating-rate/index.ts index d7cee0ed00de..96b1646b507f 100644 --- a/packages/p2p/src/components/floating-rate/index.js +++ b/packages/p2p/src/components/floating-rate/index.ts @@ -1,4 +1,4 @@ -import FloatingRate from './floating-rate.jsx'; +import FloatingRate from './floating-rate'; import './floating-rate.scss'; export default FloatingRate; diff --git a/packages/p2p/src/components/form/error.jsx b/packages/p2p/src/components/form/error.jsx deleted file mode 100644 index e794e19432a0..000000000000 --- a/packages/p2p/src/components/form/error.jsx +++ /dev/null @@ -1,16 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import './form.scss'; -import { Text } from '@deriv/components'; - -const FormSubmitErrorMessage = ({ message }) => ( - - {message} - -); - -FormSubmitErrorMessage.propTypes = { - message: PropTypes.string, -}; - -export default FormSubmitErrorMessage; diff --git a/packages/p2p/src/components/form/form.scss b/packages/p2p/src/components/form/form.scss deleted file mode 100644 index 1902ccded764..000000000000 --- a/packages/p2p/src/components/form/form.scss +++ /dev/null @@ -1,4 +0,0 @@ -.dp2p-form-error { - margin-right: auto; - padding-right: 0.8rem; -} diff --git a/packages/p2p/src/components/i18next/index.js b/packages/p2p/src/components/i18next/index.ts similarity index 89% rename from packages/p2p/src/components/i18next/index.js rename to packages/p2p/src/components/i18next/index.ts index 124a68abb48c..53b0bcdd5eb2 100644 --- a/packages/p2p/src/components/i18next/index.js +++ b/packages/p2p/src/components/i18next/index.ts @@ -21,7 +21,7 @@ import zh_tw from 'Translations/zh_tw.json'; const DEFAULT_LANGUAGE = 'EN'; let CURRENT_LANGUAGE = 'EN'; -export const setLanguage = lang => { +export const setLanguage = (lang: string) => { CURRENT_LANGUAGE = lang || DEFAULT_LANGUAGE; i18n.changeLanguage(lang); }; @@ -48,7 +48,7 @@ const i18n_config = { ZH_TW: { translations: { ...zh_tw } }, }, react: { - hashTransKey(defaultValue) { + hashTransKey(defaultValue: string) { return crc32(defaultValue); }, }, @@ -64,9 +64,9 @@ i18n.use(initReactI18next) // passes i18n down to react-i18next // component wrapped with i18n export const Localize = withI18n(i18n); -export const localize = (string, values) => { +export const localize = (string: string, values?: T) => { if (!string) return ''; - return i18n.t(crc32(string), { defaultValue: string, ...values }); + return i18n.t(crc32(string).toString(), { defaultValue: string, ...values }); }; export default i18n; diff --git a/packages/p2p/src/components/misc/__test__/animation-wrapper.spec.js b/packages/p2p/src/components/misc/__test__/animation-wrapper.spec.js deleted file mode 100644 index 029fb2b7dd54..000000000000 --- a/packages/p2p/src/components/misc/__test__/animation-wrapper.spec.js +++ /dev/null @@ -1,39 +0,0 @@ -import React from 'react'; -import { isMobile } from '@deriv/shared'; -import { render, screen } from '@testing-library/react'; -import AnimationWrapper from '../animation-wrapper.jsx'; - -jest.mock('react-transition-group', () => ({ - ...jest.requireActual('react-transition-group'), - CSSTransition: jest.fn(({ children }) =>
{children}
), -})); - -jest.mock('@deriv/shared', () => ({ - ...jest.requireActual('@deriv/shared'), - isMobile: jest.fn().mockReturnValue(false), -})); - -describe('', () => { - it('renders the children component in desktop view', () => { - render( - -
Desktop View
-
- ); - - expect(screen.queryByTestId('css-transition')).not.toBeInTheDocument(); - expect(screen.getByText('Desktop View')).toBeInTheDocument(); - }); - - it('renders the children component in desktop view', () => { - isMobile.mockReturnValue(true); - render( - -
Mobile View
-
- ); - - expect(screen.queryByTestId('css-transition')).toBeInTheDocument(); - expect(screen.getByText('Mobile View')).toBeInTheDocument(); - }); -}); diff --git a/packages/p2p/src/components/misc/animation-wrapper.jsx b/packages/p2p/src/components/misc/animation-wrapper.jsx deleted file mode 100644 index 81deb85c6c89..000000000000 --- a/packages/p2p/src/components/misc/animation-wrapper.jsx +++ /dev/null @@ -1,32 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { CSSTransition } from 'react-transition-group'; -import { isMobile } from '@deriv/shared'; -import './animation-wrapper.scss'; - -const AnimationWrapper = ({ children, is_visible, onEntered, onExit }) => { - if (isMobile()) { - return ( - - {children} - - ); - } - - return children; -}; - -AnimationWrapper.propTypes = { - children: PropTypes.any, - is_visible: PropTypes.bool, - onEntered: PropTypes.func, - onExit: PropTypes.func, -}; - -export default AnimationWrapper; diff --git a/packages/p2p/src/components/misc/animation-wrapper.scss b/packages/p2p/src/components/misc/animation-wrapper.scss deleted file mode 100644 index 7c59a96e8378..000000000000 --- a/packages/p2p/src/components/misc/animation-wrapper.scss +++ /dev/null @@ -1,22 +0,0 @@ -.animation-wrapper { - &-enter { - transform: scale3d(1, 0, 1); - opacity: 0; - - &-done { - transform: scale3d(1, 1, 1); - opacity: 1; - } - } - &-exit { - transform: scale3d(1, 1, 1); - opacity: 1; - - &-done { - display: none; - transform: scale3d(1, 0, 1); - opacity: 0; - height: 0px; - } - } -} diff --git a/packages/p2p/src/components/misc/toggle-container.jsx b/packages/p2p/src/components/misc/toggle-container.jsx deleted file mode 100644 index 60339d157963..000000000000 --- a/packages/p2p/src/components/misc/toggle-container.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import PropTypes from 'prop-types'; -import React from 'react'; -import './toggle-container.scss'; - -const ToggleContainer = ({ children }) =>
{children}
; - -ToggleContainer.propTypes = { - children: PropTypes.any, -}; - -export default ToggleContainer; diff --git a/packages/p2p/src/components/modal-manager/modals/ad-error-tooltip-modal/ad-error-tooltip-modal.jsx b/packages/p2p/src/components/modal-manager/modals/ad-error-tooltip-modal/ad-error-tooltip-modal.jsx index 48389602f2af..9e71ff900f40 100644 --- a/packages/p2p/src/components/modal-manager/modals/ad-error-tooltip-modal/ad-error-tooltip-modal.jsx +++ b/packages/p2p/src/components/modal-manager/modals/ad-error-tooltip-modal/ad-error-tooltip-modal.jsx @@ -10,7 +10,7 @@ const AdErrorTooltipModal = () => { const { hideModal, is_modal_open } = useModalManagerContext(); return ( - + { if (error_code === api_error_codes.AD_EXCEEDS_BALANCE) { return ( { } else if (error_code === api_error_codes.AD_EXCEEDS_DAILY_LIMIT) { return ( { } return ( + {is_advertiser_blocked ? ( ( -
+
@@ -49,7 +49,7 @@ const BuySellModalFooter = ({ onCancel, is_submit_disabled, onSubmit }) => { className={ my_profile_store.should_show_add_payment_method_form ? 'add-payment-method__footer' - : 'buy-sell__modal-footer' + : 'buy-sell-modal__footer' } > @@ -94,7 +94,7 @@ const BuySellModalTitle = () => { my_profile_store.setShouldShowAddPaymentMethodForm(false); } }} - className='buy-sell__modal-icon' + className='buy-sell-modal__icon' /> {localize('Add payment method')} @@ -115,7 +115,6 @@ const BuySellModal = () => { const [is_submit_disabled, setIsSubmitDisabled] = useSafeState(true); const [is_account_balance_low, setIsAccountBalanceLow] = React.useState(false); const [has_rate_changed_recently, setHasRateChangedRecently] = React.useState(false); - const MAX_ALLOWED_RATE_CHANGED_WARNING_DELAY = 2000; const { hideModal, is_modal_open, showModal } = useModalManagerContext(); const history = useHistory(); const location = useLocation(); @@ -130,9 +129,6 @@ const BuySellModal = () => { const is_the_same_advert = previous_advert?.id === new_advert.id; if (rate_has_changed && is_the_same_advert) { setHasRateChangedRecently(true); - setTimeout(() => { - setHasRateChangedRecently(false); - }, MAX_ALLOWED_RATE_CHANGED_WARNING_DELAY); } } ); @@ -167,14 +163,15 @@ const BuySellModal = () => { } else { showModal({ key: 'MarketRateChangeErrorModal' }); } + setHasRateChangedRecently(false); }; const BuySellFormError = () => { if (!!error_message && buy_sell_store.form_error_code !== api_error_codes.ORDER_CREATE_FAIL_RATE_CHANGED) { return ( -
+
@@ -205,6 +202,7 @@ const BuySellModal = () => { } else { hideModal(); buy_sell_store.fetchAdvertiserAdverts(); + buy_sell_store.unsubscribeAdvertInfo(); } }; @@ -249,12 +247,12 @@ const BuySellModal = () => { } pageHeaderReturnFn={onCancel} > @@ -280,7 +278,7 @@ const BuySellModal = () => { )} @@ -288,8 +286,8 @@ const BuySellModal = () => { { - + {buy_sell_store.table_type === buy_sell.SELL && is_account_balance_low && ( )} diff --git a/packages/p2p/src/components/modal-manager/modals/buy-sell-modal/buy-sell-modal.scss b/packages/p2p/src/components/modal-manager/modals/buy-sell-modal/buy-sell-modal.scss index 12455d7c2648..6b1b5c0020b0 100644 --- a/packages/p2p/src/components/modal-manager/modals/buy-sell-modal/buy-sell-modal.scss +++ b/packages/p2p/src/components/modal-manager/modals/buy-sell-modal/buy-sell-modal.scss @@ -1,4 +1,4 @@ -.buy-sell__modal { +.buy-sell-modal { opacity: 1 !important; @include mobile { @@ -7,7 +7,7 @@ } } - &-body { + &__body { position: relative; display: block; padding-top: 2.4rem; @@ -19,10 +19,19 @@ } } - &-danger { - margin-bottom: 1.6rem; - width: fit-content; - align-items: flex-start; + &__footer { + @include mobile { + border-top: 2px solid var(--general-section-1); + display: flex; + flex-direction: row; + justify-content: flex-end; + margin-top: auto; + padding: 1.6rem; + } + } + + &__layout { + padding: unset; } &-field { @@ -80,50 +89,10 @@ } } - &-form { + &__form { height: fit-content !important; } - &-footer { - @include mobile { - border-top: 2px solid var(--general-section-1); - display: flex; - flex-direction: row; - justify-content: flex-end; - margin-top: auto; - padding: 1.6rem; - } - } - - &--input { - display: flex; - gap: 2rem; - flex-direction: column; - padding: 0 2.4rem 2rem; - margin-bottom: 2rem; - .dc-input__wrapper { - margin-right: 0.2rem; - margin-bottom: unset; - } - - &-field { - @include desktop() { - display: flex; - } - } - @include mobile { - .dc-input { - &__container { - width: 100%; - padding: 0.5rem 1rem 0.5rem 1.2rem; - } - &__wrapper { - margin: 0.8rem 0.2rem 1.4rem 0; - } - } - } - } - &-hintbox { margin: -0.5rem 0 2.4rem; padding: 0 2.4rem; @@ -135,7 +104,7 @@ } } - &-icon { + &__icon { margin-right: 0.8rem; } @@ -172,11 +141,38 @@ } } - &-receive-amount { + &--danger { + margin-bottom: 1.6rem; + width: fit-content; + align-items: flex-start; + } + + &--input { + display: flex; + gap: 2rem; + flex-direction: column; + padding: 0 2.4rem 2rem; + margin-bottom: 2rem; + .dc-input__wrapper { + margin-right: 0.2rem; + margin-bottom: unset; + } + + &-field { + @include desktop { + display: flex; + } + } @include mobile { - border-top: 1px solid var(--general-section-2); - padding: 0.8rem 1.6rem; - background-color: var(--general-main-1); + .dc-input { + &__container { + width: 100%; + padding: 0.5rem 1rem 0.5rem 1.2rem; + } + &__wrapper { + margin: 0.8rem 0.2rem 1.4rem 0; + } + } } } @@ -217,22 +213,18 @@ } } - &--layout { - padding: unset; - } - &--error-message { padding: 0 2.4rem; } } -.buy-sell__modal-content { +.buy-sell-modal__content { .dc-input { margin-bottom: unset; } } -.dc-modal__container_buy-sell__modal { - .dc-modal-header--buy-sell__modal { +.dc-modal__container_buy-sell-modal { + .dc-modal-header--buy-sell-modal { border-bottom: 2px solid var(--general-section-5); } diff --git a/packages/p2p/src/components/modal-manager/modals/cancel-add-payment-method-modal.jsx b/packages/p2p/src/components/modal-manager/modals/cancel-add-payment-method-modal.jsx index fe6a34351d6e..807d7004f4ad 100644 --- a/packages/p2p/src/components/modal-manager/modals/cancel-add-payment-method-modal.jsx +++ b/packages/p2p/src/components/modal-manager/modals/cancel-add-payment-method-modal.jsx @@ -15,7 +15,7 @@ const CancelAddPaymentMethodModal = ({ onCancel, should_hide_all_modals_on_cance is_open={is_modal_open} small title={ - + } diff --git a/packages/p2p/src/components/modal-manager/modals/cancel-edit-payment-method-modal.jsx b/packages/p2p/src/components/modal-manager/modals/cancel-edit-payment-method-modal.jsx index b115ec8b4de0..ff86b1fe2a48 100644 --- a/packages/p2p/src/components/modal-manager/modals/cancel-edit-payment-method-modal.jsx +++ b/packages/p2p/src/components/modal-manager/modals/cancel-edit-payment-method-modal.jsx @@ -15,7 +15,7 @@ const CancelEditPaymentMethodModal = () => { is_open={is_modal_open} small title={ - + } diff --git a/packages/p2p/src/components/modal-manager/modals/create-ad-add-payment-method-modal/create-ad-add-payment-method-modal.jsx b/packages/p2p/src/components/modal-manager/modals/create-ad-add-payment-method-modal/create-ad-add-payment-method-modal.jsx index 3a76fa98060b..1c4db07c3972 100644 --- a/packages/p2p/src/components/modal-manager/modals/create-ad-add-payment-method-modal/create-ad-add-payment-method-modal.jsx +++ b/packages/p2p/src/components/modal-manager/modals/create-ad-add-payment-method-modal/create-ad-add-payment-method-modal.jsx @@ -5,7 +5,7 @@ import { Button, Icon, MobileFullPageModal, Modal } from '@deriv/components'; import { isMobile } from '@deriv/shared'; import { useStores } from 'Stores'; import { localize, Localize } from 'Components/i18next'; -import AddPaymentMethod from 'Components/my-profile/payment-methods/add-payment-method/add-payment-method.jsx'; +import AddPaymentMethod from 'Pages/my-profile/payment-methods/add-payment-method/add-payment-method.jsx'; import { useModalManagerContext } from 'Components/modal-manager/modal-manager-context'; const CreateAdAddPaymentMethodModal = () => { @@ -30,8 +30,8 @@ const CreateAdAddPaymentMethodModal = () => { if (isMobile()) { return ( { return ( - + {localize('Add payment method')} } toggleModal={onCancel} > diff --git a/packages/p2p/src/components/modal-manager/modals/create-ad-add-payment-method-modal/create-ad-add-payment-method-modal.scss b/packages/p2p/src/components/modal-manager/modals/create-ad-add-payment-method-modal/create-ad-add-payment-method-modal.scss index 075e8349b7ae..d3d30aa3e9d8 100644 --- a/packages/p2p/src/components/modal-manager/modals/create-ad-add-payment-method-modal/create-ad-add-payment-method-modal.scss +++ b/packages/p2p/src/components/modal-manager/modals/create-ad-add-payment-method-modal/create-ad-add-payment-method-modal.scss @@ -1,61 +1,44 @@ -.p2p-my-ads { - flex: 1; - display: flex; - flex-direction: column; - - @include mobile { - .page-return { - border-bottom: 2px solid var(--general-section-1); - margin: 1rem 0; - padding: 0 1.6rem 1.6rem; +.create-ad-add-payment-method-modal { + &__body { + display: flex; + flex-direction: column; + padding: 1rem 1.6rem 0; + width: 100vw; + + &--form { + padding: 1rem 0 0; } - .dc-list { - margin-left: 1vw; - width: 88vw; - - &__item { - padding-top: 0.4rem; - } + &--scroll { + overflow: auto; + padding: 0; } - .dc-mobile-full-page-modal { - opacity: 1 !important; + + &--horizontal { + padding-right: 0rem; } } - &__modal { - &-body { - display: flex; - flex-direction: column; - padding: 1rem 1.6rem 0; - width: 100vw; - - &--scroll { - overflow: auto; - } - - &--horizontal { - padding-right: 0rem; - } + &__error { + &--form { + height: fit-content !important; } - &-error { - .dc-modal-header__title--p2p-my-ads__modal-error { - padding: 2.4rem 2.4rem 0 !important; + .dc-modal-header__title--create-ad-add-payment-method-modal__error { + padding: 2.4rem 2.4rem 0 !important; + } + .dc-modal__container_create-ad-add-payment-method-modal__error { + .dc-modal-footer { + padding-top: 0 !important; } - .dc-modal__container_p2p-my-ads__modal-error { - .dc-modal-footer { - padding-top: 0 !important; - } - .dc-modal-header { - padding-bottom: 1rem; - } + .dc-modal-header { + padding-bottom: 1rem; } } + } - &-icon { - margin-right: 0.8rem; - } + &__icon { + margin-right: 0.8rem; } } diff --git a/packages/p2p/src/components/modal-manager/modals/create-ad-error-modal/create-ad-error-modal.jsx b/packages/p2p/src/components/modal-manager/modals/create-ad-error-modal/create-ad-error-modal.jsx index beeab340f29a..34f5fa2ba310 100644 --- a/packages/p2p/src/components/modal-manager/modals/create-ad-error-modal/create-ad-error-modal.jsx +++ b/packages/p2p/src/components/modal-manager/modals/create-ad-error-modal/create-ad-error-modal.jsx @@ -13,7 +13,7 @@ const CreateAdErrorModal = () => { if (my_ads_store.error_code === api_error_codes.DUPLICATE_ADVERT) { return ( { } else if (my_ads_store.error_code === api_error_codes.ADVERT_SAME_LIMITS) { return ( { } return ( { diff --git a/packages/p2p/src/components/modal-manager/modals/currency-selector-modal/index.js b/packages/p2p/src/components/modal-manager/modals/currency-selector-modal/index.js index 2d7fe249df99..35b8ffe3fbac 100644 --- a/packages/p2p/src/components/modal-manager/modals/currency-selector-modal/index.js +++ b/packages/p2p/src/components/modal-manager/modals/currency-selector-modal/index.js @@ -1,4 +1,3 @@ import CurrencySelectorModal from './currency-selector-modal'; -import './currency-selector.scss'; export default CurrencySelectorModal; diff --git a/packages/p2p/src/components/modal-manager/modals/email-link-blocked-modal/email-link-blocked-modal.jsx b/packages/p2p/src/components/modal-manager/modals/email-link-blocked-modal/email-link-blocked-modal.jsx index 9fd9c5d60f3c..04e90769bcbd 100644 --- a/packages/p2p/src/components/modal-manager/modals/email-link-blocked-modal/email-link-blocked-modal.jsx +++ b/packages/p2p/src/components/modal-manager/modals/email-link-blocked-modal/email-link-blocked-modal.jsx @@ -15,10 +15,10 @@ const EmailLinkBlockedModal = ({ <>} toggleModal={hideModal} width='440px'> - + - + {email_link_blocked_modal_error_message} diff --git a/packages/p2p/src/components/modal-manager/modals/email-link-blocked-modal/email-link-blocked-modal.scss b/packages/p2p/src/components/modal-manager/modals/email-link-blocked-modal/email-link-blocked-modal.scss index 975c829f0532..99620511e999 100644 --- a/packages/p2p/src/components/modal-manager/modals/email-link-blocked-modal/email-link-blocked-modal.scss +++ b/packages/p2p/src/components/modal-manager/modals/email-link-blocked-modal/email-link-blocked-modal.scss @@ -3,7 +3,7 @@ display: flex; flex-direction: column; - &--text { + &__text { margin: 2.4rem 0; } } diff --git a/packages/p2p/src/components/modal-manager/modals/email-link-expired-modal/email-link-expired-modal.jsx b/packages/p2p/src/components/modal-manager/modals/email-link-expired-modal/email-link-expired-modal.jsx index e68008827e7c..26479900f86e 100644 --- a/packages/p2p/src/components/modal-manager/modals/email-link-expired-modal/email-link-expired-modal.jsx +++ b/packages/p2p/src/components/modal-manager/modals/email-link-expired-modal/email-link-expired-modal.jsx @@ -23,13 +23,13 @@ const EmailLinkExpiredModal = () => { toggleModal={() => hideModal({ should_hide_all_modals: true })} width='440px' > - + - + - + diff --git a/packages/p2p/src/components/modal-manager/modals/email-link-expired-modal/email-link-expired-modal.scss b/packages/p2p/src/components/modal-manager/modals/email-link-expired-modal/email-link-expired-modal.scss index 6529d9c0022b..dd3d45cf1813 100644 --- a/packages/p2p/src/components/modal-manager/modals/email-link-expired-modal/email-link-expired-modal.scss +++ b/packages/p2p/src/components/modal-manager/modals/email-link-expired-modal/email-link-expired-modal.scss @@ -1,17 +1,17 @@ .email-link-expired-modal { - &--body { + &__body { display: flex; flex-direction: column; align-items: center; } - &--footer { + &__footer { display: flex; flex-direction: column; align-items: center; } - &--text { + &__text { margin-top: 2.4rem; } } diff --git a/packages/p2p/src/components/modal-manager/modals/email-link-verified-modal/email-link-verified-modal.jsx b/packages/p2p/src/components/modal-manager/modals/email-link-verified-modal/email-link-verified-modal.jsx index 5793e6c0d96d..3e4bb4e95fb4 100644 --- a/packages/p2p/src/components/modal-manager/modals/email-link-verified-modal/email-link-verified-modal.jsx +++ b/packages/p2p/src/components/modal-manager/modals/email-link-verified-modal/email-link-verified-modal.jsx @@ -26,17 +26,17 @@ const EmailLinkVerifiedModal = () => { > - + - + - + - - - ); -}); - -const InputComponent = observer(({ field }) => { - const { general_store } = useStores(); - const { errors, handleChange } = useFormikContext(); - - return ( - { - handleChange(e); - general_store.setNicknameError(undefined); - }} - required - /> - ); -}); - -const NicknameForm = () => { - const { general_store } = useStores(); - - const closeForm = () => { - general_store.setShouldShowPopup(false); - }; - - // TODO: move it to hook when this component will be changed as part of refactoring. - React.useEffect(() => { - window.addEventListener('popstate', closeForm); - return () => { - window.removeEventListener('popstate', closeForm); - }; - }, [closeForm]); - - return ( - - {!isMobile() && ( -
-
- -
-
- )} - { - await general_store.createAdvertiser(values.nickname); - }} - > -
-
- - - {localize('Choose a nickname')} - - - {localize('You will appear to other users as')} - -
- - {({ field }) => { - return ; - }} - -
-
- {localize('Once set, your nickname cannot be changed.')} -
-
-
- -
-
-
-
- ); -}; - -export default observer(NicknameForm); diff --git a/packages/p2p/src/components/nickname-form/nickname-form.scss b/packages/p2p/src/components/nickname-form/nickname-form.scss index 5d8308cb8bb2..74f7bcf06d44 100644 --- a/packages/p2p/src/components/nickname-form/nickname-form.scss +++ b/packages/p2p/src/components/nickname-form/nickname-form.scss @@ -1,32 +1,5 @@ -.dp2p-nickname__form { - &-header { - border-bottom: 1px solid var(--general-section-2); - - &_wrapper { - padding: 1.6rem 2.4rem; - display: flex; - align-items: center; - width: 100%; - justify-content: space-between; - box-sizing: border-box; - } - &_right { - justify-content: flex-end; - padding: 2.8rem 2.4rem 0; - } - &--title { - font-weight: bold; - color: var(--text-prominent); - - &:first-letter { - text-transform: uppercase; - } - } - &--no-border { - border: none; - } - } - &-content { +.nickname-form { + &__content { &__centre { align-items: center; display: flex; @@ -39,30 +12,21 @@ &--title { margin: 1.4rem 0; } + &--text { margin-bottom: 1.6rem; } - &--list { - color: var(--text-general); - font-size: var(--text-size-xs); - line-height: 1.43; - & li { - list-style-type: disc; - margin: 0.8rem 1.8rem 0; - } - } &--ps { - color: var(--text-general); padding-top: 0.5rem; margin: 1.6rem 0; - font-size: var(--text-size-xs); align-self: flex-start; width: 100%; text-align: center; } } - &-field { + + &__field { flex: 1; height: 4rem; margin-bottom: unset; @@ -86,51 +50,13 @@ margin-left: 3.9rem; } } - &--textarea { - margin-top: 4.3rem; - - .dc-input__hint { - top: 9.7rem; - } - .dc-input__counter { - right: 0rem; - top: 9.7rem; - } - } - &--icon { - margin: 0 1.6rem; - transform: rotate(180deg); - width: 3.66rem; - } - &--trailing { - color: var(--text-less-prominent); - font-size: var(--text-size-xxs); - } @include mobile { width: 88%; } } - &-info { - margin-bottom: 1.6rem; - &_notes { - margin-bottom: 2rem; - } - &--title { - color: var(--text-less-prominent); - font-size: var(--text-size-xxs); - } - &--text { - color: var(--text-general); - font-size: var(--text-size-xs); - word-break: break-word; - } - &--strong { - font-weight: bold; - } - } - &-footer { + &__footer { align-items: center; bottom: 0; display: flex; @@ -143,13 +69,4 @@ padding: 1.6rem; } } - &-close_icon { - cursor: pointer; - fill: var(--text-general); - } - &-wrapper { - @include mobile { - height: 100%; - } - } } diff --git a/packages/p2p/src/components/nickname-form/nickname-form.tsx b/packages/p2p/src/components/nickname-form/nickname-form.tsx new file mode 100644 index 000000000000..52bef2e2e682 --- /dev/null +++ b/packages/p2p/src/components/nickname-form/nickname-form.tsx @@ -0,0 +1,107 @@ +import React from 'react'; +import { Formik, Field, FieldProps, Form } from 'formik'; +import { observer } from 'mobx-react-lite'; +import { Button, Input, Icon, Text } from '@deriv/components'; +import { localize } from 'Components/i18next'; +import { useStores } from 'Stores'; +import './nickname-form.scss'; + +type TNicknameFormProps = { + onCancel?: () => void; +}; + +const NicknameForm = ({ onCancel }: TNicknameFormProps) => { + const { general_store } = useStores(); + + // TODO: move it to hook when this component will be changed as part of refactoring. + React.useEffect(() => { + const closeForm = () => { + general_store.setShouldShowPopup(false); + }; + + window.addEventListener('popstate', closeForm); + return () => { + window.removeEventListener('popstate', closeForm); + }; + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + { + await general_store.createAdvertiser(values.nickname); + }} + > + {({ errors, handleChange, isSubmitting, values }) => ( +
+
+ + + {localize('Choose a nickname')} + + + {localize('You will appear to other users as')} + +
+ + {({ field }: FieldProps) => ( + ) => { + handleChange(e); + general_store.setNicknameError(undefined); + }} + required + /> + )} + +
+ + {localize('Once set, your nickname cannot be changed.')} + +
+
+ + + + +
+
+ )} +
+ ); +}; + +export default observer(NicknameForm); diff --git a/packages/p2p/src/components/online-status/__tests__/online-status-avatar.spec.tsx b/packages/p2p/src/components/online-status/__tests__/online-status-avatar.spec.tsx new file mode 100644 index 000000000000..17464c3d0713 --- /dev/null +++ b/packages/p2p/src/components/online-status/__tests__/online-status-avatar.spec.tsx @@ -0,0 +1,17 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import OnlineStatusAvatar from '../online-status-avatar'; + +const props = { + is_online: 0, + nickname: 'test', + size: 40, + text_size: 'xs', +}; +describe('', () => { + it('should render shortened nickname as the avatar', () => { + render(); + + expect(screen.getByText('TE')).toBeInTheDocument(); + }); +}); diff --git a/packages/p2p/src/components/online-status/__tests__/online-status-icon.spec.tsx b/packages/p2p/src/components/online-status/__tests__/online-status-icon.spec.tsx new file mode 100644 index 000000000000..6e3d49ff66b7 --- /dev/null +++ b/packages/p2p/src/components/online-status/__tests__/online-status-icon.spec.tsx @@ -0,0 +1,19 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import OnlineStatusIcon from '../online-status-icon'; + +describe('', () => { + it('should render the default state as offline', () => { + render(); + + const icon = screen.getByTestId('dt_online_status_icon'); + expect(icon).toHaveClass('online-status__icon--offline'); + }); + + it('should render online state when user is online', () => { + render(); + + const icon = screen.getByTestId('dt_online_status_icon'); + expect(icon).toHaveClass('online-status__icon--online'); + }); +}); diff --git a/packages/p2p/src/components/online-status/__tests__/online-status-label.spec.tsx b/packages/p2p/src/components/online-status/__tests__/online-status-label.spec.tsx index fb9f74cf4768..4a227420ed22 100644 --- a/packages/p2p/src/components/online-status/__tests__/online-status-label.spec.tsx +++ b/packages/p2p/src/components/online-status/__tests__/online-status-label.spec.tsx @@ -1,15 +1,126 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import OnlineStatusLabel from '../online-status-label'; +import moment from 'moment'; +import 'moment/min/locales'; +import { isMobile, toMoment } from '@deriv/shared'; + +const props = { + is_online: 0, + last_online_time: 0, +}; + +let mock_value: moment.Moment = moment(); +jest.mock('@deriv/shared', () => ({ + ...jest.requireActual('@deriv/shared'), + toMoment: jest.fn(() => mock_value), + isMobile: jest.fn(() => false), +})); + +describe('', () => { + it('should render the component with default state', () => { + render(); + + expect(screen.getByText('Seen more than 6 months ago')).toBeInTheDocument(); + }); + it('should render component with default state in responsive view', () => { + (isMobile as jest.Mock).mockReturnValue(true); + render(); + + expect(screen.getByText('Seen more than 6 months ago')).toBeInTheDocument(); + }); + it('should show label "Online" when "last_online_time" is not being passed', () => { + const newprops = { ...props, is_online: 1 }; + render(); -describe('', () => { - it('should show online status label', () => { - render(); expect(screen.getByText('Online')).toBeInTheDocument(); }); + it('should show label "Seen 3 hours ago" when last seen is in hours', () => { + mock_value = moment('2023-05-30T18:48:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen 3 hours ago')).toBeInTheDocument(); + }); + it('should show label "Seen 1 hour ago" when user was last online 1 hour ago', () => { + mock_value = moment('2023-05-30T16:49:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen 1 hour ago')).toBeInTheDocument(); + }); + it('should show label "Seen 1 day ago" when user was last online 1 day ago', () => { + mock_value = moment('2023-05-31T16:49:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen 1 day ago')).toBeInTheDocument(); + }); + it('should show label "Seen 3 days ago" when last seen is in days', () => { + mock_value = moment('2023-06-02T16:49:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen 3 days ago')).toBeInTheDocument(); + }); + it('should show label "Seen more than 6 months ago" when last seen is in years', () => { + mock_value = moment('2025-06-02T16:49:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen more than 6 months ago')).toBeInTheDocument(); + }); + it('should show label "Seen 5 months ago" when last seen is in months', () => { + mock_value = moment('2023-11-02T16:49:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen 5 months ago')).toBeInTheDocument(); + }); + it('should show label "Seen more than 6 months ago" when user was last online more than 6 months ago', () => { + mock_value = moment('2024-01-02T16:49:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); - it(`should show user's last online status`, () => { - render(); expect(screen.getByText('Seen more than 6 months ago')).toBeInTheDocument(); }); + it('should show label "Seen 1 month ago" when user was last online 1 month ago', () => { + mock_value = moment('2023-07-02T16:49:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen 1 month ago')).toBeInTheDocument(); + }); + it('should show label "Seen 1 minute ago" when user was last online 1 minute ago', () => { + mock_value = moment('2023-05-30T15:41:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen 1 minute ago')).toBeInTheDocument(); + }); + it('should show label "Seen 2 minutes ago" when last seen is in minutes', () => { + mock_value = moment('2023-05-30T15:42:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Seen 2 minutes ago')).toBeInTheDocument(); + }); + it('should show label "Online" when last seen is in seconds', () => { + mock_value = moment('2023-05-30T15:40:38+04:00'); + (toMoment as jest.Mock).mockReturnValue(mock_value); + const newprops = { ...props, last_online_time: 1685446791 }; + render(); + + expect(screen.getByText('Online')).toBeInTheDocument(); + }); }); diff --git a/packages/p2p/src/components/online-status/index.js b/packages/p2p/src/components/online-status/index.ts similarity index 100% rename from packages/p2p/src/components/online-status/index.js rename to packages/p2p/src/components/online-status/index.ts diff --git a/packages/p2p/src/components/online-status/online-status-avatar.jsx b/packages/p2p/src/components/online-status/online-status-avatar.tsx similarity index 73% rename from packages/p2p/src/components/online-status/online-status-avatar.jsx rename to packages/p2p/src/components/online-status/online-status-avatar.tsx index 29ecd9796df2..3d1ea1628e4a 100644 --- a/packages/p2p/src/components/online-status/online-status-avatar.jsx +++ b/packages/p2p/src/components/online-status/online-status-avatar.tsx @@ -1,15 +1,20 @@ import React from 'react'; -import { Text } from '@deriv/components'; -import PropTypes from 'prop-types'; import { observer } from 'mobx-react-lite'; +import { Text } from '@deriv/components'; import { generateHexColourFromNickname, getShortNickname } from 'Utils/string'; import OnlineStatusIcon from './online-status-icon'; -import './online-status.scss'; -const OnlineStatusAvatar = ({ is_online, nickname, size, text_size }) => { +type TOnlineStatusAvatarProps = { + is_online: number | boolean; + nickname: string; + size: number; + text_size: string; +}; + +const OnlineStatusAvatar = ({ is_online, nickname, size, text_size }: TOnlineStatusAvatarProps) => { return (
- + {getShortNickname(nickname)} @@ -32,11 +37,4 @@ const OnlineStatusAvatar = ({ is_online, nickname, size, text_size }) => { ); }; -OnlineStatusAvatar.propTypes = { - is_online: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]).isRequired, - nickname: PropTypes.string.isRequired, - size: PropTypes.number, - text_size: PropTypes.string.isRequired, -}; - export default observer(OnlineStatusAvatar); diff --git a/packages/p2p/src/components/online-status/online-status-icon.jsx b/packages/p2p/src/components/online-status/online-status-icon.tsx similarity index 63% rename from packages/p2p/src/components/online-status/online-status-icon.jsx rename to packages/p2p/src/components/online-status/online-status-icon.tsx index db619491dc63..05afaf8ec8ce 100644 --- a/packages/p2p/src/components/online-status/online-status-icon.jsx +++ b/packages/p2p/src/components/online-status/online-status-icon.tsx @@ -1,11 +1,16 @@ import React from 'react'; import classNames from 'classnames'; -import PropTypes from 'prop-types'; import { observer } from 'mobx-react-lite'; -const OnlineStatusIcon = ({ is_online, size = '1em' }) => { +type TOnlineStatusIconProps = { + is_online: number | boolean; + size?: string | number; +}; + +const OnlineStatusIcon = ({ is_online, size = '1em' }: TOnlineStatusIconProps) => { return (
{ ); }; -OnlineStatusIcon.propTypes = { - is_online: PropTypes.oneOfType([PropTypes.number, PropTypes.bool]).isRequired, - size: PropTypes.oneOfType([PropTypes.number, PropTypes.string]), -}; - export default observer(OnlineStatusIcon); diff --git a/packages/p2p/src/components/online-status/online-status-label.jsx b/packages/p2p/src/components/online-status/online-status-label.jsx deleted file mode 100644 index 3911f0a8a1bf..000000000000 --- a/packages/p2p/src/components/online-status/online-status-label.jsx +++ /dev/null @@ -1,22 +0,0 @@ -import React from 'react'; -import { Text } from '@deriv/components'; -import { isMobile } from '@deriv/shared'; -import { getLastOnlineLabel } from 'Utils/adverts'; -import { observer } from 'mobx-react-lite'; -import PropTypes from 'prop-types'; - -const OnlineStatusLabel = ({ is_online, last_online_time, size = isMobile() ? 'xxxs' : 'xs' }) => { - return ( - - {getLastOnlineLabel(is_online, last_online_time)} - - ); -}; - -OnlineStatusLabel.propTypes = { - is_online: PropTypes.number.isRequired, - last_online_time: PropTypes.number, - size: PropTypes.string, -}; - -export default observer(OnlineStatusLabel); diff --git a/packages/p2p/src/components/online-status/online-status-label.tsx b/packages/p2p/src/components/online-status/online-status-label.tsx new file mode 100644 index 000000000000..b0754fa72fab --- /dev/null +++ b/packages/p2p/src/components/online-status/online-status-label.tsx @@ -0,0 +1,92 @@ +import React from 'react'; +import { observer } from 'mobx-react-lite'; +import { Duration } from 'moment'; +import { Text } from '@deriv/components'; +import { epochToMoment, getDiffDuration, isMobile, toMoment } from '@deriv/shared'; +import { localize } from 'Components/i18next'; + +type TOnlineStatusLabelProps = { + is_online: number; + last_online_time: number; + size?: string; +}; + +const OnlineStatusLabel = ({ + is_online, + last_online_time, + size = isMobile() ? 'xxxs' : 'xs', +}: TOnlineStatusLabelProps) => { + const getDifference = (last_seen_online: number) => { + const start_time = epochToMoment(last_seen_online).unix(); + const end_time = toMoment().unix(); + return getDiffDuration(start_time, end_time); + }; + + const getStatusLabel = (diff: Duration) => { + if (diff.years()) return localize('Seen more than 6 months ago'); + + if (diff.months()) { + if (diff.months() > 6) { + return localize('Seen more than 6 months ago'); + } + if (diff.months() === 1) { + return localize('Seen {{ duration }} month ago', { + duration: diff.months(), + }); + } + return localize('Seen {{ duration }} months ago', { + duration: diff.months(), + }); + } + if (diff.days()) { + if (diff.days() === 1) { + return localize('Seen {{ duration }} day ago', { + duration: diff.days(), + }); + } + return localize('Seen {{ duration }} days ago', { + duration: diff.days(), + }); + } + if (diff.hours()) { + if (diff.hours() === 1) { + return localize('Seen {{ duration }} hour ago', { + duration: diff.hours(), + }); + } + return localize('Seen {{ duration }} hours ago', { + duration: diff.hours(), + }); + } + if (diff.minutes()) { + if (diff.minutes() === 1) { + return localize('Seen {{ duration }} minute ago', { + duration: diff.minutes(), + }); + } + return localize('Seen {{ duration }} minutes ago', { + duration: diff.minutes(), + }); + } + return localize('Online'); + }; + + const last_online_label = () => { + if (!is_online) { + if (last_online_time) { + const diff = getDifference(last_online_time); + return getStatusLabel(diff); + } + return localize('Seen more than 6 months ago'); + } + return localize('Online'); + }; + + return ( + + {last_online_label()} + + ); +}; + +export default observer(OnlineStatusLabel); diff --git a/packages/p2p/src/components/online-status/online-status.scss b/packages/p2p/src/components/online-status/online-status.scss index 916d6a53fed4..1135cb8dd82a 100644 --- a/packages/p2p/src/components/online-status/online-status.scss +++ b/packages/p2p/src/components/online-status/online-status.scss @@ -2,7 +2,7 @@ &__icon { width: 1rem; height: 1rem; - margin: auto 0.5rem auto 0rem; + margin: auto 0.5rem auto 0; border-radius: 50%; @include mobile { @@ -13,6 +13,7 @@ &--online { background: var(--text-profit-success); } + &--offline { background: var(--checkbox-disabled-grey); } @@ -26,7 +27,7 @@ width: fit-content; height: fit-content; - &-text { + &__text { position: absolute; } diff --git a/packages/p2p/src/components/order-details/__test__/order-details-footer.spec.js b/packages/p2p/src/components/order-details/__test__/order-details-footer.spec.js index 63f605bc2590..2cf460dfab3d 100644 --- a/packages/p2p/src/components/order-details/__test__/order-details-footer.spec.js +++ b/packages/p2p/src/components/order-details/__test__/order-details-footer.spec.js @@ -3,7 +3,7 @@ import { useStores } from 'Stores'; import { fireEvent, render, screen } from '@testing-library/react'; import OrderDetailsFooter from '../order-details-footer.jsx'; -const mock_order_store = { +const mock_order_info = { is_buy_order: false, is_my_ad: false, is_sell_order: false, @@ -12,26 +12,31 @@ const mock_order_store = { should_show_only_received_button: false, should_show_only_complain_button: false, }; -const mockFn = jest.fn(); + +const mock_order_store = { + order_information: { ...mock_order_info }, + getAdvertiserInfo: jest.fn(), + getWebsiteStatus: jest.fn(), + confirmOrderRequest: jest.fn(), +}; jest.mock('Stores', () => ({ ...jest.requireActual('Stores'), useStores: jest.fn(() => ({ order_store: { - order_information: { ...mock_order_store }, - getAdvertiserInfo: jest.fn(() => mockFn()), - getWebsiteStatus: jest.fn(), + ...mock_order_store, }, })), })); const setShouldShowConfirmModalFn = jest.fn(); +const setShouldShowCancelOrderModalFn = jest.fn(); const setShouldShowComplainModalFn = jest.fn(); describe('', () => { it('Should show Cancel order and paid button', () => { useStores.mockImplementation(() => ({ order_store: { - order_information: { ...mock_order_store, should_show_cancel_and_paid_button: true }, - getAdvertiserInfo: jest.fn(() => mockFn()), + ...mock_order_store, + order_information: { ...mock_order_info, should_show_cancel_and_paid_button: true }, }, })); @@ -42,9 +47,10 @@ describe('', () => { }); it('cancel order when clicked', () => { + jest.spyOn(React, 'useState').mockImplementation(init => [init, setShouldShowCancelOrderModalFn]); render(); fireEvent.click(screen.getByRole('button', { name: 'Cancel order' })); - expect(mockFn).toBeCalled(); + expect(setShouldShowCancelOrderModalFn).toHaveBeenCalled(); }); it('should open confirm popup when clicked', () => { @@ -57,7 +63,8 @@ describe('', () => { it('should show complain and received button', () => { useStores.mockImplementation(() => ({ order_store: { - order_information: { ...mock_order_store, should_show_complain_and_received_button: true }, + ...mock_order_store, + order_information: { ...mock_order_info, should_show_complain_and_received_button: true }, }, })); render(); @@ -82,7 +89,8 @@ describe('', () => { it('should show compain button', () => { useStores.mockImplementation(() => ({ order_store: { - order_information: { ...mock_order_store, should_show_only_complain_button: true }, + ...mock_order_store, + order_information: { ...mock_order_info, should_show_only_complain_button: true }, }, })); render(); @@ -99,7 +107,8 @@ describe('', () => { it('should show only received button', () => { useStores.mockImplementation(() => ({ order_store: { - order_information: { ...mock_order_store, should_show_only_received_button: true }, + ...mock_order_store, + order_information: { ...mock_order_info, should_show_only_received_button: true }, }, })); render(); diff --git a/packages/p2p/src/components/order-details/__test__/order-details.spec.js b/packages/p2p/src/components/order-details/__test__/order-details.spec.js index fa2945933499..698b9960cf0c 100644 --- a/packages/p2p/src/components/order-details/__test__/order-details.spec.js +++ b/packages/p2p/src/components/order-details/__test__/order-details.spec.js @@ -1,6 +1,7 @@ import React from 'react'; -import { render, screen } from '@testing-library/react'; +import { StoreProvider, mockStore } from '@deriv/stores'; import { useStores } from 'Stores'; +import { render, screen } from '@testing-library/react'; import OrderDetails from '../order-details.jsx'; const mock_order_info = { @@ -12,7 +13,7 @@ const mock_order_info = { has_timer_expired: false, id: 123, is_active_order: false, - is_buy_order: false, + is_buy_order_for_user: false, is_buyer_confirmed_order: false, is_my_ad: false, is_pending_order: false, @@ -45,20 +46,54 @@ const mock_order_store = { has_order_payment_method_details: false, order_payment_method_details: [], setOrderPaymentMethodDetails: jest.fn(), + getSettings: jest.fn(), + getWebsiteStatus: jest.fn(), + setRatingValue: jest.fn(), + setIsRecommended: jest.fn(), + setOrderId: jest.fn(), + setActiveOrder: jest.fn(), }; const mock_sendbird_store = { should_show_chat_on_orders: false, setChatChannelUrl: jest.fn(), + setHasChatError: jest.fn(), createChatForNewOrder: jest.fn(), registerEventListeners: jest.fn().mockReturnValue(jest.fn()), registerMobXReactions: jest.fn().mockReturnValue(jest.fn()), }; +const mock_my_profile_store = { + getPaymentMethodsList: jest.fn(), +}; + +const mock_buy_sell_store = { + is_create_order_subscribed: true, + setIsCreateOrderSubscribed: jest.fn(), + unsubscribeCreateOrder: jest.fn(), +}; + +const mock_general_store = { + redirectToOrderDetails: jest.fn(), +}; + jest.mock('Stores', () => ({ ...jest.requireActual('Stores'), useStores: jest.fn(() => ({ order_store: { ...mock_order_store }, sendbird_store: { ...mock_sendbird_store }, + my_profile_store: { ...mock_my_profile_store }, + buy_sell_store: { ...mock_buy_sell_store }, + general_store: { ...mock_general_store }, + })), +})); + +jest.mock('Components/modal-manager/modal-manager-context', () => ({ + ...jest.requireActual('Components/modal-manager/modal-manager-context'), + useModalManagerContext: jest.fn(() => ({ + isCurrentModal: false, + showModal: () => {}, + hideModal: () => {}, + useRegisterModalProps: () => {}, })), })); @@ -71,7 +106,7 @@ jest.mock('Components/order-details/order-details-footer.jsx', () => jest.fn(() jest.mock('Components/order-details/order-info-block.jsx', () => jest.fn(() =>
Order Info Block
)); -jest.mock('Components/orders/chat/chat.jsx', () => jest.fn(() =>
Chat section
)); +jest.mock('Pages/orders/chat/chat.jsx', () => jest.fn(() =>
Chat section
)); jest.mock('Components/p2p-accordion/p2p-accordion.jsx', () => jest.fn(() =>
Payment methods listed
)); @@ -80,11 +115,20 @@ describe('', () => { useStores.mockReturnValue({ order_store: { ...mock_order_store, - order_information: { ...mock_order_info, should_show_lost_funds_banner: true, chat_channel_url: null }, + order_information: { + ...mock_order_info, + should_show_lost_funds_banner: true, + chat_channel_url: null, + }, }, sendbird_store: { ...mock_sendbird_store }, + my_profile_store: { ...mock_my_profile_store }, + buy_sell_store: { ...mock_buy_sell_store }, + general_store: { ...mock_general_store }, + }); + render(, { + wrapper: ({ children }) => {children}, }); - render(); expect( screen.getByText("Don't risk your funds with cash transactions. Use bank transfers or e-wallets instead.") ).toBeInTheDocument(); @@ -96,8 +140,13 @@ describe('', () => { order_information: { ...mock_order_info, should_highlight_success: true }, }, sendbird_store: { ...mock_sendbird_store }, + my_profile_store: { ...mock_my_profile_store }, + buy_sell_store: { ...mock_buy_sell_store }, + general_store: { ...mock_general_store }, + }); + render(, { + wrapper: ({ children }) => {children}, }); - render(); expect(screen.getByText('Result str')).toBeInTheDocument(); }); it('should display footer info when show_order_footer is set', () => { @@ -107,8 +156,13 @@ describe('', () => { order_information: { ...mock_order_info, should_show_order_footer: true }, }, sendbird_store: { ...mock_sendbird_store }, + my_profile_store: { ...mock_my_profile_store }, + buy_sell_store: { ...mock_buy_sell_store }, + general_store: { ...mock_general_store }, + }); + render(, { + wrapper: ({ children }) => {children}, }); - render(); expect(screen.getByText('Order details footer')).toBeInTheDocument(); }); it('should display formatted currency when the order is pending', () => { @@ -118,8 +172,13 @@ describe('', () => { order_information: { ...mock_order_info, is_pending_order: true }, }, sendbird_store: { ...mock_sendbird_store }, + my_profile_store: { ...mock_my_profile_store }, + buy_sell_store: { ...mock_buy_sell_store }, + general_store: { ...mock_general_store }, + }); + render(, { + wrapper: ({ children }) => {children}, }); - render(); expect(screen.getByText('40.00 AED')).toBeInTheDocument(); }); it('should display payment details when Order is active', () => { @@ -130,40 +189,44 @@ describe('', () => { has_order_payment_method_details: true, }, sendbird_store: { ...mock_sendbird_store }, + my_profile_store: { ...mock_my_profile_store }, + buy_sell_store: { ...mock_buy_sell_store }, + general_store: { ...mock_general_store }, + }); + render(, { + wrapper: ({ children }) => {children}, }); - render(); expect(screen.getByText('Payment details')).toBeInTheDocument(); }); - it('should render Chat component if show_chaton_orders is enabled', () => { + it('should render Chat component if should_show_chat_on_orders is enabled', () => { useStores.mockReturnValue({ order_store: { ...mock_order_store, }, sendbird_store: { ...mock_sendbird_store, should_show_chat_on_orders: true }, + my_profile_store: { ...mock_my_profile_store }, + buy_sell_store: { ...mock_buy_sell_store }, + general_store: { ...mock_general_store }, + }); + render(, { + wrapper: ({ children }) => {children}, }); - render(); expect(screen.getByText('Chat section')).toBeInTheDocument(); }); - it('should display Buy section when is_buy_order flag is enabled', () => { + it('should display Buy section when is_buy_order_for_user flag is enabled', () => { useStores.mockReturnValue({ order_store: { ...mock_order_store, - order_information: { ...mock_order_info, is_buy_order: true }, + order_information: { ...mock_order_info, is_buy_order_for_user: true }, }, sendbird_store: { ...mock_sendbird_store }, + my_profile_store: { ...mock_my_profile_store }, + buy_sell_store: { ...mock_buy_sell_store }, + general_store: { ...mock_general_store }, }); - render(); - expect(screen.getByText('Buy USD order')).toBeInTheDocument(); - }); - it('should display Buy section when is_sell_order as well as is_my_ad flag is enabled', () => { - useStores.mockReturnValue({ - order_store: { - ...mock_order_store, - order_information: { ...mock_order_info, is_sell_order: true, is_my_ad: true }, - }, - sendbird_store: { ...mock_sendbird_store }, + render(, { + wrapper: ({ children }) => {children}, }); - render(); expect(screen.getByText('Buy USD order')).toBeInTheDocument(); }); }); diff --git a/packages/p2p/src/components/order-details/__tests__/order-details-wrapper.spec.js b/packages/p2p/src/components/order-details/__tests__/order-details-wrapper.spec.js index 9121b1d56b98..a8cfa8ee6bba 100644 --- a/packages/p2p/src/components/order-details/__tests__/order-details-wrapper.spec.js +++ b/packages/p2p/src/components/order-details/__tests__/order-details-wrapper.spec.js @@ -28,7 +28,7 @@ describe('', () => { isMobile.mockReturnValue(true); const mobile_props = { className: 'order-details', - body_className: 'order-details--body', + body_className: 'order-details__body', height_offset: '80px', is_flex: true, is_modal_open: true, @@ -53,7 +53,7 @@ describe('', () => { render(); await waitFor(() => { - expect(screen.getByTestId('order-details-wrapper-desktop')).toBeInTheDocument(); + expect(screen.getByTestId('dt_page_return')).toBeInTheDocument(); expect(screen.getByText('desktop test')).toBeInTheDocument(); }); }); diff --git a/packages/p2p/src/components/order-details/order-details-complain-modal-radio-group.jsx b/packages/p2p/src/components/order-details/order-details-complain-modal-radio-group.jsx index 41ca978e4e54..7241e1a1cb4e 100644 --- a/packages/p2p/src/components/order-details/order-details-complain-modal-radio-group.jsx +++ b/packages/p2p/src/components/order-details/order-details-complain-modal-radio-group.jsx @@ -3,11 +3,11 @@ import React from 'react'; import { RadioGroup } from '@deriv/components'; import { isMobile } from '@deriv/shared'; import { localize } from 'Components/i18next'; -import 'Components/order-details/order-details-complain-modal.scss'; +import 'Components/order-details/order-details-complain-modal-radio-group.scss'; const OrderDetailsComplainModalRadioGroup = ({ dispute_reason, onCheckboxChange, is_buy_order_for_user }) => ( onCheckboxChange(event.target.value)} selected={dispute_reason} diff --git a/packages/p2p/src/components/order-details/order-details-complain-modal-radio-group.scss b/packages/p2p/src/components/order-details/order-details-complain-modal-radio-group.scss new file mode 100644 index 000000000000..de22f14a7f1d --- /dev/null +++ b/packages/p2p/src/components/order-details/order-details-complain-modal-radio-group.scss @@ -0,0 +1,37 @@ +.order-details-complain-modal-radio-group:not(.dc-radio-group__item) { + display: inline; + + @include mobile { + margin-top: 0; + + .dc-radio-group__item-wrapper { + border-bottom: 1px solid var(--general-section-1); + + > .dc-radio-group__item { + margin: 1.6rem; + } + } + } + + .dc-radio-group__item { + @include tablet-up { + border-bottom: 1px solid var(--general-section-1); + padding: 1.6rem 0; + } + + .dc-radio-group__label { + flex: 1; + } + + .dc-radio-group__circle { + align-self: start; + margin-top: 0.3rem; + border: 2px solid var(--text-less-prominent); + transition: all 0.1s ease-in-out; + + &--selected { + border: 4px solid var(--brand-red-coral); + } + } + } +} diff --git a/packages/p2p/src/components/order-details/order-details-complain-modal.jsx b/packages/p2p/src/components/order-details/order-details-complain-modal.jsx index 8b08b1e2d693..8c3ae89e6c0d 100644 --- a/packages/p2p/src/components/order-details/order-details-complain-modal.jsx +++ b/packages/p2p/src/components/order-details/order-details-complain-modal.jsx @@ -4,13 +4,13 @@ import { Button, MobileFullPageModal, Modal, Text } from '@deriv/components'; import { isMobile, useIsMounted } from '@deriv/shared'; import { localize, Localize } from 'Components/i18next'; import { requestWS } from 'Utils/websocket'; -import FormError from 'Components/form/error.jsx'; +import FormError from 'Components/section-error'; import OrderDetailsComplainModalRadioGroup from './order-details-complain-modal-radio-group.jsx'; import 'Components/order-details/order-details-complain-modal.scss'; const ComplainExplanation = () => (
- +
@@ -95,7 +95,7 @@ const OrderDetailsComplainModal = ({ toggleModal={hideComplainOrderModal} has_close_icon renderTitle={() => ( - + )} diff --git a/packages/p2p/src/components/order-details/order-details-complain-modal.scss b/packages/p2p/src/components/order-details/order-details-complain-modal.scss index b2b0392cc17c..aa14c5b5a71a 100644 --- a/packages/p2p/src/components/order-details/order-details-complain-modal.scss +++ b/packages/p2p/src/components/order-details/order-details-complain-modal.scss @@ -21,44 +21,6 @@ border-radius: 8px; } } - - &__radio-group:not(.dc-radio-group__item) { - display: inline; - - @include mobile { - margin-top: 0; - - .dc-radio-group__item-wrapper { - border-bottom: 1px solid var(--general-section-1); - - > .dc-radio-group__item { - margin: 1.6rem; - } - } - } - - .dc-radio-group__item { - @include tablet-up { - border-bottom: 1px solid var(--general-section-1); - padding: 1.6rem 0; - } - - .dc-radio-group__label { - flex: 1; - } - - .dc-radio-group__circle { - align-self: start; - margin-top: 0.3rem; - border: 2px solid var(--text-less-prominent); - transition: all 0.1s ease-in-out; - - &--selected { - border: 4px solid var(--brand-red-coral); - } - } - } - } } .dc-modal__container_order-details-complain-modal { diff --git a/packages/p2p/src/components/order-details/order-details-footer.jsx b/packages/p2p/src/components/order-details/order-details-footer.jsx index 72219419d554..d941bc0d2c1e 100644 --- a/packages/p2p/src/components/order-details/order-details-footer.jsx +++ b/packages/p2p/src/components/order-details/order-details-footer.jsx @@ -5,6 +5,7 @@ import { observer } from 'mobx-react-lite'; import { Localize } from 'Components/i18next'; import { useStores } from 'Stores'; import OrderDetailsComplainModal from './order-details-complain-modal.jsx'; +import './order-details-footer.scss'; const OrderDetailsFooter = observer(() => { const { general_store, order_store } = useStores(); @@ -48,8 +49,8 @@ const OrderDetailsFooter = observer(() => { if (should_show_cancel_and_paid_button) { return ( -
-
+
+
@@ -112,8 +113,8 @@ const OrderDetailsFooter = observer(() => { if (should_show_only_received_button) { return ( -
-
+
+
diff --git a/packages/p2p/src/components/order-details/order-details-footer.scss b/packages/p2p/src/components/order-details/order-details-footer.scss new file mode 100644 index 000000000000..63ccda5c7620 --- /dev/null +++ b/packages/p2p/src/components/order-details/order-details-footer.scss @@ -0,0 +1,19 @@ +.order-details-footer { + display: flex; + justify-content: space-between; + margin-top: auto; + padding: 1.6rem 2.4rem; + + @include mobile { + width: 100%; + padding: unset; + } + @include tablet-up { + width: 100%; + padding: 0 1.6rem 1.6rem; + } + + &--right { + margin-left: auto; + } +} diff --git a/packages/p2p/src/components/order-details/order-details-timer.jsx b/packages/p2p/src/components/order-details/order-details-timer.jsx index e1cfc916d2bf..2fb4c246a08d 100644 --- a/packages/p2p/src/components/order-details/order-details-timer.jsx +++ b/packages/p2p/src/components/order-details/order-details-timer.jsx @@ -1,10 +1,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import { observer } from 'mobx-react-lite'; +import { Text } from '@deriv/components'; import { localize } from 'Components/i18next'; import { secondsToTimer } from 'Utils/date-time'; import ServerTime from 'Utils/server-time'; import { useStores } from 'Stores'; +import './order-details-timer.scss'; const OrderDetailsTimer = observer(() => { const getTimeLeft = time => { @@ -36,9 +38,13 @@ const OrderDetailsTimer = observer(() => { if (should_show_order_timer) { return ( -
-
{localize('Time left')}
-
{remaining_time}
+
+ + {localize('Time left')} + + + {remaining_time} +
); } diff --git a/packages/p2p/src/components/order-details/order-details-timer.scss b/packages/p2p/src/components/order-details/order-details-timer.scss new file mode 100644 index 000000000000..b53069563ded --- /dev/null +++ b/packages/p2p/src/components/order-details/order-details-timer.scss @@ -0,0 +1,11 @@ +.order-details-timer { + display: flex; + flex-direction: column; + + &__counter { + margin-top: 0.4rem; + border: 1px solid var(--border-normal); + border-radius: 16px; + padding: 0.4rem 0.8rem; + } +} diff --git a/packages/p2p/src/components/order-details/order-details-wrapper.jsx b/packages/p2p/src/components/order-details/order-details-wrapper.jsx index d67207e4124d..8192c0260b26 100644 --- a/packages/p2p/src/components/order-details/order-details-wrapper.jsx +++ b/packages/p2p/src/components/order-details/order-details-wrapper.jsx @@ -3,7 +3,7 @@ import { useHistory } from 'react-router-dom'; import PropTypes from 'prop-types'; import { Icon, MobileFullPageModal, ThemedScrollbars } from '@deriv/components'; import { isMobile, routes } from '@deriv/shared'; -import PageReturn from 'Components/page-return/page-return.jsx'; +import PageReturn from 'Components/page-return'; import { useStores } from 'Stores'; import OrderDetailsFooter from 'Components/order-details/order-details-footer.jsx'; @@ -24,7 +24,7 @@ const OrderDetailsWrapper = ({ children, page_title }) => {
{ order_store.setOrderPaymentMethodDetails(undefined); order_store.setOrderId(null); order_store.setActiveOrder(null); - history.replace({ + history?.replace({ search: '', hash: location.hash, }); @@ -225,7 +225,7 @@ const OrderDetails = observer(() => {
-
{ 'order-details-card__header-status--success': should_highlight_success, } )} + as='p' + line_height='s' + weight='bold' > {status_string} -
+ {should_highlight_success && ( -
{labels.result_string}
+ + {labels.result_string} + )} {!has_timer_expired && (is_pending_order || is_buyer_confirmed_order) && ( -
+ {display_payment_amount} {local_currency} -
+ )}
- + + +
@@ -298,7 +305,7 @@ const OrderDetails = observer(() => { {labels.payment_details} - @@ -106,20 +103,20 @@ const AdvertiserPageRow = ({ row: advert }) => { } return ( - + {`${min_order_amount_limit_display}-${max_order_amount_limit_display} ${currency}`} - - + + {display_effective_rate} {local_currency} -
+
{payment_method_names ? payment_method_names.map((payment_method, key) => { return ( -
- +
+ {payment_method}
@@ -131,7 +128,7 @@ const AdvertiserPageRow = ({ row: advert }) => { {is_my_advert ? ( ) : ( - + diff --git a/packages/p2p/src/pages/advertiser-page/advertiser-page-row.scss b/packages/p2p/src/pages/advertiser-page/advertiser-page-row.scss new file mode 100644 index 000000000000..d604e620e267 --- /dev/null +++ b/packages/p2p/src/pages/advertiser-page/advertiser-page-row.scss @@ -0,0 +1,2 @@ +@import 'advertiser-page.scss'; +@import 'advertiser-page-adverts.scss'; diff --git a/packages/p2p/src/components/advertiser-page/advertiser-page-stats.jsx b/packages/p2p/src/pages/advertiser-page/advertiser-page-stats.jsx similarity index 77% rename from packages/p2p/src/components/advertiser-page/advertiser-page-stats.jsx rename to packages/p2p/src/pages/advertiser-page/advertiser-page-stats.jsx index f0afa51e934a..1c8342efa4e2 100644 --- a/packages/p2p/src/components/advertiser-page/advertiser-page-stats.jsx +++ b/packages/p2p/src/pages/advertiser-page/advertiser-page-stats.jsx @@ -4,7 +4,7 @@ import { isMobile } from '@deriv/shared'; import { observer, useStore } from '@deriv/stores'; import { localize, Localize } from 'Components/i18next'; import { useStores } from 'Stores'; -import './advertiser-page.scss'; +import './advertiser-page-stats.scss'; const AdvertiserPageStats = () => { const { advertiser_page_store, general_store } = useStores(); @@ -33,10 +33,10 @@ const AdvertiserPageStats = () => { if (isMobile()) { return ( - - - - +
+ + + { ]} /> - + {buy_completion_rate ? `${buy_completion_rate}% (${buy_orders_count})` : '-'} -
- - +
+ + {
- - - - +
+ + + { ]} /> - + {sell_completion_rate ? `${sell_completion_rate}% (${sell_orders_count})` : '-'} -
- - +
+ + {
- - - - +
+ + + { ]} /> - + {buy_orders_amount && sell_orders_amount ? ( { )} -
- - +
+ + - + {partner_count || '0'} @@ -168,10 +168,10 @@ const AdvertiserPageStats = () => { return ( -
- - - +
+ + + { ]} /> - + {buy_completion_rate ? `${buy_completion_rate}% (${buy_orders_count})` : '-'} -
- - +
+ + { ]} /> - + {sell_completion_rate ? `${sell_completion_rate}% (${sell_orders_count})` : '-'} -
- - +
+ + { ]} /> - + {buy_orders_amount && sell_orders_amount ? ( {
- - - - +
+ + + { : '-'} -
- - +
+ + { : '-'} -
- - +
+ + - + {partner_count || '0'} diff --git a/packages/p2p/src/pages/advertiser-page/advertiser-page-stats.scss b/packages/p2p/src/pages/advertiser-page/advertiser-page-stats.scss new file mode 100644 index 000000000000..f24a74ec89b8 --- /dev/null +++ b/packages/p2p/src/pages/advertiser-page/advertiser-page-stats.scss @@ -0,0 +1,75 @@ +.advertiser-page-stats { + &__row { + border-bottom: none; + display: flex; + grid-template-columns: repeat(3, 1fr); + height: 5rem; + justify-content: space-between; + margin: 2rem 0; + width: 100%; + + @include mobile { + grid-template-columns: repeat(2, 1fr); + margin: 0.6rem; + width: 90vw; + } + } + + &__cell { + display: grid; + min-width: 20rem; + text-align: center; + margin-right: 10rem; + + @include mobile { + min-width: 12rem; + + &:nth-child(5) { + min-width: 16rem; + } + } + + &-buy { + margin-left: 0.5rem; + margin-top: 0.14rem; + } + + &-completion { + display: flex; + + @include mobile { + flex-direction: row; + justify-content: center; + padding-left: 0.5rem; + } + } + + &-separator { + border-right: 1px solid #ededed; + margin-right: 2rem; + + @include mobile { + margin: 0px 3rem 0 -4rem; + } + } + } + + &__wrapper { + align-items: center; + display: flex; + + @media (max-height: 580px) { + height: 5rem; + } + @include mobile { + display: flex; + justify-content: center; + flex: none; + + background-color: var(--general-main-1); + z-index: 1; + transition: transform 0.25s linear, opacity 0.25s ease; + transform-origin: top; + } + } +} diff --git a/packages/p2p/src/components/advertiser-page/advertiser-page.jsx b/packages/p2p/src/pages/advertiser-page/advertiser-page.jsx similarity index 95% rename from packages/p2p/src/components/advertiser-page/advertiser-page.jsx rename to packages/p2p/src/pages/advertiser-page/advertiser-page.jsx index f236851cee9c..f072f53076d1 100644 --- a/packages/p2p/src/components/advertiser-page/advertiser-page.jsx +++ b/packages/p2p/src/pages/advertiser-page/advertiser-page.jsx @@ -8,27 +8,27 @@ import { useStores } from 'Stores'; import { Localize, localize } from 'Components/i18next'; import { my_profile_tabs } from 'Constants/my-profile-tabs'; import { api_error_codes } from 'Constants/api-error-codes'; -import PageReturn from 'Components/page-return/page-return.jsx'; +import PageReturn from 'Components/page-return'; import RecommendedBy from 'Components/recommended-by'; -import UserAvatar from 'Components/user/user-avatar/user-avatar.jsx'; +import UserAvatar from 'Components/user/user-avatar'; import AdvertiserPageStats from './advertiser-page-stats.jsx'; import AdvertiserPageAdverts from './advertiser-page-adverts.jsx'; import StarRating from 'Components/star-rating'; import AdvertiserPageDropdownMenu from './advertiser-page-dropdown-menu.jsx'; -import TradeBadge from '../trade-badge/trade-badge.jsx'; +import TradeBadge from 'Components/trade-badge'; import BlockUserOverlay from './block-user/block-user-overlay'; import classNames from 'classnames'; import { OnlineStatusIcon, OnlineStatusLabel } from 'Components/online-status'; import { useModalManagerContext } from 'Components/modal-manager/modal-manager-context'; -import './advertiser-page.scss'; const AdvertiserPage = () => { const { advertiser_page_store, buy_sell_store, general_store, my_profile_store } = useStores(); const { hideModal, showModal, useRegisterModalProps } = useModalManagerContext(); + const { advertiser_details_name, advertiser_details_id, counterparty_advertiser_info } = advertiser_page_store; - const is_my_advert = advertiser_page_store.advertiser_details_id === general_store.advertiser_id; + const is_my_advert = advertiser_details_id === general_store.advertiser_id; // Use general_store.advertiser_info since resubscribing to the same id from advertiser page returns error - const info = is_my_advert ? general_store.advertiser_info : advertiser_page_store.counterparty_advertiser_info; + const info = is_my_advert ? general_store.advertiser_info : counterparty_advertiser_info; const history = useHistory(); @@ -49,11 +49,11 @@ const AdvertiserPage = () => { sell_orders_count, } = info; - const nickname = advertiser_page_store.advertiser_details_name ?? name; - + const joined_since = daysSince(created_time); + const nickname = advertiser_details_name ?? name; // rating_average_decimal converts rating_average to 1 d.p number const rating_average_decimal = rating_average ? Number(rating_average).toFixed(1) : null; - const joined_since = daysSince(created_time); + const error_message = () => { return !!advertiser_page_store.is_counterparty_advertiser_blocked && !is_my_advert ? localize("Unblocking wasn't possible as {{name}} is not using Deriv P2P anymore.", { @@ -78,11 +78,21 @@ const AdvertiserPage = () => { { fireImmediately: true } ); - reaction( + return () => { + disposeCounterpartyAdvertiserIdReaction(); + advertiser_page_store.onUnmount(); + buy_sell_store.setShowAdvertiserPage(false); + }; + + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + React.useEffect(() => { + const disposeBlockUnblockUserErrorReaction = reaction( () => [advertiser_page_store.active_index, general_store.block_unblock_user_error], () => { advertiser_page_store.onTabChange(); - if (general_store.block_unblock_user_error && buy_sell_store.show_advertiser_page) { + if (general_store.block_unblock_user_error) { showModal({ key: 'ErrorModal', props: { @@ -110,20 +120,15 @@ const AdvertiserPage = () => { width: isMobile() ? '90rem' : '40rem', }, }); - general_store.setBlockUnblockUserError(null); } }, { fireImmediately: true } ); return () => { - disposeCounterpartyAdvertiserIdReaction(); - advertiser_page_store.onUnmount(); - buy_sell_store.setShowAdvertiserPage(false); + disposeBlockUnblockUserErrorReaction(); }; - - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); + }, [advertiser_details_name, counterparty_advertiser_info]); useRegisterModalProps({ key: 'BlockUserModal', @@ -184,7 +189,7 @@ const AdvertiserPage = () => { />
- + {nickname} {first_name && last_name && ( @@ -195,7 +200,6 @@ const AdvertiserPage = () => {
)}
-
diff --git a/packages/p2p/src/components/advertiser-page/advertiser-page.scss b/packages/p2p/src/pages/advertiser-page/advertiser-page.scss similarity index 51% rename from packages/p2p/src/components/advertiser-page/advertiser-page.scss rename to packages/p2p/src/pages/advertiser-page/advertiser-page.scss index 4427b7f4e35d..d7993f2817a5 100644 --- a/packages/p2p/src/components/advertiser-page/advertiser-page.scss +++ b/packages/p2p/src/pages/advertiser-page/advertiser-page.scss @@ -7,58 +7,6 @@ overflow-y: auto; } - &__dropdown { - box-shadow: 0 1rem 2rem var(--shadow-menu); - border-radius: $BORDER_RADIUS; - cursor: pointer; - position: absolute; - right: 0; - z-index: 2; - - .dc-dropdown__display { - background-color: var(--general-main-2); - border: 1px solid var(--general-active); - - span { - background-color: var(--general-main-2); - } - - &-placeholder { - top: auto; - } - } - - &-container { - margin-top: 0; - } - - &:hover { - .dc-dropdown__display { - background-color: var(--border-normal); - border: 1px solid var(--border-normal); - - span { - background-color: var(--border-normal); - } - } - } - } - - &__menu-dots-icon { - cursor: pointer; - margin-bottom: 0.8rem; - } - - &__menu-dots-toggle { - position: absolute; - right: 2.4rem; - - @include mobile { - bottom: 0.8rem; - right: 1.2rem; - } - } - &__page-return-header { position: relative; } @@ -209,79 +157,6 @@ margin-top: 0.35rem; } - &__stats { - border-bottom: none; - display: flex; - grid-template-columns: repeat(3, 1fr); - height: 5rem; - justify-content: space-between; - margin: 2rem 0; - width: 100%; - - @include mobile { - grid-template-columns: repeat(2, 1fr); - margin: 0.6rem; - width: 90vw; - } - - &-cell { - display: grid; - min-width: 20rem; - text-align: center; - margin-right: 10rem; - - @include mobile { - min-width: 12rem; - - &:nth-child(5) { - min-width: 16rem; - } - } - - &-buy { - margin-left: 0.5rem; - margin-top: 0.14rem; - } - - &-completion { - display: flex; - - @include mobile { - flex-direction: row; - justify-content: center; - padding-left: 0.5rem; - } - } - - &-separator { - border-right: 1px solid #ededed; - margin-right: 2rem; - - @include mobile { - margin: 0px 3rem 0 -4rem; - } - } - } - - &--wrapper { - align-items: center; - display: flex; - - @media (max-height: 580px) { - height: 5rem; - } - @include mobile { - display: flex; - justify-content: center; - flex: none; - - background-color: var(--general-main-1); - z-index: 1; - transition: transform 0.25s linear, opacity 0.25s ease; - transform-origin: top; - } - } - } &__cell { @include mobile { display: block; @@ -300,11 +175,13 @@ } } } + &__payment-methods-list { display: flex; flex-direction: row; flex-wrap: wrap; } + &__payment-method { display: flex; flex-wrap: wrap; @@ -318,86 +195,6 @@ @include mobile { padding: 0.4rem; - font-size: 8px; - } - } - &__adverts { - flex: 1; - display: flex; - flex-direction: column; - - &-button { - align-items: center; - display: flex; - justify-content: center; - - @include mobile { - display: flex; - flex-direction: column; - justify-content: flex-start; - margin-top: 1rem; - } - } - &-table { - display: flex; - flex: 1; - flex-direction: column; - - @include mobile { - display: flex; - flex-flow: column; - width: 100vw; - } - - &-body { - flex: 1; - display: flex; - flex-direction: column; - } - } - - &-table_row { - padding: 1.6rem; - grid-template-columns: 3fr 2fr 2.5fr 1fr; - - @include mobile { - grid-template-columns: 2fr 1fr; - min-height: 105px; - padding: 1.6rem; - width: 100vw; - } - } - - &-tabs { - width: 228px; - } - - .dc-tabs__item { - @include mobile { - width: 50%; - } - } - - &-list { - height: calc(100% - 200px); - - @include mobile { - height: calc(100% - 236px); - } - } - - &-scrollbar { - @include tablet-up { - height: calc(100vh - 527px); - } - - position: absolute; - - @include mobile { - bottom: 0; - max-height: calc(100vh - 440px) !important; - position: fixed; - } } } @@ -411,6 +208,7 @@ } } } + &__data-list { flex: 1; diff --git a/packages/p2p/src/components/advertiser-page/block-user/block-user-count.jsx b/packages/p2p/src/pages/advertiser-page/block-user/block-user-count.jsx similarity index 96% rename from packages/p2p/src/components/advertiser-page/block-user/block-user-count.jsx rename to packages/p2p/src/pages/advertiser-page/block-user/block-user-count.jsx index 8a86361852ae..9e460fc1419f 100644 --- a/packages/p2p/src/components/advertiser-page/block-user/block-user-count.jsx +++ b/packages/p2p/src/pages/advertiser-page/block-user/block-user-count.jsx @@ -57,7 +57,7 @@ const BlockUserCount = () => { message={getMessage()} > - + {user_blocked_count} diff --git a/packages/p2p/src/components/advertiser-page/block-user/block-user-count.scss b/packages/p2p/src/pages/advertiser-page/block-user/block-user-count.scss similarity index 100% rename from packages/p2p/src/components/advertiser-page/block-user/block-user-count.scss rename to packages/p2p/src/pages/advertiser-page/block-user/block-user-count.scss diff --git a/packages/p2p/src/components/advertiser-page/block-user/block-user-overlay/block-user-overlay.jsx b/packages/p2p/src/pages/advertiser-page/block-user/block-user-overlay/block-user-overlay.jsx similarity index 96% rename from packages/p2p/src/components/advertiser-page/block-user/block-user-overlay/block-user-overlay.jsx rename to packages/p2p/src/pages/advertiser-page/block-user/block-user-overlay/block-user-overlay.jsx index ccdbd03eada3..5851a07bfd60 100644 --- a/packages/p2p/src/components/advertiser-page/block-user/block-user-overlay/block-user-overlay.jsx +++ b/packages/p2p/src/pages/advertiser-page/block-user/block-user-overlay/block-user-overlay.jsx @@ -13,7 +13,7 @@ const BlockUserOverlay = ({ children, is_visible, onClickUnblock }) => {
- + { @@ -51,7 +51,7 @@ const App = () => { // Check if advertiser info has been subscribed to before the user navigates to // /advertiser?=id{counterparty_advertiser_id} from the url const disposeAdvertiserInfoSubscribedReaction = reaction( - () => general_store.is_advertiser_info_subscribed, + () => general_store.is_advertiser_info_subscribed && general_store.counterparty_advertiser_id, () => { if ( /\/advertiser$/.test(location.pathname) && @@ -245,7 +245,7 @@ const App = () => { return ( <> -
+
diff --git a/packages/p2p/src/components/app.scss b/packages/p2p/src/pages/app.scss similarity index 71% rename from packages/p2p/src/components/app.scss rename to packages/p2p/src/pages/app.scss index 37335c3aed1d..3ed4c48db9ea 100644 --- a/packages/p2p/src/components/app.scss +++ b/packages/p2p/src/pages/app.scss @@ -1,7 +1,7 @@ @import '../../../shared/src/styles/reset.scss'; @import '../../../shared/src/styles/themes.scss'; -.p2p-cashier { +.p2p { background: transparent; height: 100%; width: 100%; @@ -10,29 +10,12 @@ flex-direction: column; overflow: hidden; - &__barred-user { - .dc-hint-box { - margin-top: 1.6rem; - - &__icon { - @include mobile { - align-self: flex-start; - min-width: 16px; - min-height: 16px; - } - } - - @include mobile { - margin: 1rem 2rem; - } - } - } - &__content { padding: 0 1.6rem; } + & .dc-tabs { - &--p2p-cashier__tabs { + &--p2p__tabs { @include mobile { overflow: hidden; } @@ -55,6 +38,7 @@ } } } + & .dc-button-menu { &__wrapper { background-color: var(--state-disabled); @@ -80,10 +64,12 @@ background-color: var(--state-normal) !important; } } + &__separator { width: 100%; border-top: 1px solid var(--general-section-1); } + &__advertiser-tab { @include mobile { .dc-tabs { @@ -104,37 +90,10 @@ } } } + @include mobile { .dc-autocomplete__field { border: none; } } } - -.sendbird-fileviewer__header-delete { - display: none !important; -} - -.p2p-nickname { - &__dialog { - @include mobile { - height: 100%; - } - } -} - -.dc-modal__container_p2p-nickname { - &__dialog { - height: auto; - margin-bottom: 0; - max-height: 50rem !important; - max-width: 44rem; - min-width: 44rem; - padding: 0; - width: 100%; - - @include mobile { - min-width: 0; - } - } -} diff --git a/packages/p2p/src/components/buy-sell/__tests__/buy-sell-form-receive-amount.spec.js b/packages/p2p/src/pages/buy-sell/__tests__/buy-sell-form-receive-amount.spec.js similarity index 95% rename from packages/p2p/src/components/buy-sell/__tests__/buy-sell-form-receive-amount.spec.js rename to packages/p2p/src/pages/buy-sell/__tests__/buy-sell-form-receive-amount.spec.js index 3b87668add14..b2281817aaa1 100644 --- a/packages/p2p/src/components/buy-sell/__tests__/buy-sell-form-receive-amount.spec.js +++ b/packages/p2p/src/pages/buy-sell/__tests__/buy-sell-form-receive-amount.spec.js @@ -1,7 +1,7 @@ import React from 'react'; import { render, screen } from '@testing-library/react'; import { useStores } from 'Stores'; -import BuySellFormReceiveAmount from 'Components/buy-sell/buy-sell-form-receive-amount.jsx'; +import BuySellFormReceiveAmount from 'Pages/buy-sell/buy-sell-form-receive-amount.jsx'; jest.mock('Stores', () => ({ ...jest.requireActual('Stores'), diff --git a/packages/p2p/src/components/buy-sell/__tests__/buy-sell.spec.jsx b/packages/p2p/src/pages/buy-sell/__tests__/buy-sell.spec.jsx similarity index 74% rename from packages/p2p/src/components/buy-sell/__tests__/buy-sell.spec.jsx rename to packages/p2p/src/pages/buy-sell/__tests__/buy-sell.spec.jsx index 07e7d1367bc5..24148ec30dba 100644 --- a/packages/p2p/src/components/buy-sell/__tests__/buy-sell.spec.jsx +++ b/packages/p2p/src/pages/buy-sell/__tests__/buy-sell.spec.jsx @@ -6,12 +6,13 @@ import BuySell from '../buy-sell'; const mock_store = { general_store: { should_show_popup: false, + setShouldShowPopup: jest.fn(), setActiveIndex: jest.fn(), active_index: 1, }, buy_sell_store: { - registerIsListedReaction: jest.fn(), - registerAdvertIntervalReaction: jest.fn(), + registerIsListedReaction: jest.fn(() => jest.fn()), + registerAdvertIntervalReaction: jest.fn(() => jest.fn()), selected_local_currency: 'USD', show_advertiser_page: false, should_show_verification: true, @@ -19,25 +20,13 @@ const mock_store = { }, }; -jest.mock('Components/verification/verification.jsx', () => jest.fn(() =>
Verification Section
)); +jest.mock('Components/verification/verification', () => jest.fn(() =>
Verification Section
)); jest.mock('Stores', () => ({ ...jest.requireActual('Stores'), useStores: jest.fn(() => mock_store), })); -jest.mock('@sendbird/chat', () => ({ - SendbirdChat: jest.fn().mockReturnValue({}), -})); - -jest.mock('@sendbird/chat/groupChannel', () => ({ - SendbirdChat: jest.fn().mockReturnValue({}), -})); - -jest.mock('@sendbird/chat/message', () => ({ - SendbirdChat: jest.fn().mockReturnValue({}), -})); - describe('', () => { it('should render the buy/sell page', () => { render(); diff --git a/packages/p2p/src/components/buy-sell/__tests__/sort-dropdown.spec.js b/packages/p2p/src/pages/buy-sell/__tests__/sort-dropdown.spec.js similarity index 100% rename from packages/p2p/src/components/buy-sell/__tests__/sort-dropdown.spec.js rename to packages/p2p/src/pages/buy-sell/__tests__/sort-dropdown.spec.js diff --git a/packages/p2p/src/components/buy-sell/buy-sell-form-receive-amount.jsx b/packages/p2p/src/pages/buy-sell/buy-sell-form-receive-amount.jsx similarity index 80% rename from packages/p2p/src/components/buy-sell/buy-sell-form-receive-amount.jsx rename to packages/p2p/src/pages/buy-sell/buy-sell-form-receive-amount.jsx index 8de1f76d8d93..f2d6c0f4b378 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-form-receive-amount.jsx +++ b/packages/p2p/src/pages/buy-sell/buy-sell-form-receive-amount.jsx @@ -4,20 +4,21 @@ import { getFormattedText } from '@deriv/shared'; import { Localize } from 'Components/i18next'; import { roundOffDecimal } from 'Utils/format-value'; import { useStores } from 'Stores'; +import './buy-sell-form-receive-amount.scss'; const BuySellFormReceiveAmount = () => { const { buy_sell_store } = useStores(); return ( -
- +
+ {buy_sell_store?.is_sell_advert ? ( ) : ( )} - + {getFormattedText( roundOffDecimal(buy_sell_store?.receive_amount), buy_sell_store?.advert?.local_currency diff --git a/packages/p2p/src/pages/buy-sell/buy-sell-form-receive-amount.scss b/packages/p2p/src/pages/buy-sell/buy-sell-form-receive-amount.scss new file mode 100644 index 000000000000..1bc6d4c8ce24 --- /dev/null +++ b/packages/p2p/src/pages/buy-sell/buy-sell-form-receive-amount.scss @@ -0,0 +1,7 @@ +.buy-sell-form-receive-amount { + @include mobile { + border-top: 1px solid var(--general-section-2); + padding: 0.8rem 1.6rem; + background-color: var(--general-main-1); + } +} diff --git a/packages/p2p/src/components/buy-sell/buy-sell-form.jsx b/packages/p2p/src/pages/buy-sell/buy-sell-form.jsx similarity index 92% rename from packages/p2p/src/components/buy-sell/buy-sell-form.jsx rename to packages/p2p/src/pages/buy-sell/buy-sell-form.jsx index 8c972da25e2d..864e3036e55c 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-form.jsx +++ b/packages/p2p/src/pages/buy-sell/buy-sell-form.jsx @@ -11,12 +11,13 @@ import { localize, Localize } from 'Components/i18next'; import { ad_type } from 'Constants/floating-rate'; import { useStores } from 'Stores'; import BuySellFormReceiveAmount from './buy-sell-form-receive-amount.jsx'; -import PaymentMethodCard from '../my-profile/payment-methods/payment-method-card/payment-method-card.jsx'; +import PaymentMethodCard from 'Pages/my-profile/payment-methods/payment-method-card/payment-method-card.jsx'; import { floatingPointValidator } from 'Utils/validations'; import { countDecimalPlaces } from 'Utils/string'; import { generateEffectiveRate, setDecimalPlaces, roundOffDecimal, removeTrailingZeros } from 'Utils/format-value'; import { useModalManagerContext } from 'Components/modal-manager/modal-manager-context'; import PaymentMethodIcon from 'Components/payment-method-icon'; +import './buy-sell-form.scss'; const BuySellForm = props => { const isMounted = useIsMounted(); @@ -145,7 +146,7 @@ const BuySellForm = props => { return ( {rate_type === ad_type.FLOAT && !should_disable_field && ( -
+
{ return (
-
-
-
- +
+
+
+ {buy_sell_store.is_buy_advert ? ( ) : ( )} - + {advertiser_details.name}
-
- +
+ - + {display_effective_rate} {local_currency}
-
+
{payment_method_names && ( @@ -220,20 +220,20 @@ const BuySellForm = props => { )} {payment_method_names && payment_method_names.map((payment_method, key) => ( -
+
- + {payment_method}
))}
-
-
- +
+
+ {buy_sell_store.is_buy_advert ? ( ) : ( @@ -245,26 +245,25 @@ const BuySellForm = props => { .replace(/([\r\n]){2,}/g, '\n\n') .split('\n') .map((text, idx) => ( - + {text || '-'} ))}
-
+
{buy_sell_store.is_sell_advert && payment_method_names && ( -
+
- + {my_profile_store.advertiser_has_payment_methods ? ( ) : ( @@ -274,8 +273,8 @@ const BuySellForm = props => { {() => (
@@ -348,16 +347,16 @@ const BuySellForm = props => { )}
-
+
)} -
+
{localize('Enter {{transaction_type}} amount', { transaction_type: buy_sell_store.is_buy_advert ? 'buy' : 'sell', })} -
+
{({ field }) => ( { /> } is_relative_hint - className='buy-sell__modal-field' + className='buy-sell-form__field' trailing_icon={ - + {buy_sell_store.account_currency} } @@ -413,8 +412,8 @@ const BuySellForm = props => { {isDesktop() && (
@@ -425,7 +424,7 @@ const BuySellForm = props => { {buy_sell_store.is_sell_advert && ( {!payment_method_names && ( -
+
{({ field }) => ( {
)} -
+
{({ field }) => ( * { + margin: $gap 0 0 $gap; + } + + @include mobile { + flex-direction: column; + + .dc-input__wrapper { + margin-top: 2.5rem; + width: 90vw; + } + } + + > .dc-input { + margin-top: 1rem; // Compensate for label. + } + } + } + + &-body { + position: relative; + display: block; + padding-top: 2.4rem; + + @include mobile { + & > form { + height: fit-content !important; + } + } + } + + &-danger { + margin-bottom: 1.6rem; + width: fit-content; + align-items: flex-start; + } + + &-form { + height: fit-content !important; + } + + &-footer { + @include mobile { + border-top: 2px solid var(--general-section-1); + display: flex; + flex-direction: row; + justify-content: flex-end; + margin-top: auto; + padding: 1.6rem; + } + } + + &--input { + display: flex; + gap: 2rem; + flex-direction: column; + padding: 0 2.4rem 2rem; + margin-bottom: 2rem; + .dc-input__wrapper { + margin-right: 0.2rem; + margin-bottom: unset; + } + + &-field { + @include desktop { + display: flex; + } + } + @include mobile { + .dc-input { + &__container { + width: 100%; + padding: 0.5rem 1rem 0.5rem 1.2rem; + } + &__wrapper { + margin: 0.8rem 0.2rem 1.4rem 0; + } + } + } + } + + &-hintbox { + margin: -0.5rem 0 2.4rem; + padding: 0 2.4rem; + + .dc-hint-box { + &__icon { + align-self: flex-start; + } + } + } + + &-icon { + margin-right: 0.8rem; + } + + &-line { + border-top: 1px solid var(--general-section-5); + margin: 1.6rem 0; + width: 100%; + } + + &-payment-method { + padding: 0 2.4rem; + &--container { + align-self: center; + display: flex; + flex-direction: column; + margin-bottom: 1.6rem; + padding: 0 2.4rem; + } + + &--icon { + border-radius: 2px; + margin-right: 0.8rem; + } + + &--row { + align-items: center; + display: flex; + flex-direction: row; + margin-bottom: 0.8rem; + } + + &--title { + margin-bottom: 0.8rem; + } + } + + &-receive-amount { + @include mobile { + border-top: 1px solid var(--general-section-2); + padding: 0.8rem 1.6rem; + background-color: var(--general-main-1); + } + } + + &--sell-payment-methods { + display: flex; + flex-wrap: wrap; + gap: 0.8rem; + margin: 1.6rem 0 2.4rem; + + .payment-method-card { + margin: unset; + + @include mobile { + min-height: 8.8rem; + min-width: unset; + width: 13.6rem; + } + + &--add { + margin: unset; + + @include mobile { + min-height: 8.8rem; + width: 13.6rem; + } + } + &__body { + margin-top: 0.8rem; + + @include mobile { + margin-top: 0; + } + } + } + + &--disable { + opacity: 0.32; + } + } + + &--layout { + padding: unset; + } + + &--error-message { + padding: 0 2.4rem; + } +} + +.dc-modal__container_buy-sell-form { + .dc-modal-header--buy-sell-form { + border-bottom: 2px solid var(--general-section-5); + } + + .dc-modal-footer--separator { + margin-top: 1rem; + border-top: 2px solid var(--general-section-5); + } +} diff --git a/packages/p2p/src/components/buy-sell/buy-sell-header.jsx b/packages/p2p/src/pages/buy-sell/buy-sell-header.jsx similarity index 79% rename from packages/p2p/src/components/buy-sell/buy-sell-header.jsx rename to packages/p2p/src/pages/buy-sell/buy-sell-header.jsx index a095b6d0dd4f..f8ef9244fc61 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-header.jsx +++ b/packages/p2p/src/pages/buy-sell/buy-sell-header.jsx @@ -7,11 +7,11 @@ import { observer } from 'mobx-react-lite'; import classNames from 'classnames'; import { buy_sell } from 'Constants/buy-sell'; import { localize } from 'Components/i18next'; -import ToggleContainer from 'Components/misc/toggle-container.jsx'; -import SortDropdown from 'Components/buy-sell/sort-dropdown.jsx'; +import ToggleContainer from 'Components/toggle-container'; +import SortDropdown from 'Pages/buy-sell/sort-dropdown'; import { useStores } from 'Stores'; -import CurrencyDropdown from 'Components/buy-sell/currency-dropdown.jsx'; -import 'Components/buy-sell/buy-sell-header.scss'; +import CurrencyDropdown from 'Pages/buy-sell/currency-dropdown.jsx'; +import 'Pages/buy-sell/buy-sell-header.scss'; const getBuySellFilters = () => [ { @@ -70,15 +70,15 @@ const BuySellHeader = ({ table_type }) => { return (
-
+
{ />
{is_currency_selector_visible && } @@ -98,16 +98,16 @@ const BuySellHeader = ({ table_type }) => { placeholder={isDesktop() ? localize('Search by nickname') : localize('Search')} /> -
+
general_store.showModal({ key: 'FilterModal', props: {} })} size={40} /> diff --git a/packages/p2p/src/components/buy-sell/buy-sell-header.scss b/packages/p2p/src/pages/buy-sell/buy-sell-header.scss similarity index 93% rename from packages/p2p/src/components/buy-sell/buy-sell-header.scss rename to packages/p2p/src/pages/buy-sell/buy-sell-header.scss index 8f5af62af972..7b93559da498 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-header.scss +++ b/packages/p2p/src/pages/buy-sell/buy-sell-header.scss @@ -1,4 +1,4 @@ -.buy-sell__header { +.buy-sell-header { display: flex; flex-direction: column; @@ -21,7 +21,7 @@ z-index: 1; } - &-container { + &__container { display: flex; flex-direction: row; justify-content: space-between; @@ -31,7 +31,7 @@ } } - &-filters { + &__filters { height: 3.6rem; width: 16.8rem; @@ -41,7 +41,7 @@ } } - &-match-ads { + &__match-ads { display: flex; flex-direction: row; @@ -61,7 +61,7 @@ } } - &-row { + &__row { display: flex; flex-direction: row; align-items: center; @@ -105,6 +105,7 @@ @include mobile { justify-self: center; margin-left: 0; + margin-top: 0; } } @@ -114,8 +115,8 @@ } } } -} -.buy-sell__header-position-static { - position: static; + &__position-static { + position: static; + } } diff --git a/packages/p2p/src/components/buy-sell/buy-sell-row.jsx b/packages/p2p/src/pages/buy-sell/buy-sell-row.jsx similarity index 92% rename from packages/p2p/src/components/buy-sell/buy-sell-row.jsx rename to packages/p2p/src/pages/buy-sell/buy-sell-row.jsx index ffb59e90c5e0..04f877f19ae6 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-row.jsx +++ b/packages/p2p/src/pages/buy-sell/buy-sell-row.jsx @@ -88,13 +88,7 @@ const BuySellRow = ({ row: advert }) => { />
- + {advertiser_name} @@ -123,13 +117,13 @@ const BuySellRow = ({ row: advert }) => {
- + - + {display_effective_rate} {local_currency} - + { payment_method_names.map((payment_method, key) => { return (
- {payment_method} + + {payment_method} +
); }) ) : ( -
-
+
+ + - + +
)}
{!is_my_advert && ( @@ -223,7 +223,7 @@ const BuySellRow = ({ row: advert }) => { {min_order_amount_limit_display}–{max_order_amount_limit_display} {account_currency} - + {display_effective_rate} {local_currency} @@ -233,7 +233,7 @@ const BuySellRow = ({ row: advert }) => { payment_method_names.map((payment_method, key) => { return (
- + {payment_method}
@@ -241,7 +241,7 @@ const BuySellRow = ({ row: advert }) => { }) ) : (
- + -
diff --git a/packages/p2p/src/components/buy-sell/buy-sell-row.scss b/packages/p2p/src/pages/buy-sell/buy-sell-row.scss similarity index 99% rename from packages/p2p/src/components/buy-sell/buy-sell-row.scss rename to packages/p2p/src/pages/buy-sell/buy-sell-row.scss index 52b8793b0436..1923f9b81315 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-row.scss +++ b/packages/p2p/src/pages/buy-sell/buy-sell-row.scss @@ -84,7 +84,6 @@ @media (max-width: 320px) { padding: 0.4rem; - font-size: 10px; } } diff --git a/packages/p2p/src/components/buy-sell/buy-sell-table.jsx b/packages/p2p/src/pages/buy-sell/buy-sell-table.jsx similarity index 87% rename from packages/p2p/src/components/buy-sell/buy-sell-table.jsx rename to packages/p2p/src/pages/buy-sell/buy-sell-table.jsx index 7f5c6ccda4fc..afc9a3f0822c 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell-table.jsx +++ b/packages/p2p/src/pages/buy-sell/buy-sell-table.jsx @@ -5,10 +5,11 @@ import { isDesktop } from '@deriv/shared'; import { reaction } from 'mobx'; import { observer, useStore } from '@deriv/stores'; import { Localize } from 'Components/i18next'; -import { TableError } from 'Components/table/table-error.jsx'; +import TableError from 'Components/section-error'; import { useStores } from 'Stores'; import BuySellRow from './buy-sell-row.jsx'; -import NoAds from './no-ads/no-ads.jsx'; +import NoAds from 'Pages/buy-sell//no-ads'; +import './buy-sell-table.scss'; const BuySellRowRendererComponent = row_props => { const { buy_sell_store } = useStores(); @@ -49,13 +50,15 @@ const BuySellTable = ({ onScroll }) => { } if (buy_sell_store.api_error_message) { - return ; + return ( + + ); } if (buy_sell_store.items.length) { return ( <> -
+
{ - {list_item.text} - - } + label={{list_item.text}} /> ); })} @@ -88,7 +87,7 @@ const BuySellTable = ({ onScroll }) => { {isDesktop() && ( - + @@ -105,7 +104,7 @@ const BuySellTable = ({ onScroll }) => { )} - + .dc-table__head:first-child { + margin-left: 1.6rem; + } + } + + &__row { + padding: 1.6rem; + grid-template-columns: 2fr 1.5fr 1fr 1.5fr 1fr; + + &:hover { + background-color: var(--general-hover); + } + } + + &--sort { + display: flex; + flex-direction: column; + margin: 1.2rem 2.4rem; + + &--divider { + border-top: 1px solid var(--border-normal); + } + + &-radiogroup { + height: 10rem; + display: flex; + flex-direction: column; + } + } +} diff --git a/packages/p2p/src/components/buy-sell/buy-sell.jsx b/packages/p2p/src/pages/buy-sell/buy-sell.jsx similarity index 92% rename from packages/p2p/src/components/buy-sell/buy-sell.jsx rename to packages/p2p/src/pages/buy-sell/buy-sell.jsx index 0f9107443b27..3e47c84232fd 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell.jsx +++ b/packages/p2p/src/pages/buy-sell/buy-sell.jsx @@ -2,13 +2,12 @@ import React from 'react'; import PropTypes from 'prop-types'; import { observer } from 'mobx-react-lite'; import { localize } from 'Components/i18next'; -import PageReturn from 'Components/page-return/page-return.jsx'; -import Verification from 'Components/verification/verification.jsx'; +import PageReturn from 'Components/page-return'; +import Verification from 'Components/verification'; import { buy_sell } from 'Constants/buy-sell'; import { useStores } from 'Stores'; import BuySellHeader from './buy-sell-header.jsx'; import BuySellTable from './buy-sell-table.jsx'; -import './buy-sell.scss'; const BuySell = () => { const { buy_sell_store, general_store } = useStores(); @@ -23,13 +22,14 @@ const BuySell = () => { return () => { disposeIsListedReaction(); disposeAdvertIntervalReaction(); + general_store.setShouldShowPopup(false); }; // eslint-disable-next-line react-hooks/exhaustive-deps }, []); const onScroll = event => { if (!buy_sell_store.show_advertiser_page) { - previous_scroll_top.current = event.target.scrollTop; + previous_scroll_top.current = event?.target?.scrollTop; } }; diff --git a/packages/p2p/src/components/buy-sell/buy-sell.scss b/packages/p2p/src/pages/buy-sell/buy-sell.scss similarity index 74% rename from packages/p2p/src/components/buy-sell/buy-sell.scss rename to packages/p2p/src/pages/buy-sell/buy-sell.scss index 5857e198168a..ee7674a1a4be 100644 --- a/packages/p2p/src/components/buy-sell/buy-sell.scss +++ b/packages/p2p/src/pages/buy-sell/buy-sell.scss @@ -32,35 +32,6 @@ } } - &__table { - display: flex; - flex: 1; - flex-direction: column; - - &-body { - height: 100%; - flex: 1; - display: flex; - flex-direction: column; - } - - &-sort { - display: flex; - flex-direction: column; - margin: 1.2rem 2.4rem; - - &--divider { - border-top: 1px solid var(--border-normal); - } - - &-radiogroup { - height: 10rem; - display: flex; - flex-direction: column; - } - } - } - &__data-list { flex: 1; @@ -77,15 +48,6 @@ margin: 2rem; } - &__table-header { - display: grid; - grid-template-columns: 2fr 1.5fr 1fr 1.5fr 1fr; - - > .dc-table__head:first-child { - margin-left: 1.6rem; - } - } - &__table-row { padding: 1.6rem; grid-template-columns: 2fr 1.5fr 1fr 1.5fr 1fr; diff --git a/packages/p2p/src/components/buy-sell/currency-dropdown.jsx b/packages/p2p/src/pages/buy-sell/currency-dropdown.jsx similarity index 96% rename from packages/p2p/src/components/buy-sell/currency-dropdown.jsx rename to packages/p2p/src/pages/buy-sell/currency-dropdown.jsx index b93ea09bd191..d3b4d6d16e85 100644 --- a/packages/p2p/src/components/buy-sell/currency-dropdown.jsx +++ b/packages/p2p/src/pages/buy-sell/currency-dropdown.jsx @@ -4,7 +4,7 @@ import { observer } from 'mobx-react-lite'; import { Dropdown, useOnClickOutside } from '@deriv/components'; import { isMobile } from '@deriv/shared'; import { useStores } from 'Stores'; -import { CurrencySelector } from 'Components/buy-sell/currency-selector'; +import { CurrencySelector } from 'Pages/buy-sell/currency-selector'; import { useModalManagerContext } from 'Components/modal-manager/modal-manager-context'; import './currency-dropdown.scss'; diff --git a/packages/p2p/src/components/buy-sell/currency-dropdown.scss b/packages/p2p/src/pages/buy-sell/currency-dropdown.scss similarity index 100% rename from packages/p2p/src/components/buy-sell/currency-dropdown.scss rename to packages/p2p/src/pages/buy-sell/currency-dropdown.scss diff --git a/packages/p2p/src/components/buy-sell/currency-selector/currency-selector.jsx b/packages/p2p/src/pages/buy-sell/currency-selector/currency-selector.jsx similarity index 97% rename from packages/p2p/src/components/buy-sell/currency-selector/currency-selector.jsx rename to packages/p2p/src/pages/buy-sell/currency-selector/currency-selector.jsx index 99a7a4d59d35..7327c3ef2ab3 100644 --- a/packages/p2p/src/components/buy-sell/currency-selector/currency-selector.jsx +++ b/packages/p2p/src/pages/buy-sell/currency-selector/currency-selector.jsx @@ -28,7 +28,7 @@ const CurrencySelector = ({ className, default_value, list, onSelect }) => { { const { buy_sell_store, general_store, my_ads_store } = useStores(); diff --git a/packages/p2p/src/components/buy-sell/no-ads/no-ads.scss b/packages/p2p/src/pages/buy-sell/no-ads/no-ads.scss similarity index 100% rename from packages/p2p/src/components/buy-sell/no-ads/no-ads.scss rename to packages/p2p/src/pages/buy-sell/no-ads/no-ads.scss diff --git a/packages/p2p/src/components/buy-sell/sort-dropdown.jsx b/packages/p2p/src/pages/buy-sell/sort-dropdown.jsx similarity index 96% rename from packages/p2p/src/components/buy-sell/sort-dropdown.jsx rename to packages/p2p/src/pages/buy-sell/sort-dropdown.jsx index 2cdee1c7381f..d85b230fa9f9 100644 --- a/packages/p2p/src/components/buy-sell/sort-dropdown.jsx +++ b/packages/p2p/src/pages/buy-sell/sort-dropdown.jsx @@ -4,7 +4,7 @@ import { isDesktop } from '@deriv/shared'; import { observer } from 'mobx-react-lite'; import { localize } from 'Components/i18next'; import { useStores } from 'Stores'; -import 'Components/buy-sell/sort-dropdown.scss'; +import 'Pages/buy-sell/sort-dropdown.scss'; const SortDropdown = () => { const { buy_sell_store } = useStores(); diff --git a/packages/p2p/src/components/buy-sell/sort-dropdown.scss b/packages/p2p/src/pages/buy-sell/sort-dropdown.scss similarity index 100% rename from packages/p2p/src/components/buy-sell/sort-dropdown.scss rename to packages/p2p/src/pages/buy-sell/sort-dropdown.scss diff --git a/packages/p2p/src/components/my-ads/__tests__/ad-status.spec.js b/packages/p2p/src/pages/my-ads/__tests__/ad-status.spec.js similarity index 100% rename from packages/p2p/src/components/my-ads/__tests__/ad-status.spec.js rename to packages/p2p/src/pages/my-ads/__tests__/ad-status.spec.js diff --git a/packages/p2p/src/components/my-ads/__tests__/my-ads-table.spec.jsx b/packages/p2p/src/pages/my-ads/__tests__/my-ads-table.spec.jsx similarity index 100% rename from packages/p2p/src/components/my-ads/__tests__/my-ads-table.spec.jsx rename to packages/p2p/src/pages/my-ads/__tests__/my-ads-table.spec.jsx diff --git a/packages/p2p/src/components/my-ads/ad-status.jsx b/packages/p2p/src/pages/my-ads/ad-status.jsx similarity index 100% rename from packages/p2p/src/components/my-ads/ad-status.jsx rename to packages/p2p/src/pages/my-ads/ad-status.jsx diff --git a/packages/p2p/src/components/my-ads/ad-status.scss b/packages/p2p/src/pages/my-ads/ad-status.scss similarity index 100% rename from packages/p2p/src/components/my-ads/ad-status.scss rename to packages/p2p/src/pages/my-ads/ad-status.scss diff --git a/packages/p2p/src/components/my-ads/ad-type.jsx b/packages/p2p/src/pages/my-ads/ad-type.jsx similarity index 69% rename from packages/p2p/src/components/my-ads/ad-type.jsx rename to packages/p2p/src/pages/my-ads/ad-type.jsx index a8751925d843..7d796a62a8a9 100644 --- a/packages/p2p/src/components/my-ads/ad-type.jsx +++ b/packages/p2p/src/pages/my-ads/ad-type.jsx @@ -7,17 +7,10 @@ import './ad-type.scss'; const AdType = ({ ad_pause_color, float_rate }) => { return (
- + {localize('Float')} - + {float_rate}%
diff --git a/packages/p2p/src/components/my-ads/ad-type.scss b/packages/p2p/src/pages/my-ads/ad-type.scss similarity index 100% rename from packages/p2p/src/components/my-ads/ad-type.scss rename to packages/p2p/src/pages/my-ads/ad-type.scss diff --git a/packages/p2p/src/components/my-ads/buy-ad-payment-methods-list.jsx b/packages/p2p/src/pages/my-ads/buy-ad-payment-methods-list.jsx similarity index 99% rename from packages/p2p/src/components/my-ads/buy-ad-payment-methods-list.jsx rename to packages/p2p/src/pages/my-ads/buy-ad-payment-methods-list.jsx index 0fb42cedfa3e..6e753c5b3a38 100644 --- a/packages/p2p/src/components/my-ads/buy-ad-payment-methods-list.jsx +++ b/packages/p2p/src/pages/my-ads/buy-ad-payment-methods-list.jsx @@ -134,7 +134,7 @@ const BuyAdPaymentMethodsList = ({ my_ads_store.current_method.key === key && my_ads_store.current_method.is_deleted ? (
{ my_ads_store.setShowFilterPaymentMethods(isMobile()); @@ -291,7 +291,7 @@ const BuyAdPaymentMethodsList = ({ {({ field }) => (
my_ads_store.setShowFilterPaymentMethods(isMobile())} > {({ field }) => (
my_ads_store.setShowFilterPaymentMethods(isMobile())} > { const { showModal } = useModalManagerContext(); diff --git a/packages/p2p/src/components/my-ads/create-ad-form.jsx b/packages/p2p/src/pages/my-ads/create-ad-form.jsx similarity index 92% rename from packages/p2p/src/components/my-ads/create-ad-form.jsx rename to packages/p2p/src/pages/my-ads/create-ad-form.jsx index b4fad24eba60..924b7596761f 100644 --- a/packages/p2p/src/components/my-ads/create-ad-form.jsx +++ b/packages/p2p/src/pages/my-ads/create-ad-form.jsx @@ -1,4 +1,5 @@ -import React from 'react'; +import * as React from 'react'; +import classNames from 'classnames'; import { Formik, Field, Form } from 'formik'; import { Button, @@ -23,6 +24,7 @@ import CreateAdSummary from './create-ad-summary.jsx'; import CreateAdFormPaymentMethods from './create-ad-form-payment-methods.jsx'; import { useModalManagerContext } from 'Components/modal-manager/modal-manager-context'; import { api_error_codes } from '../../constants/api-error-codes.js'; +import './create-ad-form.scss'; const CreateAdFormWrapper = ({ children }) => { if (isMobile()) { @@ -157,19 +159,19 @@ const CreateAdForm = () => { }; return ( -
+
-
+
{({ field }) => ( onChangeAdTypeHandler(event.target.value)} selected={values.type} @@ -186,19 +188,18 @@ const CreateAdForm = () => { )} -
- -
-
+ + +
{({ field }) => ( { type='text' error={touched.offer_amount && errors.offer_amount} label={localize('Total amount')} - className='p2p-my-ads__form-field' + className={classNames('create-ad-form__field', { + 'create-ad-form__offer-amt__sell-ad': + values.type === buy_sell.SELL, + })} trailing_icon={ {currency} @@ -248,7 +251,7 @@ const CreateAdForm = () => { {({ field }) => floating_rate_store.rate_type === ad_type.FLOAT ? ( { label={localize('Fixed rate (1 {{currency}})', { currency, })} - className='p2p-my-ads__form-field' + className='create-ad-form__field' trailing_icon={ {local_currency_config.currency} @@ -300,7 +302,7 @@ const CreateAdForm = () => { }
-
+
{({ field }) => ( { type='text' error={touched.min_transaction && errors.min_transaction} label={localize('Min order')} - className='p2p-my-ads__form-field' + className='create-ad-form__field' trailing_icon={ {currency} @@ -336,11 +337,10 @@ const CreateAdForm = () => { type='text' error={touched.max_transaction && errors.max_transaction} label={localize('Max order')} - className='p2p-my-ads__form-field' + className='create-ad-form__field' trailing_icon={ {currency} @@ -355,7 +355,7 @@ const CreateAdForm = () => {
{is_sell_advert && ( -
+
{({ field }) => ( { } error={touched.contact_info && errors.contact_info} - className='p2p-my-ads__form-field p2p-my-ads__form-field--textarea' + className='create-ad-form__field create-ad-form__field--textarea' initial_character_count={ general_store.contact_info.length } @@ -398,7 +398,7 @@ const CreateAdForm = () => { } hint={localize('This information will be visible to everyone.')} - className='p2p-my-ads__form-field p2p-my-ads__form-field--textarea' + className='create-ad-form__field create-ad-form__field--textarea' initial_character_count={ general_store.default_advert_description.length } @@ -408,7 +408,7 @@ const CreateAdForm = () => { /> )} -
+
@@ -425,9 +425,9 @@ const CreateAdForm = () => { is_sell_advert={is_sell_advert} />
-
+
{isDesktop() && ( - + {getHeaders(currency).map(header => ( {header.text} ))} )} - + item.id} @@ -129,9 +130,9 @@ const MyAdsTable = () => {
{isMobile() && ( -
+