Files

257 lines
9.6 KiB
TypeScript
Raw Permalink 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, Star } from "lucide-react";
import { createEvent, updateEvent, deleteEvent } from "@/app/actions/events";
type Event = {
id: string;
title: string;
time: string;
tag: string;
iconType: string;
colorTheme: string;
isFeatured: boolean;
};
export default function EventsClient({ initialEvents }: { initialEvents: Event[] }) {
const [events] = useState<Event[]>(initialEvents);
const [isModalOpen, setIsModalOpen] = useState(false);
const [editingEvent, setEditingEvent] = useState<Event | null>(null);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const openModal = (event?: Event) => {
setEditingEvent(event || null);
setError(null);
setIsModalOpen(true);
};
const closeModal = () => {
setIsModalOpen(false);
setEditingEvent(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 (editingEvent) {
result = await updateEvent(editingEvent.id, formData);
} else {
result = await createEvent(formData);
}
if (result.success) {
window.location.reload();
} else {
setError(result.error || "Bir hata oluştu");
setLoading(false);
}
};
const handleDelete = async (id: string) => {
if (!confirm("Bu etkinliği silmek istediğinize emin misiniz?")) return;
setLoading(true);
const result = await deleteEvent(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">Etkinlikler</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 w-12">Öne Çıkan</th>
<th className="p-4 font-medium">Başlık</th>
<th className="p-4 font-medium">Zaman</th>
<th className="p-4 font-medium">Etiket</th>
<th className="p-4 font-medium text-right">İşlemler</th>
</tr>
</thead>
<tbody>
{events.map((event) => (
<tr key={event.id} className="border-b border-gray-50 hover:bg-gray-50/50">
<td className="p-4 text-center">
{event.isFeatured ? <Star className="w-5 h-5 text-yellow-400 fill-current" /> : ""}
</td>
<td className="p-4 text-gray-900 font-medium">{event.title}</td>
<td className="p-4 text-gray-600">{event.time}</td>
<td className="p-4 text-gray-500 text-sm">
<span className="px-2 py-1 bg-gray-100 rounded text-xs font-bold">{event.tag}</span>
</td>
<td className="p-4 flex justify-end gap-2">
<button
onClick={() => openModal(event)}
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(event.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>
))}
{events.length === 0 && (
<tr>
<td colSpan={5} className="p-8 text-center text-gray-500">
Henüz bir etkinlik 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-lg w-full p-6 relative max-h-[90vh] overflow-y-auto">
<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">
{editingEvent ? "Etkinlik Düzenle" : "Yeni Etkinlik 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">Başlık</label>
<input
type="text"
name="title"
defaultValue={editingEvent?.title}
placeholder="Örn: DJ Gecesi"
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">Zaman</label>
<input
type="text"
name="time"
defaultValue={editingEvent?.time}
placeholder="Örn: Cuma & Cumartesi, 22:00"
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">Etiket (Gün/Kısa Bilgi)</label>
<input
type="text"
name="tag"
defaultValue={editingEvent?.tag}
placeholder="Örn: CUM veya ÖZEL"
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 className="grid grid-cols-2 gap-4">
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">İkon Tipi</label>
<select
name="iconType"
defaultValue={editingEvent?.iconType || "music"}
className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-turquoise outline-none"
>
<option value="music">Müzik Notası</option>
<option value="dj">DJ Diski (Plak)</option>
<option value="glass">Kadeh (Rakı vb.)</option>
</select>
</div>
<div>
<label className="block text-sm font-medium text-gray-700 mb-1">Renk Teması</label>
<select
name="colorTheme"
defaultValue={editingEvent?.colorTheme || "cyan"}
className="w-full border border-gray-300 rounded-lg px-4 py-2 focus:ring-2 focus:ring-turquoise outline-none"
>
<option value="cyan">Mavi (Cyan)</option>
<option value="coral">Mercan (Coral)</option>
<option value="amber">Turuncu (Amber)</option>
</select>
</div>
</div>
<div className="flex items-center gap-3 pt-2">
<input
type="checkbox"
name="isFeatured"
id="isFeatured"
defaultChecked={editingEvent?.isFeatured}
className="w-5 h-5 text-turquoise focus:ring-turquoise border-gray-300 rounded"
/>
<label htmlFor="isFeatured" className="text-sm font-medium text-gray-700">
Öne Çıkan Etkinlik (Ana sayfada en büyük kart olarak gösterilir)
</label>
</div>
<div className="pt-4 flex justify-end gap-3 border-t border-gray-100 mt-4">
<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>
);
}