From f5ad360d02303ce27a65e67feb8ae38f1e26742c Mon Sep 17 00:00:00 2001 From: Arda Serdar Pektezol <1669855+pektezol@users.noreply.github.com> Date: Thu, 31 Oct 2024 23:58:14 +0300 Subject: frontend: convert all native confirm and alerts to custom hooks --- frontend/src/components/Discussions.tsx | 12 +- frontend/src/components/Leaderboards.tsx | 4 +- frontend/src/components/ModMenu.tsx | 16 +- frontend/src/hooks/UseConfirm.tsx | 2 +- frontend/src/pages/Profile.tsx | 396 +++++++++++++++---------------- frontend/src/pages/User.tsx | 10 +- 6 files changed, 226 insertions(+), 214 deletions(-) diff --git a/frontend/src/components/Discussions.tsx b/frontend/src/components/Discussions.tsx index c22de79..0522910 100644 --- a/frontend/src/components/Discussions.tsx +++ b/frontend/src/components/Discussions.tsx @@ -6,6 +6,7 @@ import { time_ago } from '../utils/Time'; import { API } from '../api/Api'; import "../css/Maps.css" import { Link } from 'react-router-dom'; +import useConfirm from '../hooks/UseConfirm'; interface DiscussionsProps { token?: string @@ -17,6 +18,8 @@ interface DiscussionsProps { const Discussions: React.FC = ({ token, data, isModerator, mapID, onRefresh }) => { + const { confirm, ConfirmDialogComponent } = useConfirm(); + const [discussionThread, setDiscussionThread] = React.useState(undefined); const [discussionSearch, setDiscussionSearch] = React.useState(""); @@ -48,7 +51,7 @@ const Discussions: React.FC = ({ token, data, isModerator, map }; const _delete_map_discussion = async (discussion: MapDiscussionsDetail) => { - if (window.confirm(`Are you sure you want to remove post: ${discussion.title}?`)) { + if (await confirm("Delete Map Discussion", `Are you sure you want to remove post: ${discussion.title}?`)) { if (token) { await API.delete_map_discussion(token, mapID, discussion.id); onRefresh(); @@ -58,6 +61,7 @@ const Discussions: React.FC = ({ token, data, isModerator, map return (
+ {ConfirmDialogComponent}
- e.key === "Enter" && _create_map_discussion_comment(discussionThread.discussion.id)} - onChange={(e) => setCreateDiscussionCommentContent(e.target.value)} /> + e.key === "Enter" && _create_map_discussion_comment(discussionThread.discussion.id)} + onChange={(e) => setCreateDiscussionCommentContent(e.target.value)} />
+ ) : r.kind === "singleplayer" && ( - + )} diff --git a/frontend/src/components/ModMenu.tsx b/frontend/src/components/ModMenu.tsx index 5b0d1c8..2fb1737 100644 --- a/frontend/src/components/ModMenu.tsx +++ b/frontend/src/components/ModMenu.tsx @@ -1,11 +1,12 @@ import React from 'react'; import ReactMarkdown from 'react-markdown'; +import { useNavigate } from 'react-router-dom'; import { MapSummary } from '../types/Map'; import { ModMenuContent } from '../types/Content'; import { API } from '../api/Api'; import "../css/ModMenu.css" -import { useNavigate } from 'react-router-dom'; +import useConfirm from '../hooks/UseConfirm'; interface ModMenuProps { token?: string; @@ -16,6 +17,8 @@ interface ModMenuProps { const ModMenu: React.FC = ({ token, data, selectedRun, mapID }) => { + const { confirm, ConfirmDialogComponent } = useConfirm(); + const [menu, setMenu] = React.useState(0); const [showButton, setShowButton] = React.useState(true); @@ -64,7 +67,7 @@ const ModMenu: React.FC = ({ token, data, selectedRun, mapID }) => }; const _edit_map_summary_image = async () => { - if (window.confirm("Are you sure you want to submit this to the database?")) { + if (await confirm("Edit Map Summary Image", "Are you sure you want to submit this to the database?")) { if (token) { const success = await API.put_map_image(token, mapID, image); if (success) { @@ -77,7 +80,7 @@ const ModMenu: React.FC = ({ token, data, selectedRun, mapID }) => }; const _edit_map_summary_route = async () => { - if (window.confirm("Are you sure you want to submit this to the database?")) { + if (await confirm("Edit Map Summary Route", "Are you sure you want to submit this to the database?")) { if (token) { routeContent.date += "T00:00:00Z"; const success = await API.put_map_summary(token, mapID, routeContent); @@ -91,7 +94,7 @@ const ModMenu: React.FC = ({ token, data, selectedRun, mapID }) => }; const _create_map_summary_route = async () => { - if (window.confirm("Are you sure you want to submit this to the database?")) { + if (await confirm("Create Map Summary Route", "Are you sure you want to submit this to the database?")) { if (token) { routeContent.date += "T00:00:00Z"; const success = await API.post_map_summary(token, mapID, routeContent); @@ -105,8 +108,8 @@ const ModMenu: React.FC = ({ token, data, selectedRun, mapID }) => }; const _delete_map_summary_route = async () => { - if (window.confirm(`Are you sure you want to delete this run from the database? - ${data.summary.routes[selectedRun].category.name} ${data.summary.routes[selectedRun].history.score_count} portals ${data.summary.routes[selectedRun].history.runner_name}`)) { + if (await confirm("Delete Map Summary Route", `Are you sure you want to submit this to the database?\n + ${data.summary.routes[selectedRun].category.name}\n${data.summary.routes[selectedRun].history.score_count} portals\n${data.summary.routes[selectedRun].history.runner_name}`)) { if (token) { const success = await API.delete_map_summary(token, mapID, data.summary.routes[selectedRun].route_id); if (success) { @@ -160,6 +163,7 @@ const ModMenu: React.FC = ({ token, data, selectedRun, mapID }) => return ( <> + {ConfirmDialogComponent}
diff --git a/frontend/src/hooks/UseConfirm.tsx b/frontend/src/hooks/UseConfirm.tsx index 9a7853b..0d64224 100644 --- a/frontend/src/hooks/UseConfirm.tsx +++ b/frontend/src/hooks/UseConfirm.tsx @@ -11,7 +11,7 @@ const useConfirm = () => { setIsOpen(true); setTitle(titleN); setSubtitle(subtitleN); - return new Promise((resolve) => { + return new Promise((resolve) => { setResolvePromise(() => resolve); }); }; 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 = ({ profile, token, gameData, onDeleteRec return; } - messageLoad("Deleting..."); + messageLoad("Deleting..."); const api_success = await API.delete_map_record(token!, map_id, record_id); - messageLoadClose(); + messageLoadClose(); if (api_success) { await message("Delete Record", "Successfully deleted record."); onDeleteRecord(); @@ -108,240 +108,240 @@ const Profile: React.FC = ({ profile, token, gameData, onDeleteRec }; return ( -
- {MessageDialogComponent} - {MessageDialogLoadComponent} - {ConfirmDialogComponent} - -
-
- - {profile.profile - ? ( -
- profile-image - Refresh +
+ {MessageDialogComponent} + {MessageDialogLoadComponent} + {ConfirmDialogComponent} + +
+
+ + {profile.profile + ? ( +
+ profile-image + Refresh +
+ ) : ( +
+ profile-image +
+ )} + +
+
+
{profile.user_name}
+
+ {profile.country_code === "XX" ? "" : {profile.country_code}} +
+
+ {profile.titles.map(e => ( + + {e.name} + + ))} +
- ) : (
- profile-image + {profile.links.steam === "-" ? "" : Steam} + {profile.links.twitch === "-" ? "" : Twitch} + {profile.links.youtube === "-" ? "" : Youtube} + {profile.links.p2sr === "-" ? "" : P2SR}
- )} -
-
-
{profile.user_name}
+
+
- {profile.country_code === "XX" ? "" : {profile.country_code}} + Overall + {profile.rankings.overall.rank === 0 ? "N/A " : "#" + profile.rankings.overall.rank + " "} + ({profile.rankings.overall.completion_count}/{profile.rankings.overall.completion_total}) +
- {profile.titles.map(e => ( - - {e.name} - - ))} + Singleplayer + {profile.rankings.singleplayer.rank === 0 ? "N/A " : "#" + profile.rankings.singleplayer.rank + " "} + ({profile.rankings.singleplayer.completion_count}/{profile.rankings.singleplayer.completion_total}) + +
+
+ Cooperative + {profile.rankings.cooperative.rank === 0 ? "N/A " : "#" + profile.rankings.cooperative.rank + " "} + ({profile.rankings.cooperative.completion_count}/{profile.rankings.cooperative.completion_total}) +
-
- {profile.links.steam === "-" ? "" : Steam} - {profile.links.twitch === "-" ? "" : Twitch} - {profile.links.youtube === "-" ? "" : Youtube} - {profile.links.p2sr === "-" ? "" : P2SR} -
- -
-
-
- Overall - {profile.rankings.overall.rank === 0 ? "N/A " : "#" + profile.rankings.overall.rank + " "} - ({profile.rankings.overall.completion_count}/{profile.rankings.overall.completion_total}) - -
-
- Singleplayer - {profile.rankings.singleplayer.rank === 0 ? "N/A " : "#" + profile.rankings.singleplayer.rank + " "} - ({profile.rankings.singleplayer.completion_count}/{profile.rankings.singleplayer.completion_total}) - -
-
- Cooperative - {profile.rankings.cooperative.rank === 0 ? "N/A " : "#" + profile.rankings.cooperative.rank + " "} - ({profile.rankings.cooperative.completion_count}/{profile.rankings.cooperative.completion_total}) - -
-
-
- - -
- - -
+
+
+ + +
-
-
- {gameData === null ? : - - } - {game === "0" ? - - : chapterData === null ? : +
+
+ {gameData === null ? : - { + setGame((document.querySelector('#select-game') as HTMLInputElement).value); + setChapter("0"); + const chapterSelect = document.querySelector('#select-chapter') as HTMLSelectElement; + if (chapterSelect) { + chapterSelect.value = "0"; + } + }}> + + {gameData.map((e, i) => ( ))} - } -
-
- Map Name - Portals - WRΔ - Time - - Rank - Date -
-
- - {pageNumber}/{pageMax} - + } + + {game === "0" ? + + : chapterData === null ? : + + + } +
+
+ Map Name + Portals + WRΔ + Time + + Rank + Date +
+
+ + {pageNumber}/{pageMax} + +
-
-
-
+
+
- {game === "0" - ? ( + {game === "0" + ? ( - profile.records.sort((a, b) => a.map_id - b.map_id) - .map((r, index) => ( - - Math.ceil((index + 1) / 20) === pageNumber ? ( - - - - {i === 0 && r.scores.length > 1 ? : ""} - - - ))} - - - ) : "" - ))) : maps ? - - maps.filter(e => e.is_disabled === false).sort((a, b) => a.id - b.id) - .map((r, index) => { - if (Math.ceil((index + 1) / 20) === pageNumber) { - let record = profile.records.find((e) => e.map_id === r.id); - return record === undefined ? ( - - ) : ( + profile.records.sort((a, b) => a.map_id - b.map_id) + .map((r, index) => ( + + Math.ceil((index + 1) / 20) === pageNumber ? ( - + + - {i === 0 && record!.scores.length > 1 ? : ""} ))} - - ) - } else { return null } - }) : (<>{console.warn(maps)})} -
-
-
-
+ + ) : "" + ))) : maps ? + + maps.filter(e => e.is_disabled === false).sort((a, b) => a.id - b.id) + .map((r, index) => { + if (Math.ceil((index + 1) / 20) === pageNumber) { + let record = profile.records.find((e) => e.map_id === r.id); + return record === undefined ? ( + + ) : ( + + + + {i === 0 && record!.scores.length > 1 ? : ""} + + + ))} + + + ) + } else { return null } + }) : (<>{console.warn(maps)})} +
+
+ + ); }; diff --git a/frontend/src/pages/User.tsx b/frontend/src/pages/User.tsx index c1175bb..ad230bd 100644 --- a/frontend/src/pages/User.tsx +++ b/frontend/src/pages/User.tsx @@ -8,6 +8,7 @@ import { Map } from '../types/Map'; import { API } from '../api/Api'; import { ticks_to_time } from '../utils/Time'; import "../css/Profile.css"; +import useMessage from '../hooks/UseMessage'; interface UserProps { profile?: UserProfile; @@ -17,6 +18,8 @@ interface UserProps { const User: React.FC = ({ token, profile, gameData }) => { + const { message, MessageDialogComponent } = useMessage(); + const [user, setUser] = React.useState(undefined); const [navState, setNavState] = React.useState(0); @@ -89,6 +92,7 @@ const User: React.FC = ({ token, profile, gameData }) => { return (
+ {MessageDialogComponent}
profile-image @@ -190,7 +194,7 @@ const User: React.FC = ({ token, profile, gameData }) => { Date
- + {i === 0 && r.scores.length > 1 ? + {i === 0 && record!.scores.length > 1 ?