ChandimaPrabath commited on
Commit
ad5cee0
·
1 Parent(s): 62c5ab3
frontend/src/app/category/[category]/CategoryPage.css CHANGED
@@ -7,3 +7,44 @@
7
  height: 100%;
8
  width: 100%;
9
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
7
  height: 100%;
8
  width: 100%;
9
  }
10
+
11
+ .category-page {
12
+ padding: 20px;
13
+ text-align: center;
14
+ }
15
+
16
+ .music-card-section {
17
+ display: flex;
18
+ flex-wrap: wrap;
19
+ gap: 10px;
20
+ justify-content: center;
21
+ overflow-y: auto;
22
+ height: auto; /* Allow height to adjust to content */
23
+ width: 100%;
24
+ }
25
+
26
+ .loading {
27
+ font-size: 1.5rem;
28
+ color: #555;
29
+ }
30
+
31
+ .error {
32
+ font-size: 1.2rem;
33
+ color: red; /* Change to a more visually impactful color */
34
+ }
35
+
36
+ .load-more {
37
+ margin-top: 20px;
38
+ padding: 10px 20px;
39
+ font-size: 1rem;
40
+ background-color: #0070f3; /* Use your preferred button color */
41
+ color: white;
42
+ border: none;
43
+ border-radius: 5px;
44
+ cursor: pointer;
45
+ transition: background-color 0.3s;
46
+ }
47
+
48
+ .load-more:hover {
49
+ background-color: #005bb5; /* Darker shade on hover */
50
+ }
frontend/src/app/category/[category]/page.js CHANGED
@@ -1,7 +1,7 @@
1
  'use client';
2
  import Card from "@/components/Card";
3
  import './CategoryPage.css';
4
- import { useEffect, useState } from 'react';
5
  import { use } from 'react';
6
 
7
  export default function CategoryPage({ params }) {
@@ -14,11 +14,15 @@ export default function CategoryPage({ params }) {
14
 
15
  useEffect(() => {
16
  const fetchMusicByCategory = async () => {
 
 
 
17
  try {
18
- const response = await fetch(`/api/get/category/${category}?page=${page}&limit=20`);
19
  if (!response.ok) {
20
  throw new Error("Failed to fetch music");
21
  }
 
22
  const data = await response.json();
23
 
24
  // Update music items based on response, avoiding duplicates
@@ -27,10 +31,8 @@ export default function CategoryPage({ params }) {
27
  return [...prevItems, ...newItems];
28
  });
29
 
30
- // Check if there are more files to load
31
- if (data.files.length < data.limit) {
32
- setHasMore(false); // No more music to load
33
- }
34
  } catch (err) {
35
  setError(err.message);
36
  } finally {
@@ -41,18 +43,52 @@ export default function CategoryPage({ params }) {
41
  fetchMusicByCategory();
42
  }, [category, page]);
43
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
44
  const loadMore = () => {
45
  if (hasMore) {
46
  setPage(prevPage => prevPage + 1);
47
  }
48
  };
49
 
50
- if (loading) {
51
- return <div>Loading music...</div>;
 
 
 
 
 
 
 
 
 
 
 
 
 
52
  }
53
 
54
  if (error) {
55
- return <div>Error: {error}</div>;
56
  }
57
 
58
  return (
@@ -61,16 +97,12 @@ export default function CategoryPage({ params }) {
61
  <div className="music-card-section">
62
  {musicItems.map((file, index) => (
63
  <Card
64
- key={`${file}-${page}`} // Ensure unique key by appending page number
65
  src={file} // Assuming the base URL is handled correctly
66
  />
67
  ))}
 
68
  </div>
69
- {hasMore && (
70
- <button onClick={loadMore} className="load-more">
71
- Load More
72
- </button>
73
- )}
74
  </div>
75
  );
76
  }
 
1
  'use client';
2
  import Card from "@/components/Card";
3
  import './CategoryPage.css';
4
+ import { useEffect, useState, useRef } from 'react';
5
  import { use } from 'react';
6
 
7
  export default function CategoryPage({ params }) {
 
14
 
15
  useEffect(() => {
16
  const fetchMusicByCategory = async () => {
17
+ setLoading(true);
18
+ setError(null); // Reset error state before fetch
19
+
20
  try {
21
+ const response = await fetch(`/api/get/category/${category}?page=${page}&limit=10`);
22
  if (!response.ok) {
23
  throw new Error("Failed to fetch music");
24
  }
25
+
26
  const data = await response.json();
27
 
28
  // Update music items based on response, avoiding duplicates
 
31
  return [...prevItems, ...newItems];
32
  });
33
 
34
+ // Check if there are more files to load based on total_files from the response
35
+ setHasMore(musicItems.length + data.files.length < data.total_files); // Update hasMore based on total files
 
 
36
  } catch (err) {
37
  setError(err.message);
38
  } finally {
 
43
  fetchMusicByCategory();
44
  }, [category, page]);
45
 
46
+ // Load more when scrolled to bottom of the app container
47
+ useEffect(() => {
48
+ const appContainer = document.querySelector('.app-container'); // Get the app-container element
49
+ if (!appContainer) return;
50
+
51
+ const handleScroll = () => {
52
+ const { scrollTop, clientHeight, scrollHeight } = appContainer;
53
+
54
+ // Check if we are at the bottom of the scrollable container
55
+ if (scrollHeight - scrollTop <= clientHeight + 10 && hasMore && !loading) {
56
+ loadMore();
57
+ }
58
+ };
59
+
60
+ appContainer.addEventListener('scroll', handleScroll);
61
+
62
+ return () => {
63
+ appContainer.removeEventListener('scroll', handleScroll);
64
+ };
65
+ }, [hasMore, loading]);
66
+
67
  const loadMore = () => {
68
  if (hasMore) {
69
  setPage(prevPage => prevPage + 1);
70
  }
71
  };
72
 
73
+ // Initial loading logic to fill the app-container
74
+ useEffect(() => {
75
+ const appContainer = document.querySelector('.app-container'); // Get the app-container element
76
+ if (appContainer) {
77
+ const { scrollHeight, clientHeight } = appContainer;
78
+
79
+ // If content height is less than or equal to client height, load more
80
+ if (scrollHeight <= clientHeight && hasMore) {
81
+ loadMore();
82
+ }
83
+ }
84
+ }, [musicItems, hasMore]);
85
+
86
+ if (loading && musicItems.length === 0) {
87
+ return <div className="loading">Loading music...</div>;
88
  }
89
 
90
  if (error) {
91
+ return <div className="error">Error: {error}</div>;
92
  }
93
 
94
  return (
 
97
  <div className="music-card-section">
98
  {musicItems.map((file, index) => (
99
  <Card
100
+ key={`${file}-${index}`} // Ensure unique key by using index
101
  src={file} // Assuming the base URL is handled correctly
102
  />
103
  ))}
104
+ {loading && <div className="load-more">Loading more...</div>} {/* Loading indicator at the bottom */}
105
  </div>
 
 
 
 
 
106
  </div>
107
  );
108
  }
frontend/src/app/test/[category]/CategoryPage.css DELETED
@@ -1,9 +0,0 @@
1
- .music-card-section {
2
- display: flex;
3
- flex-wrap: wrap;
4
- gap: 10px;
5
- justify-content: center;
6
- overflow-y: auto;
7
- height: 100%;
8
- width: 100%;
9
- }
 
 
 
 
 
 
 
 
 
 
frontend/src/app/test/[category]/page.js DELETED
@@ -1,76 +0,0 @@
1
- 'use client';
2
- import Card from "@/components/Card";
3
- import './CategoryPage.css';
4
- import { useEffect, useState } from 'react';
5
- import { use } from 'react';
6
-
7
- export default function CategoryPage({ params }) {
8
- const { category } = use(params); // Unwrap params using React.use()
9
- const [musicItems, setMusicItems] = useState([]);
10
- const [loading, setLoading] = useState(true);
11
- const [error, setError] = useState(null);
12
- const [page, setPage] = useState(1);
13
- const [hasMore, setHasMore] = useState(true);
14
-
15
- useEffect(() => {
16
- const fetchMusicByCategory = async () => {
17
- try {
18
- const response = await fetch(`/api/get/category/${category}?page=${page}&limit=20`);
19
- if (!response.ok) {
20
- throw new Error("Failed to fetch music");
21
- }
22
- const data = await response.json();
23
-
24
- // Update music items based on response, avoiding duplicates
25
- setMusicItems(prevItems => {
26
- const newItems = data.files.filter(file => !prevItems.includes(file));
27
- return [...prevItems, ...newItems];
28
- });
29
-
30
- // Check if there are more files to load
31
- if (data.files.length < data.limit) {
32
- setHasMore(false); // No more music to load
33
- }
34
- } catch (err) {
35
- setError(err.message);
36
- } finally {
37
- setLoading(false);
38
- }
39
- };
40
-
41
- fetchMusicByCategory();
42
- }, [category, page]);
43
-
44
- const loadMore = () => {
45
- if (hasMore) {
46
- setPage(prevPage => prevPage + 1);
47
- }
48
- };
49
-
50
- if (loading) {
51
- return <div>Loading music...</div>;
52
- }
53
-
54
- if (error) {
55
- return <div>Error: {error}</div>;
56
- }
57
-
58
- return (
59
- <div className="category-page font-[family-name:var(--font-geist-sans)]">
60
- <h1>{category.charAt(0).toUpperCase() + category.slice(1)} Music</h1>
61
- <div className="music-card-section">
62
- {musicItems.map((file, index) => (
63
- <Card
64
- key={`${file}-${page}`} // Ensure unique key by appending page number
65
- src={file} // Assuming the base URL is handled correctly
66
- />
67
- ))}
68
- </div>
69
- {hasMore && (
70
- <button onClick={loadMore} className="load-more">
71
- Load More
72
- </button>
73
- )}
74
- </div>
75
- );
76
- }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
frontend/src/components/Card.css CHANGED
@@ -1,5 +1,5 @@
1
  .music-card {
2
- width: 200px;
3
  height: 40;
4
  background-image: linear-gradient(var(--background-2), var(--foreground-2));
5
  border-top-left-radius: 20px;
@@ -9,6 +9,7 @@
9
  display: flex;
10
  align-items: center;
11
  gap: 10px;
 
12
  }
13
 
14
  .card-title {
 
1
  .music-card {
2
+ width: 250px;
3
  height: 40;
4
  background-image: linear-gradient(var(--background-2), var(--foreground-2));
5
  border-top-left-radius: 20px;
 
9
  display: flex;
10
  align-items: center;
11
  gap: 10px;
12
+ overflow: hidden;
13
  }
14
 
15
  .card-title {