Commit 04f7c521 authored by Kim, Subin's avatar Kim, Subin
Browse files

Merge remote-tracking branch 'origin/rkyoung7'

parents 147e12a8 914ed2b6
...@@ -10,11 +10,13 @@ import StudyPlanPage from "./pages/StudyPlanPage"; ...@@ -10,11 +10,13 @@ import StudyPlanPage from "./pages/StudyPlanPage";
import StudyPlanEditPage from "./pages/StudyPlanEditPage"; import StudyPlanEditPage from "./pages/StudyPlanEditPage";
import SubjectEditPage from "./pages/SubjectEditPage"; import SubjectEditPage from "./pages/SubjectEditPage";
import AdminPage from "./pages/Admin/AdminPage"; import AdminPage from "./pages/Admin/AdminPage";
import { AuthProvider } from "./utils/context.js";
import PrivateRoute from "./components/PrivateRoute"; import PrivateRoute from "./components/PrivateRoute";
import ErrorPage from "./pages/ErrorPage"; import ErrorPage from "./pages/ErrorPage";
function App() { function App() {
return ( return (
<AuthProvider >
<Router basename={process.env.PUBLIC_URL}> <Router basename={process.env.PUBLIC_URL}>
<div id="box" className="container position-relative vh-100 mx-sm-auto"> <div id="box" className="container position-relative vh-100 mx-sm-auto">
<Switch> <Switch>
...@@ -39,6 +41,7 @@ function App() { ...@@ -39,6 +41,7 @@ function App() {
</Switch> </Switch>
</div> </div>
</Router> </Router>
</AuthProvider>
); );
} }
......
import axios from "axios"; import axios from "axios";
import baseUrl from "../utils/baseUrl.js"; import baseUrl from "../utils/baseUrl.js";
const getUser = async () => {
const url = `${baseUrl}/api/auth/user`
const { data } = await axios.get(url)
return data
}
const signup = async (user) => { const signup = async (user) => {
const url = `${baseUrl}/api/auth/signup`; const url = `${baseUrl}/api/auth/signup`;
const { data, status } = await axios.post(url, user); const { data } = await axios.post(url, user);
return { data, status } return data
} }
const login = async (user) => { const login = async (user) => {
const url = `${baseUrl}/api/auth/login`; const url = `${baseUrl}/api/auth/login`;
const { data, status } = await axios.post(url, user); const { data } = await axios.post(url, user);
return { data, status } return data
}
const logout = async () => {
const url = `${baseUrl}/api/auth/logout`;
const { data } = await axios.get(url);
return data
} }
const authApi = { const authApi = {
getUser,
signup, signup,
login login,
logout
}; };
export default authApi export default authApi
\ No newline at end of file
import axios from "axios"; import axios from "axios";
import baseUrl from "../utils/baseUrl.js"; import baseUrl from "../utils/baseUrl.js";
const addsubject = async (info) => { const addsubject = async (info, userId) => {
console.log('info확인', info) console.log('subject check', userId)
// info.user = userId;
const url = `${baseUrl}/api/subject/addsubject`; const url = `${baseUrl}/api/subject/addsubject`;
const { data, status } = await axios.post(url, info); const { data } = await axios.post(url, { info, userId });
console.log('data status', data, '|', status) return data
return { data, status } }
const editSubject = async (info, id) => {
console.log("editSubject check", info, ',', id)
const url = `${baseUrl}/api/subject/editsubject`
const { data } = await axios.post(url, { info, id })
return data
}
const getSubInfo = async (info) => {
console.log('info', info)
const url = `${baseUrl}/api/subject/${info}`
const { data } = await axios.get(url);
return data
} }
const subjectApi = { const subjectApi = {
addsubject addsubject,
getSubInfo,
editSubject
}; };
export default subjectApi export default subjectApi
\ No newline at end of file
...@@ -3,12 +3,7 @@ import { Link } from "react-router-dom"; ...@@ -3,12 +3,7 @@ import { Link } from "react-router-dom";
import styles from "../Form/form.module.scss"; import styles from "../Form/form.module.scss";
const StudyPlanCard = () => { const StudyPlanCard = () => {
const [studyplan, setStudyplan] = useState({ // studyPlanList에서 props로 받아서 뿌리기
subject: "",
info: "",
contents: []
})
return ( return (
<> <>
<div className="d-flex justify-content-center mt-3"> <div className="d-flex justify-content-center mt-3">
...@@ -18,7 +13,7 @@ const StudyPlanCard = () => { ...@@ -18,7 +13,7 @@ const StudyPlanCard = () => {
<div className="d-flex justify-content-between"> <div className="d-flex justify-content-between">
<h5 className="card-title col-10">운영체제</h5> <h5 className="card-title col-10">운영체제</h5>
<div className="col-2 d-flex justify-content-end"> <div className="col-2 d-flex justify-content-end">
<Link className="text-decoration-none link-dark" to="/subject/edit"><i className="bi bi-pencil-square pe-2"></i></Link> <Link className="text-decoration-none link-dark" to="/subject/edit/ed56bebd-b9ae-4065-aae2-d39aeac5f18e"><i className="bi bi-pencil-square pe-2"></i></Link>
<i className="bi bi-trash"></i> <i className="bi bi-trash"></i>
</div> </div>
</div> </div>
......
import { useState } from 'react'; import { useState } from 'react';
import { Redirect, Link } from "react-router-dom"; import { Redirect, Link } from "react-router-dom";
import { Formik } from 'formik'; import { Formik } from 'formik';
import { useAuth } from "../../utils/context.js";
import * as Yup from 'yup'; import * as Yup from 'yup';
import authApi from '../../apis/auth.api';
import catchErrors from "../../utils/catchErrors.js"; import catchErrors from "../../utils/catchErrors.js";
import styles from "./form.module.scss"; import styles from "./form.module.scss";
const LoginForm = () => { const LoginForm = () => {
const { login } = useAuth();
const [success, setSuccess] = useState(false); const [success, setSuccess] = useState(false);
const [error, setError] = useState(""); const [error, setError] = useState("");
...@@ -28,9 +29,10 @@ const LoginForm = () => { ...@@ -28,9 +29,10 @@ const LoginForm = () => {
})} })}
onSubmit={async (values, { setSubmitting, resetForm }) => { onSubmit={async (values, { setSubmitting, resetForm }) => {
try { try {
console.log('login values', values)
setError("") setError("")
const result = await authApi.login(values) const result = await login(values)
if (result.status === 201) { if (result) {
setSuccess(true) setSuccess(true)
} }
} catch (error) { } catch (error) {
......
import { useState, useEffect } from 'react'; import { useState, useEffect } from 'react';
import { Redirect, useParams } from 'react-router-dom';
import { useAuth } from '../../utils/context.js';
import BtnGroup from "../Buttons/BtnGroup"; import BtnGroup from "../Buttons/BtnGroup";
import styles from "./form.module.scss"; import styles from "./form.module.scss";
import { useParams } from 'react-router-dom';
import subjectApi from '../../apis/subject.api'; import subjectApi from '../../apis/subject.api';
import catchErrors from '../../utils/catchErrors.js'; import catchErrors from '../../utils/catchErrors.js';
const SubjectForm = () => { const SubjectForm = () => {
const { user } = useAuth();
const { subjectId } = useParams(); const { subjectId } = useParams();
const [success, setSuccess] = useState(false)
const [error, setError] = useState(""); const [error, setError] = useState("");
const [subject, setSubject] = useState({ const [subject, setSubject] = useState({
lectureName: "", lectureName: "",
...@@ -15,6 +18,11 @@ const SubjectForm = () => { ...@@ -15,6 +18,11 @@ const SubjectForm = () => {
}) })
const [disabled, setDisabled] = useState(true) const [disabled, setDisabled] = useState(true)
useEffect(() => {
getInfo(subjectId);
}, [])
useEffect(() => { useEffect(() => {
let isMounted = true; let isMounted = true;
const checkInfo = { lectureName: subject.lectureName } const checkInfo = { lectureName: subject.lectureName }
...@@ -34,36 +42,60 @@ const SubjectForm = () => { ...@@ -34,36 +42,60 @@ const SubjectForm = () => {
} }
async function getInfo(id) {
const result = await subjectApi.getSubInfo(id)
console.log('과목수정 result확인', result)
setSubject({
lectureName: result.name,
prof: result.prof,
classRoom: result.room
})
}
async function handleSubmit(e) { async function handleSubmit(e) {
e.preventDefault(); e.preventDefault();
try { try {
setError("")
if (subjectId) { if (subjectId) {
//수정함수 실행 //수정함수 실행
await subjectApi.editSubject(subject, subjectId)
alert("과목정보가 수정되었습니다.")
setSuccess(true)
} else { } else {
await subjectApi.addsubject(subject) //등록함수 실행
await subjectApi.addsubject(subject, user.id)
} }
} catch (error) { } catch (error) {
catchErrors(error, setError) catchErrors(error, setError)
setSubject({
lectureName: "",
prof: "",
classRoom: ""
})
} }
} }
if (success) {
return <Redirect to="/studyplan" />
}
return ( return (
<> <>
<div className="position-absolute top-50 start-50 translate-middle" style={{ width: "80%" }}> <div className="position-absolute top-50 start-50 translate-middle" style={{ width: "80%" }}>
<div> <div>
<div className="mb-5 d-flex flex-row"> <div className="mb-5 d-flex flex-row">
<label className="form-label fs-4" style={{ width: "100px" }}>강의명</label> <label className="form-label fs-4" style={{ width: "100px" }}>강의명</label>
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} name="lectureName" onChange={handleChange} /> <input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.lectureName} name="lectureName" onChange={handleChange} />
</div> </div>
<div className="mb-5 pt-2 d-flex flex-row"> <div className="mb-5 pt-2 d-flex flex-row">
<label className="form-label fs-4" style={{ width: "100px" }}>교수명</label> <label className="form-label fs-4" style={{ width: "100px" }}>교수명</label>
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} name="prof" onChange={handleChange} /> <input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.prof} name="prof" onChange={handleChange} />
</div> </div>
<div className="mb-5 pt-2 d-flex flex-row"> <div className="mb-5 pt-2 d-flex flex-row">
<label className="form-label fs-4 " style={{ width: "100px", letterSpacing: "15px" }}>장소</label> <label className="form-label fs-4 " style={{ width: "100px", letterSpacing: "15px" }}>장소</label>
<input className={`form-control shadow-none rounded-0 ${styles.textInput}`} name="classRoom" onChange={handleChange} /> <input className={`form-control shadow-none rounded-0 ${styles.textInput}`} value={subject.classRoom} name="classRoom" onChange={handleChange} />
</div> </div>
</div> </div>
<div className="pt-2"> <div className="pt-2">
......
import { Link, Redirect } from "react-router-dom"; import { Link, Redirect } from "react-router-dom";
import { useAuth } from "../../utils/context.js";
import moment from "moment"; import moment from "moment";
import styles from "./menu.module.scss"; import styles from "./menu.module.scss";
const Menu = () => { const Menu = () => {
const { logout } = useAuth();
return ( return (
<> <>
<button className="btn btn-crimson shadow-none mt-2" type="button" data-bs-toggle="collapse" data-bs-target="#menuContent" aria-controls="menuContent" aria-expanded="false" aria-label="menu"> <button className="btn btn-crimson shadow-none mt-2" type="button" data-bs-toggle="collapse" data-bs-target="#menuContent" aria-controls="menuContent" aria-expanded="false" aria-label="menu">
...@@ -39,7 +41,7 @@ const Menu = () => { ...@@ -39,7 +41,7 @@ const Menu = () => {
<Link className="text-dark text-decoration-none" to={`/schedule/${moment().format("YYYY-MM-DD")}`}><i className="bi bi-check"></i>일정</Link> <Link className="text-dark text-decoration-none" to={`/schedule/${moment().format("YYYY-MM-DD")}`}><i className="bi bi-check"></i>일정</Link>
<Link className="text-dark text-decoration-none" to="/studyplan"><i className="bi bi-check"></i>학업별 계획</Link> <Link className="text-dark text-decoration-none" to="/studyplan"><i className="bi bi-check"></i>학업별 계획</Link>
</div> </div>
<p className={`position-absolute bottom-0 text-dark ${styles.logout}`}>로그아웃</p> <p className={`position-absolute bottom-0 text-dark ${styles.logout}`} onClick={logout}>로그아웃</p>
</div> </div>
</div> </div>
</div> </div>
......
import { Redirect, Route } from "react-router-dom"; import { Redirect, Route } from "react-router-dom";
// import { useAuth } from "../context/auth_context"; import { useAuth } from "../utils/context.js"
import ErrorPage from "../pages/ErrorPage"; import ErrorPage from "../pages/ErrorPage";
const PrivateRoute = ({ component: Component, ...rest }) => { const PrivateRoute = ({ component: Component, ...rest }) => {
// const { user } = useAuth(); const { user } = useAuth();
// return ( // return (
// <Route // <Route
// {...rest} // {...rest}
......
import { createContext, useCallback, useContext, useEffect, useState } from 'react';
import { Redirect } from 'react-router-dom';
import authApi from "../apis/auth.api";
import catchErrors from './catchErrors';
const AuthContext = createContext({
error: "",
user: { id: "", role: "user", name: "" },
setUser: () => { },
login: () => Promise.resolve(false),
logout: () => { },
catchErrorAuth: (error, displayError) => { },
});
const AuthProvider = ({ children }) => {
const [error, setError] = useState("");
const [user, setUser] = useState({ id: "", role: "user", name: "" });
const getUser = async () => {
const { id, role, userName } = await authApi.getUser();
const user = { id: id, role: role, name: userName };
setUser(user);
}
useEffect(() => {
getUser();
}, []);
const login = useCallback(async (data) => {
try {
setError("");
const user = await authApi.login(data);
localStorage.setItem("login", true)
setUser(user);
console.log('setUser 결과', user)
return true;
} catch (error) {
catchErrors(error, setError);
return false;
}
}, []);
const logout = useCallback(async () => {
try {
setError("");
const user = await authApi.logout();
localStorage.removeItem("login")
setUser(user);
alert("로그아웃 되었습니다.");
} catch (error) {
catchErrors(error, setError);
}
}, []);
const catchErrorAuth = useCallback(async (error, displayError) => {
let errMsg;
if (error.response) {
if (typeof error.response.data === "string") {
errMsg = error.response.data;
console.log('Error response:', errMsg);
} else {
const { data } = error.response;
if (data.redirectUrl) {
errMsg = data.message;
console.log('Error response with redirected message:', errMsg);
return await logout();
}
}
} else if (error.request) {
errMsg = error.request;
console.log('Error request:', errMsg);
} else {
errMsg = error.message;
console.log("Error message:", errMsg)
}
displayError(errMsg);
}, []);
return (
<AuthContext.Provider value={{ error, user, setUser, login, logout, catchErrorAuth }} >
{children}
</AuthContext.Provider>
);
};
const useAuth = () => useContext(AuthContext);
export { AuthProvider, useAuth };
...@@ -2,28 +2,67 @@ import { Subject } from '../db/index.js'; ...@@ -2,28 +2,67 @@ import { Subject } from '../db/index.js';
const addsubject = async (req, res) => { const addsubject = async (req, res) => {
console.log('server/addsubject req.body', req.body) console.log('server/addsubject req.body', req.body)
const { lectureName, prof, classRoom } = req.body;
try { try {
const findName = await Subject.findOne({ where: { name: lectureName } }); const { info, userId } = req.body;
const findName = await Subject.findOne({ where: { name: info.lectureName } });
if (findName) { if (findName) {
throw new Error("이미 있는 과목입니다.") throw new Error("이미 있는 과목입니다.")
} }
await Subject.create({ await Subject.create({
name: lectureName, name: info.lectureName,
prof: prof, prof: info.prof,
room: classRoom, room: info.classRoom,
userId: userId
}) })
} catch (error) { } catch (error) {
console.log(error) console.log(error)
return res.status(500).send(error.message || "과목저장 에러발생") return res.status(500).send(error.message || "과목저장 에러발생")
} }
}
const getSubInfo = async (req, res) => {
console.log('server/getSubInfo req.body', req.params)
try {
const { subjectId } = req.params;
const findSubInfo = await Subject.findOne({ where: { id: subjectId } })
if (findSubInfo) {
res.json({
name: findSubInfo.dataValues.name,
prof: findSubInfo.dataValues.prof,
room: findSubInfo.dataValues.room
})
} else {
throw new Error("과목 찾기 실패")
}
} catch (error) {
console.log(error)
return res.status(500).send(error.message || "과목정보 가져오기 에러발생")
}
}
const editSubject = async (req, res) => {
console.log('server/editSubject req.body', req.body)
try {
const { info, id } = req.body;
const result = await Subject.update({
name: info.lectureName,
prof: info.prof,
room: info.classRoom,
}, { where: { id: id } })
if (!result) {
throw new Error("과목정보 수정 에러발생")
} else {
res.send(200)
}
} catch (error) {
console.log(error)
return res.status(500).send(error.message || "과목정보 수정 에러발생")
}
} }
export default { export default {
addsubject addsubject,
getSubInfo,
editSubject
} }
\ No newline at end of file
...@@ -2,6 +2,22 @@ import jwt from "jsonwebtoken"; ...@@ -2,6 +2,22 @@ import jwt from "jsonwebtoken";
import { User } from '../db/index.js'; import { User } from '../db/index.js';
import config from "../config/app.config.js"; import config from "../config/app.config.js";
const getUser = async (req, res) => {
try {
if (req.cookies.todayku) {
const token = req.cookies.todayku;
const { id, role, name } = jwt.verify(token, config.jwtSecret);
res.json({ id, role, name });
} else {
res.json({ id: "", role: "user", name: "" });
}
} catch (error) {
console.error(error);
return res.status(500).send("유저를 가져오지 못했습니다.");
}
}
const signup = async (req, res) => { const signup = async (req, res) => {
console.log('server/signup req.body', req.body) console.log('server/signup req.body', req.body)
const { userId, password, userName, userStudNum } = req.body; const { userId, password, userName, userStudNum } = req.body;
...@@ -15,7 +31,7 @@ const signup = async (req, res) => { ...@@ -15,7 +31,7 @@ const signup = async (req, res) => {
password: password, password: password,
userName: userName, userName: userName,
studNum: userStudNum, studNum: userStudNum,
role:"user" role: "user"
}); });
res.status(201).json("success") res.status(201).json("success")
} catch (error) { } catch (error) {
...@@ -37,8 +53,9 @@ const login = async (req, res) => { ...@@ -37,8 +53,9 @@ const login = async (req, res) => {
if (passwordMatch) { if (passwordMatch) {
const signData = { const signData = {
id: user.userID, id: user.id,
name: user.userName role: "user",
name: user.userName,
}; };
const token = jwt.sign(signData, config.jwtSecret, { const token = jwt.sign(signData, config.jwtSecret, {
...@@ -52,7 +69,7 @@ const login = async (req, res) => { ...@@ -52,7 +69,7 @@ const login = async (req, res) => {
secure: config.env === "production", secure: config.env === "production",
}); });
res.status(201).json(user) res.status(201).json(signData)
} else { } else {
res.status(401).send("비밀번호가 일치하지 않습니다.") res.status(401).send("비밀번호가 일치하지 않습니다.")
} }
...@@ -63,7 +80,23 @@ const login = async (req, res) => { ...@@ -63,7 +80,23 @@ const login = async (req, res) => {
} }
} }
const logout = async (req, res) => {
try {
res.clearCookie(config.cookieName);
res.json({
id:"",
role:"user",
name:""
})
} catch (error) {
console.log(error);
return res.status(500).send("로그아웃 에러발생")
}
}
export default { export default {
getUser,
signup, signup,
login login,
logout
} }
\ No newline at end of file
...@@ -7,4 +7,13 @@ router ...@@ -7,4 +7,13 @@ router
.route("/addsubject") .route("/addsubject")
.post(subjectCtrl.addsubject) .post(subjectCtrl.addsubject)
router
.route("/:subjectId")
.get(subjectCtrl.getSubInfo)
router
.route("/editsubject")
.post(subjectCtrl.editSubject)
export default router; export default router;
\ No newline at end of file
...@@ -11,4 +11,7 @@ router ...@@ -11,4 +11,7 @@ router
.route("/login") .route("/login")
.post(userCtrl.login) .post(userCtrl.login)
router
.route("/logout")
.get(userCtrl.logout )
export default router; export default router;
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment