'use client';
import * as React from 'react';
import {
ChevronLeft,
ChevronRight,
Landmark,
CalendarDays,
CircleDollarSign,
Tag,
UserRound,
} from 'lucide-react';
import { Label as ReactAriaLabel } from 'react-aria-components';
import { type DateRange } from 'react-day-picker';
import { inputVariants } from '@/components/ui/input';
import * as Label from '@/components/ui/label';
import {
Actions,
FilterSidebar,
} from '@/components/blocks/filter/filter-popover-parts';
import { cn } from '@/utils/cn';
const MONTH_NAMES = [
'Jan',
'Feb',
'Mar',
'Apr',
'May',
'Jun',
'Jul',
'Aug',
'Sep',
'Oct',
'Nov',
'Dec',
];
const FILTER_TYPES = [
{ icon: , label: 'Date' },
{ icon: , label: 'Customers' },
{ icon: , label: 'Amount' },
{ icon: , label: 'Categories' },
{ icon: , label: 'Accounts' },
];
type MonthButtonProps = {
month: string;
monthIndex: number;
year: number;
onClick: (index: number) => void;
className: string;
};
type DateSelectorProps = {
label: string;
selectedDate?: Date;
year: number;
onYearChange: (increment: number) => void;
onMonthClick: (monthIndex: number) => void;
getMonthClassName: (year: number, monthIndex: number) => string;
};
type DividerProps = {
className?: string;
};
const MonthButton = ({
month,
monthIndex,
onClick,
className,
}: MonthButtonProps) => (
);
const VerticalDivider = ({ className }: DividerProps) => (
);
const HorizontalDivider = ({ className }: DividerProps) => (
);
const MonthCalendar = ({
year,
onYearChange,
onMonthClick,
getMonthClassName,
}: {
year: number;
onYearChange: (increment: number) => void;
onMonthClick: (monthIndex: number) => void;
getMonthClassName: (year: number, monthIndex: number) => string;
}) => (
{year}
{MONTH_NAMES.map((month, index) => (
))}
);
const DateSelector = ({
label,
selectedDate,
year,
onYearChange,
onMonthClick,
getMonthClassName,
}: DateSelectorProps) => {
const { root, wrapper } = inputVariants();
return (
{/* Header */}
{label}
{selectedDate ? (
{new Date(selectedDate).toLocaleDateString('en-US', {
month: 'short',
})}
{', '}
{new Date(selectedDate).getFullYear()}
) : (
MM / YYYY
)}
{/* Calendar */}
);
};
const useDateFilter = () => {
const [range, setRange] = React.useState({
from: new Date(2024, 4, 1),
to: new Date(2025, 1, 1),
});
// Year values
const [fromYear, setFromYear] = React.useState(2024);
const [toYear, setToYear] = React.useState(2025);
const selectMonth = (year: number, monthIndex: number) => {
// If clicking on already selected month, deselect it
if (
(range.from &&
range.from.getFullYear() === year &&
range.from.getMonth() === monthIndex) ||
(range.to &&
range.to.getFullYear() === year &&
range.to.getMonth() === monthIndex)
) {
if (
range.from &&
range.from.getFullYear() === year &&
range.from.getMonth() === monthIndex
) {
setRange((prev) => ({
...prev,
from: undefined,
}));
}
if (
range.to &&
range.to.getFullYear() === year &&
range.to.getMonth() === monthIndex
) {
setRange((prev) => ({
...prev,
to: undefined,
}));
}
return;
}
// Set new date range
if (!range.from || (range.from && range.to)) {
// Start a new range
setRange({
from: new Date(year, monthIndex, 1),
to: undefined,
});
} else if (range.from && !range.to) {
// Complete the range
const firstDate = range.from.getTime();
const secondDate = new Date(year, monthIndex, 1).getTime();
if (secondDate < firstDate) {
setRange({
from: new Date(year, monthIndex, 1),
to: range.from,
});
} else {
setRange({
from: range.from,
to: new Date(year, monthIndex, 1),
});
}
}
};
const handleCalendarClick = (year: number, monthIndex: number) => {
selectMonth(year, monthIndex);
};
const changeYear = (
currentYear: number,
setYearFn: React.Dispatch>,
dateType: 'from' | 'to',
increment: number,
) => {
const newYear = currentYear + increment;
setYearFn(newYear);
const selectedDate = dateType === 'from' ? range.from : range.to;
if (selectedDate && selectedDate.getFullYear() === currentYear) {
const month = selectedDate.getMonth();
setRange((prev) => ({
...prev,
[dateType]: new Date(newYear, month, 1),
}));
}
};
const changeFromYear = (increment: number) => {
changeYear(fromYear, setFromYear, 'from', increment);
};
const changeToYear = (increment: number) => {
changeYear(toYear, setToYear, 'to', increment);
};
const handleClear = () => {
const now = new Date();
setFromYear(now.getFullYear());
setToYear(now.getFullYear());
setRange({
from: now,
to: now,
});
};
const isMonthInRange = (year: number, month: number): boolean => {
if (!range.from && !range.to) return false;
if (range.from && !range.to) {
return (
range.from.getFullYear() === year && range.from.getMonth() === month
);
}
if (!range.from && range.to) {
return range.to.getFullYear() === year && range.to.getMonth() === month;
}
if (range.from && range.to) {
const fromTime = new Date(
range.from.getFullYear(),
range.from.getMonth(),
1,
).getTime();
const toTime = new Date(
range.to.getFullYear(),
range.to.getMonth(),
1,
).getTime();
const currentTime = new Date(year, month, 1).getTime();
return currentTime >= fromTime && currentTime <= toTime;
}
return false;
};
const getMonthClassName = (year: number, month: number): string => {
const isFrom =
range.from &&
range.from.getFullYear() === year &&
range.from.getMonth() === month;
const isTo =
range.to &&
range.to.getFullYear() === year &&
range.to.getMonth() === month;
const isInRange = isMonthInRange(year, month);
const columnIndex = month % 3;
const isLeftEdge = columnIndex === 0;
const isRightEdge = columnIndex === 2;
const colorClasses =
isFrom || isTo
? 'bg-information-light text-information-dark'
: isInRange
? 'bg-information-lighter text-information-dark'
: 'text-text-sub-600 hover:bg-bg-weak-50';
let borderClasses = '';
if (isFrom && isTo) {
borderClasses = 'rounded-md';
} else if (isFrom) {
borderClasses = 'rounded-l-lg rounded-r-none';
} else if (isTo) {
borderClasses = 'rounded-r-lg rounded-l-none';
} else if (isInRange) {
borderClasses = isLeftEdge
? 'rounded-l-lg rounded-r-none'
: isRightEdge
? 'rounded-r-lg rounded-l-none'
: 'rounded-none';
} else {
borderClasses = 'rounded-md';
}
return `${colorClasses} ${borderClasses}`;
};
return {
range,
fromYear,
toYear,
changeFromYear,
changeToYear,
handleCalendarClick,
handleClear,
getMonthClassName,
};
};
// Main Component
export default function DateFilterPopover() {
const [activeFilter, setActiveFilter] = React.useState('Date');
const {
range,
fromYear,
toYear,
changeFromYear,
changeToYear,
handleCalendarClick,
handleClear,
getMonthClassName,
} = useDateFilter();
return (
{/* Content */}
{/* Header */}
{/* Date Range Selector */}
{/* From Calendar */}
handleCalendarClick(fromYear, monthIndex)
}
getMonthClassName={getMonthClassName}
/>
{/* Dividers */}
{/* To Calendar */}
handleCalendarClick(toYear, monthIndex)
}
getMonthClassName={getMonthClassName}
/>
);
}