Commit ae1406c4 authored by CHAERIN KIM's avatar CHAERIN KIM
Browse files

Merge remote-tracking branch 'origin/hyj' into cherry

parents fc4d0a01 9e22fd14
...@@ -12,6 +12,7 @@ const loginRouter = require('./routes/login'); ...@@ -12,6 +12,7 @@ const loginRouter = require('./routes/login');
const reservesRouter = require('./routes/reserves'); const reservesRouter = require('./routes/reserves');
const noticeRouter = require('./routes/notices'); const noticeRouter = require('./routes/notices');
const connect = require('./schemas'); const connect = require('./schemas');
const writesRouter = require('./routes/writes');
const app = express(); const app = express();
connect(); connect();
...@@ -31,6 +32,7 @@ app.use('/users', usersRouter, reservesRouter); ...@@ -31,6 +32,7 @@ app.use('/users', usersRouter, reservesRouter);
app.use('/login', loginRouter); app.use('/login', loginRouter);
app.use('/reserves', reservesRouter); app.use('/reserves', reservesRouter);
app.use('/notices', noticeRouter); app.use('/notices', noticeRouter);
app.use('/writes', writesRouter);
app.listen(port, () => console.log(port)); app.listen(port, () => console.log(port));
......
...@@ -2,17 +2,14 @@ import axios from 'axios'; ...@@ -2,17 +2,14 @@ import axios from 'axios';
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect } from 'react';
import { Link, Redirect } from 'react-router-dom'; import { Link, Redirect } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import { Navbar, Nav, NavLink } from 'react-bootstrap';
import axios from 'axios';
const Nav = styled.nav` const MENU = styled(Navbar)`
background-color: #7B031D; background-color: #7B031D;
height: 6vh;
a { a {
color: #ffffff; color : white;
}
& .logoutBtn:hover {
text-decoration: underline;
} }
` `
...@@ -21,18 +18,16 @@ function Menu() { ...@@ -21,18 +18,16 @@ function Menu() {
const [user, setUser] = useState({ role: "" }) const [user, setUser] = useState({ role: "" })
const name = localStorage.getItem('name'); const name = localStorage.getItem('name');
useEffect(() => {
acheck();
}, [])
if (state) return <Redirect to="/" />;
function logout() { function logout() {
localStorage.clear(); localStorage.clear();
alert("로그아웃 되었습니다."); alert("로그아웃 되었습니다.");
setState(true); setState(true);
} }
useEffect(() => {
acheck();
}, [])
function acheck() { function acheck() {
axios.get(`/users/${localStorage.getItem('_id')}`) axios.get(`/users/${localStorage.getItem('_id')}`)
.then(res => { .then(res => {
...@@ -44,52 +39,46 @@ function Menu() { ...@@ -44,52 +39,46 @@ function Menu() {
}); });
} }
if (state) return <Redirect to="/" />
return ( return (
<Nav className="navbar sticky-top navbar-expand-md"> <MENU expand="md" variant="dark">
<a class="navbar-brand" href="#">대관 서비스</a> <Navbar.Brand href="#">대관 서비스</Navbar.Brand>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar" aria-controls="collapsibleNavbar"> <Navbar.Toggle aria-controls="basic-navbar-nav" />
<span className="navbar-toggler-icon"></span> <Navbar.Collapse id="basic-navbar-nav">
</button> <Nav className="mr-auto">
<div className="collapse navbar-collapse justify-content-between" id="collapsibleNavbar"> <NavLink as={Link} to="/notice">공지사항</NavLink>
<ul className="navbar-nav"> <NavLink as={Link} to="/home">대관 현황</NavLink>
<li className="nav-item">
<Link to="/notice" className="nav-link">공지사항</Link> <NavLink as={Link} to={{
</li> pathname: `/apply/${localStorage.getItem('_id')}`,
<li className="nav-item"> state: { id: localStorage.getItem('_id') },
<Link to="/home" className="nav-link">대관 현황</Link> }} className="nav-link">대관 신청</NavLink>
</li>
<li className="nav-item"> <NavLink as={Link} to={{
<Link to={{ pathname: `/check/${localStorage.getItem('_id')}`,
pathname: `/apply/${localStorage.getItem('_id')}`, state: { id: localStorage.getItem('_id') },
state: { id: localStorage.getItem('_id') }, }} className="nav-link">
}} className="nav-link">대관 신청</Link> 대관 확인/취소</NavLink>
</li>
<li className="nav-item"> {user.role === "admin" ? (
<Link to={{ <NavLink as={Link} to={{
pathname: `/check/${localStorage.getItem('_id')}`, pathname: `/acheck/${localStorage.getItem('_id')}`,
state: { id: localStorage.getItem('_id') }, state: { id: localStorage.getItem('_id') },
}} className="nav-link"> }} className="nav-link">
대관 확인/취소</Link> 대관 확인/취소(관리자)</NavLink>) : null}
</li> </Nav>
{user.role === "admin" ? ( <Nav >
<li className="nav-item"> <NavLink>
<Link to={{ <small className="d-flex flex-row justify-content-end">
pathname: `/acheck/${localStorage.getItem('_id')}`, <div className="text-white text-right font-weight-light pr-2">{name}</div>
<NavLink className="p-0" as={Link} to={{
pathname: `/change/${localStorage.getItem('_id')}`,
state: { id: localStorage.getItem('_id') }, state: { id: localStorage.getItem('_id') },
}} className="nav-link"> }}> 비밀번호 변경 </NavLink> / <NavLink className="p-0" onClick={logout} > 로그아웃</NavLink></small>
대관 확인/취소(관리자)</Link> </NavLink>
</li>) : null} </Nav>
</ul> </Navbar.Collapse>
<div className="h-100 mr-3"> </MENU >
<div className="text-white text-right font-weight-light"><small>{name} 안녕하세요</small></div>
<div className="text-white text-right font-weight-light"><small>
<Link to={{
pathname: `/change/${user._id}`,
state: { id: user._id },
}}>비밀번호 변경</Link> / <span className="logoutBtn" onClick={logout} >로그아웃</span></small></div>
</div>
</div>
</Nav>
) )
} }
......
...@@ -108,4 +108,4 @@ function ACheck(props) { ...@@ -108,4 +108,4 @@ function ACheck(props) {
) )
} }
export default ACheck export default ACheck
\ No newline at end of file
...@@ -211,7 +211,6 @@ function Apply(props) { ...@@ -211,7 +211,6 @@ function Apply(props) {
> >
X X
</button> </button>
</div> </div>
</div> </div>
))} ))}
...@@ -237,4 +236,4 @@ function Apply(props) { ...@@ -237,4 +236,4 @@ function Apply(props) {
) )
} }
export default Apply export default Apply
\ No newline at end of file
...@@ -2,86 +2,106 @@ import React, { useState } from 'react'; ...@@ -2,86 +2,106 @@ import React, { useState } from 'react';
import { Formik } from 'formik'; import { Formik } from 'formik';
import * as Yup from 'yup'; import * as Yup from 'yup';
import axios from 'axios'; import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css'; import Menu from '../Components/Menu';
import { Link, Redirect } from 'react-router-dom'; import { Link, Redirect } from 'react-router-dom';
import { Container, Button, Col } from 'react-bootstrap';
import styled from 'styled-components';
const Check = styled.div`
& #reCheck::after {
content: '새로운 비밀번호를 다시 입력하세요';
}
& #reCheck:not(.right) {
content: '비밀번호가 일치하지 않습니다.';
color: red;
}
`
function Change(props) { function Change(props) {
const [state, setState] = useState(); const [state, setState] = useState();
const [checkPw, setCheckPw] = useState(true);
if (state) { if (state) {
return <Redirect to="/" />; return <Redirect to="/" />;
} }
console.log(props) // console.log(props)
return ( return (
<div className="d-flex flex-column justify-content-between vh-100"> <div className="">
<Formik <Menu />
initialValues={{ password: '' }} <Container fluid className="p-0 vh-90">
validationSchema={Yup.object({ <Check className="row justify-content-center m-0">
password: Yup.string() <Col md={4} className="pt-5">
.required('비밀번호를 입력해주세요.') <Formik
.min(8, '8자 이상 입력해주세요.'), initialValues={{ password: '' }}
password2: Yup.string() validationSchema={Yup.object({
.required('비밀번호를 다시 입력해주세요.') password: Yup.string()
.min(8, '8자 이상 입력해주세요.') .required('비밀번호를 입력해주세요.')
.oneOf([Yup.ref("password"), null], '비밀번호가 일치하지 않습니다.'), .min(8, '8자 이상 입력해주세요.'),
})} password2: Yup.string()
onSubmit={(values, { setSubmitting }) => { .required('비밀번호를 다시 입력해주세요.')
axios.put(`/users/change/${props.location.state.id}`, { ...values }, .min(8, '8자 이상 입력해주세요.')
) .oneOf([Yup.ref("password"), null], '비밀번호가 일치하지 않습니다.'),
.then(res => { })}
console.log(res.data); onSubmit={(values, { setSubmitting }) => {
if (res.status === 404) return alert(res.data.error) axios.put(`/users/change/${props.location.state.id}`, { ...values },
alert("회원정보가 수정되었습니다!") )
setState(true); .then(res => {
}) console.log(res.data);
.catch(err => { if (res.status === 404) return alert(res.data.error)
alert(err.error) alert("회원정보가 수정되었습니다!")
}); setState(true);
})
.catch(err => {
alert(err.error)
});
setTimeout(() => {
setSubmitting(false);
}, 400); // finish the cycle in handler
}}
>
{({
errors,
touched,
handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur
isSubmitting,
}) => (
<form onSubmit={handleSubmit} className="d-flex flex-column">
<div className="form-group">
<div className={touched.password && errors.password ? "text-danger" : ""}> 비밀번호를 입력하세요(8자리 이상)</div>
<input
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
type="password"
name="password"
{...getFieldProps('password')}
placeholder="새로운 비밀번호"
/>
</div>
<div className="form-group">
{touched.password2 && errors.password2 ? setCheckPw(false) : null}
<div id="reCheck" className={checkPw ? "right" : "err"}></div>
<input
className={(touched.password2 && errors.password2 ? 'form-control is-invalid' : "form-control")}
type="password"
name="password2"
{...getFieldProps('password2')}
placeholder="새 비밀번호를 다시 입력해주세요."
/>
</div>
<Button type="submit" variant="secondary" disabled={isSubmitting}>저장하기</Button>
</form>
)}
</Formik>
</Col>
</Check>
setTimeout(() => { </Container>
setSubmitting(false);
}, 400); // finish the cycle in handler
}}
>
{({
errors,
touched,
handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur
isSubmitting,
}) => (
<div className="row justify-content-center align-items-center">
<form onSubmit={handleSubmit} className="col-sm-3">
<div className="form-group mb-4">
<input
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
type="password"
name="password"
{...getFieldProps('password')}
placeholder="새 비밀번호를 입력해주세요."
/>
{touched.password && errors.password ? (
<div className="invalid-feedback text-left">{errors.password}</ div>
) : null}
</div>
<div className="form-group mb-4">
<input
className={(touched.password2 && errors.password2 ? 'form-control is-invalid' : "form-control")}
type="password"
name="password2"
{...getFieldProps('password2')}
placeholder="새 비밀번호를 다시 입력해주세요."
/>
{touched.password2 && errors.password2 ? (
<div className="invalid-feedback text-left">{errors.password2}</div>
) : null}
</div>
<button type="submit" className="btn btn-light" disabled={isSubmitting}>저장</button>
</form>
</div>
)}
</Formik>
</div > </div >
); );
} }
......
...@@ -2,11 +2,20 @@ import React, { useState } from 'react'; ...@@ -2,11 +2,20 @@ import React, { useState } from 'react';
import { Field, Formik } from 'formik'; import { Field, Formik } from 'formik';
import * as Yup from 'yup'; import * as Yup from 'yup';
import axios from 'axios'; import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css';
import { Link, Redirect } from 'react-router-dom'; import { Link, Redirect } from 'react-router-dom';
import styled from 'styled-components';
import { Navbar, Container, Row, Col, Button } from 'react-bootstrap';
const Menu = styled(Navbar)`
background-color: #7B031D;
a {
color : white;
}
`
function Find() { function Find() {
const [state, setState] = useState(); const [state, setState] = useState(false);
if (state) { if (state) {
return <Redirect to={{ return <Redirect to={{
...@@ -14,88 +23,90 @@ function Find() { ...@@ -14,88 +23,90 @@ function Find() {
state: { id: localStorage.getItem('_id') }, state: { id: localStorage.getItem('_id') },
}} />; }} />;
} }
return ( return (
<div className="d-flex flex-column justify-content-between vh-100"> <div className="vh-100">
<Formik <Menu expand="md" variant="dark">
initialValues={{ id: '', question: '', answer: '' }} <Navbar.Brand>비밀번호 찾기</Navbar.Brand>
validationSchema={Yup.object({ </Menu>
id: Yup.string() <Container fluid>
.required('학번을 입력해주세요.'), <Row className="justify-content-center">
answer: Yup.string() <Col md={3} xs={11} className="p-0">
.required('답변을 입력해주세요.'), <Formik
})} initialValues={{ id: '', question: '', answer: '' }}
onSubmit={(values, { setSubmitting }) => { validationSchema={Yup.object({
axios({ id: Yup.string()
method: 'post', .required('학번을 입력해주세요.'),
url: '/login/find', answer: Yup.string()
data: values, .required('답변을 입력해주세요.'),
}).then(res => { })}
if (res.status === 404) return alert(res.data.error) onSubmit={(values, { setSubmitting }) => {
localStorage.setItem('_id', res.data.users._id) axios({
setState(true); method: 'post',
}) url: '/login/find',
.catch(err => { data: values,
alert(err.error) }).then(res => {
}); if (res.status === 404) return alert(res.data.error)
localStorage.setItem('_id', res.data.users._id)
setState(true);
})
.catch(err => {
alert(err.error)
});
console.log(values);
setTimeout(() => {
setSubmitting(false);
}, 400); // finish the cycle in handler
}}
>
{({
errors,
touched,
handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur
isSubmitting,
}) => (
<form onSubmit={handleSubmit} className="d-flex flex-column pt-5">
<div className="form-group pb-2">
<div className={touched.id && errors.id ? "text-danger" : ""}>학번을 입력하세요</div>
<input
className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")}
type="number"
name="id"
{...getFieldProps('id')}
placeholder="Input Student Id"
/>
</div>
<div className="form-group pb-2">
<label className="pr-2">본인 확인 질문</label>
<Field as="select" name="question">
<option value="">질문을 선택하세요</option>
<option value="life">자신의 인생 좌우명은?</option>
<option value="school">자신이 다녔던 초등학교의 이름은?</option>
<option value="place">기억에 남는 추억의 장소는?</option>
</Field>
</div>
<div className="form-group pb-2">
<div className={touched.answer && errors.answer ? "text-danger" : ""}>답변을 입력해주세요.</div>
<input
className={(touched.answer && errors.answer ? 'form-control is-invalid' : "form-control")}
type="text"
name="answer"
{...getFieldProps('answer')}
placeholder="Input answer" />
</div>
console.log(values); <Button className="mb-2" variant="secondary" type="submit" disabled={isSubmitting}>비밀번호 찾기</Button>
setTimeout(() => { <Button variant="outline-secondary" as={Link} to="/login">로그인하러 가기</Button>
setSubmitting(false); </form>
}, 400); // finish the cycle in handler )}
}} </Formik>
> </Col>
{({ </Row>
errors, </Container >
touched, </div >
handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur
isSubmitting,
}) => (
<div className="row justify-content-center align-items-center">
<form onSubmit={handleSubmit} className="col-sm-3">
<div className="form-group mb-4">
<input
className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")}
type="number"
name="id"
{...getFieldProps('id')}
placeholder="Input Student Id"
/>
{touched.id && errors.id ? (
<div className="invalid-feedback text-left">{errors.id}</div>
) : null}
</div>
<div className="form-group mb-4">
<label>본인 확인 질문</label>
<Field as="select" name="question">
<option value="">질문을 선택하세요</option>
<option value="life">자신의 인생 좌우명은?</option>
<option value="school">자신이 다녔던 초등학교의 이름은?</option>
<option value="place">기억에 남는 추억의 장소는?</option>
</Field>
</div>
<div className="form-group mb-4">
<input
className={(touched.answer && errors.answer ? 'form-control is-invalid' : "form-control")}
type="text"
name="answer"
{...getFieldProps('answer')}
placeholder="Input answer" />
{touched.answer && errors.answer ? (
<div className="invalid-feedback text-left">{errors.answer}</div>
) : null}
</div>
<button type="submit" className="btn btn-dark" disabled={isSubmitting}>
submit
</button>
<button><Link to="/login">로그인</Link></button>
<button><Link to="/"></Link></button>
</form>
</div>
)}
</Formik>
</div>
); );
} }
......
...@@ -5,7 +5,7 @@ import { Formik } from 'formik'; ...@@ -5,7 +5,7 @@ import { Formik } from 'formik';
import * as Yup from 'yup'; import * as Yup from 'yup';
import axios from 'axios'; import axios from 'axios';
import Logo from '../icon.png'; import Logo from '../icon.png';
import { Container, Row } from 'react-bootstrap'; import { Container, Row, Button } from 'react-bootstrap';
const Col_1 = styled.div` const Col_1 = styled.div`
background-color: #7B031D; background-color: #7B031D;
...@@ -37,11 +37,12 @@ const Col_1 = styled.div` ...@@ -37,11 +37,12 @@ const Col_1 = styled.div`
const Col_2 = styled.div` const Col_2 = styled.div`
background-color: rgb(239, 218, 200); background-color: rgb(239, 218, 200);
a { a {
color : #7B031D; color : #7B031D;
} }
&.mob-formik { & .mob-formik {
height : 80vh; height : 80vh;
width: 100%; width: 100%;
display: flex; display: flex;
...@@ -49,42 +50,40 @@ const Col_2 = styled.div` ...@@ -49,42 +50,40 @@ const Col_2 = styled.div`
align-items: center; align-items: center;
} }
&.web-formik { & .web-form {
height: 100%; height: 100%;
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
} }
& .mobb { & .mob-container {
height: 35vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
justify-content: space-around;
} }
& .webb { & .webb {
flex-direction: column; flex-direction: column;
} }
& .qwer { & .web-container {
display: flex; display: flex;
justify-content: space-between;
height: 12vh; height: 12vh;
width: 30vw; width: 30vw;
margin-bottom: 25px;
} }
& .web-input-form { & .web-input-form {
width: 80%; width: 80%;
justify-content: space-between;
align-content: space-around;
flex-direction: column;
display: flex; display: flex;
flex-direction: column;
justify-content: space-around;
} }
& .mob-input-form { & .mob-input-form {
display: flex;
flex-direction: column;
justify-content: space-around;
} }
` `
...@@ -105,7 +104,7 @@ function Login() { ...@@ -105,7 +104,7 @@ function Login() {
} }
return ( return (
<Container fluid className="p-0"> <Container fluid className="p-0">
<Row className="vw-100 vh-100 m-0" > <Row className="vw-100 vh-100 m-0 " >
<Col_1 className={"col-md-4 col-12" + (mobile ? " mobile" : " web")}> <Col_1 className={"col-md-4 col-12" + (mobile ? " mobile" : " web")}>
<div className={mobile ? "mob-head" : ""}> <div className={mobile ? "mob-head" : ""}>
<img className={mobile ? "mob-img" : "img-fluid"} src={Logo} /> <img className={mobile ? "mob-img" : "img-fluid"} src={Logo} />
...@@ -114,7 +113,7 @@ function Login() { ...@@ -114,7 +113,7 @@ function Login() {
</div> </div>
</div> </div>
</Col_1> </Col_1>
<Col_2 className={"col-md-8 col-12" + (mobile ? " mob-formik p-0" : " web-formik")}> <Col_2 className="col-md-8 col-12" >
<Formik <Formik
initialValues={{ id: '', password: '' }} initialValues={{ id: '', password: '' }}
validationSchema={Yup.object({ validationSchema={Yup.object({
...@@ -153,35 +152,37 @@ function Login() { ...@@ -153,35 +152,37 @@ function Login() {
getFieldProps, // contain values, handleChange, handleBlur getFieldProps, // contain values, handleChange, handleBlur
isSubmitting, isSubmitting,
}) => ( }) => (
<form onSubmit={handleSubmit} className={mobile ? "w-75 h-50vh" : "d-flex webb"}> <div className={mobile ? " mob-formik p-0" : " web-form"}>
<div className={mobile ? "mobb" : "qwer"}> <form onSubmit={handleSubmit} className={mobile ? "w-75" : "d-flex webb"}>
<div className={(mobile ? "mob-" : "web-") + "input-form"}> <div className={mobile ? "mob-container" : "web-container"}>
<div className={"form-group m-0" + (mobile ? " mb-2" : "")}> <div className={mobile ? "mob-input-form" : "web-input-form mr-2"}>
<input <div className={"form-group m-0" + (mobile ? " mb-2" : " ")}>
className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")} <input
type="number" className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")}
name="id" type="number"
{...getFieldProps('id')} name="id"
placeholder="Input Student Id" {...getFieldProps('id')}
/> placeholder="Input Student Id"
</div> />
<div className="form-group m-0"> </div>
<input <div className={"form-group m-0"+ (mobile ? " mb-2" : " ")}>
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")} <input
type="password" className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
name="password" type="password"
{...getFieldProps('password')} name="password"
placeholder="Input Password" {...getFieldProps('password')}
/> placeholder="Input Password"
/>
</div>
</div> </div>
<Button type="submit" variant="dark" className={mobile ? " w-100" : " w-20"} disabled={isSubmitting}> Login </Button>
</div> </div>
<button type="submit" className={"btn btn-dark" + (mobile ? " w-100" : " w-20")} disabled={isSubmitting}> Login </button>
</div>
<div><Link to="/find">비밀번호를 잊으셨나요?</Link></div> <div><Link to="/find">비밀번호를 잊으셨나요?</Link></div>
<div><Link to="/signup">회원이 아니신가요?</Link></div> <div><Link to="/signup">회원이 아니신가요?</Link></div>
</form> </form>
</div>
)} )}
</Formik> </Formik>
</Col_2> </Col_2>
......
import React, { useState, useEffect, useRef } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import Menu from '../Components/Menu'; import Menu from '../Components/Menu';
import axios from 'axios'; import axios from 'axios';
import styled from 'styled-components'; import { Link } from 'react-router-dom';
import { Container, Row, Col, Card, Accordion, Button } from 'react-bootstrap';
function Notice() { function Notice() {
const [notices, setNotices] = useState([]); const [notices, setNotices] = useState([]);
...@@ -27,9 +28,8 @@ function Notice() { ...@@ -27,9 +28,8 @@ function Notice() {
axios.get(`/notices`) axios.get(`/notices`)
.then(res => { .then(res => {
if (res.status !== 201) { if (res.status !== 201) {
alert(res.data.error); // alert(res.data.error);
} }
console.log(res.data);
setNotices(res.data); setNotices(res.data);
}) })
.catch(err => { .catch(err => {
...@@ -39,46 +39,24 @@ function Notice() { ...@@ -39,46 +39,24 @@ function Notice() {
return ( return (
<div> <div>
<Menu /> <Menu />
<div className="container-fluid"> <Container fluid>
<div className="row justify-content-center vw-100 vh-90"> <Row className="justify-content-center vw-100 vh-90">
<div className="col-md-7 col-12"> <Col md={7}>
<h2 className="p-3 border-bottom">공지사항 <Link to="/write"> 작성</Link></h2>
<h2 className="p-3 border-bottom">공지사항</h2> <Accordion>
{notices.map((notice, index) =>
<div id="accordion pt-1"> <Card>
<div class="card"> <Card.Header>
<div class="card-header" id="headingOne"> <Accordion.Toggle as={Button} variant="link" eventKey={index + 1}>{notice.notice_title} <span className="text-right">{dateForm(notice.post_date)}</span></Accordion.Toggle>
<h5 class="mb-0"> </Card.Header>
<button class="btn btn-link" data-toggle="collapse" data-target="#collapseOne" aria-expanded="true" aria-controls="collapseOne"> <Accordion.Collapse eventKey={index + 1}>
Collapsible Group Item #1 <Card.Body>{notice.notice_content}</Card.Body>
</button> </Accordion.Collapse>
</h5> </Card>)}
</div> </Accordion>
</Col>
<div id="collapseOne" class="collapse show" aria-labelledby="headingOne" data-parent="#accordion"> </Row>
<div class="card-body"> </Container>
Anim pariatur cliche reprehenderit, enim eiusmod high life accusamus terry richardson ad squid. 3 wolf moon officia aute, non cupidatat skateboard dolor brunch. Food truck quinoa nesciunt laborum eiusmod. Brunch 3 wolf moon tempor, sunt aliqua put a bird on it squid single-origin coffee nulla assumenda shoreditch et. Nihil anim keffiyeh helvetica, craft beer labore wes anderson cred nesciunt sapiente ea proident. Ad vegan excepteur butcher vice lomo. Leggings occaecat craft beer farm-to-table, raw denim aesthetic synth nesciunt you probably haven't heard of them accusamus labore sustainable VHS.
</div>
</div>
</div>
{/* {notices.map((notice, index) =>
<div className="card">
<div className="card-header" id={"Hnotice_" + index}>
<div className="row card-link collapsed" data-toggle="collapse" data-target={"#notice_" + index} aria-expanded="false" aria-controls={"notice_" + index}>
<div className="col-6 p-0">{notice.notice_title}</div>
<div className="col-3 p-0 text-center">{notice.notice_author}</div>
<div className="col-3 p-0 text-right">{dateForm(notice.post_date)}</div>
</div>
</div>
<div id={"notice_" + index} aria-labelledby={"Hnotice_" + index} className="collapse" data-parent="#accordion">
<div className="card-body">{notice.notice_content}</div>
</div>
</div>
)} */}
</div>
</div>
</div >
</div >
</div> </div>
) )
} }
......
...@@ -2,16 +2,15 @@ import React, { useState } from 'react'; ...@@ -2,16 +2,15 @@ import React, { useState } from 'react';
import { Field, Formik } from 'formik'; import { Field, Formik } from 'formik';
import * as Yup from 'yup'; import * as Yup from 'yup';
import axios from 'axios'; import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css';
import { Link, Redirect } from 'react-router-dom'; import { Link, Redirect } from 'react-router-dom';
import styled from 'styled-components'; import styled from 'styled-components';
import { Col, Container, Navbar, Button } from 'react-bootstrap';
const Nav = styled.nav` const Menu = styled(Navbar)`
background-color: #7B031D; background-color: #7B031D;
height: 10vh;
a { a {
color: #ffffff; color : white;
} }
` `
...@@ -23,7 +22,7 @@ const Wow = styled.div` ...@@ -23,7 +22,7 @@ const Wow = styled.div`
} }
& #reCheck:not(.right) { & #reCheck:not(.right) {
content: '비밀번호가 다릅니다.'; content: '비밀번호가 일치하지 않습니다.';
color: red; color: red;
} }
...@@ -40,15 +39,14 @@ function Signup() { ...@@ -40,15 +39,14 @@ function Signup() {
if (state) { if (state) {
return <Redirect to="/login" />; return <Redirect to="/login" />;
} }
return ( return (
<div className="vh-100"> <div className="vh-100">
<Nav className="navbar sticky-top navbar-expand-md"> <Menu expand="md" variant="dark">
<a class="navbar-brand" href="#">회원가입</a> <Navbar.Brand>회원가입</Navbar.Brand>
</Nav> </Menu>
<div className="container-fluid"> <Container fluid>
<Wow className="row justify-content-center rrooww"> <Wow className="row justify-content-center">
<div className="col-md-4 col-12 d-flex align-items-center h-100"> <Col md={3} xs={11} className="p-0">
<Formik <Formik
initialValues={{ name: '', id: '', password: '', password2: '', question: '', answer: '' }} initialValues={{ name: '', id: '', password: '', password2: '', question: '', answer: '' }}
validationSchema={Yup.object({ validationSchema={Yup.object({
...@@ -94,10 +92,7 @@ function Signup() { ...@@ -94,10 +92,7 @@ function Signup() {
isSubmitting, isSubmitting,
}) => ( }) => (
< form onSubmit={handleSubmit} className="asd"> < form onSubmit={handleSubmit} className="asd">
{/* col-sm-3 */}
<div className="form-group "> <div className="form-group ">
{/* mb-4 */}
<div className={touched.name && errors.name ? "text-danger" : ""}>이름을 입력하세요</div> <div className={touched.name && errors.name ? "text-danger" : ""}>이름을 입력하세요</div>
<input <input
className={(touched.name && errors.name ? 'form-control is-invalid' : "form-control")} className={(touched.name && errors.name ? 'form-control is-invalid' : "form-control")}
...@@ -106,10 +101,9 @@ function Signup() { ...@@ -106,10 +101,9 @@ function Signup() {
{...getFieldProps('name')} {...getFieldProps('name')}
placeholder="이름" /> placeholder="이름" />
</div> </div>
<div className="form-group"> <div className="form-group">
{/* mb-4 */}
<div className={touched.id && errors.id ? "text-danger" : ""}>학번을 입력하세요</div> <div className={touched.id && errors.id ? "text-danger" : ""}>학번을 입력하세요</div>
<input <input
className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")} className={(touched.id && errors.id ? 'form-control is-invalid' : "form-control")}
type="text" type="text"
...@@ -117,14 +111,10 @@ function Signup() { ...@@ -117,14 +111,10 @@ function Signup() {
{...getFieldProps('id')} {...getFieldProps('id')}
placeholder="학번/교번" placeholder="학번/교번"
/> />
{/* {touched.id && errors.id ? (
<div className="invalid-feedback text-left">{errors.id}</div>
) : null} */}
</div> </div>
<div className="form-group"> <div className="form-group">
{/* mb-4 */}
<div className={touched.password && errors.password ? "text-danger" : ""}>비밀번호를 입력하세요(8자리 이상)</div> <div className={touched.password && errors.password ? "text-danger" : ""}>비밀번호를 입력하세요(8자리 이상)</div>
<input <input
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")} className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
type="password" type="password"
...@@ -132,12 +122,9 @@ function Signup() { ...@@ -132,12 +122,9 @@ function Signup() {
{...getFieldProps('password')} {...getFieldProps('password')}
placeholder="비밀번호" placeholder="비밀번호"
/> />
{/* {touched.password && errors.password ? (
<div className="invalid-feedback text-left">{errors.password}</div>
) : null} */}
</div> </div>
<div className="form-group"> <div className="form-group">
{/* mb-4 */}
{touched.password2 && errors.password2 ? setCheckPw(false) : null} {touched.password2 && errors.password2 ? setCheckPw(false) : null}
<div id="reCheck" className={checkPw ? "right" : "err"}></div> <div id="reCheck" className={checkPw ? "right" : "err"}></div>
<input <input
...@@ -147,10 +134,9 @@ function Signup() { ...@@ -147,10 +134,9 @@ function Signup() {
{...getFieldProps('password2')} {...getFieldProps('password2')}
placeholder="비밀번호 확인" placeholder="비밀번호 확인"
/> />
</div> </div>
<div className="form-group"> <div className="form-group">
{/* mb-4 */}
<label>본인 확인 질문</label> <label>본인 확인 질문</label>
<Field as="select" name="question"> <Field as="select" name="question">
<option value="">질문을 선택하세요</option> <option value="">질문을 선택하세요</option>
...@@ -160,9 +146,7 @@ function Signup() { ...@@ -160,9 +146,7 @@ function Signup() {
</Field> </Field>
</div> </div>
<div className="form-group"> <div className="form-group">
{/* mb-4 */}
<div className={touched.answer && errors.answer ? "text-danger" : ""}>답변을 입력해주세요.</div> <div className={touched.answer && errors.answer ? "text-danger" : ""}>답변을 입력해주세요.</div>
<input <input
className={(touched.answer && errors.answer ? 'form-control is-invalid' : "form-control")} className={(touched.answer && errors.answer ? 'form-control is-invalid' : "form-control")}
type="text" type="text"
...@@ -170,19 +154,17 @@ function Signup() { ...@@ -170,19 +154,17 @@ function Signup() {
{...getFieldProps('answer')} {...getFieldProps('answer')}
placeholder="Input answer" /> placeholder="Input answer" />
</div> </div>
<button type="submit" className="btn btn-dark" disabled={isSubmitting}>회원가입</button> <Button type="submit" variant="secondary" disabled={isSubmitting}>회원가입</Button>
<button class="btn btn-light"><Link to="/login">로그인</Link></button> <Button variant="outline-secondary" as={Link} to="/login">로그인하러 가기</Button>
<button class="btn btn-light"><Link to="/"></Link></button>
</form> </form>
)} )}
</Formik> </Formik>
</div> </Col>
</Wow> </Wow>
</div> </Container>
</div > </div >
); );
} }
export default Signup; export default Signup;
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { Link, Redirect } from 'react-router-dom';
import Menu from '../Components/Menu';
import * as Yup from 'yup';
import axios from 'axios';
import { Container, Row, Col } from 'react-bootstrap';
import { Field, Formik } from 'formik';
function Write() {
const [submitData, setSubmitData] = useState(false);
const [state, setState] = useState(false);
if (state) {
return <Redirect to="/notice" />;
}
return (
<div>
<Menu />
<Container fluid>
<Row className="justify-content-center">
<Col md={12} xl={8} style={{ height: "35em" }}>
<Formik
initialValues={{ title: '', content: '' }}
validationSchema={Yup.object({
title: Yup.string()
.required('제목을 입력해주세요.'),
content: Yup.string()
.required('내용을 입력해주세요.'),
})}
onSubmit={(values, { setSubmitting }) => {
axios({
method: 'post',
url: '/writes',
data: values,
}).then(res => {
if (res.status === 404) return alert(res.data.error)
alert("공지 등록이 완료되었습니다.")
setState(true);
})
.catch(err => {
alert(err.error)
});
setTimeout(() => {
setSubmitting(false);
}, 400); // finish the cycle in handler
}}
>{({
errors,
touched,
handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur
isSubmitting,
}) => (
<form onSubmit={handleSubmit} className="asd">
{/* col-sm-3 */}
<div className="form-group">
{/* mb-4 */}
<div className={touched.name && errors.name ? "text-danger" : ""}>제목</div>
<input className={(touched.name && errors.name ? 'form-control is-invalid' : "form-control")}
type="text"
title="title"
{...getFieldProps('title')}
placeholder="제목" />
</div>
<div className="form-group ">
{/* mb-4 */}
<div className={touched.name && errors.name ? "text-danger" : ""}>내용</div>
<input className={(touched.name && errors.name ? 'form-control is-invalid' : "form-control")}
type="text"
content="content"
{...getFieldProps('content')}
placeholder="내용" />
</div>
<button type="submit" className="btn btn-dark" disabled={isSubmitting}>공지 등록</button>
</form>
)}
</Formik>
</Col>
</Row>
</Container>
</div>
)
}
export default Write
...@@ -16,13 +16,14 @@ import Apply from './Pages/ApplyPage'; ...@@ -16,13 +16,14 @@ import Apply from './Pages/ApplyPage';
import Check from './Pages/CheckPage'; import Check from './Pages/CheckPage';
import Notice from './Pages/NoticePage'; import Notice from './Pages/NoticePage';
import ACheck from './Pages/ACheckPage'; import ACheck from './Pages/ACheckPage';
import Write from './Pages/WritePage';
axios.defaults.validateStatus = function (status) { axios.defaults.validateStatus = function (status) {
return status < 500; // default return status < 500; // default
} }
ReactDOM.render( ReactDOM.render(
<Router> <Router>
<Switch> <Switch>
<PrivateRoute exact path="/" component={Home} /> <PrivateRoute exact path="/" component={Home} />
<Route path="/login" component={Login} /> <Route path="/login" component={Login} />
...@@ -32,11 +33,12 @@ ReactDOM.render( ...@@ -32,11 +33,12 @@ ReactDOM.render(
<Route path="/change" component={Change} /> <Route path="/change" component={Change} />
<Route path="/apply/:id" component={Apply} /> <Route path="/apply/:id" component={Apply} />
<Route path="/check/:id" component={Check} /> <Route path="/check/:id" component={Check} />
<Route path="/write" component={Write} />
<Route path="/notice" component={Notice} /> <Route path="/notice" component={Notice} />
<Route path="/acheck/:id" component={ACheck} /> <Route path="/acheck/:id" component={ACheck} />
<Redirect path="/" to="/" />
<Redirect path="/home" to="/" /> <Redirect path="/home" to="/" />
<Redirect path="/change/:id" to="/change"/> <Redirect path="/change/:id" to="/change" />
<Redirect path="/notice" to="/notice" />
</Switch> </Switch>
</Router>, </Router>,
document.getElementById('root') document.getElementById('root')
......
...@@ -10,6 +10,7 @@ router.get('/', function (req, res, next) { ...@@ -10,6 +10,7 @@ router.get('/', function (req, res, next) {
}) })
.catch((err) => { .catch((err) => {
console.error(err); console.error(err);
next(err); next(err);
}); });
// res.status(404).json({error:"없음."}) // res.status(404).json({error:"없음."})
......
const express = require('express');
// const path = require('path');
// const multer = require('multer');
// const fs = require('fs');
const Notice = require('../schemas/notice');
const router = express.Router();
router.post('/', function (req, res, next) {
console.log("writes req.body", req.body)
const notice = new Notice({
notice_title: req.body.title,
notice_author: "예진",
notice_content: req.body.content
});
console.log(notice);
notice.save()
.then((result) => {
console.log(result);
res.status(201).json(result);
})
.catch((err) => {
console.error(err);
next(err);
});
});
module.exports = router;
...@@ -49,4 +49,4 @@ const reserveSchema = new Schema({ ...@@ -49,4 +49,4 @@ const reserveSchema = new Schema({
}, },
}); });
module.exports = mongoose.model('Reserve', reserveSchema); module.exports = mongoose.model('Reserve', reserveSchema);
\ 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