Skip to content
Merged
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
172 changes: 45 additions & 127 deletions app/page.tsx
Original file line number Diff line number Diff line change
@@ -1,151 +1,69 @@
import { Suspense } from "react";
import ExploreBtn from "@/components/ExploreBtn";
import EventCard from "@/components/EventCard";
import SearchFilters from "@/components/SearchFilters";
import Footer from "@/components/Footer";
import RecommendedFeed from "@/components/RecommendedFeed";
import SearchFilters from "@/components/SearchFilters"; // Added missing import
import Footer from "@/components/Footer"; // Added missing import
import { IEvent } from "@/database";
import { getAllEvents, getRecommendedEvents } from "@/lib/actions/event.actions";
import { cacheLife } from "next/cache";
import { getAllEvents } from "@/lib/actions/event.actions";

interface PageProps {
searchParams: Promise<{
query?: string;
mode?: string;
tag?: string;
sortBy?: string;
}>;
}

export default async function Page({ searchParams }: PageProps) {
const resolvedSearchParams = await searchParams;
const Page = async ({ searchParams }: PageProps) => {

// 1. Resolve search variables from the URL router interface
const resolvedParams = await searchParams;

const validSortBy = ["date_asc", "date_desc", "name_asc", "name_desc", "popularity"] as const;
type SortByType = (typeof validSortBy)[number];
const rawSortBy = resolvedSearchParams.sortBy?.trim();
const sortBy = validSortBy.includes(rawSortBy as SortByType)
? (rawSortBy as SortByType)
: undefined;

const filters = {
query: resolvedSearchParams.query?.trim() || undefined,
mode: resolvedSearchParams.mode?.trim() || undefined,
tag: resolvedSearchParams.tag?.trim() || undefined,
sortBy,
};

// 1. Fetch general events (no pagination on home — high limit to get all for category sections)
const { events } = await getAllEvents(filters, 1, 100);

// 2. Target tags for recommendation
const userInterestedTags = ["Next.js", "React", "Frontend", "Hackathon"];

// 3. Fetch matching recommendations from the backend action
const recommendedEvents = await getRecommendedEvents(userInterestedTags);

// Filters for individual categories
const hackathons = events.filter(
(event: IEvent) => event.tags?.includes("Hackathon")
);

const seminars = events.filter(
(event: IEvent) => event.tags?.includes("Seminar")
);

const internships = events.filter(
(event: IEvent) => event.tags?.includes("Internship")
);

const jobs = events.filter(
(event: IEvent) => event.tags?.includes("Job")
);
// 2. Fixed Destructuring: Receives plain array directly from your updated action
const events = await getAllEvents({
query: resolvedParams.query,
mode: resolvedParams.mode,
tag: resolvedParams.tag,
});

return (
<section>
<h1 className="text-center">
The Hub for Every Dev <br /> Event You Can&apos;t Miss
</h1>

<p className="text-center mt-5">
Hackathons, Meetups, and Conferences, All in One Place
</p>
<h1 className="text-center">The Hub for Every Dev <br /> Event You Can&apos;t Miss</h1>
<p className="text-center mt-5">Hackathons, Meetups, and Conferences, All in One Place</p>

<ExploreBtn />

{/* Live Production Recommendation Feed Banner */}
<RecommendedFeed events={recommendedEvents} userTags={userInterestedTags} />

{/* 3. Insert the newly generated Search and Filter component bar */}
<div className="mt-10">
<Suspense fallback={<div className="w-full h-16 animate-pulse rounded-xl bg-white/10" />}>
<SearchFilters />
</Suspense>
<SearchFilters />
</div>

{events && events.length > 0 ? (
<div className="mt-20 space-y-16">

{/* Hackathons */}
<section>
<h3 className="mb-6">🔥 Hackathons</h3>
<ul className="events">
{hackathons.map((event: IEvent) => (
<li key={event._id} className="list-none">
<EventCard {...event} />
</li>
))}
</ul>
</section>

{/* Seminars */}
<section>
<h3 className="mb-6">📚 Seminars</h3>
<ul className="events">
{seminars.map((event: IEvent) => (
<li key={event._id} className="list-none">
<EventCard {...event} />
</li>
))}
</ul>
</section>

{/* Internships */}
<section>
<h3 className="mb-6">💼 Internships</h3>
<ul className="events">
{internships.map((event: IEvent) => (
<li key={event._id} className="list-none">
<EventCard {...event} />
</li>
))}
</ul>
</section>

{/* Jobs */}
<section>
<h3 className="mb-6">🚀 Jobs</h3>
<ul className="events">
{jobs.map((event: IEvent) => (
<li key={event._id} className="list-none">
<EventCard {...event} />
</li>
))}
</ul>
</section>

</div>
) : (
<div className="flex flex-col items-center justify-center text-center p-12 border border-dashed border-gray-300 rounded-2xl max-w-xl mx-auto bg-white/50 mt-20">
<h4 className="text-lg font-semibold text-gray-800 mb-1">
No events found
</h4>

<p className="text-sm text-gray-500 max-w-xs">
We couldn&apos;t find any listings matching your search constraints.
Try checking your spelling or adjusting filters.
</p>
</div>
)}

<div className="mt-20 space-y-7">
<h3>Featured Events</h3>

{/* 4. Display list layout conditionally or deliver clean placeholder states */}
{events && events.length > 0 ? (
<ul className="events">
{events.map((event: IEvent) => (
<li key={event._id as string} className="list-none">
<EventCard {...event} />
</li>
))}
</ul>
) : (
/* Smooth Contextual Empty State displayed dynamically */
<div className="flex flex-col items-center justify-center text-center p-12 border border-dashed border-gray-300 rounded-2xl max-w-xl mx-auto bg-white/50">
<h4 className="text-lg font-semibold text-gray-800 mb-1">No events found</h4>
{/* Fixed Linting Error: Escaped the apostrophe here */}
<p className="text-sm text-gray-500 max-w-xs">
We couldn&apos;t find any listings matching your search constraints. Try checking your spelling or adjusting filters.
</p>
</div>
)}
</div>
<Footer />
</section>
);
}
)
}

export default Page;
Loading