feat: admin auth, web menu template studio, live text editing & Ayris Tech footer backlink

This commit is contained in:
AyrisAI
2026-08-23 01:45:00 +03:00
parent e7ba6c7807
commit 1f8195ff67
48 changed files with 5588 additions and 402 deletions
@@ -0,0 +1,213 @@
"use client";
import React, { useEffect, useState } from "react";
import Link from "next/link";
import { usePathname, useRouter } from "next/navigation";
import AdminAuthGuard from "@/components/AdminAuthGuard";
import { getAdminSession, logoutAdmin, AdminUser } from "@/lib/admin-auth";
import { AyrisFooterBadge } from "@/components/AyrisFooterBadge";
export default function AdminLayoutClient({ children }: { children: React.ReactNode }) {
const pathname = usePathname();
const router = useRouter();
const [adminUser, setAdminUser] = useState<AdminUser | null>(null);
useEffect(() => {
setAdminUser(getAdminSession());
}, [pathname]);
const handleLogout = async () => {
if (confirm("Menulio Admin panelinden çıkış yapmak istediğinize emin misiniz?")) {
await logoutAdmin();
router.replace("/admin/login");
}
};
// Login page doesn't use the Admin Dashboard Shell (sidebar, header, etc.)
if (pathname === "/admin/login") {
return <>{children}</>;
}
return (
<AdminAuthGuard>
<div className="min-h-screen bg-[#09090b] text-[#fafafa] flex flex-col md:flex-row antialiased selection:bg-[#D4AF37]/30 selection:text-[#D4AF37]">
{/* Sol Sidebar */}
<aside className="w-full md:w-72 bg-[#121215] border-b md:border-b-0 md:border-r border-white/10 flex flex-col justify-between shrink-0">
<div>
{/* Logo & Başlık */}
<div className="p-6 border-b border-white/10 flex items-center justify-between">
<Link href="/admin" className="flex items-center gap-3 group">
<div className="w-9 h-9 rounded-xl bg-gradient-to-tr from-[#D4AF37] to-[#F59E0B] flex items-center justify-center shadow-lg shadow-[#D4AF37]/20">
<span className="font-extrabold text-[#0C0C0E] text-lg tracking-wider">M</span>
</div>
<div>
<div className="font-bold text-white tracking-wide text-base group-hover:text-[#D4AF37] transition-colors">
MENULIO
</div>
<div className="text-[10px] font-semibold text-[#D4AF37] tracking-widest uppercase">
Admin Stüdyosu
</div>
</div>
</Link>
</div>
{/* Navigasyon Linkleri */}
<nav className="p-4 space-y-1.5">
<div className="text-[10px] font-bold text-zinc-500 uppercase tracking-wider px-3 mb-2">
Tasarım & Şablonlar
</div>
<Link
href="/admin/templates"
className={`flex items-center gap-3 px-3 py-2.5 rounded-xl font-semibold text-sm transition-all shadow-sm ${
pathname === "/admin/templates"
? "bg-[#D4AF37]/10 text-[#D4AF37] border border-[#D4AF37]/25"
: "text-zinc-400 hover:text-white hover:bg-white/5"
}`}
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M4 16l4.586-4.586a2 2 0 012.828 0L16 16m-2-2l1.586-1.586a2 2 0 012.828 0L20 14m-6-6h.01M6 20h12a2 2 0 002-2H6a2 2 0 00-2 2v12a2 2 0 002 2z" />
</svg>
QR Şablon Stüdyosu
<span className="ml-auto text-[10px] bg-[#D4AF37] text-black font-extrabold px-1.5 py-0.5 rounded-full">
Masa Kartı
</span>
</Link>
<Link
href="/admin/menu-templates"
className={`flex items-center gap-3 px-3 py-2.5 rounded-xl font-semibold text-sm transition-all shadow-sm ${
pathname === "/admin/menu-templates"
? "bg-[#D4AF37]/10 text-[#D4AF37] border border-[#D4AF37]/25"
: "text-zinc-400 hover:text-white hover:bg-white/5"
}`}
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
Web Menü Şablonları
<span className="ml-auto text-[10px] bg-[#D4AF37] text-black font-extrabold px-1.5 py-0.5 rounded-full">
10 Tema
</span>
</Link>
<Link
href="/admin"
className={`flex items-center gap-3 px-3 py-2.5 rounded-xl text-sm font-medium transition-all ${
pathname === "/admin"
? "bg-[#D4AF37]/10 text-[#D4AF37] border border-[#D4AF37]/25"
: "text-zinc-400 hover:text-white hover:bg-white/5"
}`}
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M9 19v-6a2 2 0 00-2-2H5a2 2 0 00-2 2v6a2 2 0 002 2h2a2 2 0 002-2zm0 0V9a2 2 0 012-2h2a2 2 0 012 2v10m-6 0a2 2 0 002 2h2a2 2 0 002-2m0 0V5a2 2 0 012-2h2a2 2 0 012 2v14a2 2 0 01-2 2h-2a2 2 0 01-2-2z" />
</svg>
Genel Bakış & İstatistikler
</Link>
<div className="text-[10px] font-bold text-zinc-500 uppercase tracking-wider px-3 pt-4 mb-2">
Önizleme & Test
</div>
<Link
href="/templates"
target="_blank"
className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-zinc-400 hover:text-white hover:bg-white/5 text-sm font-medium transition-all"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 18h.01M8 21h8a2 2 0 002-2V5a2 2 0 00-2-2H8a2 2 0 00-2 2v14a2 2 0 002 2z" />
</svg>
Web Menü Simülatörü
<svg className="w-3.5 h-3.5 ml-auto text-zinc-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</Link>
<Link
href="/qr"
target="_blank"
className="flex items-center gap-3 px-3 py-2.5 rounded-xl text-zinc-400 hover:text-white hover:bg-white/5 text-sm font-medium transition-all"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M12 4v1m6 11h2m-6 0h-2v4m0-11v3m0 0h.01M12 12h4.01M16 20h4M4 12h4m12 0h.01M5 8h2a1 1 0 001-1V5a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1zm12 0h2a1 1 0 001-1V5a1 1 0 00-1-1h-2a1 1 0 00-1 1v2a1 1 0 001 1zM5 20h2a1 1 0 001-1v-2a1 1 0 00-1-1H5a1 1 0 00-1 1v2a1 1 0 001 1z" />
</svg>
Web Masa Standı Üretici
<svg className="w-3.5 h-3.5 ml-auto text-zinc-600" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14" />
</svg>
</Link>
</nav>
</div>
{/* Alt Yönetici Profil & Çıkış Kartı */}
<div className="p-4 border-t border-white/10 space-y-3">
<div className="p-3 rounded-xl bg-white/[0.04] border border-white/5 flex items-center justify-between">
<div className="flex items-center gap-2.5 min-w-0">
<div className="w-8 h-8 rounded-lg bg-[#D4AF37]/20 border border-[#D4AF37]/40 flex items-center justify-center shrink-0">
<span className="font-extrabold text-[#D4AF37] text-xs">
{adminUser?.email?.[0]?.toUpperCase() || "A"}
</span>
</div>
<div className="min-w-0">
<div className="text-xs font-bold text-white truncate">
{adminUser?.name || "Yönetici"}
</div>
<div className="text-[10px] text-zinc-400 truncate">
{adminUser?.email || "admin@menul.io"}
</div>
</div>
</div>
<button
type="button"
onClick={handleLogout}
className="p-1.5 rounded-lg text-zinc-400 hover:text-red-400 hover:bg-red-500/10 transition-colors"
title="Çıkış Yap"
>
<svg className="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
</button>
</div>
</div>
</aside>
{/* Sağ Ana İçerik */}
<main className="flex-1 flex flex-col min-w-0 bg-[#0C0C0E]">
{/* Üst Bar */}
<header className="h-16 border-b border-white/10 px-6 flex items-center justify-between bg-[#121215]/50 backdrop-blur shrink-0">
<div className="flex items-center gap-3">
<div className="text-sm font-semibold text-zinc-300">
Dinamik Şablon & İçerik Yönetimi
</div>
</div>
<div className="flex items-center gap-4">
<div className="hidden sm:flex items-center gap-2 px-3 py-1.5 rounded-full bg-white/5 border border-white/10 text-xs text-zinc-300">
<span className="w-2 h-2 rounded-full bg-[#D4AF37]" />
Oturum: <span className="font-semibold text-[#D4AF37]">{adminUser?.role === "super_admin" ? "Süper Admin" : "Yönetici"}</span>
</div>
<button
type="button"
onClick={handleLogout}
className="flex items-center gap-1.5 px-3 py-1.5 rounded-xl bg-red-500/10 border border-red-500/20 text-xs font-semibold text-red-400 hover:bg-red-500/20 transition-all cursor-pointer"
>
<svg className="w-3.5 h-3.5" fill="none" stroke="currentColor" viewBox="0 0 24 24">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth="2" d="M17 16l4-4m0 0l-4-4m4 4H7m6 4v1a3 3 0 01-3 3H6a3 3 0 01-3-3V7a3 3 0 013-3h4a3 3 0 013 3v1" />
</svg>
Çıkış Yap
</button>
</div>
</header>
{/* Sayfa İçeriği */}
<div className="flex-1 p-6 md:p-8 overflow-y-auto">
{children}
</div>
<AyrisFooterBadge className="mt-auto border-t border-white/10 bg-[#09090b]" />
</main>
</div>
</AdminAuthGuard>
);
}