63 lines
2.5 KiB
TypeScript
63 lines
2.5 KiB
TypeScript
import React from 'react';
|
|
import Link from 'next/link';
|
|
import { Radio, Users, MapPin } from 'lucide-react';
|
|
import type { Stream } from '@/lib/api';
|
|
|
|
export default function StreamCard({ stream }: { stream: Stream }) {
|
|
return (
|
|
<Link href={`/streams/${stream.id}`} className="group block">
|
|
<div className="bg-surfaceGreen border border-white/5 rounded-2xl overflow-hidden hover:border-teal/30 transition-all hover:shadow-xl hover:shadow-teal/5">
|
|
{/* Thumbnail area */}
|
|
<div className="relative aspect-video bg-black/40 overflow-hidden">
|
|
{stream.thumbnailUrl ? (
|
|
// eslint-disable-next-line @next/next/no-img-element
|
|
<img
|
|
src={stream.thumbnailUrl}
|
|
alt={stream.name}
|
|
className="w-full h-full object-cover group-hover:scale-105 transition-transform duration-500"
|
|
/>
|
|
) : (
|
|
<div className="w-full h-full flex items-center justify-center">
|
|
<Radio size={48} className="text-stone-600" />
|
|
</div>
|
|
)}
|
|
|
|
{/* Status badge */}
|
|
<div className={`absolute top-3 left-3 flex items-center gap-1.5 px-3 py-1 rounded-full text-xs font-bold uppercase tracking-wider ${
|
|
stream.status === 'live'
|
|
? 'bg-red-500/90 text-white'
|
|
: 'bg-black/60 text-stone-300'
|
|
}`}>
|
|
{stream.status === 'live' && <span className="w-1.5 h-1.5 rounded-full bg-white animate-pulse" />}
|
|
{stream.status === 'live' ? 'Live' : 'Offline'}
|
|
</div>
|
|
|
|
{/* Viewer count */}
|
|
{stream.viewerCount > 0 && (
|
|
<div className="absolute top-3 right-3 flex items-center gap-1 bg-black/60 px-2 py-1 rounded-full text-xs text-stone-200 font-semibold">
|
|
<Users size={12} />
|
|
{stream.viewerCount.toLocaleString()}
|
|
</div>
|
|
)}
|
|
</div>
|
|
|
|
{/* Info */}
|
|
<div className="p-5 space-y-2">
|
|
<h3 className="font-bold text-white group-hover:text-teal transition-colors text-base leading-snug">
|
|
{stream.name}
|
|
</h3>
|
|
{stream.location && (
|
|
<div className="flex items-center gap-1.5 text-xs text-stone-400 font-medium">
|
|
<MapPin size={12} />
|
|
{stream.location}
|
|
</div>
|
|
)}
|
|
{stream.description && (
|
|
<p className="text-sm text-stone-400 line-clamp-2 leading-relaxed">{stream.description}</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
</Link>
|
|
);
|
|
}
|