Massive functional upgrade: separated localization, full day viewer, month switch, first npm publish, code refactors

This commit is contained in:
Dmitriy Shishkov 2020-10-31 22:50:59 +05:00
parent b37fe9644a
commit 0d66f3c4f6
No known key found for this signature in database
GPG Key ID: D76D70029F55183E
22 changed files with 817 additions and 201 deletions

4
.prettierrc Normal file
View File

@ -0,0 +1,4 @@
{
"semi": false,
"singleQuote": true
}

View File

@ -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 (
<div className="App">
<Calendar eventList={events} />
<Calendar
eventList={events}
locale={locale}
initialViewer={Viewers.MonthViewer}
/>
</div>
);
)
}
export default App;
export default App

View File

@ -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"
}
]

25
example/src/locale.json Normal file
View File

@ -0,0 +1,25 @@
{
"monthNames": [
"январь",
"февраль",
"март",
"апрель",
"май",
"июнь",
"июль",
"август",
"сентябрь",
"октябрь",
"ноябрь",
"декабрь"
],
"weekdaysNames": [
"понедельник",
"вторник",
"среда",
"четверг",
"пятница",
"субота",
"воскресенье"
]
}

View File

@ -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:

View File

@ -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<ICalendarProps> = ({ eventList }) => {
const context = useContext(CalendarContext)
const { month } = context.state
const [monthDaysState, setMonthDaysState] = useState<DayT[]>([])
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<DayT>((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 (
<div
style={{
height: '100%',
width: '100%',
display: 'grid',
gridTemplateColumns: 'repeat(7, 1fr)',
gridTemplateRows: 'repeat(5, 1fr)',
gap: '5px'
}}
>
{monthDaysState.map((day, dayIndex) => (
<Day
key={dayIndex}
dayNumber={day.number}
events={day.events}
shaded={
dayIndex < month.firstDayOfWeek - 1 ||
dayIndex > month.numberOfDays + month.firstDayOfWeek - 2
}
/>
))}
<div style={styles.calendar}>
{currentViewer == Viewers.MonthViewer && <MonthView />}
{currentViewer == Viewers.DayViewer && <DayView />}
</div>
)
}

View File

@ -1,48 +0,0 @@
import React from 'react'
import { IDayProps } from './types'
const Day: React.FC<IDayProps> = ({ dayNumber, events, shaded }) => {
return (
<div
style={{
background: '#EEEEEE',
borderRadius: '5px',
maxHeight: '100px',
overflow: 'hidden',
padding: '5px',
position: 'relative',
opacity: shaded ? '0.5' : '1',
}}
>
<h5
style={{
textAlign: 'center',
margin: '0px',
}}
>
{dayNumber}
</h5>
<ul style={{ paddingLeft: '20px', margin: '0' }}>
{events.map((event, key) => (
<li key={key} style={{}}>
{event.title}
</li>
))}
</ul>
<div
style={{
position: 'absolute',
bottom: '0px',
marginLeft: '-5px',
width: '100%',
height: '50%',
display: 'block',
backgroundImage: 'linear-gradient(transparent, #EEEEEE)',
}}
/>
</div>
)
}
export default Day

View File

@ -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<CalendarContextT>({
state: initialCalendarContextState,
})
const CalendarProvider: React.FC = ({ children }) => {
const [state, setState] = useState<CalendarContextStateT>(
initialCalendarContextState
)
const [now] = useState<Date>(new Date())
useEffect(
() =>
setState((prev) => ({
...prev,
month: getCurrentMonth(now),
year: now.getFullYear(),
day: now.getDate(),
})),
[]
)
return (
<CalendarContext.Provider value={{ state, setState }}>
{children}
</CalendarContext.Provider>
)
}
export { CalendarContext, CalendarProvider }

74
src/context/calendar.tsx Normal file
View File

@ -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<CalendarContextT | null>(null)
const CalendarProvider: React.FC<ICalendarProviderProps> = ({
children,
eventList,
initialViewer,
}) => {
const [state, setState] = useState<CalendarStateT>(
initialCalendarContextState
)
const [now] = useState<Date>(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 (
<CalendarContext.Provider value={value}>
{children}
</CalendarContext.Provider>
)
}
export { CalendarContext, CalendarProvider }

32
src/context/locale.tsx Normal file
View File

@ -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<LocaleContextT | null>(null)
const LocaleProvider: React.FC<ILocaleProviderProps> = ({
children,
monthList,
weekList,
}) => {
const [state, setState] = useState<LocaleStateT>(initialLocaleState)
useEffect(() => {
setState({
monthNames: monthList,
weekdaysNames: weekList,
})
}, [monthList, weekList])
const value = useMemo(() => ({ state, setState }), [state])
return (
<LocaleContext.Provider value={value}>{children}</LocaleContext.Provider>
)
}
export { LocaleContext, LocaleProvider }

59
src/context/types.ts Normal file
View File

@ -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<SetStateAction<CalendarStateT>>
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<SetStateAction<LocaleStateT>>
export type LocaleContextT = {
state: LocaleStateT
setState?: LocaleContextSetterT
}
export interface ILocaleProviderProps {
weekList: string[]
monthList: string[]
}

23
src/hooks.ts Normal file
View File

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

View File

@ -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<ICalendarProps> = ({ eventList }) => {
const Calendar: React.FC<ICalendarProps> = ({
eventList,
initialViewer,
locale: { monthNames, weekdaysNames },
}) => {
return (
<CalendarContextProvider>
<CalendarInContext eventList={eventList} />
<CalendarContextProvider
eventList={eventList}
initialViewer={initialViewer}
>
<LocaleContextProvider monthList={monthNames} weekList={weekdaysNames}>
<CalendarInContext />
</LocaleContextProvider>
</CalendarContextProvider>
)
}
export { Viewers } from './types'
export default Calendar

View File

@ -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<SetStateAction<CalendarStateT>> | undefined,
increase: boolean
) => void
export type MonthContextT = {
number: number
firstDayOfWeek: number
lastDayOfWeek: number
numberOfDays: number
previousMonthLength: number
}
export type CalendarContextT = {
state: CalendarContextStateT
setState?: Dispatch<SetStateAction<CalendarContextStateT>>
}
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<SetStateAction<CalendarStateT>> | 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

View File

@ -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,
}

77
src/views/Day.tsx Normal file
View File

@ -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 = () => (
<svg
width="23"
height="22"
viewBox="0 0 23 22"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="#000000">
<path d="M11.5 5.21591L20.125 13.2268V22H14.375V16.2609H8.625V22H2.875V13.2268L11.5 5.21591ZM23 10.6633L11.5 0L0 10.649L1.30429 12.0503L11.5 2.6113L21.6957 12.0646L23 10.6633Z"></path>
</g>
</svg>
)
const DayViewer: React.FC<IDayViewer> = () => {
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 (
<div>
<button
title="Return to main"
onClick={handle}
style={{ background: 'none', border: 'none', cursor: 'pointer' }}
>
<HomeIcon />
</button>
<div>
<h1>{day.number}</h1>
<h3>{getMonthName(month.number, monthNames) + ' ' + year}</h3>
</div>
<ul>
{day.events?.map((event, eventIndex) => (
<li key={eventIndex}>
<h2>{event.title}</h2>
<h3>{getEventLength(event.startDate, event.endDate)}</h3>
</li>
))}
</ul>
</div>
)
}
export default DayViewer

79
src/views/DayOfMonth.tsx Normal file
View File

@ -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 = () => (
<svg
width="11"
height="20"
viewBox="0 0 11 6"
fill="none"
xmlns="http://www.w3.org/2000/svg"
>
<g fill="#000000">
<path d="M0 1.132L1.29663 0L5.50183 3.7356L9.70337 0L11 1.132L5.50183 6L0 1.132Z" />
</g>
</svg>
)
const DayOfMonth: React.FC<IDayOfMonthProps> = ({
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 (
<div
style={{
...styles.dayOfMonth,
opacity: shaded ? '0.5' : '1',
maxHeight: expanded ? '100vh' : '5rem',
}}
onClick={handleClick}
>
<h5 style={styles.monthDayNumber}>{dayNumber}</h5>
<ul style={styles.monthDayEventList}>
{events.map((event, key) => (
<li
key={key}
style={{ ...styles.monthDayEvent, backgroundColor: event.color }}
>
{event.title}
</li>
))}
</ul>
{events.length > 2 ? (
<div
style={{
...styles.monthDayBottomShade,
height: expanded ? '0px' : '50%',
}}
>
<ArrowDown />
</div>
) : (
''
)}
</div>
)
}
export default DayOfMonth

61
src/views/Month.tsx Normal file
View File

@ -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<DayT[]>([])
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<DayT>((dayNumber) => ({
number: dayNumber,
events:
index == 1
? filterEventsByDay(eventList, dayNumber, monthNumber, yearNumber)
: [],
}))
)
)
}, [month, eventList])
return (
<>
<MonthHeader />
<div style={styles.monthGrid}>
{monthDays.map((day, dayIndex) => (
<DayOfMonth
key={dayIndex}
dayNumber={day.number}
events={day.events}
shaded={shouldDayBeShaded(month, dayIndex)}
/>
))}
</div>
</>
)
}
export default MonthView

52
src/views/MonthHeader.tsx Normal file
View File

@ -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 (
<header>
<div style={styles.monthSwitchHeader}>
<button
title={getMonthName(number - 1, monthNames)}
onClick={() => switchMonthInContext(setState, false)}
style={styles.switchMonthButton}
>
&lt;
</button>
<h4 style={styles.monthSwitchHeaderTitle}>
{getMonthName(number, monthNames) + ' ' + year}
</h4>
<button
title={getMonthName(number + 1, monthNames)}
onClick={() => switchMonthInContext(setState, true)}
style={styles.switchMonthButton}
>
&gt;
</button>
</div>
<div style={styles.weekdaysListHeader}>
{weekdaysNames.map((weekDay, weekDayIndex) => (
<p key={weekDayIndex} style={styles.weekDay}>
{weekDay}
</p>
))}
</div>
</header>
)
}
export default MonthHeader

4
src/views/index.ts Normal file
View File

@ -0,0 +1,4 @@
import MonthView from './Month'
import DayView from './Day'
export { MonthView, DayView }

117
src/views/styles.ts Normal file
View File

@ -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

9
src/views/types.ts Normal file
View File

@ -0,0 +1,9 @@
import { EventT } from '../types'
export interface IDayOfMonthProps {
dayNumber: number
events: EventT[]
shaded: boolean
}
export interface IDayViewer {}