"use server"; import { revalidatePath } from "next/cache"; import { ID } from "node-appwrite"; import { InputFile } from "node-appwrite/file"; import { adminDB, adminStorage, DATABASE_ID, MEDIA_BUCKET_ID, TABLES, } from "@/lib/appwrite-server"; import { getCurrentUser } from "@/lib/auth"; async function gate() { const user = await getCurrentUser(); if (!user) throw new Error("Yetkisiz"); } function slugify(s: string) { return s .toLowerCase() .replace(/[ğ]/g, "g") .replace(/[ü]/g, "u") .replace(/[ş]/g, "s") .replace(/[ı]/g, "i") .replace(/[ö]/g, "o") .replace(/[ç]/g, "c") .replace(/[^a-z0-9]+/g, "-") .replace(/^-+|-+$/g, "") .slice(0, 80); } function num(v: FormDataEntryValue | null) { if (v === null || v === "") return null; const n = Number(v); return Number.isFinite(n) ? n : null; } function bool(v: FormDataEntryValue | null) { return v === "on" || v === "true" || v === "1"; } function str(v: FormDataEntryValue | null) { if (v === null) return null; const s = String(v).trim(); return s === "" ? null : s; } function strArr(v: FormDataEntryValue | null) { if (v === null) return null; return String(v) .split(",") .map((x) => x.trim()) .filter(Boolean); } // ─── Media upload ──────────────────────────────────────────────── export async function uploadMedia(formData: FormData): Promise { await gate(); const file = formData.get("file"); if (!(file instanceof File) || file.size === 0) { throw new Error("Dosya seçilmedi"); } const bytes = Buffer.from(await file.arrayBuffer()); await adminStorage.createFile({ bucketId: MEDIA_BUCKET_ID, fileId: ID.unique(), file: InputFile.fromBuffer(bytes, file.name), }); revalidatePath("/admin/medya"); } export async function deleteMediaFile(fileId: string) { await gate(); await adminStorage.deleteFile({ bucketId: MEDIA_BUCKET_ID, fileId }); revalidatePath("/admin/medya"); } // ─── Blog ──────────────────────────────────────────────────────── export async function saveBlogPost(formData: FormData) { await gate(); const id = str(formData.get("id")); const title = str(formData.get("title")); if (!title) throw new Error("Başlık zorunlu"); const slug = str(formData.get("slug")) || slugify(title); const status = (str(formData.get("status")) ?? "draft") as "draft" | "published"; const data = { slug, title, excerpt: str(formData.get("excerpt")), content: str(formData.get("content")), cover_image: str(formData.get("cover_image")), cover_file_id: str(formData.get("cover_file_id")), author: str(formData.get("author")), status, published_at: status === "published" ? str(formData.get("published_at")) || new Date().toISOString() : null, tags: strArr(formData.get("tags")), seo_title: str(formData.get("seo_title")), seo_description: str(formData.get("seo_description")), seo_image: str(formData.get("seo_image")), }; if (id) { await adminDB.updateRow({ databaseId: DATABASE_ID, tableId: TABLES.blogPosts, rowId: id, data, }); } else { await adminDB.createRow({ databaseId: DATABASE_ID, tableId: TABLES.blogPosts, rowId: ID.unique(), data, }); } revalidatePath("/admin/blog"); revalidatePath("/blog"); if (slug) revalidatePath(`/blog/${slug}`); } export async function deleteBlogPost(formData: FormData) { await gate(); const id = String(formData.get("id")); await adminDB.deleteRow({ databaseId: DATABASE_ID, tableId: TABLES.blogPosts, rowId: id, }); revalidatePath("/admin/blog"); revalidatePath("/blog"); } // ─── Services ──────────────────────────────────────────────────── export async function saveService(formData: FormData) { await gate(); const id = str(formData.get("id")); const title = str(formData.get("title")); if (!title) throw new Error("Başlık zorunlu"); const description = str(formData.get("description")); if (!description) throw new Error("Açıklama zorunlu"); const slug = str(formData.get("slug")) || slugify(title); const data = { slug, title, description, icon: str(formData.get("icon")), order: num(formData.get("order")) ?? 0, featured: bool(formData.get("featured")), }; if (id) { await adminDB.updateRow({ databaseId: DATABASE_ID, tableId: TABLES.services, rowId: id, data, }); } else { await adminDB.createRow({ databaseId: DATABASE_ID, tableId: TABLES.services, rowId: slug, data, }); } revalidatePath("/admin/hizmetler"); revalidatePath("/hizmetler"); revalidatePath("/"); } export async function deleteService(formData: FormData) { await gate(); const id = String(formData.get("id")); await adminDB.deleteRow({ databaseId: DATABASE_ID, tableId: TABLES.services, rowId: id, }); revalidatePath("/admin/hizmetler"); revalidatePath("/hizmetler"); } // ─── Projects ──────────────────────────────────────────────────── export async function saveProject(formData: FormData) { await gate(); const id = str(formData.get("id")); const title = str(formData.get("title")); if (!title) throw new Error("Başlık zorunlu"); const slug = str(formData.get("slug")) || slugify(title); const description = str(formData.get("description")); if (!description) throw new Error("Açıklama zorunlu"); const data = { slug, title, description, image_url: str(formData.get("image_url")), live_url: str(formData.get("live_url")), category: str(formData.get("category")), technologies: strArr(formData.get("technologies")), year: num(formData.get("year")), featured: bool(formData.get("featured")), }; if (id) { await adminDB.updateRow({ databaseId: DATABASE_ID, tableId: TABLES.projects, rowId: id, data, }); } else { await adminDB.createRow({ databaseId: DATABASE_ID, tableId: TABLES.projects, rowId: ID.unique(), data, }); } revalidatePath("/admin/projeler"); revalidatePath("/projeler"); revalidatePath("/"); } export async function deleteProject(formData: FormData) { await gate(); const id = String(formData.get("id")); await adminDB.deleteRow({ databaseId: DATABASE_ID, tableId: TABLES.projects, rowId: id, }); revalidatePath("/admin/projeler"); revalidatePath("/projeler"); } // ─── Testimonials ──────────────────────────────────────────────── export async function saveTestimonial(formData: FormData) { await gate(); const id = str(formData.get("id")); const name = str(formData.get("name")); if (!name) throw new Error("Ad zorunlu"); const message = str(formData.get("message")); if (!message) throw new Error("Mesaj zorunlu"); const data = { name, role: str(formData.get("role")), company: str(formData.get("company")), message, rating: num(formData.get("rating")) ?? 5, image_url: str(formData.get("image_url")), order: num(formData.get("order")) ?? 0, featured: bool(formData.get("featured")), }; if (id) { await adminDB.updateRow({ databaseId: DATABASE_ID, tableId: TABLES.testimonials, rowId: id, data, }); } else { await adminDB.createRow({ databaseId: DATABASE_ID, tableId: TABLES.testimonials, rowId: ID.unique(), data, }); } revalidatePath("/admin/referanslar"); revalidatePath("/"); } export async function deleteTestimonial(formData: FormData) { await gate(); const id = String(formData.get("id")); await adminDB.deleteRow({ databaseId: DATABASE_ID, tableId: TABLES.testimonials, rowId: id, }); revalidatePath("/admin/referanslar"); } // ─── SEO Settings (singleton) ──────────────────────────────────── export async function saveSeoSettings(formData: FormData) { await gate(); const data = { site_name: str(formData.get("site_name")), site_description: str(formData.get("site_description")), default_og_image: str(formData.get("default_og_image")), twitter_handle: str(formData.get("twitter_handle")), facebook_url: str(formData.get("facebook_url")), linkedin_url: str(formData.get("linkedin_url")), instagram_url: str(formData.get("instagram_url")), google_site_verification: str(formData.get("google_site_verification")), gtm_id: str(formData.get("gtm_id")), }; try { await adminDB.updateRow({ databaseId: DATABASE_ID, tableId: TABLES.seoSettings, rowId: "global", data, }); } catch { await adminDB.createRow({ databaseId: DATABASE_ID, tableId: TABLES.seoSettings, rowId: "global", data, }); } revalidatePath("/", "layout"); revalidatePath("/admin/seo"); } // ─── SEO Page (per path) ───────────────────────────────────────── export async function saveSeoPage(formData: FormData) { await gate(); const id = str(formData.get("id")); const path = str(formData.get("path")); if (!path) throw new Error("Path zorunlu"); const data = { path, title: str(formData.get("title")), description: str(formData.get("description")), og_image: str(formData.get("og_image")), canonical: str(formData.get("canonical")), noindex: bool(formData.get("noindex")), }; if (id) { await adminDB.updateRow({ databaseId: DATABASE_ID, tableId: TABLES.seoPages, rowId: id, data, }); } else { await adminDB.createRow({ databaseId: DATABASE_ID, tableId: TABLES.seoPages, rowId: ID.unique(), data, }); } revalidatePath(path); revalidatePath("/admin/seo"); } export async function deleteSeoPage(formData: FormData) { await gate(); const id = String(formData.get("id")); await adminDB.deleteRow({ databaseId: DATABASE_ID, tableId: TABLES.seoPages, rowId: id, }); revalidatePath("/admin/seo"); } // ─── Contact messages ──────────────────────────────────────────── export async function updateMessageStatus(formData: FormData) { await gate(); const id = String(formData.get("id")); const status = String(formData.get("status")) as | "new" | "read" | "replied" | "archived"; await adminDB.updateRow({ databaseId: DATABASE_ID, tableId: TABLES.contactMessages, rowId: id, data: { status }, }); revalidatePath("/admin/iletisim"); } export async function deleteMessage(formData: FormData) { await gate(); const id = String(formData.get("id")); await adminDB.deleteRow({ databaseId: DATABASE_ID, tableId: TABLES.contactMessages, rowId: id, }); revalidatePath("/admin/iletisim"); }