aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/pages/User.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/pages/User.tsx')
-rw-r--r--frontend/src/pages/User.tsx599
1 files changed, 426 insertions, 173 deletions
diff --git a/frontend/src/pages/User.tsx b/frontend/src/pages/User.tsx
index d43c0c6..b6dfbd3 100644
--- a/frontend/src/pages/User.tsx
+++ b/frontend/src/pages/User.tsx
@@ -2,13 +2,24 @@ import React from 'react';
2import { Link, useLocation, useNavigate } from 'react-router-dom'; 2import { Link, useLocation, useNavigate } from 'react-router-dom';
3import { Helmet } from 'react-helmet'; 3import { Helmet } from 'react-helmet';
4 4
5import { SteamIcon, TwitchIcon, YouTubeIcon, PortalIcon, FlagIcon, StatisticsIcon, SortIcon, ThreedotIcon, DownloadIcon, HistoryIcon } from '@images/Images'; 5import {
6 SteamIcon,
7 TwitchIcon,
8 YouTubeIcon,
9 PortalIcon,
10 FlagIcon,
11 StatisticsIcon,
12 SortIcon,
13 ThreedotIcon,
14 DownloadIcon,
15 HistoryIcon,
16} from '@images/Images';
6import { UserProfile } from '@customTypes/Profile'; 17import { UserProfile } from '@customTypes/Profile';
7import { Game, GameChapters } from '@customTypes/Game'; 18import { Game, GameChapters } from '@customTypes/Game';
8import { Map } from '@customTypes/Map'; 19import { Map } from '@customTypes/Map';
9import { API } from '@api/Api'; 20import { API } from '@api/Api';
10import { ticks_to_time } from '@utils/Time'; 21import { ticks_to_time } from '@utils/Time';
11import "@css/Profile.css"; 22import '@css/Profile.css';
12import useMessage from '@hooks/UseMessage'; 23import useMessage from '@hooks/UseMessage';
13 24
14interface UserProps { 25interface UserProps {
@@ -18,7 +29,6 @@ interface UserProps {
18} 29}
19 30
20const User: React.FC<UserProps> = ({ token, profile, gameData }) => { 31const User: React.FC<UserProps> = ({ token, profile, gameData }) => {
21
22 const { message, MessageDialogComponent } = useMessage(); 32 const { message, MessageDialogComponent } = useMessage();
23 33
24 const [user, setUser] = React.useState<UserProfile | undefined>(undefined); 34 const [user, setUser] = React.useState<UserProfile | undefined>(undefined);
@@ -27,18 +37,20 @@ const User: React.FC<UserProps> = ({ token, profile, gameData }) => {
27 const [pageNumber, setPageNumber] = React.useState(1); 37 const [pageNumber, setPageNumber] = React.useState(1);
28 const [pageMax, setPageMax] = React.useState(0); 38 const [pageMax, setPageMax] = React.useState(0);
29 39
30 const [game, setGame] = React.useState("0"); 40 const [game, setGame] = React.useState('0');
31 const [chapter, setChapter] = React.useState("0"); 41 const [chapter, setChapter] = React.useState('0');
32 const [chapterData, setChapterData] = React.useState<GameChapters | null>(null); 42 const [chapterData, setChapterData] = React.useState<GameChapters | null>(
43 null
44 );
33 const [maps, setMaps] = React.useState<Map[]>([]); 45 const [maps, setMaps] = React.useState<Map[]>([]);
34 46
35 const location = useLocation(); 47 const location = useLocation();
36 const navigate = useNavigate(); 48 const navigate = useNavigate();
37 49
38 const _fetch_user = async () => { 50 const _fetch_user = async () => {
39 const userID = location.pathname.split("/")[2]; 51 const userID = location.pathname.split('/')[2];
40 if (token && profile && profile.profile && profile.steam_id === userID) { 52 if (token && profile && profile.profile && profile.steam_id === userID) {
41 navigate("/profile"); 53 navigate('/profile');
42 return; 54 return;
43 } 55 }
44 const userData = await API.get_user(userID); 56 const userData = await API.get_user(userID);
@@ -46,7 +58,7 @@ const User: React.FC<UserProps> = ({ token, profile, gameData }) => {
46 }; 58 };
47 59
48 const _get_game_chapters = async () => { 60 const _get_game_chapters = async () => {
49 if (game !== "0") { 61 if (game !== '0') {
50 const gameChapters = await API.get_games_chapters(game); 62 const gameChapters = await API.get_games_chapters(game);
51 setChapterData(gameChapters); 63 setChapterData(gameChapters);
52 } else { 64 } else {
@@ -56,7 +68,7 @@ const User: React.FC<UserProps> = ({ token, profile, gameData }) => {
56 }; 68 };
57 69
58 const _get_game_maps = async () => { 70 const _get_game_maps = async () => {
59 if (chapter === "0") { 71 if (chapter === '0') {
60 const gameMaps = await API.get_game_maps(game); 72 const gameMaps = await API.get_game_maps(game);
61 setMaps(gameMaps); 73 setMaps(gameMaps);
62 setPageMax(Math.ceil(gameMaps.length / 20)); 74 setPageMax(Math.ceil(gameMaps.length / 20));
@@ -80,16 +92,14 @@ const User: React.FC<UserProps> = ({ token, profile, gameData }) => {
80 }, [user, game, location]); 92 }, [user, game, location]);
81 93
82 React.useEffect(() => { 94 React.useEffect(() => {
83 if (user && game !== "0") { 95 if (user && game !== '0') {
84 _get_game_maps(); 96 _get_game_maps();
85 } 97 }
86 }, [user, game, chapter, location]) 98 }, [user, game, chapter, location]);
87 99
88 if (!user) { 100 if (!user) {
89 return ( 101 return <></>;
90 <></> 102 }
91 );
92 };
93 103
94 return ( 104 return (
95 <main> 105 <main>
@@ -98,218 +108,461 @@ const User: React.FC<UserProps> = ({ token, profile, gameData }) => {
98 <meta name="description" content={user.user_name} /> 108 <meta name="description" content={user.user_name} />
99 </Helmet> 109 </Helmet>
100 {MessageDialogComponent} 110 {MessageDialogComponent}
101 <section id='section1' className='profile'> 111 <section id="section1" className="profile">
102 <div> 112 <div>
103 <img src={user.avatar_link} alt="profile-image"></img> 113 <img src={user.avatar_link} alt="profile-image"></img>
104 </div> 114 </div>
105 <div id='profile-top'> 115 <div id="profile-top">
106 <div> 116 <div>
107 <div>{user.user_name}</div> 117 <div>{user.user_name}</div>
108 <div> 118 <div>
109 {user.country_code === "XX" ? "" : <img src={`https://flagcdn.com/w80/${user.country_code.toLowerCase()}.jpg`} alt={user.country_code} />} 119 {user.country_code === 'XX' ? (
120 ''
121 ) : (
122 <img
123 src={`https://flagcdn.com/w80/${user.country_code.toLowerCase()}.jpg`}
124 alt={user.country_code}
125 />
126 )}
110 </div> 127 </div>
111 <div> 128 <div>
112 {user.titles.map(e => ( 129 {user.titles.map(e => (
113 <span className="titles" style={{ backgroundColor: `#${e.color}` }}> 130 <span
131 className="titles"
132 style={{ backgroundColor: `#${e.color}` }}
133 >
114 {e.name} 134 {e.name}
115 </span> 135 </span>
116 ))} 136 ))}
117 </div> 137 </div>
118 </div> 138 </div>
119 <div> 139 <div>
120 {user.links.steam === "-" ? "" : <a href={user.links.steam}><img src={SteamIcon} alt="Steam" /></a>} 140 {user.links.steam === '-' ? (
121 {user.links.twitch === "-" ? "" : <a href={user.links.twitch}><img src={TwitchIcon} alt="Twitch" /></a>} 141 ''
122 {user.links.youtube === "-" ? "" : <a href={user.links.youtube}><img src={YouTubeIcon} alt="Youtube" /></a>} 142 ) : (
123 {user.links.p2sr === "-" ? "" : <a href={user.links.p2sr}><img src={PortalIcon} alt="P2SR" style={{ padding: "0" }} /></a>} 143 <a href={user.links.steam}>
144 <img src={SteamIcon} alt="Steam" />
145 </a>
146 )}
147 {user.links.twitch === '-' ? (
148 ''
149 ) : (
150 <a href={user.links.twitch}>
151 <img src={TwitchIcon} alt="Twitch" />
152 </a>
153 )}
154 {user.links.youtube === '-' ? (
155 ''
156 ) : (
157 <a href={user.links.youtube}>
158 <img src={YouTubeIcon} alt="Youtube" />
159 </a>
160 )}
161 {user.links.p2sr === '-' ? (
162 ''
163 ) : (
164 <a href={user.links.p2sr}>
165 <img src={PortalIcon} alt="P2SR" style={{ padding: '0' }} />
166 </a>
167 )}
124 </div> 168 </div>
125
126 </div> 169 </div>
127 <div id='profile-bottom'> 170 <div id="profile-bottom">
128 <div> 171 <div>
129 <span>Overall</span> 172 <span>Overall</span>
130 <span>{user.rankings.overall.rank === 0 ? "N/A " : "#" + user.rankings.overall.rank + " "} 173 <span>
131 <span>({user.rankings.overall.completion_count}/{user.rankings.overall.completion_total})</span> 174 {user.rankings.overall.rank === 0
175 ? 'N/A '
176 : '#' + user.rankings.overall.rank + ' '}
177 <span>
178 ({user.rankings.overall.completion_count}/
179 {user.rankings.overall.completion_total})
180 </span>
132 </span> 181 </span>
133 </div> 182 </div>
134 <div> 183 <div>
135 <span>Singleplayer</span> 184 <span>Singleplayer</span>
136 <span>{user.rankings.singleplayer.rank === 0 ? "N/A " : "#" + user.rankings.singleplayer.rank + " "} 185 <span>
137 <span>({user.rankings.singleplayer.completion_count}/{user.rankings.singleplayer.completion_total})</span> 186 {user.rankings.singleplayer.rank === 0
187 ? 'N/A '
188 : '#' + user.rankings.singleplayer.rank + ' '}
189 <span>
190 ({user.rankings.singleplayer.completion_count}/
191 {user.rankings.singleplayer.completion_total})
192 </span>
138 </span> 193 </span>
139 </div> 194 </div>
140 <div> 195 <div>
141 <span>Cooperative</span> 196 <span>Cooperative</span>
142 <span>{user.rankings.cooperative.rank === 0 ? "N/A " : "#" + user.rankings.cooperative.rank + " "} 197 <span>
143 <span>({user.rankings.cooperative.completion_count}/{user.rankings.cooperative.completion_total})</span> 198 {user.rankings.cooperative.rank === 0
199 ? 'N/A '
200 : '#' + user.rankings.cooperative.rank + ' '}
201 <span>
202 ({user.rankings.cooperative.completion_count}/
203 {user.rankings.cooperative.completion_total})
204 </span>
144 </span> 205 </span>
145 </div> 206 </div>
146 </div> 207 </div>
147 </section> 208 </section>
148 209
149 210 <section id="section2" className="profile">
150 <section id='section2' className='profile'> 211 <button onClick={() => setNavState(0)}>
151 <button onClick={() => setNavState(0)}><img src={FlagIcon} alt="" />&nbsp;Player Records</button> 212 <img src={FlagIcon} alt="" />
152 <button onClick={() => setNavState(1)}><img src={StatisticsIcon} alt="" />&nbsp;Statistics</button> 213 &nbsp;Player Records
214 </button>
215 <button onClick={() => setNavState(1)}>
216 <img src={StatisticsIcon} alt="" />
217 &nbsp;Statistics
218 </button>
153 </section> 219 </section>
154 220
155 221 <section id="section3" className="profile1">
156 222 <div id="profileboard-nav">
157 223 {gameData === null ? (
158 224 <select>error</select>
159 <section id='section3' className='profile1'> 225 ) : (
160 <div id='profileboard-nav'> 226 <select
161 {gameData === null ? <select>error</select> : 227 id="select-game"
162
163 <select id='select-game'
164 onChange={() => { 228 onChange={() => {
165 setGame((document.querySelector('#select-game') as HTMLInputElement).value); 229 setGame(
166 setChapter("0"); 230 (document.querySelector('#select-game') as HTMLInputElement)
167 const chapterSelect = document.querySelector('#select-chapter') as HTMLSelectElement; 231 .value
232 );
233 setChapter('0');
234 const chapterSelect = document.querySelector(
235 '#select-chapter'
236 ) as HTMLSelectElement;
168 if (chapterSelect) { 237 if (chapterSelect) {
169 chapterSelect.value = "0"; 238 chapterSelect.value = '0';
170 } 239 }
171 }}> 240 }}
172 <option value={0} key={0}>All Scores</option> 241 >
242 <option value={0} key={0}>
243 All Scores
244 </option>
173 {gameData.map((e, i) => ( 245 {gameData.map((e, i) => (
174 <option value={e.id} key={i + 1}>{e.name}</option> 246 <option value={e.id} key={i + 1}>
175 ))}</select> 247 {e.name}
176 } 248 </option>
249 ))}
250 </select>
251 )}
177 252
178 {game === "0" ? 253 {game === '0' ? (
179 <select disabled> 254 <select disabled>
180 <option>All Chapters</option> 255 <option>All Chapters</option>
181 </select> 256 </select>
182 : chapterData === null ? <select></select> : 257 ) : chapterData === null ? (
183 258 <select></select>
184 <select id='select-chapter' 259 ) : (
185 onChange={() => setChapter((document.querySelector('#select-chapter') as HTMLInputElement).value)}> 260 <select
186 <option value="0" key="0">All Chapters</option> 261 id="select-chapter"
187 {chapterData.chapters.filter(e => e.is_disabled === false).map((e, i) => ( 262 onChange={() =>
188 <option value={e.id} key={i + 1}>{e.name}</option> 263 setChapter(
189 ))}</select> 264 (
190 } 265 document.querySelector(
266 '#select-chapter'
267 ) as HTMLInputElement
268 ).value
269 )
270 }
271 >
272 <option value="0" key="0">
273 All Chapters
274 </option>
275 {chapterData.chapters
276 .filter(e => e.is_disabled === false)
277 .map((e, i) => (
278 <option value={e.id} key={i + 1}>
279 {e.name}
280 </option>
281 ))}
282 </select>
283 )}
191 </div> 284 </div>
192 <div id='profileboard-top'> 285 <div id="profileboard-top">
193 <span><span>Map Name</span><img src={SortIcon} alt="" /></span> 286 <span>
194 <span style={{ justifyContent: 'center' }}><span>Portals</span><img src={SortIcon} alt="" /></span> 287 <span>Map Name</span>
195 <span style={{ justifyContent: 'center' }}><span>WRΔ </span><img src={SortIcon} alt="" /></span> 288 <img src={SortIcon} alt="" />
196 <span style={{ justifyContent: 'center' }}><span>Time</span><img src={SortIcon} alt="" /></span> 289 </span>
290 <span style={{ justifyContent: 'center' }}>
291 <span>Portals</span>
292 <img src={SortIcon} alt="" />
293 </span>
294 <span style={{ justifyContent: 'center' }}>
295 <span>WRΔ </span>
296 <img src={SortIcon} alt="" />
297 </span>
298 <span style={{ justifyContent: 'center' }}>
299 <span>Time</span>
300 <img src={SortIcon} alt="" />
301 </span>
197 <span> </span> 302 <span> </span>
198 <span><span>Rank</span><img src={SortIcon} alt="" /></span> 303 <span>
199 <span><span>Date</span><img src={SortIcon} alt="" /></span> 304 <span>Rank</span>
200 <div id='page-number'> 305 <img src={SortIcon} alt="" />
306 </span>
307 <span>
308 <span>Date</span>
309 <img src={SortIcon} alt="" />
310 </span>
311 <div id="page-number">
201 <div> 312 <div>
202 <button onClick={() => { 313 <button
203 if (pageNumber !== 1) { 314 onClick={() => {
204 setPageNumber(prevPageNumber => prevPageNumber - 1); 315 if (pageNumber !== 1) {
205 const records = document.querySelectorAll(".profileboard-record"); 316 setPageNumber(prevPageNumber => prevPageNumber - 1);
206 records.forEach((r) => { 317 const records = document.querySelectorAll(
207 (r as HTMLInputElement).style.height = "44px"; 318 '.profileboard-record'
208 }); 319 );
209 } 320 records.forEach(r => {
210 }} 321 (r as HTMLInputElement).style.height = '44px';
211 ><i className='triangle' style={{ position: 'relative', left: '-5px', }}></i> </button> 322 });
212 <span>{pageNumber}/{pageMax}</span> 323 }
213 <button onClick={() => { 324 }}
214 if (pageNumber !== pageMax) { 325 >
215 setPageNumber(prevPageNumber => prevPageNumber + 1); 326 <i
216 const records = document.querySelectorAll(".profileboard-record"); 327 className="triangle"
217 records.forEach((r) => { 328 style={{ position: 'relative', left: '-5px' }}
218 (r as HTMLInputElement).style.height = "44px"; 329 ></i>{' '}
219 }); 330 </button>
220 } 331 <span>
221 }} 332 {pageNumber}/{pageMax}
222 ><i className='triangle' style={{ position: 'relative', left: '5px', transform: 'rotate(180deg)' }}></i> </button> 333 </span>
334 <button
335 onClick={() => {
336 if (pageNumber !== pageMax) {
337 setPageNumber(prevPageNumber => prevPageNumber + 1);
338 const records = document.querySelectorAll(
339 '.profileboard-record'
340 );
341 records.forEach(r => {
342 (r as HTMLInputElement).style.height = '44px';
343 });
344 }
345 }}
346 >
347 <i
348 className="triangle"
349 style={{
350 position: 'relative',
351 left: '5px',
352 transform: 'rotate(180deg)',
353 }}
354 ></i>{' '}
355 </button>
223 </div> 356 </div>
224 </div> 357 </div>
225 </div> 358 </div>
226 <hr /> 359 <hr />
227 <div id='profileboard-records'> 360 <div id="profileboard-records">
228 361 {game === '0' ? (
229 {game === "0" 362 user.records
230 ? ( 363 .sort((a, b) => a.map_id - b.map_id)
231 364 .map((r, index) =>
232 user.records.sort((a, b) => a.map_id - b.map_id) 365 Math.ceil((index + 1) / 20) === pageNumber ? (
233 .map((r, index) => ( 366 <button className="profileboard-record" key={index}>
234 367 {r.scores.map((e, i) => (
235 Math.ceil((index + 1) / 20) === pageNumber ? ( 368 <>
236 <button className="profileboard-record" key={index}> 369 {i !== 0 ? (
237 {r.scores.map((e, i) => (<> 370 <hr style={{ gridColumn: '1 / span 8' }} />
238 {i !== 0 ? <hr style={{ gridColumn: "1 / span 8" }} /> : ""} 371 ) : (
239 372 ''
240 <Link to={`/maps/${r.map_id}`}><span>{r.map_name}</span></Link> 373 )}
241 374
242 <span style={{ display: "grid" }}>{e.score_count}</span> 375 <Link to={`/maps/${r.map_id}`}>
243 376 <span>{r.map_name}</span>
244 <span style={{ display: "grid" }}>{e.score_count - r.map_wr_count > 0 ? `+${e.score_count - r.map_wr_count}` : `-`}</span> 377 </Link>
245 <span style={{ display: "grid" }}>{ticks_to_time(e.score_time)}</span> 378
379 <span style={{ display: 'grid' }}>{e.score_count}</span>
380
381 <span style={{ display: 'grid' }}>
382 {e.score_count - r.map_wr_count > 0
383 ? `+${e.score_count - r.map_wr_count}`
384 : `-`}
385 </span>
386 <span style={{ display: 'grid' }}>
387 {ticks_to_time(e.score_time)}
388 </span>
246 <span> </span> 389 <span> </span>
247 {i === 0 ? <span>#{r.placement}</span> : <span> </span>} 390 {i === 0 ? <span>#{r.placement}</span> : <span> </span>}
248 <span>{e.date.split("T")[0]}</span> 391 <span>{e.date.split('T')[0]}</span>
249 <span style={{ flexDirection: "row-reverse" }}> 392 <span style={{ flexDirection: 'row-reverse' }}>
250 393 <button
251 <button onClick={() => { message("Demo Information", `Demo ID: ${e.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> 394 onClick={() => {
252 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${e.demo_id}`}><img src={DownloadIcon} alt="download" /></button> 395 message(
253 {i === 0 && r.scores.length > 1 ? <button onClick={() => { 396 'Demo Information',
254 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "44px" || 397 `Demo ID: ${e.demo_id}`
255 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "" ? 398 );
256 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = `${r.scores.length * 46}px` : 399 }}
257 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = "44px" 400 >
258 } 401 <img src={ThreedotIcon} alt="demo_id" />
259 }><img src={HistoryIcon} alt="history" /></button> : ""} 402 </button>
260 403 <button
404 onClick={() =>
405 (window.location.href = `/api/v1/demos?uuid=${e.demo_id}`)
406 }
407 >
408 <img src={DownloadIcon} alt="download" />
409 </button>
410 {i === 0 && r.scores.length > 1 ? (
411 <button
412 onClick={() => {
413 (
414 document.querySelectorAll(
415 '.profileboard-record'
416 )[index % 20] as HTMLInputElement
417 ).style.height === '44px' ||
418 (
419 document.querySelectorAll(
420 '.profileboard-record'
421 )[index % 20] as HTMLInputElement
422 ).style.height === ''
423 ? ((
424 document.querySelectorAll(
425 '.profileboard-record'
426 )[index % 20] as HTMLInputElement
427 ).style.height =
428 `${r.scores.length * 46}px`)
429 : ((
430 document.querySelectorAll(
431 '.profileboard-record'
432 )[index % 20] as HTMLInputElement
433 ).style.height = '44px');
434 }}
435 >
436 <img src={HistoryIcon} alt="history" />
437 </button>
438 ) : (
439 ''
440 )}
261 </span> 441 </span>
262 </>))} 442 </>
263 443 ))}
444 </button>
445 ) : (
446 ''
447 )
448 )
449 ) : maps ? (
450 maps
451 .filter(e => e.is_disabled === false)
452 .sort((a, b) => a.id - b.id)
453 .map((r, index) => {
454 if (Math.ceil((index + 1) / 20) === pageNumber) {
455 let record = user.records.find(e => e.map_id === r.id);
456 return record === undefined ? (
457 <button
458 className="profileboard-record"
459 key={index}
460 style={{ backgroundColor: '#1b1b20' }}
461 >
462 <Link to={`/maps/${r.id}`}>
463 <span>{r.name}</span>
464 </Link>
465 <span style={{ display: 'grid' }}>N/A</span>
466 <span style={{ display: 'grid' }}>N/A</span>
467 <span>N/A</span>
468 <span> </span>
469 <span>N/A</span>
470 <span>N/A</span>
471 <span style={{ flexDirection: 'row-reverse' }}></span>
264 </button> 472 </button>
265 ) : "" 473 ) : (
266 ))) : maps ? 474 <button className="profileboard-record" key={index}>
267 475 {record.scores.map((e, i) => (
268 maps.filter(e => e.is_disabled === false).sort((a, b) => a.id - b.id) 476 <>
269 .map((r, index) => { 477 {i !== 0 ? (
270 if (Math.ceil((index + 1) / 20) === pageNumber) { 478 <hr style={{ gridColumn: '1 / span 8' }} />
271 let record = user.records.find((e) => e.map_id === r.id); 479 ) : (
272 return record === undefined ? ( 480 ''
273 <button className="profileboard-record" key={index} style={{ backgroundColor: "#1b1b20" }}> 481 )}
274 <Link to={`/maps/${r.id}`}><span>{r.name}</span></Link> 482 <Link to={`/maps/${r.id}`}>
275 <span style={{ display: "grid" }}>N/A</span> 483 <span>{r.name}</span>
276 <span style={{ display: "grid" }}>N/A</span> 484 </Link>
277 <span>N/A</span> 485 <span style={{ display: 'grid' }}>
278 <span> </span> 486 {record!.scores[i].score_count}
279 <span>N/A</span> 487 </span>
280 <span>N/A</span> 488 <span style={{ display: 'grid' }}>
281 <span style={{ flexDirection: "row-reverse" }}></span> 489 {record!.scores[i].score_count -
282 </button> 490 record!.map_wr_count >
283 ) : ( 491 0
284 <button className="profileboard-record" key={index}> 492 ? `+${record!.scores[i].score_count - record!.map_wr_count}`
285 {record.scores.map((e, i) => (<> 493 : `-`}
286 {i !== 0 ? <hr style={{ gridColumn: "1 / span 8" }} /> : ""} 494 </span>
287 <Link to={`/maps/${r.id}`}><span>{r.name}</span></Link> 495 <span style={{ display: 'grid' }}>
288 <span style={{ display: "grid" }}>{record!.scores[i].score_count}</span> 496 {ticks_to_time(record!.scores[i].score_time)}
289 <span style={{ display: "grid" }}>{record!.scores[i].score_count - record!.map_wr_count > 0 ? `+${record!.scores[i].score_count - record!.map_wr_count}` : `-`}</span> 497 </span>
290 <span style={{ display: "grid" }}>{ticks_to_time(record!.scores[i].score_time)}</span>
291 <span> </span> 498 <span> </span>
292 {i === 0 ? <span>#{record!.placement}</span> : <span> </span>} 499 {i === 0 ? (
293 <span>{record!.scores[i].date.split("T")[0]}</span> 500 <span>#{record!.placement}</span>
294 <span style={{ flexDirection: "row-reverse" }}> 501 ) : (
295 502 <span> </span>
296 <button onClick={() => { message("Demo Information", `Demo ID: ${e.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> 503 )}
297 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${e.demo_id}`}><img src={DownloadIcon} alt="download" /></button> 504 <span>{record!.scores[i].date.split('T')[0]}</span>
298 {i === 0 && record!.scores.length > 1 ? <button onClick={() => { 505 <span style={{ flexDirection: 'row-reverse' }}>
299 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "44px" || 506 <button
300 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "" ? 507 onClick={() => {
301 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = `${record!.scores.length * 46}px` : 508 message(
302 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = "44px" 509 'Demo Information',
303 } 510 `Demo ID: ${e.demo_id}`
304 }><img src={HistoryIcon} alt="history" /></button> : ""} 511 );
305 512 }}
513 >
514 <img src={ThreedotIcon} alt="demo_id" />
515 </button>
516 <button
517 onClick={() =>
518 (window.location.href = `/api/v1/demos?uuid=${e.demo_id}`)
519 }
520 >
521 <img src={DownloadIcon} alt="download" />
522 </button>
523 {i === 0 && record!.scores.length > 1 ? (
524 <button
525 onClick={() => {
526 (
527 document.querySelectorAll(
528 '.profileboard-record'
529 )[index % 20] as HTMLInputElement
530 ).style.height === '44px' ||
531 (
532 document.querySelectorAll(
533 '.profileboard-record'
534 )[index % 20] as HTMLInputElement
535 ).style.height === ''
536 ? ((
537 document.querySelectorAll(
538 '.profileboard-record'
539 )[index % 20] as HTMLInputElement
540 ).style.height =
541 `${record!.scores.length * 46}px`)
542 : ((
543 document.querySelectorAll(
544 '.profileboard-record'
545 )[index % 20] as HTMLInputElement
546 ).style.height = '44px');
547 }}
548 >
549 <img src={HistoryIcon} alt="history" />
550 </button>
551 ) : (
552 ''
553 )}
306 </span> 554 </span>
307 </>))} 555 </>
308 </button> 556 ))}
309 557 </button>
310 ) 558 );
311 } else { return null } 559 } else {
312 }) : (<>{console.warn(maps)}</>)} 560 return null;
561 }
562 })
563 ) : (
564 <>{console.warn(maps)}</>
565 )}
313 </div> 566 </div>
314 </section> 567 </section>
315 </main> 568 </main>