diff --git a/packages/reports/package.json b/packages/reports/package.json index 6734ffe7e131..7ed76358435c 100644 --- a/packages/reports/package.json +++ b/packages/reports/package.json @@ -79,6 +79,7 @@ "@deriv/components": "^1.0.0", "@deriv/deriv-api": "^1.0.8", "@deriv/shared": "^1.0.0", + "@deriv/stores": "^1.0.0", "@deriv/translations": "^1.0.0", "@types/classnames": "^2.2.11", "@types/react": "^18.0.7", diff --git a/packages/reports/src/Components/Form/CompositeCalendar/composite-calendar-mobile.tsx b/packages/reports/src/Components/Form/CompositeCalendar/composite-calendar-mobile.tsx index 65fc4eb32cdd..55afc21aa5f1 100644 --- a/packages/reports/src/Components/Form/CompositeCalendar/composite-calendar-mobile.tsx +++ b/packages/reports/src/Components/Form/CompositeCalendar/composite-calendar-mobile.tsx @@ -53,7 +53,10 @@ type TCompositeCalendarMobileProps = { input_date_range: TInputDateRange; current_focus: string; duration_list: Array; - onChange: (value: { from: number | null; to: number; is_batch: boolean }, extra_data: { date_range: any }) => void; + onChange: ( + value: { from: moment.Moment | null; to: moment.Moment; is_batch: boolean }, + extra_data: { date_range: any } + ) => void; setCurrentFocus: (focus: string) => void; from: number; to: number; @@ -82,11 +85,8 @@ const CompositeCalendarMobile = React.memo( const new_from = _selected_date_range.duration; onChange( { - from: - is_today || new_from - ? toMoment().startOf('day').subtract(new_from, 'day').add(1, 's').unix() - : null, - to: toMoment().endOf('day').unix(), + from: is_today || new_from ? toMoment().startOf('day').subtract(new_from, 'day').add(1, 's') : null, + to: toMoment().endOf('day'), is_batch: true, }, { @@ -99,7 +99,7 @@ const CompositeCalendarMobile = React.memo( const today = toMoment().format('DD MMM YYYY'); const new_from = from_date || to_date || today; - const new_to = to || today; + const new_to = to_date || today; const new_date_range = Object.assign(selected_date_range, { label: `${new_from} - ${new_to}`, @@ -107,8 +107,8 @@ const CompositeCalendarMobile = React.memo( onChange( { - from: toMoment(new_from).startOf('day').add(1, 's').unix(), - to: toMoment(new_to).endOf('day').unix(), + from: toMoment(new_from).startOf('day').add(1, 's'), + to: toMoment(new_to).endOf('day'), is_batch: true, }, { diff --git a/packages/reports/src/Components/Form/CompositeCalendar/composite-calendar.jsx b/packages/reports/src/Components/Form/CompositeCalendar/composite-calendar.tsx similarity index 68% rename from packages/reports/src/Components/Form/CompositeCalendar/composite-calendar.jsx rename to packages/reports/src/Components/Form/CompositeCalendar/composite-calendar.tsx index 4f5008523ed8..691c2fea2cfa 100644 --- a/packages/reports/src/Components/Form/CompositeCalendar/composite-calendar.jsx +++ b/packages/reports/src/Components/Form/CompositeCalendar/composite-calendar.tsx @@ -1,15 +1,31 @@ -import PropTypes from 'prop-types'; import React from 'react'; import Loadable from 'react-loadable'; import { DesktopWrapper, InputField, MobileWrapper, useOnClickOutside } from '@deriv/components'; import { localize } from '@deriv/translations'; -import { daysFromTodayTo, epochToMoment, toMoment } from '@deriv/shared'; +import { daysFromTodayTo, toMoment } from '@deriv/shared'; import { connect } from 'Stores/connect'; +import { TStores } from '@deriv/stores'; import CompositeCalendarMobile from './composite-calendar-mobile'; import SideList from './side-list'; import CalendarIcon from './calendar-icon'; +import TwoMonthPicker from './two-month-picker'; +import moment from 'moment'; + +type TCompositeCalendarProps = { + current_focus: string; + onChange: (values: { [key: string]: moment.Moment }) => void; + setCurrentFocus: () => void; + to: number; + from: number; +}; + +type TTwoMonthPickerLoadableProps = { + onChange: (date: moment.Moment) => void; + isPeriodDisabled: (date: moment.Moment) => boolean; + value: number; +}; -const TwoMonthPicker = Loadable({ +const TwoMonthPickerLoadable = Loadable({ loader: () => import(/* webpackChunkName: "two-month-picker" */ './two-month-picker'), loading: () => null, render(loaded, props) { @@ -18,7 +34,7 @@ const TwoMonthPicker = Loadable({ }, }); -const CompositeCalendar = props => { +const CompositeCalendar: React.FC = props => { const { current_focus, onChange, setCurrentFocus, to, from } = props; const [show_to, setShowTo] = React.useState(false); @@ -56,30 +72,30 @@ const CompositeCalendar = props => { }, ]); - const wrapper_ref = React.useRef(); + const wrapper_ref = React.useRef() as React.MutableRefObject; useOnClickOutside(wrapper_ref, event => { - event.stopPropagation(); - event.preventDefault(); + event?.stopPropagation(); + event?.preventDefault(); hideCalendar(); }); - const selectDateRange = new_from => { + const selectDateRange = (new_from?: number) => { hideCalendar(); applyBatch({ - from: new_from ? toMoment().startOf('day').subtract(new_from, 'day').add(1, 's').unix() : null, - to: toMoment().endOf('day').unix(), + from: new_from ? toMoment().startOf('day').subtract(new_from, 'day').add(1, 's') : null, + to: toMoment().endOf('day'), is_batch: true, }); }; const getToDateLabel = () => { - const date = epochToMoment(to); + const date = toMoment(to); return daysFromTodayTo(date) === 0 ? localize('Today') : date.format('MMM, DD YYYY'); }; const getFromDateLabel = () => { - const date = epochToMoment(from); + const date = toMoment(from); return from ? date.format('MMM, DD YYYY') : ''; }; @@ -88,7 +104,7 @@ const CompositeCalendar = props => { setShowTo(false); }; - const showCalendar = e => { + const showCalendar = (e: string) => { if (e === 'from') { setShowFrom(true); } @@ -97,36 +113,36 @@ const CompositeCalendar = props => { } }; - const setToDate = date => { - updateState('to', epochToMoment(date).endOf('day').unix()); + const setToDate = (date: moment.Moment) => { + updateState('to', toMoment(date as unknown as number).endOf('day')); }; - const setFromDate = date => { + const setFromDate = (date: moment.Moment) => { updateState('from', date); hideCalendar(); }; - const updateState = (key, value) => { + const updateState = (key: string, value: moment.Moment | number) => { apply(key, value); hideCalendar(); }; - const applyBatch = values => { + const applyBatch = (values: { [key: string]: any }) => { onChange(values); }; - const apply = (key, value) => { + const apply = (key: string, value: any) => { applyBatch({ [key]: value, }); }; - const isPeriodDisabledTo = date => { - return date + 1 <= from || date > toMoment().endOf('day').unix(); + const isPeriodDisabledTo = (date: moment.Moment) => { + return date.clone().add(1, 'days').isSameOrBefore(from) || date.isAfter(toMoment().endOf('day')); }; - const isPeriodDisabledFrom = date => { - return date - 1 >= to; + const isPeriodDisabledFrom = (date: moment.Moment) => { + return moment(date).subtract(1, 'days').isSameOrAfter(to); }; return ( @@ -157,13 +173,17 @@ const CompositeCalendar = props => { {show_to && (
- +
)} {show_from && (
- +
)} @@ -176,15 +196,8 @@ const CompositeCalendar = props => { CompositeCalendar.displayName = 'CompositeCalendar'; -CompositeCalendar.propTypes = { - current_focus: PropTypes.string, - from: PropTypes.number, - onChange: PropTypes.func, - setCurrentFocus: PropTypes.func, - to: PropTypes.number, -}; export default React.memo( - connect(({ ui }) => ({ + connect(({ ui }: TStores) => ({ current_focus: ui.current_focus, setCurrentFocus: ui.setCurrentFocus, }))(CompositeCalendar) diff --git a/packages/reports/src/Components/Form/CompositeCalendar/two-month-picker.tsx b/packages/reports/src/Components/Form/CompositeCalendar/two-month-picker.tsx index d6d8ca7a87e2..f04113fbb1ae 100644 --- a/packages/reports/src/Components/Form/CompositeCalendar/two-month-picker.tsx +++ b/packages/reports/src/Components/Form/CompositeCalendar/two-month-picker.tsx @@ -5,14 +5,12 @@ import { addMonths, diffInMonths, epochToMoment, subMonths, toMoment } from '@de type TTwoMonthPicker = { onChange: (date: moment.MomentInput) => void; - isPeriodDisabled: (date: moment.MomentInput) => boolean; - value: number; + isPeriodDisabled: (date: moment.Moment) => boolean; + value: moment.Moment; }; const TwoMonthPicker = React.memo(({ onChange, isPeriodDisabled, value }: TTwoMonthPicker) => { - const [left_pane_date, setLeftPaneDate] = React.useState( - subMonths(value ? new Date(value * 1000).toISOString() : '', 1).unix() - ); + const [left_pane_date, setLeftPaneDate] = React.useState(toMoment(value).clone().subtract(1, 'month')); const [right_pane_date, setRightPaneDate] = React.useState(value); /** @@ -21,8 +19,8 @@ const TwoMonthPicker = React.memo(({ onChange, isPeriodDisabled, value }: TTwoMo * @param {moment.Moment} date */ const navigateFrom = (date: moment.Moment) => { - setLeftPaneDate(date.unix()); - setRightPaneDate(addMonths(date.toISOString(), 1).unix()); + setLeftPaneDate(date); + setRightPaneDate(addMonths(date.toISOString(), 1)); }; /** @@ -31,8 +29,8 @@ const TwoMonthPicker = React.memo(({ onChange, isPeriodDisabled, value }: TTwoMo * @param {moment.Moment} date */ const navigateTo = (date: moment.Moment) => { - setLeftPaneDate(subMonths(date.toISOString(), 1).unix()); - setRightPaneDate(toMoment(date).unix()); + setLeftPaneDate(subMonths(date.toISOString(), 1)); + setRightPaneDate(toMoment(date)); }; /** @@ -42,7 +40,7 @@ const TwoMonthPicker = React.memo(({ onChange, isPeriodDisabled, value }: TTwoMo * @param {Extract} range */ const validateFromArrows = (date: moment.Moment, range: Extract) => { - return diffInMonths(epochToMoment(left_pane_date), date) !== -1; + return diffInMonths(toMoment(left_pane_date), date) !== -1; }; /** @@ -53,7 +51,7 @@ const TwoMonthPicker = React.memo(({ onChange, isPeriodDisabled, value }: TTwoMo * @param {Extract} range */ const validateToArrows = (date: moment.Moment, range: Extract) => { - const r_date = epochToMoment(right_pane_date).startOf('month'); + const r_date = toMoment(right_pane_date).startOf('month'); if (diffInMonths(toMoment().startOf('month'), r_date) === 0) return true; // future months are disallowed return diffInMonths(r_date, date) !== 1; }; @@ -64,17 +62,17 @@ const TwoMonthPicker = React.memo(({ onChange, isPeriodDisabled, value }: TTwoMo * @param {moment.Moment} date */ const shouldDisableDate = (date: moment.Moment) => { - return isPeriodDisabled(date.unix()); + return isPeriodDisabled(date); }; const jumpToCurrentMonth = () => { - const current_month = toMoment().endOf('month').unix(); - setLeftPaneDate(epochToMoment(current_month).endOf('month').subtract(1, 'month').unix()); + const current_month = toMoment().endOf('month'); + setLeftPaneDate(toMoment(current_month).endOf('month').subtract(1, 'month')); setRightPaneDate(current_month); }; const updateSelectedDate = (e: React.MouseEvent) => { - onChange(moment.utc(e.currentTarget.dataset.date, 'YYYY-MM-DD').unix()); + onChange(moment.utc(e.currentTarget.dataset.date, 'YYYY-MM-DD')); }; return ( diff --git a/packages/reports/src/Stores/Modules/Profit/profit-store.js b/packages/reports/src/Stores/Modules/Profit/profit-store.js index e393e1b6db7e..cd22a5d3c9c8 100644 --- a/packages/reports/src/Stores/Modules/Profit/profit-store.js +++ b/packages/reports/src/Stores/Modules/Profit/profit-store.js @@ -12,7 +12,7 @@ const delay_on_scroll_time = 150; export default class ProfitTableStore extends BaseStore { data = []; date_from = null; - date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's').unix(); + date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's'); error = ''; has_loaded_all = false; is_loading = false; @@ -81,7 +81,7 @@ export default class ProfitTableStore extends BaseStore { const response = await WS.profitTable( batch_size, this.data.length, - getDateBoundaries(this.date_from, this.date_to, 0, false) + getDateBoundaries(this.date_from?.unix(), this.date_to?.unix(), 0, false) ); this.profitTableResponseHandler(response); @@ -171,7 +171,7 @@ export default class ProfitTableStore extends BaseStore { clearDateFilter() { this.date_from = null; - this.date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's').unix(); + this.date_to = toMoment().startOf('day').add(1, 'd').subtract(1, 's'); } handleDateChange(date_values, { date_range } = {}) { diff --git a/packages/shared/src/utils/date/date-time.ts b/packages/shared/src/utils/date/date-time.ts index 844bc3426aa7..67b6ce617dc4 100644 --- a/packages/shared/src/utils/date/date-time.ts +++ b/packages/shared/src/utils/date/date-time.ts @@ -81,7 +81,7 @@ export const formatTime = (epoch: number | string, time_format = 'HH:mm:ss [GMT] * @param {String} date the date to calculate number of days from today * @return {Number} an integer of the number of days */ -export const daysFromTodayTo = (date?: string) => { +export const daysFromTodayTo = (date?: string | moment.Moment) => { const diff = toMoment(date).startOf('day').diff(toMoment().startOf('day'), 'days'); return !date || diff < 0 ? '' : diff; };