From e14d476ad86610b015439c937b51a8fdd6be186b Mon Sep 17 00:00:00 2001 From: Tracy Zhang <91210454+Ceiceiceii@users.noreply.github.com> Date: Thu, 26 Oct 2023 18:37:21 -0400 Subject: [PATCH 1/4] updated login --- front-end/GoodOldMap/src/components/common/Logo.jsx | 9 +++++++-- front-end/GoodOldMap/src/components/common/leftBtn.jsx | 8 +++++++- front-end/GoodOldMap/src/pages/Authenticate/Login.jsx | 7 ++++++- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/front-end/GoodOldMap/src/components/common/Logo.jsx b/front-end/GoodOldMap/src/components/common/Logo.jsx index 759a9a4..793faa0 100644 --- a/front-end/GoodOldMap/src/components/common/Logo.jsx +++ b/front-end/GoodOldMap/src/components/common/Logo.jsx @@ -1,7 +1,12 @@ +import { useNavigate } from "react-router-dom" + const Logo = () => { const handleClick = (evt) => { - evt.stopPropagation(); - window.location.href = "/"; + const navigte = useNavigate(); + const handleClick = (evt) => { + evt.stopPropagation() + navigte("/") + } } return ( <> diff --git a/front-end/GoodOldMap/src/components/common/leftBtn.jsx b/front-end/GoodOldMap/src/components/common/leftBtn.jsx index 121e42e..bfc8e37 100644 --- a/front-end/GoodOldMap/src/components/common/leftBtn.jsx +++ b/front-end/GoodOldMap/src/components/common/leftBtn.jsx @@ -1,7 +1,13 @@ +import { useLocation, useNavigate } from "react-router-dom"; + + const LeftBtn = () => { + const location = useLocation(); + const navigate = useNavigate(); + // naviagte to previous page via state={from: pathName} property passed to the Link const handleClick = (evt) => { evt.stopPropagation(); - window.history.back(); + navigate(location?.state?.from); } return ( <> diff --git a/front-end/GoodOldMap/src/pages/Authenticate/Login.jsx b/front-end/GoodOldMap/src/pages/Authenticate/Login.jsx index 9ae3ed7..b8dc1fc 100644 --- a/front-end/GoodOldMap/src/pages/Authenticate/Login.jsx +++ b/front-end/GoodOldMap/src/pages/Authenticate/Login.jsx @@ -3,10 +3,12 @@ import AuthHeader from '../../components/form/authHeader' import PageLink from '../../components/common/pageLink' import { FormInputs } from '../../components/form/formInput' import FormBtn from '../../components/form/formBtn' +import { useNavigate } from 'react-router-dom' const Login = () => { const [message, setMessage] = useState("") const fields = ["username", "password"] + const navigate = useNavigate(); // click to login const handleClick = (evt) => { evt.preventDefault(); @@ -18,7 +20,10 @@ const Login = () => { evt.preventDefault() // pop up alert: confirm guest visit const continueGuest = window.confirm('Guest visit will not save your data, continue?'); - if (continueGuest) window.location.href = "/"; + if (continueGuest) { + navigate("/"); // Adjust this path as necessary + } + } return( From 6fe47c0c9493a9684ce9b7221654e795782d3f8b Mon Sep 17 00:00:00 2001 From: Tracy Zhang <91210454+Ceiceiceii@users.noreply.github.com> Date: Mon, 30 Oct 2023 19:36:44 -0400 Subject: [PATCH 2/4] FavList RemoveFaveList sorting redirectTODetail --- front-end/GoodOldMap/index.html | 8 +- front-end/GoodOldMap/package-lock.json | 49 +++++++ front-end/GoodOldMap/package.json | 2 + front-end/GoodOldMap/src/App.jsx | 6 +- .../src/components/popup/popupContent.jsx | 29 ++++ front-end/GoodOldMap/src/index.css | 1 - .../GoodOldMap/src/pages/Account/Account.jsx | 32 ++++- .../src/pages/AccountEdit/AccountEdit.jsx | 125 +++++++++++++++++- .../src/pages/FavoriteList/FavoriteList.jsx | 76 +++++++++++ .../GoodOldMap/src/pages/MainMap/MainMap.jsx | 14 +- 10 files changed, 333 insertions(+), 9 deletions(-) create mode 100644 front-end/GoodOldMap/src/components/popup/popupContent.jsx create mode 100644 front-end/GoodOldMap/src/pages/FavoriteList/FavoriteList.jsx diff --git a/front-end/GoodOldMap/index.html b/front-end/GoodOldMap/index.html index 4eecffc..2a00b50 100644 --- a/front-end/GoodOldMap/index.html +++ b/front-end/GoodOldMap/index.html @@ -2,10 +2,16 @@ - + + + GoodOldMap diff --git a/front-end/GoodOldMap/package-lock.json b/front-end/GoodOldMap/package-lock.json index b6ae67c..95cb972 100644 --- a/front-end/GoodOldMap/package-lock.json +++ b/front-end/GoodOldMap/package-lock.json @@ -8,8 +8,10 @@ "name": "goodoldmap", "version": "0.0.0", "dependencies": { + "leaflet": "^1.9.4", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-leaflet": "^4.2.1", "react-router-dom": "^6.17.0" }, "devDependencies": { @@ -926,6 +928,16 @@ "node": ">= 8" } }, + "node_modules/@react-leaflet/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/@remix-run/router": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz", @@ -2960,6 +2972,11 @@ "json-buffer": "3.0.1" } }, + "node_modules/leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" + }, "node_modules/levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -3606,6 +3623,19 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "node_modules/react-leaflet": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", + "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==", + "dependencies": { + "@react-leaflet/core": "^2.1.0" + }, + "peerDependencies": { + "leaflet": "^1.9.0", + "react": "^18.0.0", + "react-dom": "^18.0.0" + } + }, "node_modules/react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", @@ -5045,6 +5075,12 @@ "fastq": "^1.6.0" } }, + "@react-leaflet/core": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@react-leaflet/core/-/core-2.1.0.tgz", + "integrity": "sha512-Qk7Pfu8BSarKGqILj4x7bCSZ1pjuAPZ+qmRwH5S7mDS91VSbVVsJSrW4qA+GPrro8t69gFYVMWb1Zc4yFmPiVg==", + "requires": {} + }, "@remix-run/router": { "version": "1.10.0", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.10.0.tgz", @@ -6533,6 +6569,11 @@ "json-buffer": "3.0.1" } }, + "leaflet": { + "version": "1.9.4", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.4.tgz", + "integrity": "sha512-nxS1ynzJOmOlHp+iL3FyWqK89GtNL8U8rvlMOsQdTTssxZwCXh8N2NB3GDQOL+YR3XnWyZAxwQixURb+FA74PA==" + }, "levn": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz", @@ -6967,6 +7008,14 @@ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", "dev": true }, + "react-leaflet": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/react-leaflet/-/react-leaflet-4.2.1.tgz", + "integrity": "sha512-p9chkvhcKrWn/H/1FFeVSqLdReGwn2qmiobOQGO3BifX+/vV/39qhY8dGqbdcPh1e6jxh/QHriLXr7a4eLFK4Q==", + "requires": { + "@react-leaflet/core": "^2.1.0" + } + }, "react-refresh": { "version": "0.14.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.0.tgz", diff --git a/front-end/GoodOldMap/package.json b/front-end/GoodOldMap/package.json index 1efe2f7..12d2d60 100644 --- a/front-end/GoodOldMap/package.json +++ b/front-end/GoodOldMap/package.json @@ -10,8 +10,10 @@ "preview": "vite preview" }, "dependencies": { + "leaflet": "^1.9.4", "react": "^18.2.0", "react-dom": "^18.2.0", + "react-leaflet": "^4.2.1", "react-router-dom": "^6.17.0" }, "devDependencies": { diff --git a/front-end/GoodOldMap/src/App.jsx b/front-end/GoodOldMap/src/App.jsx index 550a01a..65edd37 100644 --- a/front-end/GoodOldMap/src/App.jsx +++ b/front-end/GoodOldMap/src/App.jsx @@ -15,7 +15,10 @@ const App = () => { <> - } /> + + }> + } /> + }> } /> } /> @@ -27,6 +30,7 @@ const App = () => { }/> } /> + diff --git a/front-end/GoodOldMap/src/components/popup/popupContent.jsx b/front-end/GoodOldMap/src/components/popup/popupContent.jsx new file mode 100644 index 0000000..a71e2be --- /dev/null +++ b/front-end/GoodOldMap/src/components/popup/popupContent.jsx @@ -0,0 +1,29 @@ +import { FormInputsPopup } from "../form/formInput"; +import { FormBtns } from "../form/formBtn"; + +function PopupContent(props){ + // props: title(str), inputs(array of object), buttons:(array of object) + return ( + // dark background +
+ {/* white popup container: */} +
+
+ {/* content area */} +

{props?.title}

+
+ +
{/* Adjust button positioning as needed */} + +
+ +
+
+
+ ); +} + + +export default PopupContent \ No newline at end of file diff --git a/front-end/GoodOldMap/src/index.css b/front-end/GoodOldMap/src/index.css index 2582867..cea22d5 100644 --- a/front-end/GoodOldMap/src/index.css +++ b/front-end/GoodOldMap/src/index.css @@ -24,5 +24,4 @@ } @layer utilities { - } \ No newline at end of file diff --git a/front-end/GoodOldMap/src/pages/Account/Account.jsx b/front-end/GoodOldMap/src/pages/Account/Account.jsx index 06ec1f7..b8275c1 100644 --- a/front-end/GoodOldMap/src/pages/Account/Account.jsx +++ b/front-end/GoodOldMap/src/pages/Account/Account.jsx @@ -1,9 +1,33 @@ const Account = () => { - + // parameters: pic, username, email, + let props = {}; + props.pic = "https://cdn.icon-icons.com/icons2/2645/PNG/512/person_icon_159921.png" + props.username = "John Doe" + props.email = "jd00001@nyu.edu" + return( - <> - account page - +
+
+ + profile picture + + +

{props.username}

+

{props.email}

+ {/* Add a button that redirects to another place */} + + + + + + +
+ +
) } diff --git a/front-end/GoodOldMap/src/pages/AccountEdit/AccountEdit.jsx b/front-end/GoodOldMap/src/pages/AccountEdit/AccountEdit.jsx index 521d3dc..7e0385e 100644 --- a/front-end/GoodOldMap/src/pages/AccountEdit/AccountEdit.jsx +++ b/front-end/GoodOldMap/src/pages/AccountEdit/AccountEdit.jsx @@ -1,3 +1,4 @@ +<<<<<<< Updated upstream const AccountEdit = () => { return( <> @@ -6,4 +7,126 @@ const AccountEdit = () => { ) } -export default AccountEdit \ No newline at end of file +export default AccountEdit +======= +import React, { useState } from 'react'; +import PopupLink from '../../components/popup/popupLink'; +import PopupContent from '../../components/popup/popupContent'; + + +const AccountEdit = () => { + const [currentActionData, setCurrentActionData] = useState(null); + + //TO DO for Richard: send data to backend + const discardChange = (evt) => { + evt.preventDefault() + evt.stopPropagation() + currentActionData && setCurrentActionData(null); + } + const confirmChangeUsername = (evt) => { + evt.preventDefault() + evt.stopPropagation() + } + const confirmChangeEmail = (evt) => { + evt.preventDefault() + evt.stopPropagation() + } + const sentForgetPwEmail = (evt) => { + evt.preventDefault() + evt.stopPropagation() + } + const confirmChangePassword = (evt) => { + evt.preventDefault() + evt.stopPropagation() + } + const confirmDeleteAccount = (evt) => { + evt.preventDefault() + evt.stopPropagation() + } + + + //All PopupContent data + const formData = { + "changeUsername": { + link: "Change Username", + title: "Change Username", + inputs: [{id:"newUsername", type:"text", placeholder:"new username"}], + buttons: [{value:"Discard", handleClick: discardChange}, + {value:"Confirm", handleClick: confirmChangeUsername}], + }, + "changeEmail": { + link: "Change Email", + title: "Change Email", + inputs: [{id:"newEmail", type:"text", placeholder:"new email"}, + {id:"password", type:"password", placeholder:"password"}], + buttons: [{value:"Discard", handleClick: discardChange}, + {value:"Confirm", handleClick: confirmChangeEmail}], + }, + "forgotPassword": { + link: "Forget Password", + title: "Forget Password", + inputs: [{id:"email", type:"text", placeholder:"email"}], + buttons: [{value:"Discard", handleClick: discardChange}, + {value: "Send Email", handleClick: sentForgetPwEmail}], + }, + "changePassword": { + link: "Change Password", + title: "Change Password", + inputs: [{id:"oldPassword", type:"password", placeholder:"old password"}, + {id:"password", type:"password", placeholder:"password"}, + {id:"confirmPassword", type:"password", placeholder:"confirm password"}], + buttons: [{value:"Discard", handleClick: discardChange}, + {value:"Confirm", handleClick: confirmChangePassword}], + }, + "logout": { + link: "Log Out", + title: "Log Out", + buttons: [{value:"Discard", handleClick: discardChange}, + {value:"Confirm", handleClick: confirmDeleteAccount}], + }, + "deleteAccount": { + link: "Delete Account", + title: "You will not be able to recover this account", + buttons: [{value:"Discard", handleClick: discardChange}, + {value:"Confirm", handleClick: confirmDeleteAccount}], + } + } + const formKeys = Object.keys(formData); + + //Function to decide which PopupContent to display + const handleAction = (key) => { + const actionData = formData[key]; + try { + if (!actionData) throw `No data found for action:: ${key}` + setCurrentActionData(actionData); + } catch (error) { + console.error(error) + } + }; + const handleClose = (evt) => { + evt.stopPropagation() + if(evt.target.classList.contains("popupBackground")) setCurrentActionData(null) + } + + //Return the AccountEdit component + return ( +
+ {/* TO DO: add image profile, add username, add user email */} + {formKeys.map((key, i) => handleAction(key)} key={i}/>)} + {/* TO DO: add logout link below*/} + {/* */} + + {currentActionData && + } + +
+ ); +}; + +export default AccountEdit; +>>>>>>> Stashed changes diff --git a/front-end/GoodOldMap/src/pages/FavoriteList/FavoriteList.jsx b/front-end/GoodOldMap/src/pages/FavoriteList/FavoriteList.jsx new file mode 100644 index 0000000..f936d38 --- /dev/null +++ b/front-end/GoodOldMap/src/pages/FavoriteList/FavoriteList.jsx @@ -0,0 +1,76 @@ +import { useNavigate } from 'react-router-dom' +import NavBar from "../../components/common/navBar" +import LeftBtn from "../../components/common/leftBtn" +import Logo from '../../components/common/Logo' +import ArtItem from "../../components/common/ArtItem.jsx" +import React, { useState } from 'react'; + + +const FavoriteList = () => { + // Declare your arts data array inside the FavoriteList component + + const url_temp = "https://upload.wikimedia.org/wikipedia/commons/thumb/7/75/Vincent_van_Gogh_-_Road_with_Cypress_and_Star_-_c._12-15_May_1890.jpg/1200px-Vincent_van_Gogh_-_Road_with_Cypress_and_Star_-_c._12-15_May_1890.jpg" + const urt_temp1 = "https://upload.wikimedia.org/wikipedia/commons/9/9d/Vincent_van_Gogh_-_Sunflowers_-_VGM_F458.jpg" + const url_temp2 = "https://upload.wikimedia.org/wikipedia/commons/6/6d/Vincent_van_Gogh_-_De_stoel_van_Gauguin_-_Google_Art_Project.jpg" + //TODO: will be a fetch request from the backend database later + const [arts, setArts] = useState([ + { id: 1, name: 'Art name A', url: url_temp, year: 2023 }, + { id: 2, name: 'Art name C', url: urt_temp1, year: 2000 }, + { id: 3, name: 'Art name B', url: url_temp2, year: 1990 } + ]); + + const navigate = useNavigate(); + + const navigateToDetail = (evt) => { + evt.preventDefault() + navigate("/info"); // Adjust this path as necessary + } + + const sortArts = (criteria) => { + if (criteria === "name") { + setArts(prevArts => [...prevArts].sort((a, b) => a.name.localeCompare(b.name))); + } else if (criteria === "year") { + setArts(prevArts => [...prevArts].sort((a, b) => a.year - b.year)); + } + } + + const handleRemoveFromFavorites = (idToRemove) => { + // Remove the art with the specified ID from the favorites list + setArts(prevArts => prevArts.filter(art => art.id !== idToRemove)); + } + + + + return ( + <> +
+ + + + + + {/*
*/} +
+

My Favorite

+ + +
+ +
+ { + arts.map(art => handleRemoveFromFavorites(art.id)} />) + } +
+
+ + + + ) +}; + +export default FavoriteList; + + diff --git a/front-end/GoodOldMap/src/pages/MainMap/MainMap.jsx b/front-end/GoodOldMap/src/pages/MainMap/MainMap.jsx index e1b055d..fb90bde 100644 --- a/front-end/GoodOldMap/src/pages/MainMap/MainMap.jsx +++ b/front-end/GoodOldMap/src/pages/MainMap/MainMap.jsx @@ -1,7 +1,19 @@ +import { MapContainer, TileLayer, useMap } from 'react-leaflet' + const MainMap = () => { return( <> - main map page + + + {/* + + A pretty CSS3 popup.
Easily customizable. +
+
*/} +
) } From 749881f30a8e8817d0c7a3157716c924a1ab1a83 Mon Sep 17 00:00:00 2001 From: Tracy Zhang <91210454+Ceiceiceii@users.noreply.github.com> Date: Mon, 30 Oct 2023 19:59:22 -0400 Subject: [PATCH 3/4] Create ArtItem --- .../GoodOldMap/src/components/common/ArtItem | 26 +++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 front-end/GoodOldMap/src/components/common/ArtItem diff --git a/front-end/GoodOldMap/src/components/common/ArtItem b/front-end/GoodOldMap/src/components/common/ArtItem new file mode 100644 index 0000000..4cceb3f --- /dev/null +++ b/front-end/GoodOldMap/src/components/common/ArtItem @@ -0,0 +1,26 @@ +import React from 'react'; +import { useNavigate } from 'react-router-dom' + +const ArtItem = ({ art,onRemoveFromFavorites }) => { + + const navigate = useNavigate(); + + const navigateToDetail = (evt) => { + evt.preventDefault() + navigate("/info"); // Adjust this path as necessary + // window.location.href = "/info"; + } + + return ( +
+ {art.name} +

+ ❤️ + {art.name} + {art.year} +

+
+ ); +}; + +export default ArtItem; From e7ddcbb1c70d692274be5308be57a9415869f2dc Mon Sep 17 00:00:00 2001 From: Tracy Zhang <91210454+Ceiceiceii@users.noreply.github.com> Date: Mon, 30 Oct 2023 20:47:39 -0400 Subject: [PATCH 4/4] addFavList remove FavList Sorting --- front-end/GoodOldMap/src/App.jsx | 5 ++--- .../src/components/common/{ArtItem => ArtItem.jsx} | 2 +- front-end/GoodOldMap/src/pages/Account/Account.jsx | 2 +- front-end/GoodOldMap/src/pages/FavoriteList/Favorite.jsx | 8 -------- .../GoodOldMap/src/pages/FavoriteList/FavoriteList.jsx | 1 + 5 files changed, 5 insertions(+), 13 deletions(-) rename front-end/GoodOldMap/src/components/common/{ArtItem => ArtItem.jsx} (93%) delete mode 100644 front-end/GoodOldMap/src/pages/FavoriteList/Favorite.jsx diff --git a/front-end/GoodOldMap/src/App.jsx b/front-end/GoodOldMap/src/App.jsx index cd99feb..6d9dc87 100644 --- a/front-end/GoodOldMap/src/App.jsx +++ b/front-end/GoodOldMap/src/App.jsx @@ -6,7 +6,7 @@ import Login from './pages/Authenticate/Login'; import Register from './pages/Authenticate/Register'; import Error from './pages/Error/Error'; import InfoDetail from './pages/InfoDetail/InfoDetail'; -import Favorite from './pages/FavoriteList/Favorite'; +import FavoriteList from './pages/FavoriteList/FavoriteList'; import AuthLayout from './pages/Authenticate/AuthLayout'; import AccountLayout from './pages/Account/AccountLayout'; import MapLayout from './pages/MainMap/MapLayout'; @@ -27,10 +27,9 @@ const App = () => { {/* TODO: add params: /info/:pieceInfo */} }/> - + }/> }> } /> - }/> } /> diff --git a/front-end/GoodOldMap/src/components/common/ArtItem b/front-end/GoodOldMap/src/components/common/ArtItem.jsx similarity index 93% rename from front-end/GoodOldMap/src/components/common/ArtItem rename to front-end/GoodOldMap/src/components/common/ArtItem.jsx index 4cceb3f..f37397f 100644 --- a/front-end/GoodOldMap/src/components/common/ArtItem +++ b/front-end/GoodOldMap/src/components/common/ArtItem.jsx @@ -12,7 +12,7 @@ const ArtItem = ({ art,onRemoveFromFavorites }) => { } return ( -
+
{art.name}

❤️ diff --git a/front-end/GoodOldMap/src/pages/Account/Account.jsx b/front-end/GoodOldMap/src/pages/Account/Account.jsx index 5e252d6..a25487e 100644 --- a/front-end/GoodOldMap/src/pages/Account/Account.jsx +++ b/front-end/GoodOldMap/src/pages/Account/Account.jsx @@ -27,7 +27,7 @@ const Account = () => { - +