"use client"; import { useEffect, useState } from "react"; import { useRouter } from "next/navigation"; import Swal from "sweetalert2"; interface User { id: string; name: string | null; email: string; role: string; emailVerified: boolean; createdAt: string; } interface AdminApiKeyRow { id: string; name: string; keyPreview: string; expiresAt: string | null; daysRemaining: number | null; remainingLabel: string; lastUsedAt: string | null; isActive: boolean; createdAt: string; } interface Session { user: { id: string; email: string; name?: string; role?: string; }; } export default function AdminPanel() { const router = useRouter(); const [users, setUsers] = useState([]); const [loading, setLoading] = useState(true); const [currentUserRole, setCurrentUserRole] = useState(""); const [keysModalUser, setKeysModalUser] = useState(null); const [userKeys, setUserKeys] = useState([]); const [keysLoading, setKeysLoading] = useState(false); const [keysPatching, setKeysPatching] = useState(null); const [expiryDraft, setExpiryDraft] = useState>({}); useEffect(() => { checkAuth(); }, []); const checkAuth = async () => { try { const res = await fetch("/api/auth/get-session", { credentials: "include", }); if (!res.ok) { router.push("/login"); return; } const session: Session = await res.json(); if (!session.user || session.user.role !== "admin") { await Swal.fire({ icon: "error", title: "Erişim Engellendi", text: "Bu sayfaya erişim yetkiniz yok. Sadece adminler görebilir.", confirmButtonColor: "#3b82f6", }); router.push("/"); return; } setCurrentUserRole(session.user.role || "user"); await fetchUsers(); } catch (err) { router.push("/login"); } }; const fetchUsers = async () => { setLoading(true); try { const res = await fetch("/api/admin/users", { credentials: "include", }); if (!res.ok) { if (res.status === 401) { router.push("/login"); return; } if (res.status === 403) { await Swal.fire({ icon: "error", title: "Yetki Hatası", text: "Bu sayfaya erişim yetkiniz yok.", confirmButtonColor: "#3b82f6", }); return; } throw new Error("Kullanıcılar yüklenemedi"); } const data = await res.json(); setUsers(data.data.users); } catch (err: any) { await Swal.fire({ icon: "error", title: "Hata", text: err.message, confirmButtonColor: "#3b82f6", }); } finally { setLoading(false); } }; const changeRole = async (userId: string, newRole: string, currentRole: string) => { const result = await Swal.fire({ title: "Rol Değiştir", text: `Bu kullanıcının rolünü "${currentRole}" → "${newRole}" olarak değiştirmek istediğinizden emin misiniz?`, icon: "question", showCancelButton: true, confirmButtonColor: "#3b82f6", cancelButtonColor: "#6b7280", confirmButtonText: "Evet, değiştir", cancelButtonText: "İptal", }); if (!result.isConfirmed) { await fetchUsers(); return; } try { const res = await fetch(`/api/admin/users/${userId}/role`, { method: "PATCH", credentials: "include", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ role: newRole }), }); if (!res.ok) { const data = await res.json(); throw new Error(data.error || "Rol güncellenemedi"); } await Swal.fire({ icon: "success", title: "Başarılı!", text: "Kullanıcı rolü güncellendi", timer: 2000, showConfirmButton: false, }); await fetchUsers(); } catch (err: any) { await Swal.fire({ icon: "error", title: "Hata", text: err.message, confirmButtonColor: "#3b82f6", }); await fetchUsers(); } }; const toggleEmailVerification = async (userId: string, currentStatus: boolean, email: string) => { const newStatus = !currentStatus; const result = await Swal.fire({ title: "Email Doğrulama", text: `${email} için email doğrulamasını ${newStatus ? "aktif" : "pasif"} yapmak istiyor musunuz?`, icon: "question", showCancelButton: true, confirmButtonColor: "#3b82f6", cancelButtonColor: "#6b7280", confirmButtonText: "Evet, değiştir", cancelButtonText: "İptal", }); if (!result.isConfirmed) { return; } try { const res = await fetch(`/api/admin/users/${userId}/verification`, { method: "PATCH", credentials: "include", headers: { "Content-Type": "application/json", }, body: JSON.stringify({ emailVerified: newStatus }), }); if (!res.ok) { const data = await res.json(); throw new Error(data.error || "Doğrulama güncellenemedi"); } await Swal.fire({ icon: "success", title: "Başarılı!", text: `Email doğrulama ${newStatus ? "aktif edildi" : "pasif edildi"}`, timer: 2000, showConfirmButton: false, }); await fetchUsers(); } catch (err: any) { await Swal.fire({ icon: "error", title: "Hata", text: err.message, confirmButtonColor: "#3b82f6", }); } }; const fetchUserKeysList = async (userId: string) => { setKeysLoading(true); try { const res = await fetch(`/api/v1/admin/users/${userId}/api-keys`, { credentials: "include", }); const data = await res.json(); if (!res.ok) { throw new Error(data.error || "Anahtarlar yüklenemedi"); } setUserKeys(data.data?.keys || []); } finally { setKeysLoading(false); } }; const openApiKeysModal = async (u: User) => { setKeysModalUser(u); setUserKeys([]); setExpiryDraft({}); try { await fetchUserKeysList(u.id); } catch (err: any) { await Swal.fire({ icon: "error", title: "Hata", text: err.message, confirmButtonColor: "#3b82f6", }); setKeysModalUser(null); } }; const patchKeyExpiry = async (userId: string, keyId: string, draft: string) => { let expiresInDays: number | null; const t = draft.trim(); if (t === "") { expiresInDays = null; } else { const n = parseInt(t, 10); if (!Number.isFinite(n) || n < 0) { await Swal.fire({ icon: "warning", title: "Geçersiz", text: "Gün sayısı boş (süresiz) veya 0 veya pozitif tam sayı olmalı.", confirmButtonColor: "#3b82f6", }); return; } expiresInDays = n === 0 ? null : n; } setKeysPatching(keyId); try { const res = await fetch( `/api/v1/admin/users/${userId}/api-keys/${keyId}`, { method: "PATCH", credentials: "include", headers: { "Content-Type": "application/json" }, body: JSON.stringify({ expiresInDays }), } ); const data = await res.json(); if (!res.ok) { throw new Error(data.error || "Güncellenemedi"); } await Swal.fire({ icon: "success", title: "Güncellendi", text: "API anahtarı süresi kaydedildi.", timer: 1800, showConfirmButton: false, }); setExpiryDraft((prev) => { const next = { ...prev }; delete next[keyId]; return next; }); await fetchUserKeysList(userId); } catch (err: any) { await Swal.fire({ icon: "error", title: "Hata", text: err.message, confirmButtonColor: "#3b82f6", }); } finally { setKeysPatching(null); } }; const deleteUser = async (userId: string, email: string) => { const result = await Swal.fire({ title: "Kullanıcıyı Sil", html: `${email} kullanıcısını silmek istediğinizden emin misiniz?

⚠️ Bu işlem geri alınamaz!
Kullanıcının tüm resimleri ve verileri silinecek.`, icon: "warning", showCancelButton: true, confirmButtonColor: "#ef4444", cancelButtonColor: "#6b7280", confirmButtonText: "Evet, sil!", cancelButtonText: "İptal", }); if (!result.isConfirmed) { return; } try { const res = await fetch(`/api/admin/users/${userId}`, { method: "DELETE", credentials: "include", }); if (!res.ok) { const data = await res.json(); throw new Error(data.error || "Kullanıcı silinemedi"); } await Swal.fire({ icon: "success", title: "Silindi!", text: "Kullanıcı başarıyla silindi", timer: 2000, showConfirmButton: false, }); await fetchUsers(); } catch (err: any) { await Swal.fire({ icon: "error", title: "Hata", text: err.message, confirmButtonColor: "#3b82f6", }); } }; const getRoleBadgeColor = (role: string) => { switch (role) { case "admin": return "bg-red-100 text-red-800 border-red-200"; case "moderator": return "bg-blue-100 text-blue-800 border-blue-200"; default: return "bg-gray-100 text-gray-800 border-gray-200"; } }; if (loading) { return (

Yükleniyor...

); } return (

Admin Panel

Kullanıcı yönetimi ve rol atama

{users.map((user) => ( ))}
Kullanıcı Email Rol Doğrulama Kayıt Tarihi İşlemler
{user.name || "İsimsiz"}
{user.id.substring(0, 8)}
{user.email} {new Date(user.createdAt).toLocaleDateString("tr-TR")}
{keysModalUser && (

API anahtarları

{keysModalUser.email} — süre: bugünden itibaren gün sayısı (boş veya 0 = süresiz)

{keysLoading ? (

Yükleniyor…

) : userKeys.length === 0 ? (

Bu kullanıcının henüz API anahtarı yok.

) : (
{userKeys.map((k) => ( ))}
İsim Önizleme Mevcut bitiş Kalan süre Yeni süre (gün)
{k.name} {k.keyPreview} {k.expiresAt ? new Date(k.expiresAt).toLocaleString("tr-TR") : "—"} {k.remainingLabel} setExpiryDraft((prev) => ({ ...prev, [k.id]: e.target.value, })) } className="w-28 rounded border border-gray-300 px-2 py-1 text-sm" />
)}
)}

Toplam Kullanıcı

{users.length}

Admin Sayısı

{users.filter((u) => u.role === "admin").length}

Moderatör Sayısı

{users.filter((u) => u.role === "moderator").length}

Doğrulananlar

{users.filter((u) => u.emailVerified).length}

); }