Skip to content
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

Akmal / chore: migrate composite calendar to typescript #25

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/reports/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,10 @@ type TCompositeCalendarMobileProps = {
input_date_range: TInputDateRange;
current_focus: string;
duration_list: Array<TInputDateRange>;
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;
Expand Down Expand Up @@ -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,
},
{
Expand All @@ -99,16 +99,16 @@ 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}`,
});

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,
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -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<TTwoMonthPickerLoadableProps, typeof TwoMonthPicker>({
loader: () => import(/* webpackChunkName: "two-month-picker" */ './two-month-picker'),
loading: () => null,
render(loaded, props) {
Expand All @@ -18,7 +34,7 @@ const TwoMonthPicker = Loadable({
},
});

const CompositeCalendar = props => {
const CompositeCalendar: React.FC<TCompositeCalendarProps> = props => {
const { current_focus, onChange, setCurrentFocus, to, from } = props;

const [show_to, setShowTo] = React.useState(false);
Expand Down Expand Up @@ -56,30 +72,30 @@ const CompositeCalendar = props => {
},
]);

const wrapper_ref = React.useRef();
const wrapper_ref = React.useRef() as React.MutableRefObject<HTMLInputElement>;

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') : '';
};

Expand All @@ -88,7 +104,7 @@ const CompositeCalendar = props => {
setShowTo(false);
};

const showCalendar = e => {
const showCalendar = (e: string) => {
if (e === 'from') {
setShowFrom(true);
}
Expand All @@ -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 (
Expand Down Expand Up @@ -157,13 +173,17 @@ const CompositeCalendar = props => {
{show_to && (
<div className='composite-calendar' ref={wrapper_ref}>
<SideList from={from} to={to} items={list} />
<TwoMonthPicker value={to} onChange={setToDate} isPeriodDisabled={isPeriodDisabledTo} />
<TwoMonthPickerLoadable value={to} onChange={setToDate} isPeriodDisabled={isPeriodDisabledTo} />
</div>
)}
{show_from && (
<div className='composite-calendar' ref={wrapper_ref}>
<SideList from={from} to={to} items={list} />
<TwoMonthPicker value={from} onChange={setFromDate} isPeriodDisabled={isPeriodDisabledFrom} />
<TwoMonthPickerLoadable
value={from}
onChange={setFromDate}
isPeriodDisabled={isPeriodDisabledFrom}
/>
</div>
)}
</DesktopWrapper>
Expand All @@ -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)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

/**
Expand All @@ -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));
};

/**
Expand All @@ -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));
};

/**
Expand All @@ -42,7 +40,7 @@ const TwoMonthPicker = React.memo(({ onChange, isPeriodDisabled, value }: TTwoMo
* @param {Extract<moment.DurationInputArg2, 'month'>} range
*/
const validateFromArrows = (date: moment.Moment, range: Extract<moment.DurationInputArg2, 'month'>) => {
return diffInMonths(epochToMoment(left_pane_date), date) !== -1;
return diffInMonths(toMoment(left_pane_date), date) !== -1;
};

/**
Expand All @@ -53,7 +51,7 @@ const TwoMonthPicker = React.memo(({ onChange, isPeriodDisabled, value }: TTwoMo
* @param {Extract<moment.DurationInputArg2, 'month'>} range
*/
const validateToArrows = (date: moment.Moment, range: Extract<moment.DurationInputArg2, 'month'>) => {
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;
};
Expand All @@ -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<HTMLElement>) => {
onChange(moment.utc(e.currentTarget.dataset.date, 'YYYY-MM-DD').unix());
onChange(moment.utc(e.currentTarget.dataset.date, 'YYYY-MM-DD'));
};

return (
Expand Down
6 changes: 3 additions & 3 deletions packages/reports/src/Stores/Modules/Profit/profit-store.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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 } = {}) {
Expand Down
2 changes: 1 addition & 1 deletion packages/shared/src/utils/date/date-time.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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;
};
Expand Down