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

Monthpicker #21

Open
wants to merge 4 commits into
base: develop
Choose a base branch
from
Open
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
2 changes: 1 addition & 1 deletion src/components/IconButton/IconButton.tsx
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import React from 'react';
import { IconButtonColors, IconButtonSizes } from '../../constants/general';
import styles from './sass/IconButton.module.scss';
import { IconButtonProps } from './interfaces/IIconButton';
import { IconButtonColors, IconButtonSizes } from '../../constants/general';

const IconButton: React.FC<IconButtonProps> = ({
size = IconButtonSizes.Medium,
Expand Down
17 changes: 17 additions & 0 deletions src/components/Icons/ArrowLeftIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { FC } from 'react';
import { IIconsProps } from './interfaces/IIcons';

const AttachmentIcon: FC<IIconsProps> = ({ fill = 'currentColor' }) => (
<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d={'M6.70998 0.710469C6.31998 0.320469 5.68998 0.320469 5.29998 0.710469L0.70998 5.30047C0.31998 '
+ '5.69047 0.31998 6.32047 0.70998 6.71047L5.29998 11.3005C5.68998 11.6905 6.31998 11.6905 6.70998 '
+ '11.3005C7.09998 10.9105 7.09998 10.2805 6.70998 9.89047L2.82998 6.00047L6.70998 2.12047C7.09998 '
+ '1.73047 7.08998 1.09047 6.70998 0.710469Z'}
fill={fill}
/>
</svg>

);

export default AttachmentIcon;
17 changes: 17 additions & 0 deletions src/components/Icons/ArrowRightIcon.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import React, { FC } from 'react';
import { IIconsProps } from './interfaces/IIcons';

const AttachmentIcon: FC<IIconsProps> = ({ fill = 'currentColor' }) => (
<svg width="8" height="12" viewBox="0 0 8 12" fill="none" xmlns="http://www.w3.org/2000/svg">
<path
d={'M1.29002 11.2895C1.68002 11.6795 2.31002 11.6795 2.70002 11.2895L7.29002 6.69953C7.68002'
+ ' 6.30953 7.68002 5.67953 7.29002 5.28953L2.70002 0.699532C2.31002 0.309532 1.68002 0.309532 '
+ '1.29002 0.699532C0.90002 1.08953 0.90002 1.71953 1.29002 2.10953L5.17002 5.99953L1.29002'
+ ' 9.87953C0.90002 10.2695 0.91002 10.9095 1.29002 11.2895Z'}
fill={fill}
/>
</svg>

);

export default AttachmentIcon;
3 changes: 3 additions & 0 deletions src/components/Icons/interfaces/IIcons.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export interface IIconsProps {
fill?: string,
}
71 changes: 71 additions & 0 deletions src/components/MonthPicker/MonthPicker.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
import React, { FC, useState } from 'react';
import IconButton from '../IconButton/IconButton';
import { parseToMonthInt, parseMonthIntToObj } from '../../utils/helpers';
import { DEFAULT_MONTH_INT, DEFAULT_YEAR_RANGE, MONTHS } from '../../constants/common';
import ArrowLeftIcon from '../Icons/ArrowLeftIcon';
import ArrowRightIcon from '../Icons/ArrowRightIcon';
import styles from './sass/MonthPicker.module.scss';
import { IMonthPickerProps } from './interfaces/IMonthPicker';

const MonthPicker: FC<IMonthPickerProps> = ({
onChange,
monthInt = DEFAULT_MONTH_INT,
yearRange = DEFAULT_YEAR_RANGE,
className = '',
}) => {
const { minYear, maxYear } = yearRange;
const { month, year } = parseMonthIntToObj(monthInt);
const [currentYear, setYear] = useState(year);

return (
<div className={`${styles.container} ${className}`}>
<div className={styles.year}>
<IconButton
tabIndex={-1}
onClick={() => setYear(currentYear - 1)}
aria-label="prevYear"
aria-disabled={currentYear <= minYear}
icon={<ArrowLeftIcon />}
/>
<div
className={styles.selectedYear}
>
<span>
{currentYear}
</span>
</div>
<IconButton
tabIndex={-1}
onClick={() => setYear(currentYear + 1)}
aria-label="nextYear"
aria-disabled={currentYear >= maxYear}
icon={<ArrowRightIcon />}
/>
</div>
<div className={styles.months}>
{MONTHS.map((item, index) => (
<div
aria-label={item}
key={item}
role="gridcell"
tabIndex={-1}
className={`${styles.month} ${month === index && currentYear === year ? styles.selected : ''}`}
onClick={() => {
onChange({
month: parseToMonthInt(currentYear, index + 1),
monthIndex: index,
year: currentYear,
monthName: item,
});
}}
onKeyDown={() => {}}
>
<span>{item}</span>
</div>
))}
</div>
</div>
);
};

export default MonthPicker;
18 changes: 18 additions & 0 deletions src/components/MonthPicker/interfaces/IMonthPicker.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
export interface IYearRange {
minYear: number
maxYear: number
}

export interface IMonthPickerInfo {
month: number
monthIndex: number
year: number
monthName: string,
}

export interface IMonthPickerProps {
onChange: (value: IMonthPickerInfo) => void
monthInt?: number
className?: string
yearRange?: IYearRange
}
84 changes: 84 additions & 0 deletions src/components/MonthPicker/sass/MonthPicker.module.scss
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
@import "../../../sass/colors";

.container {
width: 170px;
background-color: $white;
box-shadow: 0 4px 22px $shadow;

.year {
height: 32px;
display: flex;
align-items: center;
justify-content: space-between;
padding: 4px;
border-bottom: 1px solid $light-gray;

.navBtnPrev, .navBtnNext {
position: relative;
width: 24px;
height: 24px;
border-radius: 4px;
transition: .3s;
cursor: pointer;

&[aria-disabled="true"] {
pointer-events: none;
}

&:before {
position: absolute;
content: "";
width: 24px;
height: 24px;

background: {
repeat: no-repeat;
position: center;
};
}

&:hover {
background-color: $outlined-hover;
}
}

.selectedYear {
font-weight: bold;
font-size: 13px;
line-height: 16px;
color: #000000;
}
}

.months {
display: flex;
flex-wrap: wrap;

.month {
width: 50%;
text-align: center;
font-size: 13px;
line-height: 16px;
padding: 8px;
cursor: pointer;
transition: .3s;
border-bottom: 1px solid $light-gray;

&.selected {
color: $primary;

&:hover {
color: $dark-gray;
}
}

&:nth-child(even) {
border-left: 1px solid $light-gray;
}

&:hover {
background-color: $light-blue;
}
}
}
}
13 changes: 13 additions & 0 deletions src/constants/common.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { getMonthIntFromDate } from '../utils/helpers';

export const MONTHS = [
'January', 'February', 'March', 'April', 'May', 'June', 'July',
'August', 'September', 'October', 'November', 'December',
];

export const DEFAULT_YEAR_RANGE = {
minYear: 2000,
maxYear: 2100,
};

export const DEFAULT_MONTH_INT = getMonthIntFromDate().monthInt;
1 change: 1 addition & 0 deletions src/sass/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -17,3 +17,4 @@ $light-gray: #EBEEF2;
$light-gray-2: #C4C4C4;
$light-yellow: #FDFAEB;
$transparent: #FFFFFF00;
$shadow: #2B2C3028;
1 change: 1 addition & 0 deletions src/sass/main.scss
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
* {
box-sizing: border-box;
font-family: -apple-system,Inter,BlinkMacSystemFont,Segoe UI,Roboto,Oxygen,Ubuntu,Cantarell,Fira Sans,Droid Sans,Helvetica Neue,sans-serif;
}
20 changes: 20 additions & 0 deletions src/stories/MonthPicker.stories.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import MonthPicker from '../components/MonthPicker/MonthPicker';

export default {
title: 'Example/MonthPicker',
component: MonthPicker,
} as ComponentMeta<typeof MonthPicker>;

const Template: ComponentStory<typeof MonthPicker> = (args) => <MonthPicker {...args} />;

export const Default = Template.bind({});
Default.args = {
onChange: () => {},
yearRange: {
minYear: 2020,
maxYear: 2025,
},
monthInt: 202310,
};
28 changes: 28 additions & 0 deletions src/utils/helpers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
export const getMonthIntFromDate = (date = new Date()) => {
const month = date.getMonth();
const year = date.getFullYear();
const monthInt = +(`${year}${month < 9 ? `0${month + 1}` : month + 1}`);

return { monthInt, month, year };
};

export const parseToMonthInt = (year: number, month: number) => (
parseInt(`${year}${month >= 10 ? month : `0${month}`}`)
);

export const parseMonthIntToObj = (monthInt?: number) => {
let year;
let month;

if (monthInt) {
const str = monthInt.toString();
year = parseInt(str.slice(0, 4));
month = +str.slice(4) - 1;
} else {
const date = new Date();
year = date.getFullYear();
month = date.getMonth();
}

return { month, year };
};