├── src
├── readme.md
├── App.css
├── images
│ ├── GithubLogo.png
│ ├── GoogleLogo.png
│ ├── EndgamePoster.jpg
│ ├── WelcomePageBanner.jpg
│ ├── WelcomePageImage1.png
│ ├── WelcomePageImage2.png
│ ├── WelcomePageImage3.png
│ └── WelcomePageImage4.png
├── axios.js
├── Pages
│ ├── MyList.jsx
│ ├── History.jsx
│ ├── LikedMovies.jsx
│ ├── Series.jsx
│ ├── ErrorPage.jsx
│ ├── Home.jsx
│ ├── Welcome.jsx
│ ├── SignUp.jsx
│ ├── Search.jsx
│ ├── SignIn.jsx
│ ├── Profile.jsx
│ └── Play.jsx
├── componets
│ ├── Loading
│ │ └── Loading.jsx
│ ├── Footer
│ │ ├── Footer.jsx
│ │ └── styles.module.scss
│ ├── Header
│ │ ├── NavbarWithoutUser.jsx
│ │ └── Navbar.jsx
│ ├── RowPost
│ │ ├── RowPostStyles.scss
│ │ └── RowPost.jsx
│ ├── Banner
│ │ └── Banner.jsx
│ ├── UserMovieSection
│ │ └── UserMovieSection.jsx
│ └── PopUp
│ │ └── MoviePopUp.jsx
├── Context
│ ├── UserContext.jsx
│ └── moviePopUpContext.jsx
├── index.css
├── CustomHooks
│ ├── usePlayMovie.jsx
│ ├── useGenereConverter.jsx
│ ├── useUpdateWatchedMovies.jsx
│ ├── useUpdateLikedMovies.jsx
│ └── useUpdateMylist.jsx
├── index.jsx
├── Firebase
│ └── FirebaseConfig.js
├── Constants
│ ├── URLs.js
│ └── Constance.js
└── App.jsx
├── vercel.json
├── postcss.config.cjs
├── vite.config.js
├── .gitignore
├── .vscode
└── extensions.json
├── LICENSE
├── package.json
├── index.html
├── public
└── vite.svg
├── tailwind.config.cjs
└── README.md
/src/readme.md:
--------------------------------------------------------------------------------
1 | # Netflix UI clone with React.js
2 | ## _This is the directory_
3 | ---
4 |
5 |
--------------------------------------------------------------------------------
/vercel.json:
--------------------------------------------------------------------------------
1 | {
2 | "rewrites": [
3 | {"source": "/(.*)", "destination": "/"}
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/src/App.css:
--------------------------------------------------------------------------------
1 | body {
2 | background: #111;
3 | scroll-behavior: smooth;
4 | overflow-x: hidden;
5 | }
6 |
--------------------------------------------------------------------------------
/src/images/GithubLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JosinJojy/Netflix-reactjs/HEAD/src/images/GithubLogo.png
--------------------------------------------------------------------------------
/src/images/GoogleLogo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JosinJojy/Netflix-reactjs/HEAD/src/images/GoogleLogo.png
--------------------------------------------------------------------------------
/src/images/EndgamePoster.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JosinJojy/Netflix-reactjs/HEAD/src/images/EndgamePoster.jpg
--------------------------------------------------------------------------------
/postcss.config.cjs:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | plugins: {
3 | tailwindcss: {},
4 | autoprefixer: {},
5 | },
6 | }
7 |
--------------------------------------------------------------------------------
/src/images/WelcomePageBanner.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JosinJojy/Netflix-reactjs/HEAD/src/images/WelcomePageBanner.jpg
--------------------------------------------------------------------------------
/src/images/WelcomePageImage1.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JosinJojy/Netflix-reactjs/HEAD/src/images/WelcomePageImage1.png
--------------------------------------------------------------------------------
/src/images/WelcomePageImage2.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JosinJojy/Netflix-reactjs/HEAD/src/images/WelcomePageImage2.png
--------------------------------------------------------------------------------
/src/images/WelcomePageImage3.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JosinJojy/Netflix-reactjs/HEAD/src/images/WelcomePageImage3.png
--------------------------------------------------------------------------------
/src/images/WelcomePageImage4.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/JosinJojy/Netflix-reactjs/HEAD/src/images/WelcomePageImage4.png
--------------------------------------------------------------------------------
/src/axios.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { baseUrl } from "./Constants/Constance";
3 |
4 | const instance = axios.create({
5 | baseURL: baseUrl,
6 | });
7 | export default instance;
8 |
--------------------------------------------------------------------------------
/vite.config.js:
--------------------------------------------------------------------------------
1 | import { defineConfig } from 'vite'
2 | import react from '@vitejs/plugin-react'
3 |
4 | // https://vitejs.dev/config/
5 | export default defineConfig({
6 | plugins: [react()]
7 | })
8 |
--------------------------------------------------------------------------------
/src/Pages/MyList.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import UserMovieSection from "../componets/UserMovieSection/UserMovieSection";
3 |
4 | function MyList() {
5 | return ;
6 | }
7 |
8 | export default MyList;
9 |
--------------------------------------------------------------------------------
/src/Pages/History.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import UserMovieSection from "../componets/UserMovieSection/UserMovieSection";
3 |
4 | function History() {
5 | return ;
6 | }
7 |
8 | export default History;
9 |
--------------------------------------------------------------------------------
/src/Pages/LikedMovies.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import UserMovieSection from "../componets/UserMovieSection/UserMovieSection";
3 |
4 | function LikedMovies() {
5 | return ;
6 | }
7 |
8 | export default LikedMovies;
9 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | pnpm-debug.log*
8 | lerna-debug.log*
9 |
10 | node_modules
11 | dist
12 | dist-ssr
13 | *.local
14 |
15 | # Editor directories and files
16 | .vscode/*
17 | !.vscode/extensions.json
18 | .idea
19 | .DS_Store
20 | *.suo
21 | *.ntvs*
22 | *.njsproj
23 | *.sln
24 | *.sw?
25 |
--------------------------------------------------------------------------------
/src/componets/Loading/Loading.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { ClipLoader } from "react-spinners";
3 |
4 | function Loading() {
5 | return (
6 |
11 | );
12 | }
13 |
14 | export default Loading;
15 |
--------------------------------------------------------------------------------
/src/Context/UserContext.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, useState } from "react";
2 |
3 | export const AuthContext = createContext(null);
4 |
5 | export default function Context({ children }) {
6 | const [User, setUser] = useState(null);
7 |
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/src/index.css:
--------------------------------------------------------------------------------
1 | @tailwind base;
2 | @tailwind components;
3 | @tailwind utilities;
4 |
5 | body {
6 | margin: 0;
7 | font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", "Roboto", "Oxygen",
8 | "Ubuntu", "Cantarell", "Fira Sans", "Droid Sans", "Helvetica Neue",
9 | sans-serif;
10 | -webkit-font-smoothing: antialiased;
11 | -moz-osx-font-smoothing: grayscale;
12 | }
13 |
--------------------------------------------------------------------------------
/src/Context/moviePopUpContext.jsx:
--------------------------------------------------------------------------------
1 | import { createContext, useState } from "react";
2 |
3 | export const PopUpContext = createContext(null);
4 |
5 | export default function Context2({ children }) {
6 | const [showModal, setShowModal] = useState(false);
7 |
8 | return (
9 |
10 | {children}
11 |
12 | );
13 | }
14 |
--------------------------------------------------------------------------------
/.vscode/extensions.json:
--------------------------------------------------------------------------------
1 | {
2 | // See https://go.microsoft.com/fwlink/?LinkId=827846 to learn about workspace recommendations.
3 | // Extension identifier format: ${publisher}.${name}. Example: vscode.csharp
4 |
5 | // List of extensions which should be recommended for users of this workspace.
6 | "recommendations": [
7 |
8 | ],
9 | // List of extensions recommended by VS Code that should not be recommended for users of this workspace.
10 | "unwantedRecommendations": [
11 |
12 | ]
13 | }
--------------------------------------------------------------------------------
/src/CustomHooks/usePlayMovie.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useNavigate } from "react-router-dom";
3 | import useUpdateWatchedMovies from "./useUpdateWatchedMovies";
4 |
5 | function usePlayMovie() {
6 | const { addToWatchedMovies } = useUpdateWatchedMovies();
7 | const navigate = useNavigate();
8 |
9 | const playMovie = (movie, from) => {
10 | addToWatchedMovies(movie);
11 | navigate(`/play/${movie.id}`, { replace: true, state: { From: from } });
12 | };
13 |
14 | return { playMovie };
15 | }
16 |
17 | export default usePlayMovie;
18 |
--------------------------------------------------------------------------------
/src/CustomHooks/useGenereConverter.jsx:
--------------------------------------------------------------------------------
1 | import { genresList } from "../Constants/Constance";
2 |
3 | const useGenereConverter = () => {
4 | const convertGenere = (genreIds) => {
5 | const genresConvertedList = [];
6 | genreIds
7 | .slice(0, 3)
8 | .map((genreId) =>
9 | genresList
10 | .filter((el) => el.id === genreId)
11 | .map((el) => genresConvertedList.push(el.name))
12 | );
13 |
14 | return genresConvertedList;
15 | };
16 |
17 | return { convertGenere };
18 | };
19 |
20 | export default useGenereConverter;
21 |
--------------------------------------------------------------------------------
/src/index.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import ReactDOM from "react-dom/client";
3 | import App from "./App";
4 | import "./index.css";
5 |
6 | import { BrowserRouter as Router } from "react-router-dom";
7 | import { FirebaseApp } from "./Firebase/FirebaseConfig";
8 | import Context from "./Context/UserContext";
9 | import Context2 from "./Context/moviePopUpContext";
10 |
11 | ReactDOM.createRoot(document.getElementById("root")).render(
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 | );
22 |
--------------------------------------------------------------------------------
/src/Firebase/FirebaseConfig.js:
--------------------------------------------------------------------------------
1 | import { initializeApp } from "firebase/app";
2 | import { getAnalytics } from "firebase/analytics";
3 | import { getFirestore } from "firebase/firestore";
4 |
5 | const firebaseConfig = {
6 | apiKey: "AIzaSyBIhBiO3flFpAcL2Fm_Ef22QQo6udFp5b4",
7 | authDomain: "react-netflix-eb4f0.firebaseapp.com",
8 | projectId: "react-netflix-eb4f0",
9 | storageBucket: "react-netflix-eb4f0.appspot.com",
10 | messagingSenderId: "29045190704",
11 | appId: "1:29045190704:web:a7c74bd778aa5f993c7df5",
12 | measurementId: "G-9TB7LL3YPM",
13 | };
14 |
15 | // Initialize Firebase
16 | export const FirebaseApp = initializeApp(firebaseConfig);
17 | export const db = getFirestore(FirebaseApp);
18 | const analytics = getAnalytics(FirebaseApp);
19 |
--------------------------------------------------------------------------------
/src/Constants/URLs.js:
--------------------------------------------------------------------------------
1 | import { API_KEY } from "../Constants/Constance";
2 | export const TopRated = `/movie/top_rated?api_key=${API_KEY}&language=en-US`;
3 | export const originals = `discover/tv?api_key=${API_KEY}&with_networks=213&sort_by=popularity.desc&language=en-US`;
4 | export const action = `discover/movie?api_key=${API_KEY}&with_genres=28`;
5 | export const comedy = `discover/movie?api_key=${API_KEY}&with_genres=35`;
6 | export const horror = `discover/movie?api_key=${API_KEY}&with_genres=27`;
7 | export const Adventure = `discover/movie?api_key=${API_KEY}&with_genres=12`;
8 | export const SciFi = `discover/movie?api_key=${API_KEY}&with_genres=878`;
9 | export const Animated = `discover/movie?api_key=${API_KEY}&with_genres=16`;
10 | export const War = `discover/movie?api_key=${API_KEY}&with_genres=10752`;
11 | export const trending = `trending/all/week?api_key=${API_KEY}&sort_by=popularity.desc&language=en-US`;
12 | export const trendingSeries = `/trending/tv/week?api_key=${API_KEY}&sort_by=popularity.desc&language=en-US`;
13 | export const UpcomingMovies = `/movie/upcoming?api_key=${API_KEY}&language=en-US`;
14 |
--------------------------------------------------------------------------------
/src/componets/Footer/Footer.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import styles from "./styles.module.scss";
3 |
4 | function Footer2() {
5 | return (
6 |
7 |
31 |
32 | );
33 | }
34 |
35 | export default Footer2;
36 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2023 Josin Jojy
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "netflix-reactjs",
3 | "private": true,
4 | "version": "0.0.0",
5 | "type": "module",
6 | "scripts": {
7 | "dev": "vite",
8 | "build": "vite build",
9 | "preview": "vite preview"
10 | },
11 | "dependencies": {
12 | "@headlessui/react": "^1.7.4",
13 | "@tailwindcss/line-clamp": "^0.4.2",
14 | "@tanstack/react-query": "^4.28.0",
15 | "@tanstack/react-query-devtools": "^4.29.0",
16 | "axios": "^1.2.1",
17 | "firebase": "^9.14.0",
18 | "react": "^18.2.0",
19 | "react-dom": "^18.2.0",
20 | "react-hot-toast": "^2.4.0",
21 | "react-reveal": "^1.2.2",
22 | "react-router-dom": "^6.4.4",
23 | "react-spinners": "^0.13.7",
24 | "react-star-ratings": "^2.3.0",
25 | "react-youtube": "^10.1.0",
26 | "swiper": "^8.4.5"
27 | },
28 | "devDependencies": {
29 | "@types/react": "^18.0.24",
30 | "@types/react-dom": "^18.0.8",
31 | "@vitejs/plugin-react": "^2.2.0",
32 | "autoprefixer": "^10.4.13",
33 | "postcss": "^8.4.19",
34 | "react-hot-loader": "^4.13.1",
35 | "sass": "^1.56.1",
36 | "tailwindcss": "^3.2.4",
37 | "tailwindcss-textshadow": "^2.1.3",
38 | "vite": "^3.2.3"
39 | }
40 | }
41 |
--------------------------------------------------------------------------------
/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | Netflix Clone React.js
9 |
10 |
11 |
12 |
13 |
14 |
20 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
--------------------------------------------------------------------------------
/public/vite.svg:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/src/Pages/Series.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import Banner from "../componets/Banner/Banner";
3 | import Footer from "../componets/Footer/Footer";
4 | import RowPost from "../componets/RowPost/RowPost";
5 | import {
6 | originals,
7 | comedy,
8 | horror,
9 | Adventure,
10 | SciFi,
11 | Animated,
12 | War,
13 | trendingSeries,
14 | UpcomingMovies,
15 | } from "../Constants/URLs";
16 |
17 | function Series() {
18 | return (
19 |
20 |
21 |
22 |
28 |
29 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 | );
45 | }
46 |
47 | export default Series;
48 |
--------------------------------------------------------------------------------
/src/componets/Header/NavbarWithoutUser.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect } from "react";
2 | import { Link } from "react-router-dom";
3 |
4 | function NavbarWithoutUser() {
5 | const [show, handleShow] = useState(false);
6 | const transitionNavBar = () => {
7 | if (window.scrollY > 100) {
8 | handleShow(true);
9 | } else {
10 | handleShow(false);
11 | }
12 | };
13 |
14 | useEffect(() => {
15 | window.addEventListener("scroll", transitionNavBar);
16 | return () => {
17 | window.removeEventListener("scroll", transitionNavBar);
18 | };
19 | }, []);
20 |
21 | return (
22 |
45 | );
46 | }
47 |
48 | export default NavbarWithoutUser;
49 |
--------------------------------------------------------------------------------
/tailwind.config.cjs:
--------------------------------------------------------------------------------
1 | /** @type {import('tailwindcss').Config} */
2 | module.exports = {
3 | content: [
4 | "./index.html",
5 | "./src/**/*.{js,ts,jsx,tsx}",
6 | ],
7 | theme: {
8 | screens:{
9 | 'sm': '640px',
10 | 'md': '768px',
11 | 'lg': '1024px',
12 | 'xl': '1280px',
13 | '2xl': '1536px',
14 | '3xl': '2200px',
15 | },
16 | extend: {
17 | padding:{
18 | '85vh': '85vh',
19 | '50vh': '50vh',
20 | },
21 | spacing:{
22 | '40rem': "40rem",
23 | '45rem': "45rem",
24 | '55rem': "55rem",
25 | '63rem': "63rem",
26 | '70rem': "70rem",
27 |
28 | },
29 | width:{
30 | '96%' :"96%",
31 | },
32 | background:{
33 | 'avengers': "linear-gradient(to right bottom, rgba('#7ed56f',0.8), rgba('#28b485',0.8)),url()",
34 | 'fadeBottom': "linear-gradient(180deg,hsl(0deg 0% 0% / 0%),#000000a2,hsl(0deg 0% 7%));",
35 | 'fadeBlack': "background: linear-gradient(1turn,hsl(0deg 0% 0% / 60%),hsl(0deg 0% 0% / 0%) 65%);",
36 | 'fadeRed' : "linear-gradient(90deg, hsl(0deg 77% 42% / 44%) 0%, hsl(0deg 59% 46% / 51%) 35%, hsl(220deg 26% 44% / 0%) 100%) "
37 | },
38 | color:{
39 | 'black': "#010511",
40 | 'transparenWhite': "#33333380",
41 | 'transparentBlack': "#000000bf"
42 | },
43 | margin:{
44 | '-6%': "-6%",
45 | '50%': "50%",
46 | }
47 | },
48 | },
49 | plugins: [
50 | require('@tailwindcss/line-clamp'),
51 | require('tailwindcss-textshadow'),
52 | ],
53 | }
54 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Netflix Clone React.js
2 |
3 | ## Overview
4 | This project is a Netflix clone built using React.js, designed to enhance skills in web development. It features a fully interactive user interface with various functionalities, making it a comprehensive movie-watching experience. The project is powered by TMDB API, utilizing Firebase for database management.
5 |
6 | ## Screenshots
7 |
8 | 
9 |
10 |
11 |
12 | ### mobile experience
13 | 
14 |
15 | ## Key Functionalities
16 | - Sign In / Sign Up
17 | - Home Page for browsing movies
18 | - My List Section for user-specific movie selections
19 | - Liked Movies Page
20 | - Watched Movies Page
21 | - Profile Page
22 | - Play Movie Page
23 | - Search Movie Page
24 |
25 | ## Technologies Used
26 | - [React.js](https://react.dev/)
27 | - [TMDB API](https://www.themoviedb.org/)
28 | - [Firebase](https://firebase.google.com/)
29 | - [Axios](https://www.npmjs.com/package/axios)
30 | - [Swiper.js](https://swiperjs.com/)
31 | - [React-Youtube](https://www.npmjs.com/package/react-youtube)
32 | - [Tailwind CSS](https://tailwindcss.com/)
33 |
34 | ## Description
35 | This Netflix clone project was developed to deepen understanding and proficiency in React.js. Leveraging popular technologies and APIs like TMDB and Firebase, it encompasses a range of features, from user authentication to dynamic movie listings. The design is tailored to provide an immersive streaming experience, and the codebase reflects best practices in modern web development.
36 |
37 | ## Link to the Site
38 | [Netflix Clone](https://movieflix-reactjs.vercel.app/)
39 |
--------------------------------------------------------------------------------
/src/CustomHooks/useUpdateWatchedMovies.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useState } from "react";
2 | import { updateDoc, doc, arrayUnion, arrayRemove } from "firebase/firestore";
3 | import { db } from "../Firebase/FirebaseConfig";
4 | import { AuthContext } from "../Context/UserContext";
5 | import toast, { Toaster } from "react-hot-toast";
6 |
7 | function useUpdateWatchedMovies() {
8 | const { User } = useContext(AuthContext);
9 | const [Error, setError] = useState(false);
10 |
11 | function notify() {
12 | toast.success(" Movie removed from Watched List ");
13 | }
14 | function alertError(message) {
15 | toast.error(message);
16 | }
17 | const addToWatchedMovies = (movie) => {
18 | updateDoc(doc(db, "WatchedMovies", User.uid), {
19 | movies: arrayUnion(movie),
20 | });
21 | };
22 |
23 | const removeFromWatchedMovies = (movie) => {
24 | updateDoc(doc(db, "WatchedMovies", User.uid), {
25 | movies: arrayRemove(movie),
26 | })
27 | .then(() => {
28 | notify();
29 | })
30 | .catch((error) => {
31 | console.log(error.code);
32 | console.log(error.message);
33 | alertError(error.message);
34 | setError(true);
35 | });
36 | };
37 |
38 | const removePopupMessage = (
39 |
48 | );
49 |
50 | return { addToWatchedMovies, removeFromWatchedMovies, removePopupMessage };
51 | }
52 |
53 | export default useUpdateWatchedMovies;
54 |
--------------------------------------------------------------------------------
/src/Pages/ErrorPage.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useNavigate } from "react-router-dom";
3 |
4 | function ErrorPage() {
5 | const navigate = useNavigate();
6 | return (
7 |
8 |
9 |
10 | 404 error
11 |
12 |
13 | Page not found
14 |
15 |
37 |
38 |
39 | );
40 | }
41 |
42 | export default ErrorPage;
43 |
--------------------------------------------------------------------------------
/src/componets/Footer/styles.module.scss:
--------------------------------------------------------------------------------
1 | .footer {
2 | max-width: 980px;
3 | margin: 25px auto;
4 | padding: 0 30px;
5 | color: #808080;
6 | font-size: 1rem;
7 | }
8 |
9 | .containerFooter {
10 | display: flex;
11 | flex-direction: column;
12 | align-items: flex-start;
13 |
14 | .icons {
15 | display: flex;
16 | margin-bottom: 10px;
17 |
18 | svg {
19 | height: 30px;
20 | width: 41px;
21 | margin-right: 8px;
22 | cursor: pointer;
23 | }
24 |
25 | :first-child {
26 | margin-left: -9px;
27 | }
28 | }
29 |
30 | .details {
31 | display: flex;
32 | align-items: flex-start;
33 | flex-wrap: wrap;
34 |
35 | li {
36 | list-style: none;
37 | margin-bottom: 16px;
38 | flex-basis: 25%;
39 | text-align: left;
40 | cursor: pointer;
41 |
42 | &:hover {
43 | text-decoration: underline;
44 | }
45 | }
46 | }
47 |
48 | .security {
49 | display: flex;
50 | flex-direction: column;
51 |
52 | div {
53 | border: 1px solid #808080;
54 | padding: 7px 10px;
55 | cursor: pointer;
56 | margin-bottom: 15px;
57 | transition: all 0.2s ease;
58 |
59 | &:hover {
60 | color: white;
61 | }
62 | }
63 | }
64 | }
65 |
66 | @media (max-width: 710px) {
67 | .footer {
68 | font-size: 12px;
69 | }
70 |
71 | .containerFooter .details li {
72 | flex-basis: 33%;
73 | }
74 |
75 | .containerFooter .security {
76 | flex-direction: row;
77 | align-items: center;
78 |
79 | div {
80 | margin-bottom: 0;
81 | }
82 |
83 | span {
84 | margin-left: 15px;
85 | }
86 | }
87 | }
88 |
89 | @media (max-width: 600px) {
90 | .containerFooter .details li {
91 | flex-basis: 50%;
92 | }
93 | }
94 |
--------------------------------------------------------------------------------
/src/CustomHooks/useUpdateLikedMovies.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useState } from "react";
2 | import { updateDoc, doc, arrayUnion, arrayRemove } from "firebase/firestore";
3 | import { db } from "../Firebase/FirebaseConfig";
4 | import { AuthContext } from "../Context/UserContext";
5 | import toast, { Toaster } from "react-hot-toast";
6 |
7 | function useUpdateLikedMovies() {
8 | const { User } = useContext(AuthContext);
9 | const [Error, setError] = useState(false);
10 |
11 | function notify() {
12 | toast.success(" Movie added to Liked List ");
13 | }
14 | function removeNotify() {
15 | toast.success(" Movie removed from Liked List ");
16 | }
17 | function alertError(message) {
18 | toast.error(message);
19 | }
20 |
21 | const addToLikedMovies = (movie) => {
22 | updateDoc(doc(db, "LikedMovies", User.uid), {
23 | movies: arrayUnion(movie),
24 | }).then(() => {
25 | notify();
26 | });
27 | };
28 |
29 | const removeFromLikedMovies = (movie) => {
30 | updateDoc(doc(db, "LikedMovies", User.uid), {
31 | movies: arrayRemove(movie),
32 | })
33 | .then(() => {
34 | removeNotify();
35 | })
36 | .catch((error) => {
37 | console.log(error.code);
38 | console.log(error.message);
39 | alertError(error.message);
40 | setError(true);
41 | });
42 | };
43 |
44 | const LikedMoviePopupMessage = (
45 |
54 | );
55 |
56 | return { addToLikedMovies, removeFromLikedMovies, LikedMoviePopupMessage };
57 | }
58 |
59 | export default useUpdateLikedMovies;
60 |
--------------------------------------------------------------------------------
/src/CustomHooks/useUpdateMylist.jsx:
--------------------------------------------------------------------------------
1 | import React, { useContext, useState } from "react";
2 | import { updateDoc, doc, arrayUnion, arrayRemove } from "firebase/firestore";
3 | import { db } from "../Firebase/FirebaseConfig";
4 | import { AuthContext } from "../Context/UserContext";
5 | import toast, { Toaster } from "react-hot-toast";
6 |
7 | function useUpdateMylist() {
8 | const { User } = useContext(AuthContext);
9 | const [isMyListUpdates, setisMyListUpdates] = useState(false);
10 |
11 | function notify() {
12 | toast.success(" Movie added to MyList ");
13 | }
14 | function alertError(message) {
15 | toast.error(message);
16 | }
17 |
18 | const addToMyList = (movie) => {
19 | updateDoc(doc(db, "MyList", User.uid), { movies: arrayUnion(movie) })
20 | .then(() => {
21 | console.log("Data added to my List");
22 | notify();
23 | setisMyListUpdates(true);
24 | })
25 | .catch((error) => {
26 | console.log(error.code);
27 | console.log(error.message);
28 | alertError(error.message);
29 | });
30 | };
31 |
32 | const removeFromMyList = (movie) => {
33 | updateDoc(doc(db, "MyList", User.uid), { movies: arrayRemove(movie) })
34 | .then(() => {
35 | toast.success(" Movie removed from MyList ");
36 | setisMyListUpdates(true);
37 | })
38 | .catch((error) => {
39 | console.log(error.code);
40 | console.log(error.message);
41 | });
42 | };
43 |
44 | const PopupMessage = (
45 |
54 | );
55 |
56 | return { addToMyList, removeFromMyList, PopupMessage, isMyListUpdates };
57 | }
58 |
59 | export default useUpdateMylist;
60 |
--------------------------------------------------------------------------------
/src/Constants/Constance.js:
--------------------------------------------------------------------------------
1 | export const baseUrl = "https://api.themoviedb.org/3";
2 | export const API_KEY = "ecb37597e45cfeed0586f3cd57233d0b";
3 | export const imageUrl = "https://image.tmdb.org/t/p/original";
4 | export const imageUrl2 = "https://image.tmdb.org/t/p/w500";
5 |
6 | export const genresList = [
7 | {
8 | id: 28,
9 | name: "Action",
10 | },
11 | {
12 | id: 12,
13 | name: "Adventure",
14 | },
15 | {
16 | id: 16,
17 | name: "Animation",
18 | },
19 | {
20 | id: 35,
21 | name: "Comedy",
22 | },
23 | {
24 | id: 80,
25 | name: "Crime",
26 | },
27 | {
28 | id: 99,
29 | name: "Documentary",
30 | },
31 | {
32 | id: 18,
33 | name: "Drama",
34 | },
35 | {
36 | id: 10751,
37 | name: "Family",
38 | },
39 | {
40 | id: 14,
41 | name: "Fantasy",
42 | },
43 | {
44 | id: 36,
45 | name: "History",
46 | },
47 | {
48 | id: 27,
49 | name: "Horror",
50 | },
51 | {
52 | id: 10402,
53 | name: "Music",
54 | },
55 | {
56 | id: 9648,
57 | name: "Mystery",
58 | },
59 | {
60 | id: 10749,
61 | name: "Romance",
62 | },
63 | {
64 | id: 878,
65 | name: "Science Fiction",
66 | },
67 | {
68 | id: 10770,
69 | name: "TV Movie",
70 | },
71 | {
72 | id: 53,
73 | name: "Thriller",
74 | },
75 | {
76 | id: 10752,
77 | name: "War",
78 | },
79 | {
80 | id: 37,
81 | name: "Western",
82 | },
83 | {
84 | id: 10759,
85 | name: "Action & Adventure",
86 | },
87 | {
88 | id: 10762,
89 | name: "Kids",
90 | },
91 | {
92 | id: 10763,
93 | name: "News",
94 | },
95 | {
96 | id: 10764,
97 | name: "Reality",
98 | },
99 | {
100 | id: 10765,
101 | name: "Sci-Fi & Fantasy",
102 | },
103 | {
104 | id: 10766,
105 | name: "Soap",
106 | },
107 | {
108 | id: 10767,
109 | name: "Talk",
110 | },
111 | {
112 | id: 10768,
113 | name: "War & Politics",
114 | },
115 | ];
116 |
--------------------------------------------------------------------------------
/src/Pages/Home.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useEffect, useState, useContext } from "react";
3 | import Banner from "../componets/Banner/Banner";
4 | import Footer from "../componets/Footer/Footer";
5 | import RowPost from "../componets/RowPost/RowPost";
6 | import {
7 | originals,
8 | trending,
9 | comedy,
10 | horror,
11 | Adventure,
12 | SciFi,
13 | Animated,
14 | War,
15 | trendingSeries,
16 | UpcomingMovies,
17 | } from "../Constants/URLs";
18 | import { doc, getDoc } from "firebase/firestore";
19 | import { db } from "../Firebase/FirebaseConfig";
20 | import { AuthContext } from "../Context/UserContext";
21 |
22 | function Home() {
23 | const { User } = useContext(AuthContext);
24 | const [watchedMovies, setWatchedMovies] = useState([]);
25 |
26 | useEffect(() => {
27 | getDoc(doc(db, "WatchedMovies", User.uid)).then((result) => {
28 | if (result.exists()) {
29 | const mv = result.data();
30 | setWatchedMovies(mv.movies);
31 | }
32 | });
33 | }, []);
34 |
35 | return (
36 |
37 |
38 |
39 |
40 |
41 | {watchedMovies.length != 0 ? (
42 |
47 | ) : null}
48 |
54 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 | );
69 | }
70 |
71 | export default Home;
72 |
--------------------------------------------------------------------------------
/src/App.jsx:
--------------------------------------------------------------------------------
1 | import { useEffect, useContext, lazy, Suspense } from "react";
2 | import "./App.css";
3 |
4 | const Home = lazy(() => import("./Pages/Home"));
5 | const Series = lazy(() => import("./Pages/Series"));
6 | const Search = lazy(() => import("./Pages/Search"));
7 | const Profile = lazy(() => import("./Pages/Profile"));
8 | const MyList = lazy(() => import("./Pages/MyList"));
9 | const SignIn = lazy(() => import("./Pages/SignIn"));
10 | const SignUp = lazy(() => import("./Pages/SignUp"));
11 | const Welcome = lazy(() => import("./Pages/Welcome"));
12 | const ErrorPage = lazy(() => import("./Pages/ErrorPage"));
13 | const Play = lazy(() => import("./Pages/Play"));
14 | const LikedMovies = lazy(() => import("./Pages/LikedMovies"));
15 | const History = lazy(() => import("./Pages/History"));
16 |
17 | import { Routes, Route, Navigate } from "react-router-dom";
18 | import { AuthContext } from "./Context/UserContext";
19 | import { getAuth, onAuthStateChanged } from "firebase/auth";
20 | import Loading from "./componets/Loading/Loading";
21 | import Navbar from "./componets/Header/Navbar";
22 | import NavbarWithoutUser from "./componets/Header/NavbarWithoutUser";
23 |
24 | function App() {
25 | const { User, setUser } = useContext(AuthContext);
26 | useEffect(() => {
27 | const auth = getAuth();
28 | onAuthStateChanged(auth, (user) => {
29 | setUser(user);
30 | console.log(user);
31 | });
32 | }, []);
33 |
34 | return (
35 |
36 | {User ? : }
37 | }>
38 |
39 | : } />
40 | {User ? (
41 | <>
42 | } />
43 | } />
44 | } />
45 | } />
46 | } />
47 | } />
48 | } />
49 | } />
50 | >
51 | ) : null}
52 | } />
53 |
54 | } />
55 | } />
56 | } />
57 |
58 |
59 |
60 | );
61 | }
62 |
63 | export default App;
64 |
--------------------------------------------------------------------------------
/src/componets/RowPost/RowPostStyles.scss:
--------------------------------------------------------------------------------
1 | .SwiperStyle:hover {
2 | .swiper-button-prev {
3 | opacity: 1;
4 | transition: all 400ms ease-out 0s;
5 | }
6 | .swiper-button-next {
7 | opacity: 1;
8 | transition: all 400ms ease-out 0s;
9 | }
10 |
11 | .swiper-pagination {
12 | opacity: 1;
13 | }
14 | }
15 |
16 | .swiper-button-prev {
17 | color: white;
18 | opacity: 0;
19 | transition: all 400ms ease-out 0s;
20 | }
21 | .swiper-button-next {
22 | color: white;
23 | opacity: 0;
24 | transition: all 400ms ease-out 0s;
25 | }
26 |
27 | .swiper-pagination {
28 | position: initial;
29 | display: flex;
30 | justify-content: flex-end;
31 | opacity: 0;
32 | margin-top: -0.8rem;
33 | margin-bottom: 0.8rem;
34 | }
35 | .swiper-pagination-bullet {
36 | cursor: pointer;
37 | width: 12px;
38 | height: 4px;
39 | display: inline-block;
40 | opacity: 1;
41 | background-color: hsl(0deg 0% 30%);
42 | border-radius: 0px;
43 | transition: all 0.2s ease-in-out 0s;
44 | margin: 0px 0px 0px 2px !important;
45 | }
46 | .swiper-pagination-bullet-active {
47 | background-color: white;
48 | cursor: pointer;
49 | }
50 |
51 | .swiper-wrapper {
52 | padding: 40px 0;
53 | &:hover .swiper-slide {
54 | transform: translateX(-17%);
55 | z-index: -1;
56 | }
57 | }
58 |
59 | .swiper-slide:hover ~ .swiper-slide {
60 | transform: translateX(17%);
61 | }
62 | .swiper-slide:hover {
63 | z-index: 20;
64 | transition: all 350ms ease-out 0s;
65 | cursor: pointer;
66 | // border-left: 2px solid red;
67 | }
68 | .swiper-wrapper:hover {
69 | .swiper-slide {
70 | opacity: 0.4;
71 | }
72 | }
73 | .swiper-wrapper .swiper-slide:hover {
74 | opacity: 1;
75 | }
76 |
77 | .swiper-wrapper .swiper-slide:hover {
78 | transform: scale(1.5);
79 | z-index: 5;
80 | }
81 | .swiper-slide {
82 | transition: all 350ms ease-out 0s;
83 |
84 | &:hover img {
85 | z-index: 1;
86 | }
87 | &:first-child:hover {
88 | margin: 0 75px;
89 | }
90 | &:last-child:hover {
91 | margin: 0 -75px;
92 | }
93 | }
94 | .swiper-slide:hover {
95 | transition: all 350ms ease-out 0s;
96 | }
97 |
98 | .content {
99 | transition: all 0.5;
100 | background: linear-gradient(
101 | 0.05turn,
102 | rgba(0, 0, 0, 0.871),
103 | rgba(0, 0, 0, 0.023) 65%
104 | );
105 | position: absolute;
106 | bottom: -1.25rem;
107 | left: 0;
108 | padding-bottom: 1rem;
109 | width: 100%;
110 | display: none;
111 | box-sizing: border-box;
112 | }
113 |
114 | .swiper-slide:hover {
115 | .content {
116 | transition: all 0.5s;
117 | display: initial;
118 | bottom: 0;
119 | }
120 | }
121 |
122 | .swiper-slide.large {
123 | &:hover {
124 | transform: scale(1.2) !important;
125 | }
126 |
127 | .swiper-wrapper {
128 | padding: 40px 0;
129 | &:hover .swiper-slide {
130 | transform: translateX(-12%) !important;
131 | z-index: -1;
132 | }
133 | }
134 |
135 | .swiper-slide:hover ~ .swiper-slide {
136 | transform: translateX(12%) !important;
137 | }
138 | }
139 |
140 | .YouTubeVid {
141 | iframe {
142 | height: 27rem;
143 | }
144 | }
145 |
146 | @media only screen and (max-width: 650px) {
147 | .YouTubeVid {
148 | iframe {
149 | height: 13rem;
150 | }
151 | }
152 | }
153 |
154 | @media only screen and (max-width: 1050px) {
155 | .swiper-wrapper {
156 | padding: 0;
157 | &:hover.swiper-slide {
158 | transform: translateX(0);
159 | }
160 | }
161 | .swiper-wrapper:hover .swiper-slide {
162 | transform: translateX(0%);
163 | }
164 | .swiper-slide:hover ~ .swiper-slide {
165 | transform: translateX(0);
166 | }
167 | .swiper-wrapper .swiper-slide:hover {
168 | transform: scale(1.03);
169 | }
170 | .swiper-slide.large {
171 | &:hover {
172 | transform: scale(1.03) !important;
173 | }
174 | }
175 |
176 | .swiper-slide {
177 | transition: all 350ms ease-out 0s;
178 |
179 | &:hover img {
180 | z-index: 1;
181 | }
182 | &:first-child:hover {
183 | margin: 0;
184 | }
185 | &:last-child:hover {
186 | margin: 0;
187 | }
188 | }
189 |
190 | .swiper-slide:hover {
191 | .content {
192 | transition: all 0.5s;
193 | display: initial;
194 | bottom: -10.25rem;
195 | }
196 | }
197 | }
198 |
199 | .ytp-title-expanded-heading {
200 | display: none;
201 | }
202 |
--------------------------------------------------------------------------------
/src/Pages/Welcome.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useEffect } from "react";
3 |
4 | import Footer from "../componets/Footer/Footer";
5 |
6 | import WelcomePageImage1 from "../images/WelcomePageImage1.png";
7 | import WelcomePageImage2 from "../images/WelcomePageImage2.png";
8 | import WelcomePageImage3 from "../images/WelcomePageImage3.png";
9 | import WelcomePageImage4 from "../images/WelcomePageImage4.png";
10 | import WelcomePageBanner from "../images/WelcomePageBanner.jpg";
11 |
12 | import { Fade } from "react-reveal";
13 | import { Link } from "react-router-dom";
14 |
15 | function Welcome() {
16 | useEffect(() => {
17 | //alert("This is NOT REAL NETFLIX so don't Enter your REAL CREDENTIALS")
18 | const image1 = WelcomePageImage1;
19 | }, []);
20 |
21 | return (
22 |
23 | {/*Hero Section*/}
24 |
30 |
31 |
32 |
33 |
34 | Unlimited movies, TV shows and more.
35 |
36 |
37 | Watch anywahere.Cancel anytime
38 |
39 |
40 | Ready to watch? Enter your email to create or restart your
41 | membership.
42 |
43 |
44 |
48 |
49 |
52 |
53 |
54 |
55 |
56 |
57 |
63 |
64 |
65 | {/* Section 2 */}
66 |
67 |
68 |
69 |
70 |
71 |
72 | Enjoy on your TV.
73 |
74 |
75 | Watch on smart TVs, PlayStation, Xbox, Chromecast, Apple TV,
76 | Blu-ray players and more.
77 |
78 |
79 |
80 |

81 |
82 |
83 |
84 |
85 |
86 |
87 | {/* Section 3 */}
88 |
89 |
90 |
91 |
92 |
93 |

94 |
95 |
96 |
97 | Download your shows to watch offline.
98 |
99 |
100 | Save your favourites easily and always have something to
101 | watch.
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 | {/* Section 4 */}
110 |
111 |
112 |
113 |
114 |
115 |
116 | Watch everywhere.
117 |
118 |
119 | Stream unlimited movies and TV shows on your phone, tablet,
120 | laptop, and TV.
121 |
122 |
123 |
124 |

125 |
126 |
127 |
128 |
129 |
130 |
131 | {/* Section 5 */}
132 |
133 |
134 |
135 |
136 |
137 |

138 |
139 |
140 |
141 | Create profiles for children.
142 |
143 |
144 | Send children on adventures with their favourite characters in
145 | a space made just for them—free with your membership.
146 |
147 |
148 |
149 |
150 |
151 |
152 |
153 | {/* Section 6 */}
154 |
155 |
156 | {/* Footer */}
157 |
158 |
159 | );
160 | }
161 |
162 | export default Welcome;
163 |
--------------------------------------------------------------------------------
/src/Pages/SignUp.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useState, useContext } from "react";
3 |
4 | import { Link, useNavigate } from "react-router-dom";
5 | import { Fade } from "react-reveal";
6 | import {
7 | getAuth,
8 | createUserWithEmailAndPassword,
9 | onAuthStateChanged,
10 | } from "firebase/auth";
11 | import { setDoc, doc } from "firebase/firestore";
12 | import { db } from "../Firebase/FirebaseConfig";
13 | import { AuthContext } from "../Context/UserContext";
14 | import { ClipLoader } from "react-spinners";
15 | import WelcomePageBanner from "../images/WelcomePageBanner.jpg";
16 |
17 | function SignUp() {
18 | const { User, setUser } = useContext(AuthContext);
19 |
20 | const [email, setEmail] = useState("");
21 | const [password, setPassword] = useState("");
22 | const [ErrorMessage, setErrorMessage] = useState("");
23 | const [loader, setLoader] = useState(false);
24 |
25 | const navigate = useNavigate();
26 |
27 | const handleSubmit = (e) => {
28 | e.preventDefault();
29 | setLoader(true);
30 |
31 | const auth = getAuth();
32 | createUserWithEmailAndPassword(auth, email, password)
33 | .then((userCredential) => {
34 | // Signed in
35 | onAuthStateChanged(auth, (user) => {
36 | const EmptyArray = [];
37 | setDoc(doc(db, "Users", user.uid), {
38 | email: email,
39 | Uid: user.uid,
40 | }).then(() => {
41 | setDoc(
42 | doc(db, "MyList", user.uid),
43 | {
44 | movies: EmptyArray,
45 | },
46 | { merge: true }
47 | ).then(() => {
48 | setDoc(
49 | doc(db, "WatchedMovies", user.uid),
50 | {
51 | movies: EmptyArray,
52 | },
53 | { merge: true }
54 | );
55 | setDoc(
56 | doc(db, "LikedMovies", user.uid),
57 | {
58 | movies: EmptyArray,
59 | },
60 | { merge: true }
61 | );
62 | });
63 | });
64 | });
65 |
66 | const user = userCredential.user;
67 | if (user != null) {
68 | navigate("/");
69 | }
70 | })
71 | .catch((error) => {
72 | const errorCode = error.code;
73 | const errorMessage = error.message;
74 | setLoader(false);
75 | setErrorMessage(errorMessage);
76 | console.log(errorCode);
77 | console.log(errorMessage);
78 | });
79 | };
80 |
81 | return (
82 |
88 |
89 |
90 |
91 |
92 |
93 |
94 | Create a new account
95 |
96 |
97 | Not Real Netflix
98 |
99 |
206 |
207 |
208 |
209 |
210 |
211 |
212 | );
213 | }
214 |
215 | export default SignUp;
216 |
--------------------------------------------------------------------------------
/src/componets/Banner/Banner.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useContext } from "react";
2 | import { API_KEY, imageUrl } from "../../Constants/Constance";
3 | import axios from "../../axios";
4 | import { PopUpContext } from "../../Context/moviePopUpContext";
5 | import { Fade } from "react-reveal";
6 | import StarRatings from "react-star-ratings";
7 | import MoviePopUp from "../PopUp/MoviePopUp";
8 | import usePlayMovie from "../../CustomHooks/usePlayMovie";
9 |
10 | function Banner(props) {
11 | const { showModal, setShowModal } = useContext(PopUpContext);
12 | const { playMovie } = usePlayMovie();
13 |
14 | const [movie, setMovie] = useState([]);
15 | const [moviePopupInfo, setMoviePopupInfo] = useState({});
16 | const [urlId, setUrlId] = useState("");
17 |
18 | function getWindowSize() {
19 | const {innerWidth:width } = window;
20 | return {
21 | width
22 | }
23 | }
24 |
25 | const [windowSeize, setWindowSeize] = useState(getWindowSize())
26 |
27 |
28 | useEffect(() => {
29 | axios.get(props.url).then((response) => {
30 | setMovie(
31 | response.data.results.sort(function (a, b) {
32 | return 0.5 - Math.random();
33 | })[0]
34 | );
35 | console.log(movie);
36 | });
37 |
38 | function handleWindowResize() {
39 | setWindowSeize(getWindowSize())
40 | }
41 |
42 | window.addEventListener('resize', handleWindowResize)
43 |
44 | }, []);
45 |
46 | const handleMoviePopup = (movieInfo) => {
47 | setMoviePopupInfo(movieInfo);
48 | setShowModal(true);
49 |
50 | axios
51 | .get(`/movie/${movieInfo.id}/videos?api_key=${API_KEY}&language=en-US`)
52 | .then((responce) => {
53 | console.log(responce.data);
54 | if (responce.data.results.length !== 0) {
55 | setUrlId(responce.data.results[0]);
56 | } else {
57 | console.log("Array Emptey");
58 | }
59 | });
60 | };
61 |
62 | return (
63 | <>
64 |
74 |
75 |
76 | {movie.title || movie.name ? (
77 | <>
78 |
79 | {movie.title || movie.name}
80 |
81 | >
82 | ) : (
83 |
86 | )}
87 |
88 |
89 |
90 |
91 | {movie.vote_average ? (
92 |
93 |
94 |
102 |
103 |
104 | ) : null}
105 |
106 |
107 | {movie.release_date || movie.first_air_date ? (
108 |
109 | {movie.release_date || movie.first_air_date}
110 |
111 | ) : null}
112 |
113 | {movie.id && (
114 |
115 | HD
116 |
117 | )}
118 |
119 |
120 |
121 | {movie.overview ? (
122 | <>
123 |
124 | {movie.overview}
125 |
126 | >
127 | ) : (
128 | <>
129 |
134 | >
135 | )}
136 |
137 |
138 |
139 | {movie.id ? (
140 | <>
141 |
161 |
181 | >
182 | ) : (
183 | <>
184 |
206 |
223 | >
224 | )}
225 |
226 |
227 |
228 |
235 |
236 |
237 | {showModal ? : null}
238 | >
239 | );
240 | }
241 |
242 | export default Banner;
243 |
--------------------------------------------------------------------------------
/src/Pages/Search.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useState, useContext } from "react";
3 | import { API_KEY, imageUrl2 } from "../Constants/Constance";
4 | import { PopUpContext } from "../Context/moviePopUpContext";
5 | import useUpdateMylist from "../CustomHooks/useUpdateMylist";
6 | import axios from "../axios";
7 | import MoviePopUp from "../componets/PopUp/MoviePopUp";
8 | import usePlayMovie from "../CustomHooks/usePlayMovie";
9 | import useUpdateLikedMovies from "../CustomHooks/useUpdateLikedMovies";
10 | import useGenereConverter from "../CustomHooks/useGenereConverter";
11 | import StarRatings from "react-star-ratings";
12 |
13 | function Search() {
14 | const { showModal, setShowModal } = useContext(PopUpContext);
15 | const { addToMyList, PopupMessage } = useUpdateMylist();
16 | const { playMovie } = usePlayMovie();
17 | const { addToLikedMovies } = useUpdateLikedMovies();
18 | const { convertGenere } = useGenereConverter();
19 |
20 | const [searchQuery, setSearchQuery] = useState("");
21 | const [movies, setMovies] = useState([]);
22 | const [moviePopupInfo, setMoviePopupInfo] = useState({});
23 |
24 | const Search = (e) => {
25 | setSearchQuery(e.target.value);
26 | e.preventDefault();
27 | console.log(searchQuery);
28 |
29 | axios
30 | .get(
31 | `/search/movie?api_key=${API_KEY}&language=en-US&query=${searchQuery}&page=1&include_adult=false`
32 | )
33 | .then((response) => {
34 | console.log(response.data.results);
35 | setMovies(response.data.results);
36 | });
37 |
38 | if (searchQuery === "") {
39 | setMovies([]);
40 | }
41 | };
42 |
43 | const handleMoviePopup = (movieInfo) => {
44 | setMoviePopupInfo(movieInfo);
45 | setShowModal(true);
46 | };
47 |
48 | return (
49 |
50 | {PopupMessage}
51 |
52 |
53 |
60 |
80 |
81 |
82 | {/* Search results */}
83 |
84 | {movies.length !== 0 ? (
85 | movies.map((movie) => {
86 | const converted = convertGenere(movie.genre_ids);
87 | return (
88 |
89 |
90 |
94 |
handleMoviePopup(movie)}
96 | className=""
97 | src={
98 | movie.backdrop_path
99 | ? imageUrl2 + movie.backdrop_path
100 | : "https://i.ytimg.com/vi/Mwf--eGs05U/maxresdefault.jpg"
101 | }
102 | />
103 |
104 |
111 |
112 | {/* Play Button */}
113 |
playMovie(movie)}
115 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
116 | >
117 |
130 |
131 |
132 | {/* Like Button */}
133 |
addToLikedMovies(movie)}
135 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
136 | >
137 |
150 |
151 |
152 | {/* Add to MyList Button */}
153 |
addToMyList(movie)}
155 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
156 | >
157 |
170 |
171 |
172 | {/* PopUp Button */}
173 |
handleMoviePopup(movie)}
175 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
176 | >
177 |
191 |
192 |
193 |
194 |
195 | {movie.name || movie.title}
196 |
197 |
198 |
199 |
206 |
207 |
208 | {converted &&
209 | converted.map((genre) => {
210 | return (
211 |
212 | {genre}
213 |
214 | );
215 | })}
216 |
217 |
218 |
219 |
220 | );
221 | })
222 | ) : (
223 | <>
224 |
228 | >
229 | )}
230 |
231 |
232 | {showModal ?
: null}
233 |
234 | );
235 | }
236 |
237 | export default Search;
238 |
--------------------------------------------------------------------------------
/src/Pages/SignIn.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useState, useContext } from "react";
3 | import { Link, useNavigate } from "react-router-dom";
4 | import { Fade } from "react-reveal";
5 | import { ClipLoader } from "react-spinners";
6 | import {
7 | getAuth,
8 | signInWithEmailAndPassword,
9 | GoogleAuthProvider,
10 | signInWithPopup,
11 | } from "firebase/auth";
12 | import { setDoc, doc, getDoc } from "firebase/firestore";
13 | import { db } from "../Firebase/FirebaseConfig";
14 | import { AuthContext } from "../Context/UserContext";
15 |
16 | import GoogleLogo from "../images/GoogleLogo.png";
17 | import WelcomePageBanner from "../images/WelcomePageBanner.jpg";
18 |
19 | function SignIn() {
20 | const { User, setUser } = useContext(AuthContext);
21 | const navigate = useNavigate();
22 |
23 | const [email, setEmail] = useState("");
24 | const [password, setPassword] = useState("");
25 | const [ErrorMessage, setErrorMessage] = useState("");
26 | const [loader, setLoader] = useState(false);
27 |
28 | const handleSubmit = (e) => {
29 | e.preventDefault();
30 | setLoader(true);
31 |
32 | const auth = getAuth();
33 | signInWithEmailAndPassword(auth, email, password)
34 | .then((userCredential) => {
35 | // Signed in
36 | const user = userCredential.user;
37 | console.log(user);
38 | if (user != null) {
39 | navigate("/");
40 | }
41 | })
42 | .catch((error) => {
43 | const errorCode = error.code;
44 | const errorMessage = error.message;
45 | setErrorMessage(error.message);
46 | setLoader(false);
47 | console.log(errorCode);
48 | console.log(errorMessage);
49 | });
50 | };
51 |
52 | const loginWithGoogle = (e) => {
53 | e.preventDefault();
54 | const auth = getAuth();
55 | const provider = new GoogleAuthProvider();
56 |
57 | signInWithPopup(auth, provider)
58 | .then((result) => {
59 | const user = result.user;
60 | console.log(user);
61 | const EmptyArray = [];
62 |
63 | setDoc(
64 | doc(db, "Users", user.uid),
65 | {
66 | email: user.email,
67 | Uid: user.uid,
68 | },
69 | { merge: true }
70 | ).then(() => {
71 | getDoc(doc(db, "MyList", user.uid)).then((result) => {
72 | if (result.exists()) {
73 | // Data exist in MyList section for this user
74 | } else {
75 | // Creating a new MyList, WatchedMovies List, LikedMovies List for the user in the database
76 | setDoc(
77 | doc(db, "MyList", user.uid),
78 | {
79 | movies: EmptyArray,
80 | },
81 | { merge: true }
82 | );
83 | setDoc(
84 | doc(db, "WatchedMovies", user.uid),
85 | {
86 | movies: EmptyArray,
87 | },
88 | { merge: true }
89 | );
90 | setDoc(
91 | doc(db, "LikedMovies", user.uid),
92 | {
93 | movies: EmptyArray,
94 | },
95 | { merge: true }
96 | ).then(() => {
97 | navigate("/");
98 | });
99 | }
100 | });
101 | });
102 | if (user != null) {
103 | navigate("/");
104 | }
105 | })
106 | .catch((error) => {
107 | const errorCode = error.code;
108 | const errorMessage = error.message;
109 | setErrorMessage(error.message);
110 | setLoader(false);
111 | // The email of the user's account used.
112 | const email = error.customData.email;
113 | // The AuthCredential type that was used.
114 | const credential = GoogleAuthProvider.credentialFromError(error);
115 | });
116 | };
117 |
118 | return (
119 |
125 |
126 |
127 |
128 |
129 |
130 |
131 | Sign in to your account
132 |
133 |
134 | Not Real Netflix
135 |
136 |
262 |
263 |
264 |
265 |
266 |
267 |
268 | );
269 | }
270 |
271 | export default SignIn;
272 |
--------------------------------------------------------------------------------
/src/componets/Header/Navbar.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useContext } from "react";
2 |
3 | import { Transition } from "@headlessui/react";
4 | import { Fade } from "react-reveal";
5 | import { Link, useNavigate } from "react-router-dom";
6 | import { getAuth, signOut } from "firebase/auth";
7 | import { AuthContext } from "../../Context/UserContext";
8 |
9 | function Navbar(props) {
10 | const { User } = useContext(AuthContext);
11 | const [profilePic, setProfilePic] = useState("");
12 |
13 | const navigate = useNavigate();
14 |
15 | useEffect(() => {
16 | if (User != null) {
17 | setProfilePic(User.photoURL);
18 | }
19 | window.addEventListener("scroll", transitionNavBar);
20 | console.log("Navbar", User);
21 | return () => {
22 | window.removeEventListener("scroll", transitionNavBar);
23 | };
24 | }, []);
25 | const [isOpen, setIsOpen] = useState(false);
26 |
27 | const [show, handleShow] = useState(false);
28 | const transitionNavBar = () => {
29 | if (window.scrollY > 80) {
30 | handleShow(true);
31 | } else {
32 | handleShow(false);
33 | }
34 | };
35 |
36 | const NavBlack = () => {
37 | handleShow(true);
38 | };
39 | const NavTransparent = () => {
40 | handleShow(false);
41 | };
42 |
43 | const SignOut = () => {
44 | const auth = getAuth();
45 | signOut(auth)
46 | .then(() => {
47 | navigate("/");
48 | })
49 | .catch((error) => {
50 | alert(error.message);
51 | });
52 | };
53 |
54 | return (
55 |
56 |
63 |
310 |
311 |
312 | );
313 | }
314 |
315 | export default Navbar;
316 |
--------------------------------------------------------------------------------
/src/Pages/Profile.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useContext, useEffect, useRef } from "react";
2 | import { getAuth, updateProfile, signOut } from "firebase/auth";
3 | import { db } from "../Firebase/FirebaseConfig";
4 | import {
5 | ref,
6 | uploadBytesResumable,
7 | getDownloadURL,
8 | getStorage,
9 | } from "firebase/storage";
10 | import { useNavigate } from "react-router-dom";
11 | import { Fade } from "react-reveal";
12 | import toast, { Toaster } from "react-hot-toast";
13 |
14 | import { AuthContext } from "../Context/UserContext";
15 | import WelcomePageBanner from "../images/WelcomePageBanner.jpg";
16 |
17 | import "swiper/css";
18 | import "swiper/css/navigation";
19 | import "swiper/css/pagination";
20 |
21 | function Profile() {
22 | const { User } = useContext(AuthContext);
23 |
24 | const [profilePic, setProfilePic] = useState("");
25 | const [newProfielPicURL, setNewProfielPicURL] = useState("");
26 | const [newProfielPic, setNewProfielPic] = useState("");
27 | const [isUserNameChanged, setIsUserNameChanged] = useState(false);
28 | const [userName, setUserName] = useState("");
29 | const [isMyListUpdated, setisMyListUpdated] = useState(false);
30 |
31 | const navigate = useNavigate();
32 |
33 | useEffect(() => {
34 | if (User != null) {
35 | console.log(User.photoURL, "hello");
36 | setProfilePic(User.photoURL);
37 | }
38 | }, []);
39 |
40 | const inputRef = useRef(null);
41 |
42 | const handleClick = () => {
43 | inputRef.current.click();
44 | };
45 |
46 | function notify() {
47 | toast.success(" Data Updated Sucessfuly ");
48 | }
49 |
50 | const handleFileChange = (event) => {
51 | const fileObj = event.target.files[0];
52 | setNewProfielPic(fileObj);
53 | setNewProfielPicURL(URL.createObjectURL(fileObj));
54 | if (!fileObj) {
55 | return;
56 | }
57 | console.log("fileObj is", fileObj);
58 | event.target.value = null;
59 | };
60 |
61 | const changeUserName = (e) => {
62 | e.preventDefault();
63 | if (isUserNameChanged) {
64 | if (userName !== "") {
65 | const auth = getAuth();
66 | updateProfile(auth.currentUser, { displayName: userName })
67 | .then(() => {
68 | notify();
69 | })
70 | .catch((error) => {
71 | alert(error.message);
72 | });
73 | } else {
74 | setIsUserNameChanged(false);
75 | }
76 | }
77 |
78 | if (newProfielPic != "") {
79 | const storage = getStorage();
80 | const storageRef = ref(storage, `/ProfilePics/${User.uid}`);
81 | const uploadTask = uploadBytesResumable(storageRef, newProfielPic);
82 |
83 | uploadTask.on(
84 | "state_changed",
85 | (snapshot) => {
86 | const prog = Math.round(
87 | (snapshot.bytesTransferred / snapshot.totalBytes) * 100
88 | );
89 | },
90 | (error) => {
91 | alert(error.message);
92 | alert(error.code);
93 | },
94 | () => {
95 | getDownloadURL(uploadTask.snapshot.ref).then((url) => {
96 | console.log(url, "This is the new Url for Profile Pic");
97 | setProfilePic(url);
98 | const auth = getAuth();
99 | updateProfile(auth.currentUser, { photoURL: url })
100 | .then(() => {
101 | notify();
102 | setisMyListUpdated(true);
103 | })
104 | .catch((error) => {
105 | alert(error.message);
106 | });
107 | });
108 | }
109 | );
110 | }
111 | };
112 |
113 | const updateProfilePic = (imageURL) => {
114 | const auth = getAuth();
115 | updateProfile(auth.currentUser, { photoURL: imageURL })
116 | .then(() => {
117 | setProfilePic(User.photoURL);
118 | notify();
119 | })
120 | .catch((error) => {
121 | alert(error.message);
122 | });
123 | };
124 |
125 | const SignOut = () => {
126 | const auth = getAuth();
127 | signOut(auth)
128 | .then(() => {
129 | navigate("/");
130 | })
131 | .catch((error) => {
132 | alert(error.message);
133 | });
134 | };
135 |
136 | return (
137 |
138 |
144 | {isMyListUpdated ? (
145 |
154 | ) : null}
155 |
156 |
157 |
158 | Edit your Profile
159 |
160 |
161 |

174 |
175 |
176 |
177 | User Name
178 |
179 |
182 | setUserName(e.target.value) || setIsUserNameChanged(true)
183 | }
184 | className="block w-full rounded-md bg-stone-900 text-white border-gray-300 p-2 mb-6 focus:border-indigo-500 focus:ring-indigo-500 sm:text-base"
185 | placeholder={User ? User.displayName : null}
186 | />
187 |
Email
188 |
189 | {User ? User.email : null}
190 |
191 |
192 | Unique ID : {User ? User.uid : null}
193 |
194 |
195 |
196 |
197 | Who is Watching ?
198 |
199 |
200 |
![]()
202 | updateProfilePic(
203 | "https://i.pinimg.com/originals/ba/2e/44/ba2e4464e0d7b1882cc300feceac683c.png"
204 | )
205 | }
206 | className="w-16 h-16 rounded-md cursor-pointer"
207 | src="https://i.pinimg.com/originals/ba/2e/44/ba2e4464e0d7b1882cc300feceac683c.png"
208 | />
209 |
![]()
211 | updateProfilePic(
212 | "https://i.pinimg.com/736x/db/70/dc/db70dc468af8c93749d1f587d74dcb08.jpg"
213 | )
214 | }
215 | className="w-16 h-16 rounded-md cursor-pointer"
216 | src="https://i.pinimg.com/736x/db/70/dc/db70dc468af8c93749d1f587d74dcb08.jpg"
217 | />
218 |
![]()
220 | updateProfilePic(
221 | "https://upload.wikimedia.org/wikipedia/commons/0/0b/Netflix-avatar.png"
222 | )
223 | }
224 | className="w-16 h-16 rounded-md cursor-pointer"
225 | src="https://upload.wikimedia.org/wikipedia/commons/0/0b/Netflix-avatar.png"
226 | />
227 |
![]()
229 | updateProfilePic(
230 | "https://ih0.redbubble.net/image.618363037.0853/flat,1000x1000,075,f.u2.jpg"
231 | )
232 | }
233 | className="w-16 h-16 rounded-md cursor-pointer"
234 | src="https://ih0.redbubble.net/image.618363037.0853/flat,1000x1000,075,f.u2.jpg"
235 | />
236 |
242 |
257 |
258 | {newProfielPicURL ? (
259 |

260 | ) : null}
261 |
262 |
263 |
264 |
284 | {userName != "" || newProfielPic != "" ? (
285 |
305 | ) : (
306 |
326 | )}
327 |
328 |
329 |
330 |
331 |
332 | );
333 | }
334 |
335 | export default Profile;
336 |
--------------------------------------------------------------------------------
/src/componets/UserMovieSection/UserMovieSection.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useEffect, useState, useContext } from "react";
3 | import { useNavigate } from "react-router-dom";
4 | import MoviePopUp from "../PopUp/MoviePopUp";
5 | import { imageUrl2, API_KEY } from "../../Constants/Constance";
6 | import useUpdateMylist from "../../CustomHooks/useUpdateMylist";
7 | import usePlayMovie from "../../CustomHooks/usePlayMovie";
8 | import useUpdateWatchedMovies from "../../CustomHooks/useUpdateWatchedMovies";
9 | import useUpdateLikedMovies from "../../CustomHooks/useUpdateLikedMovies";
10 | import useGenereConverter from "../../CustomHooks/useGenereConverter";
11 | import { db } from "../../Firebase/FirebaseConfig";
12 | import { doc, getDoc } from "firebase/firestore";
13 | import { AuthContext } from "../../Context/UserContext";
14 | import { PopUpContext } from "../../Context/moviePopUpContext";
15 | import axios from "../../axios";
16 | import StarRatings from "react-star-ratings";
17 | import { ClipLoader } from "react-spinners";
18 |
19 | function UserMovieSection(props) {
20 | const { User } = useContext(AuthContext);
21 | const { showModal, setShowModal } = useContext(PopUpContext);
22 |
23 | const { addToMyList, removeFromMyList, PopupMessage } = useUpdateMylist();
24 | const { removeFromWatchedMovies, removePopupMessage } =
25 | useUpdateWatchedMovies();
26 | const { addToLikedMovies, removeFromLikedMovies, LikedMoviePopupMessage } =
27 | useUpdateLikedMovies();
28 | const { playMovie } = usePlayMovie();
29 | const { convertGenere } = useGenereConverter();
30 |
31 | const [myMovies, setMyMovies] = useState([]);
32 | const [moviePopupInfo, setMoviePopupInfo] = useState({});
33 | const [title, setTitle] = useState("");
34 | const [isResultEmpty, setIsResultEmpty] = useState(false);
35 |
36 | const navigate = useNavigate();
37 |
38 | function getMovies() {
39 | getDoc(doc(db, props.from, User.uid)).then((result) => {
40 | const mv = result.data();
41 | setMyMovies(mv.movies);
42 | if (mv.movies.length == 0) {
43 | setIsResultEmpty(true);
44 | }
45 | });
46 | }
47 |
48 | useEffect(() => {
49 | getMovies();
50 | if (props.from === "MyList") {
51 | setTitle("Movies in My List");
52 | } else if (props.from === "WatchedMovies") {
53 | setTitle("Watched Movies");
54 | } else if (props.from === "LikedMovies") {
55 | setTitle("Movies you Liked");
56 | }
57 | }, []);
58 |
59 | const removeMovie = (movie) => {
60 | if (props.from === "MyList") {
61 | removeFromMyList(movie);
62 | } else if (props.from === "WatchedMovies") {
63 | removeFromWatchedMovies(movie);
64 | } else if (props.from === "LikedMovies") {
65 | removeFromLikedMovies(movie);
66 | }
67 | getMovies();
68 | };
69 |
70 | const handleMoviePopup = (movieInfo) => {
71 | setMoviePopupInfo(movieInfo);
72 | setShowModal(true);
73 | };
74 |
75 | return (
76 |
77 | {PopupMessage}
78 |
79 |
80 |
81 | {!isResultEmpty ? title : null}
82 |
83 |
84 |
85 |
86 | {myMovies.length !== 0 ? (
87 | myMovies
88 | .slice(0)
89 | .reverse()
90 | .map((movie) => {
91 | let converted
92 | if (movie.genre_ids) {
93 | converted = convertGenere(movie.genre_ids);
94 | }
95 | return (
96 |
97 |
handleMoviePopup(movie)}
100 | >
101 |
102 |
![]()
handleMoviePopup(movie)}
104 | className=""
105 | src={imageUrl2 + movie.backdrop_path}
106 | />
107 |
108 |
115 |
116 | {/* Play Button */}
117 |
playMovie(movie, props.from)}
119 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
120 | >
121 |
134 |
135 |
136 | {/* Like or Dislike Button */}
137 | {props.from === "LikedMovies" ? (
138 | <>
139 |
removeMovie(movie)}
141 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
142 | >
143 |
156 |
157 | >
158 | ) : (
159 | <>
160 |
addToLikedMovies(movie)}
162 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
163 | >
164 |
177 |
178 | >
179 | )}
180 |
181 | {/* Add to MyList or remove from MyList Button */}
182 | {props.from === "MyList" ||
183 | props.from === "WatchedMovies" ? (
184 | <>
185 |
removeMovie(movie)}
187 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
188 | >
189 |
202 |
203 | >
204 | ) : (
205 | <>
206 |
addToMyList(movie)}
208 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
209 | >
210 |
223 |
224 | >
225 | )}
226 |
227 | {/* PopUp Button */}
228 |
handleMoviePopup(movie)}
230 | className="text-white w-10 h-10 2xl:w-14 2xl:h-14 border-[2px] 2xl:border-[3px] rounded-full p-2 mr-2 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:border-red-600 hover:text-red-600"
231 | >
232 |
246 |
247 |
248 |
249 |
250 | {movie.name || movie.title}
251 |
252 |
253 |
254 |
261 |
262 |
263 | {converted &&
264 | converted.map((genre) => {
265 | return (
266 |
267 | {genre}
268 |
269 | );
270 | })}
271 |
272 |
273 |
274 |
275 | );
276 | })
277 | ) : (
278 | <>
279 |
280 |
281 | {!isResultEmpty ? (
282 |
283 | ) : (
284 |
285 |
286 | No Movies Present
287 |
288 |
289 |
311 |
312 | )}
313 |
314 |
315 | >
316 | )}
317 |
318 | {showModal ? (
319 |
320 | ) : null}
321 |
322 | );
323 | }
324 |
325 | export default UserMovieSection;
326 |
--------------------------------------------------------------------------------
/src/componets/PopUp/MoviePopUp.jsx:
--------------------------------------------------------------------------------
1 | import React, { useState, useEffect, useContext } from "react";
2 | import { Fade } from "react-reveal";
3 | import StarRatings from "react-star-ratings";
4 | import { imageUrl } from "../../Constants/Constance";
5 | import { PopUpContext } from "../../Context/moviePopUpContext";
6 | import useUpdateMylist from "../../CustomHooks/useUpdateMylist";
7 | import usePlayMovie from "../../CustomHooks/usePlayMovie";
8 | import useGenereConverter from "../../CustomHooks/useGenereConverter";
9 | import useUpdateLikedMovies from "../../CustomHooks/useUpdateLikedMovies";
10 | import useUpdateWatchedMovies from "../../CustomHooks/useUpdateWatchedMovies";
11 |
12 | function MoviePopUp(props) {
13 | const { showModal, setShowModal } = useContext(PopUpContext);
14 | const { addToMyList, removeFromMyList, PopupMessage } = useUpdateMylist();
15 | const { addToLikedMovies, removeFromLikedMovies, LikedMoviePopupMessage } = useUpdateLikedMovies();
16 | const { removeFromWatchedMovies, removePopupMessage } =
17 | useUpdateWatchedMovies();
18 | const { playMovie } = usePlayMovie();
19 | const { convertGenere } = useGenereConverter();
20 |
21 | const [PopupInfo, setPopupInfo] = useState({});
22 |
23 | useEffect(() => {
24 | setPopupInfo(props.data1);
25 | }, []);
26 |
27 | return (
28 | <>
29 | {PopupMessage}
30 | {showModal && (
31 | <>
32 |
33 |
34 | {/*content*/}
35 |
36 |
37 | {/*header*/}
38 |
57 | {/*Movie Trailer or Image*/}
58 | {PopupInfo.backdrop_path ? (
59 |

60 | ) : null}
61 |
62 |
63 |
85 | {props.from === "LikedMovies" ? (
86 |
removeFromLikedMovies(PopupInfo)}
88 | className="text-white w-10 h-10 border-[2px] rounded-full p-2 mr-1 backdrop-blur-[1px] hover:bg-white hover:text-black shadow-md cursor-pointer ease-linear transition-all duration-150"
89 | >
90 |
103 |
104 | ) : (
105 |
addToLikedMovies(PopupInfo)}
107 | className="text-white w-10 h-10 border-[2px] rounded-full p-2 mr-1 backdrop-blur-[1px] hover:bg-white hover:text-black shadow-md cursor-pointer ease-linear transition-all duration-150"
108 | >
109 |
122 |
123 | )}
124 |
125 |
126 |
127 |
128 |
129 | {PopupInfo.title || PopupInfo.name}
130 |
131 |
132 | {PopupInfo.release_date}
133 |
134 |
135 |
136 | {/*body*/}
137 |
138 |
139 |
140 |
141 | {PopupInfo.overview}
142 |
143 |
144 |
145 |
146 | {/*footer*/}
147 |
148 | {/*More Info*/}
149 |
150 |
151 |
152 | Rating :
153 |
154 | {PopupInfo.vote_average && (
155 |
163 | )}
164 |
165 |
166 |
167 | Released on :{" "}
168 |
169 | {PopupInfo.release_date || PopupInfo.first_air_date}
170 |
171 |
172 |
173 | Language :
174 |
175 | {PopupInfo.original_language}
176 |
177 |
178 |
179 |
180 | Genere :
181 | {PopupInfo.genre_ids &&
182 | convertGenere(PopupInfo.genre_ids).map((genere) => {
183 | return (
184 |
185 | {genere}
186 |
187 | );
188 | })}
189 |
190 |
191 |
192 |
193 |
194 | {props.from === "MyList" ? (
195 |
216 | ) : (
217 | <>
218 | {props.from === "WatchedMovies" ? (
219 |
240 | ) : (
241 |
262 | )}
263 | >
264 | )}
265 |
266 |
287 |
288 |
289 |
290 |
291 |
292 |
293 |
294 | >
295 | )}
296 | >
297 | );
298 | }
299 |
300 | export default MoviePopUp;
301 |
--------------------------------------------------------------------------------
/src/Pages/Play.jsx:
--------------------------------------------------------------------------------
1 | import React, { useEffect, useState } from "react";
2 | import { useParams, useNavigate, useLocation } from "react-router-dom";
3 | import StarRatings from "react-star-ratings";
4 | import axios from "../axios";
5 | import { API_KEY, imageUrl, imageUrl2 } from "../Constants/Constance";
6 |
7 | import Navbar from "../componets/Header/Navbar";
8 | import Footer from "../componets/Footer/Footer";
9 | import useUpdateMylist from "../CustomHooks/useUpdateMylist";
10 | import useUpdateLikedMovies from "../CustomHooks/useUpdateLikedMovies";
11 |
12 | import "swiper/css";
13 | import "swiper/css/navigation";
14 | import "swiper/css/pagination";
15 | import usePlayMovie from "../CustomHooks/usePlayMovie";
16 | import useUpdateWatchedMovies from "../CustomHooks/useUpdateWatchedMovies";
17 |
18 | function Play() {
19 | const [urlId, setUrlId] = useState("");
20 | const [movieDetails, setMovieDetails] = useState({});
21 | const [isFromMyList, setIsFromMyList] = useState(false);
22 | const [isFromLikedMovies, setIsFromLikedMovies] = useState(false);
23 | const [isFromWatchedMovies, setIsFromWatchedMovies] = useState(false);
24 | const [moreTrailerVideos, setMoreTrailerVideos] = useState([]);
25 | const [similarMovies, setSimilarMovies] = useState([]);
26 |
27 | const { addToMyList, removeFromMyList, PopupMessage } = useUpdateMylist();
28 | const { addToLikedMovies, removeFromLikedMovies, LikedMoviePopupMessage } =
29 | useUpdateLikedMovies();
30 | const { removeFromWatchedMovies, removePopupMessage } =
31 | useUpdateWatchedMovies();
32 | const { playMovie } = usePlayMovie();
33 |
34 | const { id } = useParams();
35 | const navigate = useNavigate();
36 | const location = useLocation();
37 |
38 | useEffect(() => {
39 | if (location.state.From === "MyList") {
40 | setIsFromMyList(true);
41 | }
42 | if (location.state.From === "LikedMovies") {
43 | setIsFromLikedMovies(true);
44 | }
45 | if (location.state.From === "WatchedMovies") {
46 | setIsFromWatchedMovies(true);
47 | }
48 |
49 | axios
50 | .get(`/movie/${id}/videos?api_key=${API_KEY}&language=en-US`)
51 | .then((responce) => {
52 | console.log(responce.data, "This is the data");
53 | if (responce.data.results.length !== 0) {
54 | setUrlId(responce.data.results[0]);
55 | setMoreTrailerVideos(responce.data.results);
56 | } else {
57 | console.log("Array Emptey");
58 | }
59 | });
60 |
61 | if (urlId === "") {
62 | axios
63 | .get(`/tv/${id}/videos?api_key=${API_KEY}&language=en-US`)
64 | .then((responce) => {
65 | if (responce.data.results.length !== 0) {
66 | console.log(responce.data.results[0], "This is using find ");
67 | setUrlId(responce.data.results[0]);
68 | setMoreTrailerVideos(responce.data.results);
69 | console.log(moreTrailerVideos);
70 | } else {
71 | console.log("Array Emptey");
72 | }
73 | });
74 | }
75 | axios
76 | .get(`/movie/${id}?api_key=${API_KEY}&language=en-US`)
77 | .then((responce) => {
78 | console.log(responce.data, "Movie deatils");
79 | setMovieDetails(responce.data);
80 | console.log(responce.data.genres[0]);
81 |
82 | axios
83 | .get(
84 | `movie/${id}/recommendations?api_key=${API_KEY}&language=en-US&page=1`
85 | )
86 | .then((res) => {
87 | console.log(
88 | res.data.results.slice(0, 8),
89 | "ksdjfk ahdsfjksadhfjsdahf"
90 | );
91 | setSimilarMovies(res.data.results.slice(0, 8));
92 | });
93 | });
94 | }, []);
95 |
96 | return (
97 |
98 |
99 |
100 | {PopupMessage}
101 |
102 |
103 | {urlId ? (
104 |
112 | ) : (
113 |

114 | )}
115 |
116 |
117 | {movieDetails.id ? (
118 | <>
119 | {/* Movie details Section */}
120 |
128 |
129 |
130 | {movieDetails.original_title || movieDetails.title}
131 |
132 |
140 |
{movieDetails.overview}
141 |
142 |
143 |
144 |
150 |
156 |
157 | Geners :{" "}
158 | {movieDetails.genres &&
159 | movieDetails.genres.map((gener) => {
160 | return (
161 | <>
162 | {gener.name}
163 | >
164 | );
165 | })}
166 |
167 |
168 | {isFromMyList ? (
169 |
189 | ) : isFromWatchedMovies ? (
190 |
210 | ) : (
211 |
231 | )}
232 |
233 | {isFromLikedMovies ? (
234 |
253 | ) : (
254 |
273 | )}
274 |
275 |
276 |
277 |
278 |
279 |
280 |
286 |
292 |
293 | Geners :{" "}
294 | {movieDetails.genres &&
295 | movieDetails.genres.slice(0, 2).map((gener) => {
296 | return (
297 | <>
298 |
299 | {gener.name}
300 |
301 | >
302 | );
303 | })}
304 |
305 |
306 |
307 |
327 |
347 |
348 |
349 |

1024
355 | ? movieDetails.backdrop_path
356 | ? movieDetails.backdrop_path
357 | : "https://i.ytimg.com/vi/Mwf--eGs05U/maxresdefault.jpg"
358 | : movieDetails.poster_path)
359 | }`
360 | }
361 | className="w-40 rounded-sm lg:w-[45rem] ml-4 lg:ml-0"
362 | alt=

363 | />
364 |
365 |
366 |
367 | {/* Similar movies section */}
368 | {similarMovies.length !== 0 && (
369 |
370 |
371 |
372 |
373 | Similar Movies
374 |
375 |
376 | {similarMovies &&
377 | similarMovies.map((similarMovie) => {
378 | return (
379 |
380 |

{
389 | playMovie(similarMovie);
390 | window.location.reload(true);
391 | }}
392 | />
393 |
394 |
395 | {similarMovie.original_title ||
396 | similarMovie.title}
397 |
398 |
399 |
400 |
401 |
402 | {Math.floor(
403 | Math.random() * (100 - 60 + 1) + 60
404 | )}
405 | % match
406 |
407 |
408 | {similarMovie.release_date ||
409 | (similarMovie.first_air_date &&
410 | similarMovie.release_date) ||
411 | similarMovie.first_air_date}
412 |
413 |
414 |
415 | HD
416 |
417 |
418 |
419 |
434 |
435 |
436 |
437 | {similarMovie.overview}
438 |
439 |
440 |
441 | );
442 | })}
443 |
444 |
445 |
446 |
447 | )}
448 | >
449 | ) : (
450 | <>
451 |
452 |
453 |
454 |
455 |
456 |
457 |
458 | >
459 | )}
460 |
461 |
462 | );
463 | }
464 |
465 | export default Play;
466 |
--------------------------------------------------------------------------------
/src/componets/RowPost/RowPost.jsx:
--------------------------------------------------------------------------------
1 | import React from "react";
2 | import { useEffect, useState } from "react";
3 |
4 | import axios from "../../axios";
5 | import { imageUrl, imageUrl2, API_KEY } from "../../Constants/Constance";
6 | import useUpdateMylist from "../../CustomHooks/useUpdateMylist";
7 | import { Fade } from "react-reveal";
8 | import YouTube from "react-youtube";
9 | import StarRatings from "react-star-ratings";
10 |
11 | import usePlayMovie from "../../CustomHooks/usePlayMovie";
12 | import useUpdateWatchedMovies from "../../CustomHooks/useUpdateWatchedMovies";
13 | import useUpdateLikedMovies from "../../CustomHooks/useUpdateLikedMovies";
14 | import useGenereConverter from "../../CustomHooks/useGenereConverter";
15 |
16 | import { Swiper, SwiperSlide } from "swiper/react";
17 | import { Navigation, Pagination } from "swiper";
18 |
19 | import "swiper/css";
20 | import "swiper/css/navigation";
21 | import "swiper/css/pagination";
22 | import "./RowPostStyles.scss";
23 |
24 | function RowPost(props) {
25 | const { addToMyList, PopupMessage } = useUpdateMylist();
26 | const { playMovie } = usePlayMovie();
27 | const { removeFromWatchedMovies, removePopupMessage } =
28 | useUpdateWatchedMovies();
29 | const { addToLikedMovies, LikedMoviePopupMessage } = useUpdateLikedMovies();
30 | const { convertGenere } = useGenereConverter();
31 |
32 | const [movies, setMovies] = useState([]);
33 | const [showModal, setShowModal] = useState(false);
34 | const [moviePopupInfo, setMoviePopupInfo] = useState({});
35 | const [shouldPop, setshouldPop] = useState(true);
36 | const [urlId, setUrlId] = useState("");
37 |
38 | useEffect(() => {
39 | if (props.movieData != null) {
40 | setMovies(props.movieData);
41 | } else {
42 | axios.get(props.url).then((response) => {
43 | console.log(response.data.results);
44 | setMovies(response.data.results);
45 | });
46 | }
47 | }, []);
48 |
49 | const customSettings = {
50 | breakpoints: {
51 | 1800: { slidesPerView: 6.1, slidesPerGroup: 5 },
52 | 1690: { slidesPerView: 5.5, slidesPerGroup: 5 },
53 | 1536: { slidesPerView: 5, slidesPerGroup: 5 },
54 | 1280: { slidesPerView: 4.3, slidesPerGroup: 4 },
55 | 768: { slidesPerView: 3.3, slidesPerGroup: 3 },
56 | 625: { slidesPerView: 3.1, slidesPerGroup: 3 },
57 | 330: { slidesPerView: 2.1, slidesPerGroup: 2 },
58 | 0: { slidesPerView: 2, slidesPerGroup: 2 },
59 | },
60 | };
61 |
62 | const opts = {
63 | width: "100%",
64 | height: "auto",
65 | playerVars: {
66 | autoplay: 1,
67 | controls: 0,
68 | },
69 | modestbranding: 1,
70 | rel: 0,
71 | autohide: 1,
72 | showinfo: 0,
73 | };
74 |
75 | const handleMoviePopup = (movieInfo) => {
76 | if (shouldPop) {
77 | setMoviePopupInfo(movieInfo);
78 | setShowModal(true);
79 | axios
80 | .get(`/movie/${movieInfo.id}/videos?api_key=${API_KEY}&language=en-US`)
81 | .then((responce) => {
82 | console.log(responce.data);
83 | if (responce.data.results.length !== 0) {
84 | setUrlId(responce.data.results[0]);
85 | } else {
86 | console.log("Array Emptey");
87 | }
88 | });
89 | }
90 | };
91 |
92 | return (
93 |
97 | {PopupMessage}
98 | {removePopupMessage}
99 |
100 | {movies[0] ? (
101 | <>
102 |
103 | {props.title}
104 |
105 |
106 |
console.log("slide change")}
114 | onSwiper={(swiper) => console.log(swiper)}
115 | className="SwiperStyle"
116 | >
117 | {movies.map((obj, index) => {
118 | const converted = convertGenere(obj.genre_ids);
119 | return (
120 | handleMoviePopup(obj)}
123 | >
124 | {props.islarge ? (
125 | <>
126 |
130 | >
131 | ) : (
132 | <>
133 |
handleMoviePopup(obj)}
146 | />
147 | >
148 | )}
149 |
150 |
151 |
152 |
playMovie(obj)}
154 | onMouseEnter={() => setshouldPop(false)}
155 | onMouseLeave={() => setshouldPop(true)}
156 | className="text-white w-9 h-9 border-[2px] rounded-full p-2 mr-1 backdrop-blur-[2px] shadow-md ease-linear transition-all duration-150 hover:text-black hover:bg-white"
157 | >
158 |
171 |
172 |
173 | {props.movieData != null ? (
174 | <>
175 |
removeFromWatchedMovies(obj)}
177 | onMouseEnter={() => setshouldPop(false)}
178 | onMouseLeave={() => setshouldPop(true)}
179 | className="text-white w-9 h-9 border-[2px] rounded-full p-2 mr-1 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:text-black hover:bg-white"
180 | >
181 |
194 |
195 | >
196 | ) : (
197 | <>
198 |
addToMyList(obj)}
200 | onMouseEnter={() => setshouldPop(false)}
201 | onMouseLeave={() => setshouldPop(true)}
202 | className="text-white w-9 h-9 border-[2px] rounded-full p-2 mr-1 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:text-black hover:bg-white"
203 | >
204 |
217 |
218 | >
219 | )}
220 |
221 |
addToLikedMovies(obj)}
223 | onMouseEnter={() => setshouldPop(false)}
224 | onMouseLeave={() => setshouldPop(true)}
225 | className="text-white w-9 h-9 border-[2px] rounded-full p-2 mr-1 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:text-black hover:bg-white"
226 | >
227 |
240 |
241 |
242 |
handleMoviePopup(obj)}
244 | className="text-white w-9 h-9 border-[2px] rounded-full p-2 mr-1 backdrop-blur-[1px] shadow-md ease-linear transition-all duration-150 hover:text-black hover:bg-white"
245 | >
246 |
260 |
261 |
262 |
263 |
264 | {obj.name || obj.title}
265 |
266 |
267 |
268 | {obj.release_date ||
269 | (obj.first_air_date && obj.release_date) ||
270 | obj.first_air_date}
271 |
272 |
273 |
274 |
282 |
283 |
284 | {converted &&
285 | converted.map((genre) => {
286 | return (
287 |
288 | {genre}
289 |
290 | );
291 | })}
292 |
293 |
294 |
295 | );
296 | })}
297 |
298 | >
299 | ) : (
300 | <>
301 |
305 | >
306 | )}
307 |
308 | <>
309 | {/* Movie Pop Up section */}
310 | {showModal && (
311 | <>
312 |
313 |
314 | {/*content*/}
315 |
316 |
317 | {/*header*/}
318 |
337 | {/*Movie Trailer or Image*/}
338 | {urlId ? (
339 |
344 | ) : (
345 |

346 | )}
347 |
348 |
349 |
370 |
{
372 | addToMyList(moviePopupInfo);
373 | }}
374 | className="group text-white w-10 h-10 border-[2px] rounded-full p-2 mr-3 backdrop-blur-[1px] hover:bg-white hover:text-black shadow-md cursor-pointer ease-linear transition-all duration-150 "
375 | >
376 |
389 |
390 |
addToLikedMovies(moviePopupInfo)}
392 | className="text-white w-10 h-10 border-[2px] rounded-full p-2 mr-1 backdrop-blur-[1px] hover:bg-white hover:text-black shadow-md cursor-pointer ease-linear transition-all duration-150"
393 | >
394 |
407 |
408 |
409 |
410 |
411 |
412 |
413 | {moviePopupInfo.title || moviePopupInfo.name}
414 |
415 |
416 | {moviePopupInfo.release_date}
417 |
418 |
419 |
420 | {/*body*/}
421 |
422 |
423 |
424 |
425 | {moviePopupInfo.overview}
426 |
427 |
428 |
429 |
430 | {/*footer*/}
431 |
432 | {/*More Info*/}
433 |
434 |
435 |
436 | Rating :
437 |
438 |
446 |
447 |
448 |
449 | Released on :{" "}
450 |
451 | {moviePopupInfo.release_date ||
452 | moviePopupInfo.first_air_date}
453 |
454 |
455 |
456 | Language :
457 |
458 | {moviePopupInfo.original_language}
459 |
460 |
461 |
462 |
463 | Genere :
464 | {convertGenere(moviePopupInfo.genre_ids).slice(0,2).map(
465 | (genere) => {
466 | return (
467 |
468 | {genere}
469 |
470 | );
471 | }
472 | )}
473 |
474 |
475 |
476 |
477 |
478 |
499 |
500 |
521 |
522 |
523 |
524 |
525 |
526 |
527 |
528 | >
529 | )}
530 | >
531 |
532 | );
533 | }
534 |
535 | export default RowPost;
536 |
--------------------------------------------------------------------------------