From 158a8b441a86185535444bcf6cd5975407404e9c Mon Sep 17 00:00:00 2001 From: Felipe Cardoso Date: Tue, 11 Mar 2025 06:57:34 +0100 Subject: [PATCH] Add invitation and dashboard pages with UI components Introduced a dynamic invitation page to display event details based on a slug, including RSVP functionality (placeholder). Added a dashboard page for authenticated users, providing a welcome message and placeholder for event management. Also implemented reusable Card UI components for consistent styling. --- .../app/(main)/dashboard/events/[id]/page.tsx | 58 ++++++ .../src/app/(public)/invite/[slug]/page.tsx | 184 ++++++++++++++++++ frontend/src/components/ui/card.tsx | 68 +++++++ 3 files changed, 310 insertions(+) create mode 100644 frontend/src/app/(main)/dashboard/events/[id]/page.tsx create mode 100644 frontend/src/app/(public)/invite/[slug]/page.tsx create mode 100644 frontend/src/components/ui/card.tsx diff --git a/frontend/src/app/(main)/dashboard/events/[id]/page.tsx b/frontend/src/app/(main)/dashboard/events/[id]/page.tsx new file mode 100644 index 0000000..ad7a18b --- /dev/null +++ b/frontend/src/app/(main)/dashboard/events/[id]/page.tsx @@ -0,0 +1,58 @@ +// src/app/(main)/dashboard/page.tsx +"use client"; + +import { useAuth } from "@/context/auth-context"; +import Navbar from "@/components/layout/navbar"; + +export default function DashboardPage() { + const { user, isLoading } = useAuth(); + + // Show loading state + if (isLoading) { + return ( +
+
+
+

Loading...

+
+
+ ); + } + + return ( + <> + +
+
+

Dashboard

+ +
+

+ Welcome, {user?.first_name || "User"}! +

+

+ You are now logged in to EventSpace. +

+ +
+

Your Events

+
+

+ No events yet +

+ +
+
+
+
+
+ + ); +} diff --git a/frontend/src/app/(public)/invite/[slug]/page.tsx b/frontend/src/app/(public)/invite/[slug]/page.tsx new file mode 100644 index 0000000..ab8aad5 --- /dev/null +++ b/frontend/src/app/(public)/invite/[slug]/page.tsx @@ -0,0 +1,184 @@ +"use client"; +import React, { useEffect, useState } from "react"; +import { motion } from "framer-motion"; +import { useParams } from "next/navigation"; +import { Card, CardContent } from "@/components/ui/card"; +import { Button } from "@/components/ui/button"; +import { Calendar, Gift, MapPin, Clock } from "lucide-react"; +import Image from "next/image"; +import Link from "next/link"; +import { useEvents } from "@/context/event-context"; +import { EventResponse } from "@/client/types.gen"; + +const InvitationPage = () => { + const { slug } = useParams(); + const { getEventBySlug } = useEvents(); + const [isLoading, setIsLoading] = useState(true); + const [event, setEvent] = useState(null); + const [notFound, setNotFound] = useState(false); + const [showRSVP, setShowRSVP] = useState(false); + + useEffect(() => { + const fetchEvent = async () => { + setIsLoading(true); + try { + const eventData = await getEventBySlug(slug as string); + if (eventData) { + setEvent(eventData); + } else { + setNotFound(true); + } + } catch (error) { + console.error("Failed to fetch event data:", error); + setNotFound(true); + } finally { + setIsLoading(false); + } + }; + + if (slug) { + fetchEvent(); + } + }, [slug, getEventBySlug]); + + const formatDate = (date: string | Date) => { + return new Date(date).toLocaleDateString("en-US", { + weekday: "long", + year: "numeric", + month: "long", + day: "numeric", + }); + }; + + const formatTime = (date: string | Date) => { + return new Date(date).toLocaleTimeString("en-US", { + hour: "numeric", + minute: "2-digit", + hour12: true, + }); + }; + + if (isLoading) { + return ( +
+
+
+ Loading +
+

Loading your invitation...

+
+
+ ); + } + + if (notFound || !event) { + return ( +
+ Not Found +

+ Event Not Found +

+

+ We couldn't find an event matching your invitation. Please check your + invitation link or contact the event organizer. +

+ +
+ ); + } + + return ( +
+
+ +

+ {event.title} +

+

+ {event.description} +

+
+ + + + +
    +
  • + + {formatDate(event.event_date)} +
  • +
  • + + + {formatTime(event.event_date)} -{" "} + {formatTime(event.event_end_time || "")} + +
  • +
  • + + + {event.location_name}, {event.location_address} + +
  • + {event.gift_registry_enabled && ( +
  • + + + + Gift Registry + + +
  • + )} +
+ + {showRSVP && ( +
+

RSVP functionality coming soon!

+
+ )} +
+
+
+
+
+ ); +}; + +export default InvitationPage; diff --git a/frontend/src/components/ui/card.tsx b/frontend/src/components/ui/card.tsx new file mode 100644 index 0000000..5e960a6 --- /dev/null +++ b/frontend/src/components/ui/card.tsx @@ -0,0 +1,68 @@ +import * as React from "react" + +import { cn } from "@/lib/utils" + +function Card({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardHeader({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardTitle({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardDescription({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardContent({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +function CardFooter({ className, ...props }: React.ComponentProps<"div">) { + return ( +
+ ) +} + +export { Card, CardHeader, CardFooter, CardTitle, CardDescription, CardContent }