From 0d66f3c4f6a3fefd6c1f11de206cddbb25c0f403 Mon Sep 17 00:00:00 2001 From: Dm1tr1y147 Date: Sat, 31 Oct 2020 22:50:59 +0500 Subject: [PATCH] Massive functional upgrade: separated localization, full day viewer, month switch, first npm publish, code refactors --- .prettierrc | 4 ++ example/src/App.tsx | 15 +++-- example/src/events.json | 33 ++++++++++- example/src/locale.json | 25 ++++++++ example/yarn.lock | 2 +- src/CalendarInContext.tsx | 73 ++++-------------------- src/Day.tsx | 48 ---------------- src/context.tsx | 47 --------------- src/context/calendar.tsx | 74 ++++++++++++++++++++++++ src/context/locale.tsx | 32 +++++++++++ src/context/types.ts | 59 +++++++++++++++++++ src/hooks.ts | 23 ++++++++ src/index.tsx | 20 +++++-- src/types.ts | 57 +++++++++++-------- src/utils.ts | 107 +++++++++++++++++++++++++++++++--- src/views/Day.tsx | 77 +++++++++++++++++++++++++ src/views/DayOfMonth.tsx | 79 +++++++++++++++++++++++++ src/views/Month.tsx | 61 ++++++++++++++++++++ src/views/MonthHeader.tsx | 52 +++++++++++++++++ src/views/index.ts | 4 ++ src/views/styles.ts | 117 ++++++++++++++++++++++++++++++++++++++ src/views/types.ts | 9 +++ 22 files changed, 817 insertions(+), 201 deletions(-) create mode 100644 .prettierrc create mode 100644 example/src/locale.json delete mode 100644 src/Day.tsx delete mode 100644 src/context.tsx create mode 100644 src/context/calendar.tsx create mode 100644 src/context/locale.tsx create mode 100644 src/context/types.ts create mode 100644 src/hooks.ts create mode 100644 src/views/Day.tsx create mode 100644 src/views/DayOfMonth.tsx create mode 100644 src/views/Month.tsx create mode 100644 src/views/MonthHeader.tsx create mode 100644 src/views/index.ts create mode 100644 src/views/styles.ts create mode 100644 src/views/types.ts diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..b2095be --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "semi": false, + "singleQuote": true +} diff --git a/example/src/App.tsx b/example/src/App.tsx index 64c2e79..795038f 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -1,14 +1,19 @@ -import React from "react"; -import Calendar from "react-eventful-calendar"; +import React from 'react' +import Calendar, { Viewers } from 'react-eventful-calendar' import events from './events.json' +import locale from './locale.json' function App() { return (
- +
- ); + ) } -export default App; +export default App diff --git a/example/src/events.json b/example/src/events.json index 9f5f8e0..ab5c24e 100644 --- a/example/src/events.json +++ b/example/src/events.json @@ -2,7 +2,36 @@ { "id": 1, "title": "Test", - "startDate": "Wed Oct 28 2020 17:00:00 GMT+0500 (Yekaterinburg Standard Time)", - "endDate": "Wed Oct 28 2020 20:00:00 GMT+0500 (Yekaterinburg Standard Time)" + "startDate": "Wed Oct 22 2020 17:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "endDate": "Wed Oct 22 2020 20:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "color": "#e57373" + }, + { + "id": 2, + "title": "AnotherTest", + "startDate": "Wed Oct 22 2020 17:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "endDate": "Wed Oct 22 2020 20:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "color": "#64b5f6" + }, + { + "id": 3, + "title": "And finally: third test", + "startDate": "Wed Oct 22 2020 17:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "endDate": "Wed Oct 22 2020 20:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "color": "#81c784" + }, + { + "id": 666, + "title": "Halloween", + "startDate": "Wed Oct 31 2020 00:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "endDate": "Wed Nov 1 2020 00:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "color": "#ffb74d" + }, + { + "id": 4, + "title": "Watching film", + "startDate": "Wed Oct 31 2020 23:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "endDate": "Wed Nov 1 2020 01:00:00 GMT+0500 (Yekaterinburg Standard Time)", + "color": "#ffb74d" } ] diff --git a/example/src/locale.json b/example/src/locale.json new file mode 100644 index 0000000..72ed2f3 --- /dev/null +++ b/example/src/locale.json @@ -0,0 +1,25 @@ +{ + "monthNames": [ + "январь", + "февраль", + "март", + "апрель", + "май", + "июнь", + "июль", + "август", + "сентябрь", + "октябрь", + "ноябрь", + "декабрь" + ], + "weekdaysNames": [ + "понедельник", + "вторник", + "среда", + "четверг", + "пятница", + "субота", + "воскресенье" + ] +} diff --git a/example/yarn.lock b/example/yarn.lock index c455357..1f0fa80 100644 --- a/example/yarn.lock +++ b/example/yarn.lock @@ -8847,7 +8847,7 @@ react-error-overlay@^6.0.8: resolved "https://registry.yarnpkg.com/react-error-overlay/-/react-error-overlay-6.0.8.tgz#474ed11d04fc6bda3af643447d85e9127ed6b5de" integrity sha512-HvPuUQnLp5H7TouGq3kzBeioJmXms1wHy9EGjz2OURWBp4qZO6AfGEcnxts1D/CbwPLRAgTMPCEgYhA3sEM4vw== -react-eventful-calendar@../.: +react-eventful-calendar@../: version "1.0.0" react-is@^16.8.1: diff --git a/src/CalendarInContext.tsx b/src/CalendarInContext.tsx index e5ab2be..760c3ae 100644 --- a/src/CalendarInContext.tsx +++ b/src/CalendarInContext.tsx @@ -1,69 +1,18 @@ -import React, { useContext, useEffect, useState } from 'react' +import React from 'react' -import Day from './Day' -import { CalendarContext } from './context' -import { DayT, ICalendarProps } from './types' +import { useCalendarContext } from './hooks' +import { Viewers } from './types' +import { DayView, MonthView } from './views' +import styles from './views/styles' -const CalendarInContext: React.FC = ({ eventList }) => { - const context = useContext(CalendarContext) - - const { month } = context.state - - const [monthDaysState, setMonthDaysState] = useState([]) - - useEffect(() => { - const daysNumbersArray = [ - Array.from( - Array(month.firstDayOfWeek - 1 > 0 ? month.firstDayOfWeek - 1 : 0) - ).map( - (_, index) => - month.previousMonthLength - month.firstDayOfWeek + index + 2 - ), - Array.from(Array(month.numberOfDays)).map((_, index) => index + 1), - Array.from(Array(7 - month.lastDayOfWeek)).map((_, index) => index + 1), - ] - - setMonthDaysState( - daysNumbersArray.flatMap((month, index) => - month.map((dayNumber) => ({ - number: dayNumber, - events: eventList.filter((event) => { - if (index != 1) return false - - const eventDate = new Date(event.startDate) - - return ( - eventDate.getDate() == dayNumber && - eventDate.getMonth() == context.state.month.number - ) - }), - })) - ) - ) - }, [context.state]) +const CalendarInContext: React.FC = () => { + const { state: calendar } = useCalendarContext() + const { currentViewer } = calendar return ( -
- {monthDaysState.map((day, dayIndex) => ( - month.numberOfDays + month.firstDayOfWeek - 2 - } - /> - ))} +
+ {currentViewer == Viewers.MonthViewer && } + {currentViewer == Viewers.DayViewer && }
) } diff --git a/src/Day.tsx b/src/Day.tsx deleted file mode 100644 index 164dfc0..0000000 --- a/src/Day.tsx +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react' - -import { IDayProps } from './types' - -const Day: React.FC = ({ dayNumber, events, shaded }) => { - return ( -
-
- {dayNumber} -
-
    - {events.map((event, key) => ( -
  • - {event.title} -
  • - ))} -
-
-
- ) -} - -export default Day diff --git a/src/context.tsx b/src/context.tsx deleted file mode 100644 index 2d30843..0000000 --- a/src/context.tsx +++ /dev/null @@ -1,47 +0,0 @@ -import React, { createContext, useEffect, useState } from 'react' - -import { CalendarContextStateT, CalendarContextT } from './types' -import { getCurrentMonth } from './utils' - -const initialCalendarContextState: CalendarContextStateT = { - month: { - number: 1, - firstDayOfWeek: 1, - lastDayOfWeek: 1, - numberOfDays: 1, - previousMonthLength: 1, - }, - year: 1, - day: 1, -} - -const CalendarContext = createContext({ - state: initialCalendarContextState, -}) - -const CalendarProvider: React.FC = ({ children }) => { - const [state, setState] = useState( - initialCalendarContextState - ) - - const [now] = useState(new Date()) - - useEffect( - () => - setState((prev) => ({ - ...prev, - month: getCurrentMonth(now), - year: now.getFullYear(), - day: now.getDate(), - })), - [] - ) - - return ( - - {children} - - ) -} - -export { CalendarContext, CalendarProvider } diff --git a/src/context/calendar.tsx b/src/context/calendar.tsx new file mode 100644 index 0000000..97eeb9b --- /dev/null +++ b/src/context/calendar.tsx @@ -0,0 +1,74 @@ +import React, { createContext, useEffect, useMemo, useState } from 'react' + +import { + CalendarStateT, + CalendarContextT, + ICalendarProviderProps, +} from './types' +import { Viewers } from '../types' +import { getMonth } from '../utils' + +const initialCalendarContextState: CalendarStateT = { + month: { + number: 1, + firstDayOfWeek: 0, + lastDayOfWeek: 1, + numberOfDays: 1, + previousMonthLength: 1, + }, + year: 1, + day: { + number: 1, + }, + today: { + day: 1, + month: 1, + year: 1, + }, + eventList: [], + currentViewer: Viewers.MonthViewer, +} + +const CalendarContext = createContext(null) + +const CalendarProvider: React.FC = ({ + children, + eventList, + initialViewer, +}) => { + const [state, setState] = useState( + initialCalendarContextState + ) + + const [now] = useState(new Date()) + + useEffect( + () => + setState((prev) => ({ + ...prev, + year: now.getFullYear(), + month: getMonth(now), + day: { + number: now.getDate(), + }, + today: { + day: now.getDate(), + month: now.getMonth(), + year: now.getFullYear(), + }, + currentViewer: initialViewer, + eventList, + })), + [] + ) + + const value = useMemo(() => ({ state, setState }), [state]) + + return ( + + {children} + + ) +} + +export { CalendarContext, CalendarProvider } diff --git a/src/context/locale.tsx b/src/context/locale.tsx new file mode 100644 index 0000000..2c161e8 --- /dev/null +++ b/src/context/locale.tsx @@ -0,0 +1,32 @@ +import React, { createContext, useEffect, useMemo, useState } from 'react' +import { ILocaleProviderProps, LocaleContextT, LocaleStateT } from './types' + +const initialLocaleState: LocaleStateT = { + monthNames: [], + weekdaysNames: [], +} + +const LocaleContext = createContext(null) + +const LocaleProvider: React.FC = ({ + children, + monthList, + weekList, +}) => { + const [state, setState] = useState(initialLocaleState) + + useEffect(() => { + setState({ + monthNames: monthList, + weekdaysNames: weekList, + }) + }, [monthList, weekList]) + + const value = useMemo(() => ({ state, setState }), [state]) + + return ( + {children} + ) +} + +export { LocaleContext, LocaleProvider } diff --git a/src/context/types.ts b/src/context/types.ts new file mode 100644 index 0000000..35d71ed --- /dev/null +++ b/src/context/types.ts @@ -0,0 +1,59 @@ +import { Dispatch, SetStateAction } from 'react' +import { EventT, Viewers } from '../types' + +// Calendar + +export type CalendarStateT = { + month: MonthContextT + year: number + day: { + number: number + events?: EventT[] + } + today: { + day: number + month: number + year: number + } + eventList: EventT[] + currentViewer: Viewers +} + +export type MonthContextT = { + number: number + firstDayOfWeek: number + lastDayOfWeek: number + numberOfDays: number + previousMonthLength: number +} + +export type CalendarContextSetterT = Dispatch> + +export type CalendarContextT = { + state: CalendarStateT + setState?: CalendarContextSetterT +} + +export interface ICalendarProviderProps { + eventList: EventT[] + initialViewer: Viewers +} + +// localization + +export type LocaleStateT = { + weekdaysNames: string[] + monthNames: string[] +} + +export type LocaleContextSetterT = Dispatch> + +export type LocaleContextT = { + state: LocaleStateT + setState?: LocaleContextSetterT +} + +export interface ILocaleProviderProps { + weekList: string[] + monthList: string[] +} diff --git a/src/hooks.ts b/src/hooks.ts new file mode 100644 index 0000000..4d52313 --- /dev/null +++ b/src/hooks.ts @@ -0,0 +1,23 @@ +import { useContext } from 'react' +import { CalendarContext } from './context/calendar' +import { LocaleContext } from './context/locale' + +const useCalendarContext = () => { + const context = useContext(CalendarContext) + + if (!context) + throw new Error("Can't use calendar context outside of CalendarProvider") + + return context +} + +const useLocaleContext = () => { + const context = useContext(LocaleContext) + + if (!context) + throw new Error("Can't use locale context outside of LocaleProvider") + + return context +} + +export { useCalendarContext, useLocaleContext } diff --git a/src/index.tsx b/src/index.tsx index d90c12c..b32b9d6 100644 --- a/src/index.tsx +++ b/src/index.tsx @@ -1,14 +1,26 @@ import React from 'react' import CalendarInContext from './CalendarInContext' -import { CalendarProvider as CalendarContextProvider } from './context' +import { CalendarProvider as CalendarContextProvider } from './context/calendar' import { ICalendarProps } from './types' +import { LocaleProvider as LocaleContextProvider } from './context/locale' -const Calendar: React.FC = ({ eventList }) => { +const Calendar: React.FC = ({ + eventList, + initialViewer, + locale: { monthNames, weekdaysNames }, +}) => { return ( - - + + + + ) } +export { Viewers } from './types' + export default Calendar diff --git a/src/types.ts b/src/types.ts index cce6f68..0188ea3 100644 --- a/src/types.ts +++ b/src/types.ts @@ -1,30 +1,26 @@ import { Dispatch, SetStateAction } from 'react' +import { CalendarStateT, LocaleStateT, MonthContextT } from './context/types' -// Context +// Experimental -export type CalendarContextStateT = { - month: MonthContextT - year: number - day: number -} +export type switchMonthInContextFT = ( + setContext: Dispatch> | undefined, + increase: boolean +) => void -export type MonthContextT = { - number: number - firstDayOfWeek: number - lastDayOfWeek: number - numberOfDays: number - previousMonthLength: number -} - -export type CalendarContextT = { - state: CalendarContextStateT - setState?: Dispatch> -} +export type UseCalendarSwitchFT = () => (increase: boolean) => void // Calendar component +export enum Viewers { + MonthViewer, + DayViewer, +} + export interface ICalendarProps { eventList: EventT[] + initialViewer: Viewers + locale: LocaleStateT } // Day @@ -34,11 +30,23 @@ export type DayT = { events: EventT[] } -export interface IDayProps { - dayNumber: number - events: EventT[] - shaded: boolean -} +export type ShouldDayBeShadedFT = ( + month: MonthContextT, + dayIndex: number +) => boolean + +export type FilterEventsByDayFT = ( + eventList: EventT[], + dayNumber: number, + monthNumber: number, + yearNumber: number +) => EventT[] + +export type SetDayFT = ( + dayNumber: number, + dayEvents: EventT[], + setState: Dispatch> | undefined +) => void // Event @@ -47,4 +55,7 @@ export type EventT = { title: string startDate: string endDate: string + color: string } + +export type GetEventLengthFT = (start: string, end: string) => string diff --git a/src/utils.ts b/src/utils.ts index ae29b21..739f02e 100644 --- a/src/utils.ts +++ b/src/utils.ts @@ -1,13 +1,17 @@ -import { MonthContextT } from './types' +import { MonthContextT } from './context/types' +import { + FilterEventsByDayFT, + GetEventLengthFT, + SetDayFT, + ShouldDayBeShadedFT, + switchMonthInContextFT, +} from './types' -const getCurrentMonth = (currentDay: Date): MonthContextT => { - const monthInfo = getMonthInfo( - currentDay.getFullYear(), - currentDay.getMonth() - ) +const getMonth = (date: Date): MonthContextT => { + const monthInfo = getMonthInfo(date.getFullYear(), date.getMonth()) return { - number: currentDay.getMonth(), + number: date.getMonth(), ...monthInfo, } } @@ -20,12 +24,97 @@ const getMonthInfo = ( const lastDayOfMonth = new Date(year, month + 1, 0) const prevMonth = new Date(year, month, 0) + const firstDayOfWeek = firstDayOfMonth.getDay() + + const convertedFirstDayOfWeek = + firstDayOfWeek - 1 >= 0 ? firstDayOfWeek - 1 : 6 + return { - firstDayOfWeek: firstDayOfMonth.getDay(), + firstDayOfWeek: convertedFirstDayOfWeek, lastDayOfWeek: lastDayOfMonth.getDay(), numberOfDays: lastDayOfMonth.getDate(), previousMonthLength: prevMonth.getDate(), } } -export { getCurrentMonth, getMonthInfo } +const getMonthName = (number: number, monthNames: string[]) => + monthNames[number] + +const switchMonthInContext: switchMonthInContextFT = (setContext, increase) => { + if (!setContext) return + + setContext((previousContext) => { + const newDate = new Date( + previousContext.year, + previousContext.month.number, + 1 + ) + + if (increase) newDate.setMonth(newDate.getMonth() + 1) + else newDate.setMonth(newDate.getMonth() - 1) + + return { + ...previousContext, + year: newDate.getFullYear(), + month: getMonth(newDate), + } + }) +} + +const shouldDayBeShaded: ShouldDayBeShadedFT = (month, dayIndex) => + dayIndex < month.firstDayOfWeek || + dayIndex > month.numberOfDays + month.firstDayOfWeek - 1 + +const filterEventsByDay: FilterEventsByDayFT = ( + eventList, + dayNumber, + monthNumber, + yearnumber +) => + eventList.filter((event) => { + const eventDate = new Date(event.startDate) + + return ( + eventDate.getDate() == dayNumber && + eventDate.getMonth() == monthNumber && + eventDate.getFullYear() == yearnumber + ) + }) + +const setDay: SetDayFT = (dayNumber, dayEvents, setState) => { + if (setState) + setState((prevState) => ({ + ...prevState, + day: { + ...prevState.day, + number: dayNumber, + events: dayEvents, + }, + })) +} + +const getEventLength: GetEventLengthFT = (start, end) => { + const startDate = new Date(start) + const endDate = new Date(end) + + if ((endDate.getTime() - startDate.getTime()) / (1000 * 3600 * 24) >= 1) + return 'Whole day' + const startMinutes = startDate.getMinutes().toString() + const endMinutes = endDate.getMinutes().toString() + + return `${startDate.getHours()}:${ + startMinutes.length < 2 ? '0' + startMinutes : startMinutes + }-${endDate.getHours()}:${ + endMinutes.length < 2 ? '0' + endMinutes : endMinutes + }` +} + +export { + getMonth, + getMonthName, + switchMonthInContext, + shouldDayBeShaded, + filterEventsByDay, + setDay, + getEventLength, +} diff --git a/src/views/Day.tsx b/src/views/Day.tsx new file mode 100644 index 0000000..63b0fe0 --- /dev/null +++ b/src/views/Day.tsx @@ -0,0 +1,77 @@ +import React, { useEffect } from 'react' +import { useCalendarContext, useLocaleContext } from '../hooks' +import { Viewers } from '../types' +import { getEventLength, getMonthName } from '../utils' + +import { IDayViewer } from './types' + +const HomeIcon = () => ( + + + + + +) + +const DayViewer: React.FC = () => { + const { + state: { day, month, year }, + setState, + } = useCalendarContext() + const { + state: { monthNames }, + } = useLocaleContext() + + useEffect(() => { + if (setState) + if (day.events === undefined) { + setState((prevState) => ({ + ...prevState, + day: { + ...prevState.day, + events: prevState.eventList.filter(() => false), + }, + })) + } + }, [day.number]) + + const handle = () => { + if (setState) + setState((prevSate) => ({ + ...prevSate, + currentViewer: Viewers.MonthViewer, + })) + } + + return ( +
+ +
+

{day.number}

+

{getMonthName(month.number, monthNames) + ' ' + year}

+
+
    + {day.events?.map((event, eventIndex) => ( +
  • +

    {event.title}

    +

    {getEventLength(event.startDate, event.endDate)}

    +
  • + ))} +
+
+ ) +} + +export default DayViewer diff --git a/src/views/DayOfMonth.tsx b/src/views/DayOfMonth.tsx new file mode 100644 index 0000000..6e22ff0 --- /dev/null +++ b/src/views/DayOfMonth.tsx @@ -0,0 +1,79 @@ +import React, { useState } from 'react' +import { useCalendarContext } from '../hooks' +import { Viewers } from '../types' +import { setDay } from '../utils' + +import { IDayOfMonthProps } from './types' +import styles from './styles' + +const ArrowDown: React.FC = () => ( + + + + + +) + +const DayOfMonth: React.FC = ({ + dayNumber, + events, + shaded, +}) => { + const { setState } = useCalendarContext() + + const [expanded, setExpanded] = useState(false) + + const handleClick = () => { + if (shaded) return + if (events.length > 2 && !expanded) return setExpanded(true) + setDay(dayNumber, events, setState) + if (setState) + setState((prevState) => ({ + ...prevState, + currentViewer: Viewers.DayViewer, + })) + } + + return ( +
+
{dayNumber}
+
    + {events.map((event, key) => ( +
  • + {event.title} +
  • + ))} +
+ {events.length > 2 ? ( +
+ +
+ ) : ( + '' + )} +
+ ) +} + +export default DayOfMonth diff --git a/src/views/Month.tsx b/src/views/Month.tsx new file mode 100644 index 0000000..a3c6ec5 --- /dev/null +++ b/src/views/Month.tsx @@ -0,0 +1,61 @@ +import React, { useEffect, useState } from 'react' +import { useCalendarContext } from '../hooks' +import { DayT } from '../types' +import { filterEventsByDay, shouldDayBeShaded } from '../utils' +import DayOfMonth from './DayOfMonth' +import MonthHeader from './MonthHeader' +import styles from './styles' + +const MonthView: React.FC = () => { + const { + state: { month, eventList, year: yearNumber }, + } = useCalendarContext() + + const [monthDays, setMonthDaysState] = useState([]) + + useEffect(() => { + const daysNumbersArray = [ + Array.from( + // Array(month.firstDayOfWeek - 1 > 0 ? month.firstDayOfWeek - 1 : 0) + Array(month.firstDayOfWeek) + ).map( + (_, index) => + month.previousMonthLength - month.firstDayOfWeek + index + 1 + ), + Array.from(Array(month.numberOfDays)).map((_, index) => index + 1), + Array.from(Array(7 - month.lastDayOfWeek)).map((_, index) => index + 1), + ] + + const monthNumber = month.number + + setMonthDaysState( + daysNumbersArray.flatMap((month, index) => + month.map((dayNumber) => ({ + number: dayNumber, + events: + index == 1 + ? filterEventsByDay(eventList, dayNumber, monthNumber, yearNumber) + : [], + })) + ) + ) + }, [month, eventList]) + + return ( + <> + +
+ {monthDays.map((day, dayIndex) => ( + + ))} +
+ + ) +} + +export default MonthView diff --git a/src/views/MonthHeader.tsx b/src/views/MonthHeader.tsx new file mode 100644 index 0000000..094e673 --- /dev/null +++ b/src/views/MonthHeader.tsx @@ -0,0 +1,52 @@ +import React from 'react' +import { useCalendarContext, useLocaleContext } from '../hooks' +import { getMonthName, switchMonthInContext } from '../utils' +import styles from './styles' + +const MonthHeader: React.FC = () => { + const { + state: { weekdaysNames, monthNames }, + } = useLocaleContext() + + const { + state: { + year, + month: { number }, + }, + setState, + } = useCalendarContext() + + return ( +
+
+ +

+ {getMonthName(number, monthNames) + ' ' + year} +

+ +
+ +
+ {weekdaysNames.map((weekDay, weekDayIndex) => ( +

+ {weekDay} +

+ ))} +
+
+ ) +} + +export default MonthHeader diff --git a/src/views/index.ts b/src/views/index.ts new file mode 100644 index 0000000..1274997 --- /dev/null +++ b/src/views/index.ts @@ -0,0 +1,4 @@ +import MonthView from './Month' +import DayView from './Day' + +export { MonthView, DayView } diff --git a/src/views/styles.ts b/src/views/styles.ts new file mode 100644 index 0000000..ddc5db4 --- /dev/null +++ b/src/views/styles.ts @@ -0,0 +1,117 @@ +type Style = React.CSSProperties + +const calendar: Style = { + height: '100%', + width: '100%', + border: '1px black solid', + borderRadius: '5px', + overflow: 'hidden', +} + +// Month header + +const weekdaysListHeader: Style = { + display: 'grid', + gridTemplateColumns: 'repeat(7, 1fr)', + width: '100%', + gap: '5px', +} + +const monthSwitchHeader: Style = { + display: 'grid', + gridTemplateColumns: 'repeat(7, 1fr)', + width: '100%', + gap: '5px', + backgroundColor: 'black', + color: 'white', + padding: '5px', +} + +const switchMonthButton: Style = { + backgroundColor: 'white', + border: 'none', + borderRadius: '5px', +} + +const monthSwitchHeaderTitle: Style = { + margin: '0px', + textAlign: 'center', + textTransform: 'capitalize', + gridColumn: 'span 5', +} + +const weekDay: Style = { + overflow: 'hidden', + textOverflow: 'ellipsis', + textAlign: 'center', + padding: '5px 0', + margin: '0px', + textTransform: 'capitalize', +} + +// Month viewer + +const monthGrid: Style = { + display: 'grid', + gridTemplateColumns: 'repeat(7, 1fr)', + gap: '5px', + padding: '5px', +} + +// Month day + +const dayOfMonth: Style = { + background: '#EEEEEE', + borderRadius: '5px', + overflow: 'hidden', + minHeight: '5rem', + padding: '5px', + position: 'relative', + transition: 'all 3s', +} + +const monthDayEventList: Style = { + padding: '0px', + margin: '0px', + listStyle: 'none', + overflow: 'hidden', + borderRadius: '4px', +} + +const monthDayEvent: Style = { + padding: '2px', +} + +const monthDayBottomShade: Style = { + position: 'absolute', + bottom: '0px', + marginLeft: '-5px', + width: '100%', + overflow: 'hidden', + display: 'flex', + alignItems: 'flex-end', + justifyContent: 'center', + backgroundImage: 'linear-gradient(transparent, #EEEEEE)', +} + +const monthDayNumber: Style = { + textAlign: 'center', + margin: '0px', +} + +const styles = { + switchMonthButton, + calendar, + weekdaysListHeader, + monthSwitchHeader, + monthSwitchHeaderTitle, + weekDay, + monthGrid, + dayOfMonth, + monthDayEventList, + monthDayEvent, + monthDayBottomShade, + monthDayNumber, +} + +export default styles diff --git a/src/views/types.ts b/src/views/types.ts new file mode 100644 index 0000000..0d5bdf5 --- /dev/null +++ b/src/views/types.ts @@ -0,0 +1,9 @@ +import { EventT } from '../types' + +export interface IDayOfMonthProps { + dayNumber: number + events: EventT[] + shaded: boolean +} + +export interface IDayViewer {}