Skip to content

Commit

Permalink
Merge pull request #56 from Informatik-Projekt-Kurs/IPK-219-Avoid-ref…
Browse files Browse the repository at this point in the history
…etching-user-data-in-Dashboard

IPK-219 feat: moved user fetching into layout
  • Loading branch information
bencodes07 authored May 25, 2024
2 parents cb4715e + ec81da3 commit 0b6dec1
Show file tree
Hide file tree
Showing 7 changed files with 299 additions and 330 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,6 @@ bun.lockb

.env.development
.env.production
.env.local
.env.local

sitemap.xml
273 changes: 125 additions & 148 deletions src/app/dashboard/bookings/page.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
"use client";
import Image from "next/image";
import React, { useEffect, useState } from "react";
import type { User } from "@/types";
import { deleteToken, getAccessToken, getUser } from "@/lib/actions";
import { deleteToken } from "@/lib/actions";
import { Input } from "@/components/ui/input";
import {
DropdownMenu,
Expand Down Expand Up @@ -41,10 +39,10 @@ import {
import { Progress } from "@/components/ui/progress";
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from "@/components/ui/select";
import { Calendar } from "@/components/ui/calendar";
import { useDashboardData } from "@/components/dashboard/DashboardContext";

function Bookings() {
const [user, setUser] = useState<User | null>();
const [loading, setLoading] = useState(true);
const user = useDashboardData().user;
const [searchQuery, setSearchQuery] = useState("");
const [events, setEvents] = useState<
Array<{ Id: number; Subject: string; Location: string; StartTime: Date; EndTime: Date; RecurrenceRule: string }>
Expand Down Expand Up @@ -90,20 +88,7 @@ function Bookings() {
});

useEffect(() => {
const fetchUser = async () => {
setLoading(true);
try {
const accessToken = await getAccessToken();
const fetchedUser = await getUser(accessToken);
setUser(fetchedUser);
setLoading(false);
} catch (error) {
console.error("Failed to fetch user", error);
setLoading(false);
}
if (false) setEvents([]); // This is a dummy condition to avoid unused variable warning (events)
};
fetchUser().catch(console.error);
if (false) setEvents([]); // This is a dummy condition to avoid unused variable warning (events)
}, []);

const [bookingResult, setBookingResult] = useState<{ company: string; date: Date | undefined; time: string }>({
Expand Down Expand Up @@ -190,139 +175,131 @@ function Bookings() {
}
};

if (loading)
return (
<div className="flex h-[calc(100%-32px)] flex-col items-center justify-center p-8 px-6">
<div className="flex size-20 animate-spin items-center justify-center rounded-[50%] border-4 border-x-background border-b-background border-t-primary bg-transparent"></div>
<Image className={"absolute"} src={"/landingLogo.png"} alt={""} width={40} height={40} />
</div>
);
else
return (
<div className="flex h-[calc(100%-32px)] flex-col items-start justify-start p-8 px-6">
<header className="flex w-full flex-row items-center justify-between">
<h1 className="m-4 font-medium text-foreground md:text-2xl">Bookings</h1>
<div className="flex items-center gap-x-6">
<Input
className="w-[320px]"
placeholder="Search"
value={searchQuery}
onChange={(e) => {
setSearchQuery(e.target.value);
}}></Input>
<DropdownMenu modal={false}>
<DropdownMenuTrigger className={"mr-4"}>
<Button variant="ghost" className="relative size-8 rounded-full">
<Avatar className="size-10">
<AvatarFallback className={"bg-primary"}>{extractNameInitials(user?.name)}</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align={"end"} className={"w-56 border-border"}>
<DropdownMenuLabel className="font-normal">
<div className="flex flex-col space-y-1">
<p className="text-sm font-medium leading-none">{user?.name}</p>
<p className="text-xs leading-none text-muted-foreground">{user?.email}</p>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={() => {
router.push("/dashboard/settings");
}}>
Settings
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={logout} className={"text-red-500"}>
Log out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</header>
<div className={"mt-2 flex w-full items-center justify-between pl-4 text-foreground"}>
Your Appointments at a glance. Book a new appointment now!
<div className={"flex w-fit items-center justify-center gap-x-4 text-foreground"}>
<AlertDialog>
<AlertDialogTrigger>
<Button variant={"secondary"}>
<FaRegCircleQuestion className={"mr-1 font-bold"} />
Help
</Button>
</AlertDialogTrigger>
<AlertDialogContent className={"border-border text-foreground"}>
<AlertDialogHeader>
<AlertDialogTitle>You need help?</AlertDialogTitle>
<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]"}>&quot;boeckmannben{"<at>"}gmail.com&quot;</a>.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter className={"text-foreground"}>
<AlertDialogCancel>Close</AlertDialogCancel>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<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
return (
<div className="flex h-[calc(100%-32px)] flex-col items-start justify-start p-8 px-6">
<header className="flex w-full flex-row items-center justify-between">
<h1 className="m-4 font-medium text-foreground md:text-2xl">Bookings</h1>
<div className="flex items-center gap-x-6">
<Input
className="w-[320px]"
placeholder="Search"
value={searchQuery}
onChange={(e) => {
setSearchQuery(e.target.value);
}}></Input>
<DropdownMenu modal={false}>
<DropdownMenuTrigger className={"mr-4"}>
<Button variant="ghost" className="relative size-8 rounded-full">
<Avatar className="size-10">
<AvatarFallback className={"bg-primary"}>{extractNameInitials(user?.name)}</AvatarFallback>
</Avatar>
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align={"end"} className={"w-56 border-border"}>
<DropdownMenuLabel className="font-normal">
<div className="flex flex-col space-y-1">
<p className="text-sm font-medium leading-none">{user?.name}</p>
<p className="text-xs leading-none text-muted-foreground">{user?.email}</p>
</div>
</DropdownMenuLabel>
<DropdownMenuSeparator />
<DropdownMenuItem
onClick={() => {
router.push("/dashboard/settings");
}}>
Settings
</DropdownMenuItem>
<DropdownMenuSeparator />
<DropdownMenuItem onClick={logout} className={"text-red-500"}>
Log out
</DropdownMenuItem>
</DropdownMenuContent>
</DropdownMenu>
</div>
</header>
<div className={"mt-2 flex w-full items-center justify-between pl-4 text-foreground"}>
Your Appointments at a glance. Book a new appointment now!
<div className={"flex w-fit items-center justify-center gap-x-4 text-foreground"}>
<AlertDialog>
<AlertDialogTrigger>
<Button variant={"secondary"}>
<FaRegCircleQuestion className={"mr-1 font-bold"} />
Help
</Button>
</AlertDialogTrigger>
<AlertDialogContent className={"border-border text-foreground"}>
<AlertDialogHeader>
<AlertDialogTitle>You need help?</AlertDialogTitle>
<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]"}>&quot;boeckmannben{"<at>"}gmail.com&quot;</a>.
</AlertDialogDescription>
</AlertDialogHeader>
<AlertDialogFooter className={"text-foreground"}>
<AlertDialogCancel>Close</AlertDialogCancel>
</AlertDialogFooter>
</AlertDialogContent>
</AlertDialog>
<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) => (
<SelectItem key={content} 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>
</div>
<Progress className={"mt-3 h-1"} value={bookingContent.progress} />
</DialogClose>
<Button onClick={updateBookingProgress} className={"text-foreground"}>
Next
</Button>
</div>
</DialogFooter>
</DialogContent>
</Dialog>
</div>
</div>
<div className="mt-4 flex h-fit w-full rounded-[20px] bg-subtle p-6">
<Scheduler openingHours={{ open: "13:00", close: "19:00" }} data={filteredEvents} />
<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">
<Scheduler openingHours={{ open: "13:00", close: "19:00" }} data={filteredEvents} />
</div>
</div>
);
}

export default Bookings;
Loading

0 comments on commit 0b6dec1

Please sign in to comment.