diff --git a/frontend/index.html b/frontend/index.html index 8a2e42c..89ed825 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -6,7 +6,7 @@ Team Software Project - +
diff --git a/frontend/public/images/art_category.jpg b/frontend/public/images/art_category.jpg deleted file mode 100644 index a477bb4..0000000 Binary files a/frontend/public/images/art_category.jpg and /dev/null differ diff --git a/frontend/public/images/chatting_category.jpg b/frontend/public/images/chatting_category.jpg deleted file mode 100644 index 53902e4..0000000 Binary files a/frontend/public/images/chatting_category.jpg and /dev/null differ diff --git a/frontend/public/images/cooking_category.jpg b/frontend/public/images/cooking_category.jpg deleted file mode 100644 index fcb7b3a..0000000 Binary files a/frontend/public/images/cooking_category.jpg and /dev/null differ diff --git a/frontend/public/images/gaming_category.jpg b/frontend/public/images/gaming_category.jpg deleted file mode 100644 index a6d7cab..0000000 Binary files a/frontend/public/images/gaming_category.jpg and /dev/null differ diff --git a/frontend/public/images/thumbnails/categories/art.webp b/frontend/public/images/thumbnails/categories/art.webp new file mode 100644 index 0000000..ee0b5f9 Binary files /dev/null and b/frontend/public/images/thumbnails/categories/art.webp differ diff --git a/frontend/public/images/thumbnails/categories/chatting.webp b/frontend/public/images/thumbnails/categories/chatting.webp new file mode 100644 index 0000000..3cbc381 Binary files /dev/null and b/frontend/public/images/thumbnails/categories/chatting.webp differ diff --git a/frontend/public/images/thumbnails/categories/cooking.webp b/frontend/public/images/thumbnails/categories/cooking.webp new file mode 100644 index 0000000..a10b3b3 Binary files /dev/null and b/frontend/public/images/thumbnails/categories/cooking.webp differ diff --git a/frontend/public/images/thumbnails/categories/gaming.webp b/frontend/public/images/thumbnails/categories/gaming.webp new file mode 100644 index 0000000..b7b6221 Binary files /dev/null and b/frontend/public/images/thumbnails/categories/gaming.webp differ diff --git a/frontend/public/images/music_category.webp b/frontend/public/images/thumbnails/categories/music.webp similarity index 100% rename from frontend/public/images/music_category.webp rename to frontend/public/images/thumbnails/categories/music.webp diff --git a/frontend/public/images/thumbnails/categories/sports.webp b/frontend/public/images/thumbnails/categories/sports.webp new file mode 100644 index 0000000..c115b90 Binary files /dev/null and b/frontend/public/images/thumbnails/categories/sports.webp differ diff --git a/frontend/src/components/Layout/ListRow.tsx b/frontend/src/components/Layout/ListRow.tsx index 75e0aa5..d3d8437 100644 --- a/frontend/src/components/Layout/ListRow.tsx +++ b/frontend/src/components/Layout/ListRow.tsx @@ -27,6 +27,7 @@ const ListItem: React.FC = ({ thumbnail, onItemClick, }) => { + console.log(title, "thumbnail", thumbnail); return (
= ({
{thumbnail ? ( {title} @@ -74,6 +75,7 @@ const ListRow: React.FC = ({ title={item.title} streamer={item.type === "stream" ? (item.streamer) : undefined} viewers={item.viewers} + thumbnail={item.thumbnail} onItemClick={() => onClick?.(item.id, item.streamer || item.title) } diff --git a/frontend/src/components/Stream/StreamerRoute.tsx b/frontend/src/components/Stream/StreamerRoute.tsx index 3bbcaeb..e915609 100644 --- a/frontend/src/components/Stream/StreamerRoute.tsx +++ b/frontend/src/components/Stream/StreamerRoute.tsx @@ -13,8 +13,7 @@ const StreamerRoute: React.FC = () => { try { const response = await fetch(`/api/streamer/${streamerName}/status`); const data = await response.json(); - console.log("Stream status:", data); - setIsLive(data.status === "live"); + setIsLive(data.is_live); } catch (error) { console.error("Error checking stream status:", error); setIsLive(false); @@ -36,7 +35,7 @@ const StreamerRoute: React.FC = () => { } // streamId=0 is a special case for the streamer's latest stream - return isLive ? : ; + return isLive ? : (streamerName ? :
Error: Streamer not found
); }; export default StreamerRoute; diff --git a/frontend/src/context/StreamsContext.tsx b/frontend/src/context/StreamsContext.tsx index ec43c50..5a1d69e 100644 --- a/frontend/src/context/StreamsContext.tsx +++ b/frontend/src/context/StreamsContext.tsx @@ -41,12 +41,12 @@ export function StreamsProvider({ children }: { children: React.ReactNode }) { // Streams fetch(fetch_url[0]) .then((response) => response.json()) - .then((data) => { - const extractedData: StreamItem[] = data.streams.map((stream: any) => ({ + .then((data: StreamItem[]) => { + const extractedData: StreamItem[] = data.map((stream: any) => ({ type: "stream", id: stream.stream_id, title: stream.title, - streamer: stream.user_id, + streamer: stream.username, viewers: stream.num_viewers, thumbnail: stream.thumbnail, })); @@ -56,15 +56,17 @@ export function StreamsProvider({ children }: { children: React.ReactNode }) { // Categories fetch(fetch_url[1]) .then((response) => response.json()) - .then((data) => { - const extractedData: CategoryItem[] = data.categories.map( + .then((data: CategoryItem[]) => { + const extractedData: CategoryItem[] = data.map( (category: any) => ({ type: "category", id: category.category_id, title: category.category_name, viewers: category.num_viewers, + thumbnail: `/images/thumbnails/categories/${category.category_name.toLowerCase().replace(/ /g, "_")}.webp` }) ); + console.log(extractedData); setFeaturedCategories(extractedData); }); }, []); diff --git a/frontend/src/pages/VideoPage.tsx b/frontend/src/pages/VideoPage.tsx index ec872bd..c4ccbef 100644 --- a/frontend/src/pages/VideoPage.tsx +++ b/frontend/src/pages/VideoPage.tsx @@ -52,7 +52,7 @@ const VideoPage: React.FC = ({ streamId }) => { console.error("Failed to load stream data:", res.statusText); } res.json().then((data) => { - if (!data.validStream) navigate(`/`); + // if (!data.validStream) navigate(`/`); console.log(`Loading stream data for ${streamerName}`); setStreamData({ streamId: data.streamId, diff --git a/package-lock.json b/package-lock.json deleted file mode 100644 index d03c28d..0000000 --- a/package-lock.json +++ /dev/null @@ -1,165 +0,0 @@ -{ - "name": "cs3305-team11", - "lockfileVersion": 3, - "requires": true, - "packages": { - "": { - "dependencies": { - "lucide-react": "^0.474.0", - "react-router-dom": "^7.1.3" - }, - "devDependencies": { - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", - "typescript": "^5.7.3" - } - }, - "node_modules/@types/cookie": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz", - "integrity": "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA==", - "license": "MIT" - }, - "node_modules/@types/react": { - "version": "19.0.8", - "resolved": "https://registry.npmjs.org/@types/react/-/react-19.0.8.tgz", - "integrity": "sha512-9P/o1IGdfmQxrujGbIMDyYaaCykhLKc0NGCtYcECNUr9UAaDe4gwvV9bR6tvd5Br1SG0j+PBpbKr2UYY8CwqSw==", - "dev": true, - "license": "MIT", - "dependencies": { - "csstype": "^3.0.2" - } - }, - "node_modules/@types/react-dom": { - "version": "19.0.3", - "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-19.0.3.tgz", - "integrity": "sha512-0Knk+HJiMP/qOZgMyNFamlIjw9OFCsyC2ZbigmEEyXXixgre6IQpm/4V+r3qH4GC1JPvRJKInw+on2rV6YZLeA==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@types/react": "^19.0.0" - } - }, - "node_modules/cookie": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-1.0.2.tgz", - "integrity": "sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA==", - "license": "MIT", - "engines": { - "node": ">=18" - } - }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/lucide-react": { - "version": "0.474.0", - "resolved": "https://registry.npmjs.org/lucide-react/-/lucide-react-0.474.0.tgz", - "integrity": "sha512-CmghgHkh0OJNmxGKWc0qfPJCYHASPMVSyGY8fj3xgk4v84ItqDg64JNKFZn5hC6E0vHi6gxnbCgwhyVB09wQtA==", - "license": "ISC", - "peerDependencies": { - "react": "^16.5.1 || ^17.0.0 || ^18.0.0 || ^19.0.0" - } - }, - "node_modules/react": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react/-/react-19.0.0.tgz", - "integrity": "sha512-V8AVnmPIICiWpGfm6GLzCR/W5FXLchHop40W4nXBmdlEceh16rCN8O8LNWm5bh5XUX91fh7KpA+W0TgMKmgTpQ==", - "license": "MIT", - "peer": true, - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/react-dom": { - "version": "19.0.0", - "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-19.0.0.tgz", - "integrity": "sha512-4GV5sHFG0e/0AD4X+ySy6UJd3jVl1iNsNHdpad0qhABJ11twS3TTBnseqsKurKcsNqCEFeGL3uLpVChpIO3QfQ==", - "license": "MIT", - "peer": true, - "dependencies": { - "scheduler": "^0.25.0" - }, - "peerDependencies": { - "react": "^19.0.0" - } - }, - "node_modules/react-router": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/react-router/-/react-router-7.1.3.tgz", - "integrity": "sha512-EezYymLY6Guk/zLQ2vRA8WvdUhWFEj5fcE3RfWihhxXBW7+cd1LsIiA3lmx+KCmneAGQuyBv820o44L2+TtkSA==", - "license": "MIT", - "dependencies": { - "@types/cookie": "^0.6.0", - "cookie": "^1.0.1", - "set-cookie-parser": "^2.6.0", - "turbo-stream": "2.4.0" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - } - } - }, - "node_modules/react-router-dom": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-7.1.3.tgz", - "integrity": "sha512-qQGTE+77hleBzv9SIUIkGRvuFBQGagW+TQKy53UTZAO/3+YFNBYvRsNIZ1GT17yHbc63FylMOdS+m3oUriF1GA==", - "license": "MIT", - "dependencies": { - "react-router": "7.1.3" - }, - "engines": { - "node": ">=20.0.0" - }, - "peerDependencies": { - "react": ">=18", - "react-dom": ">=18" - } - }, - "node_modules/scheduler": { - "version": "0.25.0", - "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.25.0.tgz", - "integrity": "sha512-xFVuu11jh+xcO7JOAGJNOXld8/TcEHK/4CituBUeUb5hqxJLj9YuemAEuvm9gQ/+pgXYfbQuqAkiYu+u7YEsNA==", - "license": "MIT", - "peer": true - }, - "node_modules/set-cookie-parser": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.1.tgz", - "integrity": "sha512-IOc8uWeOZgnb3ptbCURJWNjWUPcO3ZnTTdzsurqERrP6nPyv+paC55vJM0LpOlT2ne+Ix+9+CRG1MNLlyZ4GjQ==", - "license": "MIT" - }, - "node_modules/turbo-stream": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/turbo-stream/-/turbo-stream-2.4.0.tgz", - "integrity": "sha512-FHncC10WpBd2eOmGwpmQsWLDoK4cqsA/UT/GqNoaKOQnT8uzhtCbg3EoUDMvqpOSAI0S26mr0rkjzbOO6S3v1g==", - "license": "ISC" - }, - "node_modules/typescript": { - "version": "5.7.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.3.tgz", - "integrity": "sha512-84MVSjMEHP+FQRPy3pX9sTVV/INIex71s9TL2Gm5FG/WG1SqXeKyZ0k7/blY/4FdOzI12CBy1vGc4og/eus0fw==", - "dev": true, - "license": "Apache-2.0", - "bin": { - "tsc": "bin/tsc", - "tsserver": "bin/tsserver" - }, - "engines": { - "node": ">=14.17" - } - } - } -} diff --git a/package.json b/package.json deleted file mode 100644 index 456af06..0000000 --- a/package.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "devDependencies": { - "@types/react": "^19.0.8", - "@types/react-dom": "^19.0.3", - "typescript": "^5.7.3" - }, - "dependencies": { - "lucide-react": "^0.474.0", - "react-router-dom": "^7.1.3" - } -} diff --git a/web_server/blueprints/streams.py b/web_server/blueprints/streams.py index b4c3e4e..21f91ae 100644 --- a/web_server/blueprints/streams.py +++ b/web_server/blueprints/streams.py @@ -42,11 +42,11 @@ def get_recommended_streams() -> list[dict]: @stream_bp.route('/get_categories') def get_categories() -> list[dict]: """ - Returns a list of streams in the most popular category + Returns a list of most watched categories """ category_data = most_popular_category() - streams = recommendations_based_on_category(category_data["category_id"]) + streams = recommendations_based_on_category(category_data['category_id']) return jsonify(streams) @login_required diff --git a/web_server/database/streaming.sql b/web_server/database/streaming.sql index b833289..51a7e98 100644 --- a/web_server/database/streaming.sql +++ b/web_server/database/streaming.sql @@ -49,3 +49,11 @@ CREATE TABLE streams FOREIGN KEY (category_id) REFERENCES categories(category_id) ON DELETE CASCADE, FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE ); + + +SELECT users.user_id, title, username, num_viewers, category_name + FROM streams + JOIN users ON users.user_id = streams.user_id + JOIN categories ON streams.category_id = categories.category_id + ORDER BY num_viewers DESC + LIMIT 25; \ No newline at end of file diff --git a/web_server/utils/recommendation_utils.py b/web_server/utils/recommendation_utils.py index ccfef94..85cb460 100644 --- a/web_server/utils/recommendation_utils.py +++ b/web_server/utils/recommendation_utils.py @@ -61,7 +61,7 @@ def default_recommendations(): JOIN users ON users.user_id = streams.user_id JOIN categories ON streams.category_id = categories.category_id ORDER BY num_viewers DESC - LIMIT 25 + LIMIT 25; """) db.close_connection() return data