Commit 3916c374 authored by Kim, Subin's avatar Kim, Subin
Browse files

Merge branch 'master' into kimpen

parents eb9bcd78 52c103b2
<svg width="97" height="97" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" overflow="hidden"><defs><clipPath id="clip0"><rect x="201" y="119" width="97" height="97"/></clipPath></defs><g clip-path="url(#clip0)" transform="translate(-201 -119)"><path d="M248.49 131.63C244.751 129.811 240.911 128.599 237.072 128.094 248.186 139.107 251.521 156.385 244.145 171.239 236.87 186.092 220.905 193.771 205.547 191.649 208.275 194.377 211.609 196.802 215.247 198.621 233.738 207.816 256.169 200.237 265.263 181.747 274.356 163.256 266.98 140.926 248.49 131.63Z" fill="#4472C4"/><path d="M288.805 174.068C288.603 173.765 288.603 173.36 288.805 173.057L290.725 170.228C290.927 169.824 290.927 169.42 290.725 169.117 290.523 168.814 290.018 168.611 289.715 168.712L286.582 169.521C286.178 169.622 285.774 169.42 285.572 169.117L283.652 166.288C283.349 165.883 282.945 165.782 282.541 165.883 282.136 165.984 281.833 166.389 281.833 166.793L281.631 170.228C281.631 170.632 281.328 170.935 280.924 171.137L277.792 171.845C277.388 171.946 277.084 172.249 277.084 172.754 277.084 173.158 277.286 173.562 277.691 173.664L279.004 174.371 280.722 175.28C280.823 175.381 281.025 175.482 281.126 175.684 281.227 175.886 281.227 175.988 281.227 176.19L281.227 179.625C281.227 180.029 281.429 180.433 281.833 180.534 282.237 180.635 282.642 180.534 282.945 180.231L285.168 177.503C285.471 177.2 285.875 177.099 286.279 177.2L289.614 178.413C290.018 178.514 290.422 178.413 290.725 178.109 291.028 177.806 291.028 177.301 290.826 176.998L288.805 174.068Z" fill="#4472C4"/><path d="M279.206 148.908 281.934 143.957C282.237 143.351 282.844 143.048 283.551 143.149L289.108 144.058C289.816 144.159 290.422 143.856 290.725 143.25 291.028 142.644 290.927 141.835 290.523 141.431L286.683 137.289C286.279 136.884 286.178 136.177 286.38 135.571L288.502 130.418C288.704 129.811 288.603 129.104 288.199 128.7 287.795 128.296 286.986 128.094 286.481 128.397L281.732 130.721C281.126 131.024 280.419 130.822 280.015 130.418L276.175 126.578C275.67 126.073 274.861 125.972 274.255 126.174 273.649 126.477 273.346 127.184 273.346 127.791L274.053 133.146C274.154 133.853 273.851 134.459 273.245 134.762L268.496 137.086C267.89 137.39 267.586 137.996 267.688 138.703 267.789 139.309 268.294 139.916 268.9 140.017L271.224 140.724 274.255 141.633C274.558 141.734 274.76 141.936 275.064 142.139 275.266 142.341 275.367 142.644 275.468 142.947L276.377 148.504C276.478 149.211 276.983 149.717 277.691 149.818 278.398 149.919 278.903 149.515 279.206 148.908Z" fill="#4472C4"/></g></svg>
\ No newline at end of file
<svg width="114" height="115" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" overflow="hidden"><defs><clipPath id="clip0"><rect x="108" y="110" width="114" height="115"/></clipPath></defs><g clip-path="url(#clip0)" transform="translate(-108 -110)"><path d="M33.4246 56.9691C33.4286 56.0641 33.4845 55.1602 33.592 54.2616L19.4263 54.2616 19.4263 59.6054 33.5813 59.6054C33.4799 58.7302 33.4275 57.8501 33.4246 56.9691Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/><path d="M42.3569 38.5379 32.3131 28.5 28.5344 32.2774 38.5736 42.3166C39.6887 40.9189 40.9578 39.6513 42.3569 38.5379Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/><path d="M56.9739 33.4198C57.8669 33.4235 58.7589 33.4779 59.6458 33.5825L59.6458 19.3871 54.302 19.3871 54.302 33.5825C55.1888 33.4778 56.0809 33.4235 56.9739 33.4198Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/><path d="M75.373 42.3118 85.4121 32.2727 81.6335 28.5 71.5896 38.5427C72.9887 39.6524 74.2579 40.9169 75.373 42.3118Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/><path d="M38.5439 71.5861 28.5344 81.5931 32.3131 85.3717 42.3166 75.3694C40.9207 74.2544 39.655 72.9852 38.5439 71.5861Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/><path d="M56.9739 80.5184C56.0809 80.5148 55.1888 80.4605 54.302 80.3558L54.302 94.4799 59.6458 94.4799 59.6458 80.3558C58.7589 80.4604 57.8669 80.5146 56.9739 80.5184Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/><path d="M80.3546 54.2616C80.5758 56.0358 80.5794 57.8303 80.3652 59.6054L94.525 59.6054 94.525 54.2616Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/><path d="M71.63 75.3694 81.6335 85.3717 85.4121 81.5931 75.4062 71.5861C74.2939 72.9853 73.0272 74.2545 71.63 75.3694Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/><path d="M75.7732 56.9691C75.7732 67.3524 67.3559 75.7696 56.9727 75.7696 46.5894 75.7696 38.1722 67.3524 38.1722 56.9691 38.1722 46.5859 46.5894 38.1686 56.9727 38.1686 56.973 38.1686 56.9735 38.1686 56.9739 38.1686 67.3564 38.1686 75.7732 46.5854 75.7732 56.9679 75.7732 56.9683 75.7732 56.9688 75.7732 56.9691Z" fill="#FFC000" transform="matrix(1 0 0 1.00877 108 110)"/></g></svg>
\ No newline at end of file
...@@ -15,8 +15,9 @@ import AdminPage from "./pages/AdminPage/AdminPage"; ...@@ -15,8 +15,9 @@ import AdminPage from "./pages/AdminPage/AdminPage";
import TicketingPage from "./pages/TicketingPage"; import TicketingPage from "./pages/TicketingPage";
import TicketingSeatPage from './pages/TicketingSeatPage' import TicketingSeatPage from './pages/TicketingSeatPage'
import SearchPage from "./pages/SearchPage"; import SearchPage from "./pages/SearchPage";
import Payment from "./pages/PaymentPage/PaymentPage"; import PaymentPage from "./pages/PaymentPage/PaymentPage";
import PaymentCompletePage from "./pages/PaymentCompletePage"; import PaymentCompletePage from "./pages/PaymentCompletePage";
import PaymentFailPage from "./pages/PaymentFailPage";
function App() { function App() {
...@@ -39,9 +40,10 @@ function App() { ...@@ -39,9 +40,10 @@ function App() {
<Route path="/guest" component={GuestPage} /> <Route path="/guest" component={GuestPage} />
<Route path="/ticket/seat" component={TicketingSeatPage} /> <Route path="/ticket/seat" component={TicketingSeatPage} />
<Route path="/ticket" component={TicketingPage} /> <Route path="/ticket" component={TicketingPage} />
<Route path="/payment" component={Payment} /> <Route path="/payment" component={PaymentPage} />
<Route path="/paymentcomplete" component={PaymentCompletePage} /> <Route path="/paymentcomplete" component={PaymentCompletePage} />
<Route path="/theater" component={TheaterPage} /> <Route path="/paymentfail" component={PaymentFailPage} />
<Route path="/theater" component={TheaterPage}/>
<Route path="/search" component={SearchPage} /> <Route path="/search" component={SearchPage} />
</Switch> </Switch>
</div> </div>
......
import axios from "axios";
import { baseUrl } from "../utils/baseUrl.js";
const approveReq = async (info) => {
const url = `${baseUrl}/api/kakaopay/test/single`;
const { data } = await axios.post(url,info);
return data
}
const approveSuccess = async (info) => {
const url = `${baseUrl}/api/kakaopay/success`;
const { data } = await axios.post(url,info);
return data
}
const paymentCancel = async (info) => {
const url = `${baseUrl}/api/kakaopay/cancel`;
const { data } = await axios.post(url,info);
return data
}
const kakaopayApi = {
approveReq,
approveSuccess,
paymentCancel
}
export default kakaopayApi
\ No newline at end of file
...@@ -4,7 +4,7 @@ import { baseUrl } from "../utils/baseUrl.js"; ...@@ -4,7 +4,7 @@ import { baseUrl } from "../utils/baseUrl.js";
const findReservedSeats = async (timeTable) => { const findReservedSeats = async (timeTable) => {
console.log(timeTable) console.log(timeTable)
const url = `${baseUrl}/api/reservation/findreservation`; const url = `${baseUrl}/api/reservation/findreservation`;
const { data } = await axios.post(url,{timeTable:timeTable}); const { data } = await axios.post(url, { timeTable: timeTable });
return data return data
} }
...@@ -25,12 +25,26 @@ const save = async (save) => { ...@@ -25,12 +25,26 @@ const save = async (save) => {
const url = `${baseUrl}/api/reservation/save`; const url = `${baseUrl}/api/reservation/save`;
const { data } = await axios.post(url, save); const { data } = await axios.post(url, save);
return data return data
}
const saveTid = async (tid) => {
const url = `${baseUrl}/api/reservation/savetid`;
const { data } = await axios.post(url, tid);
return data
} }
const deleteReservation = async () => {
const url = `${baseUrl}/api/reservation/delete`;
const { data } = await axios.get(url);
return data
}
const reservationApi = { const reservationApi = {
findReservation, findReservation,
findReservedSeats, findReservedSeats,
findOneReservation, findOneReservation,
save save,
saveTid,
deleteReservation
} }
export default reservationApi export default reservationApi
\ No newline at end of file
...@@ -51,7 +51,10 @@ const TimeTable = ({ ticketInfo = { movieId: 0 }, setTicketInfo }) => { ...@@ -51,7 +51,10 @@ const TimeTable = ({ ticketInfo = { movieId: 0 }, setTicketInfo }) => {
...ticketInfo, ...ticketInfo,
timetableId: time.id, timetableId: time.id,
time: time.date.split('T')[0] + " " + hours + ":" + mins, time: time.date.split('T')[0] + " " + hours + ":" + mins,
selectedTheater: time.theater.theaterName selectedTheater: time.theater.theaterName,
theaterId:time.theaterId,
partTime: time.partTime,
week: time.week
}) })
} }
...@@ -65,7 +68,7 @@ const TimeTable = ({ ticketInfo = { movieId: 0 }, setTicketInfo }) => { ...@@ -65,7 +68,7 @@ const TimeTable = ({ ticketInfo = { movieId: 0 }, setTicketInfo }) => {
if (ticketInfo.movieId !== 0) if (ticketInfo.movieId !== 0)
return <div className="d-inline-flex m-2"> return <div className="d-inline-flex m-2">
<div className={`card text-dark ${styles.cursor}`} onClick={() => handleClick(time)}> <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-body py-1"><img src={`${time.partTime==="morning"?'/images/sun.svg': time.partTime==="night"?'/images/moon.svg' :'...'} `} style={{width:'20px'}} alt=""/>{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 className="card-footer text-center py-1">{time.theater.rows * time.theater.columns - time.reservations} / {time.theater.rows * time.theater.columns}</div>
</div> </div>
</div> </div>
...@@ -80,7 +83,9 @@ const TimeTable = ({ ticketInfo = { movieId: 0 }, setTicketInfo }) => { ...@@ -80,7 +83,9 @@ const TimeTable = ({ ticketInfo = { movieId: 0 }, setTicketInfo }) => {
</div> </div>
})} })}
</div>) </div>)
: <p className="text-center mt-5 mb-0">서버에 저장되어 있는 상영시간표가 존재하지 않습니다.<br />아래의 양식을 작성해 새로운 상영시간표를 등록해주세요.</p>} : <p className="text-center mt-5 mb-0">서버에 저장되어 있는 상영시간표가 존재하지 않습니다.
{/* <br />아래의 양식을 작성해 새로운 상영시간표를 등록해주세요. */}
</p>}
</> </>
) )
} }
......
import { useState, useEffect } from "react" import { Link } from "react-router-dom"
const BoxOffice = ({TMDB_TopRated_Data}) => { const BoxOffice = ({ TMDB_TopRated_Data }) => {
return ( return (
<div className="container text-center my-3"> <div className="container text-center my-3">
{/* <div id="carouselExampleControls" className="carousel slide" data-bs-ride="carousel"> <h2 className="fw-bold text-white text-center my-5">BoxOffice</h2>
{console.log(TMDB_TopRated_Data)}
<div id="carouselExampleControls" className="carousel slide" data-bs-ride="carousel">
<div className="carousel-inner"> <div className="carousel-inner">
{TMDB_TopRated_Data.length>0 {TMDB_TopRated_Data.length > 0
? ?
TMDB_TopRated_Data.map((movie, index) => { TMDB_TopRated_Data.map((movie, index) =>
<div className={`carousel-item ${index === 0 ? "active" : ""}`}> <div className={`carousel-item ${index === 0 ? " active" : ""}`}>
{console.log(movie.poster_path)} <Link to={{
<img src={`https://image.tmdb.org/t/p/original${movie.poster_path}`} className="d-block w-100" alt="Movie Poster"/> pathname: `/movie/${movie.id}`,
state: {
...movie
}
}}
>
<img src={`https://image.tmdb.org/t/p/original${movie.poster_path}`} style={{ width: "200px" }} className="" alt="Movie Poster" />
</Link>
<div className="mt-1 text-white">{index + 1}</div>
</div> </div>
}) )
: :
<div className="carousel-item"> <div className="carousel-item">
{console.log("스틸컷 불러오기 오류")} {console.log("스틸컷 불러오기 오류")}
...@@ -29,7 +40,7 @@ const BoxOffice = ({TMDB_TopRated_Data}) => { ...@@ -29,7 +40,7 @@ const BoxOffice = ({TMDB_TopRated_Data}) => {
<span className="carousel-control-next-icon" aria-hidden="true"></span> <span className="carousel-control-next-icon" aria-hidden="true"></span>
<span className="visually-hidden">Next</span> <span className="visually-hidden">Next</span>
</button> </button>
</div> */} </div>
</div> </div>
) )
......
...@@ -23,25 +23,24 @@ const Collection = ({ TMDB_TopRated_Data }) => { ...@@ -23,25 +23,24 @@ const Collection = ({ TMDB_TopRated_Data }) => {
return ( return (
<> <>
<h2 className="fw-bold text-white text-center my-5">Movie Collection</h2> <h2 className="fw-bold text-white text-center my-5">Movie Collection</h2>
<div className="d-flex justify-content-sm-center" style={{ marginBottom: "8rem" }}> <div className="row justify-content-sm-center" style={{ marginBottom: "8rem" }}>
<div className="col-md-8"> <div className="col-sm-8">
{videoUrls.length > 0 {videoUrls.length > 0
? ?
<div className="">
<div className="ratio ratio-16x9"> <div className="ratio ratio-16x9">
<iframe src={`https://www.youtube.com/embed/${videoUrls[0].key}`} title="YouTube video" allowFullScreen></iframe> <iframe src={`https://www.youtube.com/embed/${videoUrls[0].key}`} title="YouTube video" allowFullScreen></iframe>
</div> </div>
</div>
: <div className="text-center">예고편 정보가 존재하지 않습니다.</div>} : <div className="text-center">예고편 정보가 존재하지 않습니다.</div>}
</div> </div>
<div className="col-sm-3">
{TMDB_TopRated_Data.length > 0 {TMDB_TopRated_Data.length > 0
? ?
<img src={`https://image.tmdb.org/t/p/original${TMDB_TopRated_Data[0].poster_path}`} className="col-md-3 bg-black" /> <img src={`https://image.tmdb.org/t/p/original${TMDB_TopRated_Data[0].poster_path}`} className="img-fluid bg-black" />
: :
<div className="col-md-3"></div> <div></div>
} }
</div> </div>
</div>
</> </>
) )
} }
......
import kakaopayApi from "../apis/kakaopay.api"
import catchErrors from "../utils/catchErrors"
const KakaopaymentCancelBtn = () => {
const [error, setError] = useState()
async function paymentCancel() {
try {
setError("")
//실행하기 전에 먼저 reservation에서 해당하는 예매건에 대한 tid가져오기
const response = await kakaopayApi.paymentCancel({
cid: 'TC0ONETIME',
tid: '',
cancel_amount: '',
cancel_tax_free_amount:0,
})
} catch (error) {
catchErrors(error,setError)
}
}
return (
<button className="btn btn-warning" onClick={paymentCancel }>결제취소</button>
)
}
\ No newline at end of file
...@@ -53,12 +53,14 @@ const TheaterInfo = () => { ...@@ -53,12 +53,14 @@ const TheaterInfo = () => {
try { try {
const response = await cinemaApi.getCinemaInfo() const response = await cinemaApi.getCinemaInfo()
const response2 = await theaterApi.getAll() const response2 = await theaterApi.getAll()
setCinemaInfo({ ...response.data, theaterNum: response2.data.length }) if (response && response2) {
setCinemaInfo({ ...response, theaterNum: response2.length })
setCurrentInfo({ setCurrentInfo({
name: "대중교통 안내", name: "대중교통 안내",
title: "transportation", title: "transportation",
information: response.data.transportation information: response.transportation
}) })
}
} catch (error) { } catch (error) {
catchErrors(error, setError) catchErrors(error, setError)
} }
...@@ -75,7 +77,7 @@ const TheaterInfo = () => { ...@@ -75,7 +77,7 @@ const TheaterInfo = () => {
return ( return (
<> <>
{cinemaInfo ? {cinemaInfo ?
<div> <div >
<h2 className="m-5">{cinemaInfo.cinemaName}</h2> <h2 className="m-5">{cinemaInfo.cinemaName}</h2>
<div className="my-3 text-center"> <div className="my-3 text-center">
<img src="/images/movieTheater.jpg" style={{ width: "80%" }} /> <img src="/images/movieTheater.jpg" style={{ width: "80%" }} />
...@@ -111,7 +113,7 @@ const TheaterInfo = () => { ...@@ -111,7 +113,7 @@ const TheaterInfo = () => {
<div id="map"></div> <div id="map"></div>
</div> </div>
: :
<div> <div className="pb-5">
극장정보를 불러올 없습니다. 극장정보를 불러올 없습니다.
</div>} </div>}
</> </>
......
...@@ -8,7 +8,12 @@ const TicketingTheater = ({ ticketInfo, cinemaInfo, setTicketInfo }) => { ...@@ -8,7 +8,12 @@ const TicketingTheater = ({ ticketInfo, cinemaInfo, setTicketInfo }) => {
return ( return (
<div className="d-grid gap-2"> <div className="d-grid gap-2">
{cinemaInfo
?
<button name={cinemaInfo.cinemaName} className={`${ticketInfo.cinema === cinemaInfo.cinemaName ? styles.on : styles.btn}`} onClick={handleClick}>{cinemaInfo.cinemaName}</button> <button name={cinemaInfo.cinemaName} className={`${ticketInfo.cinema === cinemaInfo.cinemaName ? styles.on : styles.btn}`} onClick={handleClick}>{cinemaInfo.cinemaName}</button>
:
<></>
}
</div> </div>
) )
} }
......
...@@ -66,7 +66,7 @@ const MoviePage = ({ location }) => { ...@@ -66,7 +66,7 @@ const MoviePage = ({ location }) => {
</div> </div>
<div className="col-sm-6" style={{ color: "white" }}> <div className="col-sm-6" style={{ color: "white" }}>
<h1 className="pb-3">{movieInfo.title}</h1> <h1 className="pb-3">{movieInfo.title}</h1>
<p>예매율:{Math.round((movieInfo.ticket_sales / (movieInfo.totalReservationRate.totalReservationRate || 1)) * 100)}% 누적관객수: {movieInfo.ticket_sales}</p> <p>예매율: {Math.round((movieInfo.ticket_sales / (movieInfo.totalReservationRate.totalReservationRate || 1)) * 100)}%</p>
{movieInfo.director || movieInfo.cast {movieInfo.director || movieInfo.cast
? ?
<> <>
...@@ -80,7 +80,7 @@ const MoviePage = ({ location }) => { ...@@ -80,7 +80,7 @@ const MoviePage = ({ location }) => {
if (idx !== 0) return acc + ', ' + cur.name if (idx !== 0) return acc + ', ' + cur.name
else return acc + cur.name else return acc + cur.name
}, "")}</p> }, "")}</p>
<p>개봉일:{movieInfo.release_date}</p> <p>개봉일: {movieInfo.release_date}</p>
<div className="text-end"> <div className="text-end">
<Link to={{ <Link to={{
pathname: `/ticket`, pathname: `/ticket`,
...@@ -101,9 +101,9 @@ const MoviePage = ({ location }) => { ...@@ -101,9 +101,9 @@ const MoviePage = ({ location }) => {
<li className="nav-item" role="presentation"> <li className="nav-item" role="presentation">
<button className="nav-link mx-auto" style={{ color: "white", borderColor: "black", backgroundColor: "black", borderBottom: state === 1 ? "3px solid" : "none", borderBottomColor: state === 1 ? "#FEDC00" : "black" }} id="stillcut-tab" data-bs-toggle="tab" data-bs-target="#stillcut" type="button" role="tab" aria-controls="stillcut" aria-selected="false" onClick={() => setState(1)}>예고편</button> <button className="nav-link mx-auto" style={{ color: "white", borderColor: "black", backgroundColor: "black", borderBottom: state === 1 ? "3px solid" : "none", borderBottomColor: state === 1 ? "#FEDC00" : "black" }} id="stillcut-tab" data-bs-toggle="tab" data-bs-target="#stillcut" type="button" role="tab" aria-controls="stillcut" aria-selected="false" onClick={() => setState(1)}>예고편</button>
</li> </li>
<li className="nav-item" role="presentation"> {/* <li className="nav-item" role="presentation">
<button className="nav-link mx-auto" style={{ color: "white", borderColor: "black", backgroundColor: "black", borderBottom: state === 2 ? "3px solid" : "none", borderBottomColor: state === 2 ? "#FEDC00" : "black" }} id="review-tab" data-bs-toggle="tab" data-bs-target="#review" type="button" role="tab" aria-controls="review" aria-selected="false" onClick={() => setState(2)}>관람평</button> <button className="nav-link mx-auto" style={{ color: "white", borderColor: "black", backgroundColor: "black", borderBottom: state === 2 ? "3px solid" : "none", borderBottomColor: state === 2 ? "#FEDC00" : "black" }} id="review-tab" data-bs-toggle="tab" data-bs-target="#review" type="button" role="tab" aria-controls="review" aria-selected="false" onClick={() => setState(2)}>관람평</button>
</li> </li> */}
</ul> </ul>
</div> </div>
<div className="tab-content text-center" id="myTabContent" style={{ color: "white" }}> <div className="tab-content text-center" id="myTabContent" style={{ color: "white" }}>
...@@ -113,9 +113,9 @@ const MoviePage = ({ location }) => { ...@@ -113,9 +113,9 @@ const MoviePage = ({ location }) => {
<div className="tab-pane fade" id="stillcut" role="tabpanel" aria-labelledby="stillcut-tab"> <div className="tab-pane fade" id="stillcut" role="tabpanel" aria-labelledby="stillcut-tab">
<Video movieId={movieInfo.id} /> <Video movieId={movieInfo.id} />
</div> </div>
<div className="tab-pane fade" id="review" role="tabpanel" aria-labelledby="review-tab"> {/* <div className="tab-pane fade" id="review" role="tabpanel" aria-labelledby="review-tab">
<div className="mt-5 pb-5 px-5">관람평</div> <div className="mt-5 pb-5 px-5">관람평</div>
</div> </div> */}
</div> </div>
</div> </div>
......
import axios from 'axios'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import axios from 'axios'
import moment from 'moment';
import { useAuth } from '../context/auth_context' import { useAuth } from '../context/auth_context'
import catchErrors from '../utils/catchErrors' import catchErrors from '../utils/catchErrors'
import reservationApi from '../apis/reservation.api' import reservationApi from '../apis/reservation.api'
import kakaopayApi from '../apis/kakaopay.api';
const PaymentCompletePage = () => { const PaymentCompletePage = () => {
const { user } = useAuth() const { user } = useAuth()
...@@ -24,20 +26,21 @@ const PaymentCompletePage = () => { ...@@ -24,20 +26,21 @@ const PaymentCompletePage = () => {
async function saveGuestReservation() { async function saveGuestReservation() {
try { try {
setError("")
const response = await axios.get(`/api/auth/guestinfo/${user.id}`); const response = await axios.get(`/api/auth/guestinfo/${user.id}`);
const response2 = await reservationApi.findOneReservation() const response2 = await reservationApi.findOneReservation()
console.log("예매내역=====",response2) const response3 = await reservationApi.saveTid({ tid: localStorage.getItem('tid')})
// if (response.data||response2) { if (response.data || response2) {
// const responseEmail = await axios.post('/api/email/send', { const responseEmail = await axios.post('/api/email/send', {
// reservationData: response2, reservationData: response2.map(el => { return { "row": el.row, "col": el.col } }),
// userData: { ...response.data }, userData: { ...response.data },
// cinema: "Butter Studio 조치원", cinema: "Butter Studio 조치원",
// title: "더 수어사이드 스쿼드", title: response2[0].title,
// theater: "1", theater: response2[0].theater.theaterName,
// time: "2021/07/21 10:00" time: response2[0].timetable.date.split('T')[0] + ' ' + moment(response2[0].timetable.start_time).format('HH:mm')
// }) })
// console.log(responseEmail.data) localStorage.removeItem('tid')
// } }
} catch (error) { } catch (error) {
catchErrors(error, setError) catchErrors(error, setError)
} }
...@@ -45,18 +48,23 @@ const PaymentCompletePage = () => { ...@@ -45,18 +48,23 @@ const PaymentCompletePage = () => {
async function saveUserReservation() { async function saveUserReservation() {
try { try {
setError("")
const response = await axios.post(`/api/auth/getuserinfo`, { const response = await axios.post(`/api/auth/getuserinfo`, {
id: user.id id: user.id
}) })
const response2 = await reservationApi.findOneReservation()
// if (response.data) { const response3 = await reservationApi.saveTid({ tid: localStorage.getItem('tid')})
// const responseEmail = await axios.post('/api/email/send', { if (response.data || response2) {
// ...response2.data, const responseEmail = await axios.post('/api/email/send', {
// ...response.data, reservationData: response2.map(el => { return { "row": el.row, "col": el.col } }),
userData: { ...response.data },
// }) cinema: "Butter Studio 조치원",
// console.log(responseEmail.data) title: response2[0].title,
// } theater: response2[0].theater.theaterName,
time: response2[0].timetable.date.split('T')[0] + ' ' + moment(response2[0].timetable.start_time).format('HH:mm')
})
localStorage.removeItem('tid')
}
} catch (error) { } catch (error) {
catchErrors(error, setError) catchErrors(error, setError)
} }
...@@ -64,9 +72,10 @@ const PaymentCompletePage = () => { ...@@ -64,9 +72,10 @@ const PaymentCompletePage = () => {
async function approveKakaopay(tid) { async function approveKakaopay(tid) {
try { try {
setError("")
const urlParams = new URLSearchParams(window.location.search); const urlParams = new URLSearchParams(window.location.search);
const pg_token = urlParams.get('pg_token'); const pg_token = urlParams.get('pg_token');
const response = await axios.post(`/api/kakaopay/success`, { const response = await kakaopayApi.approveSuccess({
'tid': tid, 'tid': tid,
cid: 'TC0ONETIME', cid: 'TC0ONETIME',
partner_order_id: 'butter_studio', partner_order_id: 'butter_studio',
...@@ -80,10 +89,18 @@ const PaymentCompletePage = () => { ...@@ -80,10 +89,18 @@ const PaymentCompletePage = () => {
} }
return ( return (
<div className="text-center"> <div className="container text-center py-5">
<h3>예매가 정상적으로 완료되었습니다.</h3> <h3 className="my-3 text-white">예매가 정상적으로 완료되었습니다.</h3>
<button>홈으로</button> {user.role === "member"
{user.role === "member" ? <button>마이페이지</button> : <></>} ?
<a href="/mypage">
<button className="btn btn-warning mx-1">마이페이지</button>
</a>
:
<a href="/">
<button className="btn btn-warning mx-1">홈으로</button>
</a>
}
</div> </div>
) )
} }
......
import { useEffect, useState } from 'react'
import { useAuth } from '../context/auth_context'
import catchErrors from '../utils/catchErrors'
import reservationApi from '../apis/reservation.api'
const PaymentCompletePage = () => {
const [error, setError] = useState()
useEffect(() => {
deleteReservation()
}, [])
async function deleteReservation() {
try {
const response = await reservationApi.deleteReservation()
localStorage.removeItem('tid')
} catch (error) {
catchErrors(error, setError)
}
}
return (
<div className="container text-center py-5">
<h3 className="my-3 text-white">결제에 실패하셨습니다.</h3>
<a href="/ticket">
<button className="btn btn-warning mx-1">다시 예매하기</button>
</a>
<a href="/">
<button className="btn btn-warning mx-1">홈으로</button>
</a>
</div>
)
}
export default PaymentCompletePage
\ No newline at end of file
import axios from 'axios' import axios from 'axios'
import { useEffect, useState } from 'react' import { useEffect, useState } from 'react'
import authApi from '../../apis/auth.api' import authApi from '../../apis/auth.api'
import kakaopayApi from '../../apis/kakaopay.api'
import reservationApi from '../../apis/reservation.api' import reservationApi from '../../apis/reservation.api'
import { useAuth } from '../../context/auth_context' import { useAuth } from '../../context/auth_context'
import catchErrors from '../../utils/catchErrors' import catchErrors from '../../utils/catchErrors'
...@@ -73,23 +74,24 @@ const Payment = ({ location }) => { ...@@ -73,23 +74,24 @@ const Payment = ({ location }) => {
userType: "member", userType: "member",
user: userInfo.id, user: userInfo.id,
...ticketInfo, ...ticketInfo,
timetable: 1
}) })
const responsekakao = await axios.post('/api/kakaopay/test/single', { const responsekakao = await kakaopayApi.approveReq({
cid: 'TC0ONETIME', cid: 'TC0ONETIME',
partner_order_id: 'butter_studio', partner_order_id: 'butter_studio',
partner_user_id: '000000'+ (userInfo.id || guestInfo.id), partner_user_id: '000000' + guestID,
item_name: ticketInfo.title, item_name: ticketInfo.title,
item_code: ticketInfo.movieId,
quantity: ticketInfo.adult + ticketInfo.youth + ticketInfo.senior, quantity: ticketInfo.adult + ticketInfo.youth + ticketInfo.senior,
total_amount: ticketInfo.totalFee, total_amount: ticketInfo.totalFee,
vat_amount: 0, vat_amount: 0,
tax_free_amount: 0, tax_free_amount: 0,
approval_url: 'http://localhost:3000/paymentcomplete', approval_url: 'http://localhost:3000/paymentcomplete',
fail_url: 'http://localhost:3000/ticket', fail_url: 'http://localhost:3000/paymentfail',
cancel_url: 'http://localhost:3000/ticket', cancel_url: 'http://localhost:3000/paymentfail',
}) })
if (response && responsekakao) { if (response && responsekakao) {
window.location.href = responsekakao.data.redirect_url localStorage.setItem('tid', responsekakao.tid)
window.location.href = responsekakao.redirect_url
} }
} else { } else {
if (guestID) { if (guestID) {
...@@ -97,12 +99,11 @@ const Payment = ({ location }) => { ...@@ -97,12 +99,11 @@ const Payment = ({ location }) => {
userType: "guest", userType: "guest",
user: guestID, user: guestID,
...ticketInfo, ...ticketInfo,
timetableId: 1
}) })
const responsekakao = await axios.post('/api/kakaopay/test/single', { const responsekakao = await kakaopayApi.approveReq({
cid: 'TC0ONETIME', cid: 'TC0ONETIME',
partner_order_id: 'butter_studio', partner_order_id: 'butter_studio',
partner_user_id: '000000'+ guestID, partner_user_id: '000000' + guestID,
item_name: ticketInfo.title, item_name: ticketInfo.title,
item_code: ticketInfo.movieId, item_code: ticketInfo.movieId,
quantity: ticketInfo.adult + ticketInfo.youth + ticketInfo.senior, quantity: ticketInfo.adult + ticketInfo.youth + ticketInfo.senior,
...@@ -110,12 +111,12 @@ const Payment = ({ location }) => { ...@@ -110,12 +111,12 @@ const Payment = ({ location }) => {
vat_amount: 0, vat_amount: 0,
tax_free_amount: 0, tax_free_amount: 0,
approval_url: 'http://localhost:3000/paymentcomplete', approval_url: 'http://localhost:3000/paymentcomplete',
fail_url: 'http://localhost:3000/ticket', fail_url: 'http://localhost:3000/paymentfail',
cancel_url: 'http://localhost:3000/ticket', cancel_url: 'http://localhost:3000/paymentfail',
}) })
if (response||responsekakao) { if (response && responsekakao) {
localStorage.setItem('tid',responsekakao.data.tid) localStorage.setItem('tid', responsekakao.tid)
window.location.href = responsekakao.data.redirect_url window.location.href = responsekakao.redirect_url
} }
} else { } else {
alert("비회원 정보를 모두 입력 후 비회원 정보 저장 버튼을 눌러주세요.") alert("비회원 정보를 모두 입력 후 비회원 정보 저장 버튼을 눌러주세요.")
...@@ -129,7 +130,6 @@ const Payment = ({ location }) => { ...@@ -129,7 +130,6 @@ const Payment = ({ location }) => {
return ( return (
<div className="container" style={{ color: "white" }}> <div className="container" style={{ color: "white" }}>
{console.log(ticketInfo)}
<div className="row justify-content-center my-5"> <div className="row justify-content-center my-5">
<div className="col-sm-4 "> <div className="col-sm-4 ">
<h3 className="py-2 text-white text-center" style={{ border: "3px solid #000000", borderBottom: "3px solid #FEDC00" }}>결제하기</h3> <h3 className="py-2 text-white text-center" style={{ border: "3px solid #000000", borderBottom: "3px solid #FEDC00" }}>결제하기</h3>
...@@ -211,7 +211,7 @@ const Payment = ({ location }) => { ...@@ -211,7 +211,7 @@ const Payment = ({ location }) => {
<h5 className="my-3">{ticketInfo.title}</h5> <h5 className="my-3">{ticketInfo.title}</h5>
<div>{ticketInfo.cinema}</div> <div>{ticketInfo.cinema}</div>
<div>{ticketInfo.time}</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="mb-3">{ticketInfo.selectedTheater} {ticketInfo.selectedSeats.map(el => String.fromCharCode(parseInt(el.split('-')[0]) + 64) + el.split('-')[1]) + ' '}</div>
<div className="rounded-3 p-3" style={{ backgroundColor: '#404040' }}> <div className="rounded-3 p-3" style={{ backgroundColor: '#404040' }}>
<div>성인: {ticketInfo.adult}</div> <div>성인: {ticketInfo.adult}</div>
<div>청소년: {ticketInfo.youth}</div> <div>청소년: {ticketInfo.youth}</div>
......
...@@ -44,7 +44,7 @@ const TheaterPage = () => { ...@@ -44,7 +44,7 @@ const TheaterPage = () => {
<TheaterInfo /> <TheaterInfo />
</div> </div>
<div className="tab-pane fade" id="stillcut" role="tabpanel" aria-labelledby="stillcut-tab"> <div className="tab-pane fade" id="stillcut" role="tabpanel" aria-labelledby="stillcut-tab">
<div>상영시간표</div> <div className="pb-5">상영시간표</div>
</div> </div>
<div className="tab-pane fade" id="review" role="tabpanel" aria-labelledby="review-tab"> <div className="tab-pane fade" id="review" role="tabpanel" aria-labelledby="review-tab">
<div className="d-flex justify-content-center"> <div className="d-flex justify-content-center">
......
...@@ -10,6 +10,7 @@ import catchErrors from "../utils/catchErrors.js" ...@@ -10,6 +10,7 @@ import catchErrors from "../utils/catchErrors.js"
const TicketingPage = ({ location }) => { const TicketingPage = ({ location }) => {
const [ticketInfo, setTicketInfo] = useState({ const [ticketInfo, setTicketInfo] = useState({
movieId: 0,
...location.state, ...location.state,
cinema: "", cinema: "",
selectedTheater: "", selectedTheater: "",
...@@ -24,7 +25,9 @@ const TicketingPage = ({ location }) => { ...@@ -24,7 +25,9 @@ const TicketingPage = ({ location }) => {
}, []) }, [])
useEffect(() => { useEffect(() => {
if (ticketInfo.movieId > 0) {
getMovieInfo() getMovieInfo()
}
}, [ticketInfo]) }, [ticketInfo])
async function getMovieInfo() { async function getMovieInfo() {
...@@ -50,11 +53,11 @@ const TicketingPage = ({ location }) => { ...@@ -50,11 +53,11 @@ const TicketingPage = ({ location }) => {
console.log(response.data) console.log(response.data)
setCinemaInfo(response.data) setCinemaInfo(response.data)
} catch (error) { } catch (error) {
console.log(error) catchErrors(error, setError)
} }
} }
return ( return (
<div className="container" style={{ backgroundColor: "black" }}> <div className="container pb-5" style={{ backgroundColor: "black" }}>
<div className="row justify-content-center my-5"> <div className="row justify-content-center my-5">
<div className="col-sm-4 mb-4 "> <div className="col-sm-4 mb-4 ">
<h3 className="py-2 text-white text-center" style={{ border: "3px solid #000000", borderBottom: "3px solid #FEDC00" }}>영화</h3> <h3 className="py-2 text-white text-center" style={{ border: "3px solid #000000", borderBottom: "3px solid #FEDC00" }}>영화</h3>
...@@ -70,12 +73,12 @@ const TicketingPage = ({ location }) => { ...@@ -70,12 +73,12 @@ const TicketingPage = ({ location }) => {
</div> </div>
</div> </div>
<div className="row p-3" style={{ backgroundColor: "#252525" }}> <div className="row p-3" style={{ backgroundColor: "#252525" }}>
<div className="col-sm-3 border-end text-center"> <div className="col-sm-3 text-center">
{movieInfo {movieInfo
? <img style={{ maxHeight: "10rem" }} src={`https://image.tmdb.org/t/p/original${movieInfo.poster_path}`} alt="영화포스터" /> ? <img style={{ maxHeight: "10rem" }} src={`https://image.tmdb.org/t/p/original${movieInfo.poster_path}`} alt="영화포스터" />
: <div className="mb-2" style={{ color: "white" }}>영화선택</div>} : <div className="mb-2" style={{ color: "white" }}>영화선택</div>}
</div> </div>
<div className="col-sm-6 border-end" style={{ color: "white" }}> <div className="col-sm-6" style={{ color: "white" }}>
<div className="mb-2 text-center">극장선택</div> <div className="mb-2 text-center">극장선택</div>
{movieInfo && ticketInfo.cinema {movieInfo && ticketInfo.cinema
? <ul> ? <ul>
...@@ -87,16 +90,16 @@ const TicketingPage = ({ location }) => { ...@@ -87,16 +90,16 @@ const TicketingPage = ({ location }) => {
: <div></div>} : <div></div>}
</div> </div>
<div className="col-sm-3 text-center"> <div className="col-sm-3 text-center">
<div className="mb-2" style={{ color: "white" }}>좌석선택</div> <div className="mb-3" style={{ color: "white" }}>좌석선택</div>
{movieInfo && ticketInfo.cinema {movieInfo && ticketInfo.cinema && ticketInfo.timetableId
? ?
<Link to={{ <Link to={{
pathname: `/ticket/seat`, pathname: `/ticket/seat`,
state: { ...ticketInfo, ...movieInfo } state: { ...ticketInfo, ...movieInfo }
}}> }}>
<img className="border border-3 rounded-3" src="/images/icons8-arrow-white.png" alt="예매하기" /> <img className="border border-3 rounded-3" src="/images/icons8-arrow-white.png" alt="예매하기" style={{width:'80px'}} />
</Link> </Link>
: <img className="border border-3 rounded-3" src="/images/icons8-arrow-white.png" alt="예매하기" /> : <img className="border border-3 rounded-3" src="/images/icons8-arrow-white.png" alt="예매하기" style={{width:'80px'}}/>
} }
</div> </div>
</div> </div>
......
...@@ -32,7 +32,7 @@ const TicketingSeatPage = ({ location }) => { ...@@ -32,7 +32,7 @@ const TicketingSeatPage = ({ location }) => {
useEffect(() => { useEffect(() => {
getInfo() getInfo()
}, []) }, [ticketInfo.timetableId])
useEffect(() => { useEffect(() => {
getTicketFee() getTicketFee()
...@@ -42,10 +42,10 @@ const TicketingSeatPage = ({ location }) => { ...@@ -42,10 +42,10 @@ const TicketingSeatPage = ({ location }) => {
try { try {
setError("") setError("")
const response = await axios.post('/api/theater/getInfo', { const response = await axios.post('/api/theater/getInfo', {
theaterId: ticketInfo.selectedTheater theaterId: ticketInfo.theaterId
}) })
setTheaterInfo(response.data) setTheaterInfo(response.data)
const response2 = await reservationApi.findReservedSeats(1); const response2 = await reservationApi.findReservedSeats(ticketInfo.timetableId);
const reserve = response2.map((el) => const reserve = response2.map((el) =>
el.row + '-' + el.col el.row + '-' + el.col
); );
...@@ -63,7 +63,9 @@ const TicketingSeatPage = ({ location }) => { ...@@ -63,7 +63,9 @@ const TicketingSeatPage = ({ location }) => {
theaterTypeId: theaterInfo.theatertypeId theaterTypeId: theaterInfo.theatertypeId
} }
}) })
const basicFee = response3.data[0].day + response3.data[0].defaultPrice + response3.data[0].weekdays const week = ticketInfo.week
const partTime = ticketInfo.partTime
const basicFee = response3.data[0][partTime] + response3.data[0].defaultPrice + response3.data[0][week]
setTicketFee({ setTicketFee({
adult: basicFee + response3.data[0].adult, adult: basicFee + response3.data[0].adult,
youth: basicFee + response3.data[0].youth, youth: basicFee + response3.data[0].youth,
...@@ -179,7 +181,7 @@ const TicketingSeatPage = ({ location }) => { ...@@ -179,7 +181,7 @@ const TicketingSeatPage = ({ location }) => {
? <ul> ? <ul>
<li>영화: {ticketInfo.title}</li> <li>영화: {ticketInfo.title}</li>
<li>극장: {ticketInfo.cinema}</li> <li>극장: {ticketInfo.cinema}</li>
<li>일시: 2021/07/21 10:00 </li> <li>일시: {ticketInfo.time} </li>
<li>상영관: {ticketInfo.selectedTheater}</li> <li>상영관: {ticketInfo.selectedTheater}</li>
<li>좌석: {selectedSeats.map(el => String.fromCharCode(parseInt(el.split('-')[0]) + 64) + el.split('-')[1]) + ' '}</li> <li>좌석: {selectedSeats.map(el => String.fromCharCode(parseInt(el.split('-')[0]) + 64) + el.split('-')[1]) + ' '}</li>
</ul> </ul>
......
import axios from 'axios' import axios from 'axios'
import config from "../config/app.config.js"; import config from "../config/app.config.js";
const success = async(req, res) => { const success = async (req, res) => {
try { try {
// const { cid, tid, partner_order_id, partner_user_id, pg_token } = req.body // const { cid, tid, partner_order_id, partner_user_id, pg_token } = req.body
const item = req.body const item = req.body
...@@ -20,12 +20,10 @@ const success = async(req, res) => { ...@@ -20,12 +20,10 @@ const success = async(req, res) => {
}) })
const resp = response.data const resp = response.data
console.log('resp', resp) console.log('resp', resp)
res.json({...resp}) res.json({ ...resp })
} catch (error) { } catch (error) {
console.log(error) console.log(error)
} }
} }
const fail = (req, res) => { const fail = (req, res) => {
...@@ -34,10 +32,27 @@ const fail = (req, res) => { ...@@ -34,10 +32,27 @@ const fail = (req, res) => {
}) })
} }
const cancel = (req, res) => { const cancel = async (req, res) => {
return res.json({ try {
message: 'Canceled' const item = req.body
const data = []
for (let property in item) {
let encodedKey = encodeURIComponent(property);
let encodedValue = encodeURIComponent(item[property]);
data.push(encodedKey + "=" + encodedValue);
}
const bodyData = data.join('&')
const response = await axios.post('https://kapi.kakao.com/v1/payment/cancel', bodyData, {
headers: {
'Authorization': `KakaoAK ${config.kakaoAdminKey}`,
'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
},
}) })
const resp = response.data
res.json(resp)
} catch (error) {
console.log(error)
}
} }
const singleTest = async (req, res) => { const singleTest = async (req, res) => {
......
...@@ -137,7 +137,7 @@ const getMovieList = async (req, res) => { ...@@ -137,7 +137,7 @@ const getMovieList = async (req, res) => {
} }
} }
elements.sort(function (a, b) { elements.sort(function (a, b) {
return a.release_date - b.release_date return b.release_date - a.release_date
}) })
res.json(elements) res.json(elements)
} else { } else {
......
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