ExpirySelect.tsx raw
1 import dayjs from "dayjs";
2 import { CalendarIcon } from "lucide-react";
3 import React from "react";
4 import { Calendar } from "src/components/ui/calendar";
5 import {
6 Popover,
7 PopoverContent,
8 PopoverTrigger,
9 } from "src/components/ui/popover";
10 import { cn } from "src/lib/utils";
11 import { expiryOptions } from "src/types";
12
13 const daysFromNow = (date?: Date) => {
14 if (!date) {
15 return undefined;
16 }
17 const now = dayjs();
18 const targetDate = dayjs(date);
19 return targetDate.diff(now, "day");
20 };
21
22 interface ExpiryProps {
23 value?: Date | undefined;
24 onChange: (expiryDate?: Date) => void;
25 }
26
27 const ExpirySelect: React.FC<ExpiryProps> = ({ value, onChange }) => {
28 const [expiryDays, setExpiryDays] = React.useState(daysFromNow(value));
29
30 const isPreset =
31 expiryDays !== undefined &&
32 Object.values(expiryOptions).includes(expiryDays);
33
34 return (
35 <>
36 <div className="grid grid-cols-3 gap-3 text-xs mb-3">
37 {Object.keys(expiryOptions).map((expiry) => {
38 return (
39 <button
40 type="button"
41 key={expiry}
42 onClick={() => {
43 const date = dayjs()
44 .add(expiryOptions[expiry], "day")
45 .endOf("day")
46 .toDate();
47 onChange(date);
48 setExpiryDays(expiryOptions[expiry]);
49 }}
50 className={cn(
51 "cursor-pointer rounded text-nowrap border-2 text-center p-3 py-4",
52 isPreset && expiryDays === expiryOptions[expiry]
53 ? "border-primary"
54 : "border-muted"
55 )}
56 >
57 {expiry}
58 </button>
59 );
60 })}
61 </div>
62 <div>
63 <Popover>
64 <PopoverTrigger asChild>
65 <button
66 type="button"
67 className="flex items-center w-full rounded-md border border-input bg-background px-3 py-2 text-sm text-left"
68 >
69 <span className={cn("flex-1", !value && "text-muted-foreground")}>
70 {value ? dayjs(value).format("DD MMMM YYYY") : "Custom date"}
71 </span>
72 <CalendarIcon className="h-4 w-4 text-muted-foreground" />
73 </button>
74 </PopoverTrigger>
75 <PopoverContent className="w-auto p-0">
76 <Calendar
77 mode="single"
78 disabled={{
79 before: new Date(),
80 }}
81 selected={value}
82 onSelect={(date?: Date) => {
83 if (!date) {
84 return;
85 }
86 date.setHours(23, 59, 59);
87 onChange(date);
88 setExpiryDays(daysFromNow(date));
89 }}
90 autoFocus
91 />
92 </PopoverContent>
93 </Popover>
94 </div>
95 </>
96 );
97 };
98
99 export default ExpirySelect;
100