diff options
Diffstat (limited to 'frontend')
| -rw-r--r-- | frontend/src/App.tsx | 28 | ||||
| -rw-r--r-- | frontend/src/api/Maps.tsx | 6 | ||||
| -rw-r--r-- | frontend/src/components/Leaderboards.tsx | 6 | ||||
| -rw-r--r-- | frontend/src/components/MessageDialog.tsx | 2 | ||||
| -rw-r--r-- | frontend/src/components/UploadRunDialog.tsx | 32 | ||||
| -rw-r--r-- | frontend/src/css/Dialog.css | 3 | ||||
| -rw-r--r-- | frontend/src/css/UploadRunDialog.css | 7 | ||||
| -rw-r--r-- | frontend/src/hooks/UseConfirm.tsx | 2 | ||||
| -rw-r--r-- | frontend/src/hooks/UseMessage.tsx | 6 | ||||
| -rw-r--r-- | frontend/src/pages/Profile.tsx | 7 |
10 files changed, 47 insertions, 52 deletions
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index d1d501d..c6952b1 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx | |||
| @@ -1,5 +1,5 @@ | |||
| 1 | import React from 'react'; | 1 | import React from 'react'; |
| 2 | import { Routes, Route, useLocation } from "react-router-dom"; | 2 | import { Routes, Route } from "react-router-dom"; |
| 3 | 3 | ||
| 4 | import { UserProfile } from './types/Profile'; | 4 | import { UserProfile } from './types/Profile'; |
| 5 | import Sidebar from './components/Sidebar'; | 5 | import Sidebar from './components/Sidebar'; |
| @@ -18,22 +18,15 @@ import { API } from './api/Api'; | |||
| 18 | import Maplist from './pages/Maplist'; | 18 | import Maplist from './pages/Maplist'; |
| 19 | import Rankings from './pages/Rankings'; | 19 | import Rankings from './pages/Rankings'; |
| 20 | import { get_user_id_from_token, get_user_mod_from_token } from './utils/Jwt'; | 20 | import { get_user_id_from_token, get_user_mod_from_token } from './utils/Jwt'; |
| 21 | import { MapDeleteEndpoint } from './types/Map'; | ||
| 22 | 21 | ||
| 23 | const App: React.FC = () => { | 22 | const App: React.FC = () => { |
| 24 | const [token, setToken] = React.useState<string | undefined>(undefined); | 23 | const [token, setToken] = React.useState<string | undefined>(undefined); |
| 25 | const [profile, setProfile] = React.useState<UserProfile | undefined>(undefined); | 24 | const [profile, setProfile] = React.useState<UserProfile | undefined>(undefined); |
| 26 | const [isModerator, setIsModerator] = React.useState<boolean>(false); | 25 | const [isModerator, setIsModerator] = React.useState<boolean>(false); |
| 27 | 26 | ||
| 28 | const [msgIsOpen, setMsgIsOpen] = React.useState<boolean>(false); | ||
| 29 | |||
| 30 | const [games, setGames] = React.useState<Game[]>([]); | 27 | const [games, setGames] = React.useState<Game[]>([]); |
| 31 | 28 | ||
| 32 | const [uploadRunDialog, setUploadRunDialog] = React.useState<boolean>(false); | 29 | const [uploadRunDialog, setUploadRunDialog] = React.useState<boolean>(false); |
| 33 | const [uploadRunDialogMapID, setUploadRunDialogMapID] = React.useState<number | undefined>(undefined); | ||
| 34 | |||
| 35 | const [confirmDialogOpen, setConfirmDialogOpen] = React.useState<boolean>(false); | ||
| 36 | const [currDeleteMapInfo, setCurrDeleteMapInfo] = React.useState<MapDeleteEndpoint>(); | ||
| 37 | 30 | ||
| 38 | const _fetch_token = async () => { | 31 | const _fetch_token = async () => { |
| 39 | const token = await API.get_token(); | 32 | const token = await API.get_token(); |
| @@ -45,10 +38,9 @@ const App: React.FC = () => { | |||
| 45 | setGames(games); | 38 | setGames(games); |
| 46 | }; | 39 | }; |
| 47 | 40 | ||
| 48 | const _set_profile = async (user_id: string | undefined) => { | 41 | const _set_profile = async (user_id?: string) => { |
| 49 | if (user_id) { | 42 | if (user_id && token) { |
| 50 | setProfile({} as UserProfile); // placeholder before we call actual user profile | 43 | const user = await API.get_profile(token); |
| 51 | const user = await API.get_profile(token!); | ||
| 52 | setProfile(user); | 44 | setProfile(user); |
| 53 | } | 45 | } |
| 54 | }; | 46 | }; |
| @@ -58,6 +50,7 @@ const App: React.FC = () => { | |||
| 58 | setProfile(undefined); | 50 | setProfile(undefined); |
| 59 | setIsModerator(false); | 51 | setIsModerator(false); |
| 60 | } else { | 52 | } else { |
| 53 | setProfile({} as UserProfile); // placeholder before we call actual user profile | ||
| 61 | _set_profile(get_user_id_from_token(token)) | 54 | _set_profile(get_user_id_from_token(token)) |
| 62 | const modStatus = get_user_mod_from_token(token) | 55 | const modStatus = get_user_mod_from_token(token) |
| 63 | if (modStatus) { | 56 | if (modStatus) { |
| @@ -81,15 +74,20 @@ const App: React.FC = () => { | |||
| 81 | 74 | ||
| 82 | return ( | 75 | return ( |
| 83 | <> | 76 | <> |
| 84 | <UploadRunDialog token={token} open={uploadRunDialog} onClose={() => setUploadRunDialog(false)} games={games} /> | 77 | <UploadRunDialog token={token} open={uploadRunDialog} onClose={(updateProfile) => { |
| 78 | setUploadRunDialog(false); | ||
| 79 | if (updateProfile) { | ||
| 80 | _set_profile(get_user_id_from_token(token)); | ||
| 81 | } | ||
| 82 | }} games={games} /> | ||
| 85 | <Sidebar setToken={setToken} profile={profile} setProfile={setProfile} onUploadRun={() => setUploadRunDialog(true)} /> | 83 | <Sidebar setToken={setToken} profile={profile} setProfile={setProfile} onUploadRun={() => setUploadRunDialog(true)} /> |
| 86 | <Routes> | 84 | <Routes> |
| 87 | <Route path="/" element={<Homepage />} /> | 85 | <Route path="/" element={<Homepage />} /> |
| 88 | <Route path="/profile" element={<Profile profile={profile} token={token} gameData={games} onDeleteRecord={() => setConfirmDialogOpen(true)} />} /> | 86 | <Route path="/profile" element={<Profile profile={profile} token={token} gameData={games} onDeleteRecord={() => _set_profile(get_user_id_from_token(token))} />} /> |
| 89 | <Route path="/users/*" element={<User profile={profile} token={token} gameData={games} />} /> | 87 | <Route path="/users/*" element={<User profile={profile} token={token} gameData={games} />} /> |
| 90 | <Route path="/games" element={<Games games={games} />} /> | 88 | <Route path="/games" element={<Games games={games} />} /> |
| 91 | <Route path='/games/:id' element={<Maplist />}></Route> | 89 | <Route path='/games/:id' element={<Maplist />}></Route> |
| 92 | <Route path="/maps/*" element={<Maps token={token} isModerator={isModerator} />}/> | 90 | <Route path="/maps/*" element={<Maps token={token} isModerator={isModerator} />} /> |
| 93 | <Route path="/rules" element={<Rules />} /> | 91 | <Route path="/rules" element={<Rules />} /> |
| 94 | <Route path="/about" element={<About />} /> | 92 | <Route path="/about" element={<About />} /> |
| 95 | <Route path='/rankings' element={<Rankings />}></Route> | 93 | <Route path='/rankings' element={<Rankings />}></Route> |
diff --git a/frontend/src/api/Maps.tsx b/frontend/src/api/Maps.tsx index 2209788..80f88d4 100644 --- a/frontend/src/api/Maps.tsx +++ b/frontend/src/api/Maps.tsx | |||
| @@ -75,7 +75,7 @@ export const delete_map_discussion = async (token: string, map_id: string, discu | |||
| 75 | return response.data.success; | 75 | return response.data.success; |
| 76 | }; | 76 | }; |
| 77 | 77 | ||
| 78 | export const post_record = async (token: string, run: UploadRunContent): Promise<string> => { | 78 | export const post_record = async (token: string, run: UploadRunContent): Promise<[boolean, string]> => { |
| 79 | if (run.partner_demo) { | 79 | if (run.partner_demo) { |
| 80 | const response = await axios.postForm(url(`maps/${run.map_id}/record`), { | 80 | const response = await axios.postForm(url(`maps/${run.map_id}/record`), { |
| 81 | "host_demo": run.host_demo, | 81 | "host_demo": run.host_demo, |
| @@ -85,7 +85,7 @@ export const post_record = async (token: string, run: UploadRunContent): Promise | |||
| 85 | "Authorization": token, | 85 | "Authorization": token, |
| 86 | } | 86 | } |
| 87 | }); | 87 | }); |
| 88 | return response.data.message; | 88 | return [ response.data.success, response.data.message ]; |
| 89 | } else { | 89 | } else { |
| 90 | const response = await axios.postForm(url(`maps/${run.map_id}/record`), { | 90 | const response = await axios.postForm(url(`maps/${run.map_id}/record`), { |
| 91 | "host_demo": run.host_demo, | 91 | "host_demo": run.host_demo, |
| @@ -94,7 +94,7 @@ export const post_record = async (token: string, run: UploadRunContent): Promise | |||
| 94 | "Authorization": token, | 94 | "Authorization": token, |
| 95 | } | 95 | } |
| 96 | }); | 96 | }); |
| 97 | return response.data.message; | 97 | return [ response.data.success, response.data.message ]; |
| 98 | } | 98 | } |
| 99 | } | 99 | } |
| 100 | 100 | ||
diff --git a/frontend/src/components/Leaderboards.tsx b/frontend/src/components/Leaderboards.tsx index f4d666d..f86aa7b 100644 --- a/frontend/src/components/Leaderboards.tsx +++ b/frontend/src/components/Leaderboards.tsx | |||
| @@ -40,8 +40,8 @@ const Leaderboards: React.FC<LeaderboardsProps> = ({ data }) => { | |||
| 40 | 40 | ||
| 41 | {data.map.is_coop ? ( | 41 | {data.map.is_coop ? ( |
| 42 | <div id='runner'> | 42 | <div id='runner'> |
| 43 | <span>Host</span> | 43 | <span>Blue</span> |
| 44 | <span>Partner</span> | 44 | <span>Orange</span> |
| 45 | </div> | 45 | </div> |
| 46 | ) : ( | 46 | ) : ( |
| 47 | <span>Runner</span> | 47 | <span>Runner</span> |
| @@ -87,7 +87,7 @@ const Leaderboards: React.FC<LeaderboardsProps> = ({ data }) => { | |||
| 87 | 87 | ||
| 88 | {r.kind === "multiplayer" ? ( | 88 | {r.kind === "multiplayer" ? ( |
| 89 | <span> | 89 | <span> |
| 90 | <button onClick={() => { window.alert(`Host demo ID: ${r.host_demo_id} \nParnter demo ID: ${r.partner_demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> | 90 | <button onClick={() => { window.alert(`Host Demo ID: ${r.host_demo_id} \nParnter Demo ID: ${r.partner_demo_id}`) }}><img src={ThreedotIcon} alt="demo_id" /></button> |
| 91 | <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> | 91 | <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> |
| 92 | <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> | 92 | <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> |
| 93 | </span> | 93 | </span> |
diff --git a/frontend/src/components/MessageDialog.tsx b/frontend/src/components/MessageDialog.tsx index 0a8db42..17b1258 100644 --- a/frontend/src/components/MessageDialog.tsx +++ b/frontend/src/components/MessageDialog.tsx | |||
| @@ -19,7 +19,7 @@ const MessageDialog: React.FC<MessageDialogProps> = ({ title, subtitle, onClose | |||
| 19 | <span>{subtitle}</span> | 19 | <span>{subtitle}</span> |
| 20 | </div> | 20 | </div> |
| 21 | <div className='dialog-element dialog-btns-container'> | 21 | <div className='dialog-element dialog-btns-container'> |
| 22 | <button onClick={onClose}>Ok</button> | 22 | <button onClick={onClose}>Close</button> |
| 23 | </div> | 23 | </div> |
| 24 | </div> | 24 | </div> |
| 25 | </div> | 25 | </div> |
diff --git a/frontend/src/components/UploadRunDialog.tsx b/frontend/src/components/UploadRunDialog.tsx index 8081643..a0d23e7 100644 --- a/frontend/src/components/UploadRunDialog.tsx +++ b/frontend/src/components/UploadRunDialog.tsx | |||
| @@ -13,18 +13,15 @@ import useConfirm from '../hooks/UseConfirm'; | |||
| 13 | interface UploadRunDialogProps { | 13 | interface UploadRunDialogProps { |
| 14 | token?: string; | 14 | token?: string; |
| 15 | open: boolean; | 15 | open: boolean; |
| 16 | onClose: () => void; | 16 | onClose: (updateProfile: boolean) => void; |
| 17 | games: Game[]; | 17 | games: Game[]; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose, games }) => { | 20 | const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose, games }) => { |
| 21 | 21 | ||
| 22 | const [confirmMessage, setConfirmMessage] = React.useState<string>("Are you sure you want to upload this demo?"); | ||
| 23 | |||
| 24 | const { message, MessageDialogComponent } = useMessage(); | 22 | const { message, MessageDialogComponent } = useMessage(); |
| 25 | const { confirm, ConfirmDialogComponent } = useConfirm(); | 23 | const { confirm, ConfirmDialogComponent } = useConfirm(); |
| 26 | 24 | ||
| 27 | |||
| 28 | const navigate = useNavigate(); | 25 | const navigate = useNavigate(); |
| 29 | 26 | ||
| 30 | const [uploadRunContent, setUploadRunContent] = React.useState<UploadRunContent>({ | 27 | const [uploadRunContent, setUploadRunContent] = React.useState<UploadRunContent>({ |
| @@ -125,44 +122,41 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose, | |||
| 125 | if (token) { | 122 | if (token) { |
| 126 | if (games[selectedGameID].is_coop) { | 123 | if (games[selectedGameID].is_coop) { |
| 127 | if (uploadRunContent.host_demo === null) { | 124 | if (uploadRunContent.host_demo === null) { |
| 128 | message("Error", "You must select a host demo to upload.") | 125 | await message("Error", "You must select a host demo to upload.") |
| 129 | return | 126 | return |
| 130 | } else if (uploadRunContent.partner_demo === null) { | 127 | } else if (uploadRunContent.partner_demo === null) { |
| 131 | message("Error", "You must select a partner demo to upload.") | 128 | await message("Error", "You must select a partner demo to upload.") |
| 132 | return | 129 | return |
| 133 | } | 130 | } |
| 134 | } else { | 131 | } else { |
| 135 | if (uploadRunContent.host_demo === null) { | 132 | if (uploadRunContent.host_demo === null) { |
| 136 | message("Error", "You must select a demo to upload.") | 133 | await message("Error", "You must select a demo to upload.") |
| 137 | return | 134 | return |
| 138 | } | 135 | } |
| 139 | } | 136 | } |
| 140 | const demo = SourceDemoParser.default() | 137 | const demo = SourceDemoParser.default() |
| 141 | .setOptions({ packets: true, header: true }) | 138 | .setOptions({ packets: true, header: true }) |
| 142 | .parse(await uploadRunContent.host_demo.arrayBuffer()); | 139 | .parse(await uploadRunContent.host_demo.arrayBuffer()); |
| 143 | const scoreboard = demo.findPacket<NetMessages.SvcUserMessage>((message) => { | 140 | const scoreboard = demo.findPacket<NetMessages.SvcUserMessage>((msg) => { |
| 144 | return message instanceof NetMessages.SvcUserMessage && message.userMessage instanceof ScoreboardTempUpdate; | 141 | return msg instanceof NetMessages.SvcUserMessage && msg.userMessage instanceof ScoreboardTempUpdate; |
| 145 | }) | 142 | }) |
| 146 | 143 | ||
| 147 | if (!scoreboard) { | 144 | if (!scoreboard) { |
| 148 | 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.") | 145 | 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.") |
| 149 | return | 146 | return |
| 150 | } | 147 | } |
| 151 | const { portalScore, timeScore } = scoreboard.userMessage?.as<ScoreboardTempUpdate>() ?? {}; | 148 | const { portalScore, timeScore } = scoreboard.userMessage?.as<ScoreboardTempUpdate>() ?? {}; |
| 152 | console.log(`Map Name: ${demo.mapName}. Portal Count: ${portalScore}. Ticks: ${timeScore}.`); | ||
| 153 | |||
| 154 | setConfirmMessage(`Map Name: ${demo.mapName}\nPortal Count: ${portalScore}\nTicks: ${timeScore}\n\nAre you sure you want to upload this demo?`) | ||
| 155 | 149 | ||
| 156 | const userConfirmed = await confirm("Upload demo?", confirmMessage); | 150 | 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?`); |
| 157 | 151 | ||
| 158 | if (!userConfirmed) { | 152 | if (!userConfirmed) { |
| 159 | return; | 153 | return; |
| 160 | } | 154 | } |
| 161 | 155 | ||
| 162 | const response = await API.post_record(token, uploadRunContent); | 156 | const [ success, response ] = await API.post_record(token, uploadRunContent); |
| 163 | await message("Message", response); | 157 | await message("Upload Record", response); |
| 164 | // navigate(0); | 158 | console.log("weweew") |
| 165 | onClose(); | 159 | onClose(success); |
| 166 | } | 160 | } |
| 167 | }; | 161 | }; |
| 168 | 162 | ||
| @@ -242,7 +236,7 @@ const UploadRunDialog: React.FC<UploadRunDialogProps> = ({ token, open, onClose, | |||
| 242 | </div> | 236 | </div> |
| 243 | <div className='upload-run-buttons-container'> | 237 | <div className='upload-run-buttons-container'> |
| 244 | <button onClick={_upload_run}>Submit</button> | 238 | <button onClick={_upload_run}>Submit</button> |
| 245 | <button onClick={() => onClose()}>Cancel</button> | 239 | <button onClick={() => onClose(false)}>Cancel</button> |
| 246 | </div> | 240 | </div> |
| 247 | </div> | 241 | </div> |
| 248 | </> | 242 | </> |
diff --git a/frontend/src/css/Dialog.css b/frontend/src/css/Dialog.css index f16425d..47f070b 100644 --- a/frontend/src/css/Dialog.css +++ b/frontend/src/css/Dialog.css | |||
| @@ -1,10 +1,9 @@ | |||
| 1 | .dimmer { | 1 | .dimmer { |
| 2 | position: fixed; | 2 | position: fixed; |
| 3 | width: calc(100%); | 3 | width: 100%; |
| 4 | height: 100%; | 4 | height: 100%; |
| 5 | background-color: rgba(0, 0, 0, 0.5); | 5 | background-color: rgba(0, 0, 0, 0.5); |
| 6 | z-index: 4; | 6 | z-index: 4; |
| 7 | left: 0px; | ||
| 8 | } | 7 | } |
| 9 | 8 | ||
| 10 | .dialog { | 9 | .dialog { |
diff --git a/frontend/src/css/UploadRunDialog.css b/frontend/src/css/UploadRunDialog.css index b4667da..c783d2a 100644 --- a/frontend/src/css/UploadRunDialog.css +++ b/frontend/src/css/UploadRunDialog.css | |||
| @@ -13,7 +13,7 @@ div#upload-run{ | |||
| 13 | left: calc(50% + 160px); top: 130px; | 13 | left: calc(50% + 160px); top: 130px; |
| 14 | transform: translateX(-50%); | 14 | transform: translateX(-50%); |
| 15 | background-color: #2b2e46; | 15 | background-color: #2b2e46; |
| 16 | z-index: 2; color: white; | 16 | z-index: 3; color: white; |
| 17 | font-family: BarlowSemicondensed-SemiBold; | 17 | font-family: BarlowSemicondensed-SemiBold; |
| 18 | } | 18 | } |
| 19 | 19 | ||
| @@ -36,10 +36,9 @@ div#upload-run{ | |||
| 36 | position: absolute; | 36 | position: absolute; |
| 37 | background-color: black; | 37 | background-color: black; |
| 38 | opacity: .3; | 38 | opacity: .3; |
| 39 | left: 320px; | 39 | width: 100%; |
| 40 | width: calc(100% - 320px); | ||
| 41 | height: 100%; | 40 | height: 100%; |
| 42 | z-index: 2; | 41 | z-index: 3; |
| 43 | cursor: no-drop; | 42 | cursor: no-drop; |
| 44 | } | 43 | } |
| 45 | 44 | ||
diff --git a/frontend/src/hooks/UseConfirm.tsx b/frontend/src/hooks/UseConfirm.tsx index 80a0d51..9a7853b 100644 --- a/frontend/src/hooks/UseConfirm.tsx +++ b/frontend/src/hooks/UseConfirm.tsx | |||
| @@ -3,9 +3,9 @@ import ConfirmDialog from '../components/ConfirmDialog'; | |||
| 3 | 3 | ||
| 4 | const useConfirm = () => { | 4 | const useConfirm = () => { |
| 5 | const [isOpen, setIsOpen] = useState(false); | 5 | const [isOpen, setIsOpen] = useState(false); |
| 6 | const [resolvePromise, setResolvePromise] = useState<((value: boolean) => void) | null>(null); | ||
| 7 | const [title, setTitle] = useState<string>(""); | 6 | const [title, setTitle] = useState<string>(""); |
| 8 | const [subtitle, setSubtitle] = useState<string>(""); | 7 | const [subtitle, setSubtitle] = useState<string>(""); |
| 8 | const [resolvePromise, setResolvePromise] = useState<((value: boolean) => void) | null>(null); | ||
| 9 | 9 | ||
| 10 | const confirm = ( titleN: string, subtitleN: string ) => { | 10 | const confirm = ( titleN: string, subtitleN: string ) => { |
| 11 | setIsOpen(true); | 11 | setIsOpen(true); |
diff --git a/frontend/src/hooks/UseMessage.tsx b/frontend/src/hooks/UseMessage.tsx index ebc4276..602cf65 100644 --- a/frontend/src/hooks/UseMessage.tsx +++ b/frontend/src/hooks/UseMessage.tsx | |||
| @@ -3,10 +3,10 @@ import MessageDialog from "../components/MessageDialog"; | |||
| 3 | 3 | ||
| 4 | const useMessage = () => { | 4 | const useMessage = () => { |
| 5 | const [isOpen, setIsOpen] = useState(false); | 5 | const [isOpen, setIsOpen] = useState(false); |
| 6 | const [resolvePromise, setResolvePromise] = useState<((value: boolean) => void) | null>(null); | ||
| 7 | 6 | ||
| 8 | const [title, setTitle] = useState<string>(""); | 7 | const [title, setTitle] = useState<string>(""); |
| 9 | const [subtitle, setSubtitle] = useState<string>(""); | 8 | const [subtitle, setSubtitle] = useState<string>(""); |
| 9 | const [resolvePromise, setResolvePromise] = useState<(() => void) | null>(null); | ||
| 10 | 10 | ||
| 11 | const message = (title: string, subtitle: string) => { | 11 | const message = (title: string, subtitle: string) => { |
| 12 | setIsOpen(true); | 12 | setIsOpen(true); |
| @@ -19,6 +19,10 @@ const useMessage = () => { | |||
| 19 | 19 | ||
| 20 | const handleClose = () => { | 20 | const handleClose = () => { |
| 21 | setIsOpen(false); | 21 | setIsOpen(false); |
| 22 | if (resolvePromise) { | ||
| 23 | resolvePromise(); | ||
| 24 | setResolvePromise(null); | ||
| 25 | } | ||
| 22 | }; | 26 | }; |
| 23 | 27 | ||
| 24 | const MessageDialogComponent = isOpen && ( | 28 | const MessageDialogComponent = isOpen && ( |
diff --git a/frontend/src/pages/Profile.tsx b/frontend/src/pages/Profile.tsx index 7559c77..5d1c75d 100644 --- a/frontend/src/pages/Profile.tsx +++ b/frontend/src/pages/Profile.tsx | |||
| @@ -63,7 +63,7 @@ const Profile: React.FC<ProfileProps> = ({ profile, token, gameData, onDeleteRec | |||
| 63 | }; | 63 | }; |
| 64 | 64 | ||
| 65 | const _delete_submission = async (map_id: number, record_id: number) => { | 65 | const _delete_submission = async (map_id: number, record_id: number) => { |
| 66 | const userConfirmed = await confirm("Delete record?", "This action cannot be undone"); | 66 | const userConfirmed = await confirm("Delete Record", "Are you sure you want to delete this record?"); |
| 67 | 67 | ||
| 68 | if (!userConfirmed) { | 68 | if (!userConfirmed) { |
| 69 | return; | 69 | return; |
| @@ -71,9 +71,10 @@ const Profile: React.FC<ProfileProps> = ({ profile, token, gameData, onDeleteRec | |||
| 71 | 71 | ||
| 72 | const api_success = await API.delete_map_record(token!, map_id, record_id); | 72 | const api_success = await API.delete_map_record(token!, map_id, record_id); |
| 73 | if (api_success) { | 73 | if (api_success) { |
| 74 | message("Success", "Successfully deleted record"); | 74 | await message("Delete Record", "Successfully deleted record."); |
| 75 | onDeleteRecord(); | ||
| 75 | } else { | 76 | } else { |
| 76 | message("Error", "Could not delete record"); | 77 | await message("Delete Record", "Could not delete record."); |
| 77 | } | 78 | } |
| 78 | }; | 79 | }; |
| 79 | 80 | ||