From d37aead0a2655d9c303c0a101d463bbbd91c663f Mon Sep 17 00:00:00 2001 From: chaaanuwu Date: Thu, 9 Apr 2026 15:22:21 +0530 Subject: [PATCH 1/2] feat: Implement add and remove watched movie functionality; update MoviePage and API integration --- client/src/api/history.api.js | 10 ++++++ client/src/pages/MoviePage.jsx | 46 ++++++++++++++++++++---- server/controllers/history.controller.js | 2 +- 3 files changed, 50 insertions(+), 8 deletions(-) diff --git a/client/src/api/history.api.js b/client/src/api/history.api.js index c1c34c2..4134769 100644 --- a/client/src/api/history.api.js +++ b/client/src/api/history.api.js @@ -15,4 +15,14 @@ export const getMovieHistory = async (movieId) => { export const getHistoryBanner = async () => { const res = await axiosInstance.get('/history'); return res.data; +} + +export const addWatchedMovie = async (title) => { + const res = await axiosInstance.post('/history', { title }); + return res; +} + +export const removeMovieFromHistory = async (movieId) => { + const res = await axiosInstance.delete(`/history/movie/${movieId}`); + return res; } \ No newline at end of file diff --git a/client/src/pages/MoviePage.jsx b/client/src/pages/MoviePage.jsx index b5c48ed..cae2fdd 100644 --- a/client/src/pages/MoviePage.jsx +++ b/client/src/pages/MoviePage.jsx @@ -2,8 +2,9 @@ import { useEffect, useState } from "react"; import { motion } from "framer-motion"; import { getMovieById } from "../api/movie.api"; import Loader from "../components/ui/Loader"; -import { getMovieHistory } from "../api/history.api"; +import { addWatchedMovie, getMovieHistory, removeMovieFromHistory } from "../api/history.api"; import { getIsMovieWatchListed } from "../api/watchList.api"; +import { BookmarkIcon, CheckCircleIcon, ClockIcon } from "@heroicons/react/24/solid"; export default function MoviePage() { const [movieData, setMovieData] = useState(null); @@ -23,9 +24,11 @@ export default function MoviePage() { getMovieHistory(movieId), getIsMovieWatchListed(movieId) ]); + setMovieData(res[0]); setWatched(res[1].data != null); setInList(res[2].data.watchListed); + } catch (error) { console.error("Error fetching movie: ", error); } finally { @@ -35,6 +38,30 @@ export default function MoviePage() { fetchMovie(); }, [movieId]); + const handleWatchedToggle = async () => { + try { + if (watched) { + const res = await removeMovieFromHistory(movieData._id); + if (res.status === 200) { + setWatched(false); + } + } else { + const res = await addWatchedMovie(movieData.title); + + if (res.status === 201) { + setWatched(true); + + setMovieData((prev) => ({ + ...prev, + ...res.data + })); + } + } + } catch (error) { + console.error("Error updating watch status: ", error); + } + } + if (loading) return ; const releaseYear = movieData ? new Date(movieData.releaseDate).getFullYear() : ""; @@ -117,17 +144,19 @@ export default function MoviePage() { > setWatched(!watched)} - activeClass="bg-(--interaction-color) text-white border-(--interaction-color)" + onClick={handleWatchedToggle} + activeClass="bg-amber-400 text-white border-amber-400" label={watched ? "Watched" : "Mark as watched"} - icon={watched ? "✓" : "○"} + trueIcon={} + falseIcon={} /> setInList(!inList)} activeClass="bg-(--secondary-color) text-white border-(--secondary-color)" label={inList ? "In Watchlist" : "Add to Watchlist"} - icon="+" + trueIcon={} + falseIcon={} /> ); diff --git a/server/controllers/history.controller.js b/server/controllers/history.controller.js index c043437..4ea673e 100644 --- a/server/controllers/history.controller.js +++ b/server/controllers/history.controller.js @@ -193,7 +193,7 @@ export const removeWatchedMovie = async (req, res) => { } const deletedMovie = await History.findOneAndDelete({ - _id: movieId, + movieId, userId }).populate("movieId", "title"); From be9595d4749f601e5ccac8829603a26daf35ae11 Mon Sep 17 00:00:00 2001 From: chaaanuwu Date: Thu, 9 Apr 2026 15:49:38 +0530 Subject: [PATCH 2/2] feat: Implement watchlist functionality in MoviePage; add toggle for adding/removing movies from watchlist --- client/src/api/watchList.api.js | 10 ++++++++++ client/src/pages/MoviePage.jsx | 28 ++++++++++++++++++++++++---- 2 files changed, 34 insertions(+), 4 deletions(-) diff --git a/client/src/api/watchList.api.js b/client/src/api/watchList.api.js index eb17523..86e35ab 100644 --- a/client/src/api/watchList.api.js +++ b/client/src/api/watchList.api.js @@ -3,4 +3,14 @@ import axiosInstance from "./axiosInstance" export const getIsMovieWatchListed = async (movieId) => { const res = await axiosInstance.get(`/watchlist/movie/${movieId}`); return res.data; +} + +export const addMovieToWatchList = async (title) => { + const res = await axiosInstance.post('/watchlist', { title }); + return res; +} + +export const removeMovieFromWatchList = async (movieId) => { + const res = await axiosInstance.delete(`/watchlist/movie/${movieId}`); + return res; } \ No newline at end of file diff --git a/client/src/pages/MoviePage.jsx b/client/src/pages/MoviePage.jsx index cae2fdd..27f1c6e 100644 --- a/client/src/pages/MoviePage.jsx +++ b/client/src/pages/MoviePage.jsx @@ -1,9 +1,10 @@ import { useEffect, useState } from "react"; +import { useParams } from "react-router-dom"; import { motion } from "framer-motion"; import { getMovieById } from "../api/movie.api"; import Loader from "../components/ui/Loader"; import { addWatchedMovie, getMovieHistory, removeMovieFromHistory } from "../api/history.api"; -import { getIsMovieWatchListed } from "../api/watchList.api"; +import { addMovieToWatchList, getIsMovieWatchListed, removeMovieFromWatchList } from "../api/watchList.api"; import { BookmarkIcon, CheckCircleIcon, ClockIcon } from "@heroicons/react/24/solid"; export default function MoviePage() { @@ -13,7 +14,7 @@ export default function MoviePage() { const [inList, setInList] = useState(false); const [reviewOpen, setReviewOpen] = useState(false); - const movieId = window.location.pathname.split("/movies/")[1]; + const { movieId } = useParams(); useEffect(() => { if (!movieId) return; @@ -49,6 +50,8 @@ export default function MoviePage() { const res = await addWatchedMovie(movieData.title); if (res.status === 201) { + if (inList) setInList(false); + setWatched(true); setMovieData((prev) => ({ @@ -62,6 +65,24 @@ export default function MoviePage() { } } + const handleWatchListToggle = async () => { + try { + if (inList) { + const res = await removeMovieFromWatchList(movieData._id); + if (res.status === 200) { + setInList(false); + } + } else { + const res = await addMovieToWatchList(movieData.title); + if (res.status === 201) { + setInList(true); + } + } + } catch (error) { + console.error("Error updating watchlist status: ", error); + } + } + if (loading) return ; const releaseYear = movieData ? new Date(movieData.releaseDate).getFullYear() : ""; @@ -135,7 +156,6 @@ export default function MoviePage() { - {/* Action Buttons */} setInList(!inList)} + onClick={handleWatchListToggle} activeClass="bg-(--secondary-color) text-white border-(--secondary-color)" label={inList ? "In Watchlist" : "Add to Watchlist"} trueIcon={}