372 lines
8.7 KiB
TypeScript
372 lines
8.7 KiB
TypeScript
"use server";
|
||
|
||
import { prisma } from "@/lib/prisma";
|
||
import { revalidatePath } from "next/cache";
|
||
import { verifyPassword, signToken, verifyToken } from "@/lib/auth";
|
||
import { cookies } from "next/headers";
|
||
|
||
// ── PROJECTS ACTIONS ──
|
||
|
||
export async function getProjects() {
|
||
try {
|
||
return await prisma.project.findMany({
|
||
orderBy: { num: "asc" },
|
||
take: 50,
|
||
});
|
||
} catch (error) {
|
||
console.error("Error fetching projects:", error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function getFeaturedProjects() {
|
||
try {
|
||
return await prisma.project.findMany({
|
||
where: { featured: true },
|
||
orderBy: { num: "asc" },
|
||
take: 4,
|
||
});
|
||
} catch (error) {
|
||
console.error("Error fetching featured projects:", error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function saveProject(data: any) {
|
||
try {
|
||
const { id, num, slug, title, tag, desc, spec, year, client, duration, tech, challenge, solution, results, image, gallery, website, featured } = data;
|
||
|
||
let project;
|
||
if (id) {
|
||
// Update
|
||
project = await prisma.project.update({
|
||
where: { id: Number(id) },
|
||
data: {
|
||
num,
|
||
slug,
|
||
title,
|
||
tag,
|
||
desc,
|
||
spec,
|
||
year,
|
||
client,
|
||
duration,
|
||
tech,
|
||
challenge,
|
||
solution,
|
||
results,
|
||
image: image || "",
|
||
gallery: gallery || [],
|
||
website: website || "",
|
||
featured: featured || false,
|
||
},
|
||
});
|
||
} else {
|
||
// Create
|
||
// Ensure slug is unique
|
||
const existing = await prisma.project.findFirst({ where: { slug } });
|
||
if (existing) {
|
||
throw new Error("A project with this slug already exists.");
|
||
}
|
||
|
||
project = await prisma.project.create({
|
||
data: {
|
||
num,
|
||
slug,
|
||
title,
|
||
tag,
|
||
desc,
|
||
spec,
|
||
year,
|
||
client,
|
||
duration,
|
||
tech,
|
||
challenge,
|
||
solution,
|
||
results,
|
||
image: image || "",
|
||
gallery: gallery || [],
|
||
website: website || "",
|
||
featured: featured || false,
|
||
},
|
||
});
|
||
}
|
||
|
||
revalidatePath("/[lang]/work", "layout");
|
||
revalidatePath("/[lang]/admin", "page");
|
||
return { success: true, project };
|
||
} catch (error: any) {
|
||
console.error("Error saving project:", error);
|
||
return { success: false, error: error.message };
|
||
}
|
||
}
|
||
|
||
export async function deleteProject(id: number) {
|
||
try {
|
||
await prisma.project.delete({
|
||
where: { id },
|
||
});
|
||
revalidatePath("/[lang]/work", "layout");
|
||
revalidatePath("/[lang]/admin", "page");
|
||
return { success: true };
|
||
} catch (error: any) {
|
||
console.error("Error deleting project:", error);
|
||
return { success: false, error: error.message };
|
||
}
|
||
}
|
||
|
||
// ── BLOG POSTS ACTIONS ──
|
||
|
||
export async function getBlogPosts() {
|
||
try {
|
||
const posts = await prisma.blogPost.findMany({
|
||
orderBy: { date: "desc" },
|
||
});
|
||
return posts;
|
||
} catch (error) {
|
||
console.error("Error fetching blog posts:", error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function saveBlogPost(data: any) {
|
||
try {
|
||
const {
|
||
id,
|
||
slug,
|
||
date,
|
||
author,
|
||
authorRole,
|
||
image,
|
||
trTitle,
|
||
trExcerpt,
|
||
trReadingTime,
|
||
trCategory,
|
||
trTags,
|
||
trContent,
|
||
enTitle,
|
||
enExcerpt,
|
||
enReadingTime,
|
||
enCategory,
|
||
enTags,
|
||
enContent,
|
||
} = data;
|
||
|
||
let post;
|
||
if (id) {
|
||
// Update
|
||
post = await prisma.blogPost.update({
|
||
where: { id: Number(id) },
|
||
data: {
|
||
slug,
|
||
date,
|
||
author,
|
||
authorRole,
|
||
image,
|
||
trTitle,
|
||
trExcerpt,
|
||
trReadingTime,
|
||
trCategory,
|
||
trTags,
|
||
trContent,
|
||
enTitle,
|
||
enExcerpt,
|
||
enReadingTime,
|
||
enCategory,
|
||
enTags,
|
||
enContent,
|
||
},
|
||
});
|
||
} else {
|
||
// Create
|
||
const existing = await prisma.blogPost.findFirst({ where: { slug } });
|
||
if (existing) {
|
||
throw new Error("A blog post with this slug already exists.");
|
||
}
|
||
|
||
post = await prisma.blogPost.create({
|
||
data: {
|
||
slug,
|
||
date,
|
||
author,
|
||
authorRole,
|
||
image,
|
||
trTitle,
|
||
trExcerpt,
|
||
trReadingTime,
|
||
trCategory,
|
||
trTags,
|
||
trContent,
|
||
enTitle,
|
||
enExcerpt,
|
||
enReadingTime,
|
||
enCategory,
|
||
enTags,
|
||
enContent,
|
||
},
|
||
});
|
||
}
|
||
|
||
revalidatePath("/[lang]/blog", "layout");
|
||
revalidatePath("/[lang]/admin", "page");
|
||
return { success: true, post };
|
||
} catch (error: any) {
|
||
console.error("Error saving blog post:", error);
|
||
return { success: false, error: error.message };
|
||
}
|
||
}
|
||
|
||
export async function deleteBlogPost(id: number) {
|
||
try {
|
||
await prisma.blogPost.delete({
|
||
where: { id },
|
||
});
|
||
revalidatePath("/[lang]/blog", "layout");
|
||
revalidatePath("/[lang]/admin", "page");
|
||
return { success: true };
|
||
} catch (error: any) {
|
||
console.error("Error deleting blog post:", error);
|
||
return { success: false, error: error.message };
|
||
}
|
||
}
|
||
|
||
// ── PARTNERS ACTIONS ──
|
||
|
||
export async function getPartners() {
|
||
try {
|
||
return await prisma.partner.findMany({
|
||
orderBy: { id: "asc" },
|
||
});
|
||
} catch (error) {
|
||
console.error("Error fetching partners:", error);
|
||
return [];
|
||
}
|
||
}
|
||
|
||
export async function savePartner(data: any) {
|
||
try {
|
||
const { id, name, tag, mono, year, desc } = data;
|
||
|
||
let partner;
|
||
if (id) {
|
||
// Update
|
||
partner = await prisma.partner.update({
|
||
where: { id: Number(id) },
|
||
data: {
|
||
name,
|
||
tag,
|
||
mono,
|
||
year,
|
||
desc,
|
||
},
|
||
});
|
||
} else {
|
||
// Create
|
||
// Ensure name is unique
|
||
const existing = await prisma.partner.findFirst({ where: { name } });
|
||
if (existing) {
|
||
throw new Error("Bu isimde bir partner zaten mevcut.");
|
||
}
|
||
|
||
partner = await prisma.partner.create({
|
||
data: {
|
||
name,
|
||
tag,
|
||
mono,
|
||
year,
|
||
desc,
|
||
},
|
||
});
|
||
}
|
||
|
||
revalidatePath("/[lang]/partners", "layout");
|
||
revalidatePath("/[lang]/admin", "page");
|
||
return { success: true, partner };
|
||
} catch (error: any) {
|
||
console.error("Error saving partner:", error);
|
||
return { success: false, error: error.message };
|
||
}
|
||
}
|
||
|
||
export async function deletePartner(id: number) {
|
||
try {
|
||
await prisma.partner.delete({
|
||
where: { id },
|
||
});
|
||
revalidatePath("/[lang]/partners", "layout");
|
||
revalidatePath("/[lang]/admin", "page");
|
||
return { success: true };
|
||
} catch (error: any) {
|
||
console.error("Error deleting partner:", error);
|
||
return { success: false, error: error.message };
|
||
}
|
||
}
|
||
|
||
// ── AUTHENTICATION ACTIONS ──
|
||
|
||
const COOKIE_NAME = "ayris_session";
|
||
|
||
export async function getAdminSession() {
|
||
try {
|
||
const cookieStore = await cookies();
|
||
const token = cookieStore.get(COOKIE_NAME)?.value;
|
||
if (!token) return null;
|
||
return verifyToken(token);
|
||
} catch (error: any) {
|
||
if (error?.digest === 'DYNAMIC_SERVER_USAGE' || error?.message?.includes('Dynamic server usage')) {
|
||
throw error;
|
||
}
|
||
console.error("Error reading admin session:", error);
|
||
return null;
|
||
}
|
||
}
|
||
|
||
export async function adminLoginAction(data: any) {
|
||
try {
|
||
const { username, password } = data;
|
||
if (!username || !password) {
|
||
return { success: false, error: "Kullanıcı adı ve şifre zorunludur!" };
|
||
}
|
||
|
||
const user = await prisma.user.findUnique({
|
||
where: { username },
|
||
});
|
||
|
||
if (!user) {
|
||
return { success: false, error: "Geçersiz kullanıcı adı veya şifre!" };
|
||
}
|
||
|
||
const isValid = verifyPassword(password, user.password);
|
||
if (!isValid) {
|
||
return { success: false, error: "Geçersiz kullanıcı adı veya şifre!" };
|
||
}
|
||
|
||
const token = signToken({ userId: user.id, username: user.username });
|
||
|
||
const cookieStore = await cookies();
|
||
cookieStore.set(COOKIE_NAME, token, {
|
||
httpOnly: true,
|
||
secure: process.env.NODE_ENV === "production",
|
||
sameSite: "strict",
|
||
maxAge: 24 * 60 * 60, // 24 hours
|
||
path: "/",
|
||
});
|
||
|
||
return { success: true };
|
||
} catch (error: any) {
|
||
console.error("Login action error:", error);
|
||
return { success: false, error: "Giriş yapılırken beklenmedik bir hata oluştu!" };
|
||
}
|
||
}
|
||
|
||
export async function adminLogoutAction() {
|
||
try {
|
||
const cookieStore = await cookies();
|
||
cookieStore.delete(COOKIE_NAME);
|
||
return { success: true };
|
||
} catch (error: any) {
|
||
console.error("Logout action error:", error);
|
||
return { success: false, error: "Çıkış yapılırken bir hata oluştu!" };
|
||
}
|
||
}
|