Patch: Fix to StreamerRoute to correctly send user to UserPage/VideoPage;

Update: Display Category Thumbnails
This commit is contained in:
Chris-1010
2025-01-29 14:51:04 +00:00
parent a4f66ba321
commit c0a110c76d
20 changed files with 25 additions and 190 deletions

View File

@@ -6,7 +6,7 @@
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Team Software Project</title>
</head>
<body class="h-screen">
<body class="min-h-screen h-full">
<div id="root" class="h-full bg-gradient-to-tr from-[#07001F] via-[#1D0085] to-[#CC00AF]"></div>
<script type="module" src="/src/main.tsx"></script>
</body>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 844 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 95 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 194 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 508 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 71 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 149 KiB

View File

Before

Width:  |  Height:  |  Size: 100 KiB

After

Width:  |  Height:  |  Size: 100 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 95 KiB

View File

@@ -27,6 +27,7 @@ const ListItem: React.FC<ListItemProps> = ({
thumbnail,
onItemClick,
}) => {
console.log(title, "thumbnail", thumbnail);
return (
<div
className="flex flex-col bg-gray-800 rounded-lg overflow-hidden cursor-pointer hover:bg-gray-700 transition-colors"
@@ -35,7 +36,7 @@ const ListItem: React.FC<ListItemProps> = ({
<div className="relative w-full pt-[56.25%]">
{thumbnail ? (
<img
src={`images/` + thumbnail}
src={thumbnail}
alt={title}
className="absolute top-0 left-0 w-full h-full object-cover"
/>
@@ -74,6 +75,7 @@ const ListRow: React.FC<ListRowProps> = ({
title={item.title}
streamer={item.type === "stream" ? (item.streamer) : undefined}
viewers={item.viewers}
thumbnail={item.thumbnail}
onItemClick={() =>
onClick?.(item.id, item.streamer || item.title)
}

View File

@@ -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 ? <VideoPage streamId={0} /> : <UserPage profile={streamerName} />;
return isLive ? <VideoPage streamId={0} /> : (streamerName ? <UserPage username={streamerName} /> : <div>Error: Streamer not found</div>);
};
export default StreamerRoute;

View File

@@ -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);
});
}, []);

View File

@@ -52,7 +52,7 @@ const VideoPage: React.FC<VideoPageProps> = ({ 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,

165
package-lock.json generated
View File

@@ -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"
}
}
}
}

View File

@@ -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"
}
}

View File

@@ -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

View File

@@ -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;

View File

@@ -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