plane/web/components/gantt-chart/views/month-view.ts
2024-03-19 20:08:35 +05:30

198 lines
6.2 KiB
TypeScript

// types
import { findTotalDaysInRange } from "@/helpers/date-time.helper";
import { weeks, months } from "../data";
import { ChartDataType, IGanttBlock } from "../types";
// data
// helpers
import { generateDate, getWeekNumberByDate, getNumberOfDaysInMonth, getDatesBetweenTwoDates } from "./helpers";
type GetAllDaysInMonthInMonthViewType = {
date: any;
day: any;
dayData: any;
weekNumber: number;
title: string;
active: boolean;
today: boolean;
};
interface IMonthChild {
active: boolean;
date: Date;
day: number;
dayData: {
key: number;
shortTitle: string;
title: string;
};
title: string;
today: boolean;
weekNumber: number;
}
export interface IMonthBlock {
children: IMonthChild[];
month: number;
monthData: {
key: number;
shortTitle: string;
title: string;
};
title: string;
year: number;
}
[];
const getAllDaysInMonthInMonthView = (month: number, year: number): IMonthChild[] => {
const day: GetAllDaysInMonthInMonthViewType[] = [];
const numberOfDaysInMonth = getNumberOfDaysInMonth(month, year);
const currentDate = new Date();
Array.from(Array(numberOfDaysInMonth).keys()).map((_day: number) => {
const date: Date = generateDate(_day + 1, month, year);
day.push({
date: date,
day: _day + 1,
dayData: weeks[date.getDay()],
weekNumber: getWeekNumberByDate(date),
title: `${weeks[date.getDay()].shortTitle} ${_day + 1}`,
active: false,
today:
currentDate.getFullYear() === year && currentDate.getMonth() === month && currentDate.getDate() === _day + 1
? true
: false,
});
});
return day;
};
const generateMonthDataByMonthAndYearInMonthView = (month: number, year: number): IMonthBlock => {
const currentMonth: number = month;
const currentYear: number = year;
const monthPayload = {
year: currentYear,
month: currentMonth,
monthData: months[currentMonth],
children: getAllDaysInMonthInMonthView(currentMonth, currentYear),
title: `${months[currentMonth].title} ${currentYear}`,
};
return monthPayload;
};
export const generateMonthChart = (monthPayload: ChartDataType, side: null | "left" | "right") => {
let renderState = monthPayload;
const renderPayload: any = [];
const range: number = renderState.data.approxFilterRange || 6;
let filteredDates: Date[] = [];
let minusDate: Date = new Date();
let plusDate: Date = new Date();
if (side === null) {
const currentDate = renderState.data.currentDate;
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
renderState = {
...renderState,
data: {
...renderState.data,
startDate: filteredDates[0],
endDate: filteredDates[filteredDates.length - 1],
},
};
} else if (side === "left") {
const currentDate = renderState.data.startDate;
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - range, currentDate.getDate());
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() - 1, currentDate.getDate());
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
renderState = {
...renderState,
data: { ...renderState.data, startDate: filteredDates[0] },
};
} else if (side === "right") {
const currentDate = renderState.data.endDate;
minusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + 1, currentDate.getDate());
plusDate = new Date(currentDate.getFullYear(), currentDate.getMonth() + range, currentDate.getDate());
if (minusDate && plusDate) filteredDates = getDatesBetweenTwoDates(minusDate, plusDate);
renderState = {
...renderState,
data: { ...renderState.data, endDate: filteredDates[filteredDates.length - 1] },
};
}
if (filteredDates && filteredDates.length > 0)
for (const currentDate in filteredDates) {
const date = filteredDates[parseInt(currentDate)];
const currentYear = date.getFullYear();
const currentMonth = date.getMonth();
renderPayload.push(generateMonthDataByMonthAndYearInMonthView(currentMonth, currentYear));
}
const scrollWidth =
renderPayload
.map((monthData: any) => monthData.children.length)
.reduce((partialSum: number, a: number) => partialSum + a, 0) * monthPayload.data.width;
return { state: renderState, payload: renderPayload, scrollWidth: scrollWidth };
};
export const getNumberOfDaysBetweenTwoDatesInMonth = (startDate: Date, endDate: Date) => {
let daysDifference: number = 0;
startDate.setHours(0, 0, 0, 0);
endDate.setHours(0, 0, 0, 0);
const timeDifference: number = startDate.getTime() - endDate.getTime();
daysDifference = Math.abs(Math.floor(timeDifference / (1000 * 60 * 60 * 24)));
return daysDifference;
};
// calc item scroll position and width
export const getMonthChartItemPositionWidthInMonth = (chartData: ChartDataType, itemData: IGanttBlock) => {
let scrollPosition: number = 0;
let scrollWidth: number = 0;
const { startDate } = chartData.data;
const { start_date: itemStartDate, target_date: itemTargetDate } = itemData;
if (!itemStartDate || !itemTargetDate) return;
startDate.setHours(0, 0, 0, 0);
itemStartDate.setHours(0, 0, 0, 0);
itemTargetDate.setHours(0, 0, 0, 0);
const positionDaysDifference = findTotalDaysInRange(startDate, itemStartDate, false);
if (!positionDaysDifference) return;
scrollPosition = positionDaysDifference * chartData.data.width;
let diffMonths = (itemStartDate.getFullYear() - startDate.getFullYear()) * 12;
diffMonths -= startDate.getMonth();
diffMonths += itemStartDate.getMonth();
scrollPosition = scrollPosition + diffMonths;
// position code ends
// width code starts
const widthTimeDifference: number = itemStartDate.getTime() - itemTargetDate.getTime();
const widthDaysDifference: number = Math.abs(Math.floor(widthTimeDifference / (1000 * 60 * 60 * 24)));
scrollWidth = (widthDaysDifference + 1) * chartData.data.width + 1;
// width code ends
return { marginLeft: scrollPosition, width: scrollWidth };
};