-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: form functionality added to booking
- Loading branch information
1 parent
a4584d2
commit 68a2c77
Showing
5 changed files
with
450 additions
and
6 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,19 @@ import { | |
AlertDialogTitle, | ||
AlertDialogTrigger | ||
} from "@/components/ui/alert-dialog"; | ||
import { | ||
Dialog, | ||
DialogClose, | ||
DialogContent, | ||
DialogDescription, | ||
DialogFooter, | ||
DialogHeader, | ||
DialogTitle, | ||
DialogTrigger | ||
} from "@/components/ui/dialog"; | ||
import { Progress } from "@/components/ui/progress"; | ||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select"; | ||
import { Calendar } from "@/components/ui/calendar"; | ||
|
||
function Bookings() { | ||
const [user, setUser] = useState<User | null>(); | ||
|
@@ -59,6 +72,23 @@ function Bookings() { | |
|
||
const router = useRouter(); | ||
|
||
const [select, setSelect] = useState(""); | ||
const [date, setDate] = useState<Date | undefined>(new Date()); | ||
|
||
const [bookingMode, setBookingMode] = useState(0); | ||
const [bookingContent, setBookingContent] = useState({ | ||
title: "Select your company", | ||
description: "With which company do you want to book this appointment?", | ||
select: { | ||
active: true, | ||
content: ["Github", "Böckmann GmbH", "MeetMate"] | ||
}, | ||
calendar: { | ||
active: false | ||
}, | ||
progress: 33 | ||
}); | ||
|
||
useEffect(() => { | ||
const fetchUser = async () => { | ||
setLoading(true); | ||
|
@@ -76,10 +106,80 @@ function Bookings() { | |
fetchUser().catch(console.error); | ||
}, []); | ||
|
||
const [bookingResult, setBookingResult] = useState<{ company: string; date: Date | undefined; time: string }>({ | ||
company: "", | ||
date: new Date(), | ||
time: "" | ||
}); | ||
|
||
useEffect(() => { | ||
setFilteredEvents(events.filter((event) => event.Subject.toLowerCase().includes(searchQuery.toLowerCase()))); | ||
}, [searchQuery, events]); | ||
|
||
function updateBookingProgress() { | ||
if (bookingMode === 1 && select !== "") { | ||
setBookingResult({ ...bookingResult, company: select }); | ||
setSelect(""); | ||
setBookingContent({ | ||
title: "Select your Date", | ||
description: "When would you like to book this appointment?", | ||
select: { | ||
active: false, | ||
content: ["13:00 - 14:00", "15:00 - 16:00", "19:00 - 20:30"] | ||
}, | ||
calendar: { | ||
active: true | ||
}, | ||
progress: 66 | ||
}); | ||
setBookingMode(bookingMode + 1); | ||
} else if (bookingMode === 2) { | ||
setBookingResult({ ...bookingResult, date }); | ||
setBookingContent({ | ||
title: "Select your Slot", | ||
description: "At what time would you like to book this appointment?", | ||
select: { | ||
active: true, | ||
content: ["13:00 - 14:00", "15:00 - 16:00", "19:00 - 20:30"] | ||
}, | ||
calendar: { | ||
active: false | ||
}, | ||
progress: 80 | ||
}); | ||
setBookingMode(bookingMode + 1); | ||
} else if (bookingMode === 3 && select !== "") { | ||
setBookingResult({ ...bookingResult, time: select }); | ||
setBookingContent({ | ||
title: "Success", | ||
description: "Your appointment was successfully booked", | ||
select: { | ||
active: false, | ||
content: ["13:00 - 14:00", "15:00 - 16:00", "19:00 - 20:30"] | ||
}, | ||
calendar: { | ||
active: false | ||
}, | ||
progress: 100 | ||
}); | ||
console.log(bookingResult); | ||
} else if (bookingMode === 0) { | ||
setBookingContent({ | ||
title: "Select your company", | ||
description: "With which company do you want to book this appointment?", | ||
select: { | ||
active: true, | ||
content: ["Github", "Böckmann GmbH", "MeetMate"] | ||
}, | ||
calendar: { | ||
active: false | ||
}, | ||
progress: 33 | ||
}); | ||
setBookingMode(1); | ||
} | ||
} | ||
|
||
const logout = async () => { | ||
try { | ||
await deleteToken(); | ||
|
@@ -150,10 +250,10 @@ function Bookings() { | |
Help | ||
</Button> | ||
</AlertDialogTrigger> | ||
<AlertDialogContent> | ||
<AlertDialogContent className={"border-border text-foreground"}> | ||
<AlertDialogHeader> | ||
<AlertDialogTitle>You need help?</AlertDialogTitle> | ||
<AlertDialogDescription className={"flex flex-wrap gap-x-2"}> | ||
<AlertDialogDescription className={"flex flex-wrap gap-2"}> | ||
If you need any help or would like to request a new feature contact{" "} | ||
<a href={"mailto:[email protected]"}>"boeckmannben{"<at>"}gmail.com"</a>. | ||
</AlertDialogDescription> | ||
|
@@ -163,10 +263,59 @@ function Bookings() { | |
</AlertDialogFooter> | ||
</AlertDialogContent> | ||
</AlertDialog> | ||
<Button className={"text-foreground"}> | ||
<FaPlus className={"mr-1"} /> | ||
Book Appointment | ||
</Button> | ||
<Dialog> | ||
<DialogTrigger> | ||
<Button | ||
onClick={() => { | ||
setBookingMode(0); | ||
setSelect(""); | ||
}} | ||
className={"text-foreground"}> | ||
<FaPlus className={"mr-1"} /> | ||
Book Appointment | ||
</Button> | ||
</DialogTrigger> | ||
<DialogContent className={"border-border text-foreground"}> | ||
<DialogHeader className={"gap-y-3"}> | ||
<DialogTitle>{bookingContent.title}</DialogTitle> | ||
<DialogDescription>{bookingContent.description}</DialogDescription> | ||
<Select onValueChange={setSelect}> | ||
<SelectTrigger style={{ display: bookingContent.select.active ? "flex" : "none" }}> | ||
<SelectValue placeholder="Select" /> | ||
</SelectTrigger> | ||
<SelectContent className={"border-border"}> | ||
{bookingContent.select.content.map((content, index) => ( | ||
<SelectItem key={index} value={content}> | ||
{content} | ||
</SelectItem> | ||
))} | ||
</SelectContent> | ||
</Select> | ||
<Calendar | ||
mode="single" | ||
className="rounded-md" | ||
selected={date} | ||
onSelect={setDate} | ||
style={{ display: bookingContent.calendar.active ? "block" : "none" }} | ||
/> | ||
</DialogHeader> | ||
<DialogFooter> | ||
<div className={"flex w-full flex-col"}> | ||
<div className={"flex justify-end gap-x-4"}> | ||
<DialogClose asChild> | ||
<Button type="button" variant="secondary"> | ||
Cancel | ||
</Button> | ||
</DialogClose> | ||
<Button onClick={updateBookingProgress} className={"text-foreground"}> | ||
Next | ||
</Button> | ||
</div> | ||
<Progress className={"mt-3 h-1"} value={bookingContent.progress} /> | ||
</div> | ||
</DialogFooter> | ||
</DialogContent> | ||
</Dialog> | ||
</div> | ||
</div> | ||
<div className="mt-4 flex h-fit w-full rounded-[20px] bg-subtle p-6"> | ||
|
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,56 @@ | ||
"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", | ||
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", | ||
nav_button_next: "absolute right-1", | ||
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: "h-9 w-9 text-center text-sm p-0 relative [&:has([aria-selected].day-range-end)]:rounded-r-md [&:has([aria-selected].day-outside)]:bg-accent/50 [&: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_range_end: "day-range-end", | ||
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: | ||
"day-outside text-muted-foreground opacity-50 aria-selected:bg-accent/50 aria-selected:text-muted-foreground aria-selected:opacity-30", | ||
day_disabled: "text-muted-foreground opacity-50", | ||
day_range_middle: "aria-selected:bg-accent aria-selected:text-accent-foreground", | ||
day_hidden: "invisible", | ||
...classNames | ||
}} | ||
components={{ | ||
IconLeft: () => <ChevronLeft className="size-4" />, | ||
IconRight: () => <ChevronRight className="size-4" /> | ||
}} | ||
{...props} | ||
/> | ||
); | ||
} | ||
Calendar.displayName = "Calendar"; | ||
|
||
export { Calendar }; |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
"use client"; | ||
|
||
import * as React from "react"; | ||
import * as DialogPrimitive from "@radix-ui/react-dialog"; | ||
import { X } from "lucide-react"; | ||
|
||
import { cn } from "@/lib/utils"; | ||
|
||
const Dialog = DialogPrimitive.Root; | ||
|
||
const DialogTrigger = DialogPrimitive.Trigger; | ||
|
||
const DialogPortal = DialogPrimitive.Portal; | ||
|
||
const DialogClose = DialogPrimitive.Close; | ||
|
||
const DialogOverlay = React.forwardRef< | ||
React.ElementRef<typeof DialogPrimitive.Overlay>, | ||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Overlay> | ||
>(({ className, ...props }, ref) => ( | ||
<DialogPrimitive.Overlay | ||
ref={ref} | ||
className={cn( | ||
"fixed inset-0 z-50 bg-black/80 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0", | ||
className | ||
)} | ||
{...props} | ||
/> | ||
)); | ||
DialogOverlay.displayName = DialogPrimitive.Overlay.displayName; | ||
|
||
const DialogContent = React.forwardRef< | ||
React.ElementRef<typeof DialogPrimitive.Content>, | ||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Content> | ||
>(({ className, children, ...props }, ref) => ( | ||
<DialogPortal> | ||
<DialogOverlay /> | ||
<DialogPrimitive.Content | ||
ref={ref} | ||
className={cn( | ||
"fixed left-[50%] top-[50%] z-50 grid w-full max-w-lg translate-x-[-50%] translate-y-[-50%] gap-4 border bg-background p-6 shadow-lg duration-200 data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 data-[state=closed]:slide-out-to-left-1/2 data-[state=closed]:slide-out-to-top-[48%] data-[state=open]:slide-in-from-left-1/2 data-[state=open]:slide-in-from-top-[48%] sm:rounded-lg", | ||
className | ||
)} | ||
{...props}> | ||
{children} | ||
<DialogPrimitive.Close className="absolute right-4 top-4 rounded-sm opacity-70 ring-offset-background transition-opacity hover:opacity-100 focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 disabled:pointer-events-none data-[state=open]:bg-accent data-[state=open]:text-muted-foreground"> | ||
<X className="size-4" /> | ||
<span className="sr-only">Close</span> | ||
</DialogPrimitive.Close> | ||
</DialogPrimitive.Content> | ||
</DialogPortal> | ||
)); | ||
DialogContent.displayName = DialogPrimitive.Content.displayName; | ||
|
||
const DialogHeader = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( | ||
<div className={cn("flex flex-col space-y-1.5 text-center sm:text-left", className)} {...props} /> | ||
); | ||
DialogHeader.displayName = "DialogHeader"; | ||
|
||
const DialogFooter = ({ className, ...props }: React.HTMLAttributes<HTMLDivElement>) => ( | ||
<div className={cn("flex flex-col-reverse sm:flex-row sm:justify-end sm:space-x-2", className)} {...props} /> | ||
); | ||
DialogFooter.displayName = "DialogFooter"; | ||
|
||
const DialogTitle = React.forwardRef< | ||
React.ElementRef<typeof DialogPrimitive.Title>, | ||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Title> | ||
>(({ className, ...props }, ref) => ( | ||
<DialogPrimitive.Title | ||
ref={ref} | ||
className={cn("text-lg font-semibold leading-none tracking-tight", className)} | ||
{...props} | ||
/> | ||
)); | ||
DialogTitle.displayName = DialogPrimitive.Title.displayName; | ||
|
||
const DialogDescription = React.forwardRef< | ||
React.ElementRef<typeof DialogPrimitive.Description>, | ||
React.ComponentPropsWithoutRef<typeof DialogPrimitive.Description> | ||
>(({ className, ...props }, ref) => ( | ||
<DialogPrimitive.Description ref={ref} className={cn("text-sm text-muted-foreground", className)} {...props} /> | ||
)); | ||
DialogDescription.displayName = DialogPrimitive.Description.displayName; | ||
|
||
export { | ||
Dialog, | ||
DialogPortal, | ||
DialogOverlay, | ||
DialogClose, | ||
DialogTrigger, | ||
DialogContent, | ||
DialogHeader, | ||
DialogFooter, | ||
DialogTitle, | ||
DialogDescription | ||
}; |
Oops, something went wrong.