ChandimaPrabath
commited on
Commit
•
1a805b3
1
Parent(s):
c0b3c6a
improved search UI
Browse files
frontend/src/app/movies/filmsPage.css
CHANGED
@@ -13,6 +13,11 @@ body {
|
|
13 |
padding: 20px;
|
14 |
max-width: 1200px;
|
15 |
margin: 0 auto;
|
|
|
|
|
|
|
|
|
|
|
16 |
}
|
17 |
|
18 |
/* Films Grid */
|
@@ -43,32 +48,34 @@ body {
|
|
43 |
margin-top: 20px;
|
44 |
display: flex;
|
45 |
align-items: center;
|
|
|
|
|
46 |
}
|
47 |
|
48 |
/* Pagination Button */
|
49 |
.pagination-button {
|
50 |
-
background-color: #
|
|
|
51 |
color: #ffffff;
|
52 |
-
border: none;
|
53 |
border-radius: 50%;
|
54 |
padding: 10px;
|
55 |
-
width:
|
56 |
-
height:
|
57 |
display: flex;
|
58 |
align-items: center;
|
59 |
justify-content: center;
|
60 |
cursor: pointer;
|
61 |
-
transition: background-color
|
62 |
}
|
63 |
|
64 |
.pagination-button.enabled:hover {
|
65 |
-
background-color: #
|
66 |
-
transform: scale(1.1);
|
67 |
}
|
68 |
|
69 |
.pagination-button.disabled {
|
70 |
background-color: #333;
|
71 |
cursor: not-allowed;
|
|
|
72 |
}
|
73 |
|
74 |
/* Page Info */
|
|
|
13 |
padding: 20px;
|
14 |
max-width: 1200px;
|
15 |
margin: 0 auto;
|
16 |
+
height: 80dvh;
|
17 |
+
overflow-y: scroll;
|
18 |
+
-ms-overflow-style: none; /* IE and Edge */
|
19 |
+
scrollbar-width: none; /* Firefox */
|
20 |
+
scroll-behavior: smooth;
|
21 |
}
|
22 |
|
23 |
/* Films Grid */
|
|
|
48 |
margin-top: 20px;
|
49 |
display: flex;
|
50 |
align-items: center;
|
51 |
+
position: absolute;
|
52 |
+
bottom: 1dvh;
|
53 |
}
|
54 |
|
55 |
/* Pagination Button */
|
56 |
.pagination-button {
|
57 |
+
background-color: #1c2354;
|
58 |
+
border: 1px solid #4339ff;
|
59 |
color: #ffffff;
|
|
|
60 |
border-radius: 50%;
|
61 |
padding: 10px;
|
62 |
+
width: 40px;
|
63 |
+
height: 40px;
|
64 |
display: flex;
|
65 |
align-items: center;
|
66 |
justify-content: center;
|
67 |
cursor: pointer;
|
68 |
+
transition: background-color 1s, border .5s;
|
69 |
}
|
70 |
|
71 |
.pagination-button.enabled:hover {
|
72 |
+
background-color: #273281;
|
|
|
73 |
}
|
74 |
|
75 |
.pagination-button.disabled {
|
76 |
background-color: #333;
|
77 |
cursor: not-allowed;
|
78 |
+
border: none;
|
79 |
}
|
80 |
|
81 |
/* Page Info */
|
frontend/src/app/movies/page.js
CHANGED
@@ -8,7 +8,7 @@ import './filmsPage.css';
|
|
8 |
|
9 |
import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';
|
10 |
|
11 |
-
const FILMS_PER_PAGE =
|
12 |
|
13 |
export default function FilmsPage() {
|
14 |
const { films, setFilms } = useFilmContext();
|
@@ -56,7 +56,7 @@ export default function FilmsPage() {
|
|
56 |
>
|
57 |
<FontAwesomeIcon
|
58 |
icon={faChevronLeft}
|
59 |
-
size="
|
60 |
/>
|
61 |
</button>
|
62 |
<span className="page-info">
|
@@ -69,7 +69,7 @@ export default function FilmsPage() {
|
|
69 |
>
|
70 |
<FontAwesomeIcon
|
71 |
icon={faChevronRight}
|
72 |
-
size="
|
73 |
/>
|
74 |
</button>
|
75 |
</div>
|
|
|
8 |
|
9 |
import { faChevronLeft, faChevronRight } from '@fortawesome/free-solid-svg-icons';
|
10 |
|
11 |
+
const FILMS_PER_PAGE = 2;
|
12 |
|
13 |
export default function FilmsPage() {
|
14 |
const { films, setFilms } = useFilmContext();
|
|
|
56 |
>
|
57 |
<FontAwesomeIcon
|
58 |
icon={faChevronLeft}
|
59 |
+
size="xl"
|
60 |
/>
|
61 |
</button>
|
62 |
<span className="page-info">
|
|
|
69 |
>
|
70 |
<FontAwesomeIcon
|
71 |
icon={faChevronRight}
|
72 |
+
size="xl"
|
73 |
/>
|
74 |
</button>
|
75 |
</div>
|
frontend/src/app/search/page.js
CHANGED
@@ -2,8 +2,11 @@
|
|
2 |
|
3 |
import { useState, useEffect } from "react";
|
4 |
import { useRouter } from "next/navigation";
|
|
|
|
|
5 |
import { search } from "@/api/searchApi"; // Ensure the path is correct for your API
|
6 |
import "./searchPage.css";
|
|
|
7 |
|
8 |
const SearchPage = () => {
|
9 |
const [query, setQuery] = useState("");
|
@@ -35,7 +38,7 @@ const SearchPage = () => {
|
|
35 |
} catch (err) {
|
36 |
setError("Failed to fetch search results.");
|
37 |
} finally {
|
38 |
-
setLoading(false);
|
39 |
}
|
40 |
};
|
41 |
|
@@ -60,6 +63,9 @@ const SearchPage = () => {
|
|
60 |
/>
|
61 |
{loading && (
|
62 |
<div className="loading-indicator">
|
|
|
|
|
|
|
63 |
<div className="spinner"></div>
|
64 |
</div>
|
65 |
)}
|
@@ -74,9 +80,11 @@ const SearchPage = () => {
|
|
74 |
<li
|
75 |
key={index}
|
76 |
className="result-item"
|
77 |
-
onClick={() =>
|
|
|
|
|
78 |
>
|
79 |
-
{film}
|
80 |
</li>
|
81 |
))}
|
82 |
</ul>
|
@@ -90,7 +98,9 @@ const SearchPage = () => {
|
|
90 |
<li
|
91 |
key={index}
|
92 |
className="result-item"
|
93 |
-
onClick={() =>
|
|
|
|
|
94 |
>
|
95 |
{series}
|
96 |
</li>
|
|
|
2 |
|
3 |
import { useState, useEffect } from "react";
|
4 |
import { useRouter } from "next/navigation";
|
5 |
+
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
6 |
+
import { faSearch } from "@fortawesome/free-solid-svg-icons";
|
7 |
import { search } from "@/api/searchApi"; // Ensure the path is correct for your API
|
8 |
import "./searchPage.css";
|
9 |
+
import MovieCard from "@/components/MovieCard";
|
10 |
|
11 |
const SearchPage = () => {
|
12 |
const [query, setQuery] = useState("");
|
|
|
38 |
} catch (err) {
|
39 |
setError("Failed to fetch search results.");
|
40 |
} finally {
|
41 |
+
setTimeout(() => setLoading(false), 500);
|
42 |
}
|
43 |
};
|
44 |
|
|
|
63 |
/>
|
64 |
{loading && (
|
65 |
<div className="loading-indicator">
|
66 |
+
<div className="search-icon">
|
67 |
+
<FontAwesomeIcon icon={faSearch} size="xl"/>
|
68 |
+
</div>
|
69 |
<div className="spinner"></div>
|
70 |
</div>
|
71 |
)}
|
|
|
80 |
<li
|
81 |
key={index}
|
82 |
className="result-item"
|
83 |
+
onClick={() =>
|
84 |
+
handleItemClick(`/film/${encodeURIComponent(film)}`)
|
85 |
+
}
|
86 |
>
|
87 |
+
<MovieCard title={film}/>
|
88 |
</li>
|
89 |
))}
|
90 |
</ul>
|
|
|
98 |
<li
|
99 |
key={index}
|
100 |
className="result-item"
|
101 |
+
onClick={() =>
|
102 |
+
handleItemClick(`/tvshow/${encodeURIComponent(series)}`)
|
103 |
+
}
|
104 |
>
|
105 |
{series}
|
106 |
</li>
|
frontend/src/app/search/searchPage.css
CHANGED
@@ -24,17 +24,16 @@
|
|
24 |
max-width: 600px;
|
25 |
padding: 10px;
|
26 |
font-size: 16px;
|
27 |
-
border: 1px solid #
|
28 |
border-radius: 5px;
|
29 |
-
background-color: #
|
30 |
color: #ffffff;
|
31 |
-
transition: border-color 0.3s ease, box-shadow 0.3s ease;
|
32 |
}
|
33 |
|
34 |
.search-input:focus {
|
35 |
outline: none;
|
36 |
-
|
37 |
-
box-shadow: 0 0 8px rgba(255, 111, 0, 0.6);
|
38 |
transform: scale(1.02);
|
39 |
}
|
40 |
|
@@ -42,9 +41,9 @@
|
|
42 |
.loading-indicator {
|
43 |
margin-top: 10px;
|
44 |
font-size: 18px;
|
45 |
-
color: #
|
46 |
opacity: 0;
|
47 |
-
animation: fadeIn
|
48 |
}
|
49 |
|
50 |
@keyframes fadeIn {
|
@@ -58,7 +57,7 @@
|
|
58 |
|
59 |
/* Error message styling */
|
60 |
.error-message {
|
61 |
-
color: #
|
62 |
text-align: center;
|
63 |
margin-top: 20px;
|
64 |
animation: bounce 1s infinite;
|
@@ -97,7 +96,7 @@
|
|
97 |
border-bottom: 2px solid #444;
|
98 |
padding-bottom: 10px;
|
99 |
margin-bottom: 15px;
|
100 |
-
color: #
|
101 |
animation: fadeIn 1s ease;
|
102 |
}
|
103 |
|
@@ -165,13 +164,87 @@
|
|
165 |
align-items: center;
|
166 |
margin-top: 20px;
|
167 |
font-size: 18px;
|
168 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
169 |
}
|
170 |
|
171 |
.loading-indicator .spinner {
|
172 |
-
width:
|
173 |
-
height:
|
174 |
-
|
|
|
175 |
border-top: 4px solid transparent;
|
176 |
border-radius: 50%;
|
177 |
margin-right: 10px;
|
|
|
24 |
max-width: 600px;
|
25 |
padding: 10px;
|
26 |
font-size: 16px;
|
27 |
+
border: 1px solid #4339ff;
|
28 |
border-radius: 5px;
|
29 |
+
background-color: #1c2354;
|
30 |
color: #ffffff;
|
31 |
+
transition: border-color 0.3s ease, box-shadow 0.3s ease, transform .5s ease;
|
32 |
}
|
33 |
|
34 |
.search-input:focus {
|
35 |
outline: none;
|
36 |
+
box-shadow: 0 0 15px rgba(17, 0, 255, 0.6);
|
|
|
37 |
transform: scale(1.02);
|
38 |
}
|
39 |
|
|
|
41 |
.loading-indicator {
|
42 |
margin-top: 10px;
|
43 |
font-size: 18px;
|
44 |
+
color: #4339ff;
|
45 |
opacity: 0;
|
46 |
+
animation: fadeIn .3s forwards;
|
47 |
}
|
48 |
|
49 |
@keyframes fadeIn {
|
|
|
57 |
|
58 |
/* Error message styling */
|
59 |
.error-message {
|
60 |
+
color: #ff3300;
|
61 |
text-align: center;
|
62 |
margin-top: 20px;
|
63 |
animation: bounce 1s infinite;
|
|
|
96 |
border-bottom: 2px solid #444;
|
97 |
padding-bottom: 10px;
|
98 |
margin-bottom: 15px;
|
99 |
+
color: #7c81c7;
|
100 |
animation: fadeIn 1s ease;
|
101 |
}
|
102 |
|
|
|
164 |
align-items: center;
|
165 |
margin-top: 20px;
|
166 |
font-size: 18px;
|
167 |
+
position: fixed;
|
168 |
+
}
|
169 |
+
|
170 |
+
.search-icon {
|
171 |
+
position: fixed;
|
172 |
+
z-index: 100;
|
173 |
+
color: #b3b7e4;
|
174 |
+
animation: search 1s infinite linear;
|
175 |
+
}
|
176 |
+
|
177 |
+
@keyframes search {
|
178 |
+
0% {
|
179 |
+
transform: translate(10px, -15px);
|
180 |
+
}
|
181 |
+
5% {
|
182 |
+
transform: translate(14.5px, -14.5px);
|
183 |
+
}
|
184 |
+
10% {
|
185 |
+
transform: translate(18.3px, -12.7px);
|
186 |
+
}
|
187 |
+
15% {
|
188 |
+
transform: translate(21.2px, -9.2px);
|
189 |
+
}
|
190 |
+
20% {
|
191 |
+
transform: translate(23px, -5px);
|
192 |
+
}
|
193 |
+
25% {
|
194 |
+
transform: translate(25px, 0px);
|
195 |
+
}
|
196 |
+
30% {
|
197 |
+
transform: translate(23px, 5px);
|
198 |
+
}
|
199 |
+
35% {
|
200 |
+
transform: translate(21.2px, 9.2px);
|
201 |
+
}
|
202 |
+
40% {
|
203 |
+
transform: translate(18.3px, 12.7px);
|
204 |
+
}
|
205 |
+
45% {
|
206 |
+
transform: translate(14.5px, 14.5px);
|
207 |
+
}
|
208 |
+
50% {
|
209 |
+
transform: translate(10px, 15px);
|
210 |
+
}
|
211 |
+
55% {
|
212 |
+
transform: translate(5.5px, 14.5px);
|
213 |
+
}
|
214 |
+
60% {
|
215 |
+
transform: translate(1.7px, 12.7px);
|
216 |
+
}
|
217 |
+
65% {
|
218 |
+
transform: translate(-2.2px, 9.2px);
|
219 |
+
}
|
220 |
+
70% {
|
221 |
+
transform: translate(-5px, 5px);
|
222 |
+
}
|
223 |
+
75% {
|
224 |
+
transform: translate(-5px, 0px);
|
225 |
+
}
|
226 |
+
80% {
|
227 |
+
transform: translate(-5px, -5px);
|
228 |
+
}
|
229 |
+
85% {
|
230 |
+
transform: translate(-2.2px, -9.2px);
|
231 |
+
}
|
232 |
+
90% {
|
233 |
+
transform: translate(1.7px, -12.7px);
|
234 |
+
}
|
235 |
+
95% {
|
236 |
+
transform: translate(5.5px, -14.5px);
|
237 |
+
}
|
238 |
+
100% {
|
239 |
+
transform: translate(10px, -15px);
|
240 |
+
}
|
241 |
}
|
242 |
|
243 |
.loading-indicator .spinner {
|
244 |
+
width: 40px;
|
245 |
+
height: 40px;
|
246 |
+
background-image: linear-gradient(#146c98, #7139ff);
|
247 |
+
border: 3px solid #3939ff;
|
248 |
border-top: 4px solid transparent;
|
249 |
border-radius: 50%;
|
250 |
margin-right: 10px;
|
frontend/src/components/Header.js
CHANGED
@@ -1,4 +1,5 @@
|
|
1 |
import "./Header.css";
|
|
|
2 |
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
3 |
import { faSearch } from "@fortawesome/free-solid-svg-icons";
|
4 |
import Image from "next/image";
|
@@ -18,9 +19,9 @@ const Header = () => {
|
|
18 |
/>
|
19 |
</div>
|
20 |
</div>
|
21 |
-
<
|
22 |
<FontAwesomeIcon icon={faSearch} size="xl" />
|
23 |
-
</
|
24 |
</div>
|
25 |
);
|
26 |
};
|
|
|
1 |
import "./Header.css";
|
2 |
+
import Link from "next/link";
|
3 |
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
|
4 |
import { faSearch } from "@fortawesome/free-solid-svg-icons";
|
5 |
import Image from "next/image";
|
|
|
19 |
/>
|
20 |
</div>
|
21 |
</div>
|
22 |
+
<Link href="/search" className="search-button">
|
23 |
<FontAwesomeIcon icon={faSearch} size="xl" />
|
24 |
+
</Link>
|
25 |
</div>
|
26 |
);
|
27 |
};
|
frontend/src/components/Sidebar.css
CHANGED
@@ -77,11 +77,11 @@
|
|
77 |
margin-bottom: 8px;
|
78 |
margin-left: 10px;
|
79 |
margin-right: 10px;
|
80 |
-
background-color: #
|
81 |
cursor: pointer;
|
82 |
white-space: nowrap;
|
83 |
position: relative;
|
84 |
-
transition: color 0.3s ease,
|
85 |
}
|
86 |
|
87 |
.sidebar-link.active {
|
@@ -92,7 +92,6 @@
|
|
92 |
|
93 |
.sidebar-link:hover {
|
94 |
color: #ffffff;
|
95 |
-
transform: translateY(-2px);
|
96 |
border: 1px solid #4339ff;
|
97 |
}
|
98 |
|
|
|
77 |
margin-bottom: 8px;
|
78 |
margin-left: 10px;
|
79 |
margin-right: 10px;
|
80 |
+
background-color: #12121f;
|
81 |
cursor: pointer;
|
82 |
white-space: nowrap;
|
83 |
position: relative;
|
84 |
+
transition: color 0.3s ease, border .3s ease-in-out, background-color .5s ease-in-out;
|
85 |
}
|
86 |
|
87 |
.sidebar-link.active {
|
|
|
92 |
|
93 |
.sidebar-link:hover {
|
94 |
color: #ffffff;
|
|
|
95 |
border: 1px solid #4339ff;
|
96 |
}
|
97 |
|