Improve event list layout: prioritize upcoming events and compact card design

- Sort events with upcoming first, then completed/cancelled at bottom
- Redesign event cards with horizontal layout to reduce vertical space
- Move event details (date, time, duration, location, participants) into single row
- Improve mobile responsiveness with flex-wrap
- Keep quick register button visible for upcoming events
This commit is contained in:
2025-11-18 19:08:34 +00:00
parent 3a6db92699
commit 9eb1d3389f
2 changed files with 60 additions and 45 deletions

View File

@@ -85,30 +85,41 @@ export function EventList({ events, onEventClick, onRegister, isLoading = false
};
return (
<div className="space-y-4">
<div className="space-y-3">
{events.map((event) => (
<div
key={event.id}
className="bg-white rounded-lg shadow hover:shadow-lg transition-all cursor-pointer border-2 border-transparent hover:border-blue-200"
onClick={() => onEventClick(event)}
>
<div className="p-6">
<div className="flex items-start justify-between mb-3">
<div className="flex-1">
<h3 className="text-lg font-semibold text-gray-900 mb-1">{event.title}</h3>
<div className="flex items-center gap-2">
<div className="p-4">
{/* Header Row */}
<div className="flex items-start justify-between gap-4 mb-3">
<div className="flex-1 min-w-0">
<div className="flex items-center gap-2 mb-1">
<h3 className="text-lg font-semibold text-gray-900 truncate">{event.title}</h3>
{getStatusBadge(event.status)}
<span className="text-sm text-gray-500">
{event.participantCount} {event.participantCount === 1 ? 'participant' : 'participants'}
</span>
</div>
<p className="text-sm text-gray-600 line-clamp-1">{event.description}</p>
</div>
{event.status === 'upcoming' && onRegister && (
<button
onClick={(e) => {
e.stopPropagation();
onRegister(event.id);
}}
className="bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors font-medium text-sm whitespace-nowrap"
>
Quick Register
</button>
)}
</div>
<div className="space-y-2 mb-4">
{/* Info Row - Horizontal Layout */}
<div className="flex flex-wrap items-center gap-x-6 gap-y-2 text-sm text-gray-600">
{/* Date and Time */}
<div className="flex items-center text-sm text-gray-600">
<svg className="h-5 w-5 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<div className="flex items-center">
<svg className="h-4 w-4 mr-1.5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
strokeLinecap="round"
strokeLinejoin="round"
@@ -116,14 +127,14 @@ export function EventList({ events, onEventClick, onRegister, isLoading = false
d="M8 7V3m8 4V3m-9 8h10M5 21h14a2 2 0 002-2V7a2 2 0 00-2-2H5a2 2 0 00-2 2v12a2 2 0 002 2z"
/>
</svg>
<span>
<span className="whitespace-nowrap">
{formatEventDate(event.scheduledDate)} at {formatEventTime(event.scheduledDate)}
</span>
</div>
{/* Duration */}
<div className="flex items-center text-sm text-gray-600">
<svg className="h-5 w-5 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<div className="flex items-center">
<svg className="h-4 w-4 mr-1.5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
strokeLinecap="round"
strokeLinejoin="round"
@@ -135,8 +146,8 @@ export function EventList({ events, onEventClick, onRegister, isLoading = false
</div>
{/* Location */}
<div className="flex items-center text-sm text-gray-600">
<svg className="h-5 w-5 mr-2 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<div className="flex items-center min-w-0 flex-1">
<svg className="h-4 w-4 mr-1.5 text-gray-400 flex-shrink-0" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
strokeLinecap="round"
strokeLinejoin="round"
@@ -145,52 +156,46 @@ export function EventList({ events, onEventClick, onRegister, isLoading = false
/>
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M15 11a3 3 0 11-6 0 3 3 0 016 0z" />
</svg>
<span>{event.locationName}</span>
<span className="truncate">{event.locationName}</span>
</div>
</div>
{/* Description Preview */}
<p className="text-sm text-gray-600 line-clamp-2 mb-4">{event.description}</p>
{/* Participants */}
<div className="flex items-center">
<svg className="h-4 w-4 mr-1.5 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path
strokeLinecap="round"
strokeLinejoin="round"
strokeWidth={2}
d="M17 20h5v-2a3 3 0 00-5.356-1.857M17 20H7m10 0v-2c0-.656-.126-1.283-.356-1.857M7 20H2v-2a3 3 0 015.356-1.857M7 20v-2c0-.656.126-1.283.356-1.857m0 0a5.002 5.002 0 019.288 0M15 7a3 3 0 11-6 0 3 3 0 016 0zm6 3a2 2 0 11-4 0 2 2 0 014 0zM7 10a2 2 0 11-4 0 2 2 0 014 0z"
/>
</svg>
<span>{event.participantCount} {event.participantCount === 1 ? 'participant' : 'participants'}</span>
</div>
{/* Completed Event Info */}
{event.status === 'completed' && event.litterCollected !== undefined && (
<div className="bg-green-50 border border-green-200 rounded-lg p-3 mb-4">
<div className="flex items-center text-sm text-green-800">
<svg className="h-5 w-5 mr-2 text-green-600" fill="currentColor" viewBox="0 0 20 20">
{/* Completed Event Info */}
{event.status === 'completed' && event.litterCollected !== undefined && (
<div className="flex items-center text-green-700 font-medium">
<svg className="h-4 w-4 mr-1.5 text-green-600" fill="currentColor" viewBox="0 0 20 20">
<path
fillRule="evenodd"
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
clipRule="evenodd"
/>
</svg>
<span className="font-medium">{event.litterCollected} kg of litter collected</span>
<span>{event.litterCollected} kg collected</span>
</div>
</div>
)}
)}
{/* Action Area */}
<div className="flex items-center justify-between pt-4 border-t border-gray-100">
{/* View Details Link */}
<button
onClick={() => onEventClick(event)}
className="text-blue-600 hover:text-blue-700 font-medium text-sm flex items-center gap-1"
className="text-blue-600 hover:text-blue-700 font-medium flex items-center gap-1 ml-auto"
>
View Details
<svg className="h-4 w-4" fill="none" viewBox="0 0 24 24" stroke="currentColor">
<path strokeLinecap="round" strokeLinejoin="round" strokeWidth={2} d="M9 5l7 7-7 7" />
</svg>
</button>
{event.status === 'upcoming' && onRegister && (
<button
onClick={(e) => {
e.stopPropagation();
onRegister(event.id);
}}
className="bg-blue-600 text-white py-2 px-4 rounded-lg hover:bg-blue-700 transition-colors font-medium text-sm"
>
Quick Register
</button>
)}
</div>
</div>
</div>