Skip to content

'DateSelector' #161

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

Open
wants to merge 18 commits into
base: develop
Choose a base branch
from
Open
18 changes: 11 additions & 7 deletions lib/components/atoms/Select/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,13 @@ const Select = ({
data-locator={elementLocator || `select-input-${name}-${id}`}
{...others}
>
{placeholder && <option value="">{placeholder}</option>}
{options.map(opt => (
<option key={opt} value={opt}>
{placeholder && (
<option value="" disabled selected>
{placeholder}
</option>
)}
{options.map((opt, index) => (
<option key={`${name}_${index.toString()}`} value={opt}>
{opt}
</option>
))}
Expand All @@ -46,10 +50,10 @@ const Select = ({

Select.defaultProps = {
disabled: false,
selectedOption: '',
placeholder: '',
className: '',
elementLocator: '',
selectedOption: 'select',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By default selected option should be null

placeholder: 'Select',
className: 'select',
elementLocator: 'select',
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Set elementLocator default value as null

};

export default styled(Select)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@

exports[`Select Styled component should render correctly 1`] = `
<select
className=""
data-locator="select-input-userType-undefined"
className="select"
data-locator="select"
disabled={false}
name="userType"
theme={
Expand Down Expand Up @@ -221,16 +221,23 @@ exports[`Select Styled component should render correctly 1`] = `
},
}
}
value=""
value="select"
>
<option
key="Option 1"
disabled={true}
selected={true}
value=""
>
Select
</option>
<option
key="userType_0"
value="Option 1"
>
Option 1
</option>
<option
key="Option 2"
key="userType_1"
value="Option 2"
>
Option 2
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@

exports[`Select Component should render correctly 1`] = `
<select
className=""
className="select"
data-locator="my-custom-select-locator"
disabled={false}
id="dropdown-1"
name="my-drop"
onChange={[Function]}
value=""
value="select"
>
<option
key="Option 1"
disabled={true}
selected={true}
value=""
>
Select
</option>
<option
key="my-drop_0"
value="Option 1"
>
Option 1
</option>
<option
key="Option 2"
key="my-drop_1"
value="Option 2"
>
Option 2
Expand Down
170 changes: 170 additions & 0 deletions lib/components/molecules/DateSelector/DateSelector.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
// @flow
/**
*
* DateSelector
*
*/
import React, { useEffect, useState } from 'react';
import styled from 'styled-components';

import classNames from 'classnames';
import styles from './DateSelector.style';
import type { Props } from './types';
import Select from '../../atoms/Select';
import Label from '../../atoms/Label';

const DateSelector = ({ id, className, format, startDate, endDate, locale }: Props): Node => {
const [selectedDate, setSelectedDate] = useState(new Date());
const [months, setMonths] = useState([]);

const getMonths = () => {
const date = new Date();
const monthsOptions = [];
for (let i = 0; i < 12; i += 1) {
date.setMonth(i);
monthsOptions.push(date.toLocaleString(locale, { month: 'long' }));
}
return monthsOptions;
};

useEffect(() => {
setMonths(getMonths());
}, []);

useEffect(() => {
setSelectedDate(startDate);
}, [startDate, endDate]);

const getDaysInMonth = () => {
const daysOptions = [];
let startDay = 1;
let endDay = new Date(selectedDate.getFullYear(), selectedDate.getMonth(), 0).getDate();
if (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't understand what this logic below is doing, first line itself has given you all the values.

You must break this complexity

Copy link
Collaborator Author

@kirtisharma1 kirtisharma1 Dec 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That was a mistake. Made changes

selectedDate.getMonth() === startDate.getMonth() &&
selectedDate.getFullYear() === startDate.getFullYear()
) {
startDay = startDate.getDate();
}
if (
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Still there is redundant code we can reduce, for example:

  1. These 2 If conditions were we are startDay and endDay could be returned by a function.

selectedDate.getMonth() === endDate.getMonth() &&
selectedDate.getFullYear() === endDate.getFullYear()
) {
endDay = endDate.getDate();
}
for (let i = startDay; i <= endDay; i += 1) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hope you know end date and start date are optional features so that might be required or might not be in some use-cases

Copy link
Collaborator Author

@kirtisharma1 kirtisharma1 Dec 16, 2019

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

these are optional features but to show default start and end dates I'm using these

daysOptions.push(i);
}
return daysOptions;
};

const getMonthOptions = () => {
let monthOptions = [...months];
if (selectedDate.getFullYear() === startDate.getFullYear()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here, this could be returned by a function and also clear case of If or else.

const startMonth = startDate.getMonth();
monthOptions = monthOptions.slice(startMonth, months.length);
}
if (selectedDate.getFullYear() === endDate.getFullYear()) {
const endMonth = endDate.getMonth();
monthOptions = monthOptions.slice(0, endMonth + 1);
}
return monthOptions;
};

const getYearOptions = () => {
const years = [];
for (let i = startDate.getFullYear(); i <= endDate.getFullYear(); i += 1) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

years.push(i);
}
return years;
};

const DaySelector = (
<>
<Label htmlFor={`${id}-day`} />
<Select
onChange={e => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

return setSelectedDate(
new Date(selectedDate.getFullYear(), selectedDate.getMonth(), e.target.value)
);
}}
id={`${id}-day`}
name="day"
className={classNames('date', className)}
selectedOption={selectedDate.getDate()}
options={getDaysInMonth()}
/>
</>
);

const MonthSelector = (
<>
<Label htmlFor={`${id}-month`} />
<Select
onChange={e => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

return setSelectedDate(
new Date(
selectedDate.getFullYear(),
months.indexOf(e.target.value),
selectedDate.getDate()
)
);
}}
id={`${id}-month`}
name="month"
className={classNames('month', className)}
selectedOption={months[selectedDate.getMonth()]}
options={getMonthOptions()}
/>
</>
);

const YearSelector = (
<>
<Label htmlFor={`${id}-year`} />
<Select
onChange={e => {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like there's a label missing for this input. That makes it hard for people using screen readers or voice control to use the input.

return setSelectedDate(
new Date(e.target.value, selectedDate.getMonth(), selectedDate.getDate())
);
}}
id={`${id}-year`}
name="year"
className={classNames('year', className)}
selectedOption={selectedDate.getFullYear()}
options={getYearOptions()}
/>
</>
);

const renderSelector = value => {
switch (value.toLowerCase()) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nice

case 'mmddyy':
case 'mmddyyyy':
return [MonthSelector, DaySelector, YearSelector];
case 'mmyy':
case 'mmyyyy':
return [MonthSelector, YearSelector];
case 'ddmmyy':
case 'ddmmyyyy':
default:
return [DaySelector, MonthSelector, YearSelector];
}
};

return <div className={className}>{renderSelector(format)}</div>;
};

DateSelector.defaultProps = {
id: 'date-selector',
className: 'date-selector',
format: 'ddmmyy',
startDate: new Date(),
endDate: new Date(new Date().setFullYear(new Date().getFullYear() + 50)),
locale: 'default',
};

export default styled(DateSelector)`
${styles};
`;

export { DateSelector as DateSelectorVanilla };
44 changes: 44 additions & 0 deletions lib/components/molecules/DateSelector/DateSelector.mock.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
const dateSelectorDefaultProps = {
className: 'example',
defaultValue: new Date(),
format: 'ddmmyy',
};

const mmddyyFormatProps = {
className: 'example',
format: 'mmddyy',
startDate: new Date(),
};

const monthYearOnlyProps = {
className: 'example',
format: 'mmyy',
};

const startDateProps = {
className: 'example',
format: 'ddmmyy',
startDate: new Date(955865024000),
};

const endDateProps = {
className: 'example',
format: 'ddmmyy',
endDate: new Date(2555865024000),
};

const startAndEndDateProps = {
className: 'example',
format: 'ddmmyy',
startDate: new Date(955865024000),
endDate: new Date(2555865024000),
};

export {
dateSelectorDefaultProps,
mmddyyFormatProps,
monthYearOnlyProps,
startDateProps,
endDateProps,
startAndEndDateProps,
};
24 changes: 24 additions & 0 deletions lib/components/molecules/DateSelector/DateSelector.story.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import React from 'react';
import { storiesOf } from '@storybook/react';
// import { action } from '@storybook/addon-actions';
import {
dateSelectorDefaultProps,
mmddyyFormatProps,
monthYearOnlyProps,
startDateProps,
endDateProps,
startAndEndDateProps,
} from './DateSelector.mock';

// Import Styled Component to showcase variations
import DateSelector, { DateSelectorVanilla } from '.';

storiesOf('Molecules/DateSelector', module)
.addParameters({ jest: ['DateSelector', 'DateSelectorVanilla'] })
.add('Knobs', () => <DateSelectorVanilla {...dateSelectorDefaultProps} />)
.add('DateSelector format ddmmyyyy', () => <DateSelector {...dateSelectorDefaultProps} />)
.add('DateSelector format mmddyyyy', () => <DateSelector {...mmddyyFormatProps} />)
.add('DateSelector format mmyyyy', () => <DateSelector {...monthYearOnlyProps} />)
.add('DateSelector with Start Date', () => <DateSelector {...startDateProps} />)
.add('DateSelector with End Date', () => <DateSelector {...endDateProps} />)
.add('DateSelector with Start and End Date', () => <DateSelector {...startAndEndDateProps} />);
5 changes: 5 additions & 0 deletions lib/components/molecules/DateSelector/DateSelector.style.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import { css } from 'styled-components';

export default css`
${props => (props.inheritedStyles ? props.inheritedStyles : '')};
`;
3 changes: 3 additions & 0 deletions lib/components/molecules/DateSelector/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
// @flow
export { default } from './DateSelector';
export { DateSelectorVanilla } from './DateSelector';
Loading