Files
kozmos-web/components/admin/AdminsClient.tsx
T

208 lines
7.3 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.
"use client";
import { useState } from "react";
import { Plus, Edit2, Trash2, X } from "lucide-react";
import { createAdmin, updateAdmin, deleteAdmin } from "@/app/actions/admin";
type Admin = {
id: string;
name: string;
email: string;
createdAt: Date;
};
export default function AdminsClient({ initialAdmins }: { initialAdmins: Admin[] }) {
const [admins, setAdmins] = useState<Admin[]>(initialAdmins);
const [isModalOpen, setIsModalOpen] = useState(false);
const [editingAdmin, setEditingAdmin] = useState<Admin | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const openModal = (admin?: Admin) => {
setEditingAdmin(admin || null);
setError(null);
setIsModalOpen(true);
};
const closeModal = () => {
setIsModalOpen(false);
setEditingAdmin(null);
setError(null);
};
const handleSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
setLoading(true);
setError(null);
const formData = new FormData(e.currentTarget);
let result;
if (editingAdmin) {
result = await updateAdmin(editingAdmin.id, formData);
} else {
result = await createAdmin(formData);
}
if (result.success) {
// Reload sayfa verileri için basit bir çözüm
window.location.reload();
} else {
setError(result.error || "Bir hata oluştu");
setLoading(false);
}
};
const handleDelete = async (id: string) => {
if (!confirm("Bu yöneticiyi silmek istediğinize emin misiniz?")) return;
setLoading(true);
const result = await deleteAdmin(id);
if (result.success) {
window.location.reload();
} else {
alert(result.error || "Silinirken hata oluştu");
setLoading(false);
}
};
return (
<div className="p-8">
<div className="flex justify-between items-center mb-8">
<h1 className="text-3xl font-serif text-gray-900">Yöneticiler</h1>
<button
onClick={() => openModal()}
className="bg-turquoise text-white px-4 py-2 rounded-lg flex items-center gap-2 hover:bg-turquoise/90 transition-colors"
>
<Plus className="w-4 h-4" />
Yeni Ekle
</button>
</div>
<div className="bg-white rounded-xl shadow-sm border border-gray-100 overflow-hidden">
<table className="w-full text-left border-collapse">
<thead>
<tr className="bg-gray-50 border-b border-gray-100 text-sm text-gray-500">
<th className="p-4 font-medium">İsim</th>
<th className="p-4 font-medium">E-posta</th>
<th className="p-4 font-medium">Kayıt Tarihi</th>
<th className="p-4 font-medium text-right">İşlemler</th>
</tr>
</thead>
<tbody>
{admins.map((admin) => (
<tr key={admin.id} className="border-b border-gray-50 hover:bg-gray-50/50">
<td className="p-4 text-gray-900 font-medium">{admin.name}</td>
<td className="p-4 text-gray-600">{admin.email}</td>
<td className="p-4 text-gray-500 text-sm">
{new Date(admin.createdAt).toLocaleDateString("tr-TR")}
</td>
<td className="p-4 flex justify-end gap-2">
<button
onClick={() => openModal(admin)}
className="p-2 text-blue-600 hover:bg-blue-50 rounded-lg transition-colors"
title="Düzenle"
>
<Edit2 className="w-4 h-4" />
</button>
<button
onClick={() => handleDelete(admin.id)}
className="p-2 text-red-600 hover:bg-red-50 rounded-lg transition-colors"
title="Sil"
>
<Trash2 className="w-4 h-4" />
</button>
</td>
</tr>
))}
{admins.length === 0 && (
<tr>
<td colSpan={4} className="p-8 text-center text-gray-500">
Henüz bir yönetici bulunmuyor.
</td>
</tr>
)}
</tbody>
</table>
</div>
{/* Modal */}
{isModalOpen && (
<div className="fixed inset-0 z-50 flex items-center justify-center bg-black/50 p-4">
<div className="bg-white rounded-xl shadow-2xl max-w-md w-full p-6 relative">
<button
onClick={closeModal}
className="absolute top-4 right-4 text-gray-400 hover:text-gray-600"
>
<X className="w-5 h-5" />
</button>
<h2 className="text-xl font-bold text-gray-900 mb-6">
{editingAdmin ? "Yönetici Düzenle" : "Yeni Yönetici Ekle"}
</h2>
{error && (
<div className="bg-red-50 text-red-600 p-3 rounded-lg text-sm mb-4">
{error}
</div>
)}
<form onSubmit={handleSubmit} className="space-y-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">İsim Soyisim</label>
<input
type="text"
name="name"
defaultValue={editingAdmin?.name}
required
className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-turquoise focus:border-transparent outline-none"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">E-posta</label>
<input
type="email"
name="email"
defaultValue={editingAdmin?.email}
required
className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-turquoise focus:border-transparent outline-none"
/>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">
Şifre {editingAdmin && <span className="text-gray-400 font-normal">(Değiştirmek istemiyorsanız boş bırakın)</span>}
</label>
<input
type="password"
name="password"
required={!editingAdmin}
className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-turquoise focus:border-transparent outline-none"
/>
</div>
<div className="pt-4 flex justify-end gap-3">
<button
type="button"
onClick={closeModal}
className="px-4 py-2 text-gray-600 hover:bg-gray-100 rounded-lg transition-colors"
>
İptal
</button>
<button
type="submit"
disabled={loading}
className="bg-turquoise text-white px-6 py-2 rounded-lg hover:bg-turquoise/90 transition-colors disabled:opacity-50"
>
{loading ? "Kaydediliyor..." : "Kaydet"}
</button>
</div>
</form>
</div>
</div>
)}
</div>
);
}