mirror of
https://github.com/lingble/chatwoot.git
synced 2025-11-02 03:57:52 +00:00
* feat: Custom date picker * chore: Calender footer * chore: Minor fix * chore: Reset date picker * chore: Minor fix * feat: Toggle button * chore: Clean up * chore: Use font inter * chore: Cleanup and fix bugs * fix: custom date range reset the calendar * chore: fix logic bug * feat: Add manual date range * fix: styles in rtl * chore: Helper specs * chore: Clean up * chore: Review fixes * chore: remove magic strings * chore: Add comments * chore: Review fixes * chore: Clean up * chore: remove magic strings * fix: Use outline instead of border * chore: Minor style fix * chore: disable pointer events for the disabled dates * chore: Fix code climate --------- Co-authored-by: Shivam Mishra <scm.mymail@gmail.com>
220 lines
5.9 KiB
JavaScript
220 lines
5.9 KiB
JavaScript
import {
|
|
startOfDay,
|
|
subDays,
|
|
endOfDay,
|
|
subMonths,
|
|
addMonths,
|
|
subYears,
|
|
addYears,
|
|
startOfMonth,
|
|
isSameMonth,
|
|
format,
|
|
startOfWeek,
|
|
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',
|
|
},
|
|
{
|
|
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.CUSTOM_RANGE', value: 'custom' },
|
|
];
|
|
|
|
export const DATE_RANGE_TYPES = {
|
|
LAST_7_DAYS: 'last7days',
|
|
LAST_30_DAYS: 'last30days',
|
|
LAST_3_MONTHS: 'last3months',
|
|
LAST_6_MONTHS: 'last6months',
|
|
LAST_YEAR: 'lastYear',
|
|
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),
|
|
}),
|
|
custom: () => ({ start: currentDate, end: currentDate }),
|
|
};
|
|
|
|
return (
|
|
ranges[range] || (() => ({ start: currentDate, end: currentDate }))
|
|
)();
|
|
};
|