# All files / src/components/user VODCard.tsx

0% Statements 0/12
0% Branches 0/10
0% Functions 0/2
0% Lines 0/12

Press n or j to go to the next uncovered block, b, p or k for the previous block.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132

     'use client';

    import React from 'react';
    import Link from 'next/link';
    import { Play, Film } from 'lucide-react';
    import { cn } from '@/lib/utils';
    import { FavoriteButton } from '@/components/user/FavoriteButton';
    import { MOVIES_BACKDROPS } from '@/constants/backdrops';

    interface VODCardProps {
      id: number;
      title: string;
      description?: string;
      year?: number | string;
      poster_url?: string;
      image_url?: string;
      backdrop_url?: string;
      rating?: number;
      progress?: number;
      category?: string;
      className?: string;
    }

    /**
     * VODCard - Modern card component for VOD content (Movies, Series, Kids, Anime, Novelas)
     *
     * Features:
     * - Modern design matching /user/content style
     * - Category badge at top
     * - Title and description overlay
     * - Bottom bar with year and Watch button
     * - Hover effects with elevation and border glow
     */
    export default function VODCard({
      id,
      title,
      description: _description,
      year,
      poster_url,
      image_url,
      backdrop_url,
      rating,
      progress: _progress = 0,
      category,
      className}: VODCardProps) {
      // Use poster_url first, then image_url, then backdrop_url as fallback
      const displayImage = poster_url || image_url || backdrop_url;

      // Random placeholder images for cards without posters
      const placeholderImages = MOVIES_BACKDROPS;

      // Get a consistent random placeholder based on the ID
      const placeholderIndex = id % placeholderImages.length;
      const fallbackImage = placeholderImages[placeholderIndex];

      return (
        <Link
          href={`/user/content/${id}/watch`}
          className={cn(
            'group relative overflow-hidden rounded-xl bg-black/40 transition-all duration-500 hover:z-10 hover:scale-105 hover:shadow-[0_10px_40px_-10px_rgba(0,0,0,0.8)]',
            className
          )}
        >
          {/* Poster Image with Gradient Overlay - Fixed aspect ratio */}
          <div
            className="relative aspect-[2/3] bg-cover bg-center"
            style={{
              backgroundImage: displayImage
                ? `url(${displayImage})`
                : `url(${fallbackImage})`
            }}
          >
            {/* Blur overlay for placeholder images */}
            {!displayImage && (
              <div className="absolute inset-0 backdrop-blur-xl bg-slate-900/60 flex items-center justify-center">
                <Film className="h-16 w-16 text-slate-400" />
              </div>
            )}

            {/* Hover Overlay - Darkens and adds play button */}
            <div className="absolute inset-0 bg-black/40 opacity-0 group-hover:opacity-100 transition-opacity duration-500 flex items-center justify-center backdrop-blur-[2px]">
              <div className="h-14 w-14 rounded-full bg-white/20 backdrop-blur-md flex items-center justify-center border border-white/30 shadow-[0_0_20px_rgba(255,255,255,0.2)] transform scale-0 group-hover:scale-100 transition-transform duration-300 delay-100">
                <Play className="h-6 w-6 text-white fill-white ml-1" />
              </div>
            </div>

            <div className="absolute inset-0 flex flex-col justify-between bg-gradient-to-t from-black via-black/20 to-transparent p-4 opacity-100 group-hover:opacity-0 transition-opacity duration-300">
              {/* Category Badge and Favorite Button */}
              <div className="flex items-center justify-between gap-2 text-xs text-slate-300">
                {category && (
                  <span className="rounded-md bg-black/60 backdrop-blur-md px-2 py-0.5 uppercase tracking-wider text-[10px] font-bold border border-white/10 shadow-sm">
                    {category}
                  </span>
                )}
                {/* Favorite button kept visible but subtle */}
                {/* <div onClick={(e) => e.preventDefault()}>
                  <FavoriteButton
                    contentType="movie"
                    contentId={String(id)}
                    className="h-8 w-8"
                    iconClassName="h-4 w-4"
                  />
                </div> */}
              </div>
            </div>
          </div>

          {/* Bottom Info - Only visible on hover in some designs, but here we keep it clean */}
          <div className="absolute bottom-0 left-0 w-full p-4 bg-gradient-to-t from-black to-transparent pt-10 transform translate-y-2 group-hover:translate-y-0 transition-transform duration-500">
            <div className="flex items-center justify-between mb-1">
              <h3 className="text-sm font-bold text-white line-clamp-1 text-shadow-sm">
                {title}
              </h3>
              <div onClick={(e) => e.preventDefault()} className="opacity-0 group-hover:opacity-100 transition-opacity duration-300">
                <FavoriteButton
                  contentType="movie"
                  contentId={String(id)}
                  className="h-6 w-6 hover:bg-white/10 rounded-full p-1"
                  iconClassName="h-3 w-3"
                />
              </div>
            </div>

            <div className="flex items-center gap-2 text-[10px] text-gray-300 font-medium">
              {year && <span className="bg-white/10 px-1.5 rounded text-white">{year}</span>}
              {rating && <span className="text-green-400">{rating} Match</span>}
            </div>
          </div>
        </Link>
      );
    }