From 3dfce91ca6e444585d9e1589594350047909a104 Mon Sep 17 00:00:00 2001 From: MIGHTY1o1 Date: Thu, 10 Oct 2024 16:49:20 +0530 Subject: [PATCH] revamped coursel movie cards --- .../components/custom/MovieCard/Carousel.tsx | 80 +++--- .../components/custom/MovieCard/MovieCard.tsx | 252 +++++++++--------- 2 files changed, 181 insertions(+), 151 deletions(-) diff --git a/client/src/components/custom/MovieCard/Carousel.tsx b/client/src/components/custom/MovieCard/Carousel.tsx index c776cc74..aa4caf59 100644 --- a/client/src/components/custom/MovieCard/Carousel.tsx +++ b/client/src/components/custom/MovieCard/Carousel.tsx @@ -1,4 +1,4 @@ -import React, { useEffect, useState } from "react" +import React, { useEffect, useState, useRef } from "react" import MovieCard from "./MovieCard" import { MovieListType, useMovieList } from "@/services/movieService" import { useJournal } from "@/services/journalService" @@ -6,6 +6,8 @@ import { calculateTopGenres, genreMap } from "@/lib/stats" import { useAuth } from "@/hooks/useAuth" import { getUserData } from "@/services/userService" import { SimpleMovie } from "@/Types/Movie" +import { ChevronRight } from "lucide-react" + interface List { list_id: string name: string @@ -31,15 +33,25 @@ const MovieList: React.FC = ({ }) => { const { user } = useAuth() const { data: movies, isLoading, error } = useMovieList(type, 1) + const [hoveredList, setHoveredList] = useState(null) const { useGetJournalEntries } = useJournal() const { data: journalEntries } = useGetJournalEntries() const [favGenre, setFavGenre] = useState(null) const [favGenreMovies, setFavGenreMovies] = useState([]) - console.log("favegenre", favGenre) const { data: favoriteGenreMovies, isLoading: isFavGenreLoading } = useMovieList("discover", 1, favGenre || undefined) + const handleScroll = (containerId: string) => { + const container = document.getElementById(containerId); + if (container) { + const cardWidth = 256; // This is the lg:w-64 value + const gap = 16; // This is the gap-4 value + const scrollAmount = (cardWidth + gap) * 4; // Scroll 4 cards at a time + container.scrollBy({ left: scrollAmount, behavior: 'smooth' }); + } + }; + useEffect(() => { const fetchFavoriteGenre = async () => { if (journalEntries && journalEntries.length > 0) { @@ -56,7 +68,6 @@ const MovieList: React.FC = ({ topGenres[0]?.genre || "" ) setFavGenre(topGenre) - console.log("topGenres", topGenres) } else if (user?.uid) { try { const userData: UserData = await getUserData(user.uid) @@ -68,9 +79,7 @@ const MovieList: React.FC = ({ const genres = topMovies .flatMap((movie) => movie.genre_ids) .filter(Boolean) - console.log("genres", genres) - // Count the occurrences of each genre const genreCounts = genres.reduce( (acc, genre) => { acc[genre!] = (acc[genre!] || 0) + 1 @@ -79,19 +88,15 @@ const MovieList: React.FC = ({ {} as Record ) - // Find the maximum count const maxCount = Math.max(...Object.values(genreCounts)) - // Filter genres with the maximum count const topGenres = Object.entries(genreCounts) .filter(([, count]) => count === maxCount) .map(([genre]) => parseInt(genre)) - // Choose the smallest genre ID among the top genres const mostCommonGenre = Math.min(...topGenres) setFavGenre(mostCommonGenre) - console.log("mostCommonGenre", mostCommonGenre) } } catch (error) { console.error("Error fetching user data:", error) @@ -104,9 +109,7 @@ const MovieList: React.FC = ({ useEffect(() => { if (favoriteGenreMovies) { - console.log("favoriteGenreMovies 1", favoriteGenreMovies) setFavGenreMovies(favoriteGenreMovies) - console.log("favoriteGenreMovies", favoriteGenreMovies) } }, [favoriteGenreMovies]) @@ -119,27 +122,44 @@ const MovieList: React.FC = ({ ) - const renderMovieList = (movieList: SimpleMovie[], title: string) => ( -
-

{title}

-
-
- {movieList?.map((movie) => ( -
- + const renderMovieList = (movieList: SimpleMovie[], title: string) => { + const containerId = `movie-list-${title.replace(/\s+/g, '-').toLowerCase()}`; + + return ( +
+

{title}

+
setHoveredList(containerId)} + onMouseLeave={() => setHoveredList(null)}> +
+
+ {movieList?.map((movie) => ( +
+ +
+ ))}
- ))} +
+ {hoveredList === containerId && ( + + )}
-
- ) + ) + } return ( <> @@ -155,4 +175,4 @@ const MovieList: React.FC = ({ ) } -export default MovieList +export default MovieList \ No newline at end of file diff --git a/client/src/components/custom/MovieCard/MovieCard.tsx b/client/src/components/custom/MovieCard/MovieCard.tsx index bf31d59e..5da1a60a 100644 --- a/client/src/components/custom/MovieCard/MovieCard.tsx +++ b/client/src/components/custom/MovieCard/MovieCard.tsx @@ -1,150 +1,160 @@ -import React, { useState } from "react"; -import { motion, AnimatePresence } from "framer-motion"; +import React, { useState, useEffect } from "react"; +import { motion } from "framer-motion"; import { useNavigate } from "react-router-dom"; -import { Play, Plus, ThumbsUp } from "lucide-react"; -import LazyImage from "../LazyLoadImage/LazyImage"; +import { Heart } from "lucide-react"; +import { toast } from "react-toastify"; +import { useAuth } from "@/hooks/useAuth"; +import { addMovieToList, createList, getUserData } from "@/services/userService"; const IMAGE_URL = "https://image.tmdb.org/t/p"; -const genreMap: { [key: number]: string } = { - 28: "Action", - 12: "Adventure", - 16: "Animation", - 35: "Comedy", - 80: "Crime", - 99: "Documentary", - 18: "Drama", - 10751: "Family", - 14: "Fantasy", - 36: "History", - 27: "Horror", - 10402: "Music", - 9648: "Mystery", - 10749: "Romance", - 878: "Science Fiction", - 10770: "TV Movie", - 53: "Thriller", - 10752: "War", - 37: "Western" -}; - interface MovieCardProps { movie_id: string; title: string | undefined; poster_path: string | undefined; - backdrop_path: string | undefined; release_date: string | undefined; - genre_ids: number[] | undefined; +} + +interface SimpleMovie { + id: string; + movie_id: string; + title: string; + poster_path: string; + release_date: string; } const MovieCard: React.FC = ({ movie_id, title, poster_path, - backdrop_path, release_date, - genre_ids, }) => { const navigate = useNavigate(); - const [isHovered, setIsHovered] = useState(false); + const [isFavourite, setIsFavourite] = useState(false); + const [isLoading, setIsLoading] = useState(false); + const { user } = useAuth(); + + useEffect(() => { + const checkFavouriteStatus = async () => { + if (user?.uid) { + try { + const userData = await getUserData(user.uid); + const favouritesList = userData.lists.find( + (list: any) => list.name === "Favourites" + ); + if (favouritesList) { + setIsFavourite( + favouritesList.movies.some((m: any) => m.movie_id === movie_id) + ); + } + } catch (error) { + console.error("Error checking favourite status:", error); + } + } + }; + + checkFavouriteStatus(); + }, [movie_id, user]); - const handleClick = (e: React.MouseEvent) => { - e.stopPropagation(); // Prevent event from bubbling up - console.log("movie_id:", movie_id); + const handleClick = () => { navigate(`/movie/${movie_id}`); }; - const genreNames = genre_ids - ?.map((id) => genreMap[id]) - .filter(Boolean) - .slice(0, 3); + const handleFavouriteClick = async (e: React.MouseEvent) => { + e.stopPropagation(); + if (!user) { + toast.error("Please log in to add movies to your Favourites."); + return; + } + + // Validate required fields before proceeding + if (!title || !poster_path || !release_date) { + toast.error("Missing required movie information."); + return; + } + + setIsLoading(true); + try { + const userData = await getUserData(user.uid); + let favouritesList = userData.lists.find( + (list: any) => list.name === "Favourites" + ); + + if (!favouritesList) { + const createListData = { + name: "Favourites", + description: "My favourite movies", + isPublic: true, + }; + favouritesList = await createList(user.uid, { + ...createListData, + list_type: "user", + }); + } + + // Check if the movie is already in the favourites list + const movieToAdd: SimpleMovie = { + id: movie_id, + movie_id: movie_id, + title: title, + poster_path: poster_path, + release_date: release_date, + }; + + // Only add the movie if it's not already a favourite + if (!isFavourite) { + await addMovieToList(favouritesList.list_id, movieToAdd); + setIsFavourite(true); + toast.success(`${title} has been added to your Favourites.`); + } else { + toast.info(`${title} is already in your Favourites.`); + } + } catch (error) { + console.error("Error adding movie to Favourites:", error); + toast.error("Failed to add movie. Please try again."); + } finally { + setIsLoading(false); + } + }; return ( -
setIsHovered(true)} - onMouseLeave={() => setIsHovered(false)} + - - - + {title - - {isHovered && ( - - -
-

{title}

-
- { - e.stopPropagation(); - // Add play functionality here - }} - > - - - { - e.stopPropagation(); - // Add to list functionality here - }} - > - - - { - e.stopPropagation(); - // Add like functionality here - }} - > - - -
-
- 97% Match - {release_date?.split('-')[0]} -
-
- {genreNames?.join(" • ")} -
-
-
- )} -
-
+
+ {/* */} + +
+
+ {release_date?.split('-')[0]} +
+

+ {title} +

+
+
+ ); };