Skip to content

Instantly share code, notes, and snippets.

@Makisuo
Created May 6, 2023 21:54
Show Gist options
  • Save Makisuo/be41d5d9a2b7fa1c8d82b8c4452f20ca to your computer and use it in GitHub Desktop.
Save Makisuo/be41d5d9a2b7fa1c8d82b8c4452f20ca to your computer and use it in GitHub Desktop.
Shadcn Combopicker
"use client";
import { useState } from "react";
import { format } from "date-fns";
import { CalendarIcon, Check } from "lucide-react";
import {
Select,
SelectContent,
SelectItem,
SelectTrigger,
SelectValue
} from "@/components/ui/select";
import { CustomDatePicker } from "./CustomDatePicker";
type Interval = {
name: string;
interval: string;
};
const intervals: Interval[] = [
{ name: "Last 24 hours", interval: "24h" },
{ name: "Last 7 days", interval: "7d" },
{ name: "Last 14 days", interval: "14d" },
{ name: "Last 30 days", interval: "30d" },
{ name: "Last 3 months", interval: "3m" },
{ name: "Last 6 months", interval: "6m" },
{ name: "Last 12 months", interval: "1y" }
];
export const DatePicker = () => {
const [value, setValue] = useState(intervals[0].interval);
const [dateRange, setDateRange] = useState<{ from: Date; to: Date } | undefined>(
undefined
);
return (
<Select
value={value}
onValueChange={(value) => {
setDateRange(undefined);
setValue(value);
}}
>
<SelectTrigger>
<CalendarIcon className="mr-2 h-4 w-4" />
{dateRange ? (
<>
{format(dateRange.from, "LLL dd, y")} - {format(dateRange.to, "LLL dd, y")}
</>
) : (
<SelectValue placeholder="Select a plan" />
)}
</SelectTrigger>
<SelectContent>
{intervals.map((interval) => (
<SelectItem
value={interval.interval}
key={interval.name}
>
<p className="font-medium">{interval.name}</p>
</SelectItem>
))}
<div className="relative flex w-full cursor-default select-none items-center rounded-sm py-1.5 pl-8 pr-2 text-sm outline-none hover:bg-accent hover:text-accent-foreground data-[disabled]:pointer-events-none data-[disabled]:opacity-50">
{value === "custom" && (
<span className="absolute left-2 flex h-3.5 w-3.5 items-center justify-center">
<Check className="h-4 w-4" />
</span>
)}
<CustomDatePicker
onSave={(dateRange) => {
setDateRange(dateRange);
setValue("custom");
}}
></CustomDatePicker>
</div>
</SelectContent>
</Select>
);
};
"use client";
import { useState } from "react";
import { subDays } from "date-fns";
import { DateRange } from "react-day-picker";
import { cn } from "@/lib/utils";
import { Button } from "@/components/ui/button";
import { Calendar } from "@/components/ui/calendar";
import {
Dialog,
DialogClose,
DialogContent,
DialogTrigger
} from "@/components/ui/dialog";
interface CustomDatePickerProps {
className?: string;
onSave?: (data: { from: Date; to: Date }) => void;
}
export function CustomDatePicker({ className, onSave }: CustomDatePickerProps) {
const [date, setDate] = useState<DateRange | undefined>({
from: subDays(new Date(), 20),
to: new Date()
});
return (
<div className={cn("grid gap-2", className)}>
<Dialog>
<DialogTrigger asChild>
<p className="font-medium">Custom</p>
</DialogTrigger>
<DialogContent className="w-auto sm:max-w-[1024px]">
<div className="flex flex-col gap-2">
<Calendar
initialFocus
mode="range"
defaultMonth={date?.from}
selected={date}
onSelect={setDate}
numberOfMonths={2}
/>
<div className="flex w-full flex-row justify-end gap-2">
<DialogClose asChild>
<Button variant="secondary">Cancel</Button>
</DialogClose>
<DialogClose asChild>
<Button
disabled={!date || !date.from || !date.to}
onClick={() => {
if (onSave && date && date.from && date.to) {
onSave(date as any);
}
}}
>
Save
</Button>
</DialogClose>
</div>
</div>
</DialogContent>
</Dialog>
</div>
);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment