Commit 49fc2a67 authored by Jiwon Yoon's avatar Jiwon Yoon
Browse files

Merge branch 'kimpen'

parents 6e0e826d ab2a8d78
......@@ -38,7 +38,7 @@ function App() {
<Route path="/movie/:movieId" component={MoviePage} />
<Route path="/mypage" component={MyPage} />
<Route path="/guest" component={GuestPage}/>
<Route path="/ticket/seat" component={TicketingSeatPage}/>
<Route path="/ticket/seat" component={TicketingSeatPage} />
<Route path="/ticket" component={TicketingPage} />
<Route path="/payment" component={PaymentPage} />
<Route path="/paymentcomplete" component={PaymentCompletePage} />
......@@ -47,6 +47,7 @@ function App() {
<Route path="/search" component={SearchPage} />
</Switch>
</div>
</Switch>
</Router>
</AuthProvider>
......
import axios from "axios";
import { baseUrl } from "../utils/baseUrl.js";
const getAll = async (selectDate) => {
const { data } = await axios.get(`${baseUrl}/api/timetable?when=${selectDate}`)
const getAll = async (selectDate, movieId) => {
const { data } = await axios.get(`${baseUrl}/api/timetable?when=${selectDate}&movieId=${movieId}`)
return data
}
......
......@@ -18,6 +18,7 @@ const MovieEdit = () => {
async function paginate(pageNum) {
try {
setError("")
const { TMDBmovies, totalPage } = (search.keyword !== '') ? await movieApi.search(search, pageNum) : await movieApi.getAllfromTM(pageNum)
setActivePage(pageNum)
setTotalPages(totalPage)
......
......@@ -5,19 +5,23 @@ import timetableApi from "../../apis/timetable.api.js";
import catchErrors from "../../utils/catchErrors.js";
import styles from "./admin.module.scss";
const TimeTable = () => {
const TimeTable = ({ ticketInfo = { movieId: 0 }, setTicketInfo }) => {
const [selectDate, setSelectDate] = useState(moment().format('YYYY-MM-DD'))
const [timeList, setTimeList] = useState([])
const [error, setError] = useState("")
useEffect(() => {
getTimeTable(selectDate)
getTimeTable(selectDate, ticketInfo.movieId)
}, [selectDate])
async function getTimeTable() {
useEffect(() => {
getTimeTable(selectDate, ticketInfo.movieId)
}, [ticketInfo.movieId])
async function getTimeTable(selectDate, movieId) {
try {
setError("")
const res = await timetableApi.getAll(selectDate)
const res = await timetableApi.getAll(selectDate, movieId)
setTimeList(res)
} catch (error) {
catchErrors(error, setError)
......@@ -35,24 +39,50 @@ const TimeTable = () => {
}
}
function handleClick(time) {
const date = new Date(time.start_time)
let hours = date.getHours()
let mins = date.getMinutes()
if (hours <= 9) hours = '0' + hours
if (mins <= 9) mins = '0' + mins
setTicketInfo({
...ticketInfo,
timetableId: time.id,
time: time.date.split('T')[0] + " " + hours + ":" + mins,
selectedTheater: time.theater.theaterName
})
}
return (
<div className="col-12 col-lg-6 ms-lg-1 mb-5">
<>
<HorizontalCalender selectDate={selectDate} setSelectDate={setSelectDate} />
{timeList.length !== 0 ?
timeList.map(el => <div className="mt-4">
<h5 className="mb-0">{el.theaterName} / <p className="d-inline fs-6 mb-0">{el.theatertype.theaterTypeName}</p></h5>
{el.timetable.map(time => <div className="d-inline-flex flex-column m-2">
<div className="d-flex justify-content-end">
<button type="button" className={`btn btn-dark btn-sm shadow-none ${styles.customBtn}`} onClick={() => deleteTime(time.id)}>X</button>
</div>
<div className="card">
<div className="card-body py-1">{moment(time.start_time).format('HH:mm')} ~ {moment(time.end_time).format('HH:mm')}</div>
<div className="card-footer text-center py-1">{time.title}</div>
<h5 className="mb-0">{el.theaterName} / <p className="d-inline fs-6 mb-0">{el.theaterTypeName}</p></h5>
{el.timetable.map(time => {
console.log("timetable==",time)
if (ticketInfo)
return <div className="d-inline-flex m-2">
<div className={`card text-dark ${styles.cursor}`} onClick={() => handleClick(time)}>
<div className="card-body py-1">{moment(time.start_time).format('HH:mm')} ~ {moment(time.end_time).format('HH:mm')}</div>
<div className="card-footer text-center py-1">{time.theater.rows * time.theater.columns - time.reservations} / {time.theater.rows * time.theater.columns}</div>
</div>
</div>
else return <div className="d-inline-flex flex-column m-2">
<div className="d-flex justify-content-end">
<button type="button" className={`btn btn-dark btn-sm shadow-none ${styles.customBtn}`} onClick={() => deleteTime(time.id)}>X</button>
</div>
<div className="card">
<div className="card-body py-1">{moment(time.start_time).format('HH:mm')} ~ {moment(time.end_time).format('HH:mm')}</div>
<div className="card-footer text-center py-1">{time.title}</div>
</div>
</div>
</div>)}
})}
</div>)
: <p className="text-center mt-5 mb-0">서버에 저장되어 있는 상영시간표가 존재하지 않습니다.<br />아래의 양식을 작성해 새로운 상영시간표를 등록해주세요.</p>}
</div>
</>
)
}
......
......@@ -7,7 +7,9 @@ const TimeTableEdit = () => {
<>
<h2 className="border-bottom border-2 text-center pb-2 me-2">현재 상영시간표 정보</h2>
<div className="d-flex flex-column flex-lg-row-reverse">
<TimeTable />
<div className="col-12 col-lg-6 ms-lg-1 mb-5">
<TimeTable />
</div>
<TimeTableEditForm />
</div>
</>
......
......@@ -75,13 +75,13 @@ const TimeTableEditForm = () => {
const { list } = showTimes
const isSelect = Object.values(selectInfo).every((el) => Boolean(el))
if (isSelect) {
const isTime = list.find(el => (el.theaterTypeId === selectInfo.theater) && ((getDate(el.start) <= getDate(selectInfo.start) && getDate(selectInfo.start) <= getDate(el.end)) || (getDate(el.start) > getDate(selectInfo.start) && getDate(el.start) <= getDate(selectInfo.end))))
const isTime = list.find(el => (el.theaterId === selectInfo.theater) && ((getDate(el.start) <= getDate(selectInfo.start) && getDate(selectInfo.start) <= getDate(el.end)) || (getDate(el.start) > getDate(selectInfo.start) && getDate(el.start) <= getDate(selectInfo.end))))
if (isTime) alert('이미 추가한 상영시간대입니다. 다른 시간대를 골라주시기 바랍니다.')
else {
const theater = theaterList.find(theater => theater.theatertypeId === selectInfo.theater)
const theater = theaterList.find(theater => theater.id === selectInfo.theater)
if (theater) {
const myTime = {
theaterTypeId: selectInfo.theater,
theaterId: selectInfo.theater,
theaterName: theater.theaterName + '관 / ' + theater.theatertype.theaterTypeName,
start: selectInfo.start,
end: selectInfo.end
......@@ -126,7 +126,7 @@ const TimeTableEditForm = () => {
try {
setError("")
showTimes.list.map(time => {
timeArr.push({ theater: time.theaterTypeId, start: time.start, end: time.end })
timeArr.push({ theater: time.theaterId, start: time.start, end: time.end })
})
const sendData = {
movieId: selectMovie.id,
......@@ -184,9 +184,9 @@ const TimeTableEditForm = () => {
theaterList.map((theater, index) => {
if (index === 0) return <>
<option value="0" disabled>상영관을 선택해주십시오.</option>
<option value={theater.theatertypeId}>{theater.theaterName} / {theater.theatertype.theaterTypeName}</option>
<option value={theater.id}>{theater.theaterName} / {theater.theatertype.theaterTypeName}</option>
</>
else return <option value={theater.theatertypeId}>{theater.theaterName} / {theater.theatertype.theaterTypeName}</option>
else return <option value={theater.id}>{theater.theaterName} / {theater.theatertype.theaterTypeName}</option>
})
: <option value="0" disabled>서버에 등록된 상영관이 없습니다.</option>}
</select>
......
import { useState, useEffect } from "react";
import { useHistory } from "react-router-dom";
import moment from "moment";
import DatePicker from "./DatePicker.js";
import styles from "./calender.module.scss";
......@@ -9,6 +10,7 @@ const Calender = ({ selectDate, setSelectDate }) => {
const [weekly, setWeekly] = useState([])
const [week, setWeek] = useState(["", "", "", "", "", "", ""])
const [month, setMonth] = useState({ pre: moment(selectDate).subtract(1, 'months').format('YYYY-MM'), cur: moment(selectDate).format('YYYY-MM'), next: moment(selectDate).add(1, 'months').format('YYYY-MM') })
const history = useHistory()
useEffect(() => {
setMonth({ ...month, pre: moment(selectDate).subtract(1, 'months').format('YYYY-MM'), cur: moment(selectDate).format('YYYY-MM'), next: moment(selectDate).add(1, 'months').format('YYYY-MM') })
......@@ -20,10 +22,10 @@ const Calender = ({ selectDate, setSelectDate }) => {
let dateArr = []
dateArr = Array(7).fill(0).map((n, i) => {
let current = moment(oneDay).add((n + i), 'days')
return <div className="col-auto align-self-end text-center" onClick={() => setSelectDate(current)}>
return <div className="col-auto align-self-end text-center" onClick={() => setSelectDate(current.format('YYYY-MM-DD'))}>
{current.isSame(oneDay) || current.format("DD") === "01" ? <strong className={styles.yearmonth}>{current.format('YYYY.MM')}</strong> : ""}
<div className={`d-flex flex-column ${styles.cursor} ` + ((current.format("d") === "0" || current.format("d") === "6") ? ((current.format("d") === "0") ? "text-danger" : "text-primary") : "")}>
<strong className={current.isSame(oneDay) ? styles.selectDate : ""}>{current.format('DD')}</strong>
<strong className={current.isSame(oneDay) ? (/admin/g.test(history.location.pathname) ? styles.selectDate : styles.selectatHome) : ""}>{current.format('DD')}</strong>
<strong>{current.isSame(oneDay) ? "오늘" : week[Number(current.format("d"))]}</strong>
</div>
</div>
......@@ -43,7 +45,7 @@ const Calender = ({ selectDate, setSelectDate }) => {
const resultArr = dateArr.map(el => <div className="col-2 align-self-end text-center" onClick={() => setSelectDate(el.date)}>
{moment(el.date).isSame(oneDay) || el.date.split('-')[2] === "01" ? <strong className={styles.yearmonth}>{moment(el.date).format('YYYY.MM')}</strong> : ""}
<div className={`d-flex flex-column ${styles.cursor} ` + ((Number(el.day) === 0 || Number(el.day) === 6) ? ((Number(el.day) === 0) ? "text-danger" : "text-primary") : "")}>
<strong className={moment(el.date).isSame(oneDay) ? styles.selectDate : ""}>{moment(el.date).format('DD')}</strong>
<strong className={moment(el.date).isSame(oneDay) ? (/admin/g.test(history.location.pathname) ? styles.selectDate : styles.selectatHome) : ""}>{moment(el.date).format('DD')}</strong>
<strong>{moment(el.date).isSame(oneDay) ? "오늘" : week[el.day]}</strong>
</div>
</div>)
......
......@@ -35,4 +35,10 @@
background-color: #000;
color: #fff;
border-radius: 50%;
}
.selectatHome {
background-color: #fff;
color: #000;
border-radius: 50%;
}
\ No newline at end of file
......@@ -23,7 +23,7 @@ const Collection = ({ TMDB_TopRated_Data }) => {
return (
<>
<h2 className="fw-bold text-white text-center my-5">Movie Collection</h2>
<div className="row justify-content-sm-center" style={{ marginBottom: "8rem" }}>
<div className="d-flex justify-content-sm-center" style={{ marginBottom: "8rem" }}>
<div className="col-md-8">
{videoUrls.length > 0
?
......
......@@ -2,6 +2,7 @@ import { useState, useEffect } from 'react'
import { useLocation } from 'react-router-dom'
import queryString from 'query-string'
import MovieCard from "./MovieCard/index.js"
import Pagination from "./Pagination.js";
import movieApi from '../apis/movie.api.js'
import catchErrors from '../utils/catchErrors.js'
......@@ -18,8 +19,8 @@ const SearchResult = () => {
async function findforKeyword() {
try {
setError("")
const { count, results } = await movieApi.search({ type: "home", keyword: title })
setResult([...results])
const res = await movieApi.search({ type: "home", keyword: title })
setResult(res)
} catch (error) {
catchErrors(error, setError)
}
......
const TicketingTimeTable = ({ ticketInfo }) => {
import TimeTable from "../Admin/TimeTable";
const TicketingTimeTable = ({ ticketInfo, setTicketInfo }) => {
return (
<div className="text-center" style={{ color: "white" }}>
<div style={{ color: "white" }}>
{ticketInfo.movieId && ticketInfo.cinema
? <div>{ticketInfo.movieId} {ticketInfo.cinema}</div>
: <div>영화와 극장을 모두 선택해주세요.</div>}
? <TimeTable ticketInfo={ticketInfo} setTicketInfo={setTicketInfo} />
: <div className="text-center">영화와 극장을 모두 선택해주세요.</div>}
</div>
)
}
......
......@@ -25,7 +25,7 @@ const Video = ({ movieId }) => {
? videoUrls.map(el => (
<div className="mt-5 pb-5">
<p>{el.name}</p>
<div class="ratio ratio-16x9">
<div className="ratio ratio-16x9">
<iframe src={`https://www.youtube.com/embed/${el.key}`} title="YouTube video" allowFullScreen></iframe>
</div>
</div>
......
......@@ -13,8 +13,8 @@ const TicketingPage = ({ location }) => {
movieId: 0,
...location.state,
cinema: "",
selectedTheater: 1,
time: "2021/07/21 10:00"
selectedTheater: "",
time: ""
})
const [cinemaInfo, setCinemaInfo] = useState({})
const [movieInfo, setMovieInfo] = useState()
......@@ -69,7 +69,7 @@ const TicketingPage = ({ location }) => {
</div>
<div className="col-sm-5 mb-4 ">
<h3 className="py-2 text-white text-center" style={{ border: "3px solid #000000", borderBottom: "3px solid #FEDC00" }}>시간표</h3>
<TicketingTimeTable ticketInfo={ticketInfo} cinemaInfo={cinemaInfo} />
<TicketingTimeTable ticketInfo={ticketInfo} setTicketInfo={setTicketInfo} />
</div>
</div>
<div className="row p-3" style={{ backgroundColor: "#252525" }}>
......@@ -85,7 +85,7 @@ const TicketingPage = ({ location }) => {
<li>영화: {movieInfo.title}</li>
<li>극장: {ticketInfo.cinema}</li>
<li>일시: {ticketInfo.time}</li>
<li>상영관: {ticketInfo.selectedTheater}</li>
<li>상영관: {(ticketInfo.selectedTheater !== "") ? ticketInfo.selectedTheater + "" : ""}</li>
</ul>
: <div></div>}
</div>
......
......@@ -97,8 +97,6 @@ const getMovieById = async (req, res) => {
}
const getMovieList = async (req, res) => {
const { category } = req.params
// console.log(category)
try {
const { category } = req.params
const movieList = await Movie.findAll()
......@@ -178,15 +176,15 @@ const findonlyTitle = async (req, res) => {
try {
const { keyword } = req.query
const movieIds = []
const { count, rows } = await Movie.findAndCountAll({
const findAll = await Movie.findAll({
where: {
title: {
[Op.substring]: keyword
}
}
});
if (rows) {
rows.forEach(movie => movieIds.push(movie.movieId))
if (findAll) {
findAll.forEach(movie => movieIds.push(movie.movieId))
const elements = await Promise.all(
movieIds.map(async (movieId) => {
const movie = await axios.get(`https://api.themoviedb.org/3/movie/${movieId}?api_key=${process.env.TMDB_APP_KEY}&language=ko-KR`)
......@@ -200,8 +198,8 @@ const findonlyTitle = async (req, res) => {
return { ...movie.data, ticket_sales: cols.ticket_sales, vote_average: cols.vote_average, totalReservationRate: totalReservationRate[0] }
})
)
return res.json({ count: movieIds.length, results: elements })
} else return res.json({ count: count, results: rows })
return res.json(elements)
} else return res.json(findAll)
} catch (error) {
return res.status(500).send(error.message || "영화 검색 중 에러 발생");
}
......
import { TimeTable, Theater, TheaterType } from "../db/index.js";
import moment from 'moment';
import { TimeTable, Theater, TheaterType, Reservation } from "../db/index.js";
import sequelize from 'sequelize'
const { Op } = sequelize
const getAll = async (req, res) => {
try {
const { when } = req.query
const { when, movieId } = req.query
const selectDate = new Date(when)
let findAll = null
const theaterArr = []
const findAll = await TimeTable.findAll({ where: { date: selectDate }, attributes: { exclude: ['createdAt', 'updatedAt'] }, order: [["theater", "ASC"], ["start_time", "ASC"]] })
findAll.forEach(element => {
if (!theaterArr.includes(element.theater)) theaterArr.push(element.theater)
findAll = movieId ? await TimeTable.findAll({ where: { date: selectDate, movieId: movieId }, attributes: { exclude: ['createdAt', 'updatedAt'] }, order: [["theaterId", "ASC"], ["start_time", "ASC"]], include: [Theater] })
: await TimeTable.findAll({ where: { date: selectDate }, attributes: { exclude: ['createdAt', 'updatedAt'] }, order: [["theaterId", "ASC"], ["start_time", "ASC"]], include: [Theater] })
findAll.forEach(async (element) => {
if (!theaterArr.includes(element.theaterId)) theaterArr.push(element.theaterId)
if (movieId) {
const { count } = await Reservation.findAndCountAll({ where: { movieId: movieId, timetableId: element.id } })
element.dataValues.reservations = count
}
})
const findTheater = await Theater.findAll({ where: { id: theaterArr }, attributes: { exclude: ['createdAt', 'updatedAt'] }, include: [TheaterType], order: [['theaterName']] })
findTheater.forEach(el => {
el.dataValues.theaterTypeName = el.dataValues.theatertype.dataValues.theaterTypeName
const arr = findAll.filter(timetable => {
if (el.id === timetable.theater) return timetable.dataValues
if (el.id === timetable.theaterId) return timetable.dataValues
})
el.dataValues.timetable = arr
})
......@@ -35,7 +41,7 @@ const submit = async (req, res) => {
const isTimeTable = await TimeTable.findAll({
where: {
[Op.and]: [
{ theater: theater.theater },
{ theaterId: theater.theater },
{
[Op.or]: [
{ [Op.and]: [{ start_time: { [Op.gt]: startTime } }, { end_time: { [Op.lte]: endTime } }] },
......@@ -62,7 +68,7 @@ const submit = async (req, res) => {
if ('06:00' <= theater.start && theater.start < '10:00') partTime = "morning"
else if ('00:00' <= theater.start < '06:00') partTime = "night"
else partTime = "day"
await TimeTable.create({ theater: theater.theater, movieId, title, release_date, date: curDate, start_time: getTime(theater.start), end_time: getTime(theater.start, runtime), partTime: partTime, week: (day === 0 || day === 6) ? "weekend" : "weekdays" })
await TimeTable.create({ theaterId: theater.theater, movieId, title, release_date, date: curDate, start_time: getTime(theater.start), end_time: getTime(theater.start, runtime), partTime: partTime, week: (day === 0 || day === 6) ? "weekend" : "weekdays" })
})
)
curDate.setDate(curDate.getDate() + 1)
......
......@@ -50,6 +50,8 @@ Theater.belongsTo(TheaterType, { onDelete: 'CASCADE' });
TicketFee.belongsTo(TheaterType, { onDelete: 'CASCADE' });
TimeTable.belongsTo(Theater);
Reservation.belongsTo(Theater);
Reservation.belongsTo(TimeTable);
......
......@@ -18,20 +18,21 @@ sequelize
})
);
const adminRole = await Role.findOne({ where: { name: "admin" } });
if (!adminRole) {
await User.create({
const adminRole = await Role.findOne({ where: { name: "admin" } })
await User.findOrCreate({
where: { userId: "admin" },
defaults: {
userId: "admin",
name: "관리자",
email: "han35799@naver.com",
nickname: "haha",
birth: "990926",
phoneNumber: "01086074580",
nickname: "admin",
birth: "000000",
phoneNumber: "01000000000",
password: "admin!",
img: "970aaa79673a39331d45d4b55ca05d25",
roleId: adminRole?.id,
});
} else { }
}
});
app.listen(appConfig.port, () => {
console.log(`Server is running on port ${appConfig.port}`);
......
......@@ -11,9 +11,6 @@ const TimeTableModel = (sequelize) => {
primaryKey: true,
autoIncrement: true,
},
theater: {
type: DataTypes.INTEGER,
},
movieId: {
type: DataTypes.INTEGER,
},
......
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