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

fixes 6106 month/year datepicker-ui not working #6199

Merged
Prev Previous commit
Refactor to used controlled input behavior
  • Loading branch information
charlesBochet committed Jul 13, 2024
commit 92c35f4ce8e3cee3ed4a142b423be12ee606de0c
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,12 @@ import { v4 } from 'uuid';

import { useFilterDropdown } from '@/object-record/object-filter-dropdown/hooks/useFilterDropdown';
import { InternalDatePicker } from '@/ui/input/components/internal/date/components/InternalDatePicker';
import { useState } from 'react';
import { isDefined } from '~/utils/isDefined';

export const ObjectFilterDropdownDateInput = () => {
const [internalDate, setInternalDate] = useState<Date | null>(new Date());

const {
filterDefinitionUsedInDropdownState,
selectedOperandInDropdownState,
Expand All @@ -24,6 +27,8 @@ export const ObjectFilterDropdownDateInput = () => {
const selectedFilter = useRecoilValue(selectedFilterState);

const handleChange = (date: Date | null) => {
setInternalDate(date);

if (!filterDefinitionUsedInDropdown || !selectedOperandInDropdown) return;
selectFilter?.({
id: selectedFilter?.id ? selectedFilter.id : v4(),
Expand All @@ -39,7 +44,7 @@ export const ObjectFilterDropdownDateInput = () => {

return (
<InternalDatePicker
date={new Date()}
date={internalDate}
onChange={handleChange}
onMouseSelect={handleChange}
/>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import ReactDatePicker from 'react-datepicker';
import styled from '@emotion/styled';
import { DateTime } from 'luxon';
import ReactDatePicker from 'react-datepicker';
import { Key } from 'ts-key-enum';
import {
IconCalendarX,
Expand All @@ -18,7 +18,6 @@ import { StyledHoverableMenuItemBase } from '@/ui/navigation/menu-item/internals
import { isDefined } from '~/utils/isDefined';

import 'react-datepicker/dist/react-datepicker.css';
import { useState } from 'react';

export const months = [
{ label: 'January', value: 0 },
Expand Down Expand Up @@ -299,7 +298,7 @@ const StyledCustomDatePickerHeader = styled.div`
`;

export type InternalDatePickerProps = {
date: Date;
date: Date | null;
onMouseSelect?: (date: Date | null) => void;
onChange?: (date: Date | null) => void;
clearable?: boolean;
Expand All @@ -309,11 +308,6 @@ export type InternalDatePickerProps = {
keyboardEventsDisabled?: boolean;
onClear?: () => void;
};
type SelectedDate = {
month: number;
day: number;
year: number;
};

export const InternalDatePicker = ({
date,
Expand All @@ -327,11 +321,6 @@ export const InternalDatePicker = ({
onClear,
}: InternalDatePickerProps) => {
const internalDate = date ?? new Date();
const [selectedDate, setSelectedDate] = useState<SelectedDate>({
year: internalDate.getFullYear(),
month: internalDate.getMonth(), // Note: JavaScript months are 0-indexed
day: internalDate.getDate(),
});

const { closeDropdown } = useDropdown(MONTH_AND_YEAR_DROPDOWN_ID);
const { closeDropdown: closeDropdownMonthSelect } = useDropdown(
Expand Down Expand Up @@ -383,25 +372,23 @@ export const InternalDatePicker = ({
};

const handleChangeMonth = (month: number) => {
const newDate = new Date(date);
const newDate = new Date(internalDate);
newDate.setMonth(month);
setSelectedDate({ ...selectedDate, month: newDate.getMonth() });
onChange?.(newDate);
};

const handleChangeYear = (year: number) => {
const newDate = new Date(date);
const newDate = new Date(internalDate);
newDate.setFullYear(year);
setSelectedDate({ ...selectedDate, year: newDate.getFullYear() });
onChange?.(newDate);
};

const dateWithoutTime = DateTime.fromJSDate(date)
const dateWithoutTime = DateTime.fromJSDate(internalDate)
.toLocal()
.set({
day: date.getUTCDate(),
month: date.getUTCMonth() + 1,
year: date.getUTCFullYear(),
day: internalDate.getUTCDate(),
month: internalDate.getUTCMonth() + 1,
year: internalDate.getUTCFullYear(),
hour: 0,
minute: 0,
second: 0,
Expand All @@ -416,9 +403,11 @@ export const InternalDatePicker = ({
<ReactDatePicker
open={true}
selected={dateToUse}
openToDate={dateToUse}
openToDate={isDefined(dateToUse) ? dateToUse : undefined}
disabledKeyboardNavigation
onChange={(newDate) => {
newDate?.setHours(internalDate.getUTCHours());
newDate?.setUTCMinutes(internalDate.getUTCMinutes());
onChange?.(newDate);
}}
customInput={
Expand Down Expand Up @@ -452,13 +441,13 @@ export const InternalDatePicker = ({
options={months}
disableBlur
onChange={handleChangeMonth}
value={selectedDate.month}
value={internalDate.getUTCMonth()}
fullWidth
/>
<Select
dropdownId={MONTH_AND_YEAR_DROPDOWN_YEAR_SELECT_ID}
onChange={handleChangeYear}
value={selectedDate.year}
value={internalDate.getUTCFullYear()}
options={years}
disableBlur
fullWidth
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import { useArgs } from '@storybook/preview-api';
import { Meta, StoryObj } from '@storybook/react';
import { expect, userEvent, within } from '@storybook/test';
import { ComponentDecorator } from 'twenty-ui';

import { isDefined } from '~/utils/isDefined';
import { InternalDatePicker } from '../InternalDatePicker';

const meta: Meta<typeof InternalDatePicker> = {
Expand All @@ -11,6 +13,16 @@ const meta: Meta<typeof InternalDatePicker> = {
argTypes: {
date: { control: 'date' },
},
render: ({ date }) => {
// eslint-disable-next-line react-hooks/rules-of-hooks
const [, updateArgs] = useArgs();
return (
<InternalDatePicker
date={isDefined(date) ? new Date(date) : new Date()}
onChange={(newDate) => updateArgs({ date: newDate })}
/>
);
},
args: { date: new Date('January 1, 2023 02:00:00') },
};

Expand Down Expand Up @@ -42,5 +54,27 @@ export const WithOpenMonthSelect: Story = {
].forEach((monthLabel) =>
expect(canvas.getByText(monthLabel)).toBeInTheDocument(),
);

await userEvent.click(canvas.getByText('February'));

expect(canvas.getByText('February')).toBeInTheDocument();
},
};

export const WithOpenYearSelect: Story = {
play: async () => {
const canvas = within(document.body);

const yearSelect = await canvas.findByText('2023');

await userEvent.click(yearSelect);

['2024', '2025', '2026'].forEach((yearLabel) =>
expect(canvas.getByText(yearLabel)).toBeInTheDocument(),
);

await userEvent.click(canvas.getByText('2024'));

expect(canvas.getByText('2024')).toBeInTheDocument();
},
};
Loading