2021-03-21 16:58:20 +02:00

230 lines
6.5 KiB
TypeScript

import React, { ReactChild } from "react";
import { ViewMode } from "../../types/public-types";
import { TopPartOfCalendar } from "./top-part-of-calendar";
import {
getLocaleMonth,
getWeekNumberISO8601,
} from "../../helpers/date-helper";
import { DateSetup } from "../../types/date-setup";
import styles from "./calendar.module.css";
export type CalendarProps = {
dateSetup: DateSetup;
locale: string;
viewMode: ViewMode;
headerHeight: number;
columnWidth: number;
fontFamily: string;
fontSize: string;
};
export const Calendar: React.FC<CalendarProps> = ({
dateSetup,
locale,
viewMode,
headerHeight,
columnWidth,
fontFamily,
fontSize,
}) => {
const getCalendarValuesForMonth = () => {
const topValues: ReactChild[] = [];
const bottomValues: ReactChild[] = [];
const topDefaultWidth = columnWidth * 6;
const topDefaultHeight = headerHeight * 0.5;
for (let i = 0; i < dateSetup.dates.length; i++) {
const date = dateSetup.dates[i];
const bottomValue = getLocaleMonth(date, locale);
bottomValues.push(
<text
key={bottomValue + date.getFullYear()}
y={headerHeight * 0.8}
x={columnWidth * i + columnWidth * 0.5}
className={styles.calendarBottomText}
>
{bottomValue}
</text>
);
if (
i === 0 ||
date.getFullYear() !== dateSetup.dates[i - 1].getFullYear()
) {
const topValue = date.getFullYear().toString();
topValues.push(
<TopPartOfCalendar
key={topValue}
value={topValue}
x1Line={columnWidth * i}
y1Line={0}
y2Line={topDefaultHeight}
xText={
topDefaultWidth + columnWidth * i - date.getMonth() * columnWidth
}
yText={topDefaultHeight * 0.9}
/>
);
}
}
return [topValues, bottomValues];
};
const getCalendarValuesForWeek = () => {
const topValues: ReactChild[] = [];
const bottomValues: ReactChild[] = [];
let weeksCount: number = 1;
const topDefaultHeight = headerHeight * 0.5;
const dates = dateSetup.dates;
for (let i = dates.length - 1; i >= 0; i--) {
const date = dates[i];
let topValue = "";
if (i === 0 || date.getMonth() !== dates[i - 1].getMonth()) {
// top
topValue = `${getLocaleMonth(date, locale)}, ${date.getFullYear()}`;
}
// bottom
const bottomValue = `W${getWeekNumberISO8601(date)}`;
bottomValues.push(
<text
key={date.getTime()}
y={headerHeight * 0.8}
x={columnWidth * i}
className={styles.calendarBottomText}
>
{bottomValue}
</text>
);
if (topValue) {
// if last day is new month
if (i !== dates.length - 1) {
topValues.push(
<TopPartOfCalendar
key={topValue}
value={topValue}
x1Line={columnWidth * i + weeksCount * columnWidth}
y1Line={0}
y2Line={topDefaultHeight}
xText={columnWidth * i + columnWidth * weeksCount * 0.5}
yText={topDefaultHeight * 0.9}
/>
);
}
weeksCount = 0;
}
weeksCount++;
}
return [topValues, bottomValues];
};
const getCalendarValuesForDay = () => {
const topValues: ReactChild[] = [];
const bottomValues: ReactChild[] = [];
const topDefaultHeight = headerHeight * 0.5;
const dates = dateSetup.dates;
for (let i = 0; i < dates.length; i++) {
const date = dates[i];
const bottomValue = date.getDate().toString();
bottomValues.push(
<text
key={date.getTime()}
y={headerHeight * 0.8}
x={columnWidth * i + columnWidth * 0.5}
className={styles.calendarBottomText}
>
{bottomValue}
</text>
);
if (
i + 1 !== dates.length &&
date.getMonth() !== dates[i + 1].getMonth()
) {
const topValue = getLocaleMonth(date, locale);
topValues.push(
<TopPartOfCalendar
key={topValue + date.getFullYear()}
value={topValue}
x1Line={columnWidth * (i + 1)}
y1Line={0}
y2Line={topDefaultHeight}
xText={columnWidth * (i + 1) - date.getDate() * columnWidth * 0.5}
yText={topDefaultHeight * 0.9}
/>
);
}
}
return [topValues, bottomValues];
};
const getCalendarValuesForOther = () => {
const topValues: ReactChild[] = [];
const bottomValues: ReactChild[] = [];
const ticks = viewMode === ViewMode.HalfDay ? 2 : 4;
const topDefaultHeight = headerHeight * 0.5;
const dates = dateSetup.dates;
for (let i = 0; i < dates.length; i++) {
const date = dates[i];
const bottomValue = Intl.DateTimeFormat(locale, {
hour: "numeric",
}).format(date);
bottomValues.push(
<text
key={date.getTime()}
y={headerHeight * 0.8}
x={columnWidth * i}
className={styles.calendarBottomText}
fontFamily={fontFamily}
>
{bottomValue}
</text>
);
if (i === 0 || date.getDate() !== dates[i - 1].getDate()) {
const topValue = `${date.getDate()} ${getLocaleMonth(date, locale)}`;
topValues.push(
<TopPartOfCalendar
key={topValue + date.getFullYear()}
value={topValue}
x1Line={columnWidth * i + ticks * columnWidth}
y1Line={0}
y2Line={topDefaultHeight}
xText={columnWidth * i + ticks * columnWidth * 0.5}
yText={topDefaultHeight * 0.9}
/>
);
}
}
return [topValues, bottomValues];
};
let topValues: ReactChild[] = [];
let bottomValues: ReactChild[] = [];
switch (dateSetup.viewMode) {
case ViewMode.Month:
[topValues, bottomValues] = getCalendarValuesForMonth();
break;
case ViewMode.Week:
[topValues, bottomValues] = getCalendarValuesForWeek();
break;
case ViewMode.Day:
[topValues, bottomValues] = getCalendarValuesForDay();
break;
default:
[topValues, bottomValues] = getCalendarValuesForOther();
break;
}
return (
<g className="calendar" fontSize={fontSize} fontFamily={fontFamily}>
<rect
x={0}
y={0}
width={columnWidth * dateSetup.dates.length}
height={headerHeight}
className={styles.calendarHeader}
/>
{bottomValues} {topValues}
</g>
);
};