216 lines
6.0 KiB
TypeScript
216 lines
6.0 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 '../../style.css';
|
||
|
|
export type CalendarProps = {
|
||
|
|
dates: Date[];
|
||
|
|
locale: string;
|
||
|
|
viewMode: ViewMode;
|
||
|
|
headerHeight: number;
|
||
|
|
columnWidth: number;
|
||
|
|
fontFamily: string;
|
||
|
|
fontSize: string;
|
||
|
|
};
|
||
|
|
|
||
|
|
export const Calendar: React.FC<CalendarProps> = ({
|
||
|
|
dates,
|
||
|
|
locale,
|
||
|
|
viewMode,
|
||
|
|
headerHeight,
|
||
|
|
columnWidth,
|
||
|
|
fontFamily,
|
||
|
|
fontSize,
|
||
|
|
}) => {
|
||
|
|
const getCalendarValuesForMonth = () => {
|
||
|
|
let topValues: ReactChild[] = [];
|
||
|
|
let bottomValues: ReactChild[] = [];
|
||
|
|
const topDefaultWidth = columnWidth * 6;
|
||
|
|
const topDefaultHeight = headerHeight * 0.5;
|
||
|
|
for (let i = 0; i < dates.length; i++) {
|
||
|
|
const date = dates[i];
|
||
|
|
let bottomValue = getLocaleMonth(date, locale);
|
||
|
|
bottomValues.push(
|
||
|
|
<text
|
||
|
|
key={bottomValue + date.getFullYear()}
|
||
|
|
y={headerHeight * 0.8}
|
||
|
|
x={columnWidth * i + columnWidth * 0.5}
|
||
|
|
className="GanttCalendar-bottomText"
|
||
|
|
>
|
||
|
|
{bottomValue}
|
||
|
|
</text>
|
||
|
|
);
|
||
|
|
if (i === 0 || date.getFullYear() !== dates[i - 1].getFullYear()) {
|
||
|
|
let 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 = () => {
|
||
|
|
let topValues: ReactChild[] = [];
|
||
|
|
let bottomValues: ReactChild[] = [];
|
||
|
|
let weeksCount: number = 0;
|
||
|
|
const topDefaultHeight = headerHeight * 0.5;
|
||
|
|
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="GanttCalendar-bottomText"
|
||
|
|
>
|
||
|
|
{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 = () => {
|
||
|
|
let topValues: ReactChild[] = [];
|
||
|
|
let bottomValues: ReactChild[] = [];
|
||
|
|
const topDefaultHeight = headerHeight * 0.5;
|
||
|
|
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="GanttCalendar-bottomText"
|
||
|
|
>
|
||
|
|
{bottomValue}
|
||
|
|
</text>
|
||
|
|
);
|
||
|
|
if (
|
||
|
|
i + 1 !== dates.length &&
|
||
|
|
date.getMonth() !== dates[i + 1].getMonth()
|
||
|
|
) {
|
||
|
|
let topValue = getLocaleMonth(date, locale);
|
||
|
|
|
||
|
|
topValues.push(
|
||
|
|
<TopPartOfCalendar
|
||
|
|
key={topValue}
|
||
|
|
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 = () => {
|
||
|
|
let topValues: ReactChild[] = [];
|
||
|
|
let bottomValues: ReactChild[] = [];
|
||
|
|
let ticks = viewMode === ViewMode.HalfDay ? 2 : 4;
|
||
|
|
const topDefaultHeight = headerHeight * 0.5;
|
||
|
|
|
||
|
|
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="GanttCalendar-bottomText"
|
||
|
|
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}
|
||
|
|
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 (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}>
|
||
|
|
{bottomValues} {topValues}
|
||
|
|
</g>
|
||
|
|
);
|
||
|
|
};
|