diff --git a/frontend/package-lock.json b/frontend/package-lock.json index 5178bf4..c56fb06 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -29,6 +29,7 @@ "react-dom": "^18.2.0", "react-email-validator": "^1.0.2", "react-icons": "^4.10.1", + "react-modal": "^3.16.1", "react-motion-animate": "^1.0.6", "react-redux": "^8.1.2", "react-router-dom": "^6.15.0", @@ -8628,6 +8629,11 @@ "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, + "node_modules/exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==" + }, "node_modules/exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -15367,6 +15373,29 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "node_modules/react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "node_modules/react-modal": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", + "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==", + "dependencies": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + }, + "engines": { + "node": ">=8" + }, + "peerDependencies": { + "react": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18", + "react-dom": "^0.14.0 || ^15.0.0 || ^16 || ^17 || ^18" + } + }, "node_modules/react-motion-animate": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/react-motion-animate/-/react-motion-animate-1.0.6.tgz", @@ -17674,6 +17703,14 @@ "makeerror": "1.0.12" } }, + "node_modules/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, "node_modules/watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", @@ -24665,6 +24702,11 @@ "strip-final-newline": "^2.0.0" } }, + "exenv": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/exenv/-/exenv-1.2.2.tgz", + "integrity": "sha512-Z+ktTxTwv9ILfgKCk32OX3n/doe+OcLTRtqK9pcL+JsP3J1/VW8Uvl4ZjLlKqeW4rzK4oesDOGMEMRIZqtP4Iw==" + }, "exit": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", @@ -29373,6 +29415,22 @@ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz", "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==" }, + "react-lifecycles-compat": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz", + "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA==" + }, + "react-modal": { + "version": "3.16.1", + "resolved": "https://registry.npmjs.org/react-modal/-/react-modal-3.16.1.tgz", + "integrity": "sha512-VStHgI3BVcGo7OXczvnJN7yT2TWHJPDXZWyI/a0ssFNhGZWsPmB8cF0z33ewDXq4VfYMO1vXgiv/g8Nj9NDyWg==", + "requires": { + "exenv": "^1.2.0", + "prop-types": "^15.7.2", + "react-lifecycles-compat": "^3.0.0", + "warning": "^4.0.3" + } + }, "react-motion-animate": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/react-motion-animate/-/react-motion-animate-1.0.6.tgz", @@ -31051,6 +31109,14 @@ "makeerror": "1.0.12" } }, + "warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "requires": { + "loose-envify": "^1.0.0" + } + }, "watchpack": { "version": "2.4.0", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", diff --git a/frontend/package.json b/frontend/package.json index 1baec9a..79f9fb1 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -24,6 +24,7 @@ "react-dom": "^18.2.0", "react-email-validator": "^1.0.2", "react-icons": "^4.10.1", + "react-modal": "^3.16.1", "react-motion-animate": "^1.0.6", "react-redux": "^8.1.2", "react-router-dom": "^6.15.0", diff --git a/frontend/src/components/SettingsComponents/Profile.js b/frontend/src/components/SettingsComponents/Profile.js index 16edc4a..eddba0f 100644 --- a/frontend/src/components/SettingsComponents/Profile.js +++ b/frontend/src/components/SettingsComponents/Profile.js @@ -3,10 +3,15 @@ import { Avatar } from "@mui/material"; import { useDispatch, useSelector } from "react-redux"; import { setUser } from "../../services/Actions/User/actions"; import toast from "react-toastify"; +import Alert from "../../helper/Alert.js"; export default function Profile() { const dispatch = useDispatch(); const dataredux = useSelector((state) => state.user.userInfo); + const [modalIsOpen, setIsOpen] = useState(false); + const [showModal, setShowModal] = useState(false); + const [showConfirm, setShowConfirm] = useState(false); + const [isConfirm, setIsConfirm] = useState(false); const data = JSON.parse(localStorage.getItem("info")); const [Pic, setPic] = useState(data.pic); @@ -25,15 +30,12 @@ export default function Profile() { const handleUpload = () => { if (selectedFile) { // Ask for confirmation before uploading - const isConfirmed = window.confirm( - "Are you sure you want to upload this image?" - ); - - if (!isConfirmed) return; + setShowConfirm(true); + if (!isConfirm) return; const formData = new FormData(); formData.append("photo", selectedFile); - + setIsConfirm(false); const cookie = localStorage.getItem("jwt"); fetch(`${process.env.REACT_APP_API_URL}/api/v1/users/uploadPhoto`, { method: "POST", @@ -45,7 +47,8 @@ export default function Profile() { .then((response) => response.json()) .then((data) => { // Alert if image uploaded successfully - alert("Image uploaded successfully!"); + setShowConfirm(false); + setIsOpen(true); dispatch(setUser(data.data.user)); }) .catch((error) => { @@ -53,7 +56,7 @@ export default function Profile() { console.error("Error uploading image:", error); }); } else { - alert("Please select an image to upload."); + setShowModal(true); } }; @@ -89,6 +92,25 @@ export default function Profile() { Upload Picture + setIsOpen(false)} + isVisible={modalIsOpen} + /> + setShowModal(false)} + isVisible={showModal} + /> + {setShowConfirm(false); setIsConfirm(false)}} + isVisible={showConfirm} + onConfirm={()=> {setIsConfirm(true); setShowConfirm(false); handleUpload()}} + /> ); } diff --git a/frontend/src/helper/Alert.js b/frontend/src/helper/Alert.js new file mode 100644 index 0000000..daade34 --- /dev/null +++ b/frontend/src/helper/Alert.js @@ -0,0 +1,58 @@ +import React from "react"; +import Modal from "react-modal"; +import { FaCheckCircle,FaExclamationCircle } from "react-icons/fa"; +import { IoIosCloseCircle } from "react-icons/io"; + +const customStyles = { + content: { + top: "50%", + left: "50%", + right: "auto", + bottom: "auto", + marginRight: "-50%", + transform: "translate(-50%, -50%)", + width: "30vw", + justifyContent: "center", + alignItems: "center", + display: "flex", + flexDirection: "column", + gap: "1rem", + backgroundColor: "#0147FF", + }, +}; + +const Alert = ({ text, status, onClose, isVisible,onConfirm }) => { + return ( +
+ + {status === "success" && + } + {status==="failure" && + } + {status==="confirm" && + } +
{text}
+ {(status === "success" || status ==="failure") && } + {(status === "confirm" && +
+ + +
+ )} +
+
+ ); +}; + +export default Alert;