├── .eslintrc.json ├── public ├── favicon.ico └── spinner.svg ├── postcss.config.js ├── jsconfig.json ├── src ├── app │ ├── globals.css │ ├── loading.jsx │ ├── head.jsx │ ├── error.jsx │ ├── Providers.jsx │ ├── layout.jsx │ ├── search │ │ └── [searchTerm] │ │ │ └── page.jsx │ ├── page.jsx │ ├── movie │ │ └── [id] │ │ │ └── page.jsx │ └── about │ │ └── page.jsx └── components │ ├── Navbar.jsx │ ├── Results.jsx │ ├── MenuItem.jsx │ ├── NavbarItem.jsx │ ├── DarkModeSwitch.jsx │ ├── Header.jsx │ ├── SearchBox.jsx │ └── Card.jsx ├── next.config.js ├── tailwind.config.js ├── .gitignore ├── package.json └── README.md /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "next/core-web-vitals" 3 | } 4 | -------------------------------------------------------------------------------- /public/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sahandghavidel/imdb/HEAD/public/favicon.ico -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | }, 6 | } 7 | -------------------------------------------------------------------------------- /jsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "baseUrl": ".", 4 | "paths": { 5 | "@/*": ["./src/*"] 6 | } 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /src/app/globals.css: -------------------------------------------------------------------------------- 1 | @tailwind base; 2 | @tailwind components; 3 | @tailwind utilities; 4 | 5 | html::-webkit-scrollbar { 6 | display: none; 7 | } 8 | 9 | html { 10 | scrollbar-width: none; 11 | } 12 | -------------------------------------------------------------------------------- /src/app/loading.jsx: -------------------------------------------------------------------------------- 1 | export default function loading() { 2 | return ( 3 |
4 | loading... 5 |
6 | ); 7 | } 8 | -------------------------------------------------------------------------------- /next.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('next').NextConfig} */ 2 | const nextConfig = { 3 | experimental: { 4 | appDir: true, 5 | }, 6 | images: { 7 | domains: ["image.tmdb.org"], 8 | }, 9 | }; 10 | 11 | module.exports = nextConfig; 12 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: [ 4 | // Or if using `src` directory: 5 | "./src/**/*.{js,ts,jsx,tsx}", 6 | ], 7 | theme: { 8 | extend: {}, 9 | }, 10 | plugins: [require("@tailwindcss/line-clamp")], 11 | darkMode: "class", 12 | }; 13 | -------------------------------------------------------------------------------- /src/app/head.jsx: -------------------------------------------------------------------------------- 1 | export default function Head() { 2 | return ( 3 | <> 4 | IMDb Clobe 5 | 6 | 7 | 8 | 9 | ) 10 | } 11 | -------------------------------------------------------------------------------- /src/components/Navbar.jsx: -------------------------------------------------------------------------------- 1 | import NavbarItem from "./NavbarItem"; 2 | 3 | export default function Navbar() { 4 | return ( 5 |
6 | 7 | 8 |
9 | ); 10 | } 11 | -------------------------------------------------------------------------------- /src/components/Results.jsx: -------------------------------------------------------------------------------- 1 | import Card from "./Card"; 2 | 3 | export default function Results({ results }) { 4 | return ( 5 |
6 | {results.map((result) => ( 7 | 8 | ))} 9 |
10 | ); 11 | } 12 | -------------------------------------------------------------------------------- /src/components/MenuItem.jsx: -------------------------------------------------------------------------------- 1 | import Link from "next/link"; 2 | 3 | export default function MenuItem({ title, address, Icon }) { 4 | return ( 5 |
6 | 7 | 8 |

{title}

9 | 10 |
11 | ); 12 | } 13 | -------------------------------------------------------------------------------- /src/app/error.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useEffect } from "react"; 4 | export default function Error({ error, reset }) { 5 | useEffect(() => { 6 | console.log(error); 7 | }, [error]); 8 | return ( 9 |
10 |

Something went wrong

11 | 12 |
13 | ); 14 | } 15 | -------------------------------------------------------------------------------- /src/app/Providers.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { ThemeProvider } from "next-themes"; 4 | 5 | export default function Providers({ children }) { 6 | return ( 7 | 8 |
9 | {children} 10 |
11 |
12 | ); 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # next.js 12 | /.next/ 13 | /out/ 14 | 15 | # production 16 | /build 17 | 18 | # misc 19 | .DS_Store 20 | *.pem 21 | 22 | # debug 23 | npm-debug.log* 24 | yarn-debug.log* 25 | yarn-error.log* 26 | .pnpm-debug.log* 27 | 28 | # local env files 29 | .env*.local 30 | 31 | # vercel 32 | .vercel 33 | -------------------------------------------------------------------------------- /public/spinner.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /src/app/layout.jsx: -------------------------------------------------------------------------------- 1 | import Header from "@/components/Header"; 2 | import Navbar from "@/components/Navbar"; 3 | import SearchBox from "@/components/SearchBox"; 4 | import "./globals.css"; 5 | import Providers from "./Providers"; 6 | 7 | export default function RootLayout({ children }) { 8 | return ( 9 | 10 | 11 | 12 | {/* Header */} 13 |
14 | 15 | {/* Navbar */} 16 | 17 | 18 | 19 | {/* SearchBox */} 20 | 21 | 22 | 23 | {children} 24 | 25 | 26 | 27 | ); 28 | } 29 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "imdb", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "dev": "next dev", 7 | "build": "next build", 8 | "start": "next start", 9 | "lint": "next lint" 10 | }, 11 | "dependencies": { 12 | "@next/font": "13.1.5", 13 | "eslint": "8.32.0", 14 | "eslint-config-next": "13.1.5", 15 | "next": "13.1.5", 16 | "next-themes": "^0.2.1", 17 | "react": "18.2.0", 18 | "react-dom": "18.2.0", 19 | "react-icons": "^4.7.1" 20 | }, 21 | "devDependencies": { 22 | "@tailwindcss/line-clamp": "^0.4.2", 23 | "autoprefixer": "^10.4.13", 24 | "postcss": "^8.4.21", 25 | "tailwindcss": "^3.2.4" 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /src/components/NavbarItem.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import Link from "next/link"; 4 | 5 | import { useSearchParams } from "next/navigation"; 6 | 7 | export default function NavbarItem({ title, param }) { 8 | const searchParams = useSearchParams(); 9 | const genre = searchParams.get("genre"); 10 | return ( 11 |
12 | 20 | {title} 21 | 22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/app/search/[searchTerm]/page.jsx: -------------------------------------------------------------------------------- 1 | import Results from "@/components/Results"; 2 | 3 | export default async function SearchPage({ params }) { 4 | const res = await fetch( 5 | `https://api.themoviedb.org/3/search/movie?api_key=${process.env.API_KEY}&query=${params.searchTerm}&language=en-US&include_adult=false` 6 | ); 7 | 8 | if (!res.ok) { 9 | throw new Error("Error fetching data"); 10 | } 11 | 12 | const data = await res.json(); 13 | 14 | const results = data.results; 15 | return ( 16 |
17 | {results && results.length === 0 && ( 18 |

No results found

19 | )} 20 | 21 | {results && } 22 |
23 | ); 24 | } 25 | -------------------------------------------------------------------------------- /src/components/DarkModeSwitch.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | import { MdLightMode } from "react-icons/md"; 3 | import { BsFillMoonFill } from "react-icons/bs"; 4 | import { useTheme } from "next-themes"; 5 | import { useEffect, useState } from "react"; 6 | export default function DarkModeSwitch() { 7 | const { systemTheme, theme, setTheme } = useTheme(); 8 | const [mounted, setMounted] = useState(false); 9 | 10 | useEffect(() => setMounted(true), []); 11 | 12 | const currentTheme = theme === "system" ? systemTheme : theme; 13 | return ( 14 | <> 15 | {mounted && 16 | (currentTheme === "dark" ? ( 17 | setTheme("light")} 20 | /> 21 | ) : ( 22 | setTheme("dark")} 25 | /> 26 | ))} 27 | 28 | ); 29 | } 30 | -------------------------------------------------------------------------------- /src/components/Header.jsx: -------------------------------------------------------------------------------- 1 | import MenuItem from "./MenuItem"; 2 | import { AiFillHome } from "react-icons/ai"; 3 | import { BsFillInfoCircleFill } from "react-icons/bs"; 4 | import Link from "next/link"; 5 | import DarkModeSwitch from "./DarkModeSwitch"; 6 | 7 | export default function Header() { 8 | return ( 9 |
10 |
11 | 12 | 13 |
14 |
15 | 16 | 17 |

18 | 19 | IMDb 20 | 21 | Clone 22 |

23 | 24 |
25 |
26 | ); 27 | } 28 | -------------------------------------------------------------------------------- /src/components/SearchBox.jsx: -------------------------------------------------------------------------------- 1 | "use client"; 2 | 3 | import { useState } from "react"; 4 | import { useRouter } from "next/navigation"; 5 | export default function SearchBox() { 6 | const [search, setSearch] = useState(""); 7 | const router = useRouter(); 8 | function handleSubmit(e) { 9 | e.preventDefault(); 10 | if (!search) return; 11 | router.push(`/search/${search}`); 12 | } 13 | return ( 14 |
18 | setSearch(e.target.value)} 21 | type="text" 22 | placeholder="Search keywords..." 23 | className="w-full h-14 rounded-sm placeholder-gary-500 outline-none bg-transparent flex-1" 24 | /> 25 | 32 |
33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /src/app/page.jsx: -------------------------------------------------------------------------------- 1 | // Fix the problem for "search params object is empty in production with next 13 app dir" 2 | 3 | // for more info "https://github.com/vercel/next.js/issues/43077" 4 | 5 | export const dynamic = "force-dynamic"; // this is the fix 6 | 7 | import Results from "@/components/Results"; 8 | 9 | const API_KEY = process.env.API_KEY; 10 | 11 | export default async function Home({ searchParams }) { 12 | const genre = searchParams.genre || "fetchTrending"; 13 | 14 | const res = await fetch( 15 | `https://api.themoviedb.org/3/${ 16 | genre === "fetchTopRated" ? "movie/top_rated" : "trending/all/week" 17 | }?api_key=${API_KEY}&language=en-US&page=1`, 18 | { next: { revalidate: 10000 } } 19 | ); 20 | 21 | if (!res.ok) { 22 | throw new Error("Failed to fetch data"); // this will be caught by the error page and passed to the page as props 23 | } 24 | 25 | const data = await res.json(); 26 | 27 | const results = data.results; 28 | 29 | return ( 30 |
31 | 32 |
33 | ); 34 | } 35 | -------------------------------------------------------------------------------- /src/components/Card.jsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | import Link from "next/link"; 3 | import { FiThumbsUp } from "react-icons/fi"; 4 | 5 | export default function Card({ result }) { 6 | return ( 7 |
8 | 9 | image is not available 24 |
25 |

{result.overview}

26 |

27 | {result.title || result.name} 28 |

29 |

30 | {result.release_date || result.first_air_date} 31 | {result.vote_count} 32 |

33 |
34 | 35 |
36 | ); 37 | } 38 | -------------------------------------------------------------------------------- /src/app/movie/[id]/page.jsx: -------------------------------------------------------------------------------- 1 | import Image from "next/image"; 2 | 3 | async function getMovie(movieId) { 4 | const res = await fetch( 5 | `https://api.themoviedb.org/3/movie/${movieId}?api_key=${process.env.API_KEY}` 6 | ); 7 | return await res.json(); 8 | } 9 | 10 | export default async function MoviePage({ params }) { 11 | const movieId = params.id; 12 | const movie = await getMovie(movieId); 13 | return ( 14 |
15 |
16 | Movie poster 31 |
32 |

33 | {movie.title || movie.name} 34 |

35 |

36 | Overview: 37 | {movie.overview} 38 |

39 |

40 | Date Released: 41 | {movie.release_date || movie.first_air_date} 42 |

43 |

44 | Rating: 45 | {movie.vote_count} 46 |

47 |
48 |
49 |
50 | ); 51 | } 52 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app). 2 | 3 | ## Getting Started 4 | 5 | First, run the development server: 6 | 7 | ```bash 8 | npm run dev 9 | # or 10 | yarn dev 11 | # or 12 | pnpm dev 13 | ``` 14 | 15 | Open [http://localhost:3000](http://localhost:3000) with your browser to see the result. 16 | 17 | You can start editing the page by modifying `app/page.jsx`. The page auto-updates as you edit the file. 18 | 19 | [API routes](https://nextjs.org/docs/api-routes/introduction) can be accessed on [http://localhost:3000/api/hello](http://localhost:3000/api/hello). This endpoint can be edited in `pages/api/hello.js`. 20 | 21 | The `pages/api` directory is mapped to `/api/*`. Files in this directory are treated as [API routes](https://nextjs.org/docs/api-routes/introduction) instead of React pages. 22 | 23 | This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font. 24 | 25 | ## Learn More 26 | 27 | To learn more about Next.js, take a look at the following resources: 28 | 29 | - [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API. 30 | - [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial. 31 | 32 | You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome! 33 | 34 | ## Deploy on Vercel 35 | 36 | The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js. 37 | 38 | Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details. 39 | -------------------------------------------------------------------------------- /src/app/about/page.jsx: -------------------------------------------------------------------------------- 1 | export default function About() { 2 | return ( 3 |
4 |

About

5 |

6 | Welcome to our movie database website! We are a team of passionate movie 7 | enthusiasts who have come together to create a one-stop destination for 8 | all your movie-related needs. 9 |

10 | 11 |

12 | Our website is designed to provide you with a comprehensive database of 13 | movies from all around the world, along with the latest news, reviews, 14 | and trailers. Our movie database is constantly updated with new 15 | releases, ensuring that you have access to the latest and greatest in 16 | the world of cinema. You can search for movies by title, director, 17 | actor, genre, or release date, making it easy to find the perfect movie 18 | for any occasion. 19 |

20 | 21 |

22 | In addition to our extensive movie database, we also offer a platform 23 | for movie lovers to connect and share their thoughts on the latest 24 | releases. Our community section includes a forum where you can discuss 25 | your favorite films with like-minded individuals and read reviews and 26 | ratings from other users. We also have a section dedicated to movie news 27 | and trailers, keeping you updated with the latest happenings in the 28 | world of cinema. Thank you for visiting our website and we hope you 29 | enjoy your time browsing through our movie database. If you have any 30 | feedback or suggestions, please feel free to contact us. We are always 31 | looking for ways to improve and enhance the user experience on our 32 | website. Happy browsing! 33 |

34 |
35 | ); 36 | } 37 | --------------------------------------------------------------------------------