Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 | 1x 1x 1x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 8x 1x 1x 1x 1x 8x 8x 8x 8x 20x 20x 4x 4x 4x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 20x 7x 7x 42x 42x 42x 42x 7x 35x 42x 42x 42x 7x 7x 20x 20x | import { Clock } from 'lucide-react';
import { FC, useEffect, useRef, useState } from 'react';
export type TimeRange = 'day' | 'last24h' | '2days' | 'week' | 'month' | 'all';
interface TimeFilterProps {
selectedRange: TimeRange;
onChange: (range: TimeRange) => void;
className?: string;
}
export const TimeFilter: FC<TimeFilterProps> = ({
selectedRange,
onChange,
className = ''
}) => {
const [isOpen, setIsOpen] = useState(false);
const dropdownRef = useRef<HTMLDivElement>(null);
const options: { value: TimeRange; label: string }[] = [
{ value: 'day', label: 'Today' },
{ value: 'last24h', label: 'Last day' },
{ value: '2days', label: 'Last 2 days' },
{ value: 'week', label: 'This week' },
{ value: 'month', label: 'This month' },
{ value: 'all', label: 'All time' },
];
const selectedLabel = options.find(opt => opt.value === selectedRange)?.label || 'All time';
// Close dropdown when clicking outside
useEffect(() => {
const handleClickOutside = (event: MouseEvent) => {
if (dropdownRef.current && !dropdownRef.current.contains(event.target as Node)) {
setIsOpen(false);
}
};
document.addEventListener('mousedown', handleClickOutside);
return () => {
document.removeEventListener('mousedown', handleClickOutside);
};
}, []);
const handleSelect = (range: TimeRange) => {
onChange(range);
setIsOpen(false);
};
return (
<div className={`relative ${className}`} ref={dropdownRef}>
<button
onClick={() => setIsOpen(!isOpen)}
className="flex items-center gap-1 px-2 py-1.5 text-sm text-gray-600 hover:bg-gray-100 hover:text-gray-800 rounded-full transition-colors duration-200"
aria-haspopup="true"
aria-expanded={isOpen}
>
<Clock className="h-4 w-4" />
<span className="ml-1">{selectedLabel}</span>
</button>
{isOpen && (
<div className="absolute left-0 mt-1 w-40 bg-white rounded-md shadow-lg py-1 z-10 border border-gray-200">
{options.map((option) => (
<button
key={option.value}
onClick={() => handleSelect(option.value)}
className={`w-full text-left px-4 py-2 text-sm ${selectedRange === option.value
? 'bg-primary-50 text-primary-700'
: 'text-gray-700 hover:bg-gray-100'
}`}
>
{option.label}
</button>
))}
</div>
)}
</div>
);
};
|