Files
leadchat/app/javascript/dashboard/components/ui/DatePicker/helpers/DatePickerHelper.js
2026-02-06 18:22:30 +05:30

291 lines
7.7 KiB
JavaScript

import {
startOfDay,
subDays,
endOfDay,
subMonths,
addMonths,
subYears,
addYears,
startOfMonth,
isSameMonth,
format,
startOfWeek,
endOfWeek,
addWeeks,
addDays,
eachDayOfInterval,
endOfMonth,
isSameDay,
isWithinInterval,
} from 'date-fns';
// Constants for calendar and date ranges
export const calendarWeeks = [
{ id: 1, label: 'M' },
{ id: 2, label: 'T' },
{ id: 3, label: 'W' },
{ id: 4, label: 'T' },
{ id: 5, label: 'F' },
{ id: 6, label: 'S' },
{ id: 7, label: 'S' },
];
export const dateRanges = [
{ label: 'DATE_PICKER.DATE_RANGE_OPTIONS.LAST_7_DAYS', value: 'last7days' },
{ label: 'DATE_PICKER.DATE_RANGE_OPTIONS.LAST_30_DAYS', value: 'last30days' },
{
label: 'DATE_PICKER.DATE_RANGE_OPTIONS.LAST_3_MONTHS',
value: 'last3months',
separator: true,
},
{
label: 'DATE_PICKER.DATE_RANGE_OPTIONS.LAST_6_MONTHS',
value: 'last6months',
},
{ label: 'DATE_PICKER.DATE_RANGE_OPTIONS.LAST_YEAR', value: 'lastYear' },
{
label: 'DATE_PICKER.DATE_RANGE_OPTIONS.THIS_WEEK',
value: 'thisWeek',
separator: true,
},
{
label: 'DATE_PICKER.DATE_RANGE_OPTIONS.MONTH_TO_DATE',
value: 'monthToDate',
},
{
label: 'DATE_PICKER.DATE_RANGE_OPTIONS.CUSTOM_RANGE',
value: 'custom',
separator: true,
},
];
export const DATE_RANGE_TYPES = {
LAST_7_DAYS: 'last7days',
LAST_30_DAYS: 'last30days',
LAST_3_MONTHS: 'last3months',
LAST_6_MONTHS: 'last6months',
LAST_YEAR: 'lastYear',
THIS_WEEK: 'thisWeek',
MONTH_TO_DATE: 'monthToDate',
CUSTOM_RANGE: 'custom',
};
export const CALENDAR_TYPES = {
START_CALENDAR: 'start',
END_CALENDAR: 'end',
};
export const CALENDAR_PERIODS = {
WEEK: 'week',
MONTH: 'month',
YEAR: 'year',
};
// Utility functions for date operations
export const monthName = currentDate => format(currentDate, 'MMMM');
export const yearName = currentDate => format(currentDate, 'yyyy');
export const getIntlDateFormatForLocale = () => {
const year = 2222;
const month = 12;
const day = 15;
const date = new Date(year, month - 1, day);
const formattedDate = new Intl.DateTimeFormat(navigator.language).format(
date
);
return formattedDate
.replace(`${year}`, 'yyyy')
.replace(`${month}`, 'MM')
.replace(`${day}`, 'dd');
};
// Utility functions for calendar operations
export const chunk = (array, size) =>
Array.from({ length: Math.ceil(array.length / size) }, (_, index) =>
array.slice(index * size, index * size + size)
);
export const getWeeksForMonth = (date, weekStartsOn = 1) => {
const startOfTheMonth = startOfMonth(date);
const startOfTheFirstWeek = startOfWeek(startOfTheMonth, { weekStartsOn });
const endOfTheLastWeek = addDays(startOfTheFirstWeek, 41); // Covering six weeks to fill the calendar
return chunk(
eachDayOfInterval({ start: startOfTheFirstWeek, end: endOfTheLastWeek }),
7
);
};
export const moveCalendarDate = (
calendar,
startCurrentDate,
endCurrentDate,
direction,
period
) => {
const adjustFunctions = {
month: { prev: subMonths, next: addMonths },
year: { prev: subYears, next: addYears },
};
const adjust = adjustFunctions[period][direction];
if (calendar === 'start') {
const newStart = adjust(startCurrentDate, 1);
return { start: newStart, end: endCurrentDate };
}
const newEnd = adjust(endCurrentDate, 1);
return { start: startCurrentDate, end: newEnd };
};
// Date comparison functions
export const isToday = (currentDate, date) =>
date.getDate() === currentDate.getDate() &&
date.getMonth() === currentDate.getMonth() &&
date.getFullYear() === currentDate.getFullYear();
export const isCurrentMonth = (day, referenceDate) =>
isSameMonth(day, referenceDate);
export const isLastDayOfMonth = day => {
const lastDay = endOfMonth(day);
return day.getDate() === lastDay.getDate();
};
export const dayIsInRange = (date, startDate, endDate) => {
if (!startDate || !endDate) {
return false;
}
// Normalize dates to ignore time differences
let startOfDayStart = startOfDay(startDate);
let startOfDayEnd = startOfDay(endDate);
// Swap if start is greater than end
if (startOfDayStart > startOfDayEnd) {
[startOfDayStart, startOfDayEnd] = [startOfDayEnd, startOfDayStart];
}
// Check if the date is within the interval or is the same as the start date
return (
isSameDay(date, startOfDayStart) ||
isWithinInterval(date, {
start: startOfDayStart,
end: startOfDayEnd,
})
);
};
// Handling hovering states in date range pickers
export const isHoveringDayInRange = (
day,
startDate,
endDate,
hoveredEndDate
) => {
if (endDate && hoveredEndDate && startDate <= hoveredEndDate) {
// Ensure the start date is not after the hovered end date
return isWithinInterval(day, { start: startDate, end: hoveredEndDate });
}
return false;
};
export const isHoveringNextDayInRange = (
day,
startDate,
endDate,
hoveredEndDate
) => {
if (startDate && !endDate && hoveredEndDate) {
// If a start date is selected, and we're hovering (but haven't clicked an end date yet)
const nextDay = addDays(day, 1);
return isWithinInterval(nextDay, { start: startDate, end: hoveredEndDate });
}
if (startDate && endDate) {
// Normal range checking between selected start and end dates
const nextDay = addDays(day, 1);
return isWithinInterval(nextDay, { start: startDate, end: endDate });
}
return false;
};
// Helper func to determine active date ranges based on user selection
export const getActiveDateRange = (range, currentDate) => {
const ranges = {
last7days: () => ({
start: startOfDay(subDays(currentDate, 6)),
end: endOfDay(currentDate),
}),
last30days: () => ({
start: startOfDay(subDays(currentDate, 29)),
end: endOfDay(currentDate),
}),
last3months: () => ({
start: startOfDay(subMonths(currentDate, 3)),
end: endOfDay(currentDate),
}),
last6months: () => ({
start: startOfDay(subMonths(currentDate, 6)),
end: endOfDay(currentDate),
}),
lastYear: () => ({
start: startOfDay(subMonths(currentDate, 12)),
end: endOfDay(currentDate),
}),
thisWeek: () => ({
start: startOfDay(startOfWeek(currentDate, { weekStartsOn: 1 })),
end: endOfDay(currentDate),
}),
monthToDate: () => ({
start: startOfDay(startOfMonth(currentDate)),
end: endOfDay(currentDate),
}),
custom: () => ({ start: currentDate, end: currentDate }),
};
return (
ranges[range] || (() => ({ start: currentDate, end: currentDate }))
)();
};
export const isNavigableRange = rangeType =>
rangeType === DATE_RANGE_TYPES.MONTH_TO_DATE ||
rangeType === DATE_RANGE_TYPES.THIS_WEEK;
const WEEK_START = 1; // Monday
const getWeekRangeAtOffset = (offset, currentDate) => {
if (offset === 0) {
return {
start: startOfDay(startOfWeek(currentDate, { weekStartsOn: WEEK_START })),
end: endOfDay(currentDate),
};
}
const targetWeek = addWeeks(currentDate, offset);
return {
start: startOfDay(startOfWeek(targetWeek, { weekStartsOn: WEEK_START })),
end: endOfDay(endOfWeek(targetWeek, { weekStartsOn: WEEK_START })),
};
};
const getMonthRangeAtOffset = (offset, currentDate) => {
if (offset === 0) {
return {
start: startOfDay(startOfMonth(currentDate)),
end: endOfDay(currentDate),
};
}
const targetMonth = addMonths(currentDate, offset);
return {
start: startOfDay(startOfMonth(targetMonth)),
end: endOfDay(endOfMonth(targetMonth)),
};
};
export const getRangeAtOffset = (
rangeType,
offset,
currentDate = new Date()
) => {
if (rangeType === DATE_RANGE_TYPES.THIS_WEEK) {
return getWeekRangeAtOffset(offset, currentDate);
}
return getMonthRangeAtOffset(offset, currentDate);
};