From a65d6d9127c3fa7f6a8ecaec5d1ffd1f47c2bc98 Mon Sep 17 00:00:00 2001
From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com>
Date: Tue, 3 Sep 2024 00:08:53 +0300
Subject: refactor: port to typescript

---
 frontend/src/components/Sidebar.tsx | 183 ++++++++++++++++++++++++++++++++++++
 1 file changed, 183 insertions(+)
 create mode 100644 frontend/src/components/Sidebar.tsx

(limited to 'frontend/src/components/Sidebar.tsx')

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 @@
+import React from 'react';
+import { Link, useLocation } from 'react-router-dom';
+
+import { BookIcon, FlagIcon, HelpIcon, HomeIcon, LogoIcon, NewsIcon, PortalIcon, SearchIcon, TableIcon } from '../images/Images';
+import Login from './Login';
+import { UserProfile } from '../types/Profile';
+import { Search } from '../types/Search';
+import { API } from '../api/Api';
+import "../css/Sidebar.css";
+
+interface SidebarProps {
+  setToken: React.Dispatch<React.SetStateAction<string | undefined>>;
+  profile?: UserProfile;
+  setProfile: React.Dispatch<React.SetStateAction<UserProfile | undefined>>;
+};
+
+const Sidebar: React.FC<SidebarProps> = ({ setToken, profile, setProfile }) => {
+
+  const [searchData, setSearchData] = React.useState<Search | undefined>(undefined);
+  const [isSidebarLocked, setIsSidebarLocked] = React.useState<boolean>(false);
+  const [isSidebarOpen, setSidebarOpen] = React.useState<boolean>(true);
+
+  const location = useLocation();
+  const path = location.pathname;
+
+  const handle_sidebar_click = (clicked_sidebar_idx: number) => {
+    const btn = document.querySelectorAll("button.sidebar-button");
+    if (isSidebarOpen) { setSidebarOpen(false); _handle_sidebar_hide() }
+    // clusterfuck
+    btn.forEach((e, i) => {
+      btn[i].classList.remove("sidebar-button-selected")
+      btn[i].classList.add("sidebar-button-deselected")
+    })
+    btn[clicked_sidebar_idx].classList.add("sidebar-button-selected")
+    btn[clicked_sidebar_idx].classList.remove("sidebar-button-deselected")
+  };
+
+  const _handle_sidebar_hide = () => {
+    var btn = document.querySelectorAll("button.sidebar-button") as NodeListOf<HTMLElement>
+    const span = document.querySelectorAll("button.sidebar-button>span") as NodeListOf<HTMLElement>
+    const side = document.querySelector("#sidebar-list") as HTMLElement;
+    const searchbar = document.querySelector("#searchbar") as HTMLInputElement;
+
+    if (isSidebarOpen) {
+      if (profile) {
+        const login = document.querySelectorAll(".login>button")[1] as HTMLElement;
+        login.style.opacity = "1"
+      }
+      setSidebarOpen(false);
+      side.style.width = "320px"
+      btn.forEach((e, i) => {
+        e.style.width = "310px"
+        e.style.padding = "0.4em 0 0 11px"
+        setTimeout(() => {
+          span[i].style.opacity = "1"
+        }, 100)
+      })
+      side.style.zIndex = "2"
+    } else {
+      if (profile) {
+        const login = document.querySelectorAll(".login>button")[1] as HTMLElement;
+        login.style.opacity = "0"
+      }
+      setSidebarOpen(true)
+      side.style.width = "40px";
+      searchbar.focus();
+      btn.forEach((e, i) => {
+        e.style.width = "40px"
+        e.style.padding = "0.4em 0 0 5px"
+        span[i].style.opacity = "0"
+      })
+      setTimeout(() => {
+        side.style.zIndex = "0"
+      }, 300);
+    }
+  };
+
+  const _handle_sidebar_lock = () => {
+    if (!isSidebarLocked) {
+      _handle_sidebar_hide()
+      setIsSidebarLocked(true);
+      setTimeout(() => setIsSidebarLocked(false), 300);
+    }
+  };
+
+  const _handle_search_change = async (q: string) => {
+    const searchResponse = await API.get_search(q);
+    setSearchData(searchResponse);
+  };
+
+  React.useEffect(() => {
+    if (path === "/") { handle_sidebar_click(1) }
+    else if (path.includes("news")) { handle_sidebar_click(2) }
+    else if (path.includes("games")) { handle_sidebar_click(3) }
+    else if (path.includes("leaderboards")) { handle_sidebar_click(4) }
+    else if (path.includes("scorelog")) { handle_sidebar_click(5) }
+    else if (path.includes("profile")) { handle_sidebar_click(6) }
+    else if (path.includes("rules")) { handle_sidebar_click(8) }
+    else if (path.includes("about")) { handle_sidebar_click(9) }
+  }, [path]);
+
+  return (
+    <div id='sidebar'>
+      <Link to="/" tabIndex={-1}>
+        <div id='logo'> {/* logo */}
+          <img src={LogoIcon} alt="" height={"80px"} />
+          <div id='logo-text'>
+            <span><b>PORTAL 2</b></span><br />
+            <span>Least Portals</span>
+          </div>
+        </div>
+      </Link>
+      <div id='sidebar-list'> {/* List */}
+        <div id='sidebar-toplist'> {/* Top */}
+
+          <button className='sidebar-button' onClick={() => _handle_sidebar_lock()}><img src={SearchIcon} alt="" /><span>Search</span></button>
+
+          <span></span>
+
+          <Link to="/" tabIndex={-1}>
+            <button className='sidebar-button'><img src={HomeIcon} alt="homepage" /><span>Home&nbsp;Page</span></button>
+          </Link>
+
+          <Link to="/news" tabIndex={-1}>
+            <button className='sidebar-button'><img src={NewsIcon} alt="news" /><span>News</span></button>
+          </Link>
+
+          <Link to="/games" tabIndex={-1}>
+            <button className='sidebar-button'><img src={PortalIcon} alt="games" /><span>Games</span></button>
+          </Link>
+
+          <Link to="/leaderboards" tabIndex={-1}>
+            <button className='sidebar-button'><img src={FlagIcon} alt="leaderboards" /><span>Leaderboards</span></button>
+          </Link>
+
+          <Link to="/scorelog" tabIndex={-1}>
+            <button className='sidebar-button'><img src={TableIcon} alt="scorelogs" /><span>Score&nbsp;Logs</span></button>
+          </Link>
+        </div>
+        <div id='sidebar-bottomlist'>
+          <span></span>
+
+          <Login setToken={setToken} profile={profile} setProfile={setProfile} />
+
+          <Link to="/rules" tabIndex={-1}>
+            <button className='sidebar-button'><img src={BookIcon} alt="leaderboardrules" /><span>Leaderboard&nbsp;Rules</span></button>
+          </Link>
+
+          <Link to="/about" tabIndex={-1}>
+            <button className='sidebar-button'><img src={HelpIcon} alt="aboutp2lp" /><span>About&nbsp;P2LP</span></button>
+          </Link>
+        </div>
+      </div>
+      <div>
+        <input type="text" id='searchbar' placeholder='Search for map or a player...' onChange={(e) => _handle_search_change(e.target.value)} />
+
+        <div id='search-data'>
+
+          {searchData?.maps.map((q, index) => (
+            <Link to={`/maps/${q.id}`} className='search-map' key={index}>
+              <span>{q.game}</span>
+              <span>{q.chapter}</span>
+              <span>{q.map}</span>
+            </Link>
+          ))}
+          {searchData?.players.map((q, index) =>
+          (
+            <Link to={
+              profile && q.steam_id === profile.steam_id ? `/profile` :
+                `/users/${q.steam_id}`
+            } className='search-player' key={index}>
+              <img src={q.avatar_link} alt='pfp'></img>
+              <span style={{ fontSize: `${36 - q.user_name.length * 0.8}px` }}>{q.user_name}</span>
+            </Link>
+          ))}
+
+        </div>
+      </div>
+    </div>
+  );
+};
+
+export default Sidebar;
-- 
cgit v1.2.3

