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 path = require('path');
const cookieParser = require('cookie-parser');
const logger = require('morgan');
const port = 3030;
require('dotenv').config();
const indexRouter = require('./routes/index');
const usersRouter = require('./routes/users');
const loginRouter = require('./routes/login');
const reservesRouter = require('./routes/reserves');
const noticeRouter = require('./routes/notices');
const connect = require('./schemas');
const writesRouter = require('./routes/writes');
const app = express();
const port = 3030;
require('dotenv').config();
connect();
app.listen(port, () => console.log(port));
// view engine setup
// app.set('views', path.join(__dirname, 'views'));
// app.set('view engine', 'pug');
......@@ -28,7 +24,7 @@ app.listen(port, () => console.log(port));
app.use(logger('dev'));
app.use(express.json());
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('/', indexRouter);
......@@ -36,7 +32,9 @@ app.use('/users', usersRouter, reservesRouter);
app.use('/login', loginRouter);
app.use('/reserves', reservesRouter);
app.use('/notices', noticeRouter);
app.use('/writes', writesRouter);
app.listen(port, () => console.log(port));
// catch 404 and forward to error handler
app.use(function(req, res, next) {
......@@ -54,4 +52,4 @@ app.use(function(err, req, res, next) {
// res.render('error');
});
module.exports = app;
module.exports = app;
\ No newline at end of file
import React, { useState, useEffect } from 'react';
import { Link, Redirect } from 'react-router-dom';
import styled from 'styled-components';
import { Navbar, Nav, NavDropdown } from 'react-bootstrap';
const Nav = styled.nav`
const MENU = styled(Navbar)`
background-color: #7B031D;
height: 6vh;
a {
color: #ffffff;
}
& .logoutBtn:hover {
text-decoration: underline;
}
`
function Menu() {
const [state, setState] = useState()
const name = localStorage.getItem('name');
if (state) return <Redirect to="/" />;
function logout() {
localStorage.clear();
alert("로그아웃 되었습니다.");
setState(true);
}
if (state) return <Redirect to="/" />
return (
<Nav className="navbar sticky-top navbar-expand-md">
<a class="navbar-brand" href="#">대관 서비스</a>
<button className="navbar-toggler" type="button" data-toggle="collapse" data-target="#collapsibleNavbar" aria-controls="collapsibleNavbar">
<MENU expand="md" variant="dark">
<Navbar.Brand href="#">대관 서비스</Navbar.Brand>
<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>
</button>
<div className="collapse navbar-collapse justify-content-between" id="collapsibleNavbar">
</button> */}
{/* <div className="collapse navbar-collapse justify-content-between" id="collapsibleNavbar">
<ul className="navbar-nav">
<li className="nav-item">
<Link to="/notice" className="nav-link">공지사항</Link>
......@@ -70,8 +94,8 @@ function Menu() {
state: { id: localStorage.getItem('_id') },
}}>비밀번호 변경</Link> / <span className="logoutBtn" onClick={logout} >로그아웃</span></small></div>
</div>
</div>
</Nav>
</div> */}
</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';
import { Field, Formik } from 'formik';
import * as Yup from 'yup';
import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css';
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() {
const [state, setState] = useState();
const [state, setState] = useState(false);
if (state) {
return <Redirect to={{
......@@ -14,88 +24,96 @@ function Find() {
state: { id: localStorage.getItem('_id') },
}} />;
}
return (
<div className="d-flex flex-column justify-content-between vh-100">
<Formik
initialValues={{ id: '', question: '', answer: '' }}
validationSchema={Yup.object({
id: Yup.string()
.required('학번을 입력해주세요.'),
answer: Yup.string()
.required('답변을 입력해주세요.'),
})}
onSubmit={(values, { setSubmitting }) => {
axios({
method: 'post',
url: '/login/find',
data: values,
}).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)
});
<div className="vh-100">
<Nav className="navbar sticky-top navbar-expand-md">
<a class="navbar-brand" href="#">비밀번호 찾기</a>
</Nav>
<Container fluid>
<Row className="justify-content-center rrooww">
<Col md={4} className="d-flex align-items-center h-100">
<Formik
initialValues={{ id: '', question: '', answer: '' }}
validationSchema={Yup.object({
id: Yup.string()
.required('학번을 입력해주세요.'),
answer: Yup.string()
.required('답변을 입력해주세요.'),
})}
onSubmit={(values, { setSubmitting }) => {
axios({
method: 'post',
url: '/login/find',
data: values,
}).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,
}) => (
<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>
console.log(values);
setTimeout(() => {
setSubmitting(false);
}, 400); // finish the cycle in handler
}}
>
{({
errors,
touched,
handleSubmit,
getFieldProps, // contain values, handleChange, handleBlur
isSubmitting,
}) => (
<Row className="justify-content-center align-items-center">
<form onSubmit={handleSubmit}>
<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>
</Col>
</form>
</Row>
)}
</Formik>
</Col>
</Row>
</Container >
</div >
);
}
......
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useRef } from 'react';
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() {
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 (
<div>
<Menu />
<div className="container">
home
<button><Link to="/login">로그인</Link></button>
<button><Link to="/signup">회원가입</Link></button>
<div className="container mt-3">
<h2>대관 현황</h2>
<p>
<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>
)
}
export default Home
\ No newline at end of file
export default Home;
\ No newline at end of file
......@@ -4,10 +4,10 @@ import { Link, Redirect } from 'react-router-dom';
import { Formik } from 'formik';
import * as Yup from 'yup';
import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css';
import Logo from '../icon.png';
import { Container, Row } from 'react-bootstrap';
const Asd = styled.div`
const Col_1 = styled.div`
background-color: #7B031D;
&.web {
......@@ -35,13 +35,14 @@ const Asd = styled.div`
}
`
const Asdf = styled.div`
const Col_2 = styled.div`
background-color: rgb(239, 218, 200);
a {
color : #7B031D;
}
&.mob-formik {
& .mob-formik {
height : 80vh;
width: 100%;
display: flex;
......@@ -49,14 +50,14 @@ const Asdf = styled.div`
align-items: center;
}
&.web-formik {
& .web-form {
height: 100%;
display: flex;
align-items: center;
justify-content: center;
}
& .mobb {
& .mob-container {
height: 35vh;
display: flex;
flex-direction: column;
......@@ -67,7 +68,7 @@ const Asdf = styled.div`
flex-direction: column;
}
& .qwer {
& .web-container {
display: flex;
justify-content: space-between;
height: 12vh;
......@@ -84,7 +85,10 @@ const Asdf = styled.div`
}
& .mob-input-form {
display: flex;
flex-direction: column;
justify-content: space-around;
}
`
......@@ -104,89 +108,93 @@ function Login() {
return <Redirect to="/home" />;
}
return (
<div className="row vw-100 vh-100 m-0">
<Asd className={"col-md-4 col-12" + (mobile ? " mobile" : " web")}>
<div className={mobile ? "mob-head" : ""}>
<img className={mobile ? "mob-img" : "img-fluid"} src={Logo} />
<div className={"d-flex " + (mobile ? "align-items-center" : "justify-content-center")}>
<h1 className="font-weight-bold text-white text-center">고려대학교<br/>대관 서비스</h1>
<Container fluid className="p-0">
<Row className="vw-100 vh-100 m-0 " >
<Col_1 className={"col-md-4 col-12" + (mobile ? " mobile" : " web")}>
<div className={mobile ? "mob-head" : ""}>
<img className={mobile ? "mob-img" : "img-fluid"} src={Logo} />
<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>
</Asd>
<Asdf className={"col-md-8 col-12" + (mobile ? " mob-formik p-0" : " web-formik")}>
<Formik
initialValues={{ id: '', password: '' }}
validationSchema={Yup.object({
id: Yup.string()
.required('학번을 입력해주세요.'),
password: Yup.string()
.required('비밀번호를 입력해주세요.')
.min(8, '8자 이상 입력해주세요.'),
})}
onSubmit={(values, { setSubmitting }) => {
axios({
method: 'post',
url: '/login',
data: values,
}).then(res => {
if (res.status === 404) return alert(res.data.error)
localStorage.setItem('token', res.data.token);
localStorage.setItem('_id', res.data.users._id);
localStorage.setItem('name', res.data.users.name);
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={mobile ? "w-75 h-50vh" : "d-flex webb"}>
<div className={mobile ? "mobb" : "qwer"}>
<div className={(mobile ? "mob-" : "web-") + "input-form"}>
<div className={"form-group m-0" + (mobile ? " mb-2" : "")}>
<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 m-0">
<input
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
type="password"
name="password"
{...getFieldProps('password')}
placeholder="Input Password"
/>
</Col_1>
<Col_2 className="col-md-8 col-12" >
<Formik
initialValues={{ id: '', password: '' }}
validationSchema={Yup.object({
id: Yup.string()
.required('학번을 입력해주세요.'),
password: Yup.string()
.required('비밀번호를 입력해주세요.')
.min(8, '8자 이상 입력해주세요.'),
})}
onSubmit={(values, { setSubmitting }) => {
axios({
method: 'post',
url: '/login',
data: values,
}).then(res => {
if (res.status === 404) return alert(res.data.error)
localStorage.setItem('token', res.data.token);
localStorage.setItem('_id', res.data.users._id);
localStorage.setItem('name', res.data.users.name);
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,
}) => (
<div className={mobile ? " mob-formik p-0" : " web-form"}>
<form onSubmit={handleSubmit} className={mobile ? "w-75 h-50vh" : "d-flex webb"}>
<div className={mobile ? "mob-container" : "web-container"}>
<div className={mobile ? "mob-input-form h-100" : "web-input-form"}>
<div className={"form-group m-0" + (mobile ? " mb-2" : "")}>
<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 h-80 m-0">
<input
className={(touched.password && errors.password ? 'form-control is-invalid' : "form-control")}
type="password"
name="password"
{...getFieldProps('password')}
placeholder="Input Password"
/>
</div>
</div>
<button type="submit" className={"btn btn-dark" + (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="/signup">회원이 아니신가요?</Link></div>
<div><Link to="/find">비밀번호를 잊으셨나요?</Link></div>
<div><Link to="/signup">회원이 아니신가요?</Link></div>
</form>
)}
</form>
</div>
)}
</Formik>
</Col_2>
</Row>
</Container>
</Formik>
</Asdf>
</div >
)
}
export default Login
\ No newline at end of file
export default Login;
\ No newline at end of file
import React, { useState, useEffect, useRef } from 'react';
import Menu from '../Components/Menu';
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() {
const [notices, setNotices] = useState([]);
......@@ -29,7 +30,6 @@ function Notice() {
if (res.status !== 201) {
alert(res.data.error);
}
console.log(res.data);
setNotices(res.data);
})
.catch(err => {
......@@ -39,34 +39,26 @@ function Notice() {
return (
<div>
<Menu />
<div className="container-fluid">
<div className="row justify-content-center vw-100 vh-90">
<div className="col-md-7 col-12">
<h2 className="p-3 border-bottom">공지사항</h2>
<div id="accordion w-90 pt-1">
<Container fluid>
<Row className="justify-content-center vw-100 vh-90">
<Col md={7}>
<h2 className="p-3 border-bottom">공지사항 <Link to="/write"> 작성</Link></h2>
<Accordion>
{notices.map((notice, index) =>
<div className="card">
<div className="card-header collapsed card-link w-100 row m-0 p-1" id={"Hnotice_" + index} data-toggle="collapse" href={"#notice_" + index}>
<div>
<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 >
<Card>
<Card.Header>
<Accordion.Toggle as={Button} variant="link" eventKey={index + 1}>{notice.notice_title} <span className="text-right">{dateForm(notice.post_date)}</span></Accordion.Toggle>
</Card.Header>
<Accordion.Collapse eventKey={index + 1}>
<Card.Body>{notice.notice_content}</Card.Body>
</Accordion.Collapse>
</Card>)}
</Accordion>
</Col>
</Row>
</Container>
</div>
)
}
export default Notice
\ No newline at end of file
export default Notice;
\ No newline at end of file
......@@ -2,7 +2,6 @@ import React, { useState } from 'react';
import { Field, Formik } from 'formik';
import * as Yup from 'yup';
import axios from 'axios';
import 'bootstrap/dist/css/bootstrap.css';
import { Link, Redirect } from 'react-router-dom';
import styled from 'styled-components';
......@@ -40,7 +39,6 @@ function Signup() {
if (state) {
return <Redirect to="/login" />;
}
return (
<div className="vh-100">
<Nav className="navbar sticky-top navbar-expand-md">
......@@ -171,8 +169,7 @@ function Signup() {
placeholder="Input answer" />
</div>
<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="/"></Link></button>
<button class="btn btn-light"><Link to="/login">로그인하러 가기</Link></button>
</form>
)}
</Formik>
......@@ -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 ReactDOM from 'react-dom';
import * as serviceWorker from './serviceWorker';
import { BrowserRouter as Router, Route, Redirect, Switch } from 'react-router-dom';
import * as serviceWorker from './serviceWorker';
import 'bootstrap';
import 'bootstrap/dist/css/bootstrap.css';
import axios from 'axios';
......@@ -16,13 +16,14 @@ import Apply from './Pages/ApplyPage';
import Check from './Pages/CheckPage';
import Notice from './Pages/NoticePage';
import ACheck from './Pages/ACheckPage';
import Write from './Pages/WritePage';
axios.defaults.validateStatus = function (status) {
return status < 500; // default
}
ReactDOM.render(
<Router>
<Router>
<Switch>
<PrivateRoute exact path="/" component={Home} />
<Route path="/login" component={Login} />
......@@ -32,11 +33,12 @@ ReactDOM.render(
<Route path="/change" component={Change} />
<Route path="/apply/:id" component={Apply} />
<Route path="/check/:id" component={Check} />
<Route path="/write" component={Write} />
<Route path="/notice" component={Notice} />
<Route path="/acheck/:id" component={ACheck} />
<Redirect path="/" to="/" />
<Redirect path="/home" to="/" />
<Redirect path="/change/:id" to="/change"/>
<Redirect path="/change/:id" to="/change" />
<Redirect path="/notice" to="/notice" />
</Switch>
</Router>,
document.getElementById('root')
......@@ -45,4 +47,4 @@ ReactDOM.render(
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// 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 = () => {
if (process.env.NODE_ENV !== 'production') {
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,
}, (error) => {
if (error) {
......
......@@ -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) {
});
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