aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/components/Sidebar.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/components/Sidebar.tsx')
-rw-r--r--frontend/src/components/Sidebar.tsx183
1 files changed, 183 insertions, 0 deletions
diff --git a/frontend/src/components/Sidebar.tsx b/frontend/src/components/Sidebar.tsx
new file mode 100644
index 0000000..a8834b6
--- /dev/null
+++ b/frontend/src/components/Sidebar.tsx
@@ -0,0 +1,183 @@
1import React from 'react';
2import { Link, useLocation } from 'react-router-dom';
3
4import { BookIcon, FlagIcon, HelpIcon, HomeIcon, LogoIcon, NewsIcon, PortalIcon, SearchIcon, TableIcon } from '../images/Images';
5import Login from './Login';
6import { UserProfile } from '../types/Profile';
7import { Search } from '../types/Search';
8import { API } from '../api/Api';
9import "../css/Sidebar.css";
10
11interface SidebarProps {
12 setToken: React.Dispatch<React.SetStateAction<string | undefined>>;
13 profile?: UserProfile;
14 setProfile: React.Dispatch<React.SetStateAction<UserProfile | undefined>>;
15};
16
17const Sidebar: React.FC<SidebarProps> = ({ setToken, profile, setProfile }) => {
18
19 const [searchData, setSearchData] = React.useState<Search | undefined>(undefined);
20 const [isSidebarLocked, setIsSidebarLocked] = React.useState<boolean>(false);
21 const [isSidebarOpen, setSidebarOpen] = React.useState<boolean>(true);
22
23 const location = useLocation();
24 const path = location.pathname;
25
26 const handle_sidebar_click = (clicked_sidebar_idx: number) => {
27 const btn = document.querySelectorAll("button.sidebar-button");
28 if (isSidebarOpen) { setSidebarOpen(false); _handle_sidebar_hide() }
29 // clusterfuck
30 btn.forEach((e, i) => {
31 btn[i].classList.remove("sidebar-button-selected")
32 btn[i].classList.add("sidebar-button-deselected")
33 })
34 btn[clicked_sidebar_idx].classList.add("sidebar-button-selected")
35 btn[clicked_sidebar_idx].classList.remove("sidebar-button-deselected")
36 };
37
38 const _handle_sidebar_hide = () => {
39 var btn = document.querySelectorAll("button.sidebar-button") as NodeListOf<HTMLElement>
40 const span = document.querySelectorAll("button.sidebar-button>span") as NodeListOf<HTMLElement>
41 const side = document.querySelector("#sidebar-list") as HTMLElement;
42 const searchbar = document.querySelector("#searchbar") as HTMLInputElement;
43
44 if (isSidebarOpen) {
45 if (profile) {
46 const login = document.querySelectorAll(".login>button")[1] as HTMLElement;
47 login.style.opacity = "1"
48 }
49 setSidebarOpen(false);
50 side.style.width = "320px"
51 btn.forEach((e, i) => {
52 e.style.width = "310px"
53 e.style.padding = "0.4em 0 0 11px"
54 setTimeout(() => {
55 span[i].style.opacity = "1"
56 }, 100)
57 })
58 side.style.zIndex = "2"
59 } else {
60 if (profile) {
61 const login = document.querySelectorAll(".login>button")[1] as HTMLElement;
62 login.style.opacity = "0"
63 }
64 setSidebarOpen(true)
65 side.style.width = "40px";
66 searchbar.focus();
67 btn.forEach((e, i) => {
68 e.style.width = "40px"
69 e.style.padding = "0.4em 0 0 5px"
70 span[i].style.opacity = "0"
71 })
72 setTimeout(() => {
73 side.style.zIndex = "0"
74 }, 300);
75 }
76 };
77
78 const _handle_sidebar_lock = () => {
79 if (!isSidebarLocked) {
80 _handle_sidebar_hide()
81 setIsSidebarLocked(true);
82 setTimeout(() => setIsSidebarLocked(false), 300);
83 }
84 };
85
86 const _handle_search_change = async (q: string) => {
87 const searchResponse = await API.get_search(q);
88 setSearchData(searchResponse);
89 };
90
91 React.useEffect(() => {
92 if (path === "/") { handle_sidebar_click(1) }
93 else if (path.includes("news")) { handle_sidebar_click(2) }
94 else if (path.includes("games")) { handle_sidebar_click(3) }
95 else if (path.includes("leaderboards")) { handle_sidebar_click(4) }
96 else if (path.includes("scorelog")) { handle_sidebar_click(5) }
97 else if (path.includes("profile")) { handle_sidebar_click(6) }
98 else if (path.includes("rules")) { handle_sidebar_click(8) }
99 else if (path.includes("about")) { handle_sidebar_click(9) }
100 }, [path]);
101
102 return (
103 <div id='sidebar'>
104 <Link to="/" tabIndex={-1}>
105 <div id='logo'> {/* logo */}
106 <img src={LogoIcon} alt="" height={"80px"} />
107 <div id='logo-text'>
108 <span><b>PORTAL 2</b></span><br />
109 <span>Least Portals</span>
110 </div>
111 </div>
112 </Link>
113 <div id='sidebar-list'> {/* List */}
114 <div id='sidebar-toplist'> {/* Top */}
115
116 <button className='sidebar-button' onClick={() => _handle_sidebar_lock()}><img src={SearchIcon} alt="" /><span>Search</span></button>
117
118 <span></span>
119
120 <Link to="/" tabIndex={-1}>
121 <button className='sidebar-button'><img src={HomeIcon} alt="homepage" /><span>Home&nbsp;Page</span></button>
122 </Link>
123
124 <Link to="/news" tabIndex={-1}>
125 <button className='sidebar-button'><img src={NewsIcon} alt="news" /><span>News</span></button>
126 </Link>
127
128 <Link to="/games" tabIndex={-1}>
129 <button className='sidebar-button'><img src={PortalIcon} alt="games" /><span>Games</span></button>
130 </Link>
131
132 <Link to="/leaderboards" tabIndex={-1}>
133 <button className='sidebar-button'><img src={FlagIcon} alt="leaderboards" /><span>Leaderboards</span></button>
134 </Link>
135
136 <Link to="/scorelog" tabIndex={-1}>
137 <button className='sidebar-button'><img src={TableIcon} alt="scorelogs" /><span>Score&nbsp;Logs</span></button>
138 </Link>
139 </div>
140 <div id='sidebar-bottomlist'>
141 <span></span>
142
143 <Login setToken={setToken} profile={profile} setProfile={setProfile} />
144
145 <Link to="/rules" tabIndex={-1}>
146 <button className='sidebar-button'><img src={BookIcon} alt="leaderboardrules" /><span>Leaderboard&nbsp;Rules</span></button>
147 </Link>
148
149 <Link to="/about" tabIndex={-1}>
150 <button className='sidebar-button'><img src={HelpIcon} alt="aboutp2lp" /><span>About&nbsp;P2LP</span></button>
151 </Link>
152 </div>
153 </div>
154 <div>
155 <input type="text" id='searchbar' placeholder='Search for map or a player...' onChange={(e) => _handle_search_change(e.target.value)} />
156
157 <div id='search-data'>
158
159 {searchData?.maps.map((q, index) => (
160 <Link to={`/maps/${q.id}`} className='search-map' key={index}>
161 <span>{q.game}</span>
162 <span>{q.chapter}</span>
163 <span>{q.map}</span>
164 </Link>
165 ))}
166 {searchData?.players.map((q, index) =>
167 (
168 <Link to={
169 profile && q.steam_id === profile.steam_id ? `/profile` :
170 `/users/${q.steam_id}`
171 } className='search-player' key={index}>
172 <img src={q.avatar_link} alt='pfp'></img>
173 <span style={{ fontSize: `${36 - q.user_name.length * 0.8}px` }}>{q.user_name}</span>
174 </Link>
175 ))}
176
177 </div>
178 </div>
179 </div>
180 );
181};
182
183export default Sidebar;