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