From dd5c4b33ca1859343bfb4366c9eb274a33bdc948 Mon Sep 17 00:00:00 2001 From: Nada Date: Mon, 10 Jun 2024 12:59:19 +0400 Subject: [PATCH 01/15] Fix: --- package-lock.json | 86 +++++++++++++++ package.json | 1 + src/components/DatePicker/DatePicker.scss | 0 src/components/DatePicker/DatePicker.tsx | 103 ++++++++++++++++++ src/components/DatePicker/index.ts | 1 + src/components/DatePicker/utils.ts | 13 +++ .../FlowTextField/FlowTextField.tsx | 81 ++++++++++++++ src/components/FlowTextField/index.ts | 0 src/components/index.ts | 1 + .../OrdersTableHeader/OrdersTableHeader.tsx | 2 + 10 files changed, 288 insertions(+) create mode 100644 src/components/DatePicker/DatePicker.scss create mode 100644 src/components/DatePicker/DatePicker.tsx create mode 100644 src/components/DatePicker/index.ts create mode 100644 src/components/DatePicker/utils.ts create mode 100644 src/components/FlowTextField/FlowTextField.tsx create mode 100644 src/components/FlowTextField/index.ts diff --git a/package-lock.json b/package-lock.json index e66f9f92..bf88ff3f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -30,6 +30,7 @@ "moment": "^2.30.1", "qrcode.react": "^3.1.0", "react": "^18.2.0", + "react-calendar": "^5.0.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-hook-form": "^7.51.1", @@ -6057,6 +6058,14 @@ "@xtuc/long": "4.2.2" } }, + "node_modules/@wojtekmaj/date-utils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/@wojtekmaj/date-utils/-/date-utils-1.5.1.tgz", + "integrity": "sha512-+i7+JmNiE/3c9FKxzWFi2IjRJ+KzZl1QPu6QNrsgaa2MuBgXvUy4gA1TVzf/JMdIIloB76xSKikTWuyYAIVLww==", + "funding": { + "url": "https://github.com/wojtekmaj/date-utils?sponsor=1" + } + }, "node_modules/@xmldom/xmldom": { "version": "0.8.10", "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz", @@ -10782,6 +10791,17 @@ "url": "https://github.com/privatenumber/get-tsconfig?sponsor=1" } }, + "node_modules/get-user-locale": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/get-user-locale/-/get-user-locale-2.3.2.tgz", + "integrity": "sha512-O2GWvQkhnbDoWFUJfaBlDIKUEdND8ATpBXD6KXcbhxlfktyD/d8w6mkzM/IlQEqGZAMz/PW6j6Hv53BiigKLUQ==", + "dependencies": { + "mem": "^8.0.0" + }, + "funding": { + "url": "https://github.com/wojtekmaj/get-user-locale?sponsor=1" + } + }, "node_modules/git-raw-commits": { "version": "2.0.11", "resolved": "https://registry.npmjs.org/git-raw-commits/-/git-raw-commits-2.0.11.tgz", @@ -14988,6 +15008,17 @@ "tmpl": "1.0.5" } }, + "node_modules/map-age-cleaner": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/map-age-cleaner/-/map-age-cleaner-0.1.3.tgz", + "integrity": "sha512-bJzx6nMoP6PDLPBFmg7+xRKeFZvFboMrGlxmNj9ClvX53KrmvM5bXFXEWjbz4cz1AFn+jWJ9z/DJSz7hrs0w3w==", + "dependencies": { + "p-defer": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -15060,6 +15091,29 @@ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.30.tgz", "integrity": "sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==" }, + "node_modules/mem": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/mem/-/mem-8.1.1.tgz", + "integrity": "sha512-qFCFUDs7U3b8mBDPyz5EToEKoAkgCzqquIgi9nkkR9bixxOVOre+09lbuH7+9Kn2NFpm56M3GUWVbU2hQgdACA==", + "dependencies": { + "map-age-cleaner": "^0.1.3", + "mimic-fn": "^3.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/mem?sponsor=1" + } + }, + "node_modules/mem/node_modules/mimic-fn": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-3.1.0.tgz", + "integrity": "sha512-Ysbi9uYW9hFyfrThdDEQuykN4Ey6BuwPD2kpI5ES/nFTDn/98yxYNLZJcgUAKPT/mcrLLKaGzJR9YVxJrIdASQ==", + "engines": { + "node": ">=8" + } + }, "node_modules/memory-fs": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.2.0.tgz", @@ -15640,6 +15694,14 @@ "node": ">= 0.8.0" } }, + "node_modules/p-defer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-defer/-/p-defer-1.0.0.tgz", + "integrity": "sha512-wB3wfAxZpk2AzOfUMJNL+d36xothRSyj8EXOa4f6GMqYDN9BJaaSISbsk+wS9abmnebVw95C2Kb5t85UmpCxuw==", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -16605,6 +16667,30 @@ "node": ">=0.10.0" } }, + "node_modules/react-calendar": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/react-calendar/-/react-calendar-5.0.0.tgz", + "integrity": "sha512-bHcE5e5f+VUKLd4R19BGkcSQLpuwjKBVG0fKz74cwPW5xDfNsReHdDbfd4z3mdjuUuZzVtw4Q920mkwK5/ZOEg==", + "dependencies": { + "@wojtekmaj/date-utils": "^1.1.3", + "clsx": "^2.0.0", + "get-user-locale": "^2.2.1", + "warning": "^4.0.0" + }, + "funding": { + "url": "https://github.com/wojtekmaj/react-calendar?sponsor=1" + }, + "peerDependencies": { + "@types/react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + } + } + }, "node_modules/react-dom": { "version": "18.3.1", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz", diff --git a/package.json b/package.json index f18cf7e6..9c59cb3c 100644 --- a/package.json +++ b/package.json @@ -36,6 +36,7 @@ "moment": "^2.30.1", "qrcode.react": "^3.1.0", "react": "^18.2.0", + "react-calendar": "^5.0.0", "react-dom": "^18.2.0", "react-dropzone": "^14.2.3", "react-hook-form": "^7.51.1", diff --git a/src/components/DatePicker/DatePicker.scss b/src/components/DatePicker/DatePicker.scss new file mode 100644 index 00000000..e69de29b diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx new file mode 100644 index 00000000..760f7fe6 --- /dev/null +++ b/src/components/DatePicker/DatePicker.tsx @@ -0,0 +1,103 @@ +import { useEffect, useRef, useState } from 'react'; +import Calendar, { CalendarProps } from 'react-calendar'; +import { useOnClickOutside } from 'usehooks-ts'; +import { LegacyCalendar1pxIcon } from '@deriv/quill-icons'; +import FlowTextField, { TFlowFieldProps } from '../FlowTextField/FlowTextField'; +import { customFormatShortWeekday, unixToDateString } from './utils'; +import 'react-calendar/dist/Calendar.css'; +import './DatePicker.scss'; + +interface TDatePickerProps extends TFlowFieldProps { + displayFormat?: string; + maxDate?: Date; + minDate?: Date; + mobileAlignment?: 'above' | 'below'; + onDateChange: (formattedDate: string | null) => void; +} + +const DatePicker = ({ + defaultValue, + disabled, + displayFormat = 'YYYY-MM-DD', + label, + maxDate, + message, + minDate, + mobileAlignment = 'below', + name, + onDateChange, + validationSchema, +}: TDatePickerProps) => { + console.log('here'); + const [selectedDate, setSelectedDate] = useState(defaultValue ? new Date(defaultValue) : null); + const [isCalendarOpen, setIsCalendarOpen] = useState(false); + const datePickerRef = useRef(null); + const inputeDateRef = useRef(null); + + const toggleCalendar = () => { + setIsCalendarOpen(prevState => !prevState); + }; + + useOnClickOutside(datePickerRef, () => { + setIsCalendarOpen(false); + }); + + const handleDateChange: CalendarProps['onChange'] = value => { + const calendarSelectedDate = Array.isArray(value) ? value[0] : value; + setSelectedDate(calendarSelectedDate); + setIsCalendarOpen(false); + }; + + useEffect(() => { + if (selectedDate !== null) { + onDateChange(unixToDateString(selectedDate)); + } + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [selectedDate]); + + return ( +
+ e.preventDefault()} + ref={inputeDateRef} + renderRightIcon={() => ( + + )} + showMessage + type='text' + validationSchema={validationSchema} + value={selectedDate !== null ? unixToDateString(selectedDate, displayFormat) : ''} + /> + {isCalendarOpen && ( +
+ +
+ )} +
+ ); +}; + +export default DatePicker; diff --git a/src/components/DatePicker/index.ts b/src/components/DatePicker/index.ts new file mode 100644 index 00000000..5a316c5b --- /dev/null +++ b/src/components/DatePicker/index.ts @@ -0,0 +1 @@ +export { default as DatePicker } from './DatePicker'; diff --git a/src/components/DatePicker/utils.ts b/src/components/DatePicker/utils.ts new file mode 100644 index 00000000..363ded47 --- /dev/null +++ b/src/components/DatePicker/utils.ts @@ -0,0 +1,13 @@ +import moment from 'moment'; + +export function customFormatShortWeekday(_locale: string | undefined, date: Date) { + const weekdays = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; + + return weekdays[date.getDay()]; +} + +export function unixToDateString(date: Date, format = 'YYYY-MM-DD') { + const formattedDate = moment(date).format(format); + + return formattedDate; +} diff --git a/src/components/FlowTextField/FlowTextField.tsx b/src/components/FlowTextField/FlowTextField.tsx new file mode 100644 index 00000000..d5639b16 --- /dev/null +++ b/src/components/FlowTextField/FlowTextField.tsx @@ -0,0 +1,81 @@ +import React, { forwardRef, Ref, useEffect, useState } from 'react'; +import { Controller, useForm } from 'react-hook-form'; +import * as Yup from 'yup'; +import { Text } from '@deriv-com/ui'; +import WalletTextField, { WalletTextFieldProps } from '../Base/WalletTextField/WalletTextField'; +import { useFlow } from '../FlowProvider'; +import { TextField } from '../TextField'; + +export interface TFlowFieldProps extends WalletTextFieldProps { + isInvalid?: WalletTextFieldProps['isInvalid']; + name: string; + validationSchema?: Yup.AnySchema; +} + +/** + * This component is just a wrapper to the Field Formik component and WalletTextField + * Use this component when you are using the FlowProvider with a form and several inputs, + * and you want those input values to be tracked and validated + */ +const FlowTextField = forwardRef( + ( + { defaultValue, disabled, errorMessage, isInvalid, name, validationSchema, ...rest }: TFlowFieldProps, + ref: Ref + ) => { + const { control } = useForm(); + const [hasTouched, setHasTouched] = useState(false); + const { setFormValues } = useFlow(); + + const validateField = (value: unknown) => { + try { + if (validationSchema) { + validationSchema.validateSync(value); + } + } catch (err: unknown) { + return (err as Yup.ValidationError).message; + } + }; + + useEffect(() => { + const setFormValuesAndTouch = async () => { + if (defaultValue) { + await setFormValues(name, defaultValue, true); + console.log('asdfasdf'); + } + }; + + setFormValuesAndTouch(); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + return ( + { + return ( +
+ { + setHasTouched(true); + field.onBlur(e); + }} + ref={ref} + /> +
+ ); + }} + /> + ); + } +); + +FlowTextField.displayName = 'FlowTextField'; +export default FlowTextField; diff --git a/src/components/FlowTextField/index.ts b/src/components/FlowTextField/index.ts new file mode 100644 index 00000000..e69de29b diff --git a/src/components/index.ts b/src/components/index.ts index 663ba46b..8f6c7614 100644 --- a/src/components/index.ts +++ b/src/components/index.ts @@ -6,6 +6,7 @@ export * from './Badge'; export * from './BuySellForm'; export * from './Checklist'; export * from './Clipboard'; +export * from './DatePicker'; export * from './DerivIframe'; export * from './FileDropzone'; export * from './FloatingRate'; diff --git a/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.tsx b/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.tsx index da24ab78..12481213 100644 --- a/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.tsx +++ b/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.tsx @@ -1,3 +1,4 @@ +import { DatePicker } from '@/components'; import { ORDERS_STATUS } from '@/constants/orders'; import { useQueryString } from '@/hooks/custom-hooks'; import { getLocalizedTabs } from '@/utils/tabs'; @@ -30,6 +31,7 @@ const OrdersTableHeader = ({ activeTab }: TOrdersTableHeaderProps) => { + console.log(value)} /> ); }; From f6203653c789a8fa4c535103738a7ce193b8e9dc Mon Sep 17 00:00:00 2001 From: Nada Date: Tue, 11 Jun 2024 15:05:38 +0400 Subject: [PATCH 02/15] feat: date filter for past orders --- package-lock.json | 8 +- package.json | 2 +- src/components/DatePicker/DatePicker.scss | 147 ++++++++++++++++++ src/components/DatePicker/DatePicker.tsx | 67 ++++---- .../DateTextField/DateTextField.scss | 34 ++++ .../DateTextField/DateTextField.tsx | 31 ++++ src/components/DateTextField/index.ts | 1 + .../FlowTextField/FlowTextField.tsx | 81 ---------- src/components/FlowTextField/index.ts | 0 .../FullPageMobileWrapper.tsx | 9 +- .../OrdersDateSelection.scss | 19 +++ .../OrdersDateSelection.tsx | 76 +++++++++ .../components/OrdersDateSelection/index.ts | 1 + .../OrdersDateSelectionFullPage.scss | 21 +++ .../OrdersDateSelectionFullPage.tsx | 88 +++++++++++ .../OrdersDateSelectionFullPage/index.ts | 1 + src/pages/orders/components/index.ts | 1 + src/pages/orders/screens/Orders/Orders.tsx | 33 +++- .../OrdersTableHeader/OrdersTableHeader.scss | 9 ++ .../OrdersTableHeader/OrdersTableHeader.tsx | 18 ++- .../__tests__/OrdersTableHeader.spec.tsx | 24 ++- 21 files changed, 537 insertions(+), 134 deletions(-) create mode 100644 src/components/DateTextField/DateTextField.scss create mode 100644 src/components/DateTextField/DateTextField.tsx create mode 100644 src/components/DateTextField/index.ts delete mode 100644 src/components/FlowTextField/FlowTextField.tsx delete mode 100644 src/components/FlowTextField/index.ts create mode 100644 src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.scss create mode 100644 src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx create mode 100644 src/pages/orders/components/OrdersDateSelection/index.ts create mode 100644 src/pages/orders/components/OrdersDateSelectionFullPage/OrdersDateSelectionFullPage.scss create mode 100644 src/pages/orders/components/OrdersDateSelectionFullPage/OrdersDateSelectionFullPage.tsx create mode 100644 src/pages/orders/components/OrdersDateSelectionFullPage/index.ts diff --git a/package-lock.json b/package-lock.json index bf88ff3f..ea9eb719 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "@babel/preset-env": "^7.24.5", "@deriv-com/api-hooks": "^0.1.24", "@deriv-com/translations": "^1.2.4", - "@deriv-com/ui": "^1.27.9", + "@deriv-com/ui": "^1.28.0", "@deriv-com/utils": "latest", "@deriv/deriv-api": "^1.0.15", "@deriv/quill-design": "^1.2.24", @@ -2676,9 +2676,9 @@ } }, "node_modules/@deriv-com/ui": { - "version": "1.27.9", - "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.27.9.tgz", - "integrity": "sha512-zsNJ/ShXFjNp39VX1f87W9dnh3DSYUl77p3GJ9nyyDem7F43gXJK8MyVFLd0eP5eXlKNkoUttU0CvIIvQxFgDA==", + "version": "1.28.0", + "resolved": "https://registry.npmjs.org/@deriv-com/ui/-/ui-1.28.0.tgz", + "integrity": "sha512-CzkjM6f+xEklcQ88H9/Y3Zho8tBVDxWa73awLKHYx0KBM6g6NXF+6J9BCJGY8DCofbz0+1Q/2QnzuuNaOlX/KQ==", "dependencies": { "@types/react-modal": "^3.16.3", "react-tiny-popover": "^8.0.4" diff --git a/package.json b/package.json index 9c59cb3c..c32bf3e1 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "@babel/preset-env": "^7.24.5", "@deriv-com/api-hooks": "^0.1.24", "@deriv-com/translations": "^1.2.4", - "@deriv-com/ui": "^1.27.9", + "@deriv-com/ui": "^1.28.0", "@deriv-com/utils": "latest", "@deriv/deriv-api": "^1.0.15", "@deriv/quill-design": "^1.2.24", diff --git a/src/components/DatePicker/DatePicker.scss b/src/components/DatePicker/DatePicker.scss index e69de29b..61da459f 100644 --- a/src/components/DatePicker/DatePicker.scss +++ b/src/components/DatePicker/DatePicker.scss @@ -0,0 +1,147 @@ +.datepicker { + display: flex; + flex-direction: column; + position: relative; + caret-color: transparent; + + &__button { + all: unset; + cursor: pointer; + + &:disabled { + filter: invert(92%) sepia(0%) saturate(112%) hue-rotate(253deg) brightness(106%) contrast(89%); + } + } + + &__container { + position: absolute; + display: inline-block; + width: 28rem; + z-index: 1; + + &--right { + right: 0; + } + + top: 4rem; + + @include mobile { + align-self: center; + top: 5rem; + left: 0; + } + + .react-calendar { + border-radius: 0.5rem; + + button { + border-radius: 0.5rem; + } + + &__navigation { + border-bottom: 0.1rem solid #d6dadb; + height: 5rem; + padding: 1.6rem; + margin-bottom: 0; + + &__arrow { + font-size: 2.4rem; + justify-content: center; + align-items: center; + } + + &__label { + font-weight: bold; + font-size: 1.4rem; + margin-top: 0.5rem; + display: flex; + justify-content: center; + } + + button { + min-width: 2.4rem; + padding: 0 0.6rem; + border-radius: 0.5rem; + + &:enabled:hover, + &:enabled:focus, + &:disabled { + background-color: unset; + } + } + } + + &__viewContainer { + padding: 0.8rem 2rem; + } + + &__month-view { + &__days, + &__weekdays { + /* stylelint-disable-next-line declaration-no-important */ + display: grid !important; // to overwrite flex property of calendar + grid-template-columns: repeat(7, 2.4rem); + grid-auto-rows: 2.4rem; + grid-gap: 1.2rem; + align-items: center; + justify-content: center; + + &__day--neighboringMonth { + color: #757575; + } + + &__day--weekend { + color: revert; + } + + &__weekday { + font-size: 1.2rem; + } + abbr { + text-decoration: none; + } + } + + &__weekdays { + margin-bottom: 1.2rem; + } + + button { + min-width: 2.4rem; + padding: 0.6rem; + border-radius: 0.5rem; + } + } + + &__tile { + font-size: 1.2rem; + + &--active, + &--hasActive { + border-radius: 0.5rem; + background: #d6dadb; + color: unset; + + &:enabled:hover, + &:enabled:focus { + background-color: #d6dadb; + } + } + + &--active { + font-weight: bold; + } + + &--now, + &:disabled { + background-color: unset; + } + } + } + + /* stylelint-disable-next-line selector-class-pattern */ + .react-calendar__month-view__days__day--weekend.react-calendar__month-view__days__day--neighboringMonth { + color: #757575; + } + } +} diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx index 760f7fe6..d20eb861 100644 --- a/src/components/DatePicker/DatePicker.tsx +++ b/src/components/DatePicker/DatePicker.tsx @@ -1,38 +1,40 @@ -import { useEffect, useRef, useState } from 'react'; +import { ComponentProps, useEffect, useRef, useState } from 'react'; +import clsx from 'clsx'; import Calendar, { CalendarProps } from 'react-calendar'; import { useOnClickOutside } from 'usehooks-ts'; -import { LegacyCalendar1pxIcon } from '@deriv/quill-icons'; -import FlowTextField, { TFlowFieldProps } from '../FlowTextField/FlowTextField'; +import DateTextField from '../DateTextField/DateTextField'; import { customFormatShortWeekday, unixToDateString } from './utils'; import 'react-calendar/dist/Calendar.css'; import './DatePicker.scss'; -interface TDatePickerProps extends TFlowFieldProps { +interface TDatePickerProps extends ComponentProps { + alignedRight?: boolean; displayFormat?: string; maxDate?: Date; minDate?: Date; mobileAlignment?: 'above' | 'below'; - onDateChange: (formattedDate: string | null) => void; + onDateChange: (date: string) => void; + rightAlignment?: boolean; + showLabel?: boolean; + value?: string; } const DatePicker = ({ - defaultValue, + alignedRight, disabled, - displayFormat = 'YYYY-MM-DD', + displayFormat = 'MMM DD, YYYY', label, maxDate, - message, minDate, - mobileAlignment = 'below', name, onDateChange, - validationSchema, + rightAlignment = false, + showLabel = false, + value, }: TDatePickerProps) => { - console.log('here'); - const [selectedDate, setSelectedDate] = useState(defaultValue ? new Date(defaultValue) : null); + const [selectedDate, setSelectedDate] = useState(value ? new Date(value) : null); const [isCalendarOpen, setIsCalendarOpen] = useState(false); const datePickerRef = useRef(null); - const inputeDateRef = useRef(null); const toggleCalendar = () => { setIsCalendarOpen(prevState => !prevState); @@ -50,45 +52,42 @@ const DatePicker = ({ useEffect(() => { if (selectedDate !== null) { - onDateChange(unixToDateString(selectedDate)); + onDateChange(unixToDateString(selectedDate, displayFormat)); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedDate]); + const getValue = () => { + const isToday = selectedDate !== null && selectedDate.getDate() === new Date().getDate(); + if (selectedDate !== null && selectedDate !== new Date() && (!isToday || showLabel)) { + return unixToDateString(selectedDate, displayFormat); + } + return ''; + }; + return ( -
- + e.preventDefault()} - ref={inputeDateRef} - renderRightIcon={() => ( - - )} - showMessage type='text' - validationSchema={validationSchema} - value={selectedDate !== null ? unixToDateString(selectedDate, displayFormat) : ''} + value={getValue()} /> {isCalendarOpen && (
{ + alignedRight?: boolean; +} + +const DateTextField = ({ alignedRight = false, label, value, ...rest }: TFlowFieldProps) => { + return ( +
+ } + readOnly + rightPlaceholder={alignedRight && } + value={value} + wrapperClassName='w-full' + /> +
+ ); +}; + +export default DateTextField; diff --git a/src/components/DateTextField/index.ts b/src/components/DateTextField/index.ts new file mode 100644 index 00000000..a68f2bc1 --- /dev/null +++ b/src/components/DateTextField/index.ts @@ -0,0 +1 @@ +export { default as DateTextField } from './DateTextField'; diff --git a/src/components/FlowTextField/FlowTextField.tsx b/src/components/FlowTextField/FlowTextField.tsx deleted file mode 100644 index d5639b16..00000000 --- a/src/components/FlowTextField/FlowTextField.tsx +++ /dev/null @@ -1,81 +0,0 @@ -import React, { forwardRef, Ref, useEffect, useState } from 'react'; -import { Controller, useForm } from 'react-hook-form'; -import * as Yup from 'yup'; -import { Text } from '@deriv-com/ui'; -import WalletTextField, { WalletTextFieldProps } from '../Base/WalletTextField/WalletTextField'; -import { useFlow } from '../FlowProvider'; -import { TextField } from '../TextField'; - -export interface TFlowFieldProps extends WalletTextFieldProps { - isInvalid?: WalletTextFieldProps['isInvalid']; - name: string; - validationSchema?: Yup.AnySchema; -} - -/** - * This component is just a wrapper to the Field Formik component and WalletTextField - * Use this component when you are using the FlowProvider with a form and several inputs, - * and you want those input values to be tracked and validated - */ -const FlowTextField = forwardRef( - ( - { defaultValue, disabled, errorMessage, isInvalid, name, validationSchema, ...rest }: TFlowFieldProps, - ref: Ref - ) => { - const { control } = useForm(); - const [hasTouched, setHasTouched] = useState(false); - const { setFormValues } = useFlow(); - - const validateField = (value: unknown) => { - try { - if (validationSchema) { - validationSchema.validateSync(value); - } - } catch (err: unknown) { - return (err as Yup.ValidationError).message; - } - }; - - useEffect(() => { - const setFormValuesAndTouch = async () => { - if (defaultValue) { - await setFormValues(name, defaultValue, true); - console.log('asdfasdf'); - } - }; - - setFormValuesAndTouch(); - // eslint-disable-next-line react-hooks/exhaustive-deps - }, []); - - return ( - { - return ( -
- { - setHasTouched(true); - field.onBlur(e); - }} - ref={ref} - /> -
- ); - }} - /> - ); - } -); - -FlowTextField.displayName = 'FlowTextField'; -export default FlowTextField; diff --git a/src/components/FlowTextField/index.ts b/src/components/FlowTextField/index.ts deleted file mode 100644 index e69de29b..00000000 diff --git a/src/components/FullPageMobileWrapper/FullPageMobileWrapper.tsx b/src/components/FullPageMobileWrapper/FullPageMobileWrapper.tsx index dfe3fcb9..f4815da4 100644 --- a/src/components/FullPageMobileWrapper/FullPageMobileWrapper.tsx +++ b/src/components/FullPageMobileWrapper/FullPageMobileWrapper.tsx @@ -1,6 +1,6 @@ import { PropsWithChildren, ReactNode } from 'react'; import clsx from 'clsx'; -import { LabelPairedArrowLeftLgBoldIcon } from '@deriv/quill-icons'; +import { LabelPairedArrowLeftLgBoldIcon, StandaloneXmarkBoldIcon } from '@deriv/quill-icons'; import './FullPageMobileWrapper.scss'; type TFullPageMobileWrapperProps = { @@ -10,6 +10,7 @@ type TFullPageMobileWrapperProps = { renderHeader?: () => ReactNode; shouldFixedFooter?: boolean; shouldShowBackIcon?: boolean; + shouldShowCloseIcon?: boolean; }; const FullPageMobileWrapper = ({ @@ -20,6 +21,7 @@ const FullPageMobileWrapper = ({ renderHeader, shouldFixedFooter = true, shouldShowBackIcon = true, + shouldShowCloseIcon = false, }: PropsWithChildren) => { return (
)} {renderHeader()} + {shouldShowCloseIcon && ( +
+ +
+ )}
)}
{children}
diff --git a/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.scss b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.scss new file mode 100644 index 00000000..0ce8ceee --- /dev/null +++ b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.scss @@ -0,0 +1,19 @@ +.orders-date-selection { + @include desktop { + display: flex; + flex-direction: row; + gap: 0.8rem; + padding: 0.4rem 0; + align-items: center; + } + + @include mobile { + margin-top: 1.6rem; + } + + &__input { + input { + padding-left: 1rem; + } + } +} diff --git a/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx new file mode 100644 index 00000000..70758be8 --- /dev/null +++ b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx @@ -0,0 +1,76 @@ +import { Dispatch, SetStateAction, useState } from 'react'; +import { DatePicker } from '@/components'; +import { LabelPairedCalendarRangeMdRegularIcon } from '@deriv/quill-icons'; +import { useTranslations } from '@deriv-com/translations'; +import { Input, useDevice } from '@deriv-com/ui'; +import { OrdersDateSelectionFullPage } from '../OrdersDateSelectionFullPage'; +import './OrdersDateSelection.scss'; + +type TOrdersDateSelectionProps = { + fromDate: string | null; + setFromDate: Dispatch>; + setToDate: Dispatch>; + toDate: string | null; +}; + +const OrdersDateSelection = ({ fromDate, setFromDate, setToDate, toDate }: TOrdersDateSelectionProps) => { + const { isMobile } = useDevice(); + const { localize } = useTranslations(); + const [isDateSelectionOpen, setIsDateSelectionOpen] = useState(false); + + const getMaxDate = () => { + if (toDate) { + return new Date(toDate); + } + return new Date(); + }; + + if (isMobile) { + return ( +
+ } + onClick={() => setIsDateSelectionOpen(true)} + readOnly + value={fromDate && toDate ? `${fromDate} - ${toDate}` : 'All time'} + /> + {isDateSelectionOpen && ( + setIsDateSelectionOpen(false)} + setFromDate={setFromDate} + setToDate={setToDate} + toDate={toDate} + /> + )} +
+ ); + } + + return ( +
+ + +
+ ); +}; + +export default OrdersDateSelection; diff --git a/src/pages/orders/components/OrdersDateSelection/index.ts b/src/pages/orders/components/OrdersDateSelection/index.ts new file mode 100644 index 00000000..b9d2198a --- /dev/null +++ b/src/pages/orders/components/OrdersDateSelection/index.ts @@ -0,0 +1 @@ +export { default as OrdersDateSelection } from './OrdersDateSelection'; diff --git a/src/pages/orders/components/OrdersDateSelectionFullPage/OrdersDateSelectionFullPage.scss b/src/pages/orders/components/OrdersDateSelectionFullPage/OrdersDateSelectionFullPage.scss new file mode 100644 index 00000000..4c48d8a9 --- /dev/null +++ b/src/pages/orders/components/OrdersDateSelectionFullPage/OrdersDateSelectionFullPage.scss @@ -0,0 +1,21 @@ +.orders-date-selection-full-page { + position: absolute; + z-index: 1; + inset: 0; + height: 100vh; + + & .mobile-wrapper { + &__header { + span { + margin: 0 auto; + } + } + + &__body { + padding: 2.4rem; + display: flex; + flex-direction: column; + gap: 2.4rem; + } + } +} diff --git a/src/pages/orders/components/OrdersDateSelectionFullPage/OrdersDateSelectionFullPage.tsx b/src/pages/orders/components/OrdersDateSelectionFullPage/OrdersDateSelectionFullPage.tsx new file mode 100644 index 00000000..d309528b --- /dev/null +++ b/src/pages/orders/components/OrdersDateSelectionFullPage/OrdersDateSelectionFullPage.tsx @@ -0,0 +1,88 @@ +import { Dispatch, SetStateAction, useState } from 'react'; +import { DatePicker, FullPageMobileWrapper } from '@/components'; +import { Localize, useTranslations } from '@deriv-com/translations'; +import { Button, Text } from '@deriv-com/ui'; +import './OrdersDateSelectionFullPage.scss'; + +type TOrdersDateSelectionFullPageProps = { + fromDate: string | null; + onClickCancel: () => void; + setFromDate: Dispatch>; + setToDate: Dispatch>; + toDate: string | null; +}; + +const OrdersDateSelectionFullPage = ({ + fromDate, + onClickCancel, + setFromDate, + setToDate, + toDate, +}: TOrdersDateSelectionFullPageProps) => { + const { localize } = useTranslations(); + const [startDate, setStartDate] = useState(fromDate); + const [endDate, setEndDate] = useState(toDate); + + return ( + ( +
+ + +
+ )} + renderHeader={() => ( + + + + )} + shouldShowBackIcon={false} + shouldShowCloseIcon + > + + +
+ ); +}; + +export default OrdersDateSelectionFullPage; diff --git a/src/pages/orders/components/OrdersDateSelectionFullPage/index.ts b/src/pages/orders/components/OrdersDateSelectionFullPage/index.ts new file mode 100644 index 00000000..e35e1cad --- /dev/null +++ b/src/pages/orders/components/OrdersDateSelectionFullPage/index.ts @@ -0,0 +1 @@ +export { default as OrdersDateSelectionFullPage } from './OrdersDateSelectionFullPage'; diff --git a/src/pages/orders/components/index.ts b/src/pages/orders/components/index.ts index c7a664bc..a5c6437c 100644 --- a/src/pages/orders/components/index.ts +++ b/src/pages/orders/components/index.ts @@ -3,6 +3,7 @@ export * from './ChatFooter'; export * from './ChatHeader'; export * from './ChatMessages'; export * from './OrderRatingButton'; +export * from './OrdersDateSelection'; export * from './OrderStatusTag'; export * from './OrderTimer'; export * from './TextAreaWithIcon'; diff --git a/src/pages/orders/screens/Orders/Orders.tsx b/src/pages/orders/screens/Orders/Orders.tsx index c8bb6458..cd7fa5ff 100644 --- a/src/pages/orders/screens/Orders/Orders.tsx +++ b/src/pages/orders/screens/Orders/Orders.tsx @@ -1,3 +1,5 @@ +import { useEffect, useState } from 'react'; +import moment from 'moment'; import { ORDERS_STATUS } from '@/constants'; import { api } from '@/hooks'; import { useQueryString } from '@/hooks/custom-hooks'; @@ -9,23 +11,38 @@ const Orders = () => { const { queryString } = useQueryString(); const { isMobile } = useDevice(); const currentTab = queryString.tab ?? ORDERS_STATUS.ACTIVE_ORDERS; + const [fromDate, setFromDate] = useState(null); + const [toDate, setToDate] = useState(null); + const isActive = currentTab === ORDERS_STATUS.ACTIVE_ORDERS; const { data = [], isLoading, loadMoreOrders, - } = api.order.useGetList({ active: currentTab === ORDERS_STATUS.ACTIVE_ORDERS ? 1 : 0 }); + } = api.order.useGetList({ + active: isActive ? 1 : 0, + date_from: !isActive && fromDate ? `${moment(fromDate).startOf('day').unix()}` : undefined, + date_to: !isActive && toDate ? `${moment(toDate).endOf('day').unix()}` : undefined, + }); + + useEffect(() => { + return () => { + setFromDate(null); + setToDate(null); + }; + }, []); return ( <> - - {isMobile && } - + {isMobile && } + ); }; diff --git a/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.scss b/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.scss index 6bfb4043..788206b4 100644 --- a/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.scss +++ b/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.scss @@ -7,6 +7,7 @@ @include mobile { margin: 1.6rem; justify-content: center; + flex-direction: column; } &__tabs { @@ -22,4 +23,12 @@ } } } + + &__filters { + display: flex; + flex-direction: row; + gap: 0.8rem; + padding: 0.4rem 0; + align-items: center; + } } diff --git a/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.tsx b/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.tsx index 12481213..37558bc5 100644 --- a/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.tsx +++ b/src/pages/orders/screens/Orders/OrdersTableHeader/OrdersTableHeader.tsx @@ -1,6 +1,7 @@ -import { DatePicker } from '@/components'; +import { Dispatch, SetStateAction } from 'react'; import { ORDERS_STATUS } from '@/constants/orders'; import { useQueryString } from '@/hooks/custom-hooks'; +import { OrdersDateSelection } from '@/pages/orders/components/OrdersDateSelection'; import { getLocalizedTabs } from '@/utils/tabs'; import { useTranslations } from '@deriv-com/translations'; import { Tab, Tabs, useDevice } from '@deriv-com/ui'; @@ -8,9 +9,13 @@ import './OrdersTableHeader.scss'; type TOrdersTableHeaderProps = { activeTab: string; + fromDate: string | null; + setFromDate: Dispatch>; + setToDate: Dispatch>; + toDate: string | null; }; -const OrdersTableHeader = ({ activeTab }: TOrdersTableHeaderProps) => { +const OrdersTableHeader = ({ activeTab, fromDate, setFromDate, setToDate, toDate }: TOrdersTableHeaderProps) => { const { isMobile } = useDevice(); const { setQueryString } = useQueryString(); const { localize } = useTranslations(); @@ -31,7 +36,14 @@ const OrdersTableHeader = ({ activeTab }: TOrdersTableHeaderProps) => { - console.log(value)} /> + {activeTab === ORDERS_STATUS.PAST_ORDERS && ( + + )}
); }; diff --git a/src/pages/orders/screens/Orders/OrdersTableHeader/__tests__/OrdersTableHeader.spec.tsx b/src/pages/orders/screens/Orders/OrdersTableHeader/__tests__/OrdersTableHeader.spec.tsx index a1b007b5..b1a7eeb0 100644 --- a/src/pages/orders/screens/Orders/OrdersTableHeader/__tests__/OrdersTableHeader.spec.tsx +++ b/src/pages/orders/screens/Orders/OrdersTableHeader/__tests__/OrdersTableHeader.spec.tsx @@ -13,18 +13,38 @@ jest.mock('@/hooks/custom-hooks', () => ({ useQueryString: () => ({ setQueryString: mockFn }), })); +const mockProps = { + activeTab: 'Active orders', + fromDate: '2024-05-12', + setFromDate: jest.fn(), + setToDate: jest.fn(), + toDate: '2024-06-01', +}; + +jest.mock('../../../../components/OrdersDateSelection', () => ({ + OrdersDateSelection: () =>
OrdersDateSelection
, +})); + describe('OrdersTableHeader', () => { it('should render OrdersTableHeader', () => { - render(); + render(); expect(screen.getByTestId('dt_orders_table_header')).toBeInTheDocument(); expect(screen.getByText('Active orders')).toBeInTheDocument(); expect(screen.getByText('Past orders')).toBeInTheDocument(); }); it('should handle clicking on tabs', async () => { - render(); + render(); const pastOrdersTab = screen.getByText('Past orders'); expect(pastOrdersTab).toBeInTheDocument(); await userEvent.click(pastOrdersTab); expect(mockFn).toHaveBeenCalledWith({ tab: 'Past orders' }); }); + it('should render OrdersDateSelection when user is on Past orders tab', () => { + render(); + expect(screen.getByText('OrdersDateSelection')).toBeInTheDocument(); + }); + it('should not render OrdersDateSelection when user is on Active orders tab', () => { + render(); + expect(screen.queryByText('OrdersDateSelection')).not.toBeInTheDocument(); + }); }); From 779da8094d76672beb7152d42f523051e8ff9d18 Mon Sep 17 00:00:00 2001 From: Nada Date: Tue, 11 Jun 2024 15:46:51 +0400 Subject: [PATCH 03/15] chore: add unit tests for date text field, order date selection, order date selection full page --- .../DateTextField/DateTextField.tsx | 8 ++- .../__tests__/DateTextField.spec.tsx | 30 +++++++++++ .../OrdersDateSelection.tsx | 4 +- .../__tests__/OrdersDateSelection.spec.tsx | 54 +++++++++++++++++++ .../OrdersDateSelectionFullPage.spec.tsx | 31 +++++++++++ 5 files changed, 123 insertions(+), 4 deletions(-) create mode 100644 src/components/DateTextField/__tests__/DateTextField.spec.tsx create mode 100644 src/pages/orders/components/OrdersDateSelection/__tests__/OrdersDateSelection.spec.tsx create mode 100644 src/pages/orders/components/OrdersDateSelectionFullPage/__tests__/OrdersDateSelectionFullPage.spec.tsx diff --git a/src/components/DateTextField/DateTextField.tsx b/src/components/DateTextField/DateTextField.tsx index a66d8ba1..d4d6d0ec 100644 --- a/src/components/DateTextField/DateTextField.tsx +++ b/src/components/DateTextField/DateTextField.tsx @@ -18,9 +18,13 @@ const DateTextField = ({ alignedRight = false, label, value, ...rest }: TFlowFie })} islabelAnimationDisabled label={value ? '' : label} - leftPlaceholder={!alignedRight && } + leftPlaceholder={ + !alignedRight && + } readOnly - rightPlaceholder={alignedRight && } + rightPlaceholder={ + alignedRight && + } value={value} wrapperClassName='w-full' /> diff --git a/src/components/DateTextField/__tests__/DateTextField.spec.tsx b/src/components/DateTextField/__tests__/DateTextField.spec.tsx new file mode 100644 index 00000000..9f2f0cfa --- /dev/null +++ b/src/components/DateTextField/__tests__/DateTextField.spec.tsx @@ -0,0 +1,30 @@ +import { render, screen } from '@testing-library/react'; +import DateTextField from '../DateTextField'; + +const mockProps = { + label: 'Date from', + value: '', +}; + +describe('DateTextField', () => { + it('should render DateTextField', () => { + render(); + expect(screen.getByText('Date from')).toBeInTheDocument(); + }); + it('should render DateTextField with value', () => { + render(); + expect(screen.getByDisplayValue('2024-06-01')).toBeInTheDocument(); + }); + it('should render DateTextField with leftPlaceholder', () => { + render(); + expect(screen.getByTestId('dt_calendar_icon_left')).toBeInTheDocument(); + }); + it('should render DateTextField with rightplaceholder when alignedRight is true', () => { + render(); + expect(screen.getByTestId('dt_calendar_icon_right')).toBeInTheDocument(); + }); + it('should render DateTextField without label when value is present', () => { + render(); + expect(screen.queryByText('Date from')).not.toBeInTheDocument(); + }); +}); diff --git a/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx index 70758be8..1d525c2e 100644 --- a/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx +++ b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx @@ -31,11 +31,11 @@ const OrdersDateSelection = ({ fromDate, setFromDate, setToDate, toDate }: TOrde } onClick={() => setIsDateSelectionOpen(true)} readOnly - value={fromDate && toDate ? `${fromDate} - ${toDate}` : 'All time'} + value={fromDate && toDate ? `${fromDate} - ${toDate}` : localize('All time')} /> {isDateSelectionOpen && ( ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: jest.fn(() => ({ isMobile: false })), +})); + +const mockProps = { + fromDate: '', + setFromDate: jest.fn(), + setToDate: jest.fn(), + toDate: '', +}; + +describe('OrdersDateSelection', () => { + it('should render OrdersDateSelection', () => { + render(); + expect(screen.getByText('Date from')).toBeInTheDocument(); + expect(screen.getByText('Today')).toBeInTheDocument(); + }); + it('should render the date input section component on mobile', () => { + (useDevice as jest.Mock).mockReturnValue({ isMobile: true }); + render(); + expect(screen.getByText('All time')).toBeInTheDocument(); + }); + it('should open the full page date selection when the input is clicked on mobile', async () => { + render(); + const input = screen.getByPlaceholderText('All time'); + await userEvent.click(input); + expect(screen.getByText('Please select duration')).toBeInTheDocument(); + }); + it('should close the full page date selection when the cancel button is clicked', async () => { + render(); + const input = screen.getByPlaceholderText('All time'); + await userEvent.click(input); + const cancelButton = screen.getByRole('button', { name: 'Cancel' }); + await userEvent.click(cancelButton); + expect(screen.queryByText('Please select duration')).not.toBeInTheDocument(); + }); + it('should show the selected dates when from Date and to Date are provided', async () => { + render(); + const input = screen.getByPlaceholderText('All time'); + expect(input).toHaveValue('2024-06-01 - 2024-06-04'); + }); + it('should show the selected dates when from Date and to Date are provided for desktop', async () => { + (useDevice as jest.Mock).mockReturnValue({ isMobile: false }); + render(); + expect(screen.getByDisplayValue('Jun 01, 2024')).toBeInTheDocument(); + expect(screen.getByDisplayValue('Jun 04, 2024')).toBeInTheDocument(); + }); +}); diff --git a/src/pages/orders/components/OrdersDateSelectionFullPage/__tests__/OrdersDateSelectionFullPage.spec.tsx b/src/pages/orders/components/OrdersDateSelectionFullPage/__tests__/OrdersDateSelectionFullPage.spec.tsx new file mode 100644 index 00000000..a6a2e486 --- /dev/null +++ b/src/pages/orders/components/OrdersDateSelectionFullPage/__tests__/OrdersDateSelectionFullPage.spec.tsx @@ -0,0 +1,31 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import OrdersDateSelectionFullPage from '../OrdersDateSelectionFullPage'; + +const mockProps = { + fromDate: '', + onClickCancel: jest.fn(), + setFromDate: jest.fn(), + setToDate: jest.fn(), + toDate: '', +}; + +describe('OrdersDateSelectionFullPage', () => { + it('should render OrdersDateSelectionFullPage', () => { + render(); + expect(screen.getByText('Please select duration')).toBeInTheDocument(); + }); + it('should call onClickCancel when the cancel button is clicked', async () => { + render(); + const cancelButton = screen.getByRole('button', { name: 'Cancel' }); + await userEvent.click(cancelButton); + expect(mockProps.onClickCancel).toHaveBeenCalledTimes(1); + }); + it('should call setFromDate and setToDate when the OK button is clicked', async () => { + render(); + const okButton = screen.getByRole('button', { name: 'OK' }); + await userEvent.click(okButton); + expect(mockProps.setFromDate).toHaveBeenCalledTimes(1); + expect(mockProps.setToDate).toHaveBeenCalledTimes(1); + }); +}); From aebf140cc5ec53b6df0a835a54c6397737f0c921 Mon Sep 17 00:00:00 2001 From: Nada Date: Tue, 11 Jun 2024 16:03:21 +0400 Subject: [PATCH 04/15] chore: add unit test for date picker --- src/components/DatePicker/DatePicker.tsx | 2 +- .../DatePicker/__tests__/DatePicker.spec.tsx | 39 +++++++++++++++++++ src/components/DatePicker/utils.ts | 13 ------- .../DateTextField/DateTextField.tsx | 6 +-- src/utils/date.ts | 24 ++++++++++++ src/utils/index.ts | 1 + 6 files changed, 68 insertions(+), 17 deletions(-) create mode 100644 src/components/DatePicker/__tests__/DatePicker.spec.tsx delete mode 100644 src/components/DatePicker/utils.ts create mode 100644 src/utils/date.ts diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx index d20eb861..580a2547 100644 --- a/src/components/DatePicker/DatePicker.tsx +++ b/src/components/DatePicker/DatePicker.tsx @@ -2,8 +2,8 @@ import { ComponentProps, useEffect, useRef, useState } from 'react'; import clsx from 'clsx'; import Calendar, { CalendarProps } from 'react-calendar'; import { useOnClickOutside } from 'usehooks-ts'; +import { customFormatShortWeekday, unixToDateString } from '@/utils'; import DateTextField from '../DateTextField/DateTextField'; -import { customFormatShortWeekday, unixToDateString } from './utils'; import 'react-calendar/dist/Calendar.css'; import './DatePicker.scss'; diff --git a/src/components/DatePicker/__tests__/DatePicker.spec.tsx b/src/components/DatePicker/__tests__/DatePicker.spec.tsx new file mode 100644 index 00000000..f1b127ee --- /dev/null +++ b/src/components/DatePicker/__tests__/DatePicker.spec.tsx @@ -0,0 +1,39 @@ +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import DatePicker from '../DatePicker'; + +const mockProps = { + label: 'Date from', + onDateChange: jest.fn(), + value: '', +}; + +describe('DatePicker', () => { + it('should render DatePicker', () => { + render(); + expect(screen.getByText('Date from')).toBeInTheDocument(); + }); + it('should render DatePicker with value', () => { + render(); + expect(screen.getByDisplayValue('Jun 01, 2024')).toBeInTheDocument(); + }); + it('should open the calendar on clicking the input field', async () => { + render(); + const input = screen.getByPlaceholderText('Date from'); + await userEvent.click(input); + expect(screen.getByTestId('dt_datepicker_container')).toBeInTheDocument(); + }); + it('should close the calendar on clicking outside the calendar', async () => { + render(); + const input = screen.getByPlaceholderText('Date from'); + await userEvent.click(input); + await userEvent.click(document.body); + expect(screen.queryByTestId('dt_datepicker_container')).not.toBeInTheDocument(); + }); + it('should handle date change', async () => { + render(); + const input = screen.getByPlaceholderText('Date from'); + await userEvent.type(input, '2024-06-01'); + expect(mockProps.onDateChange).toHaveBeenCalledWith('Jun 01, 2024'); + }); +}); diff --git a/src/components/DatePicker/utils.ts b/src/components/DatePicker/utils.ts deleted file mode 100644 index 363ded47..00000000 --- a/src/components/DatePicker/utils.ts +++ /dev/null @@ -1,13 +0,0 @@ -import moment from 'moment'; - -export function customFormatShortWeekday(_locale: string | undefined, date: Date) { - const weekdays = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; - - return weekdays[date.getDay()]; -} - -export function unixToDateString(date: Date, format = 'YYYY-MM-DD') { - const formattedDate = moment(date).format(format); - - return formattedDate; -} diff --git a/src/components/DateTextField/DateTextField.tsx b/src/components/DateTextField/DateTextField.tsx index d4d6d0ec..f4a35141 100644 --- a/src/components/DateTextField/DateTextField.tsx +++ b/src/components/DateTextField/DateTextField.tsx @@ -4,11 +4,11 @@ import { LabelPairedCalendarRangeMdRegularIcon, LegacyCalendarDateFrom1pxIcon } import { Input } from '@deriv-com/ui'; import './DateTextField.scss'; -export interface TFlowFieldProps extends ComponentProps { +type TDateTextFieldProps = ComponentProps & { alignedRight?: boolean; -} +}; -const DateTextField = ({ alignedRight = false, label, value, ...rest }: TFlowFieldProps) => { +const DateTextField = ({ alignedRight = false, label, value, ...rest }: TDateTextFieldProps) => { return (
{ + const weekdays = ['S', 'M', 'T', 'W', 'T', 'F', 'S']; + + return weekdays[date.getDay()]; +}; + +/** + * The below function converts the unix date to a string in the given format. + * @param date + * @param format + * @returns + */ +export const unixToDateString = (date: Date, format = 'YYYY-MM-DD') => { + const formattedDate = moment(date).format(format); + + return formattedDate; +}; diff --git a/src/utils/index.ts b/src/utils/index.ts index f97ef030..0b573136 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -1,6 +1,7 @@ export * from './ad-utils'; export * from './adverts'; export * from './currency'; +export * from './date'; export * from './file-dropzone'; export * from './file-uploader'; export * from './format-value'; From 5631d257d36f9c7b425022941eee94c387dbc63f Mon Sep 17 00:00:00 2001 From: Nada Date: Tue, 11 Jun 2024 16:10:31 +0400 Subject: [PATCH 05/15] fix: removed active start date --- src/components/DatePicker/DatePicker.tsx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx index 580a2547..6e19771b 100644 --- a/src/components/DatePicker/DatePicker.tsx +++ b/src/components/DatePicker/DatePicker.tsx @@ -86,7 +86,6 @@ const DatePicker = ({ data-testid='dt_datepicker_container' > Date: Tue, 11 Jun 2024 16:33:03 +0400 Subject: [PATCH 06/15] fix: style issues --- package-lock.json | 24 ++----------------- package.json | 1 - .../PaymentMethodForm/PaymentMethodForm.scss | 13 ++++++++++ 3 files changed, 15 insertions(+), 23 deletions(-) diff --git a/package-lock.json b/package-lock.json index 4d4c49e6..500064e7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,7 +23,6 @@ "@vitejs/plugin-react": "^4.2.1", "babel-jest": "^29.7.0", "clsx": "^2.1.0", - "downshift": "^9.0.0", "history": "^4.10.1", "html2canvas": "^1.4.1", "lodash": "^4.17.21", @@ -7360,11 +7359,6 @@ "dot-prop": "^5.1.0" } }, - "node_modules/compute-scroll-into-view": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz", - "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg==" - }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -8425,21 +8419,6 @@ "node": ">=8" } }, - "node_modules/downshift": { - "version": "9.0.6", - "resolved": "https://registry.npmjs.org/downshift/-/downshift-9.0.6.tgz", - "integrity": "sha512-lkqWh0eb34XuH+3z3/BH/LGVRV7ur0rielSlxtlQKsjAFF/wc/c0wsM9phUGXyzK2g1QWHoNHQyc+vVAheI17Q==", - "dependencies": { - "@babel/runtime": "^7.24.5", - "compute-scroll-into-view": "^3.1.0", - "prop-types": "^15.8.1", - "react-is": "18.2.0", - "tslib": "^2.6.2" - }, - "peerDependencies": { - "react": ">=16.12.0" - } - }, "node_modules/duplexer2": { "version": "0.0.2", "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.0.2.tgz", @@ -16646,7 +16625,8 @@ "node_modules/react-is": { "version": "18.2.0", "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.2.0.tgz", - "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==" + "integrity": "sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w==", + "dev": true }, "node_modules/react-lifecycles-compat": { "version": "3.0.4", diff --git a/package.json b/package.json index 5d8d0988..0682fa92 100644 --- a/package.json +++ b/package.json @@ -29,7 +29,6 @@ "@vitejs/plugin-react": "^4.2.1", "babel-jest": "^29.7.0", "clsx": "^2.1.0", - "downshift": "^9.0.0", "history": "^4.10.1", "html2canvas": "^1.4.1", "lodash": "^4.17.21", diff --git a/src/components/PaymentMethodForm/PaymentMethodForm.scss b/src/components/PaymentMethodForm/PaymentMethodForm.scss index 305e2adf..c27f1f47 100644 --- a/src/components/PaymentMethodForm/PaymentMethodForm.scss +++ b/src/components/PaymentMethodForm/PaymentMethodForm.scss @@ -69,6 +69,16 @@ width: 100%; font-size: 1.4rem; } + .deriv-input__right-content { + display: flex; + align-items: center; + + & .deriv-dropdown__button { + &--active { + transform: none; + } + } + } &__form { display: flex; @@ -99,6 +109,9 @@ cursor: pointer; color: #ffffff; font-size: large; + rect { + fill: #999; + } } &__field { From 7ffe8b13ccf7a7a42314ab1c76021e12a0229822 Mon Sep 17 00:00:00 2001 From: Nada Date: Wed, 12 Jun 2024 09:03:08 +0400 Subject: [PATCH 07/15] fix: pending style fixes --- src/components/FormProgress/FormProgress.scss | 2 +- .../PopoverDropdown/PopoverDropdown.scss | 16 +++++++++++----- .../PopoverDropdown/PopoverDropdown.tsx | 10 +++++----- src/pages/my-ads/components/AdType/AdType.tsx | 7 ++++--- .../components/AdType/__tests__/AdType.spec.tsx | 5 +++++ .../components/AdTypeSection/AdTypeSection.scss | 5 +++++ .../my-ads/components/AdWizard/AdWizard.scss | 1 - .../AlertComponent/AlertComponent.scss | 2 +- src/pages/my-ads/screens/MyAds/MyAds.tsx | 2 +- .../MyAds/MyAdsTableRow/MyAdsTableRow.scss | 8 ++++++-- .../MyAds/MyAdsTableRow/MyAdsTableRow.tsx | 7 +------ 11 files changed, 40 insertions(+), 25 deletions(-) diff --git a/src/components/FormProgress/FormProgress.scss b/src/components/FormProgress/FormProgress.scss index 9377e460..d9770328 100644 --- a/src/components/FormProgress/FormProgress.scss +++ b/src/components/FormProgress/FormProgress.scss @@ -7,7 +7,7 @@ display: flex; flex-direction: column; justify-content: center; - margin-bottom: 3.2rem; + margin-bottom: 2rem; } &__step { align-items: center; diff --git a/src/components/PopoverDropdown/PopoverDropdown.scss b/src/components/PopoverDropdown/PopoverDropdown.scss index a731aff9..049f7bc5 100644 --- a/src/components/PopoverDropdown/PopoverDropdown.scss +++ b/src/components/PopoverDropdown/PopoverDropdown.scss @@ -3,15 +3,21 @@ flex-direction: column; position: relative; - &__icon { - margin-left: 1rem; - } + & .tooltip-menu-icon { + width: 3.2rem; + display: flex; + justify-content: center; + border-radius: 4px; - & .deriv-tooltip { @include mobile { - display: none; + margin-top: -0.5rem; + + &:hover { + background-color: transparent; + } } } + &__list { display: flex; flex-direction: column; diff --git a/src/components/PopoverDropdown/PopoverDropdown.tsx b/src/components/PopoverDropdown/PopoverDropdown.tsx index 0a999020..35243e09 100644 --- a/src/components/PopoverDropdown/PopoverDropdown.tsx +++ b/src/components/PopoverDropdown/PopoverDropdown.tsx @@ -1,8 +1,8 @@ import { useRef, useState } from 'react'; import { useOnClickOutside } from 'usehooks-ts'; import { useIsAdvertiserBarred } from '@/hooks/custom-hooks'; -import { LabelPairedEllipsisVerticalMdRegularIcon } from '@deriv/quill-icons'; -import { Button, Text, Tooltip, useDevice } from '@deriv-com/ui'; +import { LabelPairedEllipsisVerticalLgBoldIcon } from '@deriv/quill-icons'; +import { Button, Text, TooltipMenuIcon, useDevice } from '@deriv-com/ui'; import './PopoverDropdown.scss'; type TItem = { @@ -25,13 +25,13 @@ const PopoverDropdown = ({ dropdownList, onClick, tooltipMessage }: TPopoverDrop return (
- - + setVisible(prevState => !prevState)} /> - + {visible && (
{dropdownList.map(item => ( diff --git a/src/pages/my-ads/components/AdType/AdType.tsx b/src/pages/my-ads/components/AdType/AdType.tsx index b685344a..78bc10e4 100644 --- a/src/pages/my-ads/components/AdType/AdType.tsx +++ b/src/pages/my-ads/components/AdType/AdType.tsx @@ -1,6 +1,6 @@ import { TTextColors } from 'types'; import { Localize } from '@deriv-com/translations'; -import { Text } from '@deriv-com/ui'; +import { Text, useDevice } from '@deriv-com/ui'; import './AdType.scss'; type TAdTypeProps = { @@ -8,12 +8,13 @@ type TAdTypeProps = { floatRate: string; }; const AdType = ({ adPauseColor, floatRate }: TAdTypeProps) => { + const { isDesktop } = useDevice(); return (
- + - + {floatRate}%
diff --git a/src/pages/my-ads/components/AdType/__tests__/AdType.spec.tsx b/src/pages/my-ads/components/AdType/__tests__/AdType.spec.tsx index e28ac71a..82420cfe 100644 --- a/src/pages/my-ads/components/AdType/__tests__/AdType.spec.tsx +++ b/src/pages/my-ads/components/AdType/__tests__/AdType.spec.tsx @@ -7,6 +7,11 @@ const mockProps = { floatRate: '1.23', }; +jest.mock('@deriv-com/ui', () => ({ + ...jest.requireActual('@deriv-com/ui'), + useDevice: () => ({ isDesktop: true }), +})); + describe('AdType', () => { it('should render the component as expected', () => { render(); diff --git a/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss b/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss index 941374df..fda46986 100644 --- a/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss +++ b/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss @@ -1,4 +1,9 @@ .ad-type-section { + @include desktop { + & .radio-group { + margin-top: 0; + } + } @include mobile { padding: 0 1.6rem; overflow: auto; diff --git a/src/pages/my-ads/components/AdWizard/AdWizard.scss b/src/pages/my-ads/components/AdWizard/AdWizard.scss index a28a7530..a1333643 100644 --- a/src/pages/my-ads/components/AdWizard/AdWizard.scss +++ b/src/pages/my-ads/components/AdWizard/AdWizard.scss @@ -24,7 +24,6 @@ } .wizard__main-step { - padding-top: 1rem; @include desktop { max-height: calc(100vh - 35rem); overflow-y: auto; diff --git a/src/pages/my-ads/components/AlertComponent/AlertComponent.scss b/src/pages/my-ads/components/AlertComponent/AlertComponent.scss index 16a2c882..9f3980b8 100644 --- a/src/pages/my-ads/components/AlertComponent/AlertComponent.scss +++ b/src/pages/my-ads/components/AlertComponent/AlertComponent.scss @@ -3,7 +3,7 @@ justify-content: center; position: absolute; align-items: center; - right: 4.7rem; + right: 4.2rem; height: 100%; span { diff --git a/src/pages/my-ads/screens/MyAds/MyAds.tsx b/src/pages/my-ads/screens/MyAds/MyAds.tsx index bbba4c90..98a26151 100644 --- a/src/pages/my-ads/screens/MyAds/MyAds.tsx +++ b/src/pages/my-ads/screens/MyAds/MyAds.tsx @@ -13,7 +13,7 @@ const MyAds = () => { if (!isPoaVerified || !isPoiVerified) return ; return ( -
+
{isAdvertiserBarred && }
diff --git a/src/pages/my-ads/screens/MyAds/MyAdsTableRow/MyAdsTableRow.scss b/src/pages/my-ads/screens/MyAds/MyAdsTableRow/MyAdsTableRow.scss index 98b0f35f..648951e6 100644 --- a/src/pages/my-ads/screens/MyAds/MyAdsTableRow/MyAdsTableRow.scss +++ b/src/pages/my-ads/screens/MyAds/MyAdsTableRow/MyAdsTableRow.scss @@ -27,11 +27,16 @@ display: grid; align-items: center; grid-template-columns: repeat(3, 1.6fr) 1.9fr 3fr 1.9fr; + @include desktop { + padding-right: 0; + } &-disabled { span:not(.my-ads-table-row__actions span) { &:not(.popover-dropdown__list-item span) { - color: #999; + &:not(.my-ads-table-row__line__type-and-status__wrapper span) { + color: #999; + } } } .progress-indicator { @@ -95,7 +100,6 @@ display: flex; align-items: center; justify-content: space-between; - margin-right: 1rem; &-popovers { background-color: #fff; display: flex; diff --git a/src/pages/my-ads/screens/MyAds/MyAdsTableRow/MyAdsTableRow.tsx b/src/pages/my-ads/screens/MyAds/MyAdsTableRow/MyAdsTableRow.tsx index 5317b433..51c6fa71 100644 --- a/src/pages/my-ads/screens/MyAds/MyAdsTableRow/MyAdsTableRow.tsx +++ b/src/pages/my-ads/screens/MyAds/MyAdsTableRow/MyAdsTableRow.tsx @@ -224,12 +224,7 @@ const MyAdsTableRow = ({ currentRateType, showModal, ...rest }: TMyAdsTableProps
{paymentMethodNames?.map(paymentMethod => ( - + ))}
From a0e54790348b5343183bd6567f7317fa069ecbd9 Mon Sep 17 00:00:00 2001 From: Nada Date: Wed, 12 Jun 2024 09:56:45 +0400 Subject: [PATCH 08/15] fix: align center for search icon --- .../PaymentMethodForm/PaymentMethodForm.scss | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/components/PaymentMethodForm/PaymentMethodForm.scss b/src/components/PaymentMethodForm/PaymentMethodForm.scss index c27f1f47..ceae3aab 100644 --- a/src/components/PaymentMethodForm/PaymentMethodForm.scss +++ b/src/components/PaymentMethodForm/PaymentMethodForm.scss @@ -23,6 +23,17 @@ & .deriv-input__container { width: 100%; } + + & .payment-method-form__fields { + & .payment-method-form__field-wrapper { + & .deriv-input__container { + & .deriv-input__right-content { + display: flex; + align-items: center; + } + } + } + } } @include mobile { From 7d72e981ce93362b820d29fced4f3c9631d528c7 Mon Sep 17 00:00:00 2001 From: Nada Date: Wed, 12 Jun 2024 10:15:02 +0400 Subject: [PATCH 09/15] fix: pr review comments --- src/components/DatePicker/DatePicker.tsx | 4 ++-- .../OrdersDateSelection/OrdersDateSelection.scss | 1 - .../OrdersDateSelection/OrdersDateSelection.tsx | 9 +-------- .../Orders/OrdersTableHeader/OrdersTableHeader.scss | 1 - 4 files changed, 3 insertions(+), 12 deletions(-) diff --git a/src/components/DatePicker/DatePicker.tsx b/src/components/DatePicker/DatePicker.tsx index 6e19771b..a6ab8a67 100644 --- a/src/components/DatePicker/DatePicker.tsx +++ b/src/components/DatePicker/DatePicker.tsx @@ -57,9 +57,9 @@ const DatePicker = ({ // eslint-disable-next-line react-hooks/exhaustive-deps }, [selectedDate]); + // To not display the date value when today's date is selected. const getValue = () => { - const isToday = selectedDate !== null && selectedDate.getDate() === new Date().getDate(); - if (selectedDate !== null && selectedDate !== new Date() && (!isToday || showLabel)) { + if (selectedDate && (showLabel || selectedDate.getDate() !== new Date().getDate())) { return unixToDateString(selectedDate, displayFormat); } return ''; diff --git a/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.scss b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.scss index 0ce8ceee..d4923942 100644 --- a/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.scss +++ b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.scss @@ -1,7 +1,6 @@ .orders-date-selection { @include desktop { display: flex; - flex-direction: row; gap: 0.8rem; padding: 0.4rem 0; align-items: center; diff --git a/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx index 1d525c2e..c2dcad98 100644 --- a/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx +++ b/src/pages/orders/components/OrdersDateSelection/OrdersDateSelection.tsx @@ -18,13 +18,6 @@ const OrdersDateSelection = ({ fromDate, setFromDate, setToDate, toDate }: TOrde const { localize } = useTranslations(); const [isDateSelectionOpen, setIsDateSelectionOpen] = useState(false); - const getMaxDate = () => { - if (toDate) { - return new Date(toDate); - } - return new Date(); - }; - if (isMobile) { return (
@@ -54,7 +47,7 @@ const OrdersDateSelection = ({ fromDate, setFromDate, setToDate, toDate }: TOrde
Date: Wed, 12 Jun 2024 10:34:18 +0400 Subject: [PATCH 10/15] fix: console error maximum depth exceeded fixed --- src/components/PopoverDropdown/PopoverDropdown.tsx | 12 ++++++------ .../my-ads/screens/CreateEditAd/CreateEditAd.tsx | 5 +++-- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/src/components/PopoverDropdown/PopoverDropdown.tsx b/src/components/PopoverDropdown/PopoverDropdown.tsx index 35243e09..9375d181 100644 --- a/src/components/PopoverDropdown/PopoverDropdown.tsx +++ b/src/components/PopoverDropdown/PopoverDropdown.tsx @@ -25,12 +25,12 @@ const PopoverDropdown = ({ dropdownList, onClick, tooltipMessage }: TPopoverDrop return (
- - setVisible(prevState => !prevState)} - /> + setVisible(prevState => !prevState)} + tooltipContent={tooltipMessage} + > + {visible && (
diff --git a/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx b/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx index b4582717..587e316a 100644 --- a/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx +++ b/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx @@ -200,14 +200,15 @@ const CreateEditAd = () => { } }, // eslint-disable-next-line react-hooks/exhaustive-deps - [setValue, paymentMethodList, countryList] + [paymentMethodList, countryList] ); useEffect(() => { if (advertInfo && isEdit) { setFormValues(advertInfo as NonUndefinedValues); } - }, [advertInfo, isEdit, setFormValues]); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [advertInfo, isEdit]); if ((isLoading && isEdit) || (isEdit && !advertInfo)) { return ; From 53bcc3aa04de5322492146feda6d135213f8623c Mon Sep 17 00:00:00 2001 From: Nada Date: Wed, 12 Jun 2024 11:44:19 +0400 Subject: [PATCH 11/15] fix: style issues in ad type section --- .../my-ads/components/AdTypeSection/AdTypeSection.scss | 7 +++++++ .../my-ads/components/AdTypeSection/AdTypeSection.tsx | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss b/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss index fda46986..29d10060 100644 --- a/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss +++ b/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss @@ -1,4 +1,7 @@ .ad-type-section { + &--edit { + padding-top: 2.4rem; + } @include desktop { & .radio-group { margin-top: 0; @@ -8,5 +11,9 @@ padding: 0 1.6rem; overflow: auto; max-height: calc(100vh - 27rem); + + &--edit { + padding-top: 2.4rem; + } } } diff --git a/src/pages/my-ads/components/AdTypeSection/AdTypeSection.tsx b/src/pages/my-ads/components/AdTypeSection/AdTypeSection.tsx index 59b74990..fb343605 100644 --- a/src/pages/my-ads/components/AdTypeSection/AdTypeSection.tsx +++ b/src/pages/my-ads/components/AdTypeSection/AdTypeSection.tsx @@ -1,4 +1,5 @@ import { MouseEventHandler } from 'react'; +import clsx from 'clsx'; import { Controller, useFormContext } from 'react-hook-form'; import { TCurrency } from 'types'; import { FloatingRate, RadioGroup } from '@/components'; @@ -69,7 +70,7 @@ const AdTypeSection = ({ currency, localCurrency, onCancel, rateType, ...props } }; return ( -
+
{!isEdit && ( Date: Wed, 12 Jun 2024 11:54:11 +0400 Subject: [PATCH 12/15] fix: create edit ad breaking when opening buy sell form then, edit ad --- src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx b/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx index 587e316a..ba6e6c26 100644 --- a/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx +++ b/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx @@ -204,7 +204,7 @@ const CreateEditAd = () => { ); useEffect(() => { - if (advertInfo && isEdit) { + if (advertInfo && advertInfo.id === advertId && isEdit) { setFormValues(advertInfo as NonUndefinedValues); } // eslint-disable-next-line react-hooks/exhaustive-deps From 142bac65c99f2a9718549783d9da3f0bc6887ea3 Mon Sep 17 00:00:00 2001 From: Nada Date: Wed, 12 Jun 2024 12:35:25 +0400 Subject: [PATCH 13/15] fix: issue with edit ad rate not updating --- .../screens/CreateEditAd/CreateEditAd.tsx | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx b/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx index ba6e6c26..2dfda674 100644 --- a/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx +++ b/src/pages/my-ads/screens/CreateEditAd/CreateEditAd.tsx @@ -36,6 +36,7 @@ type FormValues = { }; type TMutatePayload = Parameters[0]; +type TFormValuesInfo = NonUndefinedValues; const CreateEditAd = () => { const { queryString } = useQueryString(); @@ -165,33 +166,33 @@ const CreateEditAd = () => { // eslint-disable-next-line react-hooks/exhaustive-deps }, [isSuccess, history, shouldNotShowArchiveMessageAgain, isError, isUpdateSuccess, isUpdateError]); - const setInitialAdRate = () => { - if (rateType !== advertInfo?.rate_type) { + const setInitialAdRate = (formValues: TFormValuesInfo) => { + if (rateType !== formValues?.rate_type) { if (rateType === RATE_TYPE.FLOAT) { - return advertInfo?.is_buy ? '-0.01' : '+0.01'; + return formValues?.is_buy ? '-0.01' : '+0.01'; } return ''; } - return advertInfo?.rate; + return formValues?.rate; }; const setFormValues = useCallback( - (advertInfo: NonUndefinedValues) => { - setValue('ad-type', advertInfo.type); - setValue('amount', advertInfo.amount.toString()); - setValue('instructions', advertInfo.description); - setValue('max-order', advertInfo.max_order_amount.toString()); - setValue('min-completion-rate', advertInfo.min_completion_rate?.toString() ?? ''); - setValue('min-join-days', advertInfo.min_join_days?.toString() ?? ''); - setValue('min-order', advertInfo.min_order_amount.toString()); - setValue('rate-value', setInitialAdRate() as string); - setValue('preferred-countries', advertInfo.eligible_countries ?? Object.keys(countryList as object)); - setValue('order-completion-time', `${advertInfo.order_expiry_period}`); - if (advertInfo.type === 'sell') { - setValue('contact-details', advertInfo.contact_info); - setValue('payment-method', Object.keys(advertInfo.payment_method_details ?? {}).map(Number)); + (formValues: TFormValuesInfo) => { + setValue('ad-type', formValues.type); + setValue('amount', formValues.amount.toString()); + setValue('instructions', formValues.description); + setValue('max-order', formValues.max_order_amount.toString()); + setValue('min-completion-rate', formValues.min_completion_rate?.toString() ?? ''); + setValue('min-join-days', formValues.min_join_days?.toString() ?? ''); + setValue('min-order', formValues.min_order_amount.toString()); + setValue('rate-value', setInitialAdRate(formValues) as string); + setValue('preferred-countries', formValues.eligible_countries ?? Object.keys(countryList as object)); + setValue('order-completion-time', `${formValues.order_expiry_period}`); + if (formValues.type === 'sell') { + setValue('contact-details', formValues.contact_info); + setValue('payment-method', Object.keys(formValues.payment_method_details ?? {}).map(Number)); } else { - const paymentMethodNames = advertInfo?.payment_method_names; + const paymentMethodNames = formValues?.payment_method_names; const paymentMethodKeys = paymentMethodNames?.map( name => paymentMethodList.find(method => method.display_name === name)?.id ?? '' @@ -205,7 +206,7 @@ const CreateEditAd = () => { useEffect(() => { if (advertInfo && advertInfo.id === advertId && isEdit) { - setFormValues(advertInfo as NonUndefinedValues); + setFormValues(advertInfo as TFormValuesInfo); } // eslint-disable-next-line react-hooks/exhaustive-deps }, [advertInfo, isEdit]); From 4a973b53a4fc5ac04b8ed289239ea74096b3e5b3 Mon Sep 17 00:00:00 2001 From: Nada Date: Wed, 12 Jun 2024 12:39:15 +0400 Subject: [PATCH 14/15] fix: review comments --- .../PaymentMethodForm/PaymentMethodForm.scss | 15 ++++----------- src/pages/my-ads/components/AdType/AdType.tsx | 5 +++-- 2 files changed, 7 insertions(+), 13 deletions(-) diff --git a/src/components/PaymentMethodForm/PaymentMethodForm.scss b/src/components/PaymentMethodForm/PaymentMethodForm.scss index ceae3aab..a98fa4f7 100644 --- a/src/components/PaymentMethodForm/PaymentMethodForm.scss +++ b/src/components/PaymentMethodForm/PaymentMethodForm.scss @@ -23,17 +23,6 @@ & .deriv-input__container { width: 100%; } - - & .payment-method-form__fields { - & .payment-method-form__field-wrapper { - & .deriv-input__container { - & .deriv-input__right-content { - display: flex; - align-items: center; - } - } - } - } } @include mobile { @@ -151,6 +140,10 @@ max-height: 20rem; } } + & .deriv-input__right-content { + display: flex; + align-items: center; + } } } &__text { diff --git a/src/pages/my-ads/components/AdType/AdType.tsx b/src/pages/my-ads/components/AdType/AdType.tsx index 78bc10e4..605ab75c 100644 --- a/src/pages/my-ads/components/AdType/AdType.tsx +++ b/src/pages/my-ads/components/AdType/AdType.tsx @@ -9,12 +9,13 @@ type TAdTypeProps = { }; const AdType = ({ adPauseColor, floatRate }: TAdTypeProps) => { const { isDesktop } = useDevice(); + const textSize = isDesktop ? 'xs' : 'sm'; return (
- + - + {floatRate}%
From 6fd3206109650dfc63fd2826f7e1e896b65008a7 Mon Sep 17 00:00:00 2001 From: Nada Date: Wed, 12 Jun 2024 12:42:40 +0400 Subject: [PATCH 15/15] fix: change order of style --- .../my-ads/components/AdTypeSection/AdTypeSection.scss | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss b/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss index 29d10060..732f4a5d 100644 --- a/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss +++ b/src/pages/my-ads/components/AdTypeSection/AdTypeSection.scss @@ -1,7 +1,4 @@ .ad-type-section { - &--edit { - padding-top: 2.4rem; - } @include desktop { & .radio-group { margin-top: 0; @@ -11,9 +8,9 @@ padding: 0 1.6rem; overflow: auto; max-height: calc(100vh - 27rem); + } - &--edit { - padding-top: 2.4rem; - } + &--edit { + padding-top: 2.4rem; } }