diff options
| author | FifthWit <fifthwitbusiness@gmail.com> | 2025-01-30 10:39:41 -0600 |
|---|---|---|
| committer | FifthWit <fifthwitbusiness@gmail.com> | 2025-01-30 10:39:41 -0600 |
| commit | bad0c9ad822f96413cd1ac7a918b5e930245ad98 (patch) | |
| tree | d12e4464fbcfa7095d86d0de7f06b501b1d82da1 /frontend | |
| parent | unused var (diff) | |
| download | lphub-bad0c9ad822f96413cd1ac7a918b5e930245ad98.tar.gz lphub-bad0c9ad822f96413cd1ac7a918b5e930245ad98.tar.bz2 lphub-bad0c9ad822f96413cd1ac7a918b5e930245ad98.zip | |
missing useEffect dependancies
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/src/components/Leaderboards.tsx | 289 |
1 files changed, 203 insertions, 86 deletions
diff --git a/frontend/src/components/Leaderboards.tsx b/frontend/src/components/Leaderboards.tsx index fb614fa..05f01d0 100644 --- a/frontend/src/components/Leaderboards.tsx +++ b/frontend/src/components/Leaderboards.tsx | |||
| @@ -1,15 +1,15 @@ | |||
| 1 | import React from 'react'; | 1 | import React from "react"; |
| 2 | import { Link, useNavigate } from 'react-router-dom'; | 2 | import { Link, useNavigate } from "react-router-dom"; |
| 3 | 3 | ||
| 4 | import { DownloadIcon, ThreedotIcon } from '@images/Images'; | 4 | import { DownloadIcon, ThreedotIcon } from "@images/Images"; |
| 5 | import { MapLeaderboard } from '@customTypes/Map'; | 5 | import { MapLeaderboard } from "@customTypes/Map"; |
| 6 | import { ticks_to_time, time_ago } from '@utils/Time'; | 6 | import { ticks_to_time, time_ago } from "@utils/Time"; |
| 7 | import { API } from "@api/Api"; | 7 | import { API } from "@api/Api"; |
| 8 | import useMessage from "@hooks/UseMessage"; | 8 | import useMessage from "@hooks/UseMessage"; |
| 9 | import "@css/Maps.css" | 9 | import "@css/Maps.css"; |
| 10 | 10 | ||
| 11 | interface LeaderboardsProps { | 11 | interface LeaderboardsProps { |
| 12 | mapID: string; | 12 | mapID: string; |
| 13 | } | 13 | } |
| 14 | 14 | ||
| 15 | const Leaderboards: React.FC<LeaderboardsProps> = ({ mapID }) => { | 15 | const Leaderboards: React.FC<LeaderboardsProps> = ({ mapID }) => { |
| @@ -18,108 +18,225 @@ const Leaderboards: React.FC<LeaderboardsProps> = ({ mapID }) => { | |||
| 18 | const [pageNumber, setPageNumber] = React.useState<number>(1); | 18 | const [pageNumber, setPageNumber] = React.useState<number>(1); |
| 19 | 19 | ||
| 20 | const _fetch_map_leaderboards = async () => { | 20 | const _fetch_map_leaderboards = async () => { |
| 21 | const mapLeaderboards = await API.get_map_leaderboard(mapID, pageNumber.toString()); | 21 | const mapLeaderboards = await API.get_map_leaderboard( |
| 22 | mapID, | ||
| 23 | pageNumber.toString() | ||
| 24 | ); | ||
| 22 | setData(mapLeaderboards); | 25 | setData(mapLeaderboards); |
| 23 | }; | 26 | }; |
| 24 | 27 | ||
| 25 | const { message, MessageDialogComponent } = useMessage(); | 28 | const { message, MessageDialogComponent } = useMessage(); |
| 26 | 29 | ||
| 27 | React.useEffect(() => { | 30 | React.useEffect(() => { |
| 28 | _fetch_map_leaderboards(); | 31 | _fetch_map_leaderboards(); |
| 29 | console.log(data); | 32 | console.log(data); |
| 30 | }, [pageNumber, navigate]) | 33 | }, [pageNumber, navigate, _fetch_map_leaderboards, data]); |
| 31 | 34 | ||
| 32 | if (!data) { | 35 | if (!data) { |
| 33 | return ( | 36 | return ( |
| 34 | <section id='section6' className='summary2'> | 37 | <section id="section6" className="summary2"> |
| 35 | <h1 style={{ textAlign: "center" }}>Map is not available for competitive boards.</h1> | 38 | <h1 style={{ textAlign: "center" }}> |
| 39 | Map is not available for competitive boards. | ||
| 40 | </h1> | ||
| 36 | </section> | 41 | </section> |
| 37 | ); | 42 | ); |
| 38 | }; | 43 | } |
| 39 | 44 | ||
| 40 | if (data.records.length === 0) { | 45 | if (data.records.length === 0) { |
| 41 | return ( | 46 | return ( |
| 42 | <section id='section6' className='summary2'> | 47 | <section id="section6" className="summary2"> |
| 43 | <h1 style={{ textAlign: "center" }}>No records found.</h1> | 48 | <h1 style={{ textAlign: "center" }}>No records found.</h1> |
| 44 | </section> | 49 | </section> |
| 45 | ); | 50 | ); |
| 46 | }; | 51 | } |
| 47 | 52 | ||
| 48 | return ( | 53 | return ( |
| 49 | <div> | 54 | <div> |
| 50 | {MessageDialogComponent} | 55 | {MessageDialogComponent} |
| 51 | <section id='section6' className='summary2'> | 56 | <section id="section6" className="summary2"> |
| 52 | 57 | <div | |
| 53 | <div id='leaderboard-top' | 58 | id="leaderboard-top" |
| 54 | style={data.map.is_coop ? { gridTemplateColumns: "7.5% 40% 7.5% 15% 15% 15%" } : { gridTemplateColumns: "7.5% 30% 10% 20% 17.5% 15%" }} | 59 | style={ |
| 55 | > | 60 | data.map.is_coop |
| 56 | <span>Place</span> | 61 | ? { gridTemplateColumns: "7.5% 40% 7.5% 15% 15% 15%" } |
| 57 | 62 | : { gridTemplateColumns: "7.5% 30% 10% 20% 17.5% 15%" } | |
| 58 | {data.map.is_coop ? ( | 63 | } |
| 59 | <div id='runner'> | 64 | > |
| 60 | <span>Blue</span> | 65 | <span>Place</span> |
| 61 | <span>Orange</span> | 66 | |
| 62 | </div> | 67 | {data.map.is_coop ? ( |
| 63 | ) : ( | 68 | <div id="runner"> |
| 64 | <span>Runner</span> | 69 | <span>Blue</span> |
| 65 | )} | 70 | <span>Orange</span> |
| 66 | 71 | </div> | |
| 67 | <span>Portals</span> | 72 | ) : ( |
| 68 | <span>Time</span> | 73 | <span>Runner</span> |
| 69 | <span>Date</span> | 74 | )} |
| 70 | <div id='page-number'> | 75 | |
| 71 | <div> | 76 | <span>Portals</span> |
| 72 | 77 | <span>Time</span> | |
| 73 | <button onClick={() => pageNumber === 1 ? null : setPageNumber(prevPageNumber => prevPageNumber - 1)} | 78 | <span>Date</span> |
| 74 | ><i className='triangle' style={{ position: 'relative', left: '-5px', }}></i> </button> | 79 | <div id="page-number"> |
| 75 | <span>{data.pagination.current_page}/{data.pagination.total_pages}</span> | 80 | <div> |
| 76 | <button onClick={() => pageNumber === data.pagination.total_pages ? null : setPageNumber(prevPageNumber => prevPageNumber + 1)} | 81 | <button |
| 77 | ><i className='triangle' style={{ position: 'relative', left: '5px', transform: 'rotate(180deg)' }}></i> </button> | 82 | onClick={() => |
| 83 | pageNumber === 1 | ||
| 84 | ? null | ||
| 85 | : setPageNumber((prevPageNumber) => prevPageNumber - 1) | ||
| 86 | } | ||
| 87 | > | ||
| 88 | <i | ||
| 89 | className="triangle" | ||
| 90 | style={{ position: "relative", left: "-5px" }} | ||
| 91 | ></i>{" "} | ||
| 92 | </button> | ||
| 93 | <span> | ||
| 94 | {data.pagination.current_page}/{data.pagination.total_pages} | ||
| 95 | </span> | ||
| 96 | <button | ||
| 97 | onClick={() => | ||
| 98 | pageNumber === data.pagination.total_pages | ||
| 99 | ? null | ||
| 100 | : setPageNumber((prevPageNumber) => prevPageNumber + 1) | ||
| 101 | } | ||
| 102 | > | ||
| 103 | <i | ||
| 104 | className="triangle" | ||
| 105 | style={{ | ||
| 106 | position: "relative", | ||
| 107 | left: "5px", | ||
| 108 | transform: "rotate(180deg)", | ||
| 109 | }} | ||
| 110 | ></i>{" "} | ||
| 111 | </button> | ||
| 112 | </div> | ||
| 78 | </div> | 113 | </div> |
| 79 | </div> | 114 | </div> |
| 80 | </div> | 115 | <hr /> |
| 81 | <hr /> | 116 | <div id="leaderboard-records"> |
| 82 | <div id='leaderboard-records'> | 117 | {data.records.map((r, index) => ( |
| 83 | {data.records.map((r, index) => ( | 118 | <span |
| 84 | <span className='leaderboard-record' key={index} | 119 | className="leaderboard-record" |
| 85 | style={data.map.is_coop ? { gridTemplateColumns: "3% 4.5% 40% 4% 3.5% 15% 15% 14.5%" } : { gridTemplateColumns: "3% 4.5% 30% 4% 6% 20% 17% 15%" }} | 120 | key={index} |
| 86 | > | 121 | style={ |
| 87 | <span>{r.placement}</span> | 122 | data.map.is_coop |
| 88 | <span> </span> | 123 | ? { gridTemplateColumns: "3% 4.5% 40% 4% 3.5% 15% 15% 14.5%" } |
| 89 | {r.kind === "multiplayer" ? ( | 124 | : { gridTemplateColumns: "3% 4.5% 30% 4% 6% 20% 17% 15%" } |
| 90 | <div> | 125 | } |
| 91 | <Link to={`/users/${r.host.steam_id}`}><span><img src={r.host.avatar_link} alt='' /> {r.host.user_name}</span></Link> | 126 | > |
| 92 | <Link to={`/users/${r.partner.steam_id}`}><span><img src={r.partner.avatar_link} alt='' /> {r.partner.user_name}</span></Link> | 127 | <span>{r.placement}</span> |
| 93 | </div> | 128 | <span> </span> |
| 94 | ) : r.kind === "singleplayer" && ( | 129 | {r.kind === "multiplayer" ? ( |
| 95 | <div> | 130 | <div> |
| 96 | <Link to={`/users/${r.user.steam_id}`}><span><img src={r.user.avatar_link} alt='' /> {r.user.user_name}</span></Link> | 131 | <Link to={`/users/${r.host.steam_id}`}> |
| 97 | </div> | 132 | <span> |
| 98 | )} | 133 | <img src={r.host.avatar_link} alt="" /> {" "} |
| 99 | 134 | {r.host.user_name} | |
| 100 | <span>{r.score_count}</span> | 135 | </span> |
| 101 | <span> </span> | 136 | </Link> |
| 102 | <span className='hover-popup' popup-text={(r.score_time) + " ticks"}>{ticks_to_time(r.score_time)}</span> | 137 | <Link to={`/users/${r.partner.steam_id}`}> |
| 103 | <span className='hover-popup' popup-text={r.record_date.replace("T", ' ').split(".")[0]}>{time_ago(new Date(r.record_date.replace("T", " ").replace("Z", "")))}</span> | 138 | <span> |
| 104 | 139 | <img src={r.partner.avatar_link} alt="" /> {" "} | |
| 105 | {r.kind === "multiplayer" ? ( | 140 | {r.partner.user_name} |
| 106 | <span> | 141 | </span> |
| 107 | <button onClick={() => { message("Demo Information", `Host Demo ID: ${r.host_demo_id} \nParnter Demo ID: ${r.partner_demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> | 142 | </Link> |
| 108 | <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.partner_demo_id}`}><img src={DownloadIcon} alt="download" style={{ filter: "hue-rotate(160deg) contrast(60%) saturate(1000%)" }} /></button> | 143 | </div> |
| 109 | <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.host_demo_id}`}><img src={DownloadIcon} alt="download" style={{ filter: "hue-rotate(300deg) contrast(60%) saturate(1000%)" }} /></button> | 144 | ) : ( |
| 145 | r.kind === "singleplayer" && ( | ||
| 146 | <div> | ||
| 147 | <Link to={`/users/${r.user.steam_id}`}> | ||
| 148 | <span> | ||
| 149 | <img src={r.user.avatar_link} alt="" /> {" "} | ||
| 150 | {r.user.user_name} | ||
| 151 | </span> | ||
| 152 | </Link> | ||
| 153 | </div> | ||
| 154 | ) | ||
| 155 | )} | ||
| 156 | |||
| 157 | <span>{r.score_count}</span> | ||
| 158 | <span> </span> | ||
| 159 | <span | ||
| 160 | className="hover-popup" | ||
| 161 | popup-text={r.score_time + " ticks"} | ||
| 162 | > | ||
| 163 | {ticks_to_time(r.score_time)} | ||
| 110 | </span> | 164 | </span> |
| 111 | ) : r.kind === "singleplayer" && ( | 165 | <span |
| 112 | 166 | className="hover-popup" | |
| 113 | <span> | 167 | popup-text={r.record_date.replace("T", " ").split(".")[0]} |
| 114 | <button onClick={() => { message("Demo Information", `Demo ID: ${r.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> | 168 | > |
| 115 | <button onClick={() => window.location.href = `/api/v1/demos?uuid=${r.demo_id}`}><img src={DownloadIcon} alt="download" /></button> | 169 | {time_ago( |
| 170 | new Date(r.record_date.replace("T", " ").replace("Z", "")) | ||
| 171 | )} | ||
| 116 | </span> | 172 | </span> |
| 117 | )} | 173 | |
| 118 | </span> | 174 | {r.kind === "multiplayer" ? ( |
| 119 | ))} | 175 | <span> |
| 120 | </div> | 176 | <button |
| 121 | </section> | 177 | onClick={() => { |
| 122 | </div> | 178 | message( |
| 179 | "Demo Information", | ||
| 180 | `Host Demo ID: ${r.host_demo_id} \nParnter Demo ID: ${r.partner_demo_id}` | ||
| 181 | ); | ||
| 182 | }} | ||
| 183 | > | ||
| 184 | <img src={ThreedotIcon} alt="demo_id" /> | ||
| 185 | </button> | ||
| 186 | <button | ||
| 187 | onClick={() => | ||
| 188 | (window.location.href = `/api/v1/demos?uuid=${r.partner_demo_id}`) | ||
| 189 | } | ||
| 190 | > | ||
| 191 | <img | ||
| 192 | src={DownloadIcon} | ||
| 193 | alt="download" | ||
| 194 | style={{ | ||
| 195 | filter: | ||
| 196 | "hue-rotate(160deg) contrast(60%) saturate(1000%)", | ||
| 197 | }} | ||
| 198 | /> | ||
| 199 | </button> | ||
| 200 | <button | ||
| 201 | onClick={() => | ||
| 202 | (window.location.href = `/api/v1/demos?uuid=${r.host_demo_id}`) | ||
| 203 | } | ||
| 204 | > | ||
| 205 | <img | ||
| 206 | src={DownloadIcon} | ||
| 207 | alt="download" | ||
| 208 | style={{ | ||
| 209 | filter: | ||
| 210 | "hue-rotate(300deg) contrast(60%) saturate(1000%)", | ||
| 211 | }} | ||
| 212 | /> | ||
| 213 | </button> | ||
| 214 | </span> | ||
| 215 | ) : ( | ||
| 216 | r.kind === "singleplayer" && ( | ||
| 217 | <span> | ||
| 218 | <button | ||
| 219 | onClick={() => { | ||
| 220 | message("Demo Information", `Demo ID: ${r.demo_id}`); | ||
| 221 | }} | ||
| 222 | > | ||
| 223 | <img src={ThreedotIcon} alt="demo_id" /> | ||
| 224 | </button> | ||
| 225 | <button | ||
| 226 | onClick={() => | ||
| 227 | (window.location.href = `/api/v1/demos?uuid=${r.demo_id}`) | ||
| 228 | } | ||
| 229 | > | ||
| 230 | <img src={DownloadIcon} alt="download" /> | ||
| 231 | </button> | ||
| 232 | </span> | ||
| 233 | ) | ||
| 234 | )} | ||
| 235 | </span> | ||
| 236 | ))} | ||
| 237 | </div> | ||
| 238 | </section> | ||
| 239 | </div> | ||
| 123 | ); | 240 | ); |
| 124 | }; | 241 | }; |
| 125 | 242 | ||