diff --git a/frontend/public/images/category_thumbnails/fortnite.webp b/frontend/public/images/category_thumbnails/fortnite.webp new file mode 100644 index 0000000..9fdc786 Binary files /dev/null and b/frontend/public/images/category_thumbnails/fortnite.webp differ diff --git a/frontend/public/images/category_thumbnails/league_of_legends.webp b/frontend/public/images/category_thumbnails/league_of_legends.webp new file mode 100644 index 0000000..9db56a6 Binary files /dev/null and b/frontend/public/images/category_thumbnails/league_of_legends.webp differ diff --git a/frontend/src/components/Layout/ListItem.tsx b/frontend/src/components/Layout/ListItem.tsx index 0c15060..71c4d81 100644 --- a/frontend/src/components/Layout/ListItem.tsx +++ b/frontend/src/components/Layout/ListItem.tsx @@ -23,7 +23,7 @@ const ListItem: React.FC = ({ return (
diff --git a/frontend/src/components/Layout/ListRow.tsx b/frontend/src/components/Layout/ListRow.tsx index 0db3516..6768e9b 100644 --- a/frontend/src/components/Layout/ListRow.tsx +++ b/frontend/src/components/Layout/ListRow.tsx @@ -52,7 +52,7 @@ const ListRow: React.FC = ({
- {!wrap && items.length > 3 && ( + {!wrap && items.length > 4 && ( <> { const { categories, setCategories } = useCategories(); const navigate = useNavigate(); + const [categoryOffset, setCategoryOffset] = useState(0); + const [noCategories, setNoCategories] = useState(12); + const [hasMoreData, setHasMoreData] = useState(true); useEffect(() => { const fetchCategories = async () => { try { - const response = await fetch("/api/categories/popular/8/0"); + const response = await fetch(`/api/categories/popular/${noCategories}/${categoryOffset}`); if (!response.ok) { throw new Error("Failed to fetch categories"); } const data = await response.json(); + // Adds to offset once data is returned + if (data.length > 0) { + setCategoryOffset(prev => prev + data.length); + } else { + setHasMoreData(false); + } // Transform the data to match CategoryItem interface const processedCategories = data.map((category: any) => ({ @@ -37,6 +47,11 @@ const AllCategoriesPage: React.FC = () => { fetchCategories(); }, [setCategories]); + const logOnScroll = () => { + console.log("hi") + }; + fetchContentOnScroll(logOnScroll,hasMoreData) + if (!categories.length) { return (
diff --git a/frontend/src/pages/HomePage.tsx b/frontend/src/pages/HomePage.tsx index 20a91a8..156433a 100644 --- a/frontend/src/pages/HomePage.tsx +++ b/frontend/src/pages/HomePage.tsx @@ -38,7 +38,7 @@ const HomePage: React.FC = ({ variant = "default" }) => { description={ variant === "personalised" ? "We think you might like these streams - Streamers recommended for you" - : "Streamers that are currently live" + : "Popular streamers that are currently live!" } items={streams} wrap={false} @@ -62,7 +62,7 @@ const HomePage: React.FC = ({ variant = "default" }) => { description={ variant === "personalised" ? "Current streams from your followed categories" - : "Categories that have been 'popping off' lately" + : "Recently popular categories lately!" } items={categories} wrap={false} diff --git a/web_server/blueprints/streams.py b/web_server/blueprints/streams.py index a0a13c1..defffd5 100644 --- a/web_server/blueprints/streams.py +++ b/web_server/blueprints/streams.py @@ -73,10 +73,11 @@ def stream_data(streamer_id): ## Category Routes @stream_bp.route('/categories/popular/') @stream_bp.route('/categories/popular//') -def popular_categories(no_categories, offset=0) -> list[dict]: +def popular_categories(no_categories=4, offset=0) -> list[dict]: """ Returns a list of most popular categories """ + print(no_categories, offset, flush=True) # Limit the number of categories to 100 if no_categories < 1: return jsonify([]) diff --git a/web_server/database/app.db b/web_server/database/app.db index 2dca23a..3f252dd 100644 Binary files a/web_server/database/app.db and b/web_server/database/app.db differ diff --git a/web_server/database/testing_data.sql b/web_server/database/testing_data.sql index ed83017..93abead 100644 --- a/web_server/database/testing_data.sql +++ b/web_server/database/testing_data.sql @@ -45,20 +45,44 @@ INSERT INTO followed_categories (user_id, category_id) VALUES (5, 5); -- Sample Data for categories -INSERT INTO categories (category_name) VALUES -('Gaming'), -('Music'), -('Art'), -('Education'), -('Sports'); +INSERT INTO categories (category_name) VALUES +('Gaming'), +('Music'), +('Art'), +('Education'), +('Sports'), +('League of Legends'), +('Fortnite'), +('Minecraft'), +('Call of Duty'), +('Counter-Strike 2'), +('Valorant'), +('Dota 2'), +('Apex Legends'), +('Grand Theft Auto V'), +('The Legend of Zelda: Breath of the Wild'), +('Elden Ring'), +('Red Dead Redemption 2'), +('Cyberpunk 2077'), +('Super Smash Bros. Ultimate'), +('Overwatch 2'), +('Genshin Impact'), +('World of Warcraft'), +('Rocket League'), +('FIFA 24'), +('The Sims 4'), +('Among Us'), +('Dead by Daylight'), +('Hogwarts Legacy'); + -- Sample Data for streams -INSERT INTO streams (user_id, title, start_time, num_viewers, category_id) VALUES -(1, 'Game on!', '2025-02-16 17:00:00', 5, 1), -(2, 'Live Music Jam', '2025-01-25 20:00:00', 350, 2), -(3, 'Sketching Live', '2025-01-24 15:00:00', 80, 3), -(4, 'Math Made Easy', '2025-01-23 10:00:00', 400, 4), -(5, 'Sports Highlights', '2025-02-15 23:00:00', 210, 5); +INSERT INTO streams (user_id, title, start_time, category_id) VALUES +(1, 'Game on!', '2025-02-16 17:00:00', 1), +(2, 'Live Music Jam', '2025-01-25 20:00:00', 2), +(3, 'Sketching Live', '2025-01-24 15:00:00', 3), +(4, 'Math Made Easy', '2025-01-23 10:00:00', 4), +(5, 'Sports Highlights', '2025-02-15 23:00:00', 5); -- Sample Data for vods INSERT INTO vods (user_id, title, datetime, category_id, length, views) VALUES @@ -117,23 +141,4 @@ SELECT * FROM categories; SELECT * FROM streams; SELECT * FROM chat; SELECT * FROM tags; -SELECT * FROM stream_tags; - --- To see all tables in the database -SELECT name FROM sqlite_master WHERE type='table'; - --- UPDATE users SET is_live = 0 WHERE user_id = 1; - -SELECT users.user_id, streams.title, streams.num_viewers, users.username -FROM streams JOIN users -ON streams.user_id = users.user_id -WHERE users.user_id IN -(SELECT followed_id FROM follows WHERE user_id = 1) -AND users.is_live = 1; - -SELECT categories.category_id, categories.category_name, SUM(streams.num_viewers) AS total_viewers -FROM streams -JOIN categories ON streams.category_id = categories.category_id -GROUP BY categories.category_name -ORDER BY SUM(streams.num_viewers) DESC -LIMIT 10; +SELECT * FROM stream_tags; \ No newline at end of file diff --git a/web_server/utils/recommendation_utils.py b/web_server/utils/recommendation_utils.py index 347c6d6..63bf416 100644 --- a/web_server/utils/recommendation_utils.py +++ b/web_server/utils/recommendation_utils.py @@ -72,11 +72,11 @@ def get_highest_view_categories(no_categories: int = 4, offset: int = 0) -> Opti """ with Database() as db: categories = db.fetchall(""" - SELECT categories.category_id, categories.category_name, SUM(streams.num_viewers) AS num_viewers - FROM streams - JOIN categories ON streams.category_id = categories.category_id - GROUP BY categories.category_name - ORDER BY SUM(streams.num_viewers) DESC + SELECT categories.category_id, categories.category_name, COALESCE(SUM(streams.num_viewers), 0) AS num_viewers + FROM categories + LEFT JOIN streams ON streams.category_id = categories.category_id + GROUP BY categories.category_id, categories.category_name + ORDER BY num_viewers DESC LIMIT ? OFFSET ?; """, (no_categories, offset)) return categories