diff --git a/package.json b/package.json index 4a5c727..7ea5f82 100644 --- a/package.json +++ b/package.json @@ -35,6 +35,7 @@ "@commitlint/config-conventional": "^18.6.0", "@hookform/resolvers": "^3.3.4", "@next/eslint-plugin-next": "^14.1.0", + "@radix-ui/react-alert-dialog": "^1.0.5", "@radix-ui/react-avatar": "^1.0.4", "@radix-ui/react-checkbox": "^1.0.4", "@radix-ui/react-dropdown-menu": "^2.0.6", diff --git a/src/app/dashboard/bookings/page.tsx b/src/app/dashboard/bookings/page.tsx index 2b0c1df..dbee326 100644 --- a/src/app/dashboard/bookings/page.tsx +++ b/src/app/dashboard/bookings/page.tsx @@ -17,12 +17,45 @@ import { Avatar, AvatarFallback } from "@/components/ui/avatar"; import { extractNameInitials } from "@/lib/utils"; import { useRouter } from "next/navigation"; import Scheduler from "@/components/dashboard/scheduler/Scheduler"; -import { FaPlus } from "react-icons/fa6"; -import { FiFilter } from "react-icons/fi"; +import { FaPlus, FaRegCircleQuestion } from "react-icons/fa6"; +import { + AlertDialog, + AlertDialogCancel, + AlertDialogContent, + AlertDialogDescription, + AlertDialogFooter, + AlertDialogHeader, + AlertDialogTitle, + AlertDialogTrigger +} from "@/components/ui/alert-dialog"; function Bookings() { const [user, setUser] = useState(); const [loading, setLoading] = useState(true); + const [searchQuery, setSearchQuery] = useState(""); + const [events, setEvents] = useState< + Array<{ Id: number; Subject: string; Location: string; StartTime: Date; EndTime: Date; RecurrenceRule: string }> + >([ + { + Id: 1, + Subject: "Scrum Meeting", + Location: "Office", + StartTime: new Date(2024, 4, 6, 14, 30), + EndTime: new Date(2024, 4, 6, 15, 30), + RecurrenceRule: "" + }, + { + Id: 2, + Subject: "Scrum Meeting", + Location: "Office", + StartTime: new Date(2024, 4, 8, 17, 30), + EndTime: new Date(2024, 4, 8, 18, 30), + RecurrenceRule: "" + } + ]); + const [filteredEvents, setFilteredEvents] = useState< + Array<{ Id: number; Subject: string; Location: string; StartTime: Date; EndTime: Date; RecurrenceRule: string }> + >([]); const router = useRouter(); @@ -38,10 +71,15 @@ function Bookings() { 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); }, []); + useEffect(() => { + setFilteredEvents(events.filter((event) => event.Subject.toLowerCase().includes(searchQuery.toLowerCase()))); + }, [searchQuery, events]); + const logout = async () => { try { await deleteToken(); @@ -65,9 +103,13 @@ function Bookings() {

Bookings

- + { setSearchQuery(e.target.value); }}> - + + + + + + + + You need help? + + Contact
"boeckmannben{""}gmail.com"
for help +
+
+ + Close + +
+
- +
); diff --git a/src/components/dashboard/scheduler/Scheduler.tsx b/src/components/dashboard/scheduler/Scheduler.tsx index 0818e1b..1c44cfe 100644 --- a/src/components/dashboard/scheduler/Scheduler.tsx +++ b/src/components/dashboard/scheduler/Scheduler.tsx @@ -5,26 +5,11 @@ import { registerLicense } from "@syncfusion/ej2-base"; import { Button } from "@/components/ui/button"; import { FaArrowRight, FaArrowLeft } from "react-icons/fa6"; -function Scheduler() { - const data = [ - { - Id: 1, - Subject: "Scrum Meeting", - Location: "Office", - StartTime: new Date(2024, 4, 6, 14, 30), - EndTime: new Date(2024, 4, 6, 15, 30), - RecurrenceRule: "" - }, - { - Id: 2, - Subject: "Scrum Meeting", - Location: "Office", - StartTime: new Date(2024, 4, 8, 17, 30), - EndTime: new Date(2024, 4, 8, 18, 30), - RecurrenceRule: "" - } - ]; - const eventSettings = { dataSource: data }; +function Scheduler(props: { + openingHours: { open: string; close: string }; + data: Array<{ Id: number; Subject: string; Location: string; StartTime: Date; EndTime: Date; RecurrenceRule: string }>; +}) { + const eventSettings = { dataSource: props.data }; const [currentDate, setCurrentDate] = useState(new Date()); @@ -77,26 +62,26 @@ function Scheduler() { ( + eventTemplate={(eventProps: { Subject: string; StartTime: Date; EndTime: Date }) => (
-

{props.Subject}

+

{eventProps.Subject}

{new Intl.DateTimeFormat("en-US", { hour: "numeric", minute: "numeric" - }).format(props.StartTime)}{" "} + }).format(eventProps.StartTime)}{" "} {" "} {new Intl.DateTimeFormat("en-US", { hour: "numeric", minute: "numeric" - }).format(props.EndTime)} + }).format(eventProps.EndTime)}
)} diff --git a/src/components/ui/alert-dialog.tsx b/src/components/ui/alert-dialog.tsx new file mode 100644 index 0000000..1fb37a9 --- /dev/null +++ b/src/components/ui/alert-dialog.tsx @@ -0,0 +1,106 @@ +"use client"; + +import * as React from "react"; +import * as AlertDialogPrimitive from "@radix-ui/react-alert-dialog"; + +import { cn } from "@/lib/utils"; +import { buttonVariants } from "@/components/ui/button"; + +const AlertDialog = AlertDialogPrimitive.Root; + +const AlertDialogTrigger = AlertDialogPrimitive.Trigger; + +const AlertDialogPortal = AlertDialogPrimitive.Portal; + +const AlertDialogOverlay = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogOverlay.displayName = AlertDialogPrimitive.Overlay.displayName; + +const AlertDialogContent = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + + + + +)); +AlertDialogContent.displayName = AlertDialogPrimitive.Content.displayName; + +const AlertDialogHeader = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +AlertDialogHeader.displayName = "AlertDialogHeader"; + +const AlertDialogFooter = ({ className, ...props }: React.HTMLAttributes) => ( +
+); +AlertDialogFooter.displayName = "AlertDialogFooter"; + +const AlertDialogTitle = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogTitle.displayName = AlertDialogPrimitive.Title.displayName; + +const AlertDialogDescription = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogDescription.displayName = AlertDialogPrimitive.Description.displayName; + +const AlertDialogAction = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogAction.displayName = AlertDialogPrimitive.Action.displayName; + +const AlertDialogCancel = React.forwardRef< + React.ElementRef, + React.ComponentPropsWithoutRef +>(({ className, ...props }, ref) => ( + +)); +AlertDialogCancel.displayName = AlertDialogPrimitive.Cancel.displayName; + +export { + AlertDialog, + AlertDialogPortal, + AlertDialogOverlay, + AlertDialogTrigger, + AlertDialogContent, + AlertDialogHeader, + AlertDialogFooter, + AlertDialogTitle, + AlertDialogDescription, + AlertDialogAction, + AlertDialogCancel +}; diff --git a/src/components/ui/alert.tsx b/src/components/ui/alert.tsx new file mode 100644 index 0000000..1c7d398 --- /dev/null +++ b/src/components/ui/alert.tsx @@ -0,0 +1,43 @@ +import * as React from "react"; +import { cva, type VariantProps } from "class-variance-authority"; + +import { cn } from "@/lib/utils"; + +const alertVariants = cva( + "relative w-full rounded-lg border p-4 [&>svg+div]:translate-y-[-3px] [&>svg]:absolute [&>svg]:left-4 [&>svg]:top-4 [&>svg]:text-foreground [&>svg~*]:pl-7", + { + variants: { + variant: { + default: "bg-background text-foreground", + destructive: "border-destructive/50 text-destructive dark:border-destructive [&>svg]:text-destructive" + } + }, + defaultVariants: { + variant: "default" + } + } +); + +const Alert = React.forwardRef< + HTMLDivElement, + React.HTMLAttributes & VariantProps +>(({ className, variant, ...props }, ref) => ( +
+)); +Alert.displayName = "Alert"; + +const AlertTitle = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +AlertTitle.displayName = "AlertTitle"; + +const AlertDescription = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); +AlertDescription.displayName = "AlertDescription"; + +export { Alert, AlertTitle, AlertDescription };