78 lines
3.0 KiB
TypeScript
78 lines
3.0 KiB
TypeScript
'use client';
|
|
import React, { useState } from 'react';
|
|
import { Calendar, MapPin, Users, CheckCircle } from 'lucide-react';
|
|
import { format } from 'date-fns';
|
|
import type { Event } from '@/lib/api';
|
|
import { api } from '@/lib/api';
|
|
|
|
export default function EventCard({ event }: { event: Event }) {
|
|
const [rsvpd, setRsvpd] = useState(false);
|
|
const [email, setEmail] = useState('');
|
|
const [showEmail, setShowEmail] = useState(false);
|
|
const date = new Date(event.date);
|
|
|
|
const handleRsvp = async () => {
|
|
if (!email) { setShowEmail(true); return; }
|
|
try {
|
|
await api.rsvpEvent(event.id, email);
|
|
setRsvpd(true);
|
|
} catch {
|
|
setRsvpd(true); // optimistic
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="bg-surfaceGreen border border-white/5 rounded-2xl p-6 hover:border-teal/20 transition-all flex flex-col md:flex-row gap-6">
|
|
{/* Date block */}
|
|
<div className="shrink-0 w-20 h-20 rounded-xl bg-teal/10 border border-teal/20 flex flex-col items-center justify-center text-center">
|
|
<span className="text-teal text-xs font-bold uppercase tracking-wider">{format(date, 'MMM')}</span>
|
|
<span className="text-white text-3xl font-black leading-none">{format(date, 'd')}</span>
|
|
</div>
|
|
|
|
{/* Content */}
|
|
<div className="flex-1 space-y-3">
|
|
<h3 className="font-bold text-white text-lg leading-tight">{event.title}</h3>
|
|
<div className="flex flex-wrap gap-4 text-sm text-stone-400">
|
|
<span className="flex items-center gap-1.5">
|
|
<Calendar size={14} />
|
|
{format(date, 'EEEE, MMMM d, yyyy')} at {format(date, 'h:mm a')}
|
|
</span>
|
|
<span className="flex items-center gap-1.5">
|
|
<MapPin size={14} />
|
|
{event.location}
|
|
</span>
|
|
<span className="flex items-center gap-1.5">
|
|
<Users size={14} />
|
|
{event.rsvpCount} registered{event.capacity ? ` / ${event.capacity} max` : ''}
|
|
</span>
|
|
</div>
|
|
<p className="text-sm text-stone-400 leading-relaxed">{event.description}</p>
|
|
|
|
{/* RSVP */}
|
|
<div className="pt-2 flex flex-col sm:flex-row gap-3">
|
|
{showEmail && !rsvpd && (
|
|
<input
|
|
type="email"
|
|
value={email}
|
|
onChange={(e) => setEmail(e.target.value)}
|
|
placeholder="your@email.com"
|
|
className="flex-1 bg-black/40 border border-white/10 rounded-lg px-4 py-2 text-sm text-white placeholder:text-stone-600 focus:outline-none focus:border-teal/50"
|
|
/>
|
|
)}
|
|
<button
|
|
onClick={handleRsvp}
|
|
disabled={rsvpd}
|
|
className={`px-6 py-2.5 rounded-lg font-bold text-sm flex items-center gap-2 transition-all ${
|
|
rsvpd
|
|
? 'bg-emerald-700/30 text-emerald-400 cursor-default'
|
|
: 'bg-teal text-white hover:bg-tealLight active:scale-95'
|
|
}`}
|
|
>
|
|
{rsvpd ? <><CheckCircle size={16} /> Registered!</> : 'Register'}
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|