Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
74 changes: 13 additions & 61 deletions apps/web/app/home/page.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import Image from "next/image";
import Link from "next/link";
import { Navbar } from "@/components/layout/navbar";
import { Footer } from "@/components/layout/footer";
import { UpcomingEventsEmptyState } from "@/components/empty-state/upcoming-events-empty-state";
import CalendarIcon from "@/public/icons/calendar.svg";
import HostingIcon from "@/public/icons/ticket-star.svg";
import PastIcon from "@/public/icons/camera-smile-01.svg";
import BubbleChatIcon from "@/public/icons/bubble-chat.svg";
import ZeroIcon from "@/public/icons/zero.svg";
import EmptyStateBg from "@/public/icons/empty-state-bg.svg";

type MyEventsTab = "upcoming" | "hosting" | "past";
type ForYouTab = "discover" | "following";
Expand Down Expand Up @@ -57,43 +56,7 @@ interface GridEvent {
}

// Mock data for My Events (Timeline)
const upcomingEvents: TimelineEvent[] = [
{
id: 1,
date: "6 Mar, Friday",
day: "Friday",
time: "18:00 - 20:00 UTC",
title: "Stellar Developers Meetup",
location: "Discord",
imageUrl: "/images/event1.png",
isFree: true,
attendees: 24,
status: "going",
},
{
id: 2,
date: "8 Mar, Sunday",
day: "Sunday",
time: "10:00 - 12:00 UTC",
title: "Web3 Design Workshop",
location: "Lagos, Nigeria",
imageUrl: "/images/event2.png",
isFree: false,
price: "$25.00",
attendees: 156,
},
{
id: 3,
date: "12 Mar, Thursday",
day: "Thursday",
time: "14:00 - 16:00 UTC",
title: "Blockchain Fundamentals",
location: "Virtual",
imageUrl: "/images/event3.png",
isFree: true,
attendees: 89,
},
];
const upcomingEvents: TimelineEvent[] = [];

const hostingEvents: TimelineEvent[] = [
{
Expand Down Expand Up @@ -537,6 +500,7 @@ function GridEventCard({ event }: { event: GridEvent }) {
// My Events Section Content
function MyEventsContent({ activeTab }: { activeTab: MyEventsTab }) {
let events: TimelineEvent[] = [];
const isUpcomingTab = activeTab === "upcoming";

switch (activeTab) {
case "upcoming":
Expand All @@ -551,35 +515,22 @@ function MyEventsContent({ activeTab }: { activeTab: MyEventsTab }) {
}

if (events.length === 0) {
return (
<div className="w-full max-w-121.5 bg-[#FFEFD3] h-107.5 rounded-4xl mx-auto flex flex-col items-center justify-center gap-10 text-[#1315175C]">
<div className="max-w-56 w-full bg-white rounded-4xl h-56 relative p-5.5">
<Image
src={EmptyStateBg}
alt="Empty State Background"
width={224}
height={224}
className="object-cover w-full h-full rounded-4xl"
/>
if (isUpcomingTab) {
return <UpcomingEventsEmptyState />;
}

<div className="bg-white absolute max-w-23.75 rounded-4xl max-h-23.75 w-full h-full shadow-[#63636312] -top-7 -right-7 shadow-[0px_1.65px_1.32px_0px] flex items-center justify-center p-3">
<Image
src={ZeroIcon}
alt="Nothing Here, Yet"
width={16}
height={16}
className="object-center w-full h-full"
/>
</div>
</div>
<p className="text-xl font-medium leading-5.5">Nothing Here, Yet</p>
return (
<div className="flex min-h-[15rem] items-center justify-center rounded-[2rem] border border-dashed border-black/20 bg-white/60 px-6 text-center">
<p className="text-base font-medium text-black/55">
No events found in this section.
</p>
</div>
);
}

return (
<div className="pt-4 space-y-13.25">
{events.map((event, index) => (
{events.map((event) => (
<TimelineEventCard key={event.id} event={event} />
))}
</div>
Expand Down Expand Up @@ -655,3 +606,4 @@ export default function HomePage() {
</div>
);
}

76 changes: 76 additions & 0 deletions apps/web/components/empty-state/upcoming-events-empty-state.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
"use client";

import { motion, useReducedMotion } from "framer-motion";
import Image from "next/image";
import { useRouter } from "next/navigation";
import { Button } from "@/components/ui/button";
import EmptyStateBg from "@/public/icons/empty-state-bg.svg";
import ZeroIcon from "@/public/icons/zero.svg";

export function UpcomingEventsEmptyState() {
const router = useRouter();
const shouldReduceMotion = useReducedMotion();

return (
<motion.div
initial={shouldReduceMotion ? { opacity: 0 } : { opacity: 0, y: 10 }}
animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0 }}
transition={{ duration: 0.4, ease: "easeOut" }}
Comment on lines +16 to +18
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

useReducedMotion() is intended to minimize/disable animations, but the reduced-motion branch still animates opacity from 0→1 using the same transition (0.4s). Consider skipping animation entirely when shouldReduceMotion is true (e.g., set initial={false} and/or use a 0 duration transition in that branch) so reduced-motion users don’t get a fade-in.

Suggested change
initial={shouldReduceMotion ? { opacity: 0 } : { opacity: 0, y: 10 }}
animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0 }}
transition={{ duration: 0.4, ease: "easeOut" }}
initial={shouldReduceMotion ? false : { opacity: 0, y: 10 }}
animate={shouldReduceMotion ? { opacity: 1 } : { opacity: 1, y: 0 }}
transition={
shouldReduceMotion
? { duration: 0 }
: { duration: 0.4, ease: "easeOut" }
}

Copilot uses AI. Check for mistakes.
className="mx-auto flex min-h-[29rem] w-full max-w-[32rem] flex-col items-center justify-center px-4 text-center sm:px-6"
>
<div className="flex w-full max-w-[19rem] flex-col items-center rounded-[2rem] bg-[#FFEFD3] px-6 py-8 shadow-[0_24px_50px_rgba(255,219,159,0.32)] sm:max-w-[20rem] sm:px-7 sm:py-9">
<div className="relative flex items-start justify-center">
<div className="flex h-[12.5rem] w-[12.5rem] items-center justify-center rounded-[1.75rem] bg-white px-5 py-5 shadow-[0_16px_32px_rgba(44,32,19,0.08)] sm:h-[14rem] sm:w-[14rem]">
<Image
src={EmptyStateBg}
alt=""
aria-hidden
width={224}
height={224}
className="h-full w-full object-contain"
/>
</div>

<div className="absolute -right-6 -top-4 flex h-[4.25rem] w-[4.25rem] items-center justify-center rounded-[1.5rem] bg-white p-3 shadow-[0_12px_24px_rgba(44,32,19,0.08)] sm:-right-8 sm:-top-6 sm:h-[5.25rem] sm:w-[5.25rem]">
<Image
src={ZeroIcon}
alt=""
aria-hidden
width={48}
height={48}
className="h-full w-full object-contain"
/>
</div>
</div>

<h3 className="mt-6 text-[1.25rem] font-medium leading-tight text-[#131517] sm:text-[1.375rem]">
Nothing Here, Yet
</h3>
</div>

<p className="mt-6 max-w-[24rem] text-sm leading-6 text-black/60 sm:text-base">
You don&apos;t have any upcoming events right now. Explore what&apos;s
happening and grab a ticket for your next event.
</p>

<Button
type="button"
onClick={() => router.push("/discover")}
backgroundColor="bg-[#FFD21F]"
textColor="text-black"
className="mt-5 w-full max-w-[14rem] px-5 py-3 text-sm sm:w-auto sm:text-base"
aria-label="Discover events"
>
<span>Discover Events</span>
<Image
src="/icons/arrow-right.svg"
alt=""
aria-hidden
width={18}
height={18}
className="h-[18px] w-[18px] object-contain"
/>
</Button>
</motion.div>
);
}
Loading