-
Notifications
You must be signed in to change notification settings - Fork 319
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[DTRA] Henry/dtra 1443/market closed message v2 #16196
Merged
balakrishna-deriv
merged 11 commits into
deriv-com:master
from
henry-deriv:henry/dtra-1443/market-closed-message-v2
Aug 1, 2024
Merged
Changes from 7 commits
Commits
Show all changes
11 commits
Select commit
Hold shift + click to select a range
e730f32
fix: stop scrolling to center on symbol selection for all category
henry-deriv ad9c78c
fix: flex-start tabs list
henry-deriv bb432fd
fix: market is closed message
henry-deriv 4af353f
fix: type error
henry-deriv ba2c0e4
fix: conflicts
henry-deriv d1bb336
fix: add tests
henry-deriv 8203777
fix: add tests
henry-deriv cee868c
Merge branch 'master' of github.com:binary-com/deriv-app into henry/d…
henry-deriv 39d6b2f
fix: add a mock for closedmarketmessage
henry-deriv 8c4f9ce
fix: remove unused import
henry-deriv 89ff409
fix: comment
henry-deriv File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
26 changes: 26 additions & 0 deletions
26
packages/trader/src/AppV2/Components/ClosedMarketMessage/closed-market-message.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
.closed-market-message { | ||
&--container { | ||
display: flex; | ||
width: 100%; | ||
padding: var(--core-spacing-800); | ||
justify-content: space-between; | ||
align-items: center; | ||
background-color: var(--semantic-color-slate-solid-surface-inverse-highest); | ||
z-index: 3; | ||
bottom: 0; | ||
position: sticky; | ||
} | ||
&--left { | ||
display: flex; | ||
flex-direction: column; | ||
justify-content: center; | ||
gap: var(--core-spacing-200); | ||
|
||
&-message { | ||
color: var(--semantic-color-slate-solid-surface-normal-lowest); | ||
} | ||
} | ||
&--loading { | ||
display: none; | ||
} | ||
} |
127 changes: 127 additions & 0 deletions
127
packages/trader/src/AppV2/Components/ClosedMarketMessage/closed-market-message.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,127 @@ | ||
import React from 'react'; | ||
import { useIsMounted, WS, isMarketClosed, toMoment } from '@deriv/shared'; | ||
import { Localize } from '@deriv/translations'; | ||
import { observer, useStore } from '@deriv/stores'; | ||
import { useTraderStore } from 'Stores/useTraderStores'; | ||
import { TradingTimesRequest } from '@deriv/api-types'; | ||
import useActiveSymbols from 'AppV2/Hooks/useActiveSymbols'; | ||
import MarketOpeningTimeBanner from '../MarketOpeningTimeBanner'; | ||
import MarketCountdownTimer from '../MarketCountdownTimer'; | ||
import { CaptionText } from '@deriv-com/quill-ui'; | ||
import clsx from 'clsx'; | ||
import { calculateTimeLeft, getSymbol } from 'AppV2/Utils/closed-market-message-utils'; | ||
|
||
type TWhenMarketOpens = { | ||
days_offset: number; | ||
opening_time: string; | ||
remaining_time_to_open: number; | ||
}; | ||
|
||
const days_to_check_before_exit = 7; | ||
|
||
const getTradingTimes = async (target_time: TradingTimesRequest['trading_times']) => { | ||
const data = await WS.tradingTimes(target_time); | ||
if (data.error) { | ||
return { api_initial_load_error: data.error.message }; | ||
} | ||
return data; | ||
}; | ||
|
||
const ClosedMarketMessage = observer(() => { | ||
const { common } = useStore(); | ||
const { current_language } = common; | ||
const { symbol, prepareTradeStore } = useTraderStore(); | ||
const { activeSymbols } = useActiveSymbols({}); | ||
|
||
const isMounted = useIsMounted(); | ||
const [when_market_opens, setWhenMarketOpens] = React.useState<TWhenMarketOpens>({} as TWhenMarketOpens); | ||
const [time_left, setTimeLeft] = React.useState(calculateTimeLeft(when_market_opens?.remaining_time_to_open)); | ||
const [is_loading, setLoading] = React.useState(true); | ||
|
||
React.useEffect(() => { | ||
if (isMarketClosed(activeSymbols, symbol)) { | ||
setLoading(true); | ||
const whenMarketOpens = async ( | ||
days_offset: number, | ||
target_symbol: string | ||
): Promise<void | Record<string, unknown>> => { | ||
if (days_offset > days_to_check_before_exit) return {}; | ||
let remaining_time_to_open; | ||
const target_date = toMoment(new Date()).add(days_offset, 'days'); | ||
const api_response = await getTradingTimes(target_date.format('YYYY-MM-DD')); | ||
if (!api_response.api_initial_load_error) { | ||
const returned_symbol = getSymbol(target_symbol, api_response.trading_times); | ||
const open = returned_symbol?.times.open as string[]; | ||
const close = returned_symbol?.times.close as string[]; | ||
const is_closed_all_day = open?.length === 1 && open[0] === '--' && close[0] === '--'; | ||
if (is_closed_all_day) { | ||
return whenMarketOpens(days_offset + 1, target_symbol); | ||
} | ||
const date_str = target_date.toISOString().substring(0, 11); | ||
const getUTCDate = (hour: string) => new Date(`${date_str}${hour}Z`); | ||
for (let i = 0; i < open?.length; i++) { | ||
const diff = +getUTCDate(open[i]) - Date.now(); | ||
if (diff > 0) { | ||
remaining_time_to_open = +getUTCDate(open[i]); | ||
if (isMounted() && target_symbol === symbol) { | ||
return setWhenMarketOpens({ | ||
days_offset, | ||
opening_time: open[i], | ||
remaining_time_to_open, | ||
}); | ||
} | ||
} | ||
} | ||
whenMarketOpens(days_offset + 1, target_symbol); | ||
} | ||
}; | ||
|
||
whenMarketOpens(0, symbol); | ||
} | ||
setTimeLeft({}); | ||
setWhenMarketOpens({} as TWhenMarketOpens); | ||
// eslint-disable-next-line react-hooks/exhaustive-deps | ||
}, [symbol, activeSymbols]); | ||
|
||
React.useEffect(() => { | ||
let timer: ReturnType<typeof setTimeout>; | ||
if (when_market_opens?.remaining_time_to_open) { | ||
timer = setTimeout(() => { | ||
setTimeLeft(calculateTimeLeft(when_market_opens.remaining_time_to_open)); | ||
if (+new Date(when_market_opens.remaining_time_to_open) - +new Date() < 1000) { | ||
setLoading(true); | ||
prepareTradeStore(false); | ||
} | ||
}, 1000); | ||
} | ||
return () => { | ||
if (timer) { | ||
clearTimeout(timer); | ||
} | ||
}; | ||
}, [time_left, when_market_opens, prepareTradeStore]); | ||
|
||
if (!(when_market_opens && Object.keys(time_left).length)) return null; | ||
|
||
const { opening_time, days_offset } = when_market_opens; | ||
|
||
if (is_loading) setLoading(false); | ||
|
||
return ( | ||
<div className={clsx('closed-market-message--container', { 'closed-market-message--loading': is_loading })}> | ||
<div className='closed-market-message--left'> | ||
<CaptionText className='closed-market-message--left-message'> | ||
<Localize i18n_default_text='This market will reopen at' /> | ||
</CaptionText> | ||
<MarketOpeningTimeBanner | ||
opening_time={opening_time} | ||
days_offset={days_offset} | ||
current_language={current_language} | ||
/> | ||
</div> | ||
<MarketCountdownTimer time_left={time_left} /> | ||
</div> | ||
); | ||
}); | ||
|
||
export default ClosedMarketMessage; |
4 changes: 4 additions & 0 deletions
4
packages/trader/src/AppV2/Components/ClosedMarketMessage/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import './closed-market-message.scss'; | ||
import ClosedMarketMessage from './closed-market-message'; | ||
|
||
export default ClosedMarketMessage; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
22 changes: 22 additions & 0 deletions
22
...rader/src/AppV2/Components/MarketCountdownTimer/__tests__/market-countdown-timer.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import React from 'react'; | ||
import { screen, render } from '@testing-library/react'; | ||
import '@testing-library/jest-dom/extend-expect'; // for the `toBeInTheDocument` matcher | ||
import MarketCountdownTimer from '..'; | ||
|
||
describe('MarketCountDownTimer', () => { | ||
it('renders correctly with given time left', () => { | ||
render(<MarketCountdownTimer time_left={{ days: 1, hours: 2, minutes: 3, seconds: 4 }} />); | ||
|
||
expect(screen.getByText('26:03:04')).toBeInTheDocument(); | ||
}); | ||
it('renders correctly when there is no time left', () => { | ||
render(<MarketCountdownTimer time_left={{ days: 0, hours: 0, minutes: 0, seconds: 0 }} />); | ||
|
||
expect(screen.getByText('00:00:00')).toBeInTheDocument(); | ||
}); | ||
it('renders correctly with edge case values', () => { | ||
render(<MarketCountdownTimer time_left={{ days: 0, hours: 1, minutes: 1, seconds: 1 }} />); | ||
|
||
expect(screen.getByText('01:01:01')).toBeInTheDocument(); | ||
}); | ||
}); |
4 changes: 4 additions & 0 deletions
4
packages/trader/src/AppV2/Components/MarketCountdownTimer/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import './market-countdown-timer.scss'; | ||
import MarketCountdownTimer from './market-countdown-timer'; | ||
|
||
export default MarketCountdownTimer; |
8 changes: 8 additions & 0 deletions
8
packages/trader/src/AppV2/Components/MarketCountdownTimer/market-countdown-timer.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
.market-countdown-timer { | ||
display: flex; | ||
gap: var(--core-spacing-200); | ||
|
||
&-text { | ||
color: var(--semantic-color-slate-solid-surface-normal-lowest); | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
packages/trader/src/AppV2/Components/MarketCountdownTimer/market-countdown-timer.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import React from 'react'; | ||
import { Text } from '@deriv-com/quill-ui'; | ||
import { LabelPairedStopwatchMdBoldIcon } from '@deriv/quill-icons'; | ||
|
||
type TMarketCountDownTimer = { | ||
time_left: { | ||
days?: number; | ||
hours?: number; | ||
minutes?: number; | ||
seconds?: number; | ||
}; | ||
}; | ||
|
||
const MarketCountdownTimer = ({ time_left }: TMarketCountDownTimer) => { | ||
let timer_components = ''; | ||
|
||
if (Object.keys(time_left).length) { | ||
const hours = (Number(time_left.days) * 24 + Number(time_left.hours)).toString().padStart(2, '0'); | ||
const minutes = Number(time_left.minutes).toString().padStart(2, '0'); | ||
const seconds = Number(time_left.seconds).toString().padStart(2, '0'); | ||
timer_components = `${hours}:${minutes}:${seconds}`; | ||
} | ||
|
||
return ( | ||
<div className='market-countdown-timer'> | ||
<LabelPairedStopwatchMdBoldIcon fill='var(--semantic-color-slate-solid-surface-normal-lowest)' /> | ||
<Text bold size='md' className='market-countdown-timer-text'> | ||
{timer_components} | ||
</Text> | ||
</div> | ||
); | ||
}; | ||
|
||
export default MarketCountdownTimer; |
20 changes: 20 additions & 0 deletions
20
...rc/AppV2/Components/MarketOpeningTimeBanner/__tests__/market-opening-time-banner.spec.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
import React from 'react'; | ||
import { screen, render } from '@testing-library/react'; | ||
import MarketOpeningTimeBanner from '../market-opening-time-banner'; | ||
|
||
jest.mock('@deriv/shared', () => ({ | ||
convertTimeFormat: jest.fn(time => `Formatted: ${time}`), | ||
toMoment: jest.fn(() => ({ | ||
locale: jest.fn().mockReturnThis(), | ||
add: jest.fn().mockReturnThis(), | ||
format: jest.fn(() => '01 Jan 2024'), | ||
})), | ||
})); | ||
|
||
describe('<MarketOpeningTimeBanner />', () => { | ||
it('renders with correct formatted time and date', () => { | ||
render(<MarketOpeningTimeBanner opening_time='12:34' days_offset={1} current_language='en' />); | ||
|
||
expect(screen.getByText('Formatted: 12:34 (GMT), 01 Jan 2024')).toBeInTheDocument(); | ||
}); | ||
}); |
4 changes: 4 additions & 0 deletions
4
packages/trader/src/AppV2/Components/MarketOpeningTimeBanner/index.ts
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
import './market-opening-time-banner.scss'; | ||
import MarketOpeningTimeBanner from './market-opening-time-banner'; | ||
|
||
export default MarketOpeningTimeBanner; |
3 changes: 3 additions & 0 deletions
3
packages/trader/src/AppV2/Components/MarketOpeningTimeBanner/market-opening-time-banner.scss
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
.market-opening-time-banner { | ||
color: var(--semantic-color-slate-solid-surface-normal-lowest); | ||
} |
30 changes: 30 additions & 0 deletions
30
packages/trader/src/AppV2/Components/MarketOpeningTimeBanner/market-opening-time-banner.tsx
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
import React from 'react'; | ||
import { convertTimeFormat, toMoment } from '@deriv/shared'; | ||
import { Localize } from '@deriv/translations'; | ||
import { CaptionText } from '@deriv-com/quill-ui'; | ||
|
||
type TMarketOpeningTimeBanner = { | ||
opening_time: string; | ||
days_offset: number; | ||
current_language: string; | ||
}; | ||
|
||
const MarketOpeningTimeBanner = ({ opening_time, days_offset, current_language }: TMarketOpeningTimeBanner) => { | ||
const formatted_opening_time = convertTimeFormat(opening_time); | ||
const target_date = toMoment(new Date()).locale(current_language.toLowerCase()).add(days_offset, 'days'); | ||
const opening_date = target_date.format('DD MMM YYYY'); | ||
|
||
return ( | ||
<CaptionText bold className='market-opening-time-banner'> | ||
<Localize | ||
i18n_default_text='{{formatted_opening_time}} (GMT), {{opening_date}}' | ||
values={{ | ||
formatted_opening_time, | ||
opening_date, | ||
}} | ||
/> | ||
</CaptionText> | ||
); | ||
}; | ||
|
||
export default MarketOpeningTimeBanner; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Qs: what's the reason why we want this logic to apply?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ok, seems like it is copied from another component, but the comment is missing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yeah its copied from production