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 {}