import type { Metadata } from "next"; import { headers } from "next/headers"; import { auth } from "@/lib/auth/server"; import { db, collections, users, collectionFavorites, collectionRecipes, eq, desc, sql, and, gte, count, inArray, } from "@epicure/db"; import { ExploreCollectionsContent } from "@/components/collections/explore-collections-content"; export const metadata: Metadata = {}; export type CollectionResult = { id: string; name: string; description: string | null; authorName: string | null; recipeCount: number; starCount: number; starred: boolean; }; export default async function ExploreCollectionsPage() { const session = await auth.api.getSession({ headers: await headers() }); if (!session) return null; const sevenDaysAgo = new Date(Date.now() - 7 * 24 * 60 * 60 * 1000); const trendingRows = await db .select({ id: collections.id, name: collections.name, description: collections.description, authorName: users.name, recentStars: count(collectionFavorites.collectionId), }) .from(collections) .innerJoin(users, eq(collections.userId, users.id)) .leftJoin( collectionFavorites, and(eq(collectionFavorites.collectionId, collections.id), gte(collectionFavorites.createdAt, sevenDaysAgo)) ) .where(eq(collections.isPublic, true)) .groupBy(collections.id, users.id) .orderBy(desc(sql`count(${collectionFavorites.collectionId})`)) .limit(12); const recentRows = await db .select({ id: collections.id, name: collections.name, description: collections.description, authorName: users.name, }) .from(collections) .innerJoin(users, eq(collections.userId, users.id)) .where(eq(collections.isPublic, true)) .orderBy(desc(collections.createdAt)) .limit(12); const allIds = [...new Set([...trendingRows.map((r) => r.id), ...recentRows.map((r) => r.id)])]; const [recipeCounts, totalStars, myStars] = await Promise.all([ allIds.length > 0 ? db.select({ collectionId: collectionRecipes.collectionId, n: count() }) .from(collectionRecipes) .where(inArray(collectionRecipes.collectionId, allIds)) .groupBy(collectionRecipes.collectionId) : [], allIds.length > 0 ? db.select({ collectionId: collectionFavorites.collectionId, n: count() }) .from(collectionFavorites) .where(inArray(collectionFavorites.collectionId, allIds)) .groupBy(collectionFavorites.collectionId) : [], allIds.length > 0 ? db.query.collectionFavorites.findMany({ where: and(eq(collectionFavorites.userId, session.user.id), inArray(collectionFavorites.collectionId, allIds)), columns: { collectionId: true }, }) : [], ]); const recipeCountMap = new Map(recipeCounts.map((r) => [r.collectionId, r.n])); const starCountMap = new Map(totalStars.map((r) => [r.collectionId, r.n])); const starredSet = new Set(myStars.map((s) => s.collectionId)); function toResult(row: { id: string; name: string; description: string | null; authorName: string | null }): CollectionResult { return { id: row.id, name: row.name, description: row.description, authorName: row.authorName, recipeCount: recipeCountMap.get(row.id) ?? 0, starCount: starCountMap.get(row.id) ?? 0, starred: starredSet.has(row.id), }; } const trending = trendingRows.map(toResult); const recent = recentRows.map(toResult); return ; }