Created
July 3, 2023 03:54
-
-
Save tanishqsh/6e5284b36c29c0e2effc6e187c8f911a to your computer and use it in GitHub Desktop.
DOB Calendar
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
/DOBPicker.tsx | |
**/ | |
'use client'; | |
import * as React from 'react'; | |
import { format, subYears } from 'date-fns'; | |
import { cn } from '@/lib/utils'; | |
import { Button } from '@/components/ui/button'; | |
import { Calendar } from '@/components/ui/calendar'; | |
import { buttonVariants } from '@/components/ui/button'; | |
import { Popover, PopoverContent, PopoverTrigger } from '@/components/ui/popover'; | |
export function DOBPicker({ dob, setDOB }: { dob: Date | undefined; setDOB: React.Dispatch<React.SetStateAction<Date | undefined>> }) { | |
/** | |
* The maximum date that can be selected is 18 years ago | |
*/ | |
const maxDate = subYears(new Date(), 18); | |
return ( | |
<div className="w-full"> | |
<Popover> | |
<PopoverTrigger asChild> | |
<Button | |
variant={'default'} | |
className={cn('w-full justify-start font-mono text-left font-normal bg-white/5', !dob && 'text-muted-foreground')} | |
> | |
<svg className="w-4 h-4 mr-2" fill="none" viewBox="0 0 24 24"> | |
<path | |
stroke="currentColor" | |
stroke-linecap="round" | |
stroke-linejoin="round" | |
stroke-width="1.5" | |
d="M4.75 8.75C4.75 7.64543 5.64543 6.75 6.75 6.75H17.25C18.3546 6.75 19.25 7.64543 19.25 8.75V17.25C19.25 18.3546 18.3546 19.25 17.25 19.25H6.75C5.64543 19.25 4.75 18.3546 4.75 17.25V8.75Z" | |
></path> | |
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M8 4.75V8.25"></path> | |
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M16 4.75V8.25"></path> | |
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="1.5" d="M7.75 10.75H16.25"></path> | |
</svg> | |
{dob ? format(dob, 'PPP') : <span>Date of Birth</span>} | |
</Button> | |
</PopoverTrigger> | |
<PopoverContent className="w-full p-0 font-mono text-white bg-black border border-white/10"> | |
<Calendar | |
classNames={{ | |
cell: 'text-center text-sm p-0 relative [&:has([aria-selected])]:bg-white/5 first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20', | |
day: cn( | |
buttonVariants({ variant: 'ghost' }), | |
'h-9 w-9 p-0 font-normal aria-selected:opacity-100 hover:bg-languid-lavendar/10 hover:text-white/40' | |
), | |
day_selected: 'rounded-full bg-languid-lavendar hover:bg-white/10 text-primary-foreground', | |
caption_label: 'hidden', | |
caption_dropdowns: 'flex w-full items-center justify-center space-x-2', | |
}} | |
mode="single" | |
selected={dob} | |
fromDate={subYears(new Date(), 100)} | |
toDate={maxDate} | |
captionLayout="dropdown" | |
onSelect={setDOB} | |
defaultMonth={new Date(dob?.getFullYear() ?? maxDate.getFullYear(), dob?.getMonth() ?? maxDate.getMonth(), 1)} | |
required | |
initialFocus | |
className="border rounded-md border-white/10" | |
/> | |
</PopoverContent> | |
</Popover> | |
</div> | |
); | |
} | |
export default DOBPicker; | |
/** | |
/ui/calendar.tsx | |
**/ | |
'use client'; | |
import * as React from 'react'; | |
import { ChevronLeft, ChevronRight } from 'lucide-react'; | |
import { DayPicker } from 'react-day-picker'; | |
import { cn } from '@/lib/utils'; | |
import { buttonVariants } from '@/components/ui/button'; | |
export type CalendarProps = React.ComponentProps<typeof DayPicker>; | |
function Calendar({ className, classNames, showOutsideDays = true, ...props }: CalendarProps) { | |
return ( | |
<DayPicker | |
showOutsideDays={showOutsideDays} | |
className={cn('p-3', className)} | |
classNames={{ | |
months: 'flex flex-col sm:flex-row space-y-4 sm:space-x-4 sm:space-y-0', | |
month: 'space-y-4', | |
caption: 'flex justify-center pt-1 relative items-center', | |
caption_label: 'text-sm font-medium hidden', | |
nav: 'space-x-1 flex items-center', | |
nav_button: cn(buttonVariants({ variant: 'outline' }), 'h-7 w-7 bg-transparent p-0 opacity-50 hover:opacity-100'), | |
nav_button_previous: 'absolute left-1 border border-white/20', | |
nav_button_next: 'absolute right-1 border border-white/20', | |
table: 'w-full border-collapse space-y-1', | |
head_row: 'flex', | |
head_cell: 'text-muted-foreground rounded-md w-9 font-normal text-[0.8rem]', | |
row: 'flex w-full mt-2', | |
cell: 'text-center text-sm p-0 relative [&:has([aria-selected])]:bg-accent first:[&:has([aria-selected])]:rounded-l-md last:[&:has([aria-selected])]:rounded-r-md focus-within:relative focus-within:z-20', | |
day: cn(buttonVariants({ variant: 'ghost' }), 'h-9 w-9 p-0 font-normal aria-selected:opacity-100'), | |
day_selected: | |
'bg-primary text-primary-foreground hover:bg-primary hover:text-primary-foreground focus:bg-primary focus:text-primary-foreground', | |
day_today: 'bg-accent text-accent-foreground', | |
day_outside: 'text-muted-foreground opacity-50', | |
day_disabled: 'text-muted-foreground opacity-50', | |
day_range_middle: 'aria-selected:bg-accent aria-selected:text-accent-foreground', | |
day_hidden: 'invisible', | |
...classNames, | |
}} | |
components={{ | |
Dropdown: ({ ...props }) => ( | |
<div className="w-full"> | |
<select | |
autoFocus | |
{...props} | |
className="w-full px-1 py-2 space-x-4 text-sm text-white transition-all duration-300 rounded-md outline-none bg-white/5 hover:bg-white/10 focus-outline:none" | |
/> | |
</div> | |
), | |
IconLeft: ({ ...props }) => <ChevronLeft className="w-4 h-4" />, | |
IconRight: ({ ...props }) => <ChevronRight className="w-4 h-4" />, | |
}} | |
{...props} | |
/> | |
); | |
} | |
Calendar.displayName = 'Calendar'; | |
export { Calendar }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment