Skip to content

Commit

Permalink
Merge pull request agiledev-students-fall2023#203 from agiledev-stude…
Browse files Browse the repository at this point in the history
…nts-fall2023/update_ui

Update UI
  • Loading branch information
lesleyzhao authored Dec 14, 2023
2 parents 44f6ffd + 505351c commit 5b5b734
Show file tree
Hide file tree
Showing 40 changed files with 473 additions and 767 deletions.
4 changes: 2 additions & 2 deletions back-end/.env
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
SESSION_SECRET='myKey123!'
JWT_SECRET='myKey123!'
CLIENT_URL="http://192.168.1.159:5173/"
CLIENT_URL="http://localhost:5173/"


MONGODB_DATA_API = "https://us-east-1.aws.data.mongodb-api.com/app/data-fzvrf/endpoint/data/v1"
Expand All @@ -10,4 +10,4 @@ MONGODB_URI = "mongodb+srv://yz5835:[email protected]
EMAIL_USER='[email protected]'
EMAIL_PASS='Goodoldmap123'

SERVER_PORT = "443"
SERVER_PORT = "3000"
68 changes: 25 additions & 43 deletions back-end/src/app.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,11 @@ import cors from "cors";
import dotenv from "dotenv";
import "dotenv/config";
import morgan from "morgan";
import session from "express-session";
import mongoose from "mongoose";
import { body, validationResult } from "express-validator";
import jwt from "jsonwebtoken";
import { body } from "express-validator";
import passport from "passport";
import CustomJwtStrategy from "./config/jwt-config.mjs";
// config
import JwtStrategy from "./config/JwtStrategy.mjs";
// routes
import loginRouter from "./routes/loginRouter.mjs";
import registerRouter from "./routes/registerRouter.mjs";
Expand All @@ -21,7 +20,6 @@ import delaccountRouter from "./routes/delaccountRouter.mjs";
import resetpasswordRouter from "./routes/resetpasswordRouter.mjs";
import resetemailRouter from "./routes/resetemailRouter.mjs";
import searchArtsRouter from "./routes/searchArtsRouter.mjs";

import {
addFavListRouter,
favListRouter,
Expand All @@ -30,6 +28,9 @@ import {

export function getExpress() {
const app = express();

// config environmental variables
dotenv.config({ silent: true });

// use the morgan middleware to log all incoming http requests
app.use(morgan("dev"));
Expand All @@ -41,7 +42,6 @@ export function getExpress() {
// serve static files
const __dirname = path.dirname(url.fileURLToPath(import.meta.url));
app.use("/static", express.static(path.join(__dirname, "public")));
dotenv.config({ path: path.resolve(__dirname, "../.env") });

// cors
const corsOptions = {
Expand All @@ -52,8 +52,7 @@ export function getExpress() {
};
app.use(cors(corsOptions));

console.log(process.env.CLIENT_URL);
console.log("MongoDB URI: ", process.env.MONGODB_URI);
// console.log("MongoDB URI: ", process.env.MONGODB_URI);

// Connect to MongoDB
mongoose
Expand All @@ -65,29 +64,7 @@ export function getExpress() {
console.log("Connected to MongoDB...");
})
.catch((err) => console.error("Could not connect to MongoDB...", err));

// session to auto-save user data (like id) when they login
app.use(
session({
secret: process.env.SESSION_SECRET,
resave: false,
saveUninitialized: true,
cookie: { httpOnly: true, secure: process.env.NODE_ENV === "production" },
})
);
console.log("Session secret:", process.env.SESSION_SECRET);

// jwt strategy
passport.use(CustomJwtStrategy);

// initialize passport
app.use(passport.initialize());

// routes that does not need authentication
// app.post("/getpiece", getpieceRouter);
app.post("/register", registerRouter);
app.post("/login", loginRouter);


// Validation rules for routers
const usernameValidationRules = [
body("newUsername")
Expand Down Expand Up @@ -118,23 +95,28 @@ export function getExpress() {
// Optionally, include checks for special characters or uppercase letters
];

// routes that needs authentication
// Account routes
app.patch("/changeusername", usernameValidationRules, changeusernameRouter); //Finished
app.patch("/resetemail", emailValidationRules, resetemailRouter); //Finished
app.post("/forget", forgetpasswordRouter);
app.patch("/resetpassword", passwordValidationRules, resetpasswordRouter); //Finished
app.delete("/delaccount", delaccountRouter); //Finished
// jwt strategy
passport.use(JwtStrategy)
app.use(passport.initialize())

app.get("/test",async (req,res) => {
res.json({"status" : "Hello there!"});
})
// Authenticate private routes
// app.use("/auth", passport.authenticate('jwt', { session: false }))

// Favorites list routes
app.post("/addFavorite", addFavListRouter); //finished
app.get("/getfavlist", favListRouter);
app.get("/getArts", getArts); //finished
app.get("/searchArts", searchArtsRouter);
app.post("/auth/addFavorite", addFavListRouter); //finished
app.get("/auth/getfavlist", favListRouter);

// Account routes
app.post("/register", registerRouter);
app.post("/login", loginRouter);
app.patch("/auth/changeusername", usernameValidationRules, changeusernameRouter); //Finished
app.patch("/auth/resetemail", emailValidationRules, resetemailRouter); //Finished
app.post("/auth/forgetpassword", forgetpasswordRouter);
app.patch("/auth/resetpassword", passwordValidationRules, resetpasswordRouter); //Finished
app.delete("/auth/delaccount", delaccountRouter); //Finished

return app;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,32 +2,29 @@ import passportJWT from "passport-jwt";
import User from "../models/User.mjs";

const ExtractJwt = passportJWT.ExtractJwt
const JwtStrategy = passportJWT.ExtractJwt
const Strategy = passportJWT.Strategy

// how the token is extracted and verified from the request
const jwtOptions = {
jwtFromRequest: ExtractJwt.fromAuthHeaderWithScheme("jwt"), //fromAuthHeaderAsBearerToken()
jwtFromRequest: ExtractJwt.fromAuthHeaderAsBearerToken(), //fromAuthHeaderWithScheme("jwt")
secretOrKey: process.env.JWT_SECRET,
}

const jwtVerifyToken = async function (jwt_payload, done) {
console.log("JWT payload received", jwt_payload) // debugging

// token expiration
// TODO: token expiration check

// match user in database
try {
const user = await User.findOne({ uuid: jwt_payload.uuid })
if (!user) throw {jwtMessage: "user not found"}
if (!user) return done(null, false)
return done(null, user)

} catch (error) {
return done(null, false, {message: error.jwtMessage})
return done(err, false, {message: error.message})
}
}

const CustomJwtStrategy = () => {
return new JwtStrategy(jwtOptions, jwtVerifyToken)
}
const JwtStrategy = new Strategy(jwtOptions, jwtVerifyToken)

export default CustomJwtStrategy
export default JwtStrategy
3 changes: 0 additions & 3 deletions back-end/src/routes/forgetpasswordRouter.mjs
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
//to-do add recovery page, now we only send token to client's email
import User from '../models/User.mjs';
import bcrypt from 'bcryptjs';
import jwt from 'jsonwebtoken';
import sendRecoveryEmail from './sendEmail.mjs';
import axios from 'axios';
Expand Down
7 changes: 7 additions & 0 deletions front-end/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,27 @@
<html lang="en">
<head>
<meta charset="UTF-8" />
<!-- icon -->
<link rel="icon" type="image/svg+xml" href="/maplogo.png" />
<!-- text fonts -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Lora&display=swap" rel="stylesheet">
<!-- leaflet stylesheet -->
<link rel="stylesheet" href="https://unpkg.com/[email protected]/dist/leaflet.css"
integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY="
crossorigin=""/>
<!-- popup stylesheet -->
<link rel="stylesheet" href="https://unpkg.com/react-spring-bottom-sheet/dist/style.css" crossorigin="anonymous">
<!-- leaflet script -->
<script src="https://unpkg.com/[email protected]/dist/leaflet.js"
integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo="
crossorigin=""></script>

<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
<title>GoodOldMap</title>
</head>

<body class="bg-beige1">
<div id="root"></div>
<script type="module" src="/src/main.jsx"></script>
Expand Down
13 changes: 7 additions & 6 deletions front-end/src/App.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ import InfoDetail from './pages/InfoDetail/InfoDetail';
import FavoriteList from './pages/FavoriteList/FavoriteList';
import AppLayout from './AppLayout';
import AuthLayout from './pages/Authenticate/AuthLayout';
import AccountWithLogin from './pages/Account/AccountWithLogin';
import ResetPassword from './pages/Account/ResetPassword';
import ResetPassword from './pages/Authenticate/ResetPassword';
import PrivateRoute from './pages/Private/PrivateRoute';

import MapLayout from './pages/MainMap/MapLayout';
const App = () => {
Expand All @@ -28,15 +28,16 @@ const App = () => {
<Route path="/login" element={<Login />} />
<Route path="/register" element={<Register />} />
</Route>
<Route path="/resetpassword" element={<ResetPassword />} />

{/* TODO: add params: /info/:pieceInfo */}
<Route path="/info" element={<InfoDetail/>}/>
<Route path="/favoritelist" element={<FavoriteList />}/>
<Route path="/account" element={<AccountEdit />} />
<Route path="/accountLog" element={<AccountWithLogin />} />
<Route path="/*" element={<Error />} />
<Route path="/resetpassword" element={<ResetPassword />} />

<Route element={<PrivateRoute />}>
<Route path="/favoritelist" element={<FavoriteList />}/>
<Route path="/account" element={<AccountEdit />} />
</Route>
</Route>

</Routes>
Expand Down
5 changes: 4 additions & 1 deletion front-end/src/AppLayout.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,10 @@ import BottomNavBar from "./components/common/bottomNavBar"
const AppLayout = () => {
return (
<>
<Outlet />
{/* viewport height - bottom navbar height */}
<div className="mb-[calc(4vh+1.75rem)]">
<Outlet />
</div>
<BottomNavBar/>
</>
)
Expand Down
7 changes: 4 additions & 3 deletions front-end/src/components/art/ArtItem.jsx
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import React, { useState } from 'react';
import { useNavigate, useLocation } from 'react-router-dom';
import Card from '../common/card';
import IconButton from '@mui/material/IconButton';
import FavoriteIcon from '@mui/icons-material/Favorite';
import FavoriteBorderIcon from '@mui/icons-material/FavoriteBorder';
import axiosProvider from "../../util/api/axios"
import Card from '../common/card';
// helper
import { axiosPrivateProvider } from "../../util/api/axios"


const ArtItem = ({art}) => {
Expand Down Expand Up @@ -32,7 +33,7 @@ const ArtItem = ({art}) => {
};

try {
const response = await axiosProvider.post('/addFavorite', artData);
const response = await axiosPrivateProvider.post('/addFavorite', artData);
setIsFavorited(response.data.isFavorited);
} catch (error) {
console.error('Error updating favorites', error);
Expand Down
15 changes: 4 additions & 11 deletions front-end/src/components/common/bottomNavBar.jsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,27 @@
import { useLocation, useNavigate } from "react-router-dom"
import Logo from "./Logo"
import Logo from "../icon/logo"

const BottomNavBar = () => {
const navigate = useNavigate();
const location = useLocation();


const handleClickHeart = (evt) => {
evt.stopPropagation()
navigate("/favoritelist", { state: { from: location.pathname } })
}
const handleClickUser = (evt) => {
evt.stopPropagation()
if(localStorage.getItem('token') != null){
navigate("/account", { state: { from: location.pathname } });
}else{
navigate("/accountLog", { state: { from: location.pathname } });
}
navigate("/account", { state: { from: location.pathname } });
}
// fixed bottom navbar - height : 4vh+1.75rem
return (
<>
<div className="h-[calc(3vh+2.25rem)]">
<nav className="z-[1500] flex fixed bottom-0 pt-[2vh] pb-[2vh] px-[10%] w-full bg-beige1">
<nav className="z-[1500] flex fixed bottom-0 py-[2vh] px-[10%] w-full bg-beige1">
<div className="flex flex-row justify-between w-full max-w-[30rem] mx-auto">
<Logo />
<img className="w-7 h-7 hover:cursor-pointer" src="/heart.png" alt="heart" onClick={handleClickHeart}/>
<img className="w-7 h-7 hover:cursor-pointer" src="/user.png" alt="user" onClick={handleClickUser}/>
</div>
</nav>
</div>
</>
)
}
Expand Down
2 changes: 1 addition & 1 deletion front-end/src/components/common/navBar.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ const NavBar = ({children, relative}) => {
return (
<>
<div className="h-[calc(2vh+2rem)]">
<nav className={`${relative?"relative":"fixed"} flex p-[1vh] px-[10%] h-[calc(2vh+2rem)] w-full
<nav className={`${relative?"relative":"fixed"} flex p-[1vh] px-[10%] w-full
bg-beige1 duration-700 ${navHidden} z-20`}>
<div className="flex flex-row justify-between w-full max-w-[30rem] mx-auto">
{children}
Expand Down
6 changes: 4 additions & 2 deletions front-end/src/components/common/pageLink.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@ const PageLink = (props) => {
// attributes: to, value
const location = useLocation();
return(
<div className='w-full text-center py-2 underline'>
<div className='w-full text-center py-2'>
<Link
to={props.to}
state={{from: location.pathname}}>
{props.value}
<span className='underline'>
{props.value}
</span>
</Link>
</div>
)
Expand Down
9 changes: 0 additions & 9 deletions front-end/src/components/common/rightBtn.jsx

This file was deleted.

Loading

0 comments on commit 5b5b734

Please sign in to comment.