diff options
| author | Wolfboy248 <georgejvindkarlsen@gmail.com> | 2025-08-25 09:36:51 +0200 |
|---|---|---|
| committer | Wolfboy248 <georgejvindkarlsen@gmail.com> | 2025-08-25 09:36:51 +0200 |
| commit | 246eabe4a46d2585d653738e46089ed2bfada8bd (patch) | |
| tree | c86dd05119b0aa086a5d5401dd6a48d90a6f3bbd /frontend/src/components/Sidebar/Content.tsx | |
| parent | Reorganised Maplist and Sidebar (diff) | |
| download | lphub-246eabe4a46d2585d653738e46089ed2bfada8bd.tar.gz lphub-246eabe4a46d2585d653738e46089ed2bfada8bd.tar.bz2 lphub-246eabe4a46d2585d653738e46089ed2bfada8bd.zip | |
Restructured sidebar and implemented links var
Diffstat (limited to 'frontend/src/components/Sidebar/Content.tsx')
| -rw-r--r-- | frontend/src/components/Sidebar/Content.tsx | 117 |
1 files changed, 19 insertions, 98 deletions
diff --git a/frontend/src/components/Sidebar/Content.tsx b/frontend/src/components/Sidebar/Content.tsx index 4051b08..3d9533a 100644 --- a/frontend/src/components/Sidebar/Content.tsx +++ b/frontend/src/components/Sidebar/Content.tsx | |||
| @@ -1,124 +1,45 @@ | |||
| 1 | import React, { useRef } from "react"; | 1 | import React, { useRef } from "react"; |
| 2 | import { Link } from "react-router-dom"; | 2 | import { Link, useLocation } from "react-router-dom"; |
| 3 | import { UserProfile } from "@customTypes/Profile"; | 3 | import { UserProfile } from "@customTypes/Profile"; |
| 4 | import { Search } from "@customTypes/Search"; | ||
| 5 | import { API } from "@api/Api"; | ||
| 6 | 4 | ||
| 7 | import styles from "./Sidebar.module.css"; | 5 | import styles from "./Sidebar.module.css"; |
| 8 | 6 | ||
| 9 | import { | 7 | import { |
| 10 | FlagIcon, | ||
| 11 | HomeIcon, | ||
| 12 | PortalIcon, | ||
| 13 | SearchIcon, | 8 | SearchIcon, |
| 14 | } from "../../images/Images"; | 9 | } from "../../images/Images"; |
| 15 | 10 | ||
| 11 | import links from "./Links"; | ||
| 12 | |||
| 16 | interface ContentProps { | 13 | interface ContentProps { |
| 17 | profile?: UserProfile; | 14 | profile?: UserProfile; |
| 15 | isSearching: boolean; | ||
| 16 | selectedButtonIndex: number | ||
| 18 | isSidebarOpen: boolean; | 17 | isSidebarOpen: boolean; |
| 19 | sidebarButtonRefs: React.RefObject<(HTMLButtonElement | null)[]>; | ||
| 20 | getButtonClasses: (buttonIndex: number) => string; | ||
| 21 | handle_sidebar_click: (clicked_sidebar_idx: number) => void; | 18 | handle_sidebar_click: (clicked_sidebar_idx: number) => void; |
| 22 | }; | 19 | }; |
| 23 | 20 | ||
| 24 | const Content: React.FC<ContentProps> = ({ profile, isSidebarOpen, sidebarButtonRefs, getButtonClasses, handle_sidebar_click }) => { | 21 | const _Content: React.FC<ContentProps> = ({ profile, isSearching, selectedButtonIndex, isSidebarOpen, handle_sidebar_click }) => { |
| 25 | const [searchData, setSearchData] = React.useState<Search | undefined>( | ||
| 26 | undefined | ||
| 27 | ); | ||
| 28 | |||
| 29 | const searchbarRef = useRef<HTMLInputElement>(null); | ||
| 30 | |||
| 31 | const _handle_search_change = async (q: string) => { | ||
| 32 | const searchResponse = await API.get_search(q); | ||
| 33 | setSearchData(searchResponse); | ||
| 34 | }; | ||
| 35 | |||
| 36 | const iconClasses = ""; | ||
| 37 | 22 | ||
| 38 | return ( | 23 | return ( |
| 39 | <div className="h-full"> | 24 | <div className="h-full"> |
| 40 | 25 | ||
| 41 | <div className="px-2"> | 26 | <div className="px-2 my-2.5"> |
| 42 | <div className={`${styles.button}`}> | 27 | <button onClick={() => handle_sidebar_click(0)} className={`${styles.button} ${selectedButtonIndex == 0 ? styles["button-selected"] : ""} ${isSearching ? styles["button-hidden"] : ""}`}> |
| 43 | <img src={SearchIcon} alt="Search" className={iconClasses} /> | 28 | <img src={SearchIcon} alt="Search" /> |
| 44 | <span className="text-white font-[--font-barlow-semicondensed-regular] truncate">Search</span> | 29 | <span>Search</span> |
| 45 | </div> | 30 | </button> |
| 46 | |||
| 47 | <div className="min-w-0"> | ||
| 48 | <input | ||
| 49 | ref={searchbarRef} | ||
| 50 | type="text" | ||
| 51 | id="searchbar" | ||
| 52 | placeholder="Search for map or a player..." | ||
| 53 | onChange={e => _handle_search_change(e.target.value)} | ||
| 54 | className="w-full p-2 bg-input text-foreground border border-border rounded-lg text-sm min-w-0" | ||
| 55 | /> | ||
| 56 | |||
| 57 | {searchData && ( | ||
| 58 | <div className="mt-2 max-h-40 overflow-y-auto min-w-0"> | ||
| 59 | {searchData?.maps.map((q, index) => ( | ||
| 60 | <Link to={`/maps/${q.id}`} className="block p-2 mb-1 bg-surface1 rounded hover:bg-surface2 transition-colors min-w-0" key={index}> | ||
| 61 | <span className="block text-xs text-subtext1 truncate">{q.game}</span> | ||
| 62 | <span className="block text-xs text-subtext1 truncate">{q.chapter}</span> | ||
| 63 | <span className="block text-sm text-foreground truncate">{q.map}</span> | ||
| 64 | </Link> | ||
| 65 | ))} | ||
| 66 | {searchData?.players.map((q, index) => ( | ||
| 67 | <Link | ||
| 68 | to={ | ||
| 69 | profile && q.steam_id === profile.steam_id | ||
| 70 | ? `/profile` | ||
| 71 | : `/users/${q.steam_id}` | ||
| 72 | } | ||
| 73 | className="flex items-center p-2 mb-1 bg-surface1 rounded hover:bg-surface2 transition-colors min-w-0" | ||
| 74 | key={index} | ||
| 75 | > | ||
| 76 | <img src={q.avatar_link} alt="pfp" className="w-6 h-6 rounded-full mr-2 flex-shrink-0" /> | ||
| 77 | <span className="text-sm text-foreground truncate"> | ||
| 78 | {q.user_name} | ||
| 79 | </span> | ||
| 80 | </Link> | ||
| 81 | ))} | ||
| 82 | </div> | ||
| 83 | )} | ||
| 84 | </div> | ||
| 85 | </div> | 31 | </div> |
| 86 | 32 | ||
| 87 | <div className="flex-1 min-w-0"> | 33 | <div className="flex-1 min-w-0 mt-12"> |
| 88 | <nav className="px-2 flex flex-col gap-2"> | 34 | <nav className="px-2 flex flex-col gap-2"> |
| 89 | {[ | 35 | {links.content.map(({ to, icon, label }, i) => ( |
| 90 | { | 36 | <Link to={to} tabIndex={-1} key={i + 1}> |
| 91 | to: "/", | ||
| 92 | refIndex: 1, | ||
| 93 | icon: HomeIcon, | ||
| 94 | alt: "Home", | ||
| 95 | label: "Home Page", | ||
| 96 | }, | ||
| 97 | { | ||
| 98 | to: "/games", | ||
| 99 | refIndex: 2, | ||
| 100 | icon: PortalIcon, | ||
| 101 | alt: "Games", | ||
| 102 | label: "Games", | ||
| 103 | }, | ||
| 104 | { | ||
| 105 | to: "/rankings", | ||
| 106 | refIndex: 3, | ||
| 107 | icon: FlagIcon, | ||
| 108 | alt: "Rankings", | ||
| 109 | label: "Rankings", | ||
| 110 | }, | ||
| 111 | ].map(({ to, refIndex, icon, alt, label }) => ( | ||
| 112 | <Link to={to} tabIndex={-1} key={refIndex}> | ||
| 113 | <button | 37 | <button |
| 114 | ref={el => { | 38 | className={`${styles.button} ${selectedButtonIndex == i + 1 ? styles["button-selected"] : ""} ${isSearching ? styles["button-hidden"] : ""}`} |
| 115 | sidebarButtonRefs.current[refIndex] = el | 39 | onClick={() => handle_sidebar_click(i + 1)} |
| 116 | }} | ||
| 117 | className={`${styles.button}`} | ||
| 118 | onClick={() => handle_sidebar_click(refIndex)} | ||
| 119 | > | 40 | > |
| 120 | <img src={icon} alt={alt} className={iconClasses} /> | 41 | <img src={icon} /> |
| 121 | <span className=""> | 42 | <span> |
| 122 | {label} | 43 | {label} |
| 123 | </span> | 44 | </span> |
| 124 | </button> | 45 | </button> |
| @@ -130,4 +51,4 @@ const Content: React.FC<ContentProps> = ({ profile, isSidebarOpen, sidebarButton | |||
| 130 | ); | 51 | ); |
| 131 | } | 52 | } |
| 132 | 53 | ||
| 133 | export default Content; | 54 | export default _Content; |