Commit 5ee991bb authored by Jiwon Yoon's avatar Jiwon Yoon
Browse files

회원예매/비회원예매

parent 44b5a715
......@@ -14,7 +14,7 @@ import AdminPage from "./pages/AdminPage/AdminPage";
import TicketingPage from "./pages/TicketingPage";
import TicketingSeatPage from './pages/TicketingSeatPage'
import SearchPage from "./pages/SearchPage";
import Payment from "./pages/PaymentPage";
import Payment from "./pages/PaymentPage/PaymentPage";
function App() {
......
......@@ -103,7 +103,6 @@ const Login = () => {
<input className={styles.input} type="number" name="gusetBirthday" id="gusetBirthday" placeholder="생년월일" onChange={handleGuestOnChange} maxLength="6" required />
<input className={styles.input} type="number" name="gusetMbnum" id="gusetMbnum" placeholder="휴대폰 번호" onChange={handleGuestOnChange} maxLength="11" required />
<input className={styles.input} type="password" name="guestPassword" id="password" placeholder="비밀번호" onChange={handleGuestOnChange} maxLength="11" required />
<p className={`text-white ${styles.fontSizeTwo}`}>
비회원 정보 입력 예매 내역 확인/취소 티켓 발권이 어려울 있으니 다시 한번 확인해 주시기 바랍니다.
</p>
......
import axios from 'axios'
import { useEffect, useState } from 'react'
import Kakaopay from '../components/Kakaopay'
import { useAuth } from '../context/auth_context'
import catchErrors from '../utils/catchErrors'
const Payment = ({ location }) => {
const [ticketInfo, setTicketInfo] = useState({ ...location.state })
const [error, setError] = useState("")
const [userInfo, setUserInfo] = useState()
const { user } = useAuth()
useEffect(() => {
getUserInfo()
}, [])
async function getUserInfo() {
try {
const response = await axios.post(`/api/auth/getuserinfo`, {
id: user.id
})
setUserInfo(response.data)
} catch (error) {
catchErrors(error, setError)
}
}
async function SendMail(e) {
try {
const response = await axios.post('/api/email/send', {
...ticketInfo,
...userInfo
})
console.log(response.data)
} catch (error) {
console.log(error)
}
}
return (
<div className="container" style={{ color: "white" }}>
{console.log(ticketInfo)}
{console.log(userInfo)}
<div className="row justify-content-center my-5">
<div className="col-sm-4 mb-3 ">
<h3 className="py-2 text-white text-center" style={{ border: "3px solid #000000", borderBottom: "3px solid #FEDC00" }}>결제하기</h3>
</div>
</div>
<div className="row justify-content-center">
<div className="col-sm-8 text-center">
{user?.id > 0
?
<div>
<h5 className="mb-3">회원정보</h5>
</div>
:
<div>
<h5 className="mb-3">비회원예매 정보입력</h5>
</div>
}
<h5 className="mb-3">결제방법</h5>
<img src="/images/naverpay_button.png" />
<Kakaopay ticketInfo={ticketInfo} setTicketInfo={setTicketInfo} />
<div className="my-5">
<button className="btn btn-warning" type="button" onClick={SendMail}>결제완료</button>
</div>
</div>
<div className="col-sm-4 p-3 text-center rounded-3" style={{ backgroundColor: "#252525" }}>
<img style={{ maxHeight: "10rem" }} src={`https://image.tmdb.org/t/p/original${ticketInfo.poster_path}`} alt="영화포스터" />
<h5 className="my-3">{ticketInfo.title}</h5>
<div>{ticketInfo.cinema}</div>
<div>{ticketInfo.time}</div>
<div className="mb-3">{ticketInfo.selectedTheater} {ticketInfo.selectedSeats}</div>
<div className="rounded-3 p-3" style={{ backgroundColor: '#404040' }}>
<div>청소년: {ticketInfo.teenager}</div>
<div>성인: {ticketInfo.adult}</div>
<div>경로우대: {ticketInfo.elderly}</div>
<div> 결제금액: {ticketInfo.teenager * 7000 + ticketInfo.adult * 8000 + ticketInfo.elderly * 6000}</div>
</div>
</div>
</div>
</div>
)
}
export default Payment
\ No newline at end of file
import axios from 'axios'
import { useEffect, useState } from 'react'
import Kakaopay from '../../components/Kakaopay'
import { useAuth } from '../../context/auth_context'
import catchErrors from '../../utils/catchErrors'
import styles from './PaymentPage.module.scss'
const Payment = ({ location }) => {
const [ticketInfo, setTicketInfo] = useState({ ...location.state })
const [error, setError] = useState("")
const [userInfo, setUserInfo] = useState()
const [guestInfo, setGuestInfo] = useState({})
const [guestID, setGuestID] = useState()
const { user } = useAuth()
useEffect(() => {
console.log(user.id)
if (user.id > 0) {
getUserInfo()
}
}, [])
async function getUserInfo() {
try {
const response = await axios.post(`/api/auth/getuserinfo`, {
id: user.id
})
setUserInfo(response.data)
} catch (error) {
catchErrors(error, setError)
}
}
function handleChangeGuest(e) {
setGuestInfo({ ...guestInfo, [e.target.name]: String(e.target.value) })
}
async function handleClickGuest() {
try {
const response = await axios.post('/api/auth/guest/save', {
...guestInfo
})
setGuestID(response.data.id)
// console.log(response.data)
} catch (error) {
catchErrors(error, setError)
}
}
async function reservationComplete() {
try {
if (userInfo) {
const response = await axios.post(`/api/reservation/save`, {
userType: "member",
user: userInfo.id,
...ticketInfo,
payment: "카카오페이",
timetable: 1
})
console.log("회원예매완료===", response.data)
} else {
if (guestID) {
const response = await axios.post(`/api/reservation/save`, {
userType: "guest",
user: guestID,
...ticketInfo,
payment: "카카오페이",
timetable: 1
})
console.log("비회원예매완료===", response.data)
} else {
alert("비회원 정보를 모두 입력 후 저장버튼을 눌러주세요.")
}
}
const responseEmail = await axios.post('/api/email/send', {
...ticketInfo,
...userInfo,
...guestInfo,
})
console.log("이메일전송완료===", responseEmail.data)
} catch (error) {
catchErrors(error, setError)
}
}
return (
<div className="container" style={{ color: "white" }}>
{console.log(ticketInfo)}
{console.log(userInfo)}
{console.log(guestInfo)}
<div className="row justify-content-center my-5">
<div className="col-sm-4 ">
<h3 className="py-2 text-white text-center" style={{ border: "3px solid #000000", borderBottom: "3px solid #FEDC00" }}>결제하기</h3>
</div>
</div>
<div className="row justify-content-center">
<div className="col-sm-8 text-center">
{user?.id > 0
?
<div>
<h5 className="mb-3">회원정보</h5>
</div>
:
<div>
<h5 className="mb-4 p-2" style={{ backgroundColor: "white", color: "black" }}>비회원예매 정보입력</h5>
<div className="my-1">
<label className={styles.labelStyle}>이름</label>
<input type="text" name="name" placeholder="이름" onChange={handleChangeGuest} required />
</div>
<div className="my-1">
<label className={styles.labelStyle}>이메일</label>
<input type="email" name="email" placeholder="이메일" onChange={handleChangeGuest} required />
</div>
<div className="my-1">
<label className={styles.labelStyle}>생년월일</label>
<input type="number" name="birth" placeholder="생년월일" onChange={handleChangeGuest} maxLength="6" required />
</div>
<div className="my-1">
<label className={styles.labelStyle}>휴대폰 번호</label>
<input type="number" name="phoneNumber" placeholder="휴대폰 번호" onChange={handleChangeGuest} maxLength="11" required />
</div>
<div className="my-1">
<label className={styles.labelStyle}>비밀번호</label>
<input type="password" name="guestPassword" placeholder="비밀번호" onChange={handleChangeGuest} required style={{ width: "178px" }} />
</div>
<div className="m-2">
<p className={`text-muted ${styles.warningText}`}>
비회원 정보 오기입 예매 내역 확인/취소 티켓 발권이 어려울 있으니 다시 한번 확인해 주시기 바랍니다.
</p>
</div>
<button className="btn btn-warning mb-3" type="button" style={{ width: "100%" }} onClick={handleClickGuest}>비회원 정보 저장</button>
</div>
}
<h5 className="my-4 p-2" style={{ backgroundColor: "white", color: "black" }}>결제방법</h5>
<img src="/images/naverpay_button.png" />
<Kakaopay ticketInfo={ticketInfo} setTicketInfo={setTicketInfo} />
<div className="my-5">
<button className="btn btn-warning" type="button" style={{ width: "100%" }} onClick={reservationComplete}>결제완료</button>
</div>
</div>
<div className="col-sm-4">
<div className="text-center rounded-3 p-3" style={{ backgroundColor: "#252525" }}>
<img style={{ maxHeight: "10rem" }} src={`https://image.tmdb.org/t/p/original${ticketInfo.poster_path}`} alt="영화포스터" />
<h5 className="my-3">{ticketInfo.title}</h5>
<div>{ticketInfo.cinema}</div>
<div>{ticketInfo.time}</div>
<div className="mb-3">{ticketInfo.selectedTheater} {ticketInfo.selectedSeats.map(el => String.fromCharCode(parseInt(el.split('-')[0]) + 65) + el.split('-')[1]) + ' '}</div>
<div className="rounded-3 p-3" style={{ backgroundColor: '#404040' }}>
<div>청소년: {ticketInfo.teenager}</div>
<div>성인: {ticketInfo.adult}</div>
<div>경로우대: {ticketInfo.elderly}</div>
<div> 결제금액: {ticketInfo.teenager * 7000 + ticketInfo.adult * 8000 + ticketInfo.elderly * 6000}</div>
</div>
</div>
</div>
</div>
</div>
)
}
export default Payment
\ No newline at end of file
.labelStyle {
display: inline-block;
width: 80px;
text-align: right;
margin-right: 1rem;
}
.warningText{
font-size: small;
}
\ No newline at end of file
export { default } from "./PaymentPage"
\ No newline at end of file
......@@ -10,7 +10,7 @@ const TicketingPage = ({ location }) => {
const [ticketInfo, setTicketInfo] = useState({
...location.state,
cinema:"",
selectedTheater: 1,
selectedTheater: "1",
time: "2021/07/21 10:00"
})
const [cinemaInfo, setCinemaInfo] = useState({})
......
......@@ -29,10 +29,11 @@ const TicketingSeatPage = ({ location }) => {
async function getInfo() {
try {
const response = await axios.post('/api/theater/getInfo', {
theaterNum: ticketInfo.selectedTheater
theaterName: ticketInfo.selectedTheater
})
console.log(response.data)
setTheaterInfo(response.data)
const response2 = await axios.post('/api/reservation/findreservation', {
timetable: 1
})
......@@ -90,7 +91,7 @@ const TicketingSeatPage = ({ location }) => {
{console.log(ticketInfo)}
{console.log(reservedSeats)}
<div className="row justify-content-center my-5">
<div className="col-sm-4 mb-3 ">
<div className="col-sm-4">
<h3 className="py-2 text-white text-center" style={{ border: "3px solid #000000", borderBottom: "3px solid #FEDC00" }}>좌석선택</h3>
</div>
</div>
......@@ -144,8 +145,8 @@ const TicketingSeatPage = ({ location }) => {
<li>영화: {ticketInfo.title}</li>
<li>극장: {ticketInfo.cinema}</li>
<li>일시: 2021/07/21 10:00 </li>
<li>상영관: 3</li>
<li>좌석: {selectedSeats}</li>
<li>상영관: {ticketInfo.selectedTheater}</li>
<li>좌석: {selectedSeats.map(el=>String.fromCharCode(parseInt(el.split('-')[0]) + 64)+el.split('-')[1])+' '}</li>
</ul>
: <div></div>}
</div>
......
import nodemailer from "nodemailer"
const SendMail = async (req,res) => {
const {email, title, cinema,selectedTheater, time, nickname} = req.body
const {email, title, cinema,selectedTheater, time, name} = req.body
const selectedSeats = req.body.selectedSeats
const sendMail = async (email,title, cinema,selectedTheater, time, nickname, selectedSeats) => {
const sendMail = async (email,title, cinema,selectedTheater, time, name, selectedSeats) => {
// 메일을 전달해줄 객체
const transporter = nodemailer.createTransport({
host: 'smtp.gmail.com',
......@@ -26,7 +26,7 @@ const SendMail = async (req,res) => {
from: `${cinema} <angelayoon99@gmail.com>`,
to: `${email}`,
subject: `${cinema} 예매확인내역: ${title}`,
text: `${nickname}님의 예매: ${title} / ${cinema} / ${selectedTheater}관 / 일시: ${time} / ${selectedSeats} /`,
text: `${name}님의 예매: ${title} / ${cinema} / ${selectedTheater}관 / 일시: ${time} / ${selectedSeats} /`,
};
// 메일 전송
......@@ -39,7 +39,7 @@ const SendMail = async (req,res) => {
}
}
sendMail(email,title, cinema,selectedTheater, time, nickname, selectedSeats);
sendMail(email,title, cinema,selectedTheater, time, name, selectedSeats);
}
......
import axios from 'axios'
import { Reservation,Theater } from '../db/index.js'
import { Movie, Reservation, Theater } from '../db/index.js'
import sequelize from 'sequelize'
const { Op } = sequelize
const findReservation = async (req,res) => {
const {timetable} = req.body
const findReservation = async (req, res) => {
const { timetable } = req.body
try {
const reservedSeats = await Reservation.findAll({
where: {
timetable:timetable
timetable: timetable
}
})
console.log(reservedSeats)
res.json(reservedSeats)
} catch (error) {
return res.status(500).send(error.message || "이미 예매되어있는 좌석을 찾는 중 오류발생")
res.status(500).send(error.message || "이미 예매되어있는 좌석을 찾는 중 오류발생")
}
}
export default {findReservation}
\ No newline at end of file
const saveReservation = async (req, res) => {
const { movieId, selectedTheater, timetable, payment,user, userType } = req.body
const rows = req.body.selectedSeats.map(el => el.split('-')[0])
const cols = req.body.selectedSeats.map(el => el.split('-')[1])
try {
for (let index = 0; index < rows.length; index++) {
const reservation = await Reservation.create({
user: user,
userType: userType,
movieId: movieId,
theater: selectedTheater,
row: rows[index],
col: cols[index],
timetable: timetable,
payment: payment
})
res.json(reservation)
}
const movie = await Movie.findOne({
where: {
movieId: movieId
}
})
movie.ticket_sales++
await movie.save();
} catch (error) {
console.log(error)
res.status(500).send(error.message || "예매DB에 저장 실패")
}
}
export default {
findReservation,
saveReservation
}
\ No newline at end of file
import { Theater, TicketFee } from "../db/index.js";
const getTheaterInfo = async (req, res) => {
const { theaterNum } = req.body
const { theaterName } = req.body
try {
const theaterInfo = await Theater.findOne({
where: { theaterNum: theaterNum },
attributes: ['theaterNum', 'rows', 'columns', 'theaterType']
where: { theaterName: String(theaterName) },
attributes: ['theaterName', 'rows', 'columns']
})
// console.log("theaterInfo====",theaterInfo)
return res.json(theaterInfo)
......
import jwt from "jsonwebtoken";
import config from "../config/app.config.js";
import { User, Role } from '../db/index.js';
<<<<<<< HEAD
import { User, Role, Guest } from '../db/index.js';
const getUser = async (req, res) => {
try {
if (req.cookies) {
if (req.cookies.butterStudio) {
const token = req.cookies.butterStudio;
const decoded = jwt.verify(token, config.jwtSecret);
res.json(decoded);
......@@ -17,9 +16,6 @@ const getUser = async (req, res) => {
return res.status(500).send("유저를 가져오지 못했습니다.");
}
}
=======
// import Twilio from "twilio";
>>>>>>> jiwon
const login = async (req, res) => {
try {
......@@ -175,7 +171,6 @@ const comparePw = async (req, res) => {
}
}
<<<<<<< HEAD
const modifyUser = async (req, res) => {
try {
const token = req.cookies.butterStudio;
......@@ -189,10 +184,10 @@ const modifyUser = async (req, res) => {
if (decoded) {
let user = await User.findOne({ where: { id: decoded.id } });
await user.update({
email : userEmail,
nickname : userNickName,
phoneNumber : userMbnum,
password : userPassword,
email: userEmail,
nickname: userNickName,
phoneNumber: userMbnum,
password: userPassword,
});
res.json(user);
}
......@@ -202,21 +197,37 @@ const modifyUser = async (req, res) => {
res.status(500).send("수정 에러. 나중에 다시 시도 해주세요");
}
};
=======
const getUserInfo = async (req,res)=>{
const {id} = req.body
const getUserInfo = async (req, res) => {
const { id } = req.body
console.log(id)
try {
const userInfo = await User.findOne({
where:{id:id},
attributes:["userId","email","nickname","birth","phoneNumber"]
where: { id: id },
attributes: ["id","userId", "email", "nickname", "birth", "phoneNumber"]
})
res.json(userInfo)
} catch (error) {
res.status(500).send("회원정보 불러오기 실패");
}
}
const saveGuestInfo = async (req, res) => {
const { name, email, birth, phoneNumber, password } = req.body
try {
const newGuest = await Guest.create({
name: name,
email: email,
birth: birth,
phoneNumber: phoneNumber,
password: password,
});
res.json(newGuest);
} catch (error) {
console.log(error)
res.status(500).send("비회원정보 등록 실패");
}
}
>>>>>>> jiwon
export default {
getUser,
......@@ -226,10 +237,8 @@ export default {
confirmMbnum,
signup,
getNickName,
<<<<<<< HEAD
comparePw,
modifyUser
=======
getUserInfo
>>>>>>> jiwon
modifyUser,
getUserInfo,
saveGuestInfo
}
......@@ -8,6 +8,7 @@ import TheaterTypeModel from "../models/theatertype.model.js";
import TicketFeeModel from "../models/ticketfee.model.js";
import TimeTableModel from '../models/role.model.js';
import ReservationModel from '../models/reservation.model.js';
import GuestModel from '../models/guest.model.js'
import dbConfig from "../config/db.config.js";
const sequelize = new Sequelize(
......@@ -35,6 +36,7 @@ const TheaterType = TheaterTypeModel(sequelize)
const TicketFee = TicketFeeModel(sequelize)
const TimeTable = TimeTableModel(sequelize)
const Reservation = ReservationModel(sequelize)
const Guest = GuestModel(sequelize)
User.belongsTo(Role);
Role.hasOne(User);
......@@ -53,5 +55,6 @@ export {
TheaterType,
TicketFee,
TimeTable,
Reservation
Reservation,
Guest
}
\ No newline at end of file
......@@ -19,7 +19,7 @@ sequelize
);
const adminRole = await Role.findOne({ where: { name: "admin" } });
console.log("adminRole : ", adminRole);
// console.log("adminRole : ", adminRole);
if (!adminRole) {
await User.create({
userId: "admin",
......
import Sequelize from "sequelize";
const { DataTypes } = Sequelize;
const GuestModel = (sequelize) => {
const Guest = sequelize.define(
"guest",
{
id: {
type: DataTypes.INTEGER,
primaryKey: true,
autoIncrement: true,
},
name: {
type: DataTypes.STRING,
},
email: {
type: DataTypes.STRING,
},
birth: {
type: DataTypes.STRING,
},
phoneNumber: {
type: DataTypes.STRING
},
password: {
type: DataTypes.STRING,
},
},
{
timestamps: true,
freezeTableName: true,
tableName: "guests",
}
);
return Guest
};
export default GuestModel
\ No newline at end of file
......@@ -26,11 +26,14 @@ const ReservationModel = (sequelize) => {
timetable:{
type: DataTypes.INTEGER,
},
userType:{
type: DataTypes.STRING,
},
user:{
type: DataTypes.INTEGER,
},
payment:{
type: DataTypes.INTEGER,
type: DataTypes.STRING,
}
},
{
......
import express from "express";
import userRouter from './user.route.js'
import movieRouter from './movie.route.js'
import theaterRouter from "./theater.route.js";
import cinemaRouter from "./cinema.route.js";
import kakaopayRouter from "./kakaopay.route.js";
import emailRouter from './email.route.js'
......
......@@ -7,4 +7,7 @@ const router = express.Router();
router.route('/findreservation')
.post(ReservationCtrl.findReservation)
router.route('/save')
.post(ReservationCtrl.saveReservation)
export default router;
\ No newline at end of file
......@@ -40,11 +40,10 @@ router
.route("/:id/:token")
.get(userCtrl.confirmMbnum)
// router
// .route("/:iddd")
// .get(userCtrl.getNickName)
router.route('/getuserinfo')
.post(userCtrl.getUserInfo)
router.route('/guest/save')
.post(userCtrl.saveGuestInfo)
export default router;
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment