Files
petlink_final/components/animals/AnimalCard.tsx

162 lines
5.1 KiB
TypeScript

'use client';
import Link from 'next/link';
import Image from 'next/image';
import { MapPin, ChevronRight, AlertTriangle } from 'lucide-react';
import { Animal, formatAge } from '@/lib/mock-data';
interface AnimalCardProps {
animal: Animal;
index?: number;
}
export default function AnimalCard({ animal, index = 0 }: AnimalCardProps) {
const ageLabel = formatAge(animal.ageMonths);
const sexSymbol = animal.sex === 'MALE' ? '♂' : '♀';
const sterilizedLabel = animal.sterilized ? '· Esterilizado ✓' : '';
const subline = `${animal.breed} · ${ageLabel} ${sterilizedLabel}`.trim();
return (
<article
className="animal-card"
style={{ animationDelay: `${index * 80}ms` }}
aria-label={`${animal.name}, ${animal.breed}, ${ageLabel}, disponível no ${animal.shelter.name}`}
>
{/* Fotografia */}
<div style={{ position: 'relative', aspectRatio: '3/2', overflow: 'hidden' }}>
<Image
src={animal.photos[0]}
alt={`${animal.name}${animal.breed} ${animal.sex === 'MALE' ? 'macho' : 'fêmea'}, ${ageLabel}`}
fill
sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, 33vw"
style={{
objectFit: 'cover',
transition: 'transform 400ms ease',
}}
onMouseEnter={e => { (e.currentTarget as HTMLElement).style.transform = 'scale(1.04)'; }}
onMouseLeave={e => { (e.currentTarget as HTMLElement).style.transform = 'scale(1)'; }}
/>
{/* Gradiente base da foto */}
<div
aria-hidden="true"
style={{
position: 'absolute',
inset: 0,
background: 'linear-gradient(to top, rgba(35,20,8,0.35) 0%, transparent 50%)',
pointerEvents: 'none',
}}
/>
{/* Badge urgente — top right */}
{animal.urgent && (
<div style={{ position: 'absolute', top: '12px', right: '12px' }}>
<span className="badge-urgent">
<AlertTriangle size={9} strokeWidth={2.5} />
Urgente
</span>
</div>
)}
</div>
{/* Corpo do card */}
<div
style={{
padding: '16px',
display: 'flex',
flexDirection: 'column',
gap: '8px',
flex: 1,
}}
>
{/* Nome + sexo */}
<div style={{ display: 'flex', alignItems: 'baseline', justifyContent: 'space-between', gap: '8px' }}>
<h3
style={{
fontFamily: 'var(--font-display)',
fontWeight: 700,
fontSize: '20px',
color: 'var(--soil)',
lineHeight: 1.1,
letterSpacing: '-0.01em',
}}
>
{animal.name}
</h3>
<span
style={{
fontFamily: 'var(--font-display)',
fontWeight: 700,
fontSize: '16px',
color: 'var(--soil-mid)',
flexShrink: 0,
}}
aria-label={animal.sex === 'MALE' ? 'Macho' : 'Fêmea'}
>
{sexSymbol}
</span>
</div>
{/* Raça · Idade · Esterilizado */}
<p
style={{
fontFamily: 'var(--font-accent)',
fontSize: '10px',
fontWeight: 400,
color: 'var(--soil-faint)',
letterSpacing: '0.08em',
textTransform: 'uppercase',
lineHeight: 1.4,
}}
>
{subline}
</p>
{/* Localização */}
<div
style={{
display: 'flex',
alignItems: 'center',
gap: '5px',
fontFamily: 'var(--font-body)',
fontStyle: 'italic',
fontSize: '14px',
color: 'var(--soil-mid)',
marginTop: '2px',
}}
>
<MapPin size={12} style={{ color: 'var(--terra)', flexShrink: 0 }} aria-hidden="true" />
<span>{animal.shelter.name}, {animal.shelter.district}</span>
</div>
{/* Spacer */}
<div style={{ flex: 1 }} />
{/* Separador */}
<hr style={{ border: 'none', borderTop: '1px solid var(--parchment)', margin: '4px 0' }} />
{/* Acções */}
<div style={{ display: 'flex', gap: '8px' }}>
<Link
href={`/main/animals/${animal.id}`}
className="btn btn-secondary"
style={{ flex: 1, justifyContent: 'center', padding: '10px 12px', fontSize: '11px', minHeight: '40px' }}
aria-label={`Ver ficha completa de ${animal.name}`}
>
Ver mais
</Link>
<Link
href={`/main/animals/${animal.id}#adoptar`}
className="btn btn-primary"
style={{ flex: 1, justifyContent: 'center', padding: '10px 12px', fontSize: '11px', minHeight: '40px', gap: '4px' }}
aria-label={`Iniciar processo de adopção de ${animal.name}`}
>
Adoptar
<ChevronRight size={12} strokeWidth={2.5} />
</Link>
</div>
</div>
</article>
);
}