diff --git a/package-lock.json b/package-lock.json index 4889917..5415f0f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -23,6 +23,7 @@ "react-router-dom": "6.3.0", "react-scripts": "5.0.1", "react-spinners": "0.12.0", + "react-toastify": "^9.0.5", "recharts": "2.1.10", "sweetalert2": "11.4.17", "typescript": "4.7.3", @@ -5942,6 +5943,14 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==", + "engines": { + "node": ">=6" + } + }, "node_modules/co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -13896,6 +13905,18 @@ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0" } }, + "node_modules/react-toastify": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.5.tgz", + "integrity": "sha512-dszPCeQINY+Nm6HmsiAXT/7wsazPqv0S/RuhIYLAW+fTKcd3T1iRjZG0XqrN9nvAzqaE5J6uxMaiBrOevxjY8g==", + "dependencies": { + "clsx": "^1.1.1" + }, + "peerDependencies": { + "react": ">=16", + "react-dom": ">=16" + } + }, "node_modules/react-transition-group": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", @@ -21062,6 +21083,11 @@ "wrap-ansi": "^7.0.0" } }, + "clsx": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz", + "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==" + }, "co": { "version": "4.6.0", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", @@ -26717,6 +26743,14 @@ "@emotion/react": "^11.4.1" } }, + "react-toastify": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-9.0.5.tgz", + "integrity": "sha512-dszPCeQINY+Nm6HmsiAXT/7wsazPqv0S/RuhIYLAW+fTKcd3T1iRjZG0XqrN9nvAzqaE5J6uxMaiBrOevxjY8g==", + "requires": { + "clsx": "^1.1.1" + } + }, "react-transition-group": { "version": "2.9.0", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-2.9.0.tgz", diff --git a/package.json b/package.json index 59ab7cc..43d3718 100644 --- a/package.json +++ b/package.json @@ -18,6 +18,7 @@ "react-router-dom": "6.3.0", "react-scripts": "5.0.1", "react-spinners": "0.12.0", + "react-toastify": "^9.0.5", "recharts": "2.1.10", "sweetalert2": "11.4.17", "typescript": "4.7.3", diff --git a/src/App.tsx b/src/App.tsx index 3bfc6b7..97d54fb 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -24,6 +24,8 @@ import LeaderboardRanksPage from "./pages/LeaderboardRanksPage"; // import { UnauthorizedPage } from "./pages/UnauthorizedPage"; import { ProtectedRoute } from "./ProtectedRoute"; import { AppMenu } from "./AppMenu"; +import { ToastContainer } from 'react-toastify'; + import 'react-toastify/dist/ReactToastify.css'; export const App = () => { // if (isDoingInitialLoading) { @@ -36,6 +38,7 @@ export const App = () => { return ( + - {qty && x{qty}} + {qty &&
{qty}
} ); }; diff --git a/src/pages/FloorsEditorPage.tsx b/src/pages/FloorsEditorPage.tsx index 9488488..0104883 100644 --- a/src/pages/FloorsEditorPage.tsx +++ b/src/pages/FloorsEditorPage.tsx @@ -136,6 +136,7 @@ const FloorsEditor = ({ enemies, towerGame, allEmoji, setShouldReload }: IFloorE const handleCloseEditFloorModalAction = (reload: boolean) => { setShowAddEnemyModal(false); setShouldReload(reload); + setEditingFloor(null); } return ( diff --git a/src/pages/GameEditorPage.tsx b/src/pages/GameEditorPage.tsx index 165709a..9a5cd22 100644 --- a/src/pages/GameEditorPage.tsx +++ b/src/pages/GameEditorPage.tsx @@ -4,6 +4,7 @@ import { useParams, useNavigate } from "react-router-dom"; import { SyncLoader } from "react-spinners"; import * as Yup from "yup"; import { AiOutlineCheck, AiOutlineClose, AiOutlineCopy } from "react-icons/ai"; +import { toast } from "react-toastify"; import { getAchievements } from "../api/achievements"; import { getGameType, upsertGameType } from "../api/gamedev"; @@ -66,7 +67,13 @@ const GameEditorPage = function GameEditorPage({ editMode }: IProps) { try { await upsertGameType(upserGameTypeParams); navigate("/games"); + toast('Game successfully saved.',{ + type: 'success', + }); } catch (error: any) { + toast(`Error saving game : ${error?.message}`, { + type: "error", + }); console.log({ error }); setIsLoading(false); setErrorMessage(error.message); @@ -118,6 +125,9 @@ const GameEditorPage = function GameEditorPage({ editMode }: IProps) { return gameType; } catch (error: any) { console.log({ error }); + toast(`Error : ${error?.message}`, { + type: "error", + }); setIsLoading(false); setErrorMessage(error.message); } diff --git a/src/ui/AddEnemyToFloorModal/AddEnemyToFloorModal.tsx b/src/ui/AddEnemyToFloorModal/AddEnemyToFloorModal.tsx index 0cec3b6..ec31041 100644 --- a/src/ui/AddEnemyToFloorModal/AddEnemyToFloorModal.tsx +++ b/src/ui/AddEnemyToFloorModal/AddEnemyToFloorModal.tsx @@ -1,6 +1,7 @@ import { groupBy } from "lodash"; import { useEffect, useState } from "react"; import { AiOutlineDelete } from "react-icons/ai"; +import { toast } from "react-toastify"; import { updateFloor } from "../../api/admin"; import { emojiToImageTag } from "../../helpers/emojiHelper"; import Button from "../Button"; @@ -24,17 +25,26 @@ const AddEnemyToFloorModal = ({ const [floorEnemies, setFloorEnemies] = useState([]); const handleOnSaveButtonClick = async () => { - const floorId = floor?.id; - const enemyIds = floorEnemies.map((enemy) => enemy.id) as number[]; - - if (!floorId || !enemyIds) { - return; + try{ + const floorId = floor?.id; + const enemyIds = floorEnemies.map((enemy) => enemy.id) as number[]; + + if (!floorId || !enemyIds) { + return; + } + await updateFloor(floorId, { + enemyIds, + }); + onClose(true); + setFloorEnemies([]); + toast('Floor edited successfuly.', { + type: 'success', + }); + } catch(err: any) { + toast(`Error adding enemies to floor. ${err?.message} `, { + type: 'error', + }) } - await updateFloor(floorId, { - enemyIds, - }); - onClose(true); - setFloorEnemies([]); }; const handleOnAddEnemyClick = @@ -62,7 +72,6 @@ const AddEnemyToFloorModal = ({ (floorEnemy) => floorEnemy._enemy ); setFloorEnemies(floorEnemies); - } }, [floor?._floorEnemies]); @@ -75,8 +84,8 @@ const AddEnemyToFloorModal = ({ Edit Enemies on Floor {floor?.number} -
-
+
+

All enemies

@@ -98,7 +107,7 @@ const AddEnemyToFloorModal = ({ })}
-
+

Floor Enemies

@@ -118,7 +127,7 @@ const AddEnemyToFloorModal = ({ ))}
- setFloorEnemies([])}> + {floorEnemies && floorEnemies.length > 0 && setFloorEnemies([])}>}
diff --git a/src/ui/AddOrEditAchievementModal/AddOrEditAchievementModal.tsx b/src/ui/AddOrEditAchievementModal/AddOrEditAchievementModal.tsx index 73de78d..c5427b3 100644 --- a/src/ui/AddOrEditAchievementModal/AddOrEditAchievementModal.tsx +++ b/src/ui/AddOrEditAchievementModal/AddOrEditAchievementModal.tsx @@ -2,6 +2,7 @@ import { useFormik } from "formik"; import { useEffect } from "react"; import * as Yup from "yup"; import { useParams } from "react-router-dom"; +import { toast } from "react-toastify"; import { upsertAchievement } from "../../api/achievements"; import Button from "../Button"; @@ -30,16 +31,25 @@ const AddOrEditAchievementModal = ({ const { gameTypeId } = useParams<{ gameTypeId: string }>(); const onSubmit = async (values: IAchievementForm) => { - await upsertAchievement({ - ...(selectedAchievement?.id && { id: selectedAchievement?.id }), - _gameTypeId: selectedAchievement?._gameTypeId || parseInt(gameTypeId || ""), - ...(selectedAchievement?.createdAt && { createdAt: selectedAchievement?.createdAt }), - description: values.description, - targetValue: values.targetValue, - isEnabled: values.isEnabled, - updatedAt: new Date().toString(), - }); - onClose(); + try{ + await upsertAchievement({ + ...(selectedAchievement?.id && { id: selectedAchievement?.id }), + _gameTypeId: selectedAchievement?._gameTypeId || parseInt(gameTypeId || ""), + ...(selectedAchievement?.createdAt && { createdAt: selectedAchievement?.createdAt }), + description: values.description, + targetValue: values.targetValue, + isEnabled: values.isEnabled, + updatedAt: new Date().toString(), + }); + onClose(); + toast('Achievement successfully saved.',{ + type: 'success', + }); + } catch (err: any) { + toast(`Error : ${err.message}`, { + type: "error", + }); + } } const validationSchema = Yup.object({ diff --git a/src/ui/AddOrEditLeaderboardModal/AddOrEditLeaderboardModal.tsx b/src/ui/AddOrEditLeaderboardModal/AddOrEditLeaderboardModal.tsx index e9c7e6b..0268adb 100644 --- a/src/ui/AddOrEditLeaderboardModal/AddOrEditLeaderboardModal.tsx +++ b/src/ui/AddOrEditLeaderboardModal/AddOrEditLeaderboardModal.tsx @@ -12,6 +12,7 @@ import { resetStrategies, scoreStrategies, } from "../../utils/leaderboardStrategies"; +import { toast } from "react-toastify"; interface IProps { show: boolean; @@ -34,15 +35,25 @@ const AddOrEditLeaderboardModal = ({ const { gameTypeId } = useParams<{ gameTypeId: string }>(); const onSubmit = async (values: ILeaderboardForm) => { - await upsertLeaderboard({ - ...(selectedLeaderboard?.id && { id: selectedLeaderboard?.id }), - _gameTypeId: - selectedLeaderboard?._gameTypeId || parseInt(gameTypeId || ""), - name: values.name, - scoreStrategy: values.scoreStrategy.toLowerCase(), - resetStrategy: values.resetStrategy.toLowerCase(), - }); - onClose(); + try{ + await upsertLeaderboard({ + ...(selectedLeaderboard?.id && { id: selectedLeaderboard?.id }), + _gameTypeId: + selectedLeaderboard?._gameTypeId || parseInt(gameTypeId || ""), + name: values.name, + scoreStrategy: values.scoreStrategy.toLowerCase(), + resetStrategy: values.resetStrategy.toLowerCase(), + }); + onClose(); + toast('Leaderboard successfully saved.',{ + type: 'success', + }); + + } catch (err: any) { + toast(`Error : ${err?.message}`, { + type: "error", + }); + } }; const validationSchema = Yup.object({