'use client'; import { useState, useEffect } from 'react'; import { formatDisplayDateFull } from '@/lib/date'; const gold = '#E8A849'; const navy = '#010D1E'; const cream = '#f5f0e8'; const warm = '#a6683c'; interface SocialEvent { id: number; name: string; description: string; price: string | null; date: string | null; photos: string[]; featured_photo: string | null; active?: boolean; reservation_count: number; } interface User { id: number; username: string; role: 'admin' | 'user'; first_name: string | null; last_name: string | null; comments_disabled?: boolean; } export default function SocialEventsPage() { const [events, setEvents] = useState([]); const [loading, setLoading] = useState(true); const [error, setError] = useState(''); const [user, setUser] = useState(null); const [activePhoto, setActivePhoto] = useState>({}); const [reserving, setReserving] = useState(null); const [guests, setGuests] = useState>({}); const [notes, setNotes] = useState>({}); const [message, setMessage] = useState(null); const [myReservations, setMyReservations] = useState>({}); useEffect(() => { fetch('/api/social_events/public') .then(async (res) => { if (!res.ok) throw new Error('Failed to load social events'); const json = await res.json(); setEvents(json.data || []); }) .catch((err) => setError(err.message)) .finally(() => setLoading(false)); fetch('/api/auth/me', { credentials: 'same-origin' }) .then((r) => (r.ok ? r.json() : Promise.resolve({ user: null }))) .then((j) => setUser(j.user || null)) .catch(() => {}); fetch('/api/social_event_reservations', { credentials: 'same-origin' }) .then(async (res) => { if (!res.ok) return; const json = await res.json(); const map: Record = {}; (json.data || []).forEach((r: { social_event_id: number; guests: number }) => { map[r.social_event_id] = r.guests; }); setMyReservations(map); }) .catch(() => {}); }, []); const makeReservation = async (eventId: number) => { const count = parseInt(guests[eventId] || '1', 10); if (count < 1) return; setReserving(eventId); const res = await fetch('/api/social_event_reservations', { method: 'POST', headers: { 'Content-Type': 'application/json' }, credentials: 'same-origin', body: JSON.stringify({ social_event_id: eventId, guests: count, notes: notes[eventId] || '', }), }); setReserving(null); if (res.ok) { setMessage('Reservation submitted.'); setMyReservations((prev) => ({ ...prev, [eventId]: count })); setTimeout(() => setMessage(null), 3000); } else { setError('Reservation failed. Make sure you are logged in.'); } }; const displayedEvents = events.filter((e) => e.active !== false); return (

Social Events

Curated gatherings, tastings, and celebrations at La Huasca. Reserve your spot.

{message &&

{message}

} {loading &&

Loading events...

} {error &&

{error}

} {!loading && displayedEvents.length === 0 &&

No social events scheduled yet.

}
{displayedEvents.map((event) => { const photos = event.photos?.length ? event.photos : []; const featured = event.featured_photo || photos[0]; const currentPhoto = activePhoto[event.id] || featured || photos[0]; const myCount = myReservations[event.id]; return (
{ e.currentTarget.style.transform = 'translateY(-3px)'; e.currentTarget.style.boxShadow = '0 8px 24px rgba(1,13,30,0.14)'; }} onMouseLeave={(e) => { e.currentTarget.style.transform = 'translateY(0)'; e.currentTarget.style.boxShadow = '0 2px 8px rgba(1,13,30,0.08)'; }} >
1 ? 'pointer' : 'default', }} onClick={() => { if (photos.length > 1) { const idx = photos.indexOf(currentPhoto); setActivePhoto((prev) => ({ ...prev, [event.id]: photos[(idx + 1) % photos.length] })); } }} /> {photos.length > 1 && (
{photos.map((p, i) => (
)}

{event.name}

{event.date && (

{formatDisplayDateFull(event.date)}

)}

{event.description}

{event.price ? `$${event.price}` : 'Free'} {event.reservation_count || 0} reserved
{photos.length > 1 && (
{photos.map((p) => (
)} {user ? (
{myCount ? (

You reserved {myCount} guest{myCount === 1 ? '' : 's'}.

) : null}