diff --git a/app/(dashboard)/dashboard/page.tsx b/app/(dashboard)/dashboard/page.tsx index 8c1cd9f..df2476b 100644 --- a/app/(dashboard)/dashboard/page.tsx +++ b/app/(dashboard)/dashboard/page.tsx @@ -14,6 +14,14 @@ export default async function DashboardPage({ redirect('/login'); } + const userOnboarding = await db.user.findUnique({ + where: { id: session.user.id }, + select: { onboardingCompletedAt: true }, + }); + if (!userOnboarding?.onboardingCompletedAt) { + redirect('/onboarding'); + } + const resolvedSearchParams = await searchParams; const { ws, sort, page: pageParam } = resolvedSearchParams || {}; diff --git a/app/api/onboarding/complete/route.ts b/app/api/onboarding/complete/route.ts new file mode 100644 index 0000000..46eba41 --- /dev/null +++ b/app/api/onboarding/complete/route.ts @@ -0,0 +1,17 @@ +import { auth } from '@/lib/auth'; +import { db } from '@/lib/db'; +import { apiErrors, successResponse } from '@/lib/api-response'; + +export async function POST() { + const session = await auth(); + if (!session?.user?.id) { + return apiErrors.unauthorized(); + } + + await db.user.update({ + where: { id: session.user.id }, + data: { onboardingCompletedAt: new Date() }, + }); + + return successResponse({ completed: true }); +} diff --git a/app/onboarding/layout.tsx b/app/onboarding/layout.tsx new file mode 100644 index 0000000..19313a4 --- /dev/null +++ b/app/onboarding/layout.tsx @@ -0,0 +1,7 @@ +export default function OnboardingLayout({ children }: { children: React.ReactNode }) { + return ( +
+ {children} +
+ ); +} diff --git a/app/onboarding/page.tsx b/app/onboarding/page.tsx new file mode 100644 index 0000000..6082449 --- /dev/null +++ b/app/onboarding/page.tsx @@ -0,0 +1,24 @@ +import { auth } from '@/lib/auth'; +import { db } from '@/lib/db'; +import { redirect } from 'next/navigation'; +import { OnboardingWizard } from './onboarding-wizard'; + +export default async function OnboardingPage() { + const session = await auth(); + if (!session?.user?.id) { + redirect('/login'); + } + + const user = await db.user.findUnique({ + where: { id: session.user.id }, + select: { onboardingCompletedAt: true, name: true, email: true }, + }); + + if (user?.onboardingCompletedAt) { + redirect('/dashboard'); + } + + const userName = user?.name || user?.email?.split('@')[0] || 'there'; + + return ; +} diff --git a/prisma/migrations/20260227120000_add_onboarding/migration.sql b/prisma/migrations/20260227120000_add_onboarding/migration.sql new file mode 100644 index 0000000..dd59e7a --- /dev/null +++ b/prisma/migrations/20260227120000_add_onboarding/migration.sql @@ -0,0 +1 @@ +ALTER TABLE users ADD COLUMN IF NOT EXISTS "onboardingCompletedAt" TIMESTAMP; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 253ccb6..31debd5 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -21,6 +21,7 @@ model User { password String? // Hashed password for email/password auth createdAt DateTime @default(now()) updatedAt DateTime @updatedAt + onboardingCompletedAt DateTime? // Relations accounts Account[] @@ -70,12 +71,14 @@ enum DownloadEgressSource { enum VideoAssetKind { IMAGE VIDEO + AUDIO } enum VideoAssetProvider { R2_IMAGE YOUTUBE BUNNY + R2_AUDIO } model DownloadEgressEvent {