kreativortex/app/actions/video.ts
Jessica Rekcah 4253483f44 jalan
2025-12-02 00:22:34 +07:00

154 lines
4.5 KiB
TypeScript

'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;
}