photum/components/EventCard.tsx
João Vitor 1caeddc72c feat: Initialize PhotumManager project structure
This commit sets up the foundational project structure for PhotumManager. It includes:
- Initializing a new React project with Vite.
- Configuring essential dependencies such as React, Lucide React, and the Google Generative AI SDK.
- Setting up TypeScript and Vite configurations for optimal development.
- Defining core application metadata and initial type definitions for users and events.
- Establishing basic styling and font configurations in `index.html` with Tailwind CSS.
- Adding a `.gitignore` file to manage project dependencies and build artifacts.
- Updating the README with instructions for local development.
2025-11-25 11:02:25 -03:00

100 lines
4.5 KiB
TypeScript

import React, { useState } from 'react';
import { EventData, EventStatus } from '../types';
import { Calendar, MapPin, ArrowRight, UserCheck } from 'lucide-react';
import { STATUS_COLORS } from '../constants';
interface EventCardProps {
event: EventData;
onClick: () => void;
}
export const EventCard: React.FC<EventCardProps> = ({ event, onClick }) => {
const [imageLoaded, setImageLoaded] = useState(false);
const fullAddress = `${event.address.street}, ${event.address.number} - ${event.address.city}/${event.address.state}`;
return (
<div
className="group bg-white rounded-lg border border-gray-100 overflow-hidden hover:shadow-xl transition-all duration-300 cursor-pointer flex flex-col h-full"
onClick={onClick}
>
<div className="relative h-48 overflow-hidden bg-gray-100">
{/* Skeleton / Loading State */}
{!imageLoaded && (
<div className="absolute inset-0 bg-gray-200 animate-pulse flex items-center justify-center">
<div className="w-8 h-8 border-2 border-gray-300 border-t-brand-gold rounded-full animate-spin"></div>
</div>
)}
<img
src={event.coverImage}
alt={event.name}
className={`w-full h-full object-cover transition-all duration-700 group-hover:scale-105 ${imageLoaded ? 'opacity-100' : 'opacity-0'}`}
onLoad={() => setImageLoaded(true)}
/>
<div className="absolute inset-0 bg-gradient-to-t from-black/60 to-transparent opacity-60"></div>
<div className="absolute top-3 right-3">
<span className={`text-xs font-semibold px-2 py-1 rounded-sm uppercase tracking-wide ${STATUS_COLORS[event.status]}`}>
{event.status}
</span>
</div>
<div className="absolute bottom-3 left-4 text-white">
<p className="text-xs font-light uppercase tracking-widest opacity-90">{event.type}</p>
<h3 className="text-lg font-serif font-medium drop-shadow-md">{event.name}</h3>
</div>
</div>
<div className="p-5 flex-1 flex flex-col justify-between">
<div className="space-y-3">
<div className="flex items-center text-gray-500 text-sm">
<Calendar size={16} className="mr-2 text-brand-gold" />
<span>{new Date(event.date).toLocaleDateString()} às {event.time}</span>
</div>
{/* Location with Tooltip */}
<div className="relative group/tooltip">
<div
className="flex items-center text-gray-500 text-sm"
title={fullAddress} // Native tooltip fallback
>
<MapPin size={16} className="mr-2 text-brand-gold flex-shrink-0" />
<span className="truncate">{event.address.city}, {event.address.state}</span>
</div>
{/* Custom Tooltip */}
<div className="absolute bottom-full left-0 mb-2 hidden group-hover/tooltip:block z-20 pointer-events-none">
<div className="bg-brand-black text-white text-xs rounded py-1.5 px-3 whitespace-nowrap shadow-xl">
{event.address.street}, {event.address.number}
<br/>
{event.address.city} - {event.address.state}
{/* Arrow */}
<div className="absolute top-full left-3 -mt-1 border-4 border-transparent border-t-brand-black"></div>
</div>
</div>
</div>
{event.contacts.length > 0 && (
<div className="flex items-center text-gray-500 text-sm">
<UserCheck size={16} className="mr-2 text-brand-gold" />
<span>{event.contacts.length} {event.contacts.length === 1 ? 'Fornecedor/Contato' : 'Fornecedores/Contatos'}</span>
</div>
)}
</div>
<div className="mt-5 pt-4 border-t border-gray-50 flex items-center justify-between">
<div className="flex -space-x-2">
{[1,2,3].map(i => (
<div key={i} className="w-8 h-8 rounded-full border-2 border-white bg-gray-200" style={{backgroundImage: `url(https://i.pravatar.cc/100?img=${i})`, backgroundSize: 'cover'}}></div>
))}
<div className="w-8 h-8 rounded-full border-2 border-white bg-gray-100 flex items-center justify-center text-xs text-gray-500 font-medium">
+4
</div>
</div>
<button className="text-brand-black group-hover:text-brand-gold transition-colors">
<ArrowRight size={20} />
</button>
</div>
</div>
</div>
);
};