@@ -301,6 +317,40 @@ export function SearchFiltersComponent({ filters, onFiltersChange, activeTab }:
+
+
+ updateFilter('rideDateRange', range)}
+ placeholder="Select ride opening date range"
+ disableFuture={true}
+ fromYear={1800}
+ presets={[
+ {
+ label: "Recent (last 5 years)",
+ range: {
+ from: new Date(new Date().getFullYear() - 5, 0, 1),
+ to: new Date(),
+ },
+ },
+ {
+ label: "Modern era (2000+)",
+ range: {
+ from: new Date(2000, 0, 1),
+ to: new Date(),
+ },
+ },
+ {
+ label: "Classic era (before 2000)",
+ range: {
+ from: new Date(1800, 0, 1),
+ to: new Date(1999, 11, 31),
+ },
+ },
+ ]}
+ />
+
+
@@ -382,25 +432,37 @@ export function SearchFiltersComponent({ filters, onFiltersChange, activeTab }:
-
-
- updateFilter('foundedYearMin', e.target.value ? parseInt(e.target.value) : undefined)}
- />
- updateFilter('foundedYearMax', e.target.value ? parseInt(e.target.value) : undefined)}
- />
-
+
+
updateFilter('companyDateRange', range)}
+ placeholder="Select founding date range"
+ disableFuture={true}
+ fromYear={1800}
+ presets={[
+ {
+ label: "Founded after 2000",
+ range: {
+ from: new Date(2000, 0, 1),
+ to: new Date(),
+ },
+ },
+ {
+ label: "Founded 1950-2000",
+ range: {
+ from: new Date(1950, 0, 1),
+ to: new Date(1999, 11, 31),
+ },
+ },
+ {
+ label: "Founded before 1950",
+ range: {
+ from: new Date(1800, 0, 1),
+ to: new Date(1949, 11, 31),
+ },
+ },
+ ]}
+ />
)}
diff --git a/src/components/ui/date-range-picker.tsx b/src/components/ui/date-range-picker.tsx
new file mode 100644
index 00000000..6a101346
--- /dev/null
+++ b/src/components/ui/date-range-picker.tsx
@@ -0,0 +1,182 @@
+import * as React from "react";
+import { format } from "date-fns";
+import { CalendarIcon, X } from "lucide-react";
+import type { DateRange as CalendarDateRange } from "react-day-picker";
+
+import { cn } from "@/lib/utils";
+import { Button } from "@/components/ui/button";
+import { Calendar } from "@/components/ui/calendar";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+import { Badge } from "@/components/ui/badge";
+
+export interface DateRange {
+ from?: Date;
+ to?: Date;
+}
+
+export interface DateRangePickerProps {
+ value?: DateRange;
+ onChange?: (range: DateRange | undefined) => void;
+ placeholder?: string;
+ disabled?: boolean;
+ className?: string;
+ disableFuture?: boolean;
+ disablePast?: boolean;
+ fromYear?: number;
+ toYear?: number;
+ presets?: Array<{
+ label: string;
+ range: DateRange;
+ }>;
+}
+
+const defaultPresets = [
+ {
+ label: "Today",
+ range: {
+ from: new Date(),
+ to: new Date(),
+ },
+ },
+ {
+ label: "Last 7 days",
+ range: {
+ from: new Date(Date.now() - 7 * 24 * 60 * 60 * 1000),
+ to: new Date(),
+ },
+ },
+ {
+ label: "Last 30 days",
+ range: {
+ from: new Date(Date.now() - 30 * 24 * 60 * 60 * 1000),
+ to: new Date(),
+ },
+ },
+ {
+ label: "This year",
+ range: {
+ from: new Date(new Date().getFullYear(), 0, 1),
+ to: new Date(),
+ },
+ },
+];
+
+export function DateRangePicker({
+ value,
+ onChange,
+ placeholder = "Pick a date range",
+ disabled = false,
+ className,
+ disableFuture = false,
+ disablePast = false,
+ fromYear,
+ toYear,
+ presets = defaultPresets,
+}: DateRangePickerProps) {
+ const [open, setOpen] = React.useState(false);
+
+ const handleSelect = (range: DateRange | undefined) => {
+ onChange?.(range);
+ };
+
+ const handlePresetSelect = (preset: DateRange) => {
+ handleSelect(preset);
+ setOpen(false);
+ };
+
+ const handleClear = () => {
+ handleSelect(undefined);
+ };
+
+ const getDisabledDates = (date: Date) => {
+ const now = new Date();
+ if (disableFuture && date > now) return true;
+ if (disablePast && date < now) return true;
+ return false;
+ };
+
+ const formatRange = (range: DateRange | undefined) => {
+ if (!range?.from) return placeholder;
+ if (!range.to) return format(range.from, "MMM dd, yyyy");
+ if (range.from.getTime() === range.to.getTime()) {
+ return format(range.from, "MMM dd, yyyy");
+ }
+ return `${format(range.from, "MMM dd, yyyy")} - ${format(range.to, "MMM dd, yyyy")}`;
+ };
+
+ return (
+
+
+
+
+
+
+
+
+ void}
+ numberOfMonths={2}
+ disabled={getDisabledDates}
+ className="p-3 pointer-events-auto"
+ fromYear={fromYear}
+ toYear={toYear}
+ />
+
+ {presets.length > 0 && (
+
+
Presets
+
+ {presets.map((preset, index) => (
+
+ ))}
+
+
+ )}
+
+
+
+ {value?.from && (
+
+ {formatRange(value)}
+
+ )}
+
+ );
+}
\ No newline at end of file
diff --git a/src/components/ui/month-year-picker.tsx b/src/components/ui/month-year-picker.tsx
new file mode 100644
index 00000000..ed9cbf7e
--- /dev/null
+++ b/src/components/ui/month-year-picker.tsx
@@ -0,0 +1,143 @@
+import * as React from "react";
+import { format } from "date-fns";
+import { CalendarIcon, ChevronLeft, ChevronRight } from "lucide-react";
+
+import { cn } from "@/lib/utils";
+import { Button } from "@/components/ui/button";
+import {
+ Popover,
+ PopoverContent,
+ PopoverTrigger,
+} from "@/components/ui/popover";
+import {
+ Select,
+ SelectContent,
+ SelectItem,
+ SelectTrigger,
+ SelectValue,
+} from "@/components/ui/select";
+
+export interface MonthYearPickerProps {
+ date?: Date;
+ onSelect?: (date: Date | undefined) => void;
+ placeholder?: string;
+ disabled?: boolean;
+ className?: string;
+ fromYear?: number;
+ toYear?: number;
+}
+
+export function MonthYearPicker({
+ date,
+ onSelect,
+ placeholder = "Pick month and year",
+ disabled = false,
+ className,
+ fromYear = 1800,
+ toYear = new Date().getFullYear(),
+}: MonthYearPickerProps) {
+ const [open, setOpen] = React.useState(false);
+ const [tempMonth, setTempMonth] = React.useState(date?.getMonth() ?? new Date().getMonth());
+ const [tempYear, setTempYear] = React.useState(date?.getFullYear() ?? new Date().getFullYear());
+
+ const months = [
+ "January", "February", "March", "April", "May", "June",
+ "July", "August", "September", "October", "November", "December"
+ ];
+
+ const years = Array.from(
+ { length: toYear - fromYear + 1 },
+ (_, i) => toYear - i
+ );
+
+ const handleSelect = () => {
+ const newDate = new Date(tempYear, tempMonth, 1);
+ onSelect?.(newDate);
+ setOpen(false);
+ };
+
+ const handleClear = () => {
+ onSelect?.(undefined);
+ setOpen(false);
+ };
+
+ React.useEffect(() => {
+ if (date) {
+ setTempMonth(date.getMonth());
+ setTempYear(date.getFullYear());
+ }
+ }, [date]);
+
+ return (
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ );
+}
\ No newline at end of file