ChandimaPrabath commited on
Commit
0504ed2
1 Parent(s): 7a9a628

css and player

Browse files
frontend/src/app/genres/[genre]/genres.css CHANGED
@@ -34,28 +34,28 @@ body {
34
  }
35
 
36
  /* Horizontal scrolling container */
37
- .items-grid {
38
  display: flex;
39
  overflow-x: auto;
40
  padding: 10px 0;
41
  gap: 20px;
42
  }
43
 
44
- .items-grid::-webkit-scrollbar {
45
  height: 8px;
46
  }
47
 
48
- .items-grid::-webkit-scrollbar-thumb {
49
  background-color: #3c23cf;
50
  border-radius: 4px;
51
  }
52
 
53
- .items-grid::-webkit-scrollbar-track {
54
  background-color: #2c2c2c;
55
  }
56
 
57
  /* Card for each item */
58
- .item-card {
59
  background-color: #1d1f2d; /* Dark card background */
60
  border-radius: 8px;
61
  overflow: hidden;
@@ -64,19 +64,19 @@ body {
64
  flex: 0 0 200px; /* Fixed width for horizontal scrolling */
65
  }
66
 
67
- .item-card:hover {
68
  transform: scale(1.03);
69
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.7);
70
  }
71
 
72
  /* Styling for item link */
73
- .item-link {
74
  display: block;
75
  text-decoration: none;
76
  color: inherit;
77
  }
78
 
79
- .item-image {
80
  width: 100%;
81
  height: 100px; /* Fixed height for consistency */
82
  object-fit: cover; /* Maintain aspect ratio and fill container */
@@ -84,11 +84,11 @@ body {
84
  }
85
 
86
  /* Item information */
87
- .item-info {
88
  padding: 5px;
89
  }
90
 
91
- .item-title {
92
  font-size: 1rem;
93
  font-weight: bold;
94
  margin: 0;
@@ -98,7 +98,7 @@ body {
98
  text-overflow: ellipsis; /* Handle overflow with ellipsis */
99
  }
100
 
101
- .item-description {
102
  font-size: 0.9rem;
103
  color: #b0b0b0; /* Lighter gray for descriptions */
104
  margin: 5px 0 0;
@@ -160,37 +160,37 @@ body {
160
  outline: none;
161
  }
162
 
163
- .section-controls {
164
  display: flex;
165
  align-items: center;
166
  text-align: center;
167
  justify-content: space-between;
168
  }
169
 
170
- .scroll-controls button {
171
  margin-left: 10px;
172
  margin-right: 10px;
173
  }
174
 
175
- .filter-button {
176
  margin-right: 10px;
177
  }
178
- .bubbles-scroll-section{
179
  display: flex;
180
  overflow-x: auto;
181
  width: 100%;
182
  }
183
 
184
- .bubbles-scroll-section::-webkit-scrollbar {
185
  height: 8px;
186
  }
187
 
188
- .bubbles-scroll-section::-webkit-scrollbar-thumb {
189
  background-color: #3c23cf;
190
  border-radius: 4px;
191
  }
192
 
193
- .bubbles-scroll-section::-webkit-scrollbar-track {
194
  background-color: #2c2c2c;
195
  }
196
 
@@ -213,7 +213,7 @@ body {
213
  border: 1px solid #4339ff;
214
  }
215
 
216
- .bubble-close-button {
217
  font-size: 15px;
218
  cursor: pointer;
219
  padding: 2px;
 
34
  }
35
 
36
  /* Horizontal scrolling container */
37
+ .genre-items-grid {
38
  display: flex;
39
  overflow-x: auto;
40
  padding: 10px 0;
41
  gap: 20px;
42
  }
43
 
44
+ .genre-items-grid::-webkit-scrollbar {
45
  height: 8px;
46
  }
47
 
48
+ .genre-items-grid::-webkit-scrollbar-thumb {
49
  background-color: #3c23cf;
50
  border-radius: 4px;
51
  }
52
 
53
+ .genre-items-grid::-webkit-scrollbar-track {
54
  background-color: #2c2c2c;
55
  }
56
 
57
  /* Card for each item */
58
+ .genre-item-card {
59
  background-color: #1d1f2d; /* Dark card background */
60
  border-radius: 8px;
61
  overflow: hidden;
 
64
  flex: 0 0 200px; /* Fixed width for horizontal scrolling */
65
  }
66
 
67
+ .genre-item-card:hover {
68
  transform: scale(1.03);
69
  box-shadow: 0 4px 8px rgba(0, 0, 0, 0.7);
70
  }
71
 
72
  /* Styling for item link */
73
+ .genre-item-link {
74
  display: block;
75
  text-decoration: none;
76
  color: inherit;
77
  }
78
 
79
+ .genre-item-image {
80
  width: 100%;
81
  height: 100px; /* Fixed height for consistency */
82
  object-fit: cover; /* Maintain aspect ratio and fill container */
 
84
  }
85
 
86
  /* Item information */
87
+ .genre-item-info {
88
  padding: 5px;
89
  }
90
 
91
+ .genre-item-title {
92
  font-size: 1rem;
93
  font-weight: bold;
94
  margin: 0;
 
98
  text-overflow: ellipsis; /* Handle overflow with ellipsis */
99
  }
100
 
101
+ .genre-item-description {
102
  font-size: 0.9rem;
103
  color: #b0b0b0; /* Lighter gray for descriptions */
104
  margin: 5px 0 0;
 
160
  outline: none;
161
  }
162
 
163
+ .genre-section-controls {
164
  display: flex;
165
  align-items: center;
166
  text-align: center;
167
  justify-content: space-between;
168
  }
169
 
170
+ .genre-scroll-controls button {
171
  margin-left: 10px;
172
  margin-right: 10px;
173
  }
174
 
175
+ .genre-filter-button {
176
  margin-right: 10px;
177
  }
178
+ .genre-bubbles-scroll-section{
179
  display: flex;
180
  overflow-x: auto;
181
  width: 100%;
182
  }
183
 
184
+ .genre-bubbles-scroll-section::-webkit-scrollbar {
185
  height: 8px;
186
  }
187
 
188
+ .genre-bubbles-scroll-section::-webkit-scrollbar-thumb {
189
  background-color: #3c23cf;
190
  border-radius: 4px;
191
  }
192
 
193
+ .genre-bubbles-scroll-section::-webkit-scrollbar-track {
194
  background-color: #2c2c2c;
195
  }
196
 
 
213
  border: 1px solid #4339ff;
214
  }
215
 
216
+ .genre-bubble-close-button {
217
  font-size: 15px;
218
  cursor: pointer;
219
  padding: 2px;
frontend/src/app/genres/[genre]/page.js CHANGED
@@ -89,16 +89,16 @@ export default function GenrePage({ params }) {
89
  <div className="genre-page">
90
  <div className="genre-title-section"></div>
91
  <div className="genre-bubbles">
92
- <button className="filter-button" onClick={openModal}>
93
  <FontAwesomeIcon icon={faFilter} size="sm" />
94
  </button>
95
- <div className="bubbles-scroll-section">
96
  {selectedGenres.size > 0
97
  ? Array.from(selectedGenres).map((genre, index) => (
98
  <div key={index} className="bubbles">
99
  {genre}
100
  <button
101
- className="bubble-close-button"
102
  onClick={() => removeGenre(genre)}
103
  >
104
  <FontAwesomeIcon icon={faXmark} size="sm" />
@@ -118,49 +118,49 @@ export default function GenrePage({ params }) {
118
  {genreItems && (
119
  <>
120
  {genreItems.movies && genreItems.movies.length > 0 && (
121
- <section className="section movies">
122
- <div className="section-controls">
123
  <h2>Movies</h2>
124
  <div className="load-more-container">
125
  <button className="load-more-button" onClick={loadMore}>
126
  Load More
127
  </button>
128
  </div>
129
- <div className="scroll-controls">
130
  <button
131
  onClick={() => scroll(moviesRef, "left")}
132
- className="scroll-button"
133
  >
134
  <FontAwesomeIcon icon={faCaretLeft} size="2xl" />
135
  </button>
136
  <button
137
  onClick={() => scroll(moviesRef, "right")}
138
- className="scroll-button"
139
  >
140
  <FontAwesomeIcon icon={faCaretRight} size="2xl" />
141
  </button>
142
  </div>
143
  </div>
144
- <div className="items-grid" ref={moviesRef}>
145
  {genreItems.movies.map((item, index) => (
146
- <div key={index} className="item-card">
147
  <Link href={`/movie/${item[0]}`} passHref>
148
- <div className="item-link">
149
  <Image
150
  src={
151
  item[3] ||
152
- `https://via.placeholder.com/400x100/1a1c3f/FFF?text=${encodeURIComponent(
153
  item[0]
154
  )}`
155
  }
156
  alt={item[0]}
157
- className="item-image"
158
- height={120}
159
- width={250}
160
  />
161
- <div className="item-info">
162
- <h3 className="item-title">{item[0]}</h3>
163
- <p className="item-description">{item[2]}</p>
164
  </div>
165
  </div>
166
  </Link>
@@ -171,44 +171,44 @@ export default function GenrePage({ params }) {
171
  )}
172
 
173
  {genreItems.series && genreItems.series.length > 0 && (
174
- <section className="section series">
175
- <div className="section-controls">
176
  <h2>TV Shows</h2>
177
- <div className="scroll-controls">
178
  <button
179
  onClick={() => scroll(seriesRef, "left")}
180
- className="scroll-button"
181
  >
182
  <FontAwesomeIcon icon={faCaretLeft} size="2xl" />
183
  </button>
184
  <button
185
  onClick={() => scroll(seriesRef, "right")}
186
- className="scroll-button"
187
  >
188
  <FontAwesomeIcon icon={faCaretRight} size="2xl" />
189
  </button>
190
  </div>
191
  </div>
192
- <div className="items-grid" ref={seriesRef}>
193
  {genreItems.series.map((item, index) => (
194
- <div key={index} className="item-card">
195
  <Link href={`/series/${item[0]}`} passHref>
196
- <div className="item-link">
197
  <Image
198
  src={
199
  item[3] ||
200
- `https://via.placeholder.com/150?text=${encodeURIComponent(
201
  item[0]
202
  )}`
203
  }
204
  alt={item[0]}
205
- className="item-image"
206
- width={250}
207
- height={120}
208
  />
209
- <div className="item-info">
210
- <h3 className="item-title">{item[0]}</h3>
211
- <p className="item-description">{item[2]}</p>
212
  </div>
213
  </div>
214
  </Link>
@@ -222,7 +222,7 @@ export default function GenrePage({ params }) {
222
 
223
  {(!genreItems ||
224
  (genreItems.movies.length === 0 && genreItems.series.length === 0)) && (
225
- <p className="no-items">
226
  {selectedGenres.size === 0
227
  ? "Please select a genre to see results."
228
  : "No items available for the selected genres."}
 
89
  <div className="genre-page">
90
  <div className="genre-title-section"></div>
91
  <div className="genre-bubbles">
92
+ <button className="genre-filter-button" onClick={openModal}>
93
  <FontAwesomeIcon icon={faFilter} size="sm" />
94
  </button>
95
+ <div className="genre-bubbles-scroll-section">
96
  {selectedGenres.size > 0
97
  ? Array.from(selectedGenres).map((genre, index) => (
98
  <div key={index} className="bubbles">
99
  {genre}
100
  <button
101
+ className="genre-bubble-close-button"
102
  onClick={() => removeGenre(genre)}
103
  >
104
  <FontAwesomeIcon icon={faXmark} size="sm" />
 
118
  {genreItems && (
119
  <>
120
  {genreItems.movies && genreItems.movies.length > 0 && (
121
+ <section className="genre-section movies">
122
+ <div className="genre-section-controls">
123
  <h2>Movies</h2>
124
  <div className="load-more-container">
125
  <button className="load-more-button" onClick={loadMore}>
126
  Load More
127
  </button>
128
  </div>
129
+ <div className="genre-scroll-controls">
130
  <button
131
  onClick={() => scroll(moviesRef, "left")}
132
+ className="genre-scroll-button"
133
  >
134
  <FontAwesomeIcon icon={faCaretLeft} size="2xl" />
135
  </button>
136
  <button
137
  onClick={() => scroll(moviesRef, "right")}
138
+ className="genre-scroll-button"
139
  >
140
  <FontAwesomeIcon icon={faCaretRight} size="2xl" />
141
  </button>
142
  </div>
143
  </div>
144
+ <div className="genre-items-grid" ref={moviesRef}>
145
  {genreItems.movies.map((item, index) => (
146
+ <div key={index} className="genre-item-card">
147
  <Link href={`/movie/${item[0]}`} passHref>
148
+ <div className="genre-item-link">
149
  <Image
150
  src={
151
  item[3] ||
152
+ `https://via.placeholder.com/300x80/1a1c3f/FFF?text=${encodeURIComponent(
153
  item[0]
154
  )}`
155
  }
156
  alt={item[0]}
157
+ className="genre-item-image"
158
+ height={80}
159
+ width={300}
160
  />
161
+ <div className="genre-item-info">
162
+ <h3 className="genre-item-title">{item[0]}</h3>
163
+ <p className="genre-item-description">{item[2]}</p>
164
  </div>
165
  </div>
166
  </Link>
 
171
  )}
172
 
173
  {genreItems.series && genreItems.series.length > 0 && (
174
+ <section className="genre-section series">
175
+ <div className="genre-section-controls">
176
  <h2>TV Shows</h2>
177
+ <div className="genre-scroll-controls">
178
  <button
179
  onClick={() => scroll(seriesRef, "left")}
180
+ className="genre-scroll-button"
181
  >
182
  <FontAwesomeIcon icon={faCaretLeft} size="2xl" />
183
  </button>
184
  <button
185
  onClick={() => scroll(seriesRef, "right")}
186
+ className="genre-scroll-button"
187
  >
188
  <FontAwesomeIcon icon={faCaretRight} size="2xl" />
189
  </button>
190
  </div>
191
  </div>
192
+ <div className="genre-items-grid" ref={seriesRef}>
193
  {genreItems.series.map((item, index) => (
194
+ <div key={index} className="genre-item-card">
195
  <Link href={`/series/${item[0]}`} passHref>
196
+ <div className="genre-item-link">
197
  <Image
198
  src={
199
  item[3] ||
200
+ `https://via.placeholder.com/300x80?text=${encodeURIComponent(
201
  item[0]
202
  )}`
203
  }
204
  alt={item[0]}
205
+ className="genre-item-image"
206
+ width={300}
207
+ height={80}
208
  />
209
+ <div className="genre-item-info">
210
+ <h3 className="genre-item-title">{item[0]}</h3>
211
+ <p className="genre-item-description">{item[2]}</p>
212
  </div>
213
  </div>
214
  </Link>
 
222
 
223
  {(!genreItems ||
224
  (genreItems.movies.length === 0 && genreItems.series.length === 0)) && (
225
+ <p className="genre-no-items">
226
  {selectedGenres.size === 0
227
  ? "Please select a genre to see results."
228
  : "No items available for the selected genres."}
frontend/src/app/movie/[title]/movie.css CHANGED
@@ -187,13 +187,13 @@
187
  }
188
  }
189
 
190
- .geners-section {
191
  display: flex;
192
  text-align: center;
193
  align-items: center;
194
  }
195
 
196
- .genre-list {
197
  list-style-type: none;
198
  padding: 0;
199
  display: flex;
@@ -202,17 +202,17 @@
202
  align-items: center;
203
  }
204
 
205
- .genre-item {
206
  margin: 5px;
207
  }
208
 
209
- .genre-link {
210
  text-decoration: none;
211
  color: #0082f3; /* Next.js blue color */
212
  font-weight: bold;
213
  }
214
 
215
- .genre-link:hover {
216
  text-decoration: underline;
217
  }
218
 
 
187
  }
188
  }
189
 
190
+ .movie-geners-section {
191
  display: flex;
192
  text-align: center;
193
  align-items: center;
194
  }
195
 
196
+ .movie-genre-list {
197
  list-style-type: none;
198
  padding: 0;
199
  display: flex;
 
202
  align-items: center;
203
  }
204
 
205
+ .movie-genre-item {
206
  margin: 5px;
207
  }
208
 
209
+ .movie-genre-link {
210
  text-decoration: none;
211
  color: #0082f3; /* Next.js blue color */
212
  font-weight: bold;
213
  }
214
 
215
+ .movie-genre-link:hover {
216
  text-decoration: underline;
217
  }
218
 
frontend/src/app/movie/[title]/page.js CHANGED
@@ -109,14 +109,14 @@ export default function MovieDetailsPage({ params }) {
109
  </div>
110
  <div className="movie-details-info">
111
  <div className="movie-details-metadata">
112
- <label className="geners-section">
113
  <strong>Genre:</strong>{" "}
114
  {genres.length > 0 ? (
115
- <ul className="genre-list">
116
  {genres.map((genre) => (
117
- <li key={genre.id} className="genre-item">
118
  <Link href={`/genres/${genre.name}`} passHref>
119
- <label className="genre-link">{genre.name}</label>
120
  </Link>
121
  </li>
122
  ))}
 
109
  </div>
110
  <div className="movie-details-info">
111
  <div className="movie-details-metadata">
112
+ <label className="movie-geners-section">
113
  <strong>Genre:</strong>{" "}
114
  {genres.length > 0 ? (
115
+ <ul className="movie-genre-list">
116
  {genres.map((genre) => (
117
+ <li key={genre.id} className="movie-genre-item">
118
  <Link href={`/genres/${genre.name}`} passHref>
119
+ <label className="movie-genre-link">{genre.name}</label>
120
  </Link>
121
  </li>
122
  ))}
frontend/src/components/CastSection.css CHANGED
@@ -1,38 +1,40 @@
1
- .cast-section {
2
- /* Your styles here */
3
- }
4
-
5
- .cast-list {
6
- list-style: none;
7
- padding: 0;
8
- display: flex;
9
- flex-wrap: wrap;
10
- gap: 10px; /* Add space between items */
11
- }
12
-
13
- .cast-item {
14
- margin: 0;
15
- text-align: center;
16
- width: 100px;
17
- }
18
-
19
- .cast-image-container {
20
- position: relative;
21
- width: 100px;
22
- height: 100px;
23
- border-radius: 50%; /* Circular container */
24
- overflow: hidden;
25
- }
26
-
27
- .cast-image {
28
- border-radius: 50%; /* Circular images */
29
- object-position: top;
30
- }
31
-
32
- .cast-name {
33
- display: block;
34
- margin-top: 8px;
35
- font-weight: bold; /* Highlight the actor's name */
36
- text-overflow: clip;
37
- }
38
-
 
 
 
1
+ .cast-section h2 {
2
+ margin-bottom: 15px;
3
+ font-size: 1.5rem;
4
+ border-bottom: 2px solid #4339ff;
5
+ padding-bottom: 5px;
6
+ }
7
+
8
+ .cast-list {
9
+ list-style: none;
10
+ padding: 0;
11
+ display: flex;
12
+ flex-wrap: wrap;
13
+ gap: 15px; /* Adjusted space between items */
14
+ }
15
+
16
+ .cast-item {
17
+ margin: 0;
18
+ display: flex; /* Use flex to align image and text */
19
+ align-items: center; /* Center vertically */
20
+ width: auto; /* Allow dynamic width */
21
+ }
22
+
23
+ .cast-image-container {
24
+ position: relative;
25
+ width: 100px;
26
+ height: 100px;
27
+ border-radius: 50%; /* Circular container */
28
+ overflow: hidden;
29
+ margin-right: 10px; /* Space between image and text */
30
+ }
31
+
32
+ .cast-image {
33
+ border-radius: 50%; /* Circular images */
34
+ object-position: top;
35
+ }
36
+
37
+ .cast-name {
38
+ font-weight: bold; /* Highlight the actor's name */
39
+ text-overflow: clip;
40
+ }
frontend/src/components/CastSection.js CHANGED
@@ -4,7 +4,7 @@ import './CastSection.css';
4
  const CastSection = ({ cast }) => {
5
  return (
6
  <div className="cast-section">
7
- <strong>Cast:</strong>
8
  {cast.length > 0 ? (
9
  <ul className="cast-list">
10
  {cast.map((profile) => (
 
4
  const CastSection = ({ cast }) => {
5
  return (
6
  <div className="cast-section">
7
+ <h2>Cast</h2>
8
  {cast.length > 0 ? (
9
  <ul className="cast-list">
10
  {cast.map((profile) => (
frontend/src/components/MoviePlayer.js CHANGED
@@ -1,10 +1,9 @@
1
  "use client";
2
  import { useEffect, useRef, useState } from "react";
 
3
  import "./MoviePlayer.css";
4
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
5
  import {
6
- faFastBackward,
7
- faFastForward,
8
  faPause,
9
  faPlay,
10
  faVolumeUp,
@@ -12,13 +11,15 @@ import {
12
  faExpand,
13
  faDownload,
14
  faArrowLeft,
15
- faCaretLeft,
16
- faAngleLeft,
 
17
  } from "@fortawesome/free-solid-svg-icons";
18
  import { Spinner } from "@/components/Spinner";
19
  import SeekableProgressBar from "./SeekableProgressBar";
20
 
21
  export default function MoviePlayer({ videoUrl, title }) {
 
22
  const videoRef = useRef(null);
23
  const [isPlaying, setIsPlaying] = useState(false);
24
  const [volume, setVolume] = useState(1);
@@ -195,10 +196,19 @@ export default function MoviePlayer({ videoUrl, title }) {
195
  }
196
  };
197
 
 
 
 
 
198
  return (
199
  <div className="video-player-container" onMouseMove={handleMouseMove} onContextMenu={handleContextMenu}>
200
  <div className={`player-overlay ${showControls ? "show" : "hide"}`}>
201
- <h2 className="video-title"><div className="control-btn"><FontAwesomeIcon icon={faAngleLeft} size="lg"/></div>{title}</h2>
 
 
 
 
 
202
  <div className="controls">
203
  <div className="player-controls-top">
204
  <label className="current-time">{formatTime(videoRef?.current?.currentTime)}</label>
@@ -210,9 +220,8 @@ export default function MoviePlayer({ videoUrl, title }) {
210
  <button
211
  onClick={handleRewind}
212
  className="control-btn"
213
- disabled={!isPlaying}
214
  >
215
- <FontAwesomeIcon icon={faFastBackward} size="xl" />
216
  </button>
217
  <button onClick={togglePlayPause} className="play-pause-btn">
218
  {isPlaying ? (
@@ -224,9 +233,8 @@ export default function MoviePlayer({ videoUrl, title }) {
224
  <button
225
  onClick={handleFastForward}
226
  className="control-btn"
227
- disabled={!isPlaying}
228
  >
229
- <FontAwesomeIcon icon={faFastForward} size="xl" />
230
  </button>
231
  </div>
232
  <div className="player-controls-right">
@@ -246,7 +254,7 @@ export default function MoviePlayer({ videoUrl, title }) {
246
  onChange={handleVolumeChange}
247
  />
248
  <button onClick={toggleFullscreen} className="control-btn">
249
- <FontAwesomeIcon icon={faExpand} size="xl" />
250
  </button>
251
  {videoUrl && (
252
  <a href={videoUrl} download className="control-btn">
 
1
  "use client";
2
  import { useEffect, useRef, useState } from "react";
3
+ import { useRouter } from "next/navigation";
4
  import "./MoviePlayer.css";
5
  import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
6
  import {
 
 
7
  faPause,
8
  faPlay,
9
  faVolumeUp,
 
11
  faExpand,
12
  faDownload,
13
  faArrowLeft,
14
+ faAngleDoubleRight,
15
+ faAngleDoubleLeft,
16
+ faCompress,
17
  } from "@fortawesome/free-solid-svg-icons";
18
  import { Spinner } from "@/components/Spinner";
19
  import SeekableProgressBar from "./SeekableProgressBar";
20
 
21
  export default function MoviePlayer({ videoUrl, title }) {
22
+ const router = useRouter();
23
  const videoRef = useRef(null);
24
  const [isPlaying, setIsPlaying] = useState(false);
25
  const [volume, setVolume] = useState(1);
 
196
  }
197
  };
198
 
199
+ const handleExitClick = () => {
200
+ router.back();
201
+ };
202
+
203
  return (
204
  <div className="video-player-container" onMouseMove={handleMouseMove} onContextMenu={handleContextMenu}>
205
  <div className={`player-overlay ${showControls ? "show" : "hide"}`}>
206
+ <h2 className="video-title">
207
+ <div className="control-btn player-exit" onClick={handleExitClick}>
208
+ <FontAwesomeIcon icon={faArrowLeft} size="lg" />
209
+ </div>
210
+ {title}
211
+ </h2>
212
  <div className="controls">
213
  <div className="player-controls-top">
214
  <label className="current-time">{formatTime(videoRef?.current?.currentTime)}</label>
 
220
  <button
221
  onClick={handleRewind}
222
  className="control-btn"
 
223
  >
224
+ <FontAwesomeIcon icon={faAngleDoubleLeft} size="xl" />
225
  </button>
226
  <button onClick={togglePlayPause} className="play-pause-btn">
227
  {isPlaying ? (
 
233
  <button
234
  onClick={handleFastForward}
235
  className="control-btn"
 
236
  >
237
+ <FontAwesomeIcon icon={faAngleDoubleRight} size="xl" />
238
  </button>
239
  </div>
240
  <div className="player-controls-right">
 
254
  onChange={handleVolumeChange}
255
  />
256
  <button onClick={toggleFullscreen} className="control-btn">
257
+ <FontAwesomeIcon icon={isFullscreen ? faCompress : faExpand} size="xl" />
258
  </button>
259
  {videoUrl && (
260
  <a href={videoUrl} download className="control-btn">
frontend/src/components/Sidebar.js CHANGED
@@ -1,5 +1,5 @@
1
  "use client";
2
- import React, { useState, useEffect } from "react";
3
  import Link from "next/link";
4
  import Image from "next/image";
5
  import { usePathname } from "next/navigation";
@@ -23,6 +23,7 @@ const Sidebar = () => {
23
  const pathname = usePathname();
24
  const [hoveredLink, setHoveredLink] = useState(null);
25
  const [prevLink, setPrevLink] = useState(null);
 
26
 
27
  useEffect(() => {
28
  const activeLink = document.querySelector(
@@ -46,8 +47,25 @@ const Sidebar = () => {
46
  setHoveredLink(null);
47
  };
48
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
49
  return (
50
- <div className={`sidebar ${isOpen ? "open" : "closed"}`}>
51
  <div className="sidebar-header">
52
  <button className="sidebar-toggle" onClick={toggleSidebar}>
53
  <FontAwesomeIcon icon={faBars} size="sm" />
@@ -56,7 +74,7 @@ const Sidebar = () => {
56
  <h1 className="sidebar-title">
57
  Nexora{" "}
58
  <Image
59
- className="sidebar-logo"
60
  src="/favicon-32x32.png"
61
  width={32}
62
  height={32}
 
1
  "use client";
2
+ import React, { useState, useEffect, useRef } from "react";
3
  import Link from "next/link";
4
  import Image from "next/image";
5
  import { usePathname } from "next/navigation";
 
23
  const pathname = usePathname();
24
  const [hoveredLink, setHoveredLink] = useState(null);
25
  const [prevLink, setPrevLink] = useState(null);
26
+ const sidebarRef = useRef(null);
27
 
28
  useEffect(() => {
29
  const activeLink = document.querySelector(
 
47
  setHoveredLink(null);
48
  };
49
 
50
+ const handleClickOutside = (e) => {
51
+ if (sidebarRef.current && !sidebarRef.current.contains(e.target)) {
52
+ setIsOpen(false);
53
+ }
54
+ };
55
+
56
+ useEffect(() => {
57
+ if (isOpen) {
58
+ document.addEventListener("mousedown", handleClickOutside);
59
+ } else {
60
+ document.removeEventListener("mousedown", handleClickOutside);
61
+ }
62
+ return () => {
63
+ document.removeEventListener("mousedown", handleClickOutside);
64
+ };
65
+ }, [isOpen]);
66
+
67
  return (
68
+ <div ref={sidebarRef} className={`sidebar ${isOpen ? "open" : "closed"}`}>
69
  <div className="sidebar-header">
70
  <button className="sidebar-toggle" onClick={toggleSidebar}>
71
  <FontAwesomeIcon icon={faBars} size="sm" />
 
74
  <h1 className="sidebar-title">
75
  Nexora{" "}
76
  <Image
77
+ className="sidebar-logo"
78
  src="/favicon-32x32.png"
79
  width={32}
80
  height={32}