LiveChannelCard.tsx 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. 'use client';
  2. import Link from 'next/link';
  3. import Image from 'next/image';
  4. import { Radio, Eye } from 'lucide-react';
  5. import type { LiveChannelItem } from '@/types/response/channel/live-list';
  6. import { buildWatchUrl, formatHandle, formatCount } from '@/lib/utils/channel';
  7. type Props = {
  8. channel: LiveChannelItem;
  9. priority?: boolean;
  10. };
  11. export default function LiveChannelCard({ channel, priority = false }: Props)
  12. {
  13. const href = buildWatchUrl({ handle: channel.handle, channelSID: channel.channelSID });
  14. const viewerLabel = formatCount(channel.viewerCount);
  15. return (
  16. <Link
  17. href={href}
  18. className="live-card"
  19. aria-label={`${channel.channelName} 라이브 — ${channel.liveTitle} · 시청자 ${viewerLabel}`}
  20. >
  21. <div className="live-card__thumb-wrap">
  22. <Image
  23. src={channel.videoThumbnailUrl}
  24. alt=""
  25. fill
  26. unoptimized
  27. priority={priority}
  28. sizes="(max-width: 640px) 100vw, (max-width: 1024px) 50vw, (max-width: 1536px) 33vw, 20vw"
  29. className="live-card__thumb"
  30. />
  31. <span className="live-card__badge" aria-label="라이브 방송 중">
  32. <Radio className="size-3" aria-hidden="true" />
  33. LIVE
  34. </span>
  35. <span className="live-card__viewers" aria-hidden="true">
  36. <Eye className="size-3" />
  37. {viewerLabel}
  38. </span>
  39. </div>
  40. <div className="live-card__meta">
  41. <div className="live-card__avatar">
  42. {channel.channelThumbnailUrl ? (
  43. <Image
  44. src={channel.channelThumbnailUrl}
  45. alt=""
  46. width={36}
  47. height={36}
  48. unoptimized
  49. className="live-card__avatar-img"
  50. />
  51. ) : (
  52. <span className="live-card__avatar-fallback" aria-hidden="true">
  53. {channel.channelName.charAt(0).toUpperCase()}
  54. </span>
  55. )}
  56. </div>
  57. <div className="live-card__text">
  58. <h3 className="live-card__title">{channel.liveTitle || '라이브 방송 중'}</h3>
  59. <div className="live-card__channel-name">{channel.channelName}</div>
  60. {channel.handle && (
  61. <div className="live-card__handle">{formatHandle(channel.handle)}</div>
  62. )}
  63. </div>
  64. </div>
  65. </Link>
  66. );
  67. }