Commit 96c994a0 authored by Choi Ga Young's avatar Choi Ga Young
Browse files

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

parents 5451fbf3 13004059
const createError = require('http-errors'); // const createError = require('http-errors');
const express = require('express'); const express = require('express');
const path = require('path'); const path = require('path');
const cookieParser = require('cookie-parser'); const cookieParser = require('cookie-parser');
const logger = require('morgan'); const logger = require('morgan');
const port = 3030;
require('dotenv').config();
const indexRouter = require('./routes/index'); const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users'); const usersRouter = require('./routes/users');
const loginRouter = require('./routes/login'); 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();
const port = 3030;
require('dotenv').config();
connect(); connect();
app.listen(port, () => console.log(port));
// view engine setup // view engine setup
// app.set('views', path.join(__dirname, 'views')); // app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'pug'); // app.set('view engine', 'pug');
...@@ -28,7 +24,7 @@ app.listen(port, () => console.log(port)); ...@@ -28,7 +24,7 @@ app.listen(port, () => console.log(port));
app.use(logger('dev')); app.use(logger('dev'));
app.use(express.json()); app.use(express.json());
app.use(express.urlencoded({ extended: false })); app.use(express.urlencoded({ extended: false }));
app.use(cookieParser()); app.use(cookieParser(process.env.JWT_SECRET));
app.use(express.static(path.join(__dirname, 'public'))); app.use(express.static(path.join(__dirname, 'public')));
app.use('/', indexRouter); app.use('/', indexRouter);
...@@ -36,7 +32,9 @@ app.use('/users', usersRouter, reservesRouter); ...@@ -36,7 +32,9 @@ 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));
// catch 404 and forward to error handler // catch 404 and forward to error handler
app.use(function(req, res, next) { app.use(function(req, res, next) {
...@@ -54,4 +52,4 @@ app.use(function(err, req, res, next) { ...@@ -54,4 +52,4 @@ app.use(function(err, req, res, next) {
// res.render('error'); // res.render('error');
}); });
module.exports = app; module.exports = app;
\ No newline at end of file
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, NavDropdown } from 'react-bootstrap';
const Nav = styled.nav` const MENU = styled(Navbar)`
background-color: #7B031D; background-color: #7B031D;
height: 6vh;
a {
color: #ffffff;
}
& .logoutBtn:hover {
text-decoration: underline;
}
` `
function Menu() { function Menu() {
const [state, setState] = useState() const [state, setState] = useState()
const name = localStorage.getItem('name'); const name = localStorage.getItem('name');
if (state) return <Redirect to="/" />;
function logout() { function logout() {
localStorage.clear(); localStorage.clear();
alert("로그아웃 되었습니다."); alert("로그아웃 되었습니다.");
setState(true); setState(true);
} }
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" />
<Navbar.Collapse id="basic-navbar-nav">
<Nav className="mr-auto">
<Nav.Link><Link to="/notice">공지사항</Link></Nav.Link>
<Nav.Link><Link to="/home">대관 현황</Link></Nav.Link>
<Nav.Link><Link to={{
pathname: `/apply/${localStorage.getItem('_id')}`,
state: { id: localStorage.getItem('_id') },
}} className="nav-link">대관 신청</Link></Nav.Link>
<Nav.Link><Link to={{
pathname: `/check/${localStorage.getItem('_id')}`,
state: { id: localStorage.getItem('_id') },
}} className="nav-link">
대관 확인/취소</Link></Nav.Link>
<Nav.Link><Link to={{
pathname: `/acheck/${localStorage.getItem('_id')}`,
state: { id: localStorage.getItem('_id') },
}} className="nav-link">
대관 확인/취소(관리자)</Link></Nav.Link>
<Nav.Link>
<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/${localStorage.getItem('_id')}`,
state: { id: localStorage.getItem('_id') },
}}>비밀번호 변경</Link> / <span className="logoutBtn" onClick={logout} >로그아웃</span></small></div>
</Nav.Link>
</Nav>
</Navbar.Collapse>
{/* <button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar" aria-controls="collapsibleNavbar">
<span className="navbar-toggler-icon"></span> <span className="navbar-toggler-icon"></span>
</button> </button> */}
<div className="collapse navbar-collapse justify-content-between" id="collapsibleNavbar"> {/* <div className="collapse navbar-collapse justify-content-between" id="collapsibleNavbar">
<ul className="navbar-nav"> <ul className="navbar-nav">
<li className="nav-item"> <li className="nav-item">
<Link to="/notice" className="nav-link">공지사항</Link> <Link to="/notice" className="nav-link">공지사항</Link>
...@@ -70,8 +94,8 @@ function Menu() { ...@@ -70,8 +94,8 @@ function Menu() {
state: { id: localStorage.getItem('_id') }, state: { id: localStorage.getItem('_id') },
}}>비밀번호 변경</Link> / <span className="logoutBtn" onClick={logout} >로그아웃</span></small></div> }}>비밀번호 변경</Link> / <span className="logoutBtn" onClick={logout} >로그아웃</span></small></div>
</div> </div>
</div> </div> */}
</Nav> </MENU >
) )
} }
......
import React, { useState, useEffect, useRef } from 'react';
import Calendar from '@toast-ui/react-calendar';
import "tui-calendar/dist/tui-calendar.css";
import "tui-date-picker/dist/tui-date-picker.css";
import "tui-time-picker/dist/tui-time-picker.css";
function Cal(calledday) {
const calendarRef = useRef();
const [day, setDay] = useState(calledday);
const [myTheme, setMyTheme] = useState({
'common.dayname.color': '#333',
'common.today.color': '#333',
// 'common.creationGuide.color': 'white',
'common.creationGuide.backgroundColor': 'gray',
// Theme object to extends default dark theme.
});
useEffect(() => {
// const cal = calendarRef.current.getInstance();
// cal.setDate(new Date(day));
// cal.changeView('week', false);
// cal.today(new Date(day));
// calendar.on('clickSchedule', function (event) {
// const schedule = event.schedule;
// if (lastClickSchedule) {
// calendar.updateSchedule(lastClickSchedule.id, lastClickSchedule.calendarId, {
// isFocused: false,
// });
// }
// calendar.updateSchedule(schedule.id, schedule.calendarId, {
// isFocused: true,
// });
// lastClickSchedule = schedule;
// // open detail view
// return (console.log(isFocused))
// });
}, [day])
return (
<Calendar
height="100%"
calendars={[
{
id: 'Subject',
bgColor: '#a9a9a9',
borderColor: '#a9a9a9',
isReadOnly: 'true'
}
]}
view="week"
disableDblClick={false}
disableClick={true}
isReadOnly={false}
// template={
// popupIsAllDay=function {
// return display: "none"
// }
// }
schedules={[
{
id: '1',
calendarId: 'Subject',
category: 'time',
start: '2020-10-05T11:00:00',
end: '2020-10-05T12:00:00',
},
{
id: '2',
calendarId: 'Subject',
category: 'time',
start: '2020-10-09T10:00:00',
end: '2020-10-09T11:00:00',
},
{
id: '3',
calendarId: 'Subject',
category: 'time',
start: '2020-10-08T11:00:00',
end: '2020-10-08T15:00:00',
}
]}
scheduleView={['time']}
taskView={false}
theme={myTheme}
timezones={[
{
timezoneOffset: 540,
displayLabel: 'GMT+09:00',
tooltip: 'Seoul'
},
]}
useDetailPopup
useCreationPopup
view={"week"}
week={{
workweek: true,
hourStart: 8,
hourEnd: 23
}}
/>
)
}
export default Cal
\ No newline at end of file
...@@ -2,11 +2,21 @@ import React, { useState } from 'react'; ...@@ -2,11 +2,21 @@ 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 { Container, Row, Col } from 'react-bootstrap';
const Nav = styled.nav`
background-color: #7B031D;
height: 10vh;
a {
color: #ffffff;
}
`
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 +24,96 @@ function Find() { ...@@ -14,88 +24,96 @@ 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 <Nav className="navbar sticky-top navbar-expand-md">
initialValues={{ id: '', question: '', answer: '' }} <a class="navbar-brand" href="#">비밀번호 찾기</a>
validationSchema={Yup.object({ </Nav>
id: Yup.string() <Container fluid>
.required('학번을 입력해주세요.'), <Row className="justify-content-center rrooww">
answer: Yup.string() <Col md={4} className="d-flex align-items-center h-100">
.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); console.log(values);
setTimeout(() => { setTimeout(() => {
setSubmitting(false); setSubmitting(false);
}, 400); // finish the cycle in handler }, 400); // finish the cycle in handler
}} }}
> >
{({ {({
errors, errors,
touched, touched,
handleSubmit, handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur getFieldProps, // contain values, handleChange, handleBlur
isSubmitting, isSubmitting,
}) => ( }) => (
<div className="row justify-content-center align-items-center"> <Row className="justify-content-center align-items-center">
<form onSubmit={handleSubmit} className="col-sm-3"> <form onSubmit={handleSubmit}>
<div className="form-group mb-4"> <Col sm={3}>
<input <div className="form-group mb-4">
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"
{touched.id && errors.id ? ( />
<div className="invalid-feedback text-left">{errors.id}</div> {touched.id && errors.id ? (
) : null} <div className="invalid-feedback text-left">{errors.id}</div>
</div> ) : null}
<div className="form-group mb-4"> </div>
<label>본인 확인 질문</label> <div className="form-group mb-4">
<Field as="select" name="question"> <label>본인 확인 질문</label>
<option value="">질문을 선택하세요</option> <Field as="select" name="question">
<option value="life">자신의 인생 좌우명은?</option> <option value="">질문을 선택하세요</option>
<option value="school">자신이 다녔던 초등학교의 이름은?</option> <option value="life">자신의 인생 좌우명은?</option>
<option value="place">기억에 남는 추억의 장소는?</option> <option value="school">자신이 다녔던 초등학교의 이름은?</option>
</Field> <option value="place">기억에 남는 추억의 장소는?</option>
</div> </Field>
<div className="form-group mb-4"> </div>
<input <div className="form-group mb-4">
className={(touched.answer && errors.answer ? 'form-control is-invalid' : "form-control")} <input
type="text" className={(touched.answer && errors.answer ? 'form-control is-invalid' : "form-control")}
name="answer" type="text"
{...getFieldProps('answer')} name="answer"
placeholder="Input answer" /> {...getFieldProps('answer')}
{touched.answer && errors.answer ? ( placeholder="Input answer" />
<div className="invalid-feedback text-left">{errors.answer}</div> {touched.answer && errors.answer ? (
) : null} <div className="invalid-feedback text-left">{errors.answer}</div>
</div> ) : null}
<button type="submit" className="btn btn-dark" disabled={isSubmitting}> </div>
submit <button type="submit" className="btn btn-dark" disabled={isSubmitting}>submit </button>
</button> <button><Link to="/login">로그인</Link></button>
<button><Link to="/login">로그인</Link></button> <button><Link to="/"></Link></button>
<button><Link to="/"></Link></button> </Col>
</form> </form>
</div> </Row>
)} )}
</Formik> </Formik>
</div> </Col>
</Row>
</Container >
</div >
); );
} }
......
import React, { useState, useEffect } from 'react'; import React, { useState, useEffect, useRef } from 'react';
import Menu from '../Components/Menu'; import Menu from '../Components/Menu';
import { Link, Redirect } from 'react-router-dom'; import Schedule from '../Components/Schedule';
import styled from 'styled-components';
import moment from 'moment';
import "moment/locale/ko";
moment.locale("ko", {
week: {
dow: 1
}
});
const Drop = styled.div`
& button {
border solid 1px;
}
`
const Tab = styled.ul`
& a, a:hover, a:active {
color: black;
}
`
function Home() { function Home() {
const [show, setShow] = useState(false);
const [weeks, setWeeks] = useState([]);
const [days, setDays] = useState([]);
const [sendDate, setSendDate] = useState(null);
useEffect(() => {
Dateform();
}, []);
function Dateform() {
let today = moment();
let weeks = [];
let dates = [];
let sendDates = [];
for (let i = 0; i < 6; i++) {
if (i !== 0) {
today.add(7, 'd');
}
let date = { start: null, end: null };
date.start = today.startOf('week').format("MMM Do");
date.end = today.endOf('week').weekday(4).format("MMM Do");
dates.push(date);
const week = date.start + " ~ " + date.end;
weeks.push(week);
let sendDate = today.startOf('week').format("YYYY-MM-DD");
sendDates.push(sendDate);
};
setWeeks([...weeks])
setDays([...sendDates])
};
function choose(e, index) {
setShow(true)
setSendDate(days[index])
}
return ( return (
<div> <div>
<Menu /> <Menu />
<div className="container"> <div className="container mt-3">
home <h2>대관 현황</h2>
<button><Link to="/login">로그인</Link></button> <p>
<button><Link to="/signup">회원가입</Link></button> <strong>대관 가능 시간</strong>
<ul>
<li>평일: 9 - 22/ 예약가능 시간 이후 폐쇄</li>
<li>주말: 이용 불가</li>
</ul>
</p>
<Drop className="row dropdown mt-1 mb-2">
<button className="btn btn-lg dropdown-toggle mx-auto col-5" type="button" id="dropdownMenuButton" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
기간을 선택해주십시오.
</button>
<div className="dropdown-menu col-5" aria-labelledby="dropdownMenuButton">
{weeks.map((week, index) => (
<a className="dropdown-item" id={index} onClick={(e) => choose(e, index)}>{week}</a>
))}
</div>
</Drop>
<Tab className="nav nav-tabs nav-justified mt-4" id="myTab" role="tablist" style={show ? {} : { display: "none" }}>
<li className="nav-item">
<a className="nav-link active" id="7-tab" data-toggle="tab" href="#tab-7" role="tab" aria-controls="7" aria-selected="true"> 7-223 </a>
</li>
<li className="nav-item">
<a className="nav-link" id="9-tab" data-toggle="tab" href="#tab-9" role="tab" aria-controls="9" aria-selected="false"> 9-116 </a>
</li>
<li className="nav-item">
<a className="nav-link" id="25-tab" data-toggle="tab" href="#tab-25" role="tab" aria-controls="25" aria-selected="false"> 25-307 </a>
</li>
</Tab>
<div className="tab-content row justify-content-center" id="myTabContent" style={show ? {} : { display: "none" }}>
<div className="tab-pane fade show active col-md-11 col-12" id="tab-7" role="tabpanel" aria-labelledby="7-tab">
<Schedule day={sendDate}/>
</div>
<div className="tab-pane fade col-md-11 col-12" id="tab-9" role="tabpanel" aria-labelledby="9-tab">
<Schedule day={sendDate}/>
</div>
<div className="tab-pane fade col-md-11 col-12" id="tab-25" role="tabpanel" aria-labelledby="25-tab">
<Schedule day={sendDate}/>
</div>
</div>
<h3>유의사항</h3>
<p>
<ul>
<li>강의실을 대관하는 대표자를 기준으로 최대 6시간까지 대관이 가능합니다.</li>
<li>1 대관시 최대 3시간까지 이용이 가능합니다. (1시간 단위로 대관 가능)</li>
<li><strong style={{ color: "red" }}>대관 시간 이외 강의실을 이용하다 적발될 경우 한달 강의실 이용이 불가합니다.</strong></li>
</ul>
</p>
<div className="bg-white">
<h6>고려대학교 대관시스템</h6>
</div>
</div> </div>
</div> </div>
) )
} }
export default Home export default Home;
\ No newline at end of file \ No newline at end of file
...@@ -4,10 +4,10 @@ import { Link, Redirect } from 'react-router-dom'; ...@@ -4,10 +4,10 @@ import { Link, Redirect } from 'react-router-dom';
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 Logo from '../icon.png'; import Logo from '../icon.png';
import { Container, Row } from 'react-bootstrap';
const Asd = styled.div` const Col_1 = styled.div`
background-color: #7B031D; background-color: #7B031D;
&.web { &.web {
...@@ -35,13 +35,14 @@ const Asd = styled.div` ...@@ -35,13 +35,14 @@ const Asd = styled.div`
} }
` `
const Asdf = 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,14 +50,14 @@ const Asdf = styled.div` ...@@ -49,14 +50,14 @@ const Asdf = 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; height: 35vh;
display: flex; display: flex;
flex-direction: column; flex-direction: column;
...@@ -67,7 +68,7 @@ const Asdf = styled.div` ...@@ -67,7 +68,7 @@ const Asdf = styled.div`
flex-direction: column; flex-direction: column;
} }
& .qwer { & .web-container {
display: flex; display: flex;
justify-content: space-between; justify-content: space-between;
height: 12vh; height: 12vh;
...@@ -84,7 +85,10 @@ const Asdf = styled.div` ...@@ -84,7 +85,10 @@ const Asdf = styled.div`
} }
& .mob-input-form { & .mob-input-form {
display: flex;
flex-direction: column;
justify-content: space-around;
} }
` `
...@@ -104,89 +108,93 @@ function Login() { ...@@ -104,89 +108,93 @@ function Login() {
return <Redirect to="/home" />; return <Redirect to="/home" />;
} }
return ( return (
<div className="row vw-100 vh-100 m-0"> <Container fluid className="p-0">
<Asd className={"col-md-4 col-12" + (mobile ? " mobile" : " web")}> <Row className="vw-100 vh-100 m-0 " >
<div className={mobile ? "mob-head" : ""}> <Col_1 className={"col-md-4 col-12" + (mobile ? " mobile" : " web")}>
<img className={mobile ? "mob-img" : "img-fluid"} src={Logo} /> <div className={mobile ? "mob-head" : ""}>
<div className={"d-flex " + (mobile ? "align-items-center" : "justify-content-center")}> <img className={mobile ? "mob-img" : "img-fluid"} src={Logo} />
<h1 className="font-weight-bold text-white text-center">고려대학교<br/>대관 서비스</h1> <div className={"d-flex " + (mobile ? "align-items-center" : "justify-content-center")}>
<h1 className="font-weight-bold text-white text-center">고려대학교<br />대관 서비스</h1>
</div>
</div> </div>
</div> </Col_1>
</Asd> <Col_2 className="col-md-8 col-12" >
<Asdf className={"col-md-8 col-12" + (mobile ? " mob-formik p-0" : " web-formik")}> <Formik
<Formik initialValues={{ id: '', password: '' }}
initialValues={{ id: '', password: '' }} validationSchema={Yup.object({
validationSchema={Yup.object({ id: Yup.string()
id: Yup.string() .required('학번을 입력해주세요.'),
.required('학번을 입력해주세요.'), password: Yup.string()
password: Yup.string() .required('비밀번호를 입력해주세요.')
.required('비밀번호를 입력해주세요.') .min(8, '8자 이상 입력해주세요.'),
.min(8, '8자 이상 입력해주세요.'), })}
})} onSubmit={(values, { setSubmitting }) => {
onSubmit={(values, { setSubmitting }) => { axios({
axios({ method: 'post',
method: 'post', url: '/login',
url: '/login', data: values,
data: values, }).then(res => {
}).then(res => { if (res.status === 404) return alert(res.data.error)
if (res.status === 404) return alert(res.data.error)
localStorage.setItem('token', res.data.token);
localStorage.setItem('token', res.data.token); localStorage.setItem('_id', res.data.users._id);
localStorage.setItem('_id', res.data.users._id); localStorage.setItem('name', res.data.users.name);
localStorage.setItem('name', res.data.users.name); setState(true);
setState(true); })
}) .catch(err => {
.catch(err => { alert(err.error)
alert(err.error) });
});
setTimeout(() => {
setTimeout(() => { setSubmitting(false);
setSubmitting(false); }, 400); // finish the cycle in handler
}, 400); // finish the cycle in handler }}
}} >
> {({
{({ errors,
errors, touched,
touched, handleSubmit,
handleSubmit, getFieldProps, // contain values, handleChange, handleBlur
getFieldProps, // contain values, handleChange, handleBlur isSubmitting,
isSubmitting, }) => (
}) => ( <div className={mobile ? " mob-formik p-0" : " web-form"}>
<form onSubmit={handleSubmit} className={mobile ? "w-75 h-50vh" : "d-flex webb"}> <form onSubmit={handleSubmit} className={mobile ? "w-75 h-50vh" : "d-flex webb"}>
<div className={mobile ? "mobb" : "qwer"}> <div className={mobile ? "mob-container" : "web-container"}>
<div className={(mobile ? "mob-" : "web-") + "input-form"}> <div className={mobile ? "mob-input-form h-100" : "web-input-form"}>
<div className={"form-group m-0" + (mobile ? " mb-2" : "")}> <div className={"form-group m-0" + (mobile ? " mb-2" : "")}>
<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="number" type="number"
name="id" name="id"
{...getFieldProps('id')} {...getFieldProps('id')}
placeholder="Input Student Id" placeholder="Input Student Id"
/> />
</div> </div>
<div className="form-group m-0"> <div className="form-group h-80 m-0">
<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"
name="password" name="password"
{...getFieldProps('password')} {...getFieldProps('password')}
placeholder="Input Password" placeholder="Input Password"
/> />
</div>
</div>
<button type="submit" className={"btn btn-dark" + (mobile ? " w-100" : " w-20")} disabled={isSubmitting}> Login </button>
</div> </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>
</Col_2>
</Row>
</Container>
</Formik>
</Asdf>
</div >
) )
} }
export default Login export default Login;
\ No newline at end of file \ No newline at end of file
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([]);
...@@ -29,7 +30,6 @@ function Notice() { ...@@ -29,7 +30,6 @@ function Notice() {
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,34 +39,26 @@ function Notice() { ...@@ -39,34 +39,26 @@ 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>
<div id="accordion w-90 pt-1">
{notices.map((notice, index) => {notices.map((notice, index) =>
<div className="card"> <Card>
<div className="card-header collapsed card-link w-100 row m-0 p-1" id={"Hnotice_" + index} data-toggle="collapse" href={"#notice_" + index}> <Card.Header>
<div> <Accordion.Toggle as={Button} variant="link" eventKey={index + 1}>{notice.notice_title} <span className="text-right">{dateForm(notice.post_date)}</span></Accordion.Toggle>
<div className="col-6 p-0">{notice.notice_title}</div> </Card.Header>
<div className="col-3 p-0 text-center">{notice.notice_author}</div> <Accordion.Collapse eventKey={index + 1}>
<div className="col-3 p-0 text-right">{dateForm(notice.post_date)}</div> <Card.Body>{notice.notice_content}</Card.Body>
</div> </Accordion.Collapse>
</div> </Card>)}
<div id={"notice_" + index} aria-labelledby={"Hnotice_" + index} className="collapse" data-parent="#accordion"> </Accordion>
<div className="card-body">{notice.notice_content}</div> </Col>
</div> </Row>
</div> </Container>
)}
</div>
</div>
</div >
</div >
</div> </div>
) )
} }
export default Notice export default Notice;
\ No newline at end of file \ No newline at end of file
...@@ -2,7 +2,6 @@ import React, { useState } from 'react'; ...@@ -2,7 +2,6 @@ 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';
...@@ -40,7 +39,6 @@ function Signup() { ...@@ -40,7 +39,6 @@ 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"> <Nav className="navbar sticky-top navbar-expand-md">
...@@ -171,8 +169,7 @@ function Signup() { ...@@ -171,8 +169,7 @@ function Signup() {
placeholder="Input answer" /> placeholder="Input answer" />
</div> </div>
<button type="submit" className="btn btn-dark" disabled={isSubmitting}>회원가입</button> <button type="submit" className="btn btn-dark" disabled={isSubmitting}>회원가입</button>
<button class="btn btn-light"><Link to="/login">로그인</Link></button> <button class="btn btn-light"><Link to="/login">로그인하러 가기</Link></button>
<button class="btn btn-light"><Link to="/"></Link></button>
</form> </form>
)} )}
</Formik> </Formik>
...@@ -185,4 +182,4 @@ function Signup() { ...@@ -185,4 +182,4 @@ function Signup() {
} }
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
import React from 'react'; import React from 'react';
import ReactDOM from 'react-dom'; import ReactDOM from 'react-dom';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom'; import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
import * as serviceWorker from './serviceWorker';
import 'bootstrap'; import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.css'; import 'bootstrap/dist/css/bootstrap.css';
import axios from 'axios'; import axios from 'axios';
...@@ -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')
...@@ -45,4 +47,4 @@ ReactDOM.render( ...@@ -45,4 +47,4 @@ ReactDOM.render(
// If you want your app to work offline and load faster, you can change // If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls. // unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA // Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister(); serviceWorker.unregister();
\ No newline at end of file
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;
...@@ -5,7 +5,7 @@ module.exports = () => { ...@@ -5,7 +5,7 @@ module.exports = () => {
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
mongoose.set('debug', true); mongoose.set('debug', true);
} }
mongoose.connect('mongodb://rkyoung7:rkdud127@localhost:27017/admin', { mongoose.connect('mongodb://hyj:hyj3657@localhost:27017/admin', {
dbName: 'ku_rental', useNewUrlParser: true, useUnifiedTopology: true, dbName: 'ku_rental', useNewUrlParser: true, useUnifiedTopology: true,
}, (error) => { }, (error) => {
if (error) { if (error) {
......
...@@ -46,4 +46,4 @@ const reserveSchema = new Schema({ ...@@ -46,4 +46,4 @@ const reserveSchema = new Schema({
}, },
}); });
module.exports = mongoose.model('Reserve', reserveSchema); module.exports = mongoose.model('Reserve', reserveSchema);
\ No newline at end of file
...@@ -49,4 +49,4 @@ userSchema.pre("save", function (next) { ...@@ -49,4 +49,4 @@ userSchema.pre("save", function (next) {
}); });
module.exports = mongoose.model('User', userSchema); module.exports = mongoose.model('User', userSchema);
\ 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