ChandimaPrabath commited on
Commit
cb20bdc
1 Parent(s): 0da6de1
frontend/package-lock.json CHANGED
@@ -8,6 +8,7 @@
8
  "name": "frontend",
9
  "version": "0.1.0",
10
  "dependencies": {
 
11
  "@fortawesome/fontawesome-svg-core": "^6.6.0",
12
  "@fortawesome/free-regular-svg-icons": "^6.6.0",
13
  "@fortawesome/free-solid-svg-icons": "^6.6.0",
@@ -100,6 +101,14 @@
100
  "node": ">=6"
101
  }
102
  },
 
 
 
 
 
 
 
 
103
  "node_modules/@fortawesome/fontawesome-svg-core": {
104
  "version": "6.6.0",
105
  "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.6.0.tgz",
 
8
  "name": "frontend",
9
  "version": "0.1.0",
10
  "dependencies": {
11
+ "@fortawesome/fontawesome-free": "^6.6.0",
12
  "@fortawesome/fontawesome-svg-core": "^6.6.0",
13
  "@fortawesome/free-regular-svg-icons": "^6.6.0",
14
  "@fortawesome/free-solid-svg-icons": "^6.6.0",
 
101
  "node": ">=6"
102
  }
103
  },
104
+ "node_modules/@fortawesome/fontawesome-free": {
105
+ "version": "6.6.0",
106
+ "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz",
107
+ "integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==",
108
+ "engines": {
109
+ "node": ">=6"
110
+ }
111
+ },
112
  "node_modules/@fortawesome/fontawesome-svg-core": {
113
  "version": "6.6.0",
114
  "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-6.6.0.tgz",
frontend/package.json CHANGED
@@ -9,6 +9,7 @@
9
  "lint": "next lint"
10
  },
11
  "dependencies": {
 
12
  "@fortawesome/fontawesome-svg-core": "^6.6.0",
13
  "@fortawesome/free-regular-svg-icons": "^6.6.0",
14
  "@fortawesome/free-solid-svg-icons": "^6.6.0",
 
9
  "lint": "next lint"
10
  },
11
  "dependencies": {
12
+ "@fortawesome/fontawesome-free": "^6.6.0",
13
  "@fortawesome/fontawesome-svg-core": "^6.6.0",
14
  "@fortawesome/free-regular-svg-icons": "^6.6.0",
15
  "@fortawesome/free-solid-svg-icons": "^6.6.0",
frontend/src/app/films/filmsPage.css CHANGED
@@ -37,7 +37,7 @@
37
  }
38
 
39
  .pagination-button {
40
- background-color: #2c2b2b;
41
  color: #f5f5f5;
42
  border: none;
43
  border-radius: 5px;
@@ -50,7 +50,7 @@
50
  }
51
 
52
  .pagination-button:hover {
53
- background-color: #555;
54
  transform: scale(1.05);
55
  }
56
 
 
37
  }
38
 
39
  .pagination-button {
40
+ background-color: #21264a;
41
  color: #f5f5f5;
42
  border: none;
43
  border-radius: 5px;
 
50
  }
51
 
52
  .pagination-button:hover {
53
+ background-color: #202a75;
54
  transform: scale(1.05);
55
  }
56
 
frontend/src/app/films/page.js CHANGED
@@ -57,7 +57,7 @@ export default function FilmsPage() {
57
  <FontAwesomeIcon
58
  icon={faCaretLeft}
59
  size="2xl"
60
- color='#e88f36'
61
  bounce={isPrevButtonEnabled}
62
  />
63
  </button>
@@ -72,7 +72,7 @@ export default function FilmsPage() {
72
  <FontAwesomeIcon
73
  icon={faCaretRight}
74
  size="2xl"
75
- color='#e88f36'
76
  bounce={isNextButtonEnabled}
77
  />
78
  </button>
 
57
  <FontAwesomeIcon
58
  icon={faCaretLeft}
59
  size="2xl"
60
+ color='#3f5fd2'
61
  bounce={isPrevButtonEnabled}
62
  />
63
  </button>
 
72
  <FontAwesomeIcon
73
  icon={faCaretRight}
74
  size="2xl"
75
+ color='#3f5fd2'
76
  bounce={isNextButtonEnabled}
77
  />
78
  </button>
frontend/src/app/globals.css CHANGED
@@ -1,33 +1,10 @@
 
 
1
  @tailwind base;
2
  @tailwind components;
3
  @tailwind utilities;
4
 
5
- :root {
6
- --foreground-rgb: 0, 0, 0;
7
- --background-start-rgb: 214, 219, 220;
8
- --background-end-rgb: 255, 255, 255;
9
- }
10
-
11
- @media (prefers-color-scheme: dark) {
12
- :root {
13
- --foreground-rgb: 255, 255, 255;
14
- --background-start-rgb: 0, 0, 0;
15
- --background-end-rgb: 0, 0, 0;
16
- }
17
- }
18
-
19
  body {
20
- color: rgb(var(--foreground-rgb));
21
- background: linear-gradient(
22
- to bottom,
23
- transparent,
24
- rgb(var(--background-end-rgb))
25
- )
26
- rgb(var(--background-start-rgb));
27
- }
28
-
29
- @layer utilities {
30
- .text-balance {
31
- text-wrap: balance;
32
- }
33
- }
 
1
+ @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700;900&family=Noto+Sans:wght@400;500;700;900&display=swap');
2
+
3
  @tailwind base;
4
  @tailwind components;
5
  @tailwind utilities;
6
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  body {
8
+ font-family: 'Inter', 'Noto Sans', sans-serif;
9
+ background-color: #0a0a10;
10
+ }
 
 
 
 
 
 
 
 
 
 
 
frontend/src/app/layout.js CHANGED
@@ -1,24 +1,10 @@
1
  import { Inter } from "next/font/google";
2
  import "./globals.css";
3
- import Navbar from "../components/Navbar";
4
  import { FilmProvider } from "@/context/FilmContext";
5
- import { library } from "@fortawesome/fontawesome-svg-core";
6
  import { config } from "@fortawesome/fontawesome-svg-core";
7
  import "@fortawesome/fontawesome-svg-core/styles.css";
8
  config.autoAddCss = false;
9
- import {
10
- faEllipsisVertical,
11
- faPlay,
12
- faChevronLeft,
13
- faCaretDown,
14
- faCaretLeft,
15
- faCaretRight,
16
- faMagnifyingGlass,
17
- faHome,
18
- faFilm,
19
- faTv,
20
- } from "@fortawesome/free-solid-svg-icons";
21
-
22
  const inter = Inter({ subsets: ["latin"] });
23
 
24
  export const metadata = {
@@ -31,7 +17,7 @@ export default function RootLayout({ children }) {
31
  <html lang="en">
32
  <body className={inter.className}>
33
  <header>
34
- <Navbar />
35
  </header>
36
  <FilmProvider>{children}</FilmProvider>
37
  </body>
 
1
  import { Inter } from "next/font/google";
2
  import "./globals.css";
3
+ import Sidebar from '@/components/Sidebar';
4
  import { FilmProvider } from "@/context/FilmContext";
 
5
  import { config } from "@fortawesome/fontawesome-svg-core";
6
  import "@fortawesome/fontawesome-svg-core/styles.css";
7
  config.autoAddCss = false;
 
 
 
 
 
 
 
 
 
 
 
 
 
8
  const inter = Inter({ subsets: ["latin"] });
9
 
10
  export const metadata = {
 
17
  <html lang="en">
18
  <body className={inter.className}>
19
  <header>
20
+ <Sidebar />
21
  </header>
22
  <FilmProvider>{children}</FilmProvider>
23
  </body>
frontend/src/app/page.js CHANGED
@@ -1,43 +1,148 @@
1
- 'use client';
2
- import { useEffect, useState } from 'react';
3
- import apiClient from "@/api/apiClient";
4
-
5
- export default function Home() {
6
- const [films, setFilms] = useState([]);
7
- const [loading, setLoading] = useState(true);
8
- const [error, setError] = useState(null);
9
-
10
- useEffect(() => {
11
- async function fetchFilms() {
12
- try {
13
- const all_films = await apiClient.getAllFilms();
14
- setFilms(all_films);
15
- console.log(all_films);
16
- } catch (error) {
17
- setError('Failed to load films.');
18
- console.error('Error fetching films:', error);
19
- } finally {
20
- setLoading(false);
21
- }
22
- }
23
-
24
- fetchFilms();
25
- }, []);
26
-
27
- if (loading) return <p>Loading...</p>;
28
- if (error) return <p>{error}</p>;
29
 
 
30
  return (
31
  <>
32
- <div>
33
- <h1>Welcome to the Streaming Service</h1>
34
- <p>Explore our collection of films and TV shows.</p>
35
- <ul>
36
- {films.map((film, index) => (
37
- <li key={index}>{film.title}</li>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
38
  ))}
39
- </ul>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
40
  </div>
41
  </>
42
  );
43
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import Head from "next/head";
2
+ import HeroSection from "@/components/HeroSection";
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3
 
4
+ const HomePage = () => {
5
  return (
6
  <>
7
+ <Head>
8
+ <title>Home Page</title>
9
+ <meta
10
+ name="description"
11
+ content="Home page for the streaming service"
12
+ />
13
+ <link rel="icon" href="/favicon.ico" />
14
+ </Head>
15
+ <div style={styles.container}>
16
+ <HeroSection />
17
+ <h2 style={styles.sectionTitle}>Popular TV Shows</h2>
18
+ <div style={styles.gridContainer}>
19
+ {[
20
+ "https://cdn.usegalileo.ai/stability/687bdd7d-7a06-425e-b527-7e18f4fe2201.png",
21
+ "https://cdn.usegalileo.ai/stability/acb62b11-0501-4e27-b6ba-83eed9b83e95.png",
22
+ "https://cdn.usegalileo.ai/stability/78f55a19-d0fa-4986-a7cb-60190a3fa76f.png",
23
+ "https://cdn.usegalileo.ai/stability/05bd1020-2f24-4a82-9b8f-2680fa920751.png",
24
+ "https://cdn.usegalileo.ai/stability/912a274b-dd29-4b40-9140-1c1dcd76bd07.png",
25
+ "https://cdn.usegalileo.ai/sdxl10/a9cf44f2-a00c-4aaa-8350-7c70cfaa4dd0.png",
26
+ "https://cdn.usegalileo.ai/stability/0eee4644-0e4c-4549-8c6a-c445b3903d3c.png",
27
+ "https://cdn.usegalileo.ai/sdxl10/089b78f9-0a0a-4f17-a7a1-4684c3b5efb1.png",
28
+ "https://cdn.usegalileo.ai/sdxl10/f4aa01e0-cfe0-4a32-a419-9ef37149b620.png",
29
+ "https://cdn.usegalileo.ai/stability/95bccea1-1d96-4395-bd11-feb0d7650b30.png",
30
+ "https://cdn.usegalileo.ai/stability/4a3482f4-899f-4dc9-9806-03025979894b.png",
31
+ "https://images.unsplash.com/photo-1639452127871-8c6ea78d2b11?crop=entropy&amp;cs=tinysrgb&amp;fit=max&amp;fm=jpg&amp;ixid=M3w0NTI0NDl8MHwxfHNlYXJjaHw0fHxkYXJrJTIwdGhlbWV8ZW58MXx8fHwxNzI0NDkwMjIyfDA&amp;ixlib=rb-4.0.3&amp;q=80&amp;w=1080",
32
+ ].map((url, index) => (
33
+ <div key={index} style={styles.imageWrapper}>
34
+ <div
35
+ style={{ ...styles.image, backgroundImage: `url(${url})` }}
36
+ />
37
+ </div>
38
  ))}
39
+ </div>
40
+ <h2 style={styles.sectionTitle}>Trending Movies</h2>
41
+ <div style={styles.gridContainer}>
42
+ {[
43
+ "https://cdn.usegalileo.ai/sdxl10/e410f67a-8111-44e4-8370-99ffbfeeb7f1.png",
44
+ "https://cdn.usegalileo.ai/stability/953f8b85-e6b9-4906-8e47-c9d12bf6c9e6.png",
45
+ "https://cdn.usegalileo.ai/stability/58480847-a20d-4ad8-8ef7-aebf592bc4fb.png",
46
+ "https://cdn.usegalileo.ai/stability/e354bd6d-aa67-44be-be97-28be6bc058f0.png",
47
+ "https://cdn.usegalileo.ai/sdxl10/d251f08e-3da4-4d05-937d-1cbb318ca2e4.png",
48
+ "https://cdn.usegalileo.ai/stability/f870c303-f081-4ce7-b89a-5c7336dce39e.png",
49
+ "https://cdn.usegalileo.ai/stability/6fad613e-3db5-436f-a4d0-e5f4651a6fe0.png",
50
+ "https://cdn.usegalileo.ai/sdxl10/4b19f651-702b-4474-8800-e81184b43539.png",
51
+ "https://cdn.usegalileo.ai/stability/89022a7e-44c9-42d5-b671-2d10fe48ad07.png",
52
+ "https://cdn.usegalileo.ai/stability/a6873021-6f80-47de-bf2c-f4facf9a7eb7.png",
53
+ "https://cdn.usegalileo.ai/stability/a49b740a-d6ae-42da-a446-5877abf5c63d.png",
54
+ "https://cdn.usegalileo.ai/stability/2e6bd747-164e-4f5e-baf7-91fa3af15f25.png",
55
+ ].map((url, index) => (
56
+ <div key={index} style={styles.imageWrapper}>
57
+ <div
58
+ style={{ ...styles.image, backgroundImage: `url(${url})` }}
59
+ />
60
+ </div>
61
+ ))}
62
+ </div>
63
  </div>
64
  </>
65
  );
66
+ };
67
+
68
+ const styles = {
69
+ container: {
70
+ display: "flex",
71
+ flexDirection: "column",
72
+ maxWidth: "960px",
73
+ margin: "0 auto",
74
+ flex: 1,
75
+ },
76
+ heroSection: {
77
+ display: "flex",
78
+ minHeight: "400px",
79
+ flexDirection: "column",
80
+ justifyContent: "flex-end",
81
+ backgroundImage:
82
+ 'linear-gradient(rgba(0, 0, 0, 0.1) 0%, rgba(0, 0, 0, 0.4) 100%), url("https://cdn.usegalileo.ai/sdxl10/5e86a222-949b-4c84-b77b-bec08e557e36.png")',
83
+ backgroundSize: "cover",
84
+ backgroundPosition: "center",
85
+
86
+ padding: "0 16px 40px",
87
+ borderRadius: "16px",
88
+ color: "#ffffff",
89
+ textAlign: "left",
90
+ },
91
+ heroContent: {
92
+ display: "flex",
93
+ flexDirection: "column",
94
+ gap: "16px",
95
+ },
96
+ heroTitle: {
97
+ fontSize: "2.5rem",
98
+ fontWeight: "bold",
99
+ lineHeight: "1.2",
100
+ },
101
+ heroSubtitle: {
102
+ fontSize: "1rem",
103
+ fontWeight: "normal",
104
+ lineHeight: "1.4",
105
+ },
106
+ playButton: {
107
+ display: "flex",
108
+ alignItems: "center",
109
+ justifyContent: "center",
110
+ width: "auto",
111
+ height: "40px",
112
+ padding: "0 16px",
113
+ borderRadius: "8px",
114
+ backgroundColor: "#695ffa",
115
+ color: "#ffffff",
116
+ fontSize: "1rem",
117
+ fontWeight: "bold",
118
+ cursor: "pointer",
119
+ },
120
+ sectionTitle: {
121
+ color: "#ffffff",
122
+ fontSize: "1.4rem",
123
+ fontWeight: "bold",
124
+ margin: "16px 0",
125
+ paddingLeft: "16px",
126
+ },
127
+ gridContainer: {
128
+ display: "grid",
129
+ gridTemplateColumns: "repeat(auto-fit, minmax(158px, 1fr))",
130
+ gap: "16px",
131
+ padding: "0 16px",
132
+ },
133
+ imageWrapper: {
134
+ display: "flex",
135
+ flexDirection: "column",
136
+ gap: "8px",
137
+ },
138
+ image: {
139
+ width: "100%",
140
+ backgroundSize: "cover",
141
+ backgroundPosition: "center",
142
+ aspectRatio: "16/9",
143
+ borderRadius: "16px",
144
+ height: "100%",
145
+ },
146
+ };
147
+
148
+ export default HomePage;
frontend/src/components/HeroSection.css ADDED
@@ -0,0 +1,165 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .hero-container {
2
+ position: relative;
3
+ width: 100%;
4
+ overflow: hidden;
5
+ }
6
+
7
+ .hero-section {
8
+ display: flex;
9
+ flex-direction: column;
10
+ min-height: 480px;
11
+ position: relative;
12
+ border-radius: 12px;
13
+ padding: 1rem;
14
+ padding-bottom: 2.5rem;
15
+ justify-content: flex-end;
16
+ }
17
+
18
+ .hero-image {
19
+ position: absolute;
20
+ top: 0;
21
+ left: 0;
22
+ width: 100%;
23
+ height: 100%;
24
+ background-size: cover;
25
+ background-position: center;
26
+ background-repeat: no-repeat;
27
+ transition: opacity .2s ease-in-out;
28
+ opacity: 0;
29
+ }
30
+
31
+ .hero-image.active {
32
+ opacity: 1;
33
+ }
34
+
35
+ .hero-text {
36
+ display: flex;
37
+ flex-direction: column;
38
+ gap: 0.5rem;
39
+ text-align: left;
40
+ position: relative;
41
+ z-index: 1;
42
+ }
43
+
44
+ .hero-title {
45
+ color: white;
46
+ font-size: 2.5rem;
47
+ font-weight: 900;
48
+ line-height: 1.2;
49
+ transition: font-size 0.3s ease-in-out;
50
+ }
51
+
52
+ .hero-description {
53
+ color: white;
54
+ font-size: 1rem;
55
+ font-weight: normal;
56
+ line-height: 1.4;
57
+ transition: font-size 0.3s ease-in-out;
58
+ }
59
+
60
+ .hero-indicators {
61
+ position: absolute;
62
+ bottom: 1rem;
63
+ left: 50%;
64
+ transform: translateX(-50%);
65
+ display: flex;
66
+ gap: 0.5rem;
67
+ }
68
+
69
+ .indicator {
70
+ width: 20px;
71
+ height: 10px;
72
+ border-radius: 5px;
73
+ background-color: gray;
74
+ cursor: pointer;
75
+ transition: background-color 0.3s ease-in-out, transform 0.3s ease-in-out;
76
+ }
77
+
78
+ .indicator.active {
79
+ background-color: white;
80
+ transform: scale(1.2);
81
+ }
82
+
83
+ /* Responsive Styles */
84
+ @media (max-width: 1200px) {
85
+ .hero-title {
86
+ font-size: 2rem;
87
+ }
88
+ .hero-description {
89
+ font-size: 0.875rem;
90
+ }
91
+ .hero-button {
92
+ height: 2rem;
93
+ font-size: 0.75rem;
94
+ padding: 0 0.75rem;
95
+ }
96
+ .indicator {
97
+ width: 15px;
98
+ height: 7px;
99
+ }
100
+ }
101
+
102
+ @media (max-width: 992px) {
103
+ .hero-section {
104
+ min-height: 400px;
105
+ }
106
+ .hero-title {
107
+ font-size: 1.75rem;
108
+ }
109
+ .hero-description {
110
+ font-size: 0.75rem;
111
+ }
112
+ .hero-button {
113
+ height: 1.75rem;
114
+ font-size: 0.675rem;
115
+ padding: 0 0.5rem;
116
+ }
117
+ .indicator {
118
+ width: 12px;
119
+ height: 6px;
120
+ }
121
+ }
122
+
123
+ @media (max-width: 768px) {
124
+ .hero-section {
125
+ min-height: 300px;
126
+ padding: 0.5rem;
127
+ padding-bottom: 2rem;
128
+ }
129
+ .hero-title {
130
+ font-size: 1.5rem;
131
+ }
132
+ .hero-description {
133
+ font-size: 0.875rem;
134
+ }
135
+ .hero-button {
136
+ height: 1.5rem;
137
+ font-size: 0.75rem;
138
+ padding: 0 0.5rem;
139
+ }
140
+ .indicator {
141
+ width: 15px;
142
+ height: 8px;
143
+ }
144
+ }
145
+
146
+ @media (max-width: 576px) {
147
+ .hero-section {
148
+ min-height: 200px;
149
+ }
150
+ .hero-title {
151
+ font-size: 1.25rem;
152
+ }
153
+ .hero-description {
154
+ font-size: 0.75rem;
155
+ }
156
+ .hero-button {
157
+ height: 1.25rem;
158
+ font-size: 0.625rem;
159
+ padding: 0 0.5rem;
160
+ }
161
+ .indicator {
162
+ width: 12px;
163
+ height: 6px;
164
+ }
165
+ }
frontend/src/components/HeroSection.js ADDED
@@ -0,0 +1,141 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 'use client';
2
+ import { useState, useEffect, useRef } from 'react';
3
+ import './HeroSection.css';
4
+
5
+ const dummyItems = [
6
+ {
7
+ title: "My Spy (2020)",
8
+ description: "An exciting new release!",
9
+ imageUrl: "https://i.ytimg.com/vi/pfAhQSz-j_o/maxresdefault.jpg"
10
+ },
11
+ {
12
+ title: "My Spy 2 (2024)",
13
+ description: "Don't miss this one!",
14
+ imageUrl: "https://m.media-amazon.com/images/M/MV5BNDA5MTlhMDMtN2QwOS00N2MwLTgyY2ItOTU3YjBkNjM4OTMwXkEyXkFqcGc@._V1_.jpg"
15
+ },
16
+ {
17
+ title: "The Matrix (1999)",
18
+ description: "A revolutionary sci-fi film.",
19
+ imageUrl: "https://www.visitindianacountypa.org/wp-content/uploads/2024/05/The-Matrix-1999-Movie-Poster.jpg"
20
+ },
21
+ {
22
+ title: "Inception (2010)",
23
+ description: "A mind-bending thriller.",
24
+ imageUrl: "https://www.youtube.com/watch?v=T03XUKBn8UA"
25
+ },
26
+ {
27
+ title: "Interstellar (2014)",
28
+ description: "A journey through space and time.",
29
+ imageUrl: "https://m.media-amazon.com/images/I/71B5r9miWQL._AC_SY679_.jpg"
30
+ },
31
+ {
32
+ title: "The Grand Budapest Hotel (2014)",
33
+ description: "A quirky and visually stunning comedy.",
34
+ imageUrl: "https://m.media-amazon.com/images/I/71P6YpYH2DL._AC_SY679_.jpg"
35
+ },
36
+ {
37
+ title: "Parasite (2019)",
38
+ description: "A gripping social thriller.",
39
+ imageUrl: "https://m.media-amazon.com/images/I/71bETIp-2rL._AC_SY679_.jpg"
40
+ },
41
+ {
42
+ title: "Spider-Man: Into the Spider-Verse (2018)",
43
+ description: "A fresh take on the Spider-Man story.",
44
+ imageUrl: "https://m.media-amazon.com/images/I/71T9Yyx9MiL._AC_SY679_.jpg"
45
+ },
46
+ {
47
+ title: "Knives Out (2019)",
48
+ description: "A clever whodunit mystery.",
49
+ imageUrl: "https://m.media-amazon.com/images/I/71WBkkgPTsL._AC_SY679_.jpg"
50
+ },
51
+ {
52
+ title: "Dune (2021)",
53
+ description: "An epic adaptation of the sci-fi classic.",
54
+ imageUrl: "https://m.media-amazon.com/images/I/71jwlJ+j99L._AC_SY679_.jpg"
55
+ },
56
+ {
57
+ title: "Joker (2019)",
58
+ description: "A dark take on the iconic character.",
59
+ imageUrl: "https://m.media-amazon.com/images/I/71Uphd6N0pL._AC_SY679_.jpg"
60
+ },
61
+ {
62
+ title: "Blade Runner 2049 (2017)",
63
+ description: "A visually stunning sci-fi sequel.",
64
+ imageUrl: "https://m.media-amazon.com/images/I/71mB6bX5sAL._AC_SY679_.jpg"
65
+ }
66
+ ];
67
+
68
+
69
+ const HeroSection = () => {
70
+ const [currentIndex, setCurrentIndex] = useState(0);
71
+ const intervalRef = useRef(null);
72
+ const [fadeOut, setFadeOut] = useState(false);
73
+
74
+ const startAutoSwitch = () => {
75
+ if (intervalRef.current) clearInterval(intervalRef.current);
76
+ intervalRef.current = setInterval(() => {
77
+ setFadeOut(true); // Trigger fade-out
78
+ setTimeout(() => {
79
+ setCurrentIndex(prevIndex => (prevIndex + 1) % dummyItems.length);
80
+ setFadeOut(false); // Trigger fade-in
81
+ }, 200); // Match this timeout with the animation duration
82
+ }, 5000);
83
+ };
84
+
85
+ useEffect(() => {
86
+ startAutoSwitch(); // Start auto-switching when component mounts
87
+
88
+ return () => {
89
+ clearInterval(intervalRef.current); // Clean up interval on component unmount
90
+ };
91
+ }, []);
92
+
93
+ const handleIndicatorClick = (index) => {
94
+ setFadeOut(true); // Trigger fade-out
95
+ setTimeout(() => {
96
+ setCurrentIndex(index);
97
+ setFadeOut(false); // Trigger fade-in
98
+ }, 100);
99
+ startAutoSwitch();
100
+ };
101
+
102
+ useEffect(() => {
103
+ startAutoSwitch();
104
+
105
+ return () => {
106
+ clearInterval(intervalRef.current);
107
+ };
108
+ }, [currentIndex]);
109
+
110
+ const { title, description, imageUrl } = dummyItems[currentIndex];
111
+
112
+ return (
113
+ <div className="hero-container">
114
+ <div className="hero-section">
115
+ {dummyItems.map((item, index) => (
116
+ <div
117
+ key={index}
118
+ className={`hero-image ${index === currentIndex ? 'active' : ''} ${fadeOut ? 'fade-out' : ''}`}
119
+ style={{ backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.1) 0%, #11121f 100%), url("${item.imageUrl}")` }}
120
+ ></div>
121
+ ))}
122
+ <div className="hero-text">
123
+ <h1 className="hero-title">{title}</h1>
124
+ <h2 className="hero-description">{description}</h2>
125
+ </div>
126
+ </div>
127
+
128
+ <div className="hero-indicators">
129
+ {dummyItems.map((_, index) => (
130
+ <div
131
+ key={index}
132
+ className={`indicator ${index === currentIndex ? 'active' : ''}`}
133
+ onClick={() => handleIndicatorClick(index)}
134
+ ></div>
135
+ ))}
136
+ </div>
137
+ </div>
138
+ );
139
+ };
140
+
141
+ export default HeroSection;
frontend/src/components/Navbar.css DELETED
@@ -1,89 +0,0 @@
1
- /* Container for the navbar and underline */
2
- nav {
3
- position: relative;
4
- }
5
-
6
- .nav-links {
7
- list-style: none;
8
- padding: 0;
9
- margin: 0;
10
- display: flex;
11
- justify-content: center;
12
- position: relative; /* Ensure it's positioned relative for absolute positioning of underlines */
13
- }
14
-
15
- @import url('https://fonts.googleapis.com/css2?family=Pacifico&family=Rubik+Burned&family=Rubik+Marker+Hatch&family=Rubik+Maze&family=Rubik+Microbe&family=Rubik:ital,wght@0,300..900;1,300..900&display=swap');
16
-
17
- .nav-link {
18
- text-decoration: none;
19
- color: #b0b0b0;
20
- display: flex;
21
- align-items: center;
22
- justify-content: center;
23
- width: 70px;
24
- height: 50px;
25
- position: relative;
26
- font-size: 1em;
27
- font-family: "Signika", sans-serif;
28
- font-optical-sizing: auto;
29
- font-style: normal;
30
- font-variation-settings: "GRAD" 0;
31
- font-weight: 600;
32
- padding: 0 15px;
33
- transition: color 0.3s ease, transform 0.3s ease;
34
- box-sizing: border-box;
35
- }
36
-
37
- .nav-link-menue {
38
- text-decoration: none;
39
- color: #b0b0b0;
40
- display: flex;
41
- align-items: center;
42
- justify-content: center;
43
- position: relative;
44
- padding: 11px 10px;
45
- transition: color 0.3s ease, transform 0.3s ease;
46
- box-sizing: border-box;
47
- }
48
-
49
- .nav-link-menue.active {
50
- color: #ffffff;
51
- }
52
-
53
- .nav-link-menue:hover {
54
- color: #ffffff;
55
- transform: translateY(-2px);
56
- }
57
-
58
- .nav-link.active {
59
- color: #ffffff;
60
- }
61
-
62
- .nav-link:hover {
63
- color: #ffffff;
64
- transform: translateY(-2px);
65
- }
66
-
67
- .underline {
68
- position: absolute;
69
- bottom: -3px; /* Adjust this to position the underline correctly at the bottom of the navbar */
70
- height: 3px;
71
- transition: width 0.3s ease, left 0.3s ease;
72
- }
73
-
74
- .active-underline {
75
- background-color: #e88f36; /* Warm orange underline for active route */
76
- }
77
-
78
- .hover-underline {
79
- background-color: #007bc7; /* Bright blue underline for hover effect */
80
- }
81
-
82
- /* Media Queries for Mobile Devices */
83
- @media (max-width: 768px) {
84
- .nav-link {
85
- width: 70px;
86
- padding: 10px;
87
- }
88
- }
89
-
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/src/components/Sidebar.css ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .sidebar {
2
+ display: flex;
3
+ flex-direction: column;
4
+ position: fixed;
5
+ top: 0;
6
+ left: 0;
7
+ height: 100vh;
8
+ background-color: #0c0c16;
9
+ color: white;
10
+ font-family: 'Inter', sans-serif;
11
+ transition: width 0.3s;
12
+ z-index: 1000;
13
+ }
14
+
15
+ .sidebar-content {
16
+ display: flex;
17
+ flex-direction: column;
18
+ flex: 1;
19
+ }
20
+
21
+ .sidebar.open {
22
+ width: 320px;
23
+ }
24
+
25
+ .sidebar.closed {
26
+ width: 100px;
27
+ height: 1px;
28
+ }
29
+
30
+ .sidebar-header {
31
+ display: flex;
32
+ align-items: center;
33
+ padding-top: 20px;
34
+ padding-left: 20px;
35
+ }
36
+
37
+ .sidebar-toggle {
38
+ background: none;
39
+ border: none;
40
+ color: white;
41
+ font-size: 1.5rem;
42
+ cursor: pointer;
43
+ }
44
+
45
+ .sidebar-title {
46
+ font-size: 1.25rem;
47
+ margin-left: 16px;
48
+ white-space: nowrap;
49
+ }
50
+
51
+ .sidebar-menu {
52
+ margin-top: 16px;
53
+ flex: 1;
54
+ }
55
+
56
+ .sidebar-link {
57
+ text-decoration: none;
58
+ color: #b0b0b0;
59
+ display: flex;
60
+ align-items: center;
61
+ padding: 8px 16px;
62
+ border-radius: 8px;
63
+ margin-bottom: 8px;
64
+ margin-left: 10px;
65
+ margin-right: 10px;
66
+ background-color: #161527;
67
+ cursor: pointer;
68
+ white-space: nowrap;
69
+ position: relative;
70
+ transition: color 0.3s ease, transform 0.3s ease;
71
+ }
72
+
73
+ .sidebar-link.active {
74
+ color: #ffffff;
75
+ background-color: #21264a;
76
+ }
77
+
78
+ .sidebar-link:hover {
79
+ color: #ffffff;
80
+ transform: translateY(-2px);
81
+ }
82
+
83
+ .sidebar-footer {
84
+ padding: 16px;
85
+ }
86
+
87
+ .sidebar-item {
88
+ display: flex;
89
+ align-items: center;
90
+ padding: 8px 16px;
91
+ border-radius: 8px;
92
+ cursor: pointer;
93
+ white-space: nowrap;
94
+ }
95
+
96
+ .sidebar-item svg {
97
+ margin-right: 15px;
98
+ }
99
+
100
+ .sidebar-item-text {
101
+ font-size: 0.875rem;
102
+ font-weight: 500;
103
+ }
frontend/src/components/{Navbar.js → Sidebar.js} RENAMED
@@ -1,36 +1,32 @@
1
  "use client";
2
- import { useEffect, useState } from "react";
3
- import { usePathname } from "next/navigation";
4
  import Link from "next/link";
 
 
5
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
- import { faHome, faMagnifyingGlass, faFilm, faTv, faCaretDown } from "@fortawesome/free-solid-svg-icons";
7
- import "./Navbar.css"; // Ensure CSS is in the correct location
8
 
9
- function Navbar() {
10
- const pathname = usePathname(); // Use Next.js usePathname
 
11
  const [hoveredLink, setHoveredLink] = useState(null);
12
  const [prevLink, setPrevLink] = useState(null);
13
- const [isModalOpen, setIsModalOpen] = useState(false);
14
-
15
- const handleModalClose = () => {
16
- setIsModalOpen(false);
17
- };
18
-
19
- const handleModalOpen = () => {
20
- setIsModalOpen(!isModalOpen);
21
- };
22
 
23
  useEffect(() => {
24
  const activeLink = document.querySelector(
25
- `.nav-link[href="${pathname}"]`
26
  );
27
  if (activeLink) {
28
  setPrevLink(activeLink);
29
  }
30
  }, [pathname]);
31
 
 
 
 
 
32
  const handleMouseEnter = (e) => {
33
- setPrevLink(document.querySelector(".nav-link.active"));
34
  setHoveredLink(e.target);
35
  };
36
 
@@ -39,81 +35,77 @@ function Navbar() {
39
  };
40
 
41
  return (
42
- <nav>
43
- <ul className="nav-links">
44
- <li>
 
 
 
 
 
 
 
45
  <Link
46
  href="/"
47
- className={`nav-link ${pathname === "/" ? "active" : ""}`}
48
  onMouseEnter={handleMouseEnter}
49
  onMouseLeave={handleMouseLeave}
50
  >
51
- <FontAwesomeIcon icon={faHome} size="lg" />
52
  </Link>
53
- </li>
54
- <li>
55
  <Link
56
- href="/search"
57
- className={`nav-link ${pathname === "/search" ? "active" : ""}`}
58
  onMouseEnter={handleMouseEnter}
59
  onMouseLeave={handleMouseLeave}
60
  >
61
- <FontAwesomeIcon icon={faMagnifyingGlass} size="lg" />
62
  </Link>
63
- </li>
64
- <li>
65
  <Link
66
- href="/films"
67
- className={`nav-link ${pathname === "/films" ? "active" : ""}`}
 
 
68
  onMouseEnter={handleMouseEnter}
69
  onMouseLeave={handleMouseLeave}
70
  >
71
- <FontAwesomeIcon icon={faFilm} size="lg" />
72
  </Link>
73
- </li>
74
- <li>
75
  <Link
76
- href="/tvshows"
77
- className={`nav-link ${pathname === "/tvshows" ? "active" : ""}`}
 
 
 
 
 
 
 
 
78
  onMouseEnter={handleMouseEnter}
79
  onMouseLeave={handleMouseLeave}
80
  >
81
- <FontAwesomeIcon icon={faTv} size="lg" />
82
  </Link>
83
- </li>
84
- <li>
85
- <FontAwesomeIcon
86
- className="nav-link-menue"
87
- icon={faCaretDown}
88
- size="xl"
89
- onClick={handleModalOpen}
90
- />
91
- </li>
92
- </ul>
93
- <span
94
- className="underline active-underline"
95
- style={
96
- prevLink
97
- ? {
98
- width: prevLink.offsetWidth,
99
- left: prevLink.offsetLeft,
100
- }
101
- : {}
102
- }
103
- />
104
- <span
105
- className="underline hover-underline"
106
- style={
107
- hoveredLink
108
- ? {
109
- width: hoveredLink.offsetWidth,
110
- left: hoveredLink.offsetLeft,
111
- }
112
- : {}
113
- }
114
- />
115
- </nav>
116
  );
117
- }
118
 
119
- export default Navbar;
 
1
  "use client";
2
+ import React, { useState, useEffect } from "react";
 
3
  import Link from "next/link";
4
+ import { usePathname } from "next/navigation";
5
+ import "./Sidebar.css";
6
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
7
+ import { faBars, faCogs, faHome, faStar, faTv, faFilm, faBookBookmark } from "@fortawesome/free-solid-svg-icons";
 
8
 
9
+ const Sidebar = () => {
10
+ const [isOpen, setIsOpen] = useState(false);
11
+ const pathname = usePathname();
12
  const [hoveredLink, setHoveredLink] = useState(null);
13
  const [prevLink, setPrevLink] = useState(null);
 
 
 
 
 
 
 
 
 
14
 
15
  useEffect(() => {
16
  const activeLink = document.querySelector(
17
+ `.sidebar-link[href="${pathname}"]`
18
  );
19
  if (activeLink) {
20
  setPrevLink(activeLink);
21
  }
22
  }, [pathname]);
23
 
24
+ const toggleSidebar = () => {
25
+ setIsOpen(!isOpen);
26
+ };
27
+
28
  const handleMouseEnter = (e) => {
29
+ setPrevLink(document.querySelector(".sidebar-link.active"));
30
  setHoveredLink(e.target);
31
  };
32
 
 
35
  };
36
 
37
  return (
38
+ <div className={`sidebar ${isOpen ? "open" : "closed"}`}>
39
+ <div className="sidebar-header">
40
+ <button className="sidebar-toggle" onClick={toggleSidebar}>
41
+ <FontAwesomeIcon icon={faBars} size="sm" />
42
+ </button>
43
+ {isOpen && <h1 className="sidebar-title">Streamz</h1>}
44
+ </div>
45
+ <div className="sidebar-content">
46
+ {isOpen && (
47
+ <div className="sidebar-menu">
48
  <Link
49
  href="/"
50
+ className={`sidebar-link ${pathname === "/" ? "active" : ""}`}
51
  onMouseEnter={handleMouseEnter}
52
  onMouseLeave={handleMouseLeave}
53
  >
54
+ <SidebarItem icon={faHome} text="Home" />
55
  </Link>
 
 
56
  <Link
57
+ href="/films"
58
+ className={`sidebar-link ${pathname === "/films" ? "active" : ""}`}
59
  onMouseEnter={handleMouseEnter}
60
  onMouseLeave={handleMouseLeave}
61
  >
62
+ <SidebarItem icon={faFilm} text="Movies" />
63
  </Link>
 
 
64
  <Link
65
+ href="/tvshows"
66
+ className={`sidebar-link ${
67
+ pathname === "/tvshows" ? "active" : ""
68
+ }`}
69
  onMouseEnter={handleMouseEnter}
70
  onMouseLeave={handleMouseLeave}
71
  >
72
+ <SidebarItem icon={faTv} text="Series" />
73
  </Link>
 
 
74
  <Link
75
+ href="/new"
76
+ className={`sidebar-link ${pathname === "/new" ? "active" : ""}`}
77
+ onMouseEnter={handleMouseEnter}
78
+ onMouseLeave={handleMouseLeave}
79
+ >
80
+ <SidebarItem icon={faStar} text="New" />
81
+ </Link>
82
+ <Link
83
+ href="/mylist"
84
+ className={`sidebar-link ${pathname === "/mylist" ? "active" : ""}`}
85
  onMouseEnter={handleMouseEnter}
86
  onMouseLeave={handleMouseLeave}
87
  >
88
+ <SidebarItem icon={faBookBookmark} text="My List" />
89
  </Link>
90
+ </div>
91
+ )}
92
+ {isOpen && (
93
+ <div className="sidebar-footer">
94
+ <SidebarItem icon={faCogs} text="Settings" />
95
+ </div>
96
+ )}
97
+ </div>
98
+ </div>
99
+ );
100
+ };
101
+
102
+ const SidebarItem = ({ icon, text }) => {
103
+ return (
104
+ <div className="sidebar-item">
105
+ <FontAwesomeIcon icon={icon} size="lg" />
106
+ <p className="sidebar-item-text">{text}</p>
107
+ </div>
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
  );
109
+ };
110
 
111
+ export default Sidebar;