-
+
+
);
};
diff --git a/components/ui/animated-modal.tsx b/components/ui/animated-modal.tsx
new file mode 100644
index 0000000..1a0a747
--- /dev/null
+++ b/components/ui/animated-modal.tsx
@@ -0,0 +1,245 @@
+"use client";
+import { cn } from "@/lib/utils";
+import { AnimatePresence, motion } from "framer-motion";
+import { createPortal } from "react-dom";
+import React, {
+ ReactNode,
+ createContext,
+ useContext,
+ useEffect,
+ useRef,
+ useState,
+} from "react";
+
+interface ModalContextType {
+ open: boolean;
+ setOpen: (open: boolean) => void;
+}
+
+const ModalContext = createContext
(undefined);
+
+export const ModalProvider = ({ children }: { children: ReactNode }) => {
+ const [open, setOpen] = useState(false);
+
+ return (
+
+ {children}
+
+ );
+};
+
+export const useModal = () => {
+ const context = useContext(ModalContext);
+ if (!context) {
+ throw new Error("useModal must be used within a ModalProvider");
+ }
+ return context;
+};
+
+export function Modal({ children }: { children: ReactNode }) {
+ return {children};
+}
+
+export const ModalTrigger = ({
+ children,
+ className,
+}: {
+ children: ReactNode;
+ className?: string;
+}) => {
+ const { setOpen } = useModal();
+ return (
+
+ );
+};
+
+export const ModalBody = ({
+ children,
+ className,
+}: {
+ children: ReactNode;
+ className?: string;
+}) => {
+ const { open } = useModal();
+
+ useEffect(() => {
+ if (open) {
+ document.body.style.overflow = "hidden";
+ } else {
+ document.body.style.overflow = "auto";
+ }
+ }, [open]);
+
+ const modalRef = useRef(null);
+ const { setOpen } = useModal();
+ useOutsideClick(modalRef, () => setOpen(false));
+
+ return createPortal(
+
+ {open && (
+
+
+
+
+
+ {children}
+
+
+ )}
+ ,
+ document.body
+ );
+};
+
+export const ModalContent = ({
+ children,
+ className,
+}: {
+ children: ReactNode;
+ className?: string;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
+
+export const ModalFooter = ({
+ children,
+ className,
+}: {
+ children: ReactNode;
+ className?: string;
+}) => {
+ return (
+
+ {children}
+
+ );
+};
+
+const Overlay = ({ className }: { className?: string }) => {
+ return (
+
+ );
+};
+
+const CloseIcon = () => {
+ const { setOpen } = useModal();
+ return (
+
+ );
+};
+
+// Hook to detect clicks outside of a component.
+// Add it in a separate file, I've added here for simplicity
+export const useOutsideClick = (
+ ref: React.RefObject,
+ callback: Function
+) => {
+ useEffect(() => {
+ const listener = (event: any) => {
+ // DO NOTHING if the element being clicked is the target element or their children
+ if (!ref.current || ref.current.contains(event.target)) {
+ return;
+ }
+ callback(event);
+ };
+
+ document.addEventListener("mousedown", listener);
+ document.addEventListener("touchstart", listener);
+
+ return () => {
+ document.removeEventListener("mousedown", listener);
+ document.removeEventListener("touchstart", listener);
+ };
+ }, [ref, callback]);
+};
diff --git a/components/ui/drawer.tsx b/components/ui/drawer.tsx
new file mode 100644
index 0000000..1e7e4d3
--- /dev/null
+++ b/components/ui/drawer.tsx
@@ -0,0 +1,118 @@
+"use client"
+
+import * as React from "react"
+import { Drawer as DrawerPrimitive } from "vaul"
+
+import { cn } from "@/lib/utils"
+
+const Drawer = ({
+ shouldScaleBackground = true,
+ ...props
+}: React.ComponentProps) => (
+
+)
+Drawer.displayName = "Drawer"
+
+const DrawerTrigger = DrawerPrimitive.Trigger
+
+const DrawerPortal = DrawerPrimitive.Portal
+
+const DrawerClose = DrawerPrimitive.Close
+
+const DrawerOverlay = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DrawerOverlay.displayName = DrawerPrimitive.Overlay.displayName
+
+const DrawerContent = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, children, ...props }, ref) => (
+
+
+
+
+ {children}
+
+
+))
+DrawerContent.displayName = "DrawerContent"
+
+const DrawerHeader = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DrawerHeader.displayName = "DrawerHeader"
+
+const DrawerFooter = ({
+ className,
+ ...props
+}: React.HTMLAttributes) => (
+
+)
+DrawerFooter.displayName = "DrawerFooter"
+
+const DrawerTitle = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DrawerTitle.displayName = DrawerPrimitive.Title.displayName
+
+const DrawerDescription = React.forwardRef<
+ React.ElementRef,
+ React.ComponentPropsWithoutRef
+>(({ className, ...props }, ref) => (
+
+))
+DrawerDescription.displayName = DrawerPrimitive.Description.displayName
+
+export {
+ Drawer,
+ DrawerPortal,
+ DrawerOverlay,
+ DrawerTrigger,
+ DrawerClose,
+ DrawerContent,
+ DrawerHeader,
+ DrawerFooter,
+ DrawerTitle,
+ DrawerDescription,
+}
diff --git a/layouts/EventsPageLayout.tsx b/layouts/EventPageLayout/EventsPageLayout.tsx
similarity index 96%
rename from layouts/EventsPageLayout.tsx
rename to layouts/EventPageLayout/EventsPageLayout.tsx
index 958a423..3240962 100644
--- a/layouts/EventsPageLayout.tsx
+++ b/layouts/EventPageLayout/EventsPageLayout.tsx
@@ -35,11 +35,11 @@ const EventsPageLayout = () => {
deadline={event.date}
formLink={event.form_link}
/>
- ))}
+ ))}