File size: 9,516 Bytes
4bea261
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
import { useState, useEffect, useCallback } from 'react';
import { Play, Info, ChevronLeft, ChevronRight } from 'lucide-react';
import { formatImageUrl } from '../lib/image';

export default function HeroBanner({ movies = [] }) {
  const [active, setActive] = useState(0);
  const [progress, setProgress] = useState(0);
  const [favorites, setFavorites] = useState([]);

  useEffect(() => {
    fetch('/api/user/favorite')
      .then(res => res.json())
      .then(data => {
        if (data && data.favorites) {
          setFavorites(data.favorites.map(f => f.slug));
        }
      })
      .catch(() => {});
  }, []);

  const handleFavoriteClick = async (m) => {
    try {
      const res = await fetch('/api/user/favorite', {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify({
          movieSlug: m.slug,
          movieName: m.name,
          movieThumb: m.thumb_url || m.poster_url
        })
      });
      const data = await res.json();
      if (res.ok) {
        if (window.txatoast) {
          window.txatoast.success(data.message);
        }
        if (data.action === 'added') {
          setFavorites(prev => [...prev, m.slug]);
        } else {
          setFavorites(prev => prev.filter(slug => slug !== m.slug));
        }
      } else {
        if (window.txatoast) {
          window.txatoast.error(data.error || 'Vui lòng đăng nhập!');
        }
      }
    } catch (e) {
      if (window.txatoast) {
        window.txatoast.error('Không thể thực hiện lúc này!');
      }
    }
  };

  const heroMovies = movies.slice(0, 5);

  const next = useCallback(() => {
    setActive((prev) => (prev + 1) % heroMovies.length);
    setProgress(0);
  }, [heroMovies.length]);

  const prev = useCallback(() => {
    setActive((prev) => (prev - 1 + heroMovies.length) % heroMovies.length);
    setProgress(0);
  }, [heroMovies.length]);

  useEffect(() => {
    if (heroMovies.length <= 1) return;
    const interval = 100; // 0.1s
    const step = 100 / (6000 / interval); // 6s per slide
    
    const timer = setInterval(() => {
      setProgress((p) => {
        if (p >= 100) {
          next();
          return 0;
        }
        return p + step;
      });
    }, interval);

    return () => clearInterval(timer);
  }, [heroMovies.length, next]);

  if (!heroMovies.length) return null;
  const movie = heroMovies[active];
  const bg = formatImageUrl(movie.poster_url || movie.thumb_url);
  const year = movie.year || (movie.modified?.time ? new Date(movie.modified.time).getFullYear() : '');

  return (
    <div className="relative h-[600px] w-full overflow-hidden md:h-[750px] lg:h-[850px]">
      {/* Background Slides with Stylized Text */}
      {heroMovies.map((m, i) => (
        <div
          key={m._id}
          className={`absolute inset-0 transition-all duration-[2000ms] ease-out ${
            i === active ? 'opacity-100 scale-100' : 'opacity-0 scale-110'
          }`}
        >
          {/* Main Background Image */}
          <div 
            className="absolute inset-0 bg-cover bg-center md:bg-[center_right_20%]"
            style={{ backgroundImage: `url(${formatImageUrl(m.poster_url || m.thumb_url)})` }}
          />
          
          {/* Stylized Background Text Layer (The "Thu Hút Mãnh Liệt" style in bg) */}
          <div className="absolute inset-0 flex items-center justify-center opacity-10 select-none pointer-events-none overflow-hidden">
             <h1 className="text-[20vw] font-black uppercase whitespace-nowrap rotate-[-10deg] text-white">
                {m.name}
             </h1>
          </div>
        </div>
      ))}

      {/* Gradients for cinematic feel */}
      <div className="absolute inset-0 bg-gradient-to-r from-[#0f0f0f] via-[#0f0f0f]/80 to-transparent z-10" />
      <div className="absolute inset-0 bg-gradient-to-t from-[#0f0f0f] via-transparent to-transparent z-10" />

      <div className="relative mx-auto flex h-full max-w-7xl flex-col justify-center px-6 z-20">
        <div className="max-w-2xl transition-all duration-700 transform opacity-100 translate-y-0">
          <h1 className="text-4xl font-black text-white md:text-6xl lg:text-7xl drop-shadow-[0_0_30px_rgba(255,255,255,0.2)]">
            <a href={`/phim/${movie.slug}`} className="hover:text-primary transition-colors cursor-pointer">
              {movie.name}
            </a>
          </h1>
          
          {movie.origin_name && (
            <p className="mt-2 text-sm font-bold text-gray-400 md:text-base uppercase tracking-wider opacity-60 italic">{movie.origin_name}</p>
          )}

          {/* Badges Row */}
          <div className="mt-6 flex flex-wrap items-center gap-3">
             <div className="flex items-center gap-1.5 rounded-lg bg-yellow-500/20 px-2.5 py-1 text-[10px] font-black text-yellow-500 ring-1 ring-yellow-500/30">
                <i className="fas fa-star"></i> {movie.tmdb?.vote_average || (8.5 + (movie.slug.length % 15) / 10).toFixed(1)}
             </div>
             <span className="glass rounded-lg px-2.5 py-1 text-[10px] font-black text-gray-300 ring-1 ring-white/10 uppercase">
                {movie.quality || 'Full HD'}
             </span>
             <span className="glass rounded-lg px-2.5 py-1 text-[10px] font-black text-gray-300 ring-1 ring-white/10">
                {year}
             </span>
             {movie.tmdb?.season && (
                <span className="glass rounded-lg px-2.5 py-1 text-[10px] font-black text-gray-300 ring-1 ring-white/10">
                   Phần {movie.tmdb.season}
                </span>
             )}
             <span className="glass rounded-lg px-2.5 py-1 text-[10px] font-black text-gray-300 ring-1 ring-white/10">
                {movie.episode_current?.toLowerCase().includes('hoàn tất') ? 'Hoàn tất' : `Tập ${movie.episode_current?.match(/\d+/)?.[0] || '??'}`} 
                {movie.episode_total && movie.episode_total !== '1' && ` / ${movie.episode_total}`}
             </span>
          </div>

          {/* Categories Row */}
          <div className="mt-4 flex flex-wrap gap-2">
             {movie.category?.slice(0, 4).map(cat => (
               <span key={cat.id} className="text-[11px] font-bold text-gray-500 hover:text-white transition-colors cursor-pointer">
                  {cat.name}
               </span>
             ))}
          </div>

          <p className="mt-8 line-clamp-3 max-w-xl text-sm leading-relaxed text-gray-400 md:text-base drop-shadow-md">
            {movie.content?.replace(/<[^>]*>/g, '') || movie.description || ''}
          </p>

          <div className="mt-10 flex items-center gap-4">
            <a
              href={`/xem/${movie.slug}`}
              className="group flex h-14 w-14 items-center justify-center rounded-full bg-yellow-500 text-black shadow-[0_0_30px_rgba(234,179,8,0.4)] transition-all hover:scale-110 active:scale-95"
              data-txatooltip="Xem phim ngay"
            >
              <i className="fas fa-play text-xl ml-1"></i>
            </a>
            
            <button 
               className={`glass flex h-14 w-14 items-center justify-center rounded-full transition-all hover:bg-white/10 hover:ring-2 hover:ring-white/20 ${favorites.includes(movie.slug) ? 'text-primary' : 'text-white'}`}
               onClick={() => handleFavoriteClick(movie)}
               data-txatooltip={favorites.includes(movie.slug) ? "Bỏ yêu thích" : "Thêm vào yêu thích"}
            >
               <i className={`${favorites.includes(movie.slug) ? 'fas' : 'far'} fa-heart text-xl`}></i>
            </button>

            <a
              href={`/phim/${movie.slug}`}
              className="glass flex h-14 w-14 items-center justify-center rounded-full text-white transition-all hover:bg-white/10 hover:ring-2 hover:ring-white/20"
              data-txatooltip="Thông tin chi tiết"
            >
               <i className="fas fa-info text-xl"></i>
            </a>
          </div>
        </div>

        {/* Thumbnails Navigation (Right side row) */}
        <div className="absolute bottom-16 right-6 hidden lg:flex items-center gap-3">
            {heroMovies.map((m, i) => (
              <div 
                key={m._id} 
                onClick={() => { setActive(i); setProgress(0); }}
                className={`group relative h-16 w-24 cursor-pointer overflow-hidden rounded-xl border-2 transition-all duration-500 ${
                   i === active ? 'border-primary scale-110 shadow-[0_0_20px_rgba(229,9,20,0.5)]' : 'border-white/10 opacity-50 hover:opacity-100'
                }`}
              >
                <img src={formatImageUrl(m.thumb_url || m.poster_url)} className="h-full w-full object-cover" alt="nav" />
                {i === active && (
                   <div className="absolute bottom-0 left-0 h-1 bg-primary transition-all duration-100" style={{ width: `${progress}%` }} />
                )}
              </div>
            ))}
        </div>

        {/* Mobile Navigation */}
        <div className="absolute bottom-8 left-6 flex lg:hidden gap-2">
           {heroMovies.map((_, i) => (
              <div 
                 key={i} 
                 onClick={() => { setActive(i); setProgress(0); }}
                 className={`h-1.5 rounded-full transition-all duration-500 ${i === active ? 'w-8 bg-primary' : 'w-2 bg-white/20'}`}
              />
           ))}
        </div>
      </div>
    </div>
  );
}