tahamajs's picture
download
raw
3.34 kB
// src/components/networking/EventCard.tsx
import { Calendar, Clock, MapPin, Video, Users, Tag, ExternalLink, Play, Bell, BellOff } from "lucide-react";
import type { Event } from "@/types/networking";
import { useNavigate } from "react-router-dom";
import { useState } from "react";
interface EventCardProps {
event: Event;
onRSVP?: (eventId: string, status: "yes" | "maybe" | "no") => void;
}
export function EventCard({ event, onRSVP }: EventCardProps) {
const navigate = useNavigate();
const [rsvp, setRsvp] = useState<"yes" | "maybe" | "no" | null>(null);
const handleRSVP = (status: "yes" | "maybe" | "no") => {
setRsvp(status);
onRSVP?.(event.id, status);
};
const isPast = new Date(event.scheduledEnd) < new Date();
return (
<div className={`glass rounded-2xl border border-white/20 dark:border-white/10 p-4 transition ${event.isLive ? "ring-2 ring-red-500 animate-pulse" : ""}`}>
<div className="flex items-start justify-between">
<div className="flex-1">
<div className="flex items-center gap-2 mb-1">
<span className="text-[10px] px-2 py-0.5 rounded-full bg-primary/10 text-primary capitalize">{event.type.replace(/_/g, " ")}</span>
{event.isLive && <span className="text-[10px] px-2 py-0.5 rounded-full bg-red-500 text-white animate-pulse">LIVE</span>}
</div>
<h3 className="font-bold text-lg cursor-pointer hover:text-primary" onClick={() => navigate(`/events/${event.id}`)}>{event.title}</h3>
<p className="text-sm text-gray-500 mt-1">{event.hostName}</p>
<div className="flex flex-wrap items-center gap-3 mt-2 text-xs text-gray-500">
<span className="flex items-center gap-1"><Calendar className="w-3.5 h-3.5"/> {new Date(event.scheduledStart).toLocaleDateString()}</span>
<span className="flex items-center gap-1"><Clock className="w-3.5 h-3.5"/> {new Date(event.scheduledStart).toLocaleTimeString([], { hour: "2-digit", minute: "2-digit" })}</span>
{event.isOnline ? <span className="flex items-center gap-1"><Video className="w-3.5 h-3.5"/> Online</span> : <span className="flex items-center gap-1"><MapPin className="w-3.5 h-3.5"/> {event.location}</span>}
<span className="flex items-center gap-1"><Users className="w-3.5 h-3.5"/> {event.attendanceCount}</span>
</div>
</div>
<div className="flex flex-col gap-2">
{!isPast && (
<>
<button onClick={() => handleRSVP("yes")} className={`btn btn-xs ${rsvp === "yes" ? "btn-primary" : "btn-ghost"}`}>Going</button>
<button onClick={() => handleRSVP("maybe")} className={`btn btn-xs ${rsvp === "maybe" ? "btn-primary" : "btn-ghost"}`}>Maybe</button>
</>
)}
{event.streamUrl && <a href={event.streamUrl} target="_blank" className="btn btn-ghost btn-xs gap-1"><ExternalLink className="w-3 h-3"/> Join</a>}
{event.recordingUrl && <a href={event.recordingUrl} target="_blank" className="btn btn-ghost btn-xs gap-1"><Play className="w-3 h-3"/> Recording</a>}
</div>
</div>
{event.tags.length > 0 && <div className="flex flex-wrap gap-1 mt-3">{event.tags.map(t => <span key={t} className="text-[9px] bg-white/10 px-2 py-0.5 rounded-full">{t}</span>)}</div>}
</div>
);
}

Xet Storage Details

Size:
3.34 kB
·
Xet hash:
57e4ae34b39df479deb7706e52258a0ab8ee2e00de74c0ed0539e3eaaa382b29

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.