diff --git a/frontend/src/components/Input/Button.tsx b/frontend/src/components/Input/Button.tsx index 5ceb21f..1ade1a3 100644 --- a/frontend/src/components/Input/Button.tsx +++ b/frontend/src/components/Input/Button.tsx @@ -15,7 +15,7 @@ const Button: React.FC = ({ return ( + + {title.includes("🔴") && ( +

+ Currently Live! +

+ )} + + + ); + } return (
= ({

{title}

- {type === "stream" &&

{streamer}

} + {type === "stream" &&

{username}

} {type === "stream" && (

{streamCategory}

)} diff --git a/frontend/src/components/Layout/ListRow.tsx b/frontend/src/components/Layout/ListRow.tsx index dca19f5..1f3e6cb 100644 --- a/frontend/src/components/Layout/ListRow.tsx +++ b/frontend/src/components/Layout/ListRow.tsx @@ -5,32 +5,41 @@ import { } from "lucide-react"; import "../../assets/styles/listRow.css"; import ListItem, { ListItemProps } from "./ListItem"; +import { useNavigate } from "react-router-dom"; interface ListRowProps { + variant?: "default" | "search"; type: "stream" | "category" | "user"; title?: string; description?: string; items: ListItemProps[]; - wrap: boolean; + wrap?: boolean; onClick: (itemName: string) => void; + titleClickable?: boolean; extraClasses?: string; itemExtraClasses?: string; + amountForScroll?: number; children?: React.ReactNode; } // Row of entries const ListRow: React.FC = ({ + variant = "default", + type, title = "", description = "", items, - wrap, + wrap = false, + titleClickable = false, onClick, extraClasses = "", itemExtraClasses = "", + amountForScroll = 4, children, }) => { const slider = useRef(null); const scrollAmount = window.innerWidth * 0.3; + const navigate = useNavigate(); const slideRight = () => { if (!wrap && slider.current) { @@ -44,17 +53,46 @@ const ListRow: React.FC = ({ } }; + const handleTitleClick = (type: string) => { + switch (type) { + case "stream": + break; + case "category": + navigate("/categories"); + break; + case "user": + break; + default: + break; + } + }; + return (
-
-

{title}

+
+

handleTitleClick(type) : undefined} + > + {title} +

{description}

-
- {!wrap && items.length > 4 && ( +
+ {!wrap && items.length > amountForScroll && ( <> = ({ ref={slider} className={`flex ${ wrap ? "flex-wrap" : "overflow-x-scroll whitespace-nowrap" - } max-w-[95%] items-center justify-between scroll-smooth scrollbar-hide gap-5 mx-auto`} + } max-w-[95%] items-center justify-evenly w-full mx-auto scroll-smooth scrollbar-hide gap-5`} > - {items.map((item) => ( - item.type === "stream" && item.streamer - ? onClick?.(item.streamer) + (item.type === "stream" || item.type === "user") && + item.username + ? onClick?.(item.username) : onClick?.(item.title) } extraClasses={`${itemExtraClasses} min-w-[20vw]`} @@ -104,4 +142,4 @@ const ListRow: React.FC = ({ ); }; -export default ListRow; \ No newline at end of file +export default ListRow; diff --git a/frontend/src/components/Layout/Logo.tsx b/frontend/src/components/Layout/Logo.tsx index c693d38..b877baa 100644 --- a/frontend/src/components/Layout/Logo.tsx +++ b/frontend/src/components/Layout/Logo.tsx @@ -2,17 +2,21 @@ import React from "react"; interface LogoProps { variant?: "home" | "default"; + extraClasses?: string; } -const Logo: React.FC = ({ variant = "default" }) => { +const Logo: React.FC = ({ + variant = "default", + extraClasses = "", +}) => { const gradient = "text-transparent group-hover:mx-1 transition-all"; return ( @@ -207,8 +200,12 @@ const UserPage: React.FC = () => { {userPageVariant.toUpperCase()}
-

About {profileData.username}

-

{profileData.bio}

+

+ About {profileData.username} +

+

+ {profileData.bio} +

@@ -298,13 +295,9 @@ const UserPage: React.FC = () => {
- -
{showAuthModal && setShowAuthModal(false)} />} - - ); }; diff --git a/web_server/blueprints/search_bar.py b/web_server/blueprints/search_bar.py index cf14190..15def37 100644 --- a/web_server/blueprints/search_bar.py +++ b/web_server/blueprints/search_bar.py @@ -41,10 +41,11 @@ def search_results(): # 3 streams streams = db.fetchall(""" - SELECT bm25(stream_fts) AS score, s.user_id, s.title, s.num_viewers, s.category_id, u.username + SELECT bm25(stream_fts) AS score, s.user_id, s.title, s.num_viewers, c.category_name, u.username FROM streams AS s INNER JOIN stream_fts AS f ON s.user_id = f.user_id INNER JOIN users AS u ON s.user_id = u.user_id + INNER JOIN categories AS c ON s.category_id = c.category_id WHERE f.title LIKE '%' || ? || '%' ORDER BY score ASC LIMIT 3; @@ -54,7 +55,7 @@ def search_results(): print(query, streams, users, categories, flush=True) - return jsonify({"categories": categories, "users": users, "streams": streams}) + return jsonify({"streams": streams, "categories": categories, "users": users}) @search_bp.route("/search/categories", methods=["GET", "POST"]) def search_categories():