diff --git a/app/admin/events/page.tsx b/app/admin/events/page.tsx index 6c8ae20f2..5b911f894 100644 --- a/app/admin/events/page.tsx +++ b/app/admin/events/page.tsx @@ -6,26 +6,59 @@ import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@ import { Card, CardContent, CardDescription, CardHeader, CardTitle } from "@/components/ui/card" import { Badge } from "@/components/ui/badge" import { Input } from "@/components/ui/input" -import { Search, Plus, Calendar, MapPin } from "lucide-react" +import { Search, Plus, Calendar, MapPin, Edit, Trash2 } from "lucide-react" import { toast } from "sonner" import { apiFetch } from "@/lib/api-fetch" +import { Dialog, DialogContent, DialogHeader, DialogTitle } from "@/components/ui/dialog" +import { Label } from "@/components/ui/label" +import { Textarea } from "@/components/ui/textarea" +import { Switch } from "@/components/ui/switch" interface Event { id: number slug: string title: string excerpt: string + description: string organizer: string date: string + time: string + duration: string + category: string location: string + capacity: number + price: string + payment: string status: string featured: boolean + registration_required: boolean } export default function AdminEvents() { const [events, setEvents] = useState([]) const [loading, setLoading] = useState(true) const [searchTerm, setSearchTerm] = useState("") + const [isCreateDialogOpen, setIsCreateDialogOpen] = useState(false) + const [editingEvent, setEditingEvent] = useState(null) + const [formData, setFormData] = useState({ + title: "", + slug: "", + excerpt: "", + description: "", + organizer: "", + date: "", + time: "", + duration: "", + category: "", + location: "", + capacity: 0, + price: "Free", + payment: "Not Required", + status: "draft", + featured: false, + registration_required: true + }) + const [formLoading, setFormLoading] = useState(false) const fetchEvents = async () => { try { @@ -50,7 +83,7 @@ export default function AdminEvents() { return } const data = await response.json() - setEvents(data.events || []) + setEvents(data || []) } catch (error) { toast.error("Failed to fetch events") console.error('Fetch error:', error) @@ -76,6 +109,135 @@ export default function AdminEvents() { featured: events.filter(e => e.featured).length } + const handleCreateEvent = async () => { + try { + setFormLoading(true) + + // Generate slug from title if not provided + const slug = formData.slug || formData.title.toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '') + + const eventData = { + ...formData, + slug, + categories: [formData.category], + tags: [], + locations: [formData.location], + registered: 0, + event_type: ["Offline"], + team_size: { min: 1, max: 1 }, + user_types: ["Professionals", "College Students"], + rules: [], + schedule: {}, + faq: {}, + socials: {}, + sponsors: [] + } + + let response + if (editingEvent) { + // Update existing event + response = await apiFetch('/api/admin/events', { + method: 'PUT', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify({ + slug: editingEvent.slug, + data: eventData + }) + }) + } else { + // Create new event + response = await apiFetch('/api/admin/events', { + method: 'POST', + headers: { + 'Content-Type': 'application/json', + }, + body: JSON.stringify(eventData) + }) + } + + if (!response.ok) { + const errorData = await response.json().catch(() => ({})) + const errorMessage = errorData.error || (editingEvent ? 'Failed to update event' : 'Failed to create event') + throw new Error(errorMessage) + } + + toast.success(editingEvent ? 'Event updated successfully!' : 'Event created successfully!') + setIsCreateDialogOpen(false) + setEditingEvent(null) + setFormData({ + title: "", + slug: "", + excerpt: "", + description: "", + organizer: "", + date: "", + time: "", + duration: "", + category: "", + location: "", + capacity: 0, + price: "Free", + payment: "Not Required", + status: "draft", + featured: false, + registration_required: true + }) + fetchEvents() + } catch (error) { + toast.error(editingEvent ? 'Failed to update event' : 'Failed to create event') + console.error('Create/Update event error:', error) + } finally { + setFormLoading(false) + } + } + + const handleEditEvent = (event: Event) => { + setEditingEvent(event) + setFormData({ + title: event.title, + slug: event.slug, + excerpt: event.excerpt, + description: event.description, + organizer: event.organizer, + date: event.date, + time: event.time, + duration: event.duration, + category: event.category, + location: event.location, + capacity: event.capacity, + price: event.price, + payment: event.payment, + status: event.status, + featured: event.featured, + registration_required: event.registration_required + }) + setIsCreateDialogOpen(true) + } + + const handleDeleteEvent = async (slug: string) => { + if (!confirm('Are you sure you want to delete this event?')) { + return + } + + try { + const response = await apiFetch(`/api/admin/events?slug=${slug}`, { + method: 'DELETE' + }) + + if (!response.ok) { + throw new Error('Failed to delete event') + } + + toast.success('Event deleted successfully!') + fetchEvents() + } catch (error) { + toast.error('Failed to delete event') + console.error('Delete event error:', error) + } + } + return (
{/* Header */} @@ -95,7 +257,7 @@ export default function AdminEvents() { - @@ -171,6 +333,7 @@ export default function AdminEvents() { Location Status Featured + Actions @@ -207,6 +370,24 @@ export default function AdminEvents() { )} + +
+ + +
+
))}
@@ -214,6 +395,235 @@ export default function AdminEvents() { )} + + {/* Create Event Dialog */} + { + setIsCreateDialogOpen(open) + if (!open) { + setEditingEvent(null) + setFormData({ + title: "", + slug: "", + excerpt: "", + description: "", + organizer: "", + date: "", + time: "", + duration: "", + category: "", + location: "", + capacity: 0, + price: "Free", + payment: "Not Required", + status: "draft", + featured: false, + registration_required: true + }) + } + }}> + + + {editingEvent ? 'Edit Event' : 'Create New Event'} + + +
+
+
+ + setFormData({...formData, title: e.target.value})} + placeholder="Enter event title" + /> +
+
+ + setFormData({...formData, slug: e.target.value})} + placeholder="auto-generated from title" + /> +
+
+ +
+ +