aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/pages/Profile.tsx
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/pages/Profile.tsx')
-rw-r--r--frontend/src/pages/Profile.tsx396
1 files changed, 198 insertions, 198 deletions
diff --git a/frontend/src/pages/Profile.tsx b/frontend/src/pages/Profile.tsx
index 5c5676e..590bb9b 100644
--- a/frontend/src/pages/Profile.tsx
+++ b/frontend/src/pages/Profile.tsx
@@ -71,10 +71,10 @@ const Profile: React.FC<ProfileProps> = ({ profile, token, gameData, onDeleteRec
71 return; 71 return;
72 } 72 }
73 73
74 messageLoad("Deleting..."); 74 messageLoad("Deleting...");
75 75
76 const api_success = await API.delete_map_record(token!, map_id, record_id); 76 const api_success = await API.delete_map_record(token!, map_id, record_id);
77 messageLoadClose(); 77 messageLoadClose();
78 if (api_success) { 78 if (api_success) {
79 await message("Delete Record", "Successfully deleted record."); 79 await message("Delete Record", "Successfully deleted record.");
80 onDeleteRecord(); 80 onDeleteRecord();
@@ -108,240 +108,240 @@ const Profile: React.FC<ProfileProps> = ({ profile, token, gameData, onDeleteRec
108 }; 108 };
109 109
110 return ( 110 return (
111 <div> 111 <div>
112 {MessageDialogComponent} 112 {MessageDialogComponent}
113 {MessageDialogLoadComponent} 113 {MessageDialogLoadComponent}
114 {ConfirmDialogComponent} 114 {ConfirmDialogComponent}
115 115
116 <main> 116 <main>
117 <section id='section1' className='profile'> 117 <section id='section1' className='profile'>
118 118
119 {profile.profile 119 {profile.profile
120 ? ( 120 ? (
121 <div id='profile-image' onClick={_update_profile}> 121 <div id='profile-image' onClick={_update_profile}>
122 <img src={profile.avatar_link} alt="profile-image"></img> 122 <img src={profile.avatar_link} alt="profile-image"></img>
123 <span>Refresh</span> 123 <span>Refresh</span>
124 </div>
125 ) : (
126 <div>
127 <img src={profile.avatar_link} alt="profile-image"></img>
128 </div>
129 )}
130
131 <div id='profile-top'>
132 <div>
133 <div>{profile.user_name}</div>
134 <div>
135 {profile.country_code === "XX" ? "" : <img src={`https://flagcdn.com/w80/${profile.country_code.toLowerCase()}.jpg`} alt={profile.country_code} />}
136 </div>
137 <div>
138 {profile.titles.map(e => (
139 <span className="titles" style={{ backgroundColor: `#${e.color}` }}>
140 {e.name}
141 </span>
142 ))}
143 </div>
124 </div> 144 </div>
125 ) : (
126 <div> 145 <div>
127 <img src={profile.avatar_link} alt="profile-image"></img> 146 {profile.links.steam === "-" ? "" : <a href={profile.links.steam}><img src={SteamIcon} alt="Steam" /></a>}
147 {profile.links.twitch === "-" ? "" : <a href={profile.links.twitch}><img src={TwitchIcon} alt="Twitch" /></a>}
148 {profile.links.youtube === "-" ? "" : <a href={profile.links.youtube}><img src={YouTubeIcon} alt="Youtube" /></a>}
149 {profile.links.p2sr === "-" ? "" : <a href={profile.links.p2sr}><img src={PortalIcon} alt="P2SR" style={{ padding: "0" }} /></a>}
128 </div> 150 </div>
129 )}
130 151
131 <div id='profile-top'> 152 </div>
132 <div> 153 <div id='profile-bottom'>
133 <div>{profile.user_name}</div>
134 <div> 154 <div>
135 {profile.country_code === "XX" ? "" : <img src={`https://flagcdn.com/w80/${profile.country_code.toLowerCase()}.jpg`} alt={profile.country_code} />} 155 <span>Overall</span>
156 <span>{profile.rankings.overall.rank === 0 ? "N/A " : "#" + profile.rankings.overall.rank + " "}
157 <span>({profile.rankings.overall.completion_count}/{profile.rankings.overall.completion_total})</span>
158 </span>
136 </div> 159 </div>
137 <div> 160 <div>
138 {profile.titles.map(e => ( 161 <span>Singleplayer</span>
139 <span className="titles" style={{ backgroundColor: `#${e.color}` }}> 162 <span>{profile.rankings.singleplayer.rank === 0 ? "N/A " : "#" + profile.rankings.singleplayer.rank + " "}
140 {e.name} 163 <span>({profile.rankings.singleplayer.completion_count}/{profile.rankings.singleplayer.completion_total})</span>
141 </span> 164 </span>
142 ))} 165 </div>
166 <div>
167 <span>Cooperative</span>
168 <span>{profile.rankings.cooperative.rank === 0 ? "N/A " : "#" + profile.rankings.cooperative.rank + " "}
169 <span>({profile.rankings.cooperative.completion_count}/{profile.rankings.cooperative.completion_total})</span>
170 </span>
143 </div> 171 </div>
144 </div> 172 </div>
145 <div> 173 </section>
146 {profile.links.steam === "-" ? "" : <a href={profile.links.steam}><img src={SteamIcon} alt="Steam" /></a>}
147 {profile.links.twitch === "-" ? "" : <a href={profile.links.twitch}><img src={TwitchIcon} alt="Twitch" /></a>}
148 {profile.links.youtube === "-" ? "" : <a href={profile.links.youtube}><img src={YouTubeIcon} alt="Youtube" /></a>}
149 {profile.links.p2sr === "-" ? "" : <a href={profile.links.p2sr}><img src={PortalIcon} alt="P2SR" style={{ padding: "0" }} /></a>}
150 </div>
151
152 </div>
153 <div id='profile-bottom'>
154 <div>
155 <span>Overall</span>
156 <span>{profile.rankings.overall.rank === 0 ? "N/A " : "#" + profile.rankings.overall.rank + " "}
157 <span>({profile.rankings.overall.completion_count}/{profile.rankings.overall.completion_total})</span>
158 </span>
159 </div>
160 <div>
161 <span>Singleplayer</span>
162 <span>{profile.rankings.singleplayer.rank === 0 ? "N/A " : "#" + profile.rankings.singleplayer.rank + " "}
163 <span>({profile.rankings.singleplayer.completion_count}/{profile.rankings.singleplayer.completion_total})</span>
164 </span>
165 </div>
166 <div>
167 <span>Cooperative</span>
168 <span>{profile.rankings.cooperative.rank === 0 ? "N/A " : "#" + profile.rankings.cooperative.rank + " "}
169 <span>({profile.rankings.cooperative.completion_count}/{profile.rankings.cooperative.completion_total})</span>
170 </span>
171 </div>
172 </div>
173 </section>
174
175
176 <section id='section2' className='profile'>
177 <button onClick={() => setNavState(0)}><img src={FlagIcon} alt="" />&nbsp;Player Records</button>
178 <button onClick={() => setNavState(1)}><img src={StatisticsIcon} alt="" />&nbsp;Statistics</button>
179 </section>
180 174
181 175
176 <section id='section2' className='profile'>
177 <button onClick={() => setNavState(0)}><img src={FlagIcon} alt="" />&nbsp;Player Records</button>
178 <button onClick={() => setNavState(1)}><img src={StatisticsIcon} alt="" />&nbsp;Statistics</button>
179 </section>
182 180
183 181
184 182
185 <section id='section3' className='profile1'>
186 <div id='profileboard-nav'>
187 {gameData === null ? <select>error</select> :
188 183
189 <select id='select-game'
190 onChange={() => {
191 setGame((document.querySelector('#select-game') as HTMLInputElement).value);
192 setChapter("0");
193 const chapterSelect = document.querySelector('#select-chapter') as HTMLSelectElement;
194 if (chapterSelect) {
195 chapterSelect.value = "0";
196 }
197 }}>
198 <option value={0} key={0}>All Scores</option>
199 {gameData.map((e, i) => (
200 <option value={e.id} key={i + 1}>{e.name}</option>
201 ))}</select>
202 }
203 184
204 {game === "0" ? 185 <section id='section3' className='profile1'>
205 <select disabled> 186 <div id='profileboard-nav'>
206 <option>All Chapters</option> 187 {gameData === null ? <select>error</select> :
207 </select>
208 : chapterData === null ? <select></select> :
209 188
210 <select id='select-chapter' 189 <select id='select-game'
211 onChange={() => setChapter((document.querySelector('#select-chapter') as HTMLInputElement).value)}> 190 onChange={() => {
212 <option value="0" key="0">All Chapters</option> 191 setGame((document.querySelector('#select-game') as HTMLInputElement).value);
213 {chapterData.chapters.filter(e => e.is_disabled === false).map((e, i) => ( 192 setChapter("0");
193 const chapterSelect = document.querySelector('#select-chapter') as HTMLSelectElement;
194 if (chapterSelect) {
195 chapterSelect.value = "0";
196 }
197 }}>
198 <option value={0} key={0}>All Scores</option>
199 {gameData.map((e, i) => (
214 <option value={e.id} key={i + 1}>{e.name}</option> 200 <option value={e.id} key={i + 1}>{e.name}</option>
215 ))}</select> 201 ))}</select>
216 } 202 }
217 </div> 203
218 <div id='profileboard-top'> 204 {game === "0" ?
219 <span><span>Map Name</span><img src={SortIcon} alt="" /></span> 205 <select disabled>
220 <span style={{ justifyContent: 'center' }}><span>Portals</span><img src={SortIcon} alt="" /></span> 206 <option>All Chapters</option>
221 <span style={{ justifyContent: 'center' }}><span>WRΔ </span><img src={SortIcon} alt="" /></span> 207 </select>
222 <span style={{ justifyContent: 'center' }}><span>Time</span><img src={SortIcon} alt="" /></span> 208 : chapterData === null ? <select></select> :
223 <span> </span> 209
224 <span><span>Rank</span><img src={SortIcon} alt="" /></span> 210 <select id='select-chapter'
225 <span><span>Date</span><img src={SortIcon} alt="" /></span> 211 onChange={() => setChapter((document.querySelector('#select-chapter') as HTMLInputElement).value)}>
226 <div id='page-number'> 212 <option value="0" key="0">All Chapters</option>
227 <div> 213 {chapterData.chapters.filter(e => e.is_disabled === false).map((e, i) => (
228 <button onClick={() => { 214 <option value={e.id} key={i + 1}>{e.name}</option>
229 if (pageNumber !== 1) { 215 ))}</select>
230 setPageNumber(prevPageNumber => prevPageNumber - 1); 216 }
231 const records = document.querySelectorAll(".profileboard-record"); 217 </div>
232 records.forEach((r) => { 218 <div id='profileboard-top'>
233 (r as HTMLInputElement).style.height = "44px"; 219 <span><span>Map Name</span><img src={SortIcon} alt="" /></span>
234 }); 220 <span style={{ justifyContent: 'center' }}><span>Portals</span><img src={SortIcon} alt="" /></span>
235 } 221 <span style={{ justifyContent: 'center' }}><span>WRΔ </span><img src={SortIcon} alt="" /></span>
236 }} 222 <span style={{ justifyContent: 'center' }}><span>Time</span><img src={SortIcon} alt="" /></span>
237 ><i className='triangle' style={{ position: 'relative', left: '-5px', }}></i> </button> 223 <span> </span>
238 <span>{pageNumber}/{pageMax}</span> 224 <span><span>Rank</span><img src={SortIcon} alt="" /></span>
239 <button onClick={() => { 225 <span><span>Date</span><img src={SortIcon} alt="" /></span>
240 if (pageNumber !== pageMax) { 226 <div id='page-number'>
241 setPageNumber(prevPageNumber => prevPageNumber + 1); 227 <div>
242 const records = document.querySelectorAll(".profileboard-record"); 228 <button onClick={() => {
243 records.forEach((r) => { 229 if (pageNumber !== 1) {
244 (r as HTMLInputElement).style.height = "44px"; 230 setPageNumber(prevPageNumber => prevPageNumber - 1);
245 }); 231 const records = document.querySelectorAll(".profileboard-record");
246 } 232 records.forEach((r) => {
247 }} 233 (r as HTMLInputElement).style.height = "44px";
248 ><i className='triangle' style={{ position: 'relative', left: '5px', transform: 'rotate(180deg)' }}></i> </button> 234 });
235 }
236 }}
237 ><i className='triangle' style={{ position: 'relative', left: '-5px', }}></i> </button>
238 <span>{pageNumber}/{pageMax}</span>
239 <button onClick={() => {
240 if (pageNumber !== pageMax) {
241 setPageNumber(prevPageNumber => prevPageNumber + 1);
242 const records = document.querySelectorAll(".profileboard-record");
243 records.forEach((r) => {
244 (r as HTMLInputElement).style.height = "44px";
245 });
246 }
247 }}
248 ><i className='triangle' style={{ position: 'relative', left: '5px', transform: 'rotate(180deg)' }}></i> </button>
249 </div>
249 </div> 250 </div>
250 </div> 251 </div>
251 </div> 252 <hr />
252 <hr /> 253 <div id='profileboard-records'>
253 <div id='profileboard-records'>
254 254
255 {game === "0" 255 {game === "0"
256 ? ( 256 ? (
257 257
258 profile.records.sort((a, b) => a.map_id - b.map_id) 258 profile.records.sort((a, b) => a.map_id - b.map_id)
259 .map((r, index) => ( 259 .map((r, index) => (
260 260
261 Math.ceil((index + 1) / 20) === pageNumber ? ( 261 Math.ceil((index + 1) / 20) === pageNumber ? (
262 <button className="profileboard-record" key={index}>
263 {r.scores.map((e, i) => (<>
264 {i !== 0 ? <hr style={{ gridColumn: "1 / span 8" }} /> : ""}
265
266 <Link to={`/maps/${r.map_id}`}><span>{r.map_name}</span></Link>
267
268 <span style={{ display: "grid" }}>{e.score_count}</span>
269
270 <span style={{ display: "grid" }}>{e.score_count - r.map_wr_count > 0 ? `+${e.score_count - r.map_wr_count}` : e.score_count - r.map_wr_count}</span>
271 <span style={{ display: "grid" }}>{ticks_to_time(e.score_time)}</span>
272 <span> </span>
273 {i === 0 ? <span>#{r.placement}</span> : <span> </span>}
274 <span>{e.date.split("T")[0]}</span>
275 <span style={{ flexDirection: "row-reverse" }}>
276
277 <button style={{ marginRight: "10px" }} onClick={() => { message("Demo information", `Demo ID: ${e.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button>
278 <button onClick={() => { _delete_submission(r.map_id, e.record_id) }}><img src={DeleteIcon}></img></button>
279 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${e.demo_id}`}><img src={DownloadIcon} alt="download" /></button>
280 {i === 0 && r.scores.length > 1 ? <button onClick={() => {
281 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "44px" ||
282 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "" ?
283 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = `${r.scores.length * 46}px` :
284 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = "44px"
285 }
286 }><img src={HistoryIcon} alt="history" /></button> : ""}
287
288 </span>
289 </>))}
290
291 </button>
292 ) : ""
293 ))) : maps ?
294
295 maps.filter(e => e.is_disabled === false).sort((a, b) => a.id - b.id)
296 .map((r, index) => {
297 if (Math.ceil((index + 1) / 20) === pageNumber) {
298 let record = profile.records.find((e) => e.map_id === r.id);
299 return record === undefined ? (
300 <button className="profileboard-record" key={index} style={{ backgroundColor: "#1b1b20" }}>
301 <Link to={`/maps/${r.id}`}><span>{r.name}</span></Link>
302 <span style={{ display: "grid" }}>N/A</span>
303 <span style={{ display: "grid" }}>N/A</span>
304 <span>N/A</span>
305 <span> </span>
306 <span>N/A</span>
307 <span>N/A</span>
308 <span style={{ flexDirection: "row-reverse" }}></span>
309 </button>
310 ) : (
311 <button className="profileboard-record" key={index}> 262 <button className="profileboard-record" key={index}>
312 {record.scores.map((e, i) => (<> 263 {r.scores.map((e, i) => (<>
313 {i !== 0 ? <hr style={{ gridColumn: "1 / span 8" }} /> : ""} 264 {i !== 0 ? <hr style={{ gridColumn: "1 / span 8" }} /> : ""}
314 <Link to={`/maps/${r.id}`}><span>{r.name}</span></Link> 265
315 <span style={{ display: "grid" }}>{record!.scores[i].score_count}</span> 266 <Link to={`/maps/${r.map_id}`}><span>{r.map_name}</span></Link>
316 <span style={{ display: "grid" }}>{record!.scores[i].score_count - record!.map_wr_count > 0 ? `+${record!.scores[i].score_count - record!.map_wr_count}` : record!.scores[i].score_count - record!.map_wr_count}</span> 267
317 <span style={{ display: "grid" }}>{ticks_to_time(record!.scores[i].score_time)}</span> 268 <span style={{ display: "grid" }}>{e.score_count}</span>
269
270 <span style={{ display: "grid" }}>{e.score_count - r.map_wr_count > 0 ? `+${e.score_count - r.map_wr_count}` : e.score_count - r.map_wr_count}</span>
271 <span style={{ display: "grid" }}>{ticks_to_time(e.score_time)}</span>
318 <span> </span> 272 <span> </span>
319 {i === 0 ? <span>#{record!.placement}</span> : <span> </span>} 273 {i === 0 ? <span>#{r.placement}</span> : <span> </span>}
320 <span>{record!.scores[i].date.split("T")[0]}</span> 274 <span>{e.date.split("T")[0]}</span>
321 <span style={{ flexDirection: "row-reverse" }}> 275 <span style={{ flexDirection: "row-reverse" }}>
322 276
323 <button onClick={() => { message("Demo information", `Demo ID: ${e.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> 277 <button style={{ marginRight: "10px" }} onClick={() => { message("Demo Information", `Demo ID: ${e.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button>
324 <button onClick={() => { _delete_submission(r.id, e.record_id) }}><img src={DeleteIcon}></img></button> 278 <button onClick={() => { _delete_submission(r.map_id, e.record_id) }}><img src={DeleteIcon}></img></button>
325 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${e.demo_id}`}><img src={DownloadIcon} alt="download" /></button> 279 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${e.demo_id}`}><img src={DownloadIcon} alt="download" /></button>
326 {i === 0 && record!.scores.length > 1 ? <button onClick={() => { 280 {i === 0 && r.scores.length > 1 ? <button onClick={() => {
327 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "44px" || 281 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "44px" ||
328 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "" ? 282 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "" ?
329 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = `${record!.scores.length * 46}px` : 283 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = `${r.scores.length * 46}px` :
330 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = "44px" 284 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = "44px"
331 } 285 }
332 }><img src={HistoryIcon} alt="history" /></button> : ""} 286 }><img src={HistoryIcon} alt="history" /></button> : ""}
333 287
334 </span> 288 </span>
335 </>))} 289 </>))}
336 </button>
337 290
338 ) 291 </button>
339 } else { return null } 292 ) : ""
340 }) : (<>{console.warn(maps)}</>)} 293 ))) : maps ?
341 </div> 294
342 </section> 295 maps.filter(e => e.is_disabled === false).sort((a, b) => a.id - b.id)
343 </main> 296 .map((r, index) => {
344 </div> 297 if (Math.ceil((index + 1) / 20) === pageNumber) {
298 let record = profile.records.find((e) => e.map_id === r.id);
299 return record === undefined ? (
300 <button className="profileboard-record" key={index} style={{ backgroundColor: "#1b1b20" }}>
301 <Link to={`/maps/${r.id}`}><span>{r.name}</span></Link>
302 <span style={{ display: "grid" }}>N/A</span>
303 <span style={{ display: "grid" }}>N/A</span>
304 <span>N/A</span>
305 <span> </span>
306 <span>N/A</span>
307 <span>N/A</span>
308 <span style={{ flexDirection: "row-reverse" }}></span>
309 </button>
310 ) : (
311 <button className="profileboard-record" key={index}>
312 {record.scores.map((e, i) => (<>
313 {i !== 0 ? <hr style={{ gridColumn: "1 / span 8" }} /> : ""}
314 <Link to={`/maps/${r.id}`}><span>{r.name}</span></Link>
315 <span style={{ display: "grid" }}>{record!.scores[i].score_count}</span>
316 <span style={{ display: "grid" }}>{record!.scores[i].score_count - record!.map_wr_count > 0 ? `+${record!.scores[i].score_count - record!.map_wr_count}` : record!.scores[i].score_count - record!.map_wr_count}</span>
317 <span style={{ display: "grid" }}>{ticks_to_time(record!.scores[i].score_time)}</span>
318 <span> </span>
319 {i === 0 ? <span>#{record!.placement}</span> : <span> </span>}
320 <span>{record!.scores[i].date.split("T")[0]}</span>
321 <span style={{ flexDirection: "row-reverse" }}>
322
323 <button onClick={() => { message("Demo Information", `Demo ID: ${e.demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button>
324 <button onClick={() => { _delete_submission(r.id, e.record_id) }}><img src={DeleteIcon}></img></button>
325 <button onClick={() => window.location.href = `/api/v1/demos?uuid=${e.demo_id}`}><img src={DownloadIcon} alt="download" /></button>
326 {i === 0 && record!.scores.length > 1 ? <button onClick={() => {
327 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "44px" ||
328 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height === "" ?
329 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = `${record!.scores.length * 46}px` :
330 (document.querySelectorAll(".profileboard-record")[index % 20] as HTMLInputElement).style.height = "44px"
331 }
332 }><img src={HistoryIcon} alt="history" /></button> : ""}
333
334 </span>
335 </>))}
336 </button>
337
338 )
339 } else { return null }
340 }) : (<>{console.warn(maps)}</>)}
341 </div>
342 </section>
343 </main>
344 </div>
345 ); 345 );
346}; 346};
347 347