From 56ada22fb555b6c01d85ff122d02349f56d5b418 Mon Sep 17 00:00:00 2001 From: Dang Nguyen Nguyen Date: Sun, 24 Sep 2023 12:47:50 -0700 Subject: [PATCH 1/5] successfully manage token --- src/components/Home/Home.jsx | 12 ++++++++--- src/components/Map/Map.jsx | 41 +++++++++++++++++++++++------------- src/context/DataContext.js | 1 + 3 files changed, 36 insertions(+), 18 deletions(-) diff --git a/src/components/Home/Home.jsx b/src/components/Home/Home.jsx index e00e8f5..50573a7 100644 --- a/src/components/Home/Home.jsx +++ b/src/components/Home/Home.jsx @@ -53,6 +53,7 @@ export default function Home() { const [data, setData] = useState([]); const [leaderboard, setLeaderboard] = useState([]); const { user, logOut } = UserAuth(); + const [token, setToken] = useState(""); const btnRef = useRef(); const { isOpen, onOpen, onClose } = useDisclosure(); @@ -157,12 +158,10 @@ export default function Home() { setLeaderboard( leaderboardData.map((item) => ({ ...item, id: item.id })) ); - // Check if the current user's email exists in the leaderboard const userEmailExists = leaderboardData.some( (entry) => entry.email === user?.email ); - // If it does not exist, add the user to the leaderboard if (!userEmailExists) { await axios.post( @@ -172,7 +171,6 @@ export default function Home() { points: 5, // You can modify this as per your requirements } ); - // Fetch the leaderboard again after insertion const { data: updatedLeaderboardData } = await axios.get( `${process.env.REACT_APP_AWS_BACKEND_URL}/leaderboard/` @@ -191,6 +189,13 @@ export default function Home() { getLeaderboard(); }, [user]); + // set token to auth + useEffect(() => { + if (user) { + setToken(user.accessToken); + } + }, [user]); + window.onresize = () => { setScreenWidth(window.screen.width); }; @@ -199,6 +204,7 @@ export default function Home() { { const newItem = { image: newAddedItem.image, diff --git a/src/context/DataContext.js b/src/context/DataContext.js index 0d090b2..6918ee0 100644 --- a/src/context/DataContext.js +++ b/src/context/DataContext.js @@ -2,6 +2,7 @@ import { createContext } from "react"; const DataContext = createContext({ data: [], + token: "", isLoginModalOpen: false, onLoginModalOpen: () => {}, onLoginModalClose: () => {}, From c5658fc234790fd497973f9abb813956d78c713a Mon Sep 17 00:00:00 2001 From: Dang Nguyen Nguyen Date: Sun, 24 Sep 2023 18:25:50 -0700 Subject: [PATCH 2/5] did auth, email, fixed leaderboard --- .../FeedbackModal/FeedbackModal.jsx | 39 +++++++++++---- src/components/Home/Home.jsx | 19 ++++++-- src/components/Home/Leaderboard.jsx | 32 ++++++------- .../ImageContainer/ImageContainer.jsx | 2 +- src/components/InfoModal/InfoModal.jsx | 9 +++- src/components/Map/Map.jsx | 16 +++++-- src/components/Map/MapIcons.js | 48 +++++++++---------- 7 files changed, 105 insertions(+), 60 deletions(-) diff --git a/src/components/FeedbackModal/FeedbackModal.jsx b/src/components/FeedbackModal/FeedbackModal.jsx index 0e64dc7..db51cd5 100644 --- a/src/components/FeedbackModal/FeedbackModal.jsx +++ b/src/components/FeedbackModal/FeedbackModal.jsx @@ -23,15 +23,26 @@ export default function FeedbackModal({ email, }) { const [feedbackHelped, setFeedbackHelped] = useState(null); - const { setLoading } = useContext(DataContext); + const { setLoading, token } = useContext(DataContext); async function handleFeedback() { + if (!token) { + return; + } setLoading(false); axios - .put(`${process.env.REACT_APP_AWS_BACKEND_URL}/items/${props.id}`, { - ...props, - isresolved: true, - ishelped: feedbackHelped, - }) + .put( + `${process.env.REACT_APP_AWS_BACKEND_URL}/items/${props.id}`, + { + ...props, + isresolved: true, + ishelped: feedbackHelped, + }, + { + headers: { + Authorization: `Bearer ${token}`, // verify auth + }, + } + ) .then(() => console.log("Success")) .catch((err) => console.log(err)); @@ -51,10 +62,18 @@ export default function FeedbackModal({ // Update the leaderboard const pointsToAdd = props.islost ? 2 : 5; - axios.put(`${process.env.REACT_APP_AWS_BACKEND_URL}/leaderboard`, { - email: email, - pointsToAdd: pointsToAdd, - }); + axios.put( + `${process.env.REACT_APP_AWS_BACKEND_URL}/leaderboard`, + { + email: email, + pointsToAdd: pointsToAdd, + }, + { + headers: { + Authorization: `Bearer ${token}`, // verify auth + }, + } + ); setLeaderboard((prev) => prev.map((u) => diff --git a/src/components/Home/Home.jsx b/src/components/Home/Home.jsx index 50573a7..e36de77 100644 --- a/src/components/Home/Home.jsx +++ b/src/components/Home/Home.jsx @@ -88,6 +88,8 @@ export default function Home() { ); } + console.log(token); + const [loading, setLoading] = useState(false); const [newAddedItem, setNewAddedItem] = useState({ @@ -169,6 +171,11 @@ export default function Home() { { email: user.email, points: 5, // You can modify this as per your requirements + }, + { + headers: { + Authorization: `Bearer ${token}`, // verify auth + }, } ); // Fetch the leaderboard again after insertion @@ -309,7 +316,7 @@ export default function Home() { gap={{ base: 1, md: 1.5 }} justifyContent={"center"} background={"#74a2fa"} - padding={{ base: "6px", md: 1.5 }} + padding={{ base: "5px", md: 1.5 }} borderRadius={"xl"} _hover={{ background: "#365fad", @@ -323,10 +330,14 @@ export default function Home() { - + {user ? leaderboard.find((u) => u.email === user.email)?.points : 0} diff --git a/src/components/Home/Leaderboard.jsx b/src/components/Home/Leaderboard.jsx index 36994d0..15f307f 100644 --- a/src/components/Home/Leaderboard.jsx +++ b/src/components/Home/Leaderboard.jsx @@ -69,7 +69,7 @@ export default function Leaderboard({ 1 - + {leaderboard[0]?.email} - - + + {leaderboard[0]?.points} gold medal 2 - - {leaderboard[0]?.email} + + {leaderboard[1]?.email} - - {leaderboard[0]?.points} 🍪 + + {leaderboard[1]?.points} 🍪 3 - - {leaderboard[0]?.email} + + {leaderboard[2]?.email} - - {leaderboard[0]?.points} 🍪 + + {leaderboard[2]?.points} 🍪 diff --git a/src/components/ImageContainer/ImageContainer.jsx b/src/components/ImageContainer/ImageContainer.jsx index 39b03fe..e65226a 100644 --- a/src/components/ImageContainer/ImageContainer.jsx +++ b/src/components/ImageContainer/ImageContainer.jsx @@ -16,7 +16,7 @@ export default function ImageContainer({ image, isresolved }) { alignItems={"center"} marginTop={30} flexDir={"column"} - w={450} + w={{ base: "100vw", md: 450 }} > RETURNED diff --git a/src/components/InfoModal/InfoModal.jsx b/src/components/InfoModal/InfoModal.jsx index 762e880..e77d1ee 100644 --- a/src/components/InfoModal/InfoModal.jsx +++ b/src/components/InfoModal/InfoModal.jsx @@ -27,6 +27,7 @@ export default function InfoModal({ setLeaderboard, }) { const [showEmail, setShowEmail] = useState(false); + const [isShared, setIsShared] = useState(false); const { onLoginModalOpen } = useContext(DataContext); const { user } = UserAuth(); const navigate = useNavigate(); @@ -170,8 +171,14 @@ export default function InfoModal({ size={"lg"} variant={"outline"} gap={2} + onClick={() => { + setIsShared(true); + navigator.clipboard.writeText( + `https://zotnfound.com/${props.id}` + ); + }} > - Share + {!isShared ? "Share" : "Copied"} diff --git a/src/components/Map/Map.jsx b/src/components/Map/Map.jsx index 00eaf5d..13af6c2 100644 --- a/src/components/Map/Map.jsx +++ b/src/components/Map/Map.jsx @@ -197,10 +197,18 @@ export default function Map({ // Update the leaderboard const pointsToAdd = newAddedItem.islost ? 1 : 3; - axios.put(`${process.env.REACT_APP_AWS_BACKEND_URL}/leaderboard`, { - email: user.email, - pointsToAdd: pointsToAdd, - }); + axios.put( + `${process.env.REACT_APP_AWS_BACKEND_URL}/leaderboard`, + { + email: user.email, + pointsToAdd: pointsToAdd, + }, + { + headers: { + Authorization: `Bearer ${token}`, // verify auth + }, + } + ); setLeaderboard((prev) => prev.map((u) => diff --git a/src/components/Map/MapIcons.js b/src/components/Map/MapIcons.js index 582980a..5a35815 100644 --- a/src/components/Map/MapIcons.js +++ b/src/components/Map/MapIcons.js @@ -20,74 +20,74 @@ import fly_img from "../../assets/images/fly_img.png"; const resolvedIcon = L.icon({ iconUrl: resolved, - iconSize: [50, 50], - iconAnchor: [25, 40], + iconSize: [40, 40], + iconAnchor: [20, 30], }); const headphoneLost = L.icon({ iconUrl: headphone_lost, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const headphoneFound = L.icon({ iconUrl: headphone_found, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const phoneLost = L.icon({ iconUrl: phone_lost, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const phoneFound = L.icon({ iconUrl: phone_found, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const keyLost = L.icon({ iconUrl: key_lost, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const keyFound = L.icon({ iconUrl: key_found, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const walletLost = L.icon({ iconUrl: wallet_lost, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const walletFound = L.icon({ iconUrl: wallet_found, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const othersLost = L.icon({ iconUrl: others_lost, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); const othersFound = L.icon({ iconUrl: others_found, - iconSize: [60, 60], - iconAnchor: [30, 50], + iconSize: [50, 50], + iconAnchor: [25, 40], }); export const othersDrag = L.icon({ iconUrl: others_black, - iconSize: [50, 50], - iconAnchor: [25, 30], + iconSize: [40, 40], + iconAnchor: [25, 25], }); export const flyImg = L.icon({ From 9ea09a83fc79f20582a8efff8bcbdb4399d87790 Mon Sep 17 00:00:00 2001 From: Dang Nguyen Nguyen Date: Sun, 24 Sep 2023 18:56:22 -0700 Subject: [PATCH 3/5] added Returned filter --- src/components/Filter/Filter.jsx | 31 +++++++++++++++++++++++- src/components/Home/Home.jsx | 4 ++- src/components/InfoModal/InfoModal.jsx | 10 +++++--- src/components/Map/Map.jsx | 3 ++- src/components/ResultsBar/ResultsBar.jsx | 4 +-- src/components/Type/TypeCard.jsx | 11 ++++++--- 6 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/components/Filter/Filter.jsx b/src/components/Filter/Filter.jsx index 9001308..dc22fa0 100644 --- a/src/components/Filter/Filter.jsx +++ b/src/components/Filter/Filter.jsx @@ -18,9 +18,11 @@ import { Button, } from "@chakra-ui/react"; import "./Filter.css"; +import { UserAuth } from "../../context/AuthContext"; export default function Filter({ findFilter, setFindFilter, onClose, isOpen }) { const [value, setValue] = useState("everything"); + const { user } = UserAuth(); useEffect(() => { /* eslint-disable react-hooks/exhaustive-deps */ @@ -70,12 +72,29 @@ export default function Filter({ findFilter, setFindFilter, onClose, isOpen }) { Found + + { + setFindFilter((prev) => ({ + ...prev, + isShowReturned: !prev.isShowReturned, + })); + }} + defaultChecked={findFilter.isShowReturned} + /> + + Returned + + { setFindFilter((prev) => ({ ...prev, @@ -83,7 +102,12 @@ export default function Filter({ findFilter, setFindFilter, onClose, isOpen }) { })); }} /> - + Your Posts @@ -124,6 +148,9 @@ export default function Filter({ findFilter, setFindFilter, onClose, isOpen }) { + + Found/Lost Date: + { setFindFilter((prev) => ({ @@ -149,6 +176,8 @@ export default function Filter({ findFilter, setFindFilter, onClose, isOpen }) { isFound: true, islost: true, uploadDate: "", + isYourPosts: false, + isShowReturned: true, }); onClose(); }} diff --git a/src/components/Home/Home.jsx b/src/components/Home/Home.jsx index e36de77..65f571e 100644 --- a/src/components/Home/Home.jsx +++ b/src/components/Home/Home.jsx @@ -75,6 +75,7 @@ export default function Home() { islost: true, uploadDate: "", isYourPosts: false, + isShowReturned: true, }); function isFilterOff() { @@ -84,7 +85,8 @@ export default function Home() { findFilter.islost === true && findFilter.uploadDate === "" && search === "" && - !findFilter.isYourPosts + !findFilter.isYourPosts && + findFilter.isShowReturned === true ); } diff --git a/src/components/InfoModal/InfoModal.jsx b/src/components/InfoModal/InfoModal.jsx index e77d1ee..fa9a0f2 100644 --- a/src/components/InfoModal/InfoModal.jsx +++ b/src/components/InfoModal/InfoModal.jsx @@ -57,7 +57,11 @@ export default function InfoModal({ > - + {props.islost ? ( - Lost on {props.itemDate} + Lost on {props.itemdate} ) : ( - Found on {props.itemDate} + Found on {props.itemdate} )} { diff --git a/src/components/ResultsBar/ResultsBar.jsx b/src/components/ResultsBar/ResultsBar.jsx index b2eee54..6507e22 100644 --- a/src/components/ResultsBar/ResultsBar.jsx +++ b/src/components/ResultsBar/ResultsBar.jsx @@ -24,10 +24,10 @@ export default function ResultsBar({ findFilter.isFound === !item.islost) && (findFilter.type === "everything" || findFilter.type === item.type) && (findFilter.uploadDate === "" || - !item.itemdate || (item.itemdate && item.itemdate.includes(findFilter.uploadDate))) && (!findFilter.isYourPosts || - (findFilter.isYourPosts && item.email === user.email)) + (findFilter.isYourPosts && item.email === user.email)) && + (findFilter.isShowReturned || !item.isresolved) ); }) .map((item) => { diff --git a/src/components/Type/TypeCard.jsx b/src/components/Type/TypeCard.jsx index 977a017..ec08fd6 100644 --- a/src/components/Type/TypeCard.jsx +++ b/src/components/Type/TypeCard.jsx @@ -19,15 +19,20 @@ export default function TypeCard({ backgroundColor={newAddedItem.type === type ? "#787092" : "white"} variant="outline" border="5px rgb(166, 152, 216) solid" - w={{ md: "7vw", base: "13vh" }} - h={{ md: "7vw", base: "13vh" }} + minW={{ md: "7vw", base: "13vh" }} + minH={{ md: "7vw", base: "13vh" }} borderRadius="20px" alignItems={"center"} justifyContent={"center"} flexDir={"column"} onClick={handleOnClick} > - + {type.toUpperCase()} Date: Sun, 24 Sep 2023 19:08:28 -0700 Subject: [PATCH 4/5] delete admin --- src/components/InfoModal/InfoModal.jsx | 47 ++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 7 deletions(-) diff --git a/src/components/InfoModal/InfoModal.jsx b/src/components/InfoModal/InfoModal.jsx index fa9a0f2..57da1bb 100644 --- a/src/components/InfoModal/InfoModal.jsx +++ b/src/components/InfoModal/InfoModal.jsx @@ -18,6 +18,7 @@ import DataContext from "../../context/DataContext"; import ImageContainer from "../ImageContainer/ImageContainer"; import FeedbackModal from "../FeedbackModal/FeedbackModal"; import { LinkIcon, CheckIcon, EmailIcon } from "@chakra-ui/icons"; +import axios from "axios"; export default function InfoModal({ setData, @@ -28,22 +29,39 @@ export default function InfoModal({ }) { const [showEmail, setShowEmail] = useState(false); const [isShared, setIsShared] = useState(false); - const { onLoginModalOpen } = useContext(DataContext); + const { onLoginModalOpen, token, setLoading } = useContext(DataContext); const { user } = UserAuth(); const navigate = useNavigate(); const feedbackModalDisclosure = useDisclosure(); const currentEmail = user?.email; - // function viewEmail() { - // if (user) { - // setShowEmail(true); - // } - // } - async function handleResolve() { feedbackModalDisclosure.onOpen(); } + async function handleDelete() { + onClose(); + setLoading(false); + if (!currentEmail) { + return; + } + axios + .delete(`${process.env.REACT_APP_AWS_BACKEND_URL}/items/${props.id}`, { + headers: { + Authorization: `Bearer ${token}`, // verify auth + }, + }) + .then(() => console.log("Success")) + .catch((err) => console.log(err)); + setData((prevItems) => { + if (prevItems && prevItems.length > 0) { + return prevItems.filter((item) => item.id !== props.id); + } + return prevItems; + }); + setLoading(true); + } + const formattedDate = formatDate(new Date(props.date)); return ( <> @@ -170,6 +188,21 @@ export default function InfoModal({ Resolve )} + + {[ + "dangnn1@uci.edu", + "stevenz9@uci.edu", + "katyh1@uci.edu", + ].includes(currentEmail) && ( + + )}