aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/components/UploadRunDialog.tsx
diff options
context:
space:
mode:
authorFifthWit <fifthwitbusiness@gmail.com>2025-01-30 10:44:30 -0600
committerFifthWit <fifthwitbusiness@gmail.com>2025-01-30 10:44:30 -0600
commite40f07211f5f15dcb138e2520a76d13afd3c0cfd (patch)
tree46bad6a17e66d55a4a65088c0b6eb8c48641615a /frontend/src/components/UploadRunDialog.tsx
parentadded prettier for more consistency (diff)
downloadlphub-e40f07211f5f15dcb138e2520a76d13afd3c0cfd.tar.gz
lphub-e40f07211f5f15dcb138e2520a76d13afd3c0cfd.tar.bz2
lphub-e40f07211f5f15dcb138e2520a76d13afd3c0cfd.zip
formatted with prettier
Diffstat (limited to 'frontend/src/components/UploadRunDialog.tsx')
-rw-r--r--frontend/src/components/UploadRunDialog.tsx366
1 files changed, 253 insertions, 113 deletions
diff --git a/frontend/src/components/UploadRunDialog.tsx b/frontend/src/components/UploadRunDialog.tsx
index c02fdb8..227a564 100644
--- a/frontend/src/components/UploadRunDialog.tsx
+++ b/frontend/src/components/UploadRunDialog.tsx
@@ -8,7 +8,7 @@ import { API } from '@api/Api';
8import { useNavigate } from 'react-router-dom'; 8import { useNavigate } from 'react-router-dom';
9import useMessage from '@hooks/UseMessage'; 9import useMessage from '@hooks/UseMessage';
10import useConfirm from '@hooks/UseConfirm'; 10import useConfirm from '@hooks/UseConfirm';
11import useMessageLoad from "@hooks/UseMessageLoad"; 11import useMessageLoad from '@hooks/UseMessageLoad';
12import { MapNames } from '@customTypes/MapNames'; 12import { MapNames } from '@customTypes/MapNames';
13 13
14interface UploadRunDialogProps { 14interface UploadRunDialogProps {
@@ -18,21 +18,27 @@ interface UploadRunDialogProps {
18 games: Game[]; 18 games: Game[];
19} 19}
20 20
21const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose, games }) => { 21const UploadRunDialog: React.FC<UploadRunDialogProps> = ({
22 22 token,
23 open,
24 onClose,
25 games,
26}) => {
23 const { message, MessageDialogComponent } = useMessage(); 27 const { message, MessageDialogComponent } = useMessage();
24 const { confirm, ConfirmDialogComponent } = useConfirm(); 28 const { confirm, ConfirmDialogComponent } = useConfirm();
25 const { messageLoad, messageLoadClose, MessageDialogLoadComponent } = useMessageLoad(); 29 const { messageLoad, messageLoadClose, MessageDialogLoadComponent } =
30 useMessageLoad();
26 31
27 const navigate = useNavigate(); 32 const navigate = useNavigate();
28 33
29 const [uploadRunContent, setUploadRunContent] = React.useState<UploadRunContent>({ 34 const [uploadRunContent, setUploadRunContent] =
30 host_demo: null, 35 React.useState<UploadRunContent>({
31 partner_demo: null, 36 host_demo: null,
32 }); 37 partner_demo: null,
38 });
33 39
34 const [selectedGameID, setSelectedGameID] = React.useState<number>(0); 40 const [selectedGameID, setSelectedGameID] = React.useState<number>(0);
35 const [selectedGameName, setSelectedGameName] = React.useState<string>(""); 41 const [selectedGameName, setSelectedGameName] = React.useState<string>('');
36 42
37 // dropdowns 43 // dropdowns
38 const [dropdown1Vis, setDropdown1Vis] = React.useState<boolean>(false); 44 const [dropdown1Vis, setDropdown1Vis] = React.useState<boolean>(false);
@@ -41,7 +47,8 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
41 const [loading, setLoading] = React.useState<boolean>(false); 47 const [loading, setLoading] = React.useState<boolean>(false);
42 48
43 const [dragHightlight, setDragHighlight] = React.useState<boolean>(false); 49 const [dragHightlight, setDragHighlight] = React.useState<boolean>(false);
44 const [dragHightlightPartner, setDragHighlightPartner] = React.useState<boolean>(false); 50 const [dragHightlightPartner, setDragHighlightPartner] =
51 React.useState<boolean>(false);
45 52
46 const fileInputRef = React.useRef<HTMLInputElement>(null); 53 const fileInputRef = React.useRef<HTMLInputElement>(null);
47 const fileInputRefPartner = React.useRef<HTMLInputElement>(null); 54 const fileInputRefPartner = React.useRef<HTMLInputElement>(null);
@@ -52,9 +59,12 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
52 } else { 59 } else {
53 fileInputRefPartner.current?.click(); 60 fileInputRefPartner.current?.click();
54 } 61 }
55 } 62 };
56 63
57 const _handle_drag_over = (e: React.DragEvent<HTMLDivElement>, host: boolean) => { 64 const _handle_drag_over = (
65 e: React.DragEvent<HTMLDivElement>,
66 host: boolean
67 ) => {
58 e.preventDefault(); 68 e.preventDefault();
59 e.stopPropagation(); 69 e.stopPropagation();
60 if (host) { 70 if (host) {
@@ -62,9 +72,12 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
62 } else { 72 } else {
63 setDragHighlightPartner(true); 73 setDragHighlightPartner(true);
64 } 74 }
65 } 75 };
66 76
67 const _handle_drag_leave = (e: React.DragEvent<HTMLDivElement>, host: boolean) => { 77 const _handle_drag_leave = (
78 e: React.DragEvent<HTMLDivElement>,
79 host: boolean
80 ) => {
68 e.preventDefault(); 81 e.preventDefault();
69 e.stopPropagation(); 82 e.stopPropagation();
70 if (host) { 83 if (host) {
@@ -72,7 +85,7 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
72 } else { 85 } else {
73 setDragHighlightPartner(false); 86 setDragHighlightPartner(false);
74 } 87 }
75 } 88 };
76 89
77 const _handle_drop = (e: React.DragEvent<HTMLDivElement>, host: boolean) => { 90 const _handle_drop = (e: React.DragEvent<HTMLDivElement>, host: boolean) => {
78 e.preventDefault(); 91 e.preventDefault();
@@ -80,7 +93,7 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
80 setDragHighlight(true); 93 setDragHighlight(true);
81 94
82 _handle_file_change(e.dataTransfer.files, host); 95 _handle_file_change(e.dataTransfer.files, host);
83 } 96 };
84 97
85 const _handle_dropdowns = (dropdown: number) => { 98 const _handle_dropdowns = (dropdown: number) => {
86 setDropdown1Vis(false); 99 setDropdown1Vis(false);
@@ -89,9 +102,9 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
89 setDropdown1Vis(!dropdown1Vis); 102 setDropdown1Vis(!dropdown1Vis);
90 } else if (dropdown == 2) { 103 } else if (dropdown == 2) {
91 setDropdown2Vis(!dropdown2Vis); 104 setDropdown2Vis(!dropdown2Vis);
92 document.querySelector("#dropdown2")?.scrollTo(0, 0); 105 document.querySelector('#dropdown2')?.scrollTo(0, 0);
93 } 106 }
94 } 107 };
95 108
96 const _handle_game_select = async (game_id: string, game_name: string) => { 109 const _handle_game_select = async (game_id: string, game_name: string) => {
97 setLoading(true); 110 setLoading(true);
@@ -120,62 +133,85 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
120 if (token) { 133 if (token) {
121 if (games[selectedGameID].is_coop) { 134 if (games[selectedGameID].is_coop) {
122 if (uploadRunContent.host_demo === null) { 135 if (uploadRunContent.host_demo === null) {
123 await message("Error", "You must select a host demo to upload.") 136 await message('Error', 'You must select a host demo to upload.');
124 return 137 return;
125 } else if (uploadRunContent.partner_demo === null) { 138 } else if (uploadRunContent.partner_demo === null) {
126 await message("Error", "You must select a partner demo to upload.") 139 await message('Error', 'You must select a partner demo to upload.');
127 return 140 return;
128 } 141 }
129 } else { 142 } else {
130 if (uploadRunContent.host_demo === null) { 143 if (uploadRunContent.host_demo === null) {
131 await message("Error", "You must select a demo to upload.") 144 await message('Error', 'You must select a demo to upload.');
132 return 145 return;
133 } 146 }
134 } 147 }
135 const demo = SourceDemoParser.default() 148 const demo = SourceDemoParser.default()
136 .setOptions({ packets: true, header: true }) 149 .setOptions({ packets: true, header: true })
137 .parse(await uploadRunContent.host_demo.arrayBuffer()); 150 .parse(await uploadRunContent.host_demo.arrayBuffer());
138 const scoreboard = demo.findPacket<NetMessages.SvcUserMessage>((msg) => { 151 const scoreboard = demo.findPacket<NetMessages.SvcUserMessage>(msg => {
139 return msg instanceof NetMessages.SvcUserMessage && msg.userMessage instanceof ScoreboardTempUpdate; 152 return (
140 }) 153 msg instanceof NetMessages.SvcUserMessage &&
154 msg.userMessage instanceof ScoreboardTempUpdate
155 );
156 });
141 157
142 if (!scoreboard) { 158 if (!scoreboard) {
143 await message("Error", "Error while processing demo: Unable to get scoreboard result. Either there is a demo that is corrupt or haven't been recorded in challenge mode.") 159 await message(
144 return 160 'Error',
161 "Error while processing demo: Unable to get scoreboard result. Either there is a demo that is corrupt or haven't been recorded in challenge mode."
162 );
163 return;
145 } 164 }
146 165
147 if (!demo.mapName || !MapNames[demo.mapName]) { 166 if (!demo.mapName || !MapNames[demo.mapName]) {
148 await message("Error", "Error while processing demo: Invalid map name.") 167 await message(
149 return 168 'Error',
169 'Error while processing demo: Invalid map name.'
170 );
171 return;
150 } 172 }
151 173
152 if (selectedGameID === 0 && MapNames[demo.mapName] > 60) { 174 if (selectedGameID === 0 && MapNames[demo.mapName] > 60) {
153 await message("Error", "Error while processing demo: Invalid cooperative demo in singleplayer submission.") 175 await message(
154 return 176 'Error',
177 'Error while processing demo: Invalid cooperative demo in singleplayer submission.'
178 );
179 return;
155 } else if (selectedGameID === 1 && MapNames[demo.mapName] <= 60) { 180 } else if (selectedGameID === 1 && MapNames[demo.mapName] <= 60) {
156 await message("Error", "Error while processing demo: Invalid singleplayer demo in cooperative submission.") 181 await message(
157 return 182 'Error',
183 'Error while processing demo: Invalid singleplayer demo in cooperative submission.'
184 );
185 return;
158 } 186 }
159 187
160 const { portalScore, timeScore } = scoreboard.userMessage?.as<ScoreboardTempUpdate>() ?? {}; 188 const { portalScore, timeScore } =
189 scoreboard.userMessage?.as<ScoreboardTempUpdate>() ?? {};
161 190
162 const userConfirmed = await confirm("Upload Record", `Map Name: ${demo.mapName}\nPortal Count: ${portalScore}\nTicks: ${timeScore}\n\nAre you sure you want to upload this demo?`); 191 const userConfirmed = await confirm(
192 'Upload Record',
193 `Map Name: ${demo.mapName}\nPortal Count: ${portalScore}\nTicks: ${timeScore}\n\nAre you sure you want to upload this demo?`
194 );
163 195
164 if (!userConfirmed) { 196 if (!userConfirmed) {
165 return; 197 return;
166 } 198 }
167 199
168 messageLoad("Uploading..."); 200 messageLoad('Uploading...');
169 const [success, response] = await API.post_record(token, uploadRunContent, MapNames[demo.mapName]); 201 const [success, response] = await API.post_record(
202 token,
203 uploadRunContent,
204 MapNames[demo.mapName]
205 );
170 messageLoadClose(); 206 messageLoadClose();
171 await message("Upload Record", response); 207 await message('Upload Record', response);
172 if (success) { 208 if (success) {
173 setUploadRunContent({ 209 setUploadRunContent({
174 host_demo: null, 210 host_demo: null,
175 partner_demo: null, 211 partner_demo: null,
176 }); 212 });
177 onClose(success); 213 onClose(success);
178 navigate("/profile"); 214 navigate('/profile');
179 } 215 }
180 } 216 }
181 }; 217 };
@@ -184,7 +220,7 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
184 if (open) { 220 if (open) {
185 setDragHighlightPartner(false); 221 setDragHighlightPartner(false);
186 setDragHighlight(false); 222 setDragHighlight(false);
187 _handle_game_select("1", "Portal 2 - Singleplayer"); // a different approach?. 223 _handle_game_select('1', 'Portal 2 - Singleplayer'); // a different approach?.
188 } 224 }
189 }, [open]); 225 }, [open]);
190 226
@@ -196,84 +232,191 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
196 {MessageDialogLoadComponent} 232 {MessageDialogLoadComponent}
197 {ConfirmDialogComponent} 233 {ConfirmDialogComponent}
198 234
199 <div id='upload-run-menu'> 235 <div id="upload-run-menu">
200 <div id='upload-run-menu-add'> 236 <div id="upload-run-menu-add">
201 <div id='upload-run-route-category'> 237 <div id="upload-run-route-category">
202 <div style={{ padding: "15px 0px" }} className='upload-run-dropdown-container upload-run-item'> 238 <div
203 <h3 style={{ margin: "0px 0px" }}>Select Game</h3> 239 style={{ padding: '15px 0px' }}
204 <div onClick={() => _handle_dropdowns(1)} style={{ display: "flex", alignItems: "center", cursor: "pointer", justifyContent: "space-between", margin: "10px 0px" }}> 240 className="upload-run-dropdown-container upload-run-item"
205 <div className='dropdown-cur'>{selectedGameName}</div> 241 >
206 <i style={{ rotate: "-90deg", transform: "translate(-5px, 10px)" }} className="triangle"></i> 242 <h3 style={{ margin: '0px 0px' }}>Select Game</h3>
243 <div
244 onClick={() => _handle_dropdowns(1)}
245 style={{
246 display: 'flex',
247 alignItems: 'center',
248 cursor: 'pointer',
249 justifyContent: 'space-between',
250 margin: '10px 0px',
251 }}
252 >
253 <div className="dropdown-cur">{selectedGameName}</div>
254 <i
255 style={{
256 rotate: '-90deg',
257 transform: 'translate(-5px, 10px)',
258 }}
259 className="triangle"
260 ></i>
207 </div> 261 </div>
208 <div style={{ top: "110px" }} className={dropdown1Vis ? "upload-run-dropdown" : "upload-run-dropdown hidden"}> 262 <div
209 {games.map((game) => ( 263 style={{ top: '110px' }}
210 <div onClick={() => { _handle_game_select(game.id.toString(), game.name); _handle_dropdowns(1) }} key={game.id}>{game.name}</div> 264 className={
265 dropdown1Vis
266 ? 'upload-run-dropdown'
267 : 'upload-run-dropdown hidden'
268 }
269 >
270 {games.map(game => (
271 <div
272 onClick={() => {
273 _handle_game_select(game.id.toString(), game.name);
274 _handle_dropdowns(1);
275 }}
276 key={game.id}
277 >
278 {game.name}
279 </div>
211 ))} 280 ))}
212 </div> 281 </div>
213 </div> 282 </div>
214 283
215 { 284 {!loading && (
216 !loading && 285 <>
217 ( 286 <div>
218 <> 287 <h3 style={{ margin: '10px 0px' }}>Host Demo</h3>
219 288 <div
220 <div> 289 onClick={() => {
221 <h3 style={{ margin: "10px 0px" }}>Host Demo</h3> 290 _handle_file_click(true);
222 <div onClick={() => { _handle_file_click(true) }} onDragOver={(e) => { _handle_drag_over(e, true) }} onDrop={(e) => { _handle_drop(e, true) }} onDragLeave={(e) => { _handle_drag_leave(e, true) }} className={`upload-run-drag-area ${dragHightlight ? "upload-run-drag-area-highlight" : ""} ${uploadRunContent.host_demo ? "upload-run-drag-area-hidden" : ""}`}> 291 }}
223 <input ref={fileInputRef} type="file" name="host_demo" id="host_demo" accept=".dem" onChange={(e) => _handle_file_change(e.target.files, true)} /> 292 onDragOver={e => {
224 {!uploadRunContent.host_demo ? 293 _handle_drag_over(e, true);
294 }}
295 onDrop={e => {
296 _handle_drop(e, true);
297 }}
298 onDragLeave={e => {
299 _handle_drag_leave(e, true);
300 }}
301 className={`upload-run-drag-area ${dragHightlight ? 'upload-run-drag-area-highlight' : ''} ${uploadRunContent.host_demo ? 'upload-run-drag-area-hidden' : ''}`}
302 >
303 <input
304 ref={fileInputRef}
305 type="file"
306 name="host_demo"
307 id="host_demo"
308 accept=".dem"
309 onChange={e =>
310 _handle_file_change(e.target.files, true)
311 }
312 />
313 {!uploadRunContent.host_demo ? (
314 <div>
315 <span>Drag and drop</span>
225 <div> 316 <div>
226 <span>Drag and drop</span> 317 <span
227 <div> 318 style={{
228 <span style={{ fontFamily: "BarlowSemiCondensed-Regular" }}>Or click here</span><br /> 319 fontFamily: 'BarlowSemiCondensed-Regular',
229 <button style={{ borderRadius: "24px", padding: "5px 8px", margin: "5px 0px" }}>Upload</button> 320 }}
230 </div> 321 >
322 Or click here
323 </span>
324 <br />
325 <button
326 style={{
327 borderRadius: '24px',
328 padding: '5px 8px',
329 margin: '5px 0px',
330 }}
331 >
332 Upload
333 </button>
231 </div> 334 </div>
232 : null} 335 </div>
233 336 ) : null}
234 <span className="upload-run-demo-name">{uploadRunContent.host_demo?.name}</span>
235 </div>
236 {
237 games[selectedGameID].is_coop &&
238 (
239 <>
240 <div>
241 <h3 style={{ margin: "10px 0px" }}>Partner Demo</h3>
242 <div onClick={() => { _handle_file_click(false) }} onDragOver={(e) => { _handle_drag_over(e, false) }} onDrop={(e) => { _handle_drop(e, false) }} onDragLeave={(e) => { _handle_drag_leave(e, false) }} className={`upload-run-drag-area ${dragHightlightPartner ? "upload-run-drag-area-highlight-partner" : ""} ${uploadRunContent.partner_demo ? "upload-run-drag-area-hidden" : ""}`}>
243 <input ref={fileInputRefPartner} type="file" name="partner_demo" id="partner_demo" accept=".dem" onChange={(e) => _handle_file_change(e.target.files, false)} /> {!uploadRunContent.partner_demo ?
244 <div>
245 <span>Drag and drop</span>
246 <div>
247 <span style={{ fontFamily: "BarlowSemiCondensed-Regular" }}>Or click here</span><br />
248 <button style={{ borderRadius: "24px", padding: "5px 8px", margin: "5px 0px" }}>Upload</button>
249 </div>
250 </div>
251 : null}
252
253 <span className="upload-run-demo-name">{uploadRunContent.partner_demo?.name}</span>
254 </div>
255 </div>
256 </>
257 )
258 }
259 </div>
260 <div className='search-container'>
261 337
338 <span className="upload-run-demo-name">
339 {uploadRunContent.host_demo?.name}
340 </span>
262 </div> 341 </div>
263 342 {games[selectedGameID].is_coop && (
264 </> 343 <>
265 ) 344 <div>
266 } 345 <h3 style={{ margin: '10px 0px' }}>Partner Demo</h3>
346 <div
347 onClick={() => {
348 _handle_file_click(false);
349 }}
350 onDragOver={e => {
351 _handle_drag_over(e, false);
352 }}
353 onDrop={e => {
354 _handle_drop(e, false);
355 }}
356 onDragLeave={e => {
357 _handle_drag_leave(e, false);
358 }}
359 className={`upload-run-drag-area ${dragHightlightPartner ? 'upload-run-drag-area-highlight-partner' : ''} ${uploadRunContent.partner_demo ? 'upload-run-drag-area-hidden' : ''}`}
360 >
361 <input
362 ref={fileInputRefPartner}
363 type="file"
364 name="partner_demo"
365 id="partner_demo"
366 accept=".dem"
367 onChange={e =>
368 _handle_file_change(e.target.files, false)
369 }
370 />{' '}
371 {!uploadRunContent.partner_demo ? (
372 <div>
373 <span>Drag and drop</span>
374 <div>
375 <span
376 style={{
377 fontFamily: 'BarlowSemiCondensed-Regular',
378 }}
379 >
380 Or click here
381 </span>
382 <br />
383 <button
384 style={{
385 borderRadius: '24px',
386 padding: '5px 8px',
387 margin: '5px 0px',
388 }}
389 >
390 Upload
391 </button>
392 </div>
393 </div>
394 ) : null}
395 <span className="upload-run-demo-name">
396 {uploadRunContent.partner_demo?.name}
397 </span>
398 </div>
399 </div>
400 </>
401 )}
402 </div>
403 <div className="search-container"></div>
404 </>
405 )}
267 </div> 406 </div>
268 <div className='upload-run-buttons-container'> 407 <div className="upload-run-buttons-container">
269 <button onClick={_upload_run}>Submit</button> 408 <button onClick={_upload_run}>Submit</button>
270 <button onClick={() => { 409 <button
271 onClose(false); 410 onClick={() => {
272 setUploadRunContent({ 411 onClose(false);
273 host_demo: null, 412 setUploadRunContent({
274 partner_demo: null, 413 host_demo: null,
275 }); 414 partner_demo: null,
276 }}>Cancel</button> 415 });
416 }}
417 >
418 Cancel
419 </button>
277 </div> 420 </div>
278 </div> 421 </div>
279 </div> 422 </div>
@@ -281,10 +424,7 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose,
281 ); 424 );
282 } 425 }
283 426
284 return ( 427 return <></>;
285 <></>
286 );
287
288}; 428};
289 429
290export default UploadRunDialog; 430export default UploadRunDialog;