'use server'; import { prisma } from '@/lib/prisma'; import { auth } from '@/lib/auth'; import { headers } from 'next/headers'; import { revalidatePath } from 'next/cache'; import { redirect } from 'next/navigation'; import { z } from 'zod'; const VideoSchema = z.object({ title: z.string().min(1), description: z.string().optional(), videoUrl: z.string().min(1), videoType: z.enum(['YOUTUBE', 'LOCAL']), isPublic: z.boolean(), menuId: z.string().optional(), }); export async function createVideo(data: { title: string; description: string; videoUrl: string; videoType: 'YOUTUBE' | 'LOCAL'; isPublic: boolean; menuId?: string; }) { const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user) { throw new Error('Unauthorized'); } // Get user profile const userProfile = await prisma.userProfile.findUnique({ where: { userId: session.user.id }, }); if (!userProfile) { throw new Error('User profile not found. Please complete your profile first.'); } const validatedData = VideoSchema.parse(data); let thumbnailUrl = null; if (validatedData.videoType === 'YOUTUBE') { const videoId = extractYoutubeId(validatedData.videoUrl); if (videoId) { thumbnailUrl = `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`; } } await prisma.video.create({ data: { ...validatedData, uploaderId: userProfile.id, thumbnailUrl, createdBy: session.user.id, updatedBy: session.user.id, }, }); revalidatePath('/dashboard/videos'); if (validatedData.menuId) { // We need to find the slug to revalidate the page, but revalidating the layout might be enough or we can just revalidate the specific page if we fetch the menu. // For now, let's revalidate the dashboard layout to be safe or just the videos page. // Actually, we can fetch the menu to get the slug. const menu = await prisma.menu.findUnique({ where: { id: validatedData.menuId } }); if (menu) { revalidatePath(`/dashboard/pages/${menu.slug}`); } } redirect('/dashboard/videos'); } export async function updateVideo(id: string, data: { title: string; description: string; videoUrl: string; videoType: 'YOUTUBE' | 'LOCAL'; isPublic: boolean; menuId?: string; }) { const session = await auth.api.getSession({ headers: await headers() }); if (!session?.user) { throw new Error('Unauthorized'); } // Get user profile const userProfile = await prisma.userProfile.findUnique({ where: { userId: session.user.id }, }); if (!userProfile) { throw new Error('User profile not found. Please complete your profile first.'); } // Check if user owns the video const existingVideo = await prisma.video.findUnique({ where: { id }, }); if (!existingVideo || existingVideo.uploaderId !== userProfile.id) { throw new Error('Video not found or you do not have permission to edit it'); } const validatedData = VideoSchema.parse(data); let thumbnailUrl = existingVideo.thumbnailUrl; if (validatedData.videoType === 'YOUTUBE') { const videoId = extractYoutubeId(validatedData.videoUrl); if (videoId) { thumbnailUrl = `https://img.youtube.com/vi/${videoId}/maxresdefault.jpg`; } } await prisma.video.update({ where: { id }, data: { ...validatedData, thumbnailUrl, updatedBy: session.user.id, }, }); revalidatePath('/dashboard/videos'); revalidatePath(`/dashboard/videos/${id}`); if (validatedData.menuId) { const menu = await prisma.menu.findUnique({ where: { id: validatedData.menuId } }); if (menu) { revalidatePath(`/dashboard/pages/${menu.slug}`); } } if (existingVideo.menuId && existingVideo.menuId !== validatedData.menuId) { const oldMenu = await prisma.menu.findUnique({ where: { id: existingVideo.menuId } }); if (oldMenu) { revalidatePath(`/dashboard/pages/${oldMenu.slug}`); } } redirect(`/dashboard/videos/${id}`); } function extractYoutubeId(url: string) { const regExp = /^.*(youtu.be\/|v\/|u\/\w\/|embed\/|watch\?v=|&v=)([^#&?]*).*/; const match = url.match(regExp); return (match && match[2].length === 11) ? match[2] : null; }