Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | 1x 11x 11x 11x 11x 11x | /**
* EventLogistics Component (Story 4.1.3)
* Displays event logistics information with icons
*/
import { Calendar, Clock, MapPin, Users, Tag } from 'lucide-react';
import { format } from 'date-fns';
import type { EventDetail } from '@/types/event.types';
import { useTranslation } from 'react-i18next';
interface EventLogisticsProps {
event: EventDetail;
}
export const EventLogistics = ({ event }: EventLogisticsProps) => {
const { t } = useTranslation('events');
// Parse date string to Date object
const eventDate = event.date ? new Date(event.date) : null;
// Use typicalStartTime and typicalEndTime from event type (not event.date hour)
const startTime = event.typicalStartTime || null;
const endTime = event.typicalEndTime || null;
return (
<div className="grid grid-cols-1 gap-6 sm:grid-cols-2 lg:grid-cols-4">
{/* Date */}
{eventDate && (
<div className="flex items-start gap-3">
<Calendar className="h-5 w-5 text-primary mt-1 flex-shrink-0" />
<div>
<p className="text-sm text-zinc-400">{t('common:labels.date')}</p>
<p className="text-lg font-light text-zinc-100">{format(eventDate, 'PPP')}</p>
</div>
</div>
)}
{/* Time */}
{startTime && (
<div className="flex items-start gap-3">
<Clock className="h-5 w-5 text-primary mt-1 flex-shrink-0" />
<div>
<p className="text-sm text-zinc-400">{t('public.logistics.time')}</p>
<p className="text-lg font-light text-zinc-100">
{startTime}h - {endTime}h
</p>
</div>
</div>
)}
{/* Location */}
{event.venueName && (
<div className="flex items-start gap-3">
<MapPin className="h-5 w-5 text-primary mt-1 flex-shrink-0" />
<div>
<p className="text-sm text-zinc-400">{t('public.logistics.location')}</p>
<p className="text-lg font-light text-zinc-100">{event.venueName}</p>
{event.venueAddress && (
<p className="text-sm text-zinc-500 mt-1">{event.venueAddress.split(',')[0]}</p>
)}
</div>
</div>
)}
{/* Capacity — show registrationCapacity only (venueCapacity is organizer-internal) */}
{event.registrationCapacity != null && (
<div className="flex items-start gap-3">
<Users className="h-5 w-5 text-primary mt-1 flex-shrink-0" />
<div>
<p className="text-sm text-zinc-400">{t('public.logistics.capacity')}</p>
<p className="text-lg font-light text-zinc-100">
{(event.confirmedCount || 0) + (event.waitlistCount || 0)} /{' '}
{event.registrationCapacity}
</p>
</div>
</div>
)}
{/* Topic */}
{event.topic?.name && (
<div className="flex items-start gap-3">
<Tag className="h-5 w-5 text-primary mt-1 flex-shrink-0" />
<div>
<p className="text-sm text-zinc-400">{t('public.logistics.topic', 'Topic')}</p>
<p className="text-lg font-light text-zinc-100">{event.topic.name}</p>
</div>
</div>
)}
</div>
);
};
|