Files
moybeach-main/app/admin/settings/page.tsx
T
2026-07-10 09:30:48 +03:00

261 lines
17 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { prisma } from '@/lib/db';
import { getSession } from '@/lib/auth';
import { redirect } from 'next/navigation'
import { Save } from 'lucide-react';
import { updateSiteSettings } from '../actions';
import { revalidatePath } from 'next/cache';
import { uploadImage } from '@/lib/openinary';
export default async function SettingsAdminPage() {
const session = await getSession();
if (!session) redirect('/admin/login');
const settings = await prisma.siteSettings.findFirst();
return (
<div>
<div className="flex justify-between items-center mb-8">
<h1 className="text-3xl font-bold">Site Ayarları</h1>
</div>
<div className="bg-white dark:bg-slate-900 rounded-2xl shadow-sm border border-slate-200 dark:border-slate-800 p-6">
<form action={async (formData: FormData) => {
'use server';
const data: any = {
phone: formData.get('phone') as string,
email: formData.get('email') as string,
addressText1: formData.get('addressText1') as string,
addressText2: formData.get('addressText2') as string,
workingHours: formData.get('workingHours') as string,
instagramUrl: formData.get('instagramUrl') as string,
facebookUrl: formData.get('facebookUrl') as string,
youtubeUrl: formData.get('youtubeUrl') as string,
whatsappNumber: formData.get('whatsappNumber') as string,
// SEO fields
siteUrl: formData.get('siteUrl') as string,
metaTitleTr: formData.get('metaTitleTr') as string,
metaTitleEn: formData.get('metaTitleEn') as string,
metaDescTr: formData.get('metaDescTr') as string,
metaDescEn: formData.get('metaDescEn') as string,
metaKeywordsTr: formData.get('metaKeywordsTr') as string,
metaKeywordsEn: formData.get('metaKeywordsEn') as string,
twitterHandle: formData.get('twitterHandle') as string,
googleVerify: formData.get('googleVerify') as string,
};
const logoFile = formData.get('logo') as File;
if (logoFile && logoFile.size > 0) {
data.logoUrl = await uploadImage(logoFile);
}
const ogImageFile = formData.get('ogImage') as File;
if (ogImageFile && ogImageFile.size > 0) {
data.ogImage = await uploadImage(ogImageFile);
}
await updateSiteSettings(data);
revalidatePath('/', 'layout');
redirect('/admin/settings');
}} className="space-y-10">
{/* Logo Section */}
<section>
<h2 className="text-xl font-bold mb-4 border-b border-slate-200 dark:border-slate-700 pb-2">Logo Ayarları</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Yeni Logo Yükle</label>
<input
type="file"
name="logo"
accept="image/*"
className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100"
/>
</div>
{settings?.logoUrl && (
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Mevcut Logo</label>
<div className="p-4 bg-slate-800 rounded-lg w-fit">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={settings.logoUrl} alt="Logo" className="h-12 w-auto object-contain" />
</div>
</div>
)}
</div>
</section>
{/* Contact Section */}
<section>
<h2 className="text-xl font-bold mb-4 border-b border-slate-200 dark:border-slate-700 pb-2">İletişim Bilgileri</h2>
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Telefon</label>
<input type="text" name="phone" defaultValue={settings?.phone || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="+90 534 465 62 35" />
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">E-posta</label>
<input type="email" name="email" defaultValue={settings?.email || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="info@moybeachakyaka.com" />
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Çalışma Saatleri</label>
<input type="text" name="workingHours" defaultValue={settings?.workingHours || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="Her Gün: 09:00 - 02:00" />
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">WhatsApp Numarası</label>
<input type="text" name="whatsappNumber" defaultValue={settings?.whatsappNumber || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="905344656235" />
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Adres Satırı 1</label>
<input type="text" name="addressText1" defaultValue={settings?.addressText1 || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="Akyaka Mah. Gümüş Sok." />
</div>
<div className="md:col-span-2">
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Adres Satırı 2</label>
<input type="text" name="addressText2" defaultValue={settings?.addressText2 || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="Ula, Muğla / Türkiye" />
</div>
</div>
</section>
{/* Social Media */}
<section>
<h2 className="text-xl font-bold mb-4 border-b border-slate-200 dark:border-slate-700 pb-2">Sosyal Medya Linkleri</h2>
<div className="grid grid-cols-1 md:grid-cols-3 gap-6">
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Instagram URL</label>
<input type="url" name="instagramUrl" defaultValue={settings?.instagramUrl || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="https://instagram.com/moybeachakyaka" />
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Facebook URL</label>
<input type="url" name="facebookUrl" defaultValue={settings?.facebookUrl || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="https://facebook.com/moybeachakyaka" />
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">YouTube URL</label>
<input type="url" name="youtubeUrl" defaultValue={settings?.youtubeUrl || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="https://youtube.com/@moybeach" />
</div>
</div>
</section>
{/* SEO Section */}
<section>
<h2 className="text-xl font-bold mb-1 border-b border-slate-200 dark:border-slate-700 pb-2 flex items-center gap-2">
🔍 SEO & Metadata Ayarları
</h2>
<p className="text-sm text-slate-500 dark:text-slate-400 mb-6">
Arama motorları ve sosyal medya paylaşımları için meta bilgileri.
</p>
{/* Site URL */}
<div className="mb-6">
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Site URL <span className="text-slate-400 font-normal">(canonical & sitemap için)</span>
</label>
<input type="url" name="siteUrl" defaultValue={settings?.siteUrl || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="https://moybeach.com" />
</div>
{/* Meta Titles */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Meta Başlık Türkçe
</label>
<input type="text" name="metaTitleTr" defaultValue={settings?.metaTitleTr || ""} maxLength={60} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="Moy Beach Akyaka | Lüks & Huzur" />
<p className="text-xs text-slate-400 mt-1">Max 60 karakter önerilir</p>
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Meta Başlık İngilizce
</label>
<input type="text" name="metaTitleEn" defaultValue={settings?.metaTitleEn || ""} maxLength={60} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="Moy Beach Akyaka | Luxury & Serenity" />
<p className="text-xs text-slate-400 mt-1">Max 60 characters recommended</p>
</div>
</div>
{/* Meta Descriptions */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Meta Açıklama Türkçe
</label>
<textarea name="metaDescTr" rows={3} defaultValue={settings?.metaDescTr || ""} maxLength={160} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500 resize-none" placeholder="Akyaka'nın kalbinde doğayla iç içe lüks bir beach, restoran ve otel deneyimi." />
<p className="text-xs text-slate-400 mt-1">Max 160 karakter önerilir</p>
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Meta Açıklama İngilizce
</label>
<textarea name="metaDescEn" rows={3} defaultValue={settings?.metaDescEn || ""} maxLength={160} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500 resize-none" placeholder="A luxury beach, restaurant and hotel experience in the heart of Akyaka." />
<p className="text-xs text-slate-400 mt-1">Max 160 characters recommended</p>
</div>
</div>
{/* Keywords */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Anahtar Kelimeler Türkçe
</label>
<input type="text" name="metaKeywordsTr" defaultValue={settings?.metaKeywordsTr || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="moy beach, akyaka, beach, restoran, otel, muğla" />
<p className="text-xs text-slate-400 mt-1">Virgülle ayırın</p>
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Keywords English
</label>
<input type="text" name="metaKeywordsEn" defaultValue={settings?.metaKeywordsEn || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="moy beach, akyaka, beach, restaurant, hotel, mugla" />
<p className="text-xs text-slate-400 mt-1">Separate with commas</p>
</div>
</div>
{/* OG Image */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6 mb-6">
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
OG / Paylaşım Görseli
<span className="text-slate-400 font-normal ml-1">(1200×630px önerilir)</span>
</label>
<input type="file" name="ogImage" accept="image/*" className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500 file:mr-4 file:py-2 file:px-4 file:rounded-full file:border-0 file:text-sm file:font-semibold file:bg-blue-50 file:text-blue-700 hover:file:bg-blue-100" />
</div>
{settings?.ogImage && (
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">Mevcut OG Görseli</label>
<div className="rounded-lg overflow-hidden border border-slate-200 dark:border-slate-700 w-full max-w-xs">
{/* eslint-disable-next-line @next/next/no-img-element */}
<img src={settings.ogImage} alt="OG Image" className="w-full h-auto object-cover" />
</div>
</div>
)}
</div>
{/* Twitter & Google Verify */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Twitter/X Handle
<span className="text-slate-400 font-normal ml-1">(@işareti olmadan)</span>
</label>
<div className="relative">
<span className="absolute left-3 top-1/2 -translate-y-1/2 text-slate-400 font-medium">@</span>
<input type="text" name="twitterHandle" defaultValue={settings?.twitterHandle || ""} className="w-full pl-8 pr-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="moybeachakyaka" />
</div>
</div>
<div>
<label className="block text-sm font-medium text-slate-700 dark:text-slate-300 mb-1">
Google Search Console Doğrulama Kodu
</label>
<input type="text" name="googleVerify" defaultValue={settings?.googleVerify || ""} className="w-full px-4 py-2 bg-slate-50 dark:bg-slate-800 border border-slate-200 dark:border-slate-700 rounded-lg outline-none focus:ring-2 focus:ring-blue-500" placeholder="google-site-verification kodu" />
<p className="text-xs text-slate-400 mt-1">Google Search Console Doğrulama HTML Meta Tag'deki content değeri</p>
</div>
</div>
</section>
<div className="pt-4 flex justify-end">
<button type="submit" className="flex items-center space-x-2 bg-blue-600 hover:bg-blue-700 text-white px-8 py-3 rounded-lg transition-colors font-medium">
<Save className="w-5 h-5" />
<span>Ayarları Kaydet</span>
</button>
</div>
</form>
</div>
</div>
);
}