230 lines
6.5 KiB
TypeScript
Raw Normal View History

2020-08-05 08:14:22 +03:00
import React, { ReactChild } from "react";
import { ViewMode } from "../../types/public-types";
import { TopPartOfCalendar } from "./top-part-of-calendar";
2020-07-22 20:50:43 +03:00
import {
getLocaleMonth,
getWeekNumberISO8601,
2020-08-05 08:14:22 +03:00
} from "../../helpers/date-helper";
2021-03-21 16:58:20 +02:00
import { DateSetup } from "../../types/date-setup";
2020-08-05 08:14:22 +03:00
import styles from "./calendar.module.css";
2020-07-22 20:50:43 +03:00
export type CalendarProps = {
2021-03-21 16:58:20 +02:00
dateSetup: DateSetup;
2020-07-22 20:50:43 +03:00
locale: string;
viewMode: ViewMode;
headerHeight: number;
columnWidth: number;
fontFamily: string;
fontSize: string;
};
export const Calendar: React.FC<CalendarProps> = ({
2021-03-21 16:58:20 +02:00
dateSetup,
2020-07-22 20:50:43 +03:00
locale,
viewMode,
headerHeight,
columnWidth,
fontFamily,
fontSize,
}) => {
const getCalendarValuesForMonth = () => {
2020-08-05 08:14:22 +03:00
const topValues: ReactChild[] = [];
const bottomValues: ReactChild[] = [];
2020-07-22 20:50:43 +03:00
const topDefaultWidth = columnWidth * 6;
const topDefaultHeight = headerHeight * 0.5;
2021-03-21 16:58:20 +02:00
for (let i = 0; i < dateSetup.dates.length; i++) {
const date = dateSetup.dates[i];
2020-08-05 08:14:22 +03:00
const bottomValue = getLocaleMonth(date, locale);
2020-07-22 20:50:43 +03:00
bottomValues.push(
<text
key={bottomValue + date.getFullYear()}
y={headerHeight * 0.8}
x={columnWidth * i + columnWidth * 0.5}
2020-08-05 08:14:22 +03:00
className={styles.calendarBottomText}
2020-07-22 20:50:43 +03:00
>
{bottomValue}
</text>
);
2021-03-21 16:58:20 +02:00
if (
i === 0 ||
date.getFullYear() !== dateSetup.dates[i - 1].getFullYear()
) {
2020-08-05 08:14:22 +03:00
const topValue = date.getFullYear().toString();
2020-07-22 20:50:43 +03:00
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 = () => {
2020-08-05 08:14:22 +03:00
const topValues: ReactChild[] = [];
const bottomValues: ReactChild[] = [];
let weeksCount: number = 1;
2020-07-22 20:50:43 +03:00
const topDefaultHeight = headerHeight * 0.5;
2021-03-21 16:58:20 +02:00
const dates = dateSetup.dates;
2020-07-22 20:50:43 +03:00
for (let i = dates.length - 1; i >= 0; i--) {
const date = dates[i];
2020-08-05 08:14:22 +03:00
let topValue = "";
2020-07-22 20:50:43 +03:00
if (i === 0 || date.getMonth() !== dates[i - 1].getMonth()) {
2020-08-05 08:14:22 +03:00
// top
2020-07-22 20:50:43 +03:00
topValue = `${getLocaleMonth(date, locale)}, ${date.getFullYear()}`;
}
2020-08-05 08:14:22 +03:00
// bottom
2020-07-22 20:50:43 +03:00
const bottomValue = `W${getWeekNumberISO8601(date)}`;
bottomValues.push(
<text
key={date.getTime()}
y={headerHeight * 0.8}
x={columnWidth * i}
2020-08-05 08:14:22 +03:00
className={styles.calendarBottomText}
2020-07-22 20:50:43 +03:00
>
{bottomValue}
</text>
);
if (topValue) {
2020-08-05 08:14:22 +03:00
// if last day is new month
2020-07-22 20:50:43 +03:00
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 = () => {
2020-08-05 08:14:22 +03:00
const topValues: ReactChild[] = [];
const bottomValues: ReactChild[] = [];
2020-07-22 20:50:43 +03:00
const topDefaultHeight = headerHeight * 0.5;
2021-03-21 16:58:20 +02:00
const dates = dateSetup.dates;
2020-07-22 20:50:43 +03:00
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}
2020-08-05 08:14:22 +03:00
className={styles.calendarBottomText}
2020-07-22 20:50:43 +03:00
>
{bottomValue}
</text>
);
if (
i + 1 !== dates.length &&
date.getMonth() !== dates[i + 1].getMonth()
) {
2020-08-05 08:14:22 +03:00
const topValue = getLocaleMonth(date, locale);
2020-07-22 20:50:43 +03:00
topValues.push(
<TopPartOfCalendar
key={topValue + date.getFullYear()}
2020-07-22 20:50:43 +03:00
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 = () => {
2020-08-05 08:14:22 +03:00
const topValues: ReactChild[] = [];
const bottomValues: ReactChild[] = [];
const ticks = viewMode === ViewMode.HalfDay ? 2 : 4;
2020-07-22 20:50:43 +03:00
const topDefaultHeight = headerHeight * 0.5;
2021-03-21 16:58:20 +02:00
const dates = dateSetup.dates;
2020-07-22 20:50:43 +03:00
for (let i = 0; i < dates.length; i++) {
const date = dates[i];
const bottomValue = Intl.DateTimeFormat(locale, {
2020-08-05 08:14:22 +03:00
hour: "numeric",
2020-07-22 20:50:43 +03:00
}).format(date);
bottomValues.push(
<text
key={date.getTime()}
y={headerHeight * 0.8}
x={columnWidth * i}
2020-08-05 08:14:22 +03:00
className={styles.calendarBottomText}
2020-07-22 20:50:43 +03:00
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()}
2020-07-22 20:50:43 +03:00
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[] = [];
2021-03-21 16:58:20 +02:00
switch (dateSetup.viewMode) {
2020-07-22 20:50:43 +03:00
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}
2021-03-21 16:58:20 +02:00
width={columnWidth * dateSetup.dates.length}
height={headerHeight}
className={styles.calendarHeader}
/>
2020-07-22 20:50:43 +03:00
{bottomValues} {topValues}
</g>
);
};