import { redirect } from "next/navigation" import { auth } from "@/auth" import { prisma } from "@/lib/prisma" import { createJoinLinkToken } from "@/lib/join-link" import { DashboardContent } from "@/components/dashboard/dashboard-content" import type { MeetingDTO } from "@/components/dashboard/types" // This route reads the session (cookies) and queries the DB for the // current user's meetings on every request, so it can't be part of the // static shell under Cache Components. Opting out of instant-navigation // validation here is the documented migration path (see // node_modules/next/dist/docs/01-app/02-guides/authentication-with-cache-components.md) // for a route that should always render fresh data rather than a cached // shell — dashboard data (active/upcoming meetings) must never be stale. export const instant = false const PAST_MEETINGS_LIMIT = 10 export default async function DashboardPage() { const session = await auth() if (!session?.user?.id) { redirect("/login?callbackUrl=/dashboard") } const hostUserId = Number(session.user.id) const [activeMeetings, upcomingMeetings, pastMeetings] = await Promise.all([ prisma.meeting.findMany({ where: { hostUserId, status: "active" }, orderBy: { startedAt: "desc" }, }), prisma.meeting.findMany({ where: { hostUserId, status: "scheduled", scheduledAt: { gte: new Date() }, }, orderBy: { scheduledAt: "asc" }, }), prisma.meeting.findMany({ where: { hostUserId, status: "ended" }, orderBy: { endedAt: "desc" }, take: PAST_MEETINGS_LIMIT, }), ]) async function toDTO( meeting: (typeof activeMeetings)[number], withJoinLink: boolean ): Promise { return { id: meeting.id, uuid: meeting.uuid, title: meeting.title, type: meeting.type, status: meeting.status, scheduledAt: meeting.scheduledAt?.toISOString() ?? null, startedAt: meeting.startedAt?.toISOString() ?? null, endedAt: meeting.endedAt?.toISOString() ?? null, joinUrl: withJoinLink ? `/join/${meeting.uuid}?token=${await createJoinLinkToken(meeting.uuid, { scheduledAt: meeting.scheduledAt, })}` : null, } } const [active, upcoming, past] = await Promise.all([ Promise.all(activeMeetings.map((meeting) => toDTO(meeting, true))), Promise.all(upcomingMeetings.map((meeting) => toDTO(meeting, true))), Promise.all(pastMeetings.map((meeting) => toDTO(meeting, false))), ]) return ( ) }