feat: add prisma support, admin panel and auth

This commit is contained in:
AyrisAI
2026-05-15 19:11:17 +03:00
parent 31c3deb2da
commit 09a105cd1e
29 changed files with 3606 additions and 441 deletions

150
app/admin/actions.ts Normal file
View File

@@ -0,0 +1,150 @@
'use server';
import { prisma } from '@/app/lib/prisma';
import { revalidatePath } from 'next/cache';
import { cookies } from 'next/headers';
import { redirect } from 'next/navigation';
import bcrypt from 'bcryptjs';
import { encrypt } from '@/app/lib/auth';
/* ────── Auth Actions ────── */
export async function authenticate(formData: FormData) {
const username = formData.get('username') as string;
const password = formData.get('password') as string;
const user = await prisma.user.findUnique({ where: { username } });
if (!user || !(await bcrypt.compare(password, user.password))) {
return { error: 'Geçersiz kullanıcı adı veya şifre' };
}
// Create session
const expires = new Date(Date.now() + 2 * 60 * 60 * 1000); // 2 hours
const session = await encrypt({ userId: user.id, username: user.username, expires });
(await cookies()).set('session', session, { expires, httpOnly: true });
redirect('/admin');
}
export async function signout() {
(await cookies()).set('session', '', { expires: new Date(0) });
redirect('/login');
}
export async function createCategory(formData: FormData) {
const title = formData.get('title') as string;
const externalId = formData.get('externalId') as string;
await prisma.category.create({
data: {
title,
externalId: externalId || null,
restaurantId: (await prisma.restaurant.findFirst())?.id || '',
},
});
revalidatePath('/admin/categories');
revalidatePath('/');
}
export async function updateCategory(id: string, formData: FormData) {
const title = formData.get('title') as string;
const externalId = formData.get('externalId') as string;
await prisma.category.update({
where: { id },
data: {
title,
externalId: externalId || null,
},
});
revalidatePath('/admin/categories');
revalidatePath('/');
}
export async function deleteCategory(id: string) {
// Optional: check if there are items first, or let prisma handles cascade if configured
await prisma.item.deleteMany({ where: { categoryId: id } });
await prisma.category.delete({ where: { id } });
revalidatePath('/admin/categories');
revalidatePath('/');
}
/* ────── Item Actions ────── */
export async function createItem(formData: FormData) {
const name = formData.get('name') as string;
const categoryId = formData.get('categoryId') as string;
const ingredients = formData.get('ingredients') as string;
const tasteProfile = formData.get('tasteProfile') as string;
const grapeVariety = formData.get('grapeVariety') as string;
const priceInput = formData.get('price') as string;
let price;
try {
// Try to parse as JSON if it looks like an object, otherwise keep as string
price = (priceInput.startsWith('{') || priceInput.startsWith('['))
? JSON.parse(priceInput)
: priceInput;
} catch (e) {
price = priceInput;
}
await prisma.item.create({
data: {
name,
categoryId,
ingredients: ingredients || null,
tasteProfile: tasteProfile || null,
grapeVariety: grapeVariety || null,
price,
},
});
revalidatePath('/admin/items');
revalidatePath('/');
}
export async function updateItem(id: string, formData: FormData) {
const name = formData.get('name') as string;
const categoryId = formData.get('categoryId') as string;
const ingredients = formData.get('ingredients') as string;
const tasteProfile = formData.get('tasteProfile') as string;
const grapeVariety = formData.get('grapeVariety') as string;
const priceInput = formData.get('price') as string;
let price;
try {
price = (priceInput.startsWith('{') || priceInput.startsWith('['))
? JSON.parse(priceInput)
: priceInput;
} catch (e) {
price = priceInput;
}
await prisma.item.update({
where: { id },
data: {
name,
categoryId,
ingredients: ingredients || null,
tasteProfile: tasteProfile || null,
grapeVariety: grapeVariety || null,
price,
},
});
revalidatePath('/admin/items');
revalidatePath('/');
}
export async function deleteItem(id: string) {
await prisma.item.delete({ where: { id } });
revalidatePath('/admin/items');
revalidatePath('/');
}