230 lines
6.5 KiB
TypeScript
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>
|
|
);
|
|
};
|