From 8c5e4a08bf2599a0a4c41ededec63fe2f725f8dd Mon Sep 17 00:00:00 2001 From: Sergey Krylov Date: Wed, 24 Apr 2024 05:53:42 +0300 Subject: [PATCH] feat: update project to typescript #9 --- .../MoneyControllApp/{index.js => index.ts} | 0 .../RouterProvider/{index.jsx => index.tsx} | 0 ...App.spec.jsx => MoneyControllApp.spec.tsx} | 0 ...rollApp.ui.jsx => MoneyControllApp.ui.tsx} | 0 src/global.d.ts | 5 ++ src/pages/CalendarPage/{index.js => index.ts} | 0 ...alendarPage.ui.jsx => CalendarPage.ui.tsx} | 1 + src/shared/constants/{date.js => date.ts} | 6 +++ src/shared/constants/{index.js => index.ts} | 6 +++ src/shared/constants/{locale.js => locale.ts} | 19 +++++-- .../hoc/withProvider/{index.js => index.ts} | 0 ...rovider.spec.jsx => withProvider.spec.tsx} | 18 ++++--- .../hoc/withProvider/ui/withProvider.ui.jsx | 9 ---- .../hoc/withProvider/ui/withProvider.ui.tsx | 13 +++++ .../utils/date/{date.spec.js => date.spec.ts} | 0 src/shared/utils/date/{date.js => date.ts} | 4 +- src/shared/utils/date/{index.js => index.ts} | 0 .../CalendarWidget/{index.js => index.ts} | 0 .../CalendarWidget/ui/CalendarWidget.spec.tsx | 46 ++++++++++++++++ ...darWidget.ui.jsx => CalendarWidget.ui.tsx} | 20 +++---- .../ui/CalendarWidgetContext.jsx | 41 -------------- .../ui/CalendarWidgetContext.tsx | 54 +++++++++++++++++++ .../DateCell/{index.js => index.ts} | 0 .../{DateCell.spec.jsx => DateCell.spec.tsx} | 2 +- .../DateCell/ui/DateCell.style.module.css | 16 +++++- .../ui/{DateCell.ui.jsx => DateCell.ui.tsx} | 35 ++++++------ .../components/DateRow/{index.js => index.ts} | 0 .../ui/{DateRow.spec.jsx => DateRow.spec.tsx} | 18 ++++--- .../ui/{DateRow.ui.jsx => DateRow.ui.tsx} | 13 +++-- .../DateWrapper/{index.js => index.ts} | 0 ...eWrapper.spec.jsx => DateWrapper.spec.tsx} | 0 ...{DateWrapper.ui.jsx => DateWrapper.ui.tsx} | 0 .../DayOfWeekCell/{index.js => index.ts} | 0 ...ekCell.spec.jsx => DayOfWeekCell.spec.tsx} | 9 ++-- ...OfWeekCell.ui.jsx => DayOfWeekCell.ui.tsx} | 17 +++--- .../DayOfWeekRow/{index.js => index.ts} | 0 .../MonthSelect/ui/MonthSelect.spec.jsx | 12 +++-- .../NextMonthButton/{index.js => index.ts} | 0 ...tton.spec.jsx => NextMonthButton.spec.tsx} | 16 ++++-- ...thButton.ui.jsx => NextMonthButton.ui.tsx} | 18 +++---- .../PrevMonthButton/{index.js => index.ts} | 0 ...tton.spec.jsx => PrevMonthButton.spec.tsx} | 17 ++++-- ...thButton.ui.jsx => PrevMonthButton.ui.tsx} | 18 +++---- .../TodayButton/{index.js => index.ts} | 0 ...ayButton.spec.jsx => TodayButton.spec.tsx} | 10 ++-- ...{TodayButton.ui.jsx => TodayButton.ui.tsx} | 14 ++--- .../YearSelect/{index.js => index.ts} | 0 ...earSelect.spec.jsx => YearSelect.spec.tsx} | 7 ++- .../{YearSelect.ui.jsx => YearSelect.ui.tsx} | 19 ++++--- 49 files changed, 315 insertions(+), 168 deletions(-) rename src/apps/MoneyControllApp/{index.js => index.ts} (100%) rename src/apps/MoneyControllApp/model/providers/RouterProvider/{index.jsx => index.tsx} (100%) rename src/apps/MoneyControllApp/ui/{MoneyControllApp.spec.jsx => MoneyControllApp.spec.tsx} (100%) rename src/apps/MoneyControllApp/ui/{MoneyControllApp.ui.jsx => MoneyControllApp.ui.tsx} (100%) create mode 100644 src/global.d.ts rename src/pages/CalendarPage/{index.js => index.ts} (100%) rename src/pages/CalendarPage/ui/{CalendarPage.ui.jsx => CalendarPage.ui.tsx} (91%) rename src/shared/constants/{date.js => date.ts} (61%) rename src/shared/constants/{index.js => index.ts} (54%) rename src/shared/constants/{locale.js => locale.ts} (81%) rename src/shared/hoc/withProvider/{index.js => index.ts} (100%) rename src/shared/hoc/withProvider/ui/{withProvider.spec.jsx => withProvider.spec.tsx} (79%) delete mode 100644 src/shared/hoc/withProvider/ui/withProvider.ui.jsx create mode 100644 src/shared/hoc/withProvider/ui/withProvider.ui.tsx rename src/shared/utils/date/{date.spec.js => date.spec.ts} (100%) rename src/shared/utils/date/{date.js => date.ts} (69%) rename src/shared/utils/date/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/{index.js => index.ts} (100%) create mode 100644 src/widgets/CalendarWidget/ui/CalendarWidget.spec.tsx rename src/widgets/CalendarWidget/ui/{CalendarWidget.ui.jsx => CalendarWidget.ui.tsx} (63%) delete mode 100644 src/widgets/CalendarWidget/ui/CalendarWidgetContext.jsx create mode 100644 src/widgets/CalendarWidget/ui/CalendarWidgetContext.tsx rename src/widgets/CalendarWidget/ui/components/DateCell/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/DateCell/ui/{DateCell.spec.jsx => DateCell.spec.tsx} (96%) rename src/widgets/CalendarWidget/ui/components/DateCell/ui/{DateCell.ui.jsx => DateCell.ui.tsx} (51%) rename src/widgets/CalendarWidget/ui/components/DateRow/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/DateRow/ui/{DateRow.spec.jsx => DateRow.spec.tsx} (72%) rename src/widgets/CalendarWidget/ui/components/DateRow/ui/{DateRow.ui.jsx => DateRow.ui.tsx} (81%) rename src/widgets/CalendarWidget/ui/components/DateWrapper/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/DateWrapper/ui/{DateWrapper.spec.jsx => DateWrapper.spec.tsx} (100%) rename src/widgets/CalendarWidget/ui/components/DateWrapper/ui/{DateWrapper.ui.jsx => DateWrapper.ui.tsx} (100%) rename src/widgets/CalendarWidget/ui/components/DayOfWeekCell/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/{DayOfWeekCell.spec.jsx => DayOfWeekCell.spec.tsx} (91%) rename src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/{DayOfWeekCell.ui.jsx => DayOfWeekCell.ui.tsx} (56%) rename src/widgets/CalendarWidget/ui/components/DayOfWeekRow/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/NextMonthButton/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/{NextMonthButton.spec.jsx => NextMonthButton.spec.tsx} (59%) rename src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/{NextMonthButton.ui.jsx => NextMonthButton.ui.tsx} (71%) rename src/widgets/CalendarWidget/ui/components/PrevMonthButton/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/PrevMonthButton/ui/{PrevMonthButton.spec.jsx => PrevMonthButton.spec.tsx} (56%) rename src/widgets/CalendarWidget/ui/components/PrevMonthButton/ui/{PrevMonthButton.ui.jsx => PrevMonthButton.ui.tsx} (71%) rename src/widgets/CalendarWidget/ui/components/TodayButton/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/TodayButton/ui/{TodayButton.spec.jsx => TodayButton.spec.tsx} (83%) rename src/widgets/CalendarWidget/ui/components/TodayButton/ui/{TodayButton.ui.jsx => TodayButton.ui.tsx} (75%) rename src/widgets/CalendarWidget/ui/components/YearSelect/{index.js => index.ts} (100%) rename src/widgets/CalendarWidget/ui/components/YearSelect/ui/{YearSelect.spec.jsx => YearSelect.spec.tsx} (88%) rename src/widgets/CalendarWidget/ui/components/YearSelect/ui/{YearSelect.ui.jsx => YearSelect.ui.tsx} (79%) diff --git a/src/apps/MoneyControllApp/index.js b/src/apps/MoneyControllApp/index.ts similarity index 100% rename from src/apps/MoneyControllApp/index.js rename to src/apps/MoneyControllApp/index.ts diff --git a/src/apps/MoneyControllApp/model/providers/RouterProvider/index.jsx b/src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx similarity index 100% rename from src/apps/MoneyControllApp/model/providers/RouterProvider/index.jsx rename to src/apps/MoneyControllApp/model/providers/RouterProvider/index.tsx diff --git a/src/apps/MoneyControllApp/ui/MoneyControllApp.spec.jsx b/src/apps/MoneyControllApp/ui/MoneyControllApp.spec.tsx similarity index 100% rename from src/apps/MoneyControllApp/ui/MoneyControllApp.spec.jsx rename to src/apps/MoneyControllApp/ui/MoneyControllApp.spec.tsx diff --git a/src/apps/MoneyControllApp/ui/MoneyControllApp.ui.jsx b/src/apps/MoneyControllApp/ui/MoneyControllApp.ui.tsx similarity index 100% rename from src/apps/MoneyControllApp/ui/MoneyControllApp.ui.jsx rename to src/apps/MoneyControllApp/ui/MoneyControllApp.ui.tsx diff --git a/src/global.d.ts b/src/global.d.ts new file mode 100644 index 0000000..27a02e8 --- /dev/null +++ b/src/global.d.ts @@ -0,0 +1,5 @@ +/// + +declare module '*.css' { + export default Record; +} diff --git a/src/pages/CalendarPage/index.js b/src/pages/CalendarPage/index.ts similarity index 100% rename from src/pages/CalendarPage/index.js rename to src/pages/CalendarPage/index.ts diff --git a/src/pages/CalendarPage/ui/CalendarPage.ui.jsx b/src/pages/CalendarPage/ui/CalendarPage.ui.tsx similarity index 91% rename from src/pages/CalendarPage/ui/CalendarPage.ui.jsx rename to src/pages/CalendarPage/ui/CalendarPage.ui.tsx index 5e18cfd..9ca240f 100644 --- a/src/pages/CalendarPage/ui/CalendarPage.ui.jsx +++ b/src/pages/CalendarPage/ui/CalendarPage.ui.tsx @@ -13,6 +13,7 @@ const CalendarPage = () => ( locale="en" maxDate={new Date(2027, 2, 15)} minDate={new Date(1996, 9, 15)} + value={new Date(2023, 9, 15)} /> diff --git a/src/shared/constants/date.js b/src/shared/constants/date.ts similarity index 61% rename from src/shared/constants/date.js rename to src/shared/constants/date.ts index 5ae005e..3c23baa 100644 --- a/src/shared/constants/date.js +++ b/src/shared/constants/date.ts @@ -13,6 +13,9 @@ export const MONTHS = { DECEMBER: 11, }; +export type MonthsKeys = keyof typeof MONTHS; +export type MonthsValues = typeof MONTHS[MonthsKeys]; + export const DAYS_IN_WEEK = 7; export const WEEK_DAYS = { @@ -24,3 +27,6 @@ export const WEEK_DAYS = { FRIDAY: 5, SATURDAY: 6, }; + +export type WeekDaysKeys = keyof typeof WEEK_DAYS; +export type WeekDaysValues = typeof WEEK_DAYS[WeekDaysKeys]; diff --git a/src/shared/constants/index.js b/src/shared/constants/index.ts similarity index 54% rename from src/shared/constants/index.js rename to src/shared/constants/index.ts index fdc476c..55361e3 100644 --- a/src/shared/constants/index.js +++ b/src/shared/constants/index.ts @@ -1,2 +1,8 @@ export { DAYS_IN_WEEK, MONTHS, WEEK_DAYS } from './date'; export { MONTHS_LABEL, WEEK_DAYS_LABEL } from './locale'; +export type { + MonthsKeys, + MonthsValues, + WeekDaysKeys, + WeekDaysValues, +} from './date'; diff --git a/src/shared/constants/locale.js b/src/shared/constants/locale.ts similarity index 81% rename from src/shared/constants/locale.js rename to src/shared/constants/locale.ts index 10d3edc..5c799e9 100644 --- a/src/shared/constants/locale.js +++ b/src/shared/constants/locale.ts @@ -1,6 +1,12 @@ -import { MONTHS, WEEK_DAYS } from './date'; +import { MONTHS, WEEK_DAYS } from 'shared/constants/date'; +import type { MonthsValues, WeekDaysValues } from 'shared/constants/date'; -export const MONTHS_LABEL = { +type Locale = { + ru: T; + en: T; +}; + +export const MONTHS_LABEL: Record = { [MONTHS.JANUARY]: { ru: 'Январь', en: 'January', @@ -51,7 +57,14 @@ export const MONTHS_LABEL = { }, }; -export const WEEK_DAYS_LABEL = { +type WeekDaysLabel = { + full: string; + short: string; +}; + +type WeekDaysLabelLocale = Locale; + +export const WEEK_DAYS_LABEL: Record = { [WEEK_DAYS.SUNDAY]: { ru: { full: 'Воскресенье', diff --git a/src/shared/hoc/withProvider/index.js b/src/shared/hoc/withProvider/index.ts similarity index 100% rename from src/shared/hoc/withProvider/index.js rename to src/shared/hoc/withProvider/index.ts diff --git a/src/shared/hoc/withProvider/ui/withProvider.spec.jsx b/src/shared/hoc/withProvider/ui/withProvider.spec.tsx similarity index 79% rename from src/shared/hoc/withProvider/ui/withProvider.spec.jsx rename to src/shared/hoc/withProvider/ui/withProvider.spec.tsx index 65b10c6..3bff4e5 100644 --- a/src/shared/hoc/withProvider/ui/withProvider.spec.jsx +++ b/src/shared/hoc/withProvider/ui/withProvider.spec.tsx @@ -2,13 +2,19 @@ import { fireEvent, render, screen } from '@testing-library/react'; import PropTypes from 'prop-types'; import React, { useContext, useMemo, useState } from 'react'; -import { withProvider } from 'shared/hoc/withProvider/index'; +import withProvider from './withProvider.ui'; + +import type { PropsWithChildren } from 'react'; describe('Test withProvider', () => { const renderCounter = () => { - const TestContext = React.createContext({}); + type TestContextValue = { + testState: number; + setTestState: React.Dispatch>; + }; + const TestContext = React.createContext({} as TestContextValue); - const TestProvider = (props) => { + const TestProvider = (props: PropsWithChildren) => { const { children } = props; const [testState, setTestState] = useState(100); @@ -74,7 +80,7 @@ describe('Test withProvider', () => { renderCounter(); const counterElem = screen.getByTestId('counter'); - expect(counterElem).toHaveTextContent(100); + expect(counterElem).toHaveTextContent('100'); }); test('change state - increment', () => { @@ -84,7 +90,7 @@ describe('Test withProvider', () => { fireEvent.click(plusBtn); const counterElem = screen.getByTestId('counter'); - expect(counterElem).toHaveTextContent(101); + expect(counterElem).toHaveTextContent('101'); }); test('change state - decrement', () => { @@ -94,6 +100,6 @@ describe('Test withProvider', () => { fireEvent.click(minusBtn); const counterElem = screen.getByTestId('counter'); - expect(counterElem).toHaveTextContent(99); + expect(counterElem).toHaveTextContent('99'); }); }); diff --git a/src/shared/hoc/withProvider/ui/withProvider.ui.jsx b/src/shared/hoc/withProvider/ui/withProvider.ui.jsx deleted file mode 100644 index 3f3b48f..0000000 --- a/src/shared/hoc/withProvider/ui/withProvider.ui.jsx +++ /dev/null @@ -1,9 +0,0 @@ -// todo fix eslint -// eslint-disable-next-line react/function-component-definition -const withProvider = (Provider) => (Component) => (...params) => ( - - - -); - -export default withProvider; diff --git a/src/shared/hoc/withProvider/ui/withProvider.ui.tsx b/src/shared/hoc/withProvider/ui/withProvider.ui.tsx new file mode 100644 index 0000000..d4385c7 --- /dev/null +++ b/src/shared/hoc/withProvider/ui/withProvider.ui.tsx @@ -0,0 +1,13 @@ +// todo fix eslint + +import type { FC, PropsWithChildren } from 'react'; + +// eslint-disable-next-line react/function-component-definition +const withProvider = (Provider: FC) => (Component: FC) => (...params: T[]) => ( + + {/* @ts-ignore */} + + +); + +export default withProvider; diff --git a/src/shared/utils/date/date.spec.js b/src/shared/utils/date/date.spec.ts similarity index 100% rename from src/shared/utils/date/date.spec.js rename to src/shared/utils/date/date.spec.ts diff --git a/src/shared/utils/date/date.js b/src/shared/utils/date/date.ts similarity index 69% rename from src/shared/utils/date/date.js rename to src/shared/utils/date/date.ts index 0ed9892..6bcb1c9 100644 --- a/src/shared/utils/date/date.js +++ b/src/shared/utils/date/date.ts @@ -1,11 +1,11 @@ -export const firstDayOfMonthDate = (date) => { +export const firstDayOfMonthDate = (date: Date) => { const monthIndex = date.getMonth(); const year = date.getFullYear(); return new Date(year, monthIndex, 1); }; -export const lastDayOfMonthDate = (date) => { +export const lastDayOfMonthDate = (date: Date) => { const monthIndex = date.getMonth(); const year = date.getFullYear(); diff --git a/src/shared/utils/date/index.js b/src/shared/utils/date/index.ts similarity index 100% rename from src/shared/utils/date/index.js rename to src/shared/utils/date/index.ts diff --git a/src/widgets/CalendarWidget/index.js b/src/widgets/CalendarWidget/index.ts similarity index 100% rename from src/widgets/CalendarWidget/index.js rename to src/widgets/CalendarWidget/index.ts diff --git a/src/widgets/CalendarWidget/ui/CalendarWidget.spec.tsx b/src/widgets/CalendarWidget/ui/CalendarWidget.spec.tsx new file mode 100644 index 0000000..8a42c54 --- /dev/null +++ b/src/widgets/CalendarWidget/ui/CalendarWidget.spec.tsx @@ -0,0 +1,46 @@ +import { render, screen } from '@testing-library/react'; + +import CalendarWidget from './CalendarWidget.ui'; + +import type { CalendarWidgetProps } from './CalendarWidget.ui'; + +describe('Test CalendarWidget', () => { + const setup = (props?: CalendarWidgetProps) => { + render(); + }; + + test('Basic render', () => { + setup(); + + const calendarWidgetElem = screen.getByTestId('calendar-widget'); + expect(calendarWidgetElem).toBeInTheDocument(); + expect(calendarWidgetElem).toBeVisible(); + }); + + test('Render components', () => { + setup(); + + const calendarWidgetElem = screen.getByTestId('calendar-widget'); + const headerRowElem = screen.getByTestId('header-row'); + const dayOfWeekRowElem = screen.getByTestId('day-of-week-row'); + const dateWrapperElem = screen.getByTestId('date-wrapper'); + + expect(calendarWidgetElem).toContainElement(headerRowElem); + expect(calendarWidgetElem).toContainElement(dayOfWeekRowElem); + expect(calendarWidgetElem).toContainElement(dateWrapperElem); + }); + + // todo + test('Render with value', () => { + setup({ value: new Date(2023, 1, 15) }); + + const calendarWidgetElem = screen.getByTestId('calendar-widget'); + const headerRowElem = screen.getByTestId('header-row'); + const dayOfWeekRowElem = screen.getByTestId('day-of-week-row'); + const dateWrapperElem = screen.getByTestId('date-wrapper'); + + expect(calendarWidgetElem).toContainElement(headerRowElem); + expect(calendarWidgetElem).toContainElement(dayOfWeekRowElem); + expect(calendarWidgetElem).toContainElement(dateWrapperElem); + }); +}); diff --git a/src/widgets/CalendarWidget/ui/CalendarWidget.ui.jsx b/src/widgets/CalendarWidget/ui/CalendarWidget.ui.tsx similarity index 63% rename from src/widgets/CalendarWidget/ui/CalendarWidget.ui.jsx rename to src/widgets/CalendarWidget/ui/CalendarWidget.ui.tsx index 92fa43a..dfe53c3 100644 --- a/src/widgets/CalendarWidget/ui/CalendarWidget.ui.jsx +++ b/src/widgets/CalendarWidget/ui/CalendarWidget.ui.tsx @@ -1,14 +1,20 @@ -import PropTypes from 'prop-types'; - import classes from './CalendarWidget.module.css'; import { CalendarWidgetProvider } from './CalendarWidgetContext'; import { DateWrapper } from './components/DateWrapper'; import { DayOfWeekRow } from './components/DayOfWeekRow'; import { HeaderRow } from './components/HeaderRow'; -const CalendarWidget = (props) => ( +import type { FC } from 'react'; + +export type CalendarWidgetProps = { + maxDate?: Date; + minDate?: Date; + value?: Date; + locale?: 'en' | 'ru'; +}; +const CalendarWidget: FC = (props) => ( -
+
@@ -18,10 +24,4 @@ const CalendarWidget = (props) => ( ); -CalendarWidget.propTypes = { - maxDate: PropTypes.instanceOf(Date), - minDate: PropTypes.instanceOf(Date), - value: PropTypes.instanceOf(Date), -}; - export default CalendarWidget; diff --git a/src/widgets/CalendarWidget/ui/CalendarWidgetContext.jsx b/src/widgets/CalendarWidget/ui/CalendarWidgetContext.jsx deleted file mode 100644 index 92ae75c..0000000 --- a/src/widgets/CalendarWidget/ui/CalendarWidgetContext.jsx +++ /dev/null @@ -1,41 +0,0 @@ -import PropTypes from 'prop-types'; -import { createContext, useMemo, useState } from 'react'; - -export const CalendarWidgetContext = createContext({}); - -export const CalendarWidgetProvider = (props) => { - const { - children, - maxDate = new Date(2030, 0, 1), - minDate = new Date(1990, 0, 1), - locale = 'ru', - ...restProps - } = props; - - const [targetDate, setTargetDate] = useState(new Date()); - - const contextValue = useMemo(() => ({ - targetYear: targetDate.getFullYear(), - targetMonthIndex: targetDate.getMonth(), - targetDate, - setTargetDate, - minDate, - maxDate, - locale, - ...restProps, - }), [maxDate, minDate, targetDate, locale, restProps]); - - return ( - - {children} - - ); -}; - -CalendarWidgetProvider.propTypes = { - children: PropTypes.node.isRequired, - - maxDate: PropTypes.instanceOf(Date), - minDate: PropTypes.instanceOf(Date), - locale: PropTypes.oneOf(['ru', 'en']), -}; diff --git a/src/widgets/CalendarWidget/ui/CalendarWidgetContext.tsx b/src/widgets/CalendarWidget/ui/CalendarWidgetContext.tsx new file mode 100644 index 0000000..3d6e163 --- /dev/null +++ b/src/widgets/CalendarWidget/ui/CalendarWidgetContext.tsx @@ -0,0 +1,54 @@ +import PropTypes from 'prop-types'; +import React, { createContext, useMemo, useState } from 'react'; + +import type { CalendarWidgetProps } from './CalendarWidget.ui'; +import type { FC, PropsWithChildren } from 'react'; + +type CalendarWidgetContextValue = Required & { + targetYear: number; + targetMonthIndex: number; + targetDate: Date; + setTargetDate: React.Dispatch>; +}; +export const CalendarWidgetContext = createContext({} as CalendarWidgetContextValue); + +export type CalendarWidgetProviderProps = PropsWithChildren; + +export const CalendarWidgetProvider: FC = (props) => { + const { + children, + maxDate = new Date(2030, 0, 1), + minDate = new Date(1990, 0, 1), + locale = 'ru', + value = new Date(), + ...restProps + } = props; + + const [targetDate, setTargetDate] = useState(value); + + const contextValue = useMemo(() => ({ + targetYear: targetDate.getFullYear(), + targetMonthIndex: targetDate.getMonth(), + targetDate, + setTargetDate, + minDate, + maxDate, + locale, + value, + ...restProps, + }), [maxDate, minDate, targetDate, locale, restProps, value]); + + return ( + + {children} + + ); +}; + +CalendarWidgetProvider.propTypes = { + children: PropTypes.node.isRequired, + + maxDate: PropTypes.instanceOf(Date), + minDate: PropTypes.instanceOf(Date), + locale: PropTypes.oneOf(['ru', 'en']), +}; diff --git a/src/widgets/CalendarWidget/ui/components/DateCell/index.js b/src/widgets/CalendarWidget/ui/components/DateCell/index.ts similarity index 100% rename from src/widgets/CalendarWidget/ui/components/DateCell/index.js rename to src/widgets/CalendarWidget/ui/components/DateCell/index.ts diff --git a/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.jsx b/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.tsx similarity index 96% rename from src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.jsx rename to src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.tsx index ac52c45..8819c30 100644 --- a/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.jsx +++ b/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.spec.tsx @@ -3,7 +3,7 @@ import { render, screen } from '@testing-library/react'; import DateCell from './DateCell.ui'; describe('Base Render', () => { - const setup = (date) => { + const setup = (date: Date) => { render(); }; diff --git a/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.style.module.css b/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.style.module.css index 33002eb..55246c4 100644 --- a/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.style.module.css +++ b/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.style.module.css @@ -16,13 +16,25 @@ border-right: 1px solid black; } - &.today { + .today { color: red; font-size: 1.2em; font-weight: bold; } - &.outMothRange { + .outMothRange { color: darkgrey; } + + .valueDate { + color: gold; + background: red; + border-radius: 50%; + padding: 5px; + height: 1.2em; + width: 1.2em; + display: inline-flex; + justify-content: center; + align-items: center; + } } diff --git a/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.ui.jsx b/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.ui.tsx similarity index 51% rename from src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.ui.jsx rename to src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.ui.tsx index 26d5b2a..3fd2048 100644 --- a/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.ui.jsx +++ b/src/widgets/CalendarWidget/ui/components/DateCell/ui/DateCell.ui.tsx @@ -1,44 +1,49 @@ import classnames from 'classnames'; -import PropTypes from 'prop-types'; import { useContext } from 'react'; import { CalendarWidgetContext } from '../../../CalendarWidgetContext'; import classes from './DateCell.style.module.css'; -const DateCell = (props) => { +import type { FC } from 'react'; + +type DateCellProps = { + date: Date; +}; +const DateCell: FC = (props) => { const { date, } = props; const format = 'en-En'; - const { targetMonthIndex } = useContext(CalendarWidgetContext); + const { targetMonthIndex, value } = useContext(CalendarWidgetContext); const todayDate = new Date(); const dataDate = new Intl.DateTimeFormat(format).format(date); const dataToday = new Intl.DateTimeFormat(format).format(todayDate); + const dataValue = new Intl.DateTimeFormat(format).format(value); const isOutMonthRange = date.getMonth() !== targetMonthIndex; return (
- {date.getDate()} + + {date.getDate()} +
); }; -DateCell.propTypes = { - date: PropTypes.instanceOf(Date).isRequired, -}; - export default DateCell; diff --git a/src/widgets/CalendarWidget/ui/components/DateRow/index.js b/src/widgets/CalendarWidget/ui/components/DateRow/index.ts similarity index 100% rename from src/widgets/CalendarWidget/ui/components/DateRow/index.js rename to src/widgets/CalendarWidget/ui/components/DateRow/index.ts diff --git a/src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.spec.jsx b/src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.spec.tsx similarity index 72% rename from src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.spec.jsx rename to src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.spec.tsx index 7371937..ef8d83a 100644 --- a/src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.spec.jsx +++ b/src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.spec.tsx @@ -2,8 +2,10 @@ import { render, screen } from '@testing-library/react'; import DateRow from './DateRow.ui'; +import type { DateRowType } from './DateRow.ui'; + describe('Test Date Row', () => { - const setup = (cells) => { + const setup = (cells: DateRowType['cells']) => { render(); }; @@ -53,13 +55,13 @@ describe('Test Date Row', () => { setupWeek(); const dateCellElems = screen.getAllByTestId('date-cell'); - expect(dateCellElems[0]).toHaveTextContent(15); - expect(dateCellElems[1]).toHaveTextContent(16); - expect(dateCellElems[2]).toHaveTextContent(17); - expect(dateCellElems[3]).toHaveTextContent(18); - expect(dateCellElems[4]).toHaveTextContent(19); - expect(dateCellElems[5]).toHaveTextContent(20); - expect(dateCellElems[6]).toHaveTextContent(21); + expect(dateCellElems[0]).toHaveTextContent('15'); + expect(dateCellElems[1]).toHaveTextContent('16'); + expect(dateCellElems[2]).toHaveTextContent('17'); + expect(dateCellElems[3]).toHaveTextContent('18'); + expect(dateCellElems[4]).toHaveTextContent('19'); + expect(dateCellElems[5]).toHaveTextContent('20'); + expect(dateCellElems[6]).toHaveTextContent('21'); }); }); }); diff --git a/src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.ui.jsx b/src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.ui.tsx similarity index 81% rename from src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.ui.jsx rename to src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.ui.tsx index 7c6acc2..9f44e98 100644 --- a/src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.ui.jsx +++ b/src/widgets/CalendarWidget/ui/components/DateRow/ui/DateRow.ui.tsx @@ -1,10 +1,13 @@ -import PropTypes from 'prop-types'; - import { DateCell } from '../../DateCell'; import classes from './DateRow.style.module.css'; -const DateRow = (props) => { +import type { FC } from 'react'; + +export type DateRowType = { + cells: Date[]; +}; +const DateRow: FC = (props) => { const { cells, } = props; @@ -28,8 +31,4 @@ const DateRow = (props) => { ); }; -DateRow.propTypes = { - cells: PropTypes.arrayOf(PropTypes.instanceOf(Date)), -}; - export default DateRow; diff --git a/src/widgets/CalendarWidget/ui/components/DateWrapper/index.js b/src/widgets/CalendarWidget/ui/components/DateWrapper/index.ts similarity index 100% rename from src/widgets/CalendarWidget/ui/components/DateWrapper/index.js rename to src/widgets/CalendarWidget/ui/components/DateWrapper/index.ts diff --git a/src/widgets/CalendarWidget/ui/components/DateWrapper/ui/DateWrapper.spec.jsx b/src/widgets/CalendarWidget/ui/components/DateWrapper/ui/DateWrapper.spec.tsx similarity index 100% rename from src/widgets/CalendarWidget/ui/components/DateWrapper/ui/DateWrapper.spec.jsx rename to src/widgets/CalendarWidget/ui/components/DateWrapper/ui/DateWrapper.spec.tsx diff --git a/src/widgets/CalendarWidget/ui/components/DateWrapper/ui/DateWrapper.ui.jsx b/src/widgets/CalendarWidget/ui/components/DateWrapper/ui/DateWrapper.ui.tsx similarity index 100% rename from src/widgets/CalendarWidget/ui/components/DateWrapper/ui/DateWrapper.ui.jsx rename to src/widgets/CalendarWidget/ui/components/DateWrapper/ui/DateWrapper.ui.tsx diff --git a/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/index.js b/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/index.ts similarity index 100% rename from src/widgets/CalendarWidget/ui/components/DayOfWeekCell/index.js rename to src/widgets/CalendarWidget/ui/components/DayOfWeekCell/index.ts diff --git a/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.spec.jsx b/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.spec.tsx similarity index 91% rename from src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.spec.jsx rename to src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.spec.tsx index 357d0df..00cb8d8 100644 --- a/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.spec.jsx +++ b/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.spec.tsx @@ -7,14 +7,17 @@ import { CalendarWidgetProvider } from '../../../CalendarWidgetContext'; import DayOfWeekCell from './DayOfWeekCell.ui'; +import type { DayOfWeekCellProps } from './DayOfWeekCell.ui'; +import type { CalendarWidgetProviderProps } from '../../../CalendarWidgetContext'; + describe('Test DayOfWeekCell', () => { - const setup = (day, locale) => { + const setup = (day: DayOfWeekCellProps['day'], locale: CalendarWidgetProviderProps['locale']) => { const DayOfWeekCellComponent = () => ( ); - const Provider = (props) => ( - + const Provider = (props: CalendarWidgetProviderProps) => ( + ); const DayOfWeekCellWithProvider = withProvider(Provider)(DayOfWeekCellComponent); diff --git a/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.ui.jsx b/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.ui.tsx similarity index 56% rename from src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.ui.jsx rename to src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.ui.tsx index 0dd4836..220c38b 100644 --- a/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.ui.jsx +++ b/src/widgets/CalendarWidget/ui/components/DayOfWeekCell/ui/DayOfWeekCell.ui.tsx @@ -1,16 +1,21 @@ -import PropTypes from 'prop-types'; import { useContext } from 'react'; -import { WEEK_DAYS_LABEL, WEEK_DAYS } from 'shared/constants'; +import type { WeekDaysValues } from 'shared/constants'; +import { WEEK_DAYS_LABEL } from 'shared/constants'; import { CalendarWidgetContext } from '../../../CalendarWidgetContext'; import classes from './DayOfWeekCell.style.module.css'; -const DayOfWeekCell = (props) => { +import type { FC } from 'react'; + +export type DayOfWeekCellProps = { + day: WeekDaysValues; +}; +const DayOfWeekCell: FC = (props) => { const { day } = props; const { locale } = useContext(CalendarWidgetContext); - const content = WEEK_DAYS_LABEL[day][locale]?.short; + const content = WEEK_DAYS_LABEL[day]?.[locale].short; return ( @@ -20,8 +25,4 @@ const DayOfWeekCell = (props) => { ); }; -DayOfWeekCell.propTypes = { - day: PropTypes.oneOf(Object.values(WEEK_DAYS)).isRequired, -}; - export default DayOfWeekCell; diff --git a/src/widgets/CalendarWidget/ui/components/DayOfWeekRow/index.js b/src/widgets/CalendarWidget/ui/components/DayOfWeekRow/index.ts similarity index 100% rename from src/widgets/CalendarWidget/ui/components/DayOfWeekRow/index.js rename to src/widgets/CalendarWidget/ui/components/DayOfWeekRow/index.ts diff --git a/src/widgets/CalendarWidget/ui/components/MonthSelect/ui/MonthSelect.spec.jsx b/src/widgets/CalendarWidget/ui/components/MonthSelect/ui/MonthSelect.spec.jsx index 238745c..e9bdaca 100644 --- a/src/widgets/CalendarWidget/ui/components/MonthSelect/ui/MonthSelect.spec.jsx +++ b/src/widgets/CalendarWidget/ui/components/MonthSelect/ui/MonthSelect.spec.jsx @@ -15,11 +15,15 @@ describe('Test MonthSelect', () => { user = userEvent.setup(); }); - const setup = (props) => { + const setup = (props, providerProps) => { const MonthSelectComponent = () => ( ); - const MonthSelectWithProvider = withProvider(CalendarWidgetProvider)(MonthSelectComponent); + + const Provider = (params) => ( + + ); + const MonthSelectWithProvider = withProvider(Provider)(MonthSelectComponent); render(); }; @@ -40,13 +44,13 @@ describe('Test MonthSelect', () => { test('onChange handler', async () => { const onChange = jest.fn(); - setup({ onChange }); + setup({ onChange }, { value: new Date(2020, 9, 15) }); const monthSelectElem = screen.getByTestId('month-select'); await user.selectOptions(monthSelectElem, String(MONTHS.JULY)); expect(onChange).toHaveBeenCalled(); - const newDate = new Date(2024, 6); + const newDate = new Date(2020, 6); expect(onChange).toHaveBeenCalledWith(newDate); }); }); diff --git a/src/widgets/CalendarWidget/ui/components/NextMonthButton/index.js b/src/widgets/CalendarWidget/ui/components/NextMonthButton/index.ts similarity index 100% rename from src/widgets/CalendarWidget/ui/components/NextMonthButton/index.js rename to src/widgets/CalendarWidget/ui/components/NextMonthButton/index.ts diff --git a/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.jsx b/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.tsx similarity index 59% rename from src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.jsx rename to src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.tsx index e8266d6..6e9ad7f 100644 --- a/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.jsx +++ b/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.spec.tsx @@ -7,18 +7,25 @@ import { CalendarWidgetProvider } from '../../../CalendarWidgetContext'; import NextMonthButton from './NextMonthButton.ui'; +import type { NextMonthButtonProps } from './NextMonthButton.ui'; +import type { CalendarWidgetProviderProps } from '../../../CalendarWidgetContext'; +import type { UserEvent } from '@testing-library/user-event'; + describe('Test NextMonthButton', () => { - let user; + let user: UserEvent; beforeEach(() => { user = userEvent.setup(); }); - const setup = (props) => { + const setup = (props?: NextMonthButtonProps, providerProps?: CalendarWidgetProviderProps) => { const NextMonthButtonComponent = () => ( ); - const NextMonthButtonWithProvider = withProvider(CalendarWidgetProvider)(NextMonthButtonComponent); + const Provider = (params: CalendarWidgetProviderProps) => ( + + ); + const NextMonthButtonWithProvider = withProvider(Provider)(NextMonthButtonComponent); render(); }; @@ -33,11 +40,12 @@ describe('Test NextMonthButton', () => { test('onClick handler', async () => { const onClick = jest.fn(); - setup({ onClick }); + setup({ onClick }, { value: new Date(2020, 9, 15) }); const nextMontButtonElem = screen.getByTestId('next-month-button'); await user.click(nextMontButtonElem); expect(onClick).toHaveBeenCalled(); + expect(onClick).toHaveBeenCalledWith(new Date(2020, 10, 1)); }); }); diff --git a/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.ui.jsx b/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.ui.tsx similarity index 71% rename from src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.ui.jsx rename to src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.ui.tsx index b7001c7..b5d0c07 100644 --- a/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.ui.jsx +++ b/src/widgets/CalendarWidget/ui/components/NextMonthButton/ui/NextMonthButton.ui.tsx @@ -1,9 +1,15 @@ -import PropTypes from 'prop-types'; import { useContext } from 'react'; import { CalendarWidgetContext } from '../../../CalendarWidgetContext'; -const NextMonthButton = (props) => { +import type { ReactNode, FC } from 'react'; + +export type NextMonthButtonProps = { + children?: ReactNode; + onClick?: (newDate: Date) => void; + disabled?: boolean; +}; +const NextMonthButton: FC = (props) => { const { children = 'next', disabled, @@ -27,7 +33,7 @@ const NextMonthButton = (props) => { return (