diff options
Diffstat (limited to 'frontend/src/pages/Maps.tsx')
| -rw-r--r-- | frontend/src/pages/Maps.tsx | 166 |
1 files changed, 120 insertions, 46 deletions
diff --git a/frontend/src/pages/Maps.tsx b/frontend/src/pages/Maps.tsx index fb13563..50fe03b 100644 --- a/frontend/src/pages/Maps.tsx +++ b/frontend/src/pages/Maps.tsx | |||
| @@ -1,28 +1,32 @@ | |||
| 1 | import React from 'react'; | 1 | import React from "react"; |
| 2 | import { Link, useLocation } from 'react-router-dom'; | 2 | import { Link, useLocation } from "react-router-dom"; |
| 3 | import { Helmet } from 'react-helmet'; | 3 | import { Helmet } from "react-helmet"; |
| 4 | 4 | ||
| 5 | import { PortalIcon, FlagIcon, ChatIcon } from '@images/Images'; | 5 | import { PortalIcon, FlagIcon, ChatIcon } from "../images/Images"; |
| 6 | import Summary from '@components/Summary'; | 6 | import Summary from "@components/Summary"; |
| 7 | import Leaderboards from '@components/Leaderboards'; | 7 | import Leaderboards from "@components/Leaderboards"; |
| 8 | import Discussions from '@components/Discussions'; | 8 | import Discussions from "@components/Discussions"; |
| 9 | import ModMenu from '@components/ModMenu'; | 9 | import ModMenu from "@components/ModMenu"; |
| 10 | import { MapDiscussions, MapLeaderboard, MapSummary } from '@customTypes/Map'; | 10 | import { MapDiscussions, MapLeaderboard, MapSummary } from "@customTypes/Map"; |
| 11 | import { API } from '@api/Api'; | 11 | import { API } from "@api/Api"; |
| 12 | import "@css/Maps.css"; | ||
| 13 | 12 | ||
| 14 | interface MapProps { | 13 | interface MapProps { |
| 15 | token?: string; | 14 | token?: string; |
| 16 | isModerator: boolean; | 15 | isModerator: boolean; |
| 17 | }; | 16 | } |
| 18 | 17 | ||
| 19 | const Maps: React.FC<MapProps> = ({ token, isModerator }) => { | 18 | const Maps: React.FC<MapProps> = ({ token, isModerator }) => { |
| 20 | |||
| 21 | const [selectedRun, setSelectedRun] = React.useState<number>(0); | 19 | const [selectedRun, setSelectedRun] = React.useState<number>(0); |
| 22 | 20 | ||
| 23 | const [mapSummaryData, setMapSummaryData] = React.useState<MapSummary | undefined>(undefined); | 21 | const [mapSummaryData, setMapSummaryData] = React.useState< |
| 24 | const [mapLeaderboardData, setMapLeaderboardData] = React.useState<MapLeaderboard | undefined>(undefined); | 22 | MapSummary | undefined |
| 25 | const [mapDiscussionsData, setMapDiscussionsData] = React.useState<MapDiscussions | undefined>(undefined); | 23 | >(undefined); |
| 24 | const [mapLeaderboardData, setMapLeaderboardData] = React.useState< | ||
| 25 | MapLeaderboard | undefined | ||
| 26 | >(undefined); | ||
| 27 | const [mapDiscussionsData, setMapDiscussionsData] = React.useState< | ||
| 28 | MapDiscussions | undefined | ||
| 29 | >(undefined); | ||
| 26 | 30 | ||
| 27 | const [navState, setNavState] = React.useState<number>(0); | 31 | const [navState, setNavState] = React.useState<number>(0); |
| 28 | 32 | ||
| @@ -30,45 +34,66 @@ const Maps: React.FC<MapProps> = ({ token, isModerator }) => { | |||
| 30 | 34 | ||
| 31 | const mapID = location.pathname.split("/")[2]; | 35 | const mapID = location.pathname.split("/")[2]; |
| 32 | 36 | ||
| 33 | const _fetch_map_summary = async () => { | 37 | const _fetch_map_summary = React.useCallback(async () => { |
| 34 | const mapSummary = await API.get_map_summary(mapID); | 38 | const mapSummary = await API.get_map_summary(mapID); |
| 35 | setMapSummaryData(mapSummary); | 39 | setMapSummaryData(mapSummary); |
| 36 | }; | 40 | }, [mapID]); |
| 37 | 41 | ||
| 38 | const _fetch_map_leaderboards = async () => { | 42 | const _fetch_map_leaderboards = React.useCallback(async () => { |
| 39 | const mapLeaderboards = await API.get_map_leaderboard(mapID, "1"); | 43 | const mapLeaderboards = await API.get_map_leaderboard(mapID, "1"); |
| 40 | setMapLeaderboardData(mapLeaderboards); | 44 | setMapLeaderboardData(mapLeaderboards); |
| 41 | }; | 45 | }, [mapID]); |
| 42 | 46 | ||
| 43 | const _fetch_map_discussions = async () => { | 47 | const _fetch_map_discussions = React.useCallback(async () => { |
| 44 | const mapDiscussions = await API.get_map_discussions(mapID); | 48 | const mapDiscussions = await API.get_map_discussions(mapID); |
| 45 | setMapDiscussionsData(mapDiscussions); | 49 | setMapDiscussionsData(mapDiscussions); |
| 46 | }; | 50 | }, [mapID]); |
| 47 | 51 | ||
| 48 | React.useEffect(() => { | 52 | React.useEffect(() => { |
| 49 | _fetch_map_summary(); | 53 | _fetch_map_summary(); |
| 50 | _fetch_map_leaderboards(); | 54 | _fetch_map_leaderboards(); |
| 51 | _fetch_map_discussions(); | 55 | _fetch_map_discussions(); |
| 52 | }, [mapID]); | 56 | }, [ |
| 57 | mapID, | ||
| 58 | _fetch_map_discussions, | ||
| 59 | _fetch_map_leaderboards, | ||
| 60 | _fetch_map_summary, | ||
| 61 | ]); | ||
| 53 | 62 | ||
| 54 | if (!mapSummaryData) { | 63 | if (!mapSummaryData) { |
| 55 | // loading placeholder | 64 | // loading placeholder |
| 56 | return ( | 65 | return ( |
| 57 | <> | 66 | <> |
| 58 | <main> | 67 | <main className="*:text-foreground relative left-0 w-[calc(100%-20rem)] min-h-screen p-4 sm:p-8"> |
| 59 | <section id='section1' className='summary1'> | 68 | <section id="section1" className="summary1"> |
| 60 | <div> | 69 | <div> |
| 61 | <Link to="/games"><button className='nav-button' style={{ borderRadius: "20px 20px 20px 20px" }}><i className='triangle'></i><span>Games List</span></button></Link> | 70 | <Link to="/games"> |
| 71 | <button | ||
| 72 | className="nav-button rounded-[20px] h-10 bg-surface border-0 text-foreground text-lg font-[--font-barlow-semicondensed-regular] transition-colors duration-100 hover:bg-surface2 flex items-center px-2" | ||
| 73 | > | ||
| 74 | <i className="triangle"></i> | ||
| 75 | <span className="px-2">Games List</span> | ||
| 76 | </button> | ||
| 77 | </Link> | ||
| 62 | </div> | 78 | </div> |
| 63 | </section> | 79 | </section> |
| 64 | 80 | ||
| 65 | <section id='section2' className='summary1'> | 81 | <section id="section2" className="summary1 mt-4 flex gap-2 flex-wrap"> |
| 66 | <button className='nav-button'><img src={PortalIcon} alt="" /><span>Summary</span></button> | 82 | <button className="nav-button"> |
| 67 | <button className='nav-button'><img src={FlagIcon} alt="" /><span>Leaderboards</span></button> | 83 | <img src={PortalIcon} alt="" className="w-5 h-5 sm:w-6 sm:h-6" /> |
| 68 | <button className='nav-button'><img src={ChatIcon} alt="" /><span>Discussions</span></button> | 84 | <span>Summary</span> |
| 85 | </button> | ||
| 86 | <button className="nav-button"> | ||
| 87 | <img src={FlagIcon} alt="" className="w-5 h-5 sm:w-6 sm:h-6" /> | ||
| 88 | <span>Leaderboards</span> | ||
| 89 | </button> | ||
| 90 | <button className="nav-button"> | ||
| 91 | <img src={ChatIcon} alt="" className="w-5 h-5 sm:w-6 sm:h-6" /> | ||
| 92 | <span>Discussions</span> | ||
| 93 | </button> | ||
| 69 | </section> | 94 | </section> |
| 70 | 95 | ||
| 71 | <section id='section6' className='summary2' /> | 96 | <section id="section6" className="summary2 mt-4" /> |
| 72 | </main> | 97 | </main> |
| 73 | </> | 98 | </> |
| 74 | ); | 99 | ); |
| @@ -80,29 +105,78 @@ const Maps: React.FC<MapProps> = ({ token, isModerator }) => { | |||
| 80 | <title>LPHUB | {mapSummaryData.map.map_name}</title> | 105 | <title>LPHUB | {mapSummaryData.map.map_name}</title> |
| 81 | <meta name="description" content={mapSummaryData.map.map_name} /> | 106 | <meta name="description" content={mapSummaryData.map.map_name} /> |
| 82 | </Helmet> | 107 | </Helmet> |
| 83 | {isModerator && <ModMenu token={token} data={mapSummaryData} selectedRun={selectedRun} mapID={mapID} />} | 108 | {isModerator && ( |
| 84 | 109 | <ModMenu | |
| 85 | <div id='background-image'> | 110 | token={token} |
| 111 | data={mapSummaryData} | ||
| 112 | selectedRun={selectedRun} | ||
| 113 | mapID={mapID} | ||
| 114 | /> | ||
| 115 | )} | ||
| 116 | |||
| 117 | <div id="background-image"> | ||
| 86 | <img src={mapSummaryData.map.image} alt="" /> | 118 | <img src={mapSummaryData.map.image} alt="" /> |
| 87 | </div> | 119 | </div> |
| 88 | <main> | 120 | <main className="relative left-0 w-full sm:ml-80 sm:w-[calc(100%-20rem)] min-h-screen max-h-screen overflow-y-auto p-4 sm:p-8 scrollbar-thin scrollbar-track-surface scrollbar-thumb-muted hover:scrollbar-thumb-surface1"> |
| 89 | <section id='section1' className='summary1'> | 121 | <section id="section1" className="summary1"> |
| 90 | <div> | 122 | <div> |
| 91 | <Link to="/games"><button className='nav-button' style={{ borderRadius: "20px 0px 0px 20px" }}><i className='triangle'></i><span>Games List</span></button></Link> | 123 | <Link to="/games"> |
| 92 | <Link to={`/games/${mapSummaryData.map.is_coop ? "2" : "1"}?chapter=${mapSummaryData.map.chapter_name.split(" ")[1]}`}><button className='nav-button' style={{ borderRadius: "0px 20px 20px 0px", marginLeft: "2px" }}><i className='triangle'></i><span>{mapSummaryData.map.chapter_name}</span></button></Link> | 124 | <button |
| 93 | <br /><span><b>{mapSummaryData.map.map_name}</b></span> | 125 | className="nav-button rounded-[20px] h-10 bg-surface border-0 text-foreground text-lg font-[--font-barlow-semicondensed-regular] transition-colors duration-100 hover:bg-surface2 flex items-center px-2" |
| 126 | > | ||
| 127 | <i className="triangle"></i> | ||
| 128 | <span className="px-2">Games List</span> | ||
| 129 | </button> | ||
| 130 | </Link> | ||
| 131 | <Link | ||
| 132 | to={`/games/${mapSummaryData.map.is_coop ? "2" : "1"}?chapter=${mapSummaryData.map.chapter_name.split(" ")[1]}`} | ||
| 133 | > | ||
| 134 | <button | ||
| 135 | className="nav-button ml-2" | ||
| 136 | > | ||
| 137 | <i className="triangle"></i> | ||
| 138 | <span className="px-2">{mapSummaryData.map.chapter_name}</span> | ||
| 139 | </button> | ||
| 140 | </Link> | ||
| 141 | <br /> | ||
| 142 | <span className="block mt-2 text-lg sm:text-xl text-foreground"> | ||
| 143 | <b>{mapSummaryData.map.map_name}</b> | ||
| 144 | </span> | ||
| 94 | </div> | 145 | </div> |
| 95 | </section> | 146 | </section> |
| 96 | 147 | ||
| 97 | <section id='section2' className='summary1'> | 148 | <section id="section2" className="summary1 mt-4 flex gap-2 flex-wrap"> |
| 98 | <button className='nav-button' onClick={() => setNavState(0)}><img src={PortalIcon} alt="" /><span>Summary</span></button> | 149 | <button className="nav-button" onClick={() => setNavState(0)}> |
| 99 | <button className='nav-button' onClick={() => setNavState(1)}><img src={FlagIcon} alt="" /><span>Leaderboards</span></button> | 150 | <img src={PortalIcon} alt="" className="w-5 h-5 sm:w-6 sm:h-6" /> |
| 100 | <button className='nav-button' onClick={() => setNavState(2)}><img src={ChatIcon} alt="" /><span>Discussions</span></button> | 151 | <span>Summary</span> |
| 152 | </button> | ||
| 153 | <button className="nav-button" onClick={() => setNavState(1)}> | ||
| 154 | <img src={FlagIcon} alt="" className="w-5 h-5 sm:w-6 sm:h-6" /> | ||
| 155 | <span>Leaderboards</span> | ||
| 156 | </button> | ||
| 157 | <button className="nav-button" onClick={() => setNavState(2)}> | ||
| 158 | <img src={ChatIcon} alt="" className="w-5 h-5 sm:w-6 sm:h-6" /> | ||
| 159 | <span>Discussions</span> | ||
| 160 | </button> | ||
| 101 | </section> | 161 | </section> |
| 102 | 162 | ||
| 103 | {navState === 0 && <Summary selectedRun={selectedRun} setSelectedRun={setSelectedRun} data={mapSummaryData} />} | 163 | {navState === 0 && ( |
| 164 | <Summary | ||
| 165 | selectedRun={selectedRun} | ||
| 166 | setSelectedRun={setSelectedRun} | ||
| 167 | data={mapSummaryData} | ||
| 168 | /> | ||
| 169 | )} | ||
| 104 | {navState === 1 && <Leaderboards mapID={mapID} />} | 170 | {navState === 1 && <Leaderboards mapID={mapID} />} |
| 105 | {navState === 2 && <Discussions data={mapDiscussionsData} token={token} isModerator={isModerator} mapID={mapID} onRefresh={() => _fetch_map_discussions()} />} | 171 | {navState === 2 && ( |
| 172 | <Discussions | ||
| 173 | data={mapDiscussionsData} | ||
| 174 | token={token} | ||
| 175 | isModerator={isModerator} | ||
| 176 | mapID={mapID} | ||
| 177 | onRefresh={() => _fetch_map_discussions()} | ||
| 178 | /> | ||
| 179 | )} | ||
| 106 | </main> | 180 | </main> |
| 107 | </> | 181 | </> |
| 108 | ); | 182 | ); |