From f8d38c965d0df707c88902c214509c103aa0f919 Mon Sep 17 00:00:00 2001 From: Sinji Date: Thu, 21 Nov 2024 13:47:52 +0900 Subject: [PATCH 01/49] =?UTF-8?q?feat:=20Title=20=ED=8D=BC=EB=B8=94?= =?UTF-8?q?=EB=A6=AC=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TicketHolderList.styled.ts | 112 +----- .../ticketholderlist/TicketHolderList.tsx | 372 ++++-------------- .../components/banner/Banner.styled.ts | 50 --- .../components/banner/Banner.tsx | 35 -- .../managercard/ManagerCard.styled.ts | 178 --------- .../components/managercard/ManagerCard.tsx | 128 ------ .../narrowDropDown/NarrowDropDown.styled.ts | 107 ----- .../narrowDropDown/NarrowDropDown.tsx | 144 ------- .../selectIcon/SelectIcon.styled.ts | 30 -- .../components/selectIcon/SelectIcon.tsx | 25 -- .../components/title/Title.styled.ts | 40 ++ .../components/title/Title.tsx | 25 ++ .../ticketholderlist/constants/silkagel.png | Bin 18768 -> 0 bytes .../constants/ticketholderlist.ts | 101 ----- 14 files changed, 142 insertions(+), 1205 deletions(-) delete mode 100644 src/pages/ticketholderlist/components/banner/Banner.styled.ts delete mode 100644 src/pages/ticketholderlist/components/banner/Banner.tsx delete mode 100644 src/pages/ticketholderlist/components/managercard/ManagerCard.styled.ts delete mode 100644 src/pages/ticketholderlist/components/managercard/ManagerCard.tsx delete mode 100644 src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.styled.ts delete mode 100644 src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx delete mode 100644 src/pages/ticketholderlist/components/selectIcon/SelectIcon.styled.ts delete mode 100644 src/pages/ticketholderlist/components/selectIcon/SelectIcon.tsx create mode 100644 src/pages/ticketholderlist/components/title/Title.styled.ts create mode 100644 src/pages/ticketholderlist/components/title/Title.tsx delete mode 100644 src/pages/ticketholderlist/constants/silkagel.png delete mode 100644 src/pages/ticketholderlist/constants/ticketholderlist.ts diff --git a/src/pages/ticketholderlist/TicketHolderList.styled.ts b/src/pages/ticketholderlist/TicketHolderList.styled.ts index d5004c78..059dcadb 100644 --- a/src/pages/ticketholderlist/TicketHolderList.styled.ts +++ b/src/pages/ticketholderlist/TicketHolderList.styled.ts @@ -1,121 +1,15 @@ -import { IconToggleOff, IconToggleOn } from "@assets/svgs"; import styled from "styled-components"; -export const BodyWrapper = styled.div` +export const TicketHolderListWrpper = styled.section` display: flex; - align-items: flex-start; - justify-content: center; - width: 37.4rem; - height: auto; - min-height: 60.8rem; /* 60.8rem(body의 높이) + 5.6rem(버튼의 높이) */ - margin-bottom: 10.4rem; padding: 2.4rem; `; -export const BodyLayout = styled.section` - display: flex; - flex: 1 0 0; - flex-direction: column; - gap: 1.2rem; - align-items: flex-start; -`; - -export const LayoutHeaderBox = styled.div` - display: flex; - gap: 3.2rem; - align-items: flex-end; - align-self: stretch; -`; - -export const LayoutFilterBox = styled.div` - display: flex; - gap: 0.6rem; - align-items: center; -`; - -export const ToggleWrapper = styled.div` - display: flex; - gap: 0.4rem; - align-items: center; -`; - -export const ToggleText = styled.span` - color: ${({ theme }) => theme.colors.gray_400}; - ${({ theme }) => theme.fonts["body2-normal-medi"]}; -`; - -export const ToggleButton = styled.button<{ $detail: boolean }>` - position: relative; - display: flex; - align-items: center; - justify-content: space-between; - width: 5.6rem; - height: 3.3rem; - - background-color: ${({ theme, $detail }) => - $detail ? theme.colors.pink_500 : theme.colors.gray_700}; - cursor: pointer; - border: none; - border-radius: 36px; -`; - -export const Circle = styled.span<{ $detail: boolean }>` - position: absolute; - top: 50%; - left: ${({ $detail }) => ($detail ? "4rem" : "1.6rem")}; - width: 2.7rem; - height: 2.7rem; - - background-color: ${({ theme }) => theme.colors.white}; - transform: translate(-50%, -50%); - border-radius: 50%; - - transition: left 0.25s ease-in-out; /* left 속성은 변하게 된다면 이 애니메이션 적용 */ -`; - -export const ToggleOnIcon = styled(IconToggleOn)<{ $width: string; $height: string }>` - width: ${({ $width }) => $width}; - height: ${({ $height }) => $height}; -`; - -export const ToggleOffIcon = styled(IconToggleOff)<{ $width: string; $height: string }>` - width: ${({ $width }) => $width}; - height: ${({ $height }) => $height}; -`; - -export const FooterButtonText = styled.span` - margin-top: 2.4rem; - - color: ${({ theme }) => theme.colors.gray_200}; - text-align: center; - ${({ theme }) => theme.fonts["body2-normal-semi"]}; -`; - export const FooterButtonWrapper = styled.div` position: fixed; bottom: 0; - left: 50%; z-index: 1; - display: flex; - flex-direction: column; - gap: 2.4rem; - align-items: center; - width: 37.4rem; - min-height: 13.8rem; - - background-color: ${({ theme }) => theme.colors.gray_900}; - transform: translate(-50%, 0); - border-top: 1px solid #3e3e3e; -`; - -export const MarginBottom = styled.div<{ $value: string }>` - margin-bottom: ${({ $value }) => $value}; -`; -export const TwoButtonWrapper = styled.div` - display: flex; - flex-direction: row; - gap: 1.1rem; - align-items: flex-start; - justify-content: center; + min-height: 10.4rem; + padding: 0.8rem 2.4rem 0; `; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 11725586..afce6c88 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -1,24 +1,60 @@ import { useTicketPatch, useTicketRetrive, useTicketUpdate } from "@apis/domains/tickets/queries"; -import { IconCheck } from "@assets/svgs"; -import Button from "@components/commons/button/Button"; import Loading from "@components/commons/loading/Loading"; import MetaTag from "@components/commons/meta/MetaTag"; -import Toast from "@components/commons/toast/Toast"; import { NAVIGATION_STATE } from "@constants/navigationState"; import { useHeader, useModal, useToast } from "@hooks"; -import { PatchFormDataProps } from "@typings/deleteBookerFormatProps"; import { useEffect, useState } from "react"; import { CSVLink } from "react-csv"; import { useNavigate, useParams } from "react-router-dom"; -import Banner from "./components/banner/Banner"; -import ManagerCard from "./components/managercard/ManagerCard"; import { convertingNumber } from "@constants/convertingNumber"; -import NarrowDropDown from "./components/narrowDropDown/NarrowDropDown"; -import eximg from "./constants/silkagel.png"; -import { BookingListProps } from "./constants/ticketholderlist"; import * as S from "./TicketHolderList.styled"; +import { Button } from "@components/commons"; +import Title from "@pages/ticketholderlist/components/title/Title"; + +const data = { + performanceTitle: "비트밴드 정기공연", + performanceTeamName: "비트밴드", + isBooking: true, + totalScheduleCount: 2, + totalPerformanceTicketCount: 100, + totalPerformanceSoldTicketCount: 50, + bookingList: [ + { + bookingId: 1, + bookerName: "황혜린", + bookerPhoneNumber: "010-1234-5678", + scheduleId: 2, + purchaseTicketCount: 3, + createdAt: "2024-07-07T12:34:56.789Z", + bookingStatus: "REFUND_REQUIRED", + scheduleNumber: "SECOND", + bankName: "NH_NONGHYUP", + accountNumber: "123-12-1234-123", + accountHolder: "전희주", + }, + { + bookingId: 2, + bookerName: "이동훈", + bookerPhoneNumber: "010-1234-0000", + scheduleId: 1, + purchaseTicketCount: 2, + createdAt: "2024-07-08T12:34:56.789Z", + bookingStatus: "BOOKING_CONFIRMED", + scheduleNumber: "FIRST", + // 예매 확정된 상태이므로 환불계좌 정보 없음 + bankName: "", + accountNumber: "", + accountHolder: "", + }, + ], +}; + +type PaymentType = + | "CHECKING_PAYMENT" + | "BOOKING_CONFIRMED" + | "BOOKING_CANCELLED" + | "REFUND_REQUIRED"; -type PaymentType = "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; interface CSVDataType { createdAt: string; scheduleNumber: string; @@ -28,6 +64,8 @@ interface CSVDataType { bookingStatus: string; } +// 관리자 페이지에서만 사용해서 공통 type으로 안 뺌 +// TODO : TicketHolderList 내 type으로 빼기 const convertingBookingStatus = (_bookingStatus: PaymentType): string => { switch (_bookingStatus) { case "CHECKING_PAYMENT": @@ -35,11 +73,14 @@ const convertingBookingStatus = (_bookingStatus: PaymentType): string => { case "BOOKING_CONFIRMED": return "입금 완료"; case "BOOKING_CANCELLED": - return "취소된 예매자"; + return "취소 완료"; + case "REFUND_REQUIRED": + return "환불 요청"; default: - throw new Error("알 수 없는 타입입니다."); + throw new Error("알 수 없는 상태입니다."); } }; + const headers = [ { label: "예매일시", key: "createdAt" }, { label: "회차", key: "scheduleNumber" }, @@ -50,49 +91,17 @@ const headers = [ ]; const TicketHolderList = () => { + const [paymentData, setPaymentData] = useState(); + const [CSVDataArr, setCSVDataArr] = useState([]); const { performanceId } = useParams(); - const [reservedCount, setReservedCount] = useState(0); - //판매 완료 여부에 따라 배너 렌더링 달라질 지 고민 - const [isOutdated, setIsOutdated] = useState(false); - - // 0, undefined 일 때는 전체 렌더링 (필터링을 위한 state들) - const [schedule, setSchedule] = useState(0); //1,2,3 에 따라 필터링 - const [payment, setPayment] = useState(undefined); - - const [isEditMode, setIsEditMode] = useState(false); - - const { data, isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); - const [paymentData, setPaymentData] = useState(); - const [alreadyPayments, setAlreadyPayments] = useState>({}); - const [initBookingStatuses, setInitBookingStatuses] = useState>({}); - const { showToast, isToastVisible } = useToast(); + // const { data, isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); + const { isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); useEffect(() => { - setPaymentData(data?.bookingList ?? []); - if (data?.bookingList) { - const immutableAlreadyPayments = data.bookingList.reduce( - (acc, item) => { - acc[item.bookingId] = item.bookingStatus === "BOOKING_CONFIRMED"; - return acc; - }, - {} as Record - ); - - const immutableBookingStatuses = data.bookingList.reduce( - (acc, item) => { - acc[item.bookingId] = item.bookingStatus; - return acc; - }, - {} as Record - ); - - setAlreadyPayments(immutableAlreadyPayments); - setInitBookingStatuses(immutableBookingStatuses); - //전체 데이터를 기반으로 csv 추출 데이터 구축 const tempCSVDataArr: CSVDataType[] = []; @@ -108,7 +117,7 @@ const TicketHolderList = () => { bookerName: item.bookerName, purchaseTicketCount: `${item.purchaseTicketCount}매`, bookerPhoneNumber: item.bookerPhoneNumber, - bookingStatus: convertingBookingStatus(item.bookingStatus), + bookingStatus: convertingBookingStatus(item.bookingStatus as PaymentType), }); }); @@ -119,185 +128,25 @@ const TicketHolderList = () => { } }, [data]); - const { openConfirm, closeConfirm } = useModal(); - const { mutate, mutateAsync } = useTicketUpdate(); - const { mutate: patchMutate, mutateAsync: patchMutateAsync, isPending } = useTicketPatch(); - const handlePaymentFixAxiosFunc = () => { - if (isPending) { - return; - } - //PUT API 요청 - mutate({ - performanceId: Number(performanceId), - performanceTitle: data?.performanceTitle, - totalScheduleCount: data?.totalScheduleCount, - bookingList: paymentData, - }); - closeConfirm(); - showToast(); - setTimeout(() => { - window.location.reload(); - }, 1000); - }; - const handlePaymentFixBtn = () => { - openConfirm({ - title: "선택한 게스트를 입금 처리하겠습니까?", - subTitle: "입금 완료로 변경된 예매자에게\n 입금 확인 완료 웹발신이 발송돼요.", - okText: "저장할게요", - noText: "아니요", - okCallback: handlePaymentFixAxiosFunc, - noCallback: closeConfirm, - }); - }; - - const [patchFormData, setPatchFormData] = useState({ - performanceId: Number(performanceId), - bookingList: [], - }); - - const handleBookerPatchAxiosFunc = async () => { - await patchMutateAsync(patchFormData); - window.location.reload(); - - closeConfirm(); - - //window.location.reload(); - }; - - const handleDeleteBtn = () => { - openConfirm({ - title: "선택한 게스트를 삭제하시겠어요?", - subTitle: "삭제된 게스트는 복구되지 않아요.", - okText: "삭제할게요", - noText: "아니요", - okCallback: handleBookerPatchAxiosFunc, - noCallback: closeConfirm, - }); - }; - const navigate = useNavigate(); const handleNavigateBack = () => { navigate("/gig-manage"); }; - const handleResetEditMode = () => { - setHeader({ - headerStyle: NAVIGATION_STATE.ICON_TITLE_SUB_TEXT, - title: "예매자 관리", - subText: "편집", - leftOnClick: handleNavigateBack, - rightOnClick: handleEditButton, - }); - }; - - const handleLeftButton = () => { - openConfirm({ - title: "화면을 나갈까요?", - subTitle: "'상태 저장' 없이 화면을 나갈 경우,\n 수정 내용이 저장되지 않아요.", - okText: "계속할게요", - noText: "나갈게요", - okCallback: closeConfirm, - noCallback: handleResetEditMode, - }); - }; - const { setHeader } = useHeader(); - - const handleCloseButton = async () => { - setIsEditMode(false); - - //원 상태도 되돌림 (입금 여부 수정, 삭제용 체크) - //Todo : 새로고침 후 편집 -> 닫기 반복 클릭하면 에러 발생(빈 배열로 설정되던 에러 + 이상한 렌더링) -> 해결 - const refetchData = await refetch(); - setPaymentData(refetchData?.data?.bookingList ?? []); - setPatchFormData({ - performanceId: Number(performanceId), - bookingList: [], - }); - - setHeader({ - headerStyle: NAVIGATION_STATE.ICON_TITLE_SUB_TEXT, - title: "예매자 관리", - subText: "편집", - leftOnClick: handleLeftButton, - rightOnClick: handleEditButton, - }); - }; - - const handleEditButton = () => { - setIsEditMode(true); - setHeader({ - headerStyle: NAVIGATION_STATE.TITLE_SUB_TEXT, - title: "예매자 편집", - subText: "닫기", - rightOnClick: handleLeftButton, - }); - }; - useEffect(() => { setHeader({ headerStyle: NAVIGATION_STATE.ICON_TITLE_SUB_TEXT, title: "예매자 관리", - subText: "편집", + // TODO : 사이즈 안 맞는 거 공통컴포넌트 수정하기 + subText: "CSV 다운", leftOnClick: handleNavigateBack, - rightOnClick: handleEditButton, + // TODO : rightOnClick CSV 다운로드로 변경 + // rightOnClick: , }); }, [setHeader]); - const count = data?.totalScheduleCount; //api로 받아온 값 (동적 회차 수) - - //최대 10회차로 렌더링 될 수 있도록 변경 필요 - //schedule ===0 -> 전체 회차, payment === undefined -> 전체 입금 여부 - const filteredData = paymentData?.filter((obj) => { - const isScheduleMatched = - schedule === 0 || - (obj.scheduleNumber === "FIRST" && schedule === 1) || - (obj.scheduleNumber === "SECOND" && schedule === 2) || - (obj.scheduleNumber === "THIRD" && schedule === 3) || - (obj.scheduleNumber === "FOURTH" && schedule === 4) || - (obj.scheduleNumber === "FIFTH" && schedule === 5) || - (obj.scheduleNumber === "SIXTH" && schedule === 6) || - (obj.scheduleNumber === "SEVENTH" && schedule === 7) || - (obj.scheduleNumber === "EIGHTH" && schedule === 8) || - (obj.scheduleNumber === "NINTH" && schedule === 9) || - (obj.scheduleNumber === "TENTH" && schedule === 10); - - const isPaymentMatched = - obj.bookingStatus !== "BOOKING_CANCELLED" && - (payment === undefined || payment === initBookingStatuses[obj.bookingId]); - - return isScheduleMatched && isPaymentMatched; - }); - - useEffect(() => { - //총 매수 계산 - const totalCount = filteredData?.reduce( - (totalSum, obj) => (obj.purchaseTicketCount as number) + totalSum, - 0 - ) as number; - setReservedCount(totalCount); - }, [filteredData]); - - const handlePaymentToggle = (_isEditMode: boolean, bookingId?: number) => { - //Edit(편집) 모드 일때만 바뀌도록 - if (_isEditMode) { - setPaymentData((arr) => - arr?.map((item) => - item.bookingId === bookingId - ? { - ...item, - //예매 확정(입금 완료) <-> 입금 확인 중(미입금) 변경되도록 - bookingStatus: - item.bookingStatus === "BOOKING_CONFIRMED" - ? "CHECKING_PAYMENT" - : "BOOKING_CONFIRMED", - } - : item - ) - ); - } - }; return ( <> @@ -305,91 +154,18 @@ const TicketHolderList = () => { ) : ( <> - {isPending && } - - - - - - {/*set 함수 직접 넘기는 거 안좋다고 했지만, 내부에서 감싸야 하므로 넘김 */} - - 모든 회차 - - - 입금 상태 - - - - {filteredData?.map((obj, index) => ( - handlePaymentToggle(isEditMode, obj.bookingId)} - bookername={obj.bookerName} - purchaseTicketeCount={obj.purchaseTicketCount} - scheduleNumber={obj.scheduleNumber} - bookerPhoneNumber={obj.bookerPhoneNumber} - createAt={obj.createdAt} - alreadyBookingConfirmed={alreadyPayments[obj.bookingId]} - /> - ))} - - {isEditMode ? ( - - 저장 후, 입금 상태 재변경은 불가능합니다. - - - - - - ) : ( - <> - - - 예매자 정보를 CSV 파일로 저장할 수 있어요. - - - - - - } isVisible={isToastVisible} toastBottom={37}> - 예매 확정 WEB 발신 문자가 전송되었습니다. - - - )} - - + + + <S.FooterButtonWrapper> + {/* TODO : 상태에 따라 텍스트 다르게 */} + <Button>예매자 관리하기</Button> + </S.FooterButtonWrapper> + </S.TicketHolderListWrpper> </> )} </> diff --git a/src/pages/ticketholderlist/components/banner/Banner.styled.ts b/src/pages/ticketholderlist/components/banner/Banner.styled.ts deleted file mode 100644 index f100fe48..00000000 --- a/src/pages/ticketholderlist/components/banner/Banner.styled.ts +++ /dev/null @@ -1,50 +0,0 @@ -import styled from "styled-components"; - -export const BannerWrapper = styled.div<{ $image: string }>` - width: 37.5rem; - height: 7.2rem; - - /* 사용자가 입력한 이미지 background 적당히 잘라서 사용하도록 */ - background-image: url(${({ $image }) => $image}); - background-repeat: no-repeat; - background-position: center; - background-size: cover; -`; - -export const BannerTextLayout = styled.div` - display: flex; - flex-shrink: 0; - align-items: center; - justify-content: center; - width: 37.5rem; - height: 7.2rem; - - background: rgb(0 0 0 / 60%); -`; - -export const BannerTextBox = styled.div` - display: flex; - align-items: center; - justify-content: space-between; - width: 32.7rem; -`; - -export const BannerTitleText = styled.span` - width: 17.7rem; - overflow: hidden; - - color: ${({ theme }) => theme.colors.white}; - ${({ theme }) => theme.fonts.heading4}; - white-space: nowrap; - text-overflow: ellipsis; -`; - -export const BannerStateTextBox = styled.span` - color: ${({ theme }) => theme.colors.white}; - ${({ theme }) => theme.fonts["body1-normal-semi"]}; -`; - -export const CountTextSpan = styled.span` - color: ${({ theme }) => theme.colors.pink_400}; - ${({ theme }) => theme.fonts["body1-normal-semi"]}; -`; diff --git a/src/pages/ticketholderlist/components/banner/Banner.tsx b/src/pages/ticketholderlist/components/banner/Banner.tsx deleted file mode 100644 index 2f5da94f..00000000 --- a/src/pages/ticketholderlist/components/banner/Banner.tsx +++ /dev/null @@ -1,35 +0,0 @@ -import * as S from "./Banner.styled"; - -interface BannerProps { - title?: string; - image: string; - reservedCount: number; - isOutdated: boolean; -} - -const Banner = ({ title, image, reservedCount, isOutdated }: BannerProps) => { - return ( - <S.BannerWrapper $image={image}> - <S.BannerTextLayout> - <S.BannerTextBox> - <S.BannerTextBox> - <S.BannerTitleText>{title}</S.BannerTitleText> - {isOutdated ? ( - <S.BannerStateTextBox> - 총<S.CountTextSpan> {reservedCount}매 </S.CountTextSpan> - 판매 됨 - </S.BannerStateTextBox> - ) : ( - <S.BannerStateTextBox> - <S.CountTextSpan> {reservedCount}매 </S.CountTextSpan> - 예매됨 - </S.BannerStateTextBox> - )} - </S.BannerTextBox> - </S.BannerTextBox> - </S.BannerTextLayout> - </S.BannerWrapper> - ); -}; - -export default Banner; diff --git a/src/pages/ticketholderlist/components/managercard/ManagerCard.styled.ts b/src/pages/ticketholderlist/components/managercard/ManagerCard.styled.ts deleted file mode 100644 index 51c91f2e..00000000 --- a/src/pages/ticketholderlist/components/managercard/ManagerCard.styled.ts +++ /dev/null @@ -1,178 +0,0 @@ -import { IconCheckboxSelectedOn, IconCheckboxUnselectedOn } from "@assets/svgs"; -import styled, { keyframes } from "styled-components"; - -const expandAnimation = keyframes` - 0% { - height: 7.4rem; - } - - 100% { - height: 14.6rem; - } -`; - -const unexpandAnimation = keyframes` - 0% { - height: 14.6rem; - } - - 100% { - height: 7.4rem; - } -`; - -const revealAnimation = keyframes` - 0% { - transform: translateY(-20px); - opacity: 0; - } - - 100% { - transform: translateY(0); - opacity: 1; - } -`; - -const unrevealAnimation = keyframes` - 0% { - transform: translateY(0); - opacity: 0; - } - - 100% { - transform: translateY(-20px); - opacity: 0; - } -`; - -export const ManagerCardWrapper = styled.article` - display: flex; - flex-shrink: 0; - align-items: center; - justify-content: center; - width: 32.6rem; - height: 10rem; - padding-left: 0.4rem; -`; - -export const ManagerCardLayout = styled.div<{ $isEditMode: boolean }>` - display: flex; - flex-direction: column; - flex-shrink: 0; - gap: 1.6rem; - align-items: flex-start; - width: ${({ $isEditMode }) => ($isEditMode ? "22.2rem" : "25.2rem")}; - height: 10rem; - margin-right: 0.2rem; - padding: 1.6rem; - - background-color: ${({ theme }) => theme.colors.gray_800}; - border-right: 1px solid ${({ theme }) => theme.colors.black}; - border-radius: 6px; - - transition: max-height 0.5s ease; -`; - -export const ManagerCardBox = styled.div` - display: flex; - flex-direction: column; - gap: 0.4rem; - align-items: flex-start; - align-self: stretch; -`; - -/* -언제 사용할 지 모르니까 주석으로 남겨둠 -export const ManagerCardDetailBox = styled.div<{ $isDetail: boolean }>` - display: flex; - flex-direction: column; - gap: 0.4rem; - align-items: flex-start; - align-self: stretch; - - background-color: ${({ theme, $isDetail }) => $isDetail && theme.colors.gray_800}; - opacity: ${({ $isDetail }) => ($isDetail ? "1" : "0")}; - - transition: background-color 0.25s ease; - animation: ${({ $isDetail }) => ($isDetail ? revealAnimation : unrevealAnimation)} 0.7s ease; -`; - - -export const ManagerCardDetailLayout = styled.div<{ $isDetail: boolean; $isEditMode: boolean }>` - - display: flex; - flex-direction: column; - flex-shrink: 0; - gap: 1.6rem; - align-items: flex-start; - width: ${({ $isEditMode }) => ($isEditMode ? "22.2rem" : "25.2rem")}; - - height: ${({ $isDetail }) => ($isDetail ? "14.6rem" : "7.4rem")}; - padding: 1.6rem; - - background-color: ${({ theme }) => theme.colors.gray_800}; - opacity: ${({ $isDetail }) => ($isDetail ? "1" : "0")}; - border-right: 1px solid ${({ theme }) => theme.colors.black}; - border-radius: 6px; -`; -*/ - -export const ManagerCardTextBox = styled.div` - display: flex; - gap: 0.6rem; - align-items: center; - justify-content: flex-start; -`; - -export const ManagerCardTextTitle = styled.span` - color: ${({ theme }) => theme.colors.gray_400}; - ${({ theme }) => theme.fonts["body2-normal-medi"]}; - white-space: nowrap; -`; - -export const ManagerCardTextContent = styled.span` - color: ${({ theme }) => theme.colors.white}; - ${({ theme }) => theme.fonts["body2-normal-medi"]}; - white-space: nowrap; -`; - -export const ManagerCardRadioLayout = styled.div` - display: flex; - flex-shrink: 0; - align-items: center; - justify-content: center; - width: 7.4rem; - height: 10rem; - padding: 1.5rem 1.5rem 1.5rem 1.6rem; - - background-color: ${({ theme }) => theme.colors.gray_800}; - border-radius: 6px; -`; - -export const ManagerCardRadioBox = styled.div<{ $isEditMode: boolean }>` - display: flex; - flex-direction: column; - flex-shrink: 0; - gap: 1rem; - align-items: center; - width: 4.3rem; - - cursor: ${({ $isEditMode }) => ($isEditMode ? "default" : "pointer")}; -`; - -export const SelectedIcon = styled(IconCheckboxSelectedOn)` - width: 1.8rem; - height: 1.8rem; -`; - -export const UnselectedIcon = styled(IconCheckboxUnselectedOn)` - width: 1.8rem; - height: 1.8rem; -`; - -export const ManagerCardRadioText = styled.span<{ $isPaid }>` - color: ${({ theme, $isPaid }) => ($isPaid ? theme.colors.pink_400 : theme.colors.gray_300)}; - text-align: center; - - ${({ theme }) => theme.fonts["caption2-semi"]}; -`; diff --git a/src/pages/ticketholderlist/components/managercard/ManagerCard.tsx b/src/pages/ticketholderlist/components/managercard/ManagerCard.tsx deleted file mode 100644 index 5fe87414..00000000 --- a/src/pages/ticketholderlist/components/managercard/ManagerCard.tsx +++ /dev/null @@ -1,128 +0,0 @@ -import { PatchFormDataProps } from "@typings/deleteBookerFormatProps"; -import { Dispatch, SetStateAction } from "react"; -import SelectIcon from "../selectIcon/SelectIcon"; -import * as S from "./ManagerCard.styled"; - -export const convertingNumber = (_scheduleNumber: string) => { - switch (_scheduleNumber) { - case "FIRST": - return 1; - case "SECOND": - return 2; - case "THIRD": - return 3; - case "FOURTH": - return 4; - case "FIFTH": - return 5; - case "SIXTH": - return 6; - case "SEVENTH": - return 7; - case "EIGHTH": - return 8; - case "NINTH": - return 9; - case "TENTH": - return 10; - default: - throw new Error("없는 회차"); - } -}; - -const ManagerCard = ({ - patchFormData, - setPatchFormData, - isEditMode, - bookingId, - isPaid, - setPaid, - bookername, - purchaseTicketeCount, - scheduleNumber, - bookerPhoneNumber, - createAt, - alreadyBookingConfirmed, -}: { - patchFormData: PatchFormDataProps; - setPatchFormData: Dispatch<SetStateAction<PatchFormDataProps>>; - isEditMode: boolean; - bookingId?: number; - isPaid?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; - setPaid: () => void; - bookername?: string; - purchaseTicketeCount?: number; - scheduleNumber?: string; - bookerPhoneNumber?: string; - createAt?: string; - alreadyBookingConfirmed: boolean; -}) => { - const handleCheckBox = (managerBookingId: number) => { - //삭제할 데이터 form에 추가하는 로직 - setPatchFormData((prevFormData) => { - const isAlreadyChecked = prevFormData.bookingList.some( - (_bookingId) => _bookingId === managerBookingId - ); - - const updateBookingList = isAlreadyChecked - ? prevFormData.bookingList.filter((_bookingId) => _bookingId !== managerBookingId) - : [...prevFormData.bookingList, managerBookingId]; - return { ...prevFormData, bookingList: updateBookingList }; - }); - - //입금 여부 변경될 거 추가하는 로직 - setPaid(); - }; - - const date = createAt?.split("T")[0]; - const formattedDate = date?.replace(/-/g, ". "); - - return ( - <S.ManagerCardWrapper> - {isEditMode && ( - <SelectIcon - onClick={() => handleCheckBox(bookingId as number)} - isChecked={patchFormData.bookingList.some((_bookingId) => _bookingId === bookingId)} - alreadyBookingConfirmed={alreadyBookingConfirmed} - /> - )} - <S.ManagerCardLayout - $isEditMode={isEditMode} - onClick={() => { - if (alreadyBookingConfirmed) { - return; - } - isEditMode && handleCheckBox(bookingId as number); - }} - > - <S.ManagerCardBox> - <S.ManagerCardTextBox> - <S.ManagerCardTextContent>{bookername}</S.ManagerCardTextContent> - <S.ManagerCardTextContent>{`(${bookerPhoneNumber})`}</S.ManagerCardTextContent> - </S.ManagerCardTextBox> - <S.ManagerCardTextBox> - <S.ManagerCardTextContent>{`${convertingNumber(scheduleNumber as string)}회차`}</S.ManagerCardTextContent> - <S.ManagerCardTextContent>{`/ ${purchaseTicketeCount}매`}</S.ManagerCardTextContent> - </S.ManagerCardTextBox> - <S.ManagerCardTextBox> - <S.ManagerCardTextTitle>{formattedDate}</S.ManagerCardTextTitle> - </S.ManagerCardTextBox> - </S.ManagerCardBox> - </S.ManagerCardLayout> - - <S.ManagerCardRadioLayout> - <S.ManagerCardRadioBox $isEditMode={isEditMode}> - <S.ManagerCardRadioText $isPaid={isPaid === "BOOKING_CONFIRMED"}> - {isPaid === "BOOKING_CONFIRMED" - ? "입금 완료" - : isPaid === "CHECKING_PAYMENT" - ? "미입금" - : "예매 취소"} - </S.ManagerCardRadioText> - </S.ManagerCardRadioBox> - </S.ManagerCardRadioLayout> - </S.ManagerCardWrapper> - ); -}; - -export default ManagerCard; diff --git a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.styled.ts b/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.styled.ts deleted file mode 100644 index 4b37b8bc..00000000 --- a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.styled.ts +++ /dev/null @@ -1,107 +0,0 @@ -import SvgIconChevronBack from "@assets/svgs/IconChevronBack"; -import styled, { css } from "styled-components"; - -export const DropdownWrapper = styled.div` - position: relative; -`; - -export const DropdownButton = styled.button<{ $isChoosed: boolean }>` - display: inline-flex; - flex-shrink: 0; - gap: 0.6rem; - align-items: center; - min-width: 9.3rem; - height: 4rem; - padding: 0.8rem 0.8rem 0.8rem 1.2rem; - - /* border: 1px solid - ${({ theme, $isChoosed }) => ($isChoosed ? theme.colors.gray_0 : theme.colors.gray_700)}; */ - border-radius: 0.4rem; -`; - -export const DropDownButtonContent = styled.div` - display: flex; - gap: 0.4rem; - align-items: center; - justify-content: space-between; - width: 100%; -`; - -export const ButtonContentSpan = styled.span` - color: ${({ theme }) => theme.colors.gray_0}; - ${({ theme }) => theme.fonts["body2-normal-medi"]}; -`; - -export const SvgIcon = styled(SvgIconChevronBack)<{ $rotate: boolean }>` - width: 16px; - height: 16px; - - transform: rotate(180deg); - - ${(prop) => - prop.$rotate && - css` - transform: rotate(360deg); - `} -`; - -export const DropdownContentWrapper = styled.div<{ $show: boolean }>` - position: absolute; - top: 4.06rem; /* 버튼의 높이 3.26rem + 간격 0.8rem */ - z-index: 1; - display: ${(props) => (props.$show ? "flex" : "none")}; - flex-shrink: 0; - gap: 0.6rem; - align-items: center; - width: 9.2rem; - margin-top: 0.8rem; - padding: 0.8rem 0.8rem 0.8rem 1.2rem; - - background-color: ${({ theme }) => theme.colors.black}; - border: 1px solid ${({ theme }) => theme.colors.gray_400}; - border-radius: 0.4rem; -`; - -export const DropdownContentLayout = styled.div` - display: flex; - flex-direction: column; - gap: 0.6rem; - align-items: flex-start; - justify-content: center; -`; - -export const DropdownContentButton = styled.button<{ $isLast: boolean }>` - display: flex; - flex-direction: column; - gap: 0.8rem; - align-items: flex-start; - width: 6.8rem; - - /* 피그마에서는 겹치는 부분이 제대로 계산 안되서, 개발하면서 적당히 줄여둠 */ - padding: 0.2rem 0 0.6rem; - - ${({ $isLast }) => - !$isLast && - css` - border-bottom: 1px solid ${({ theme }) => theme.colors.gray_700}; - `} -`; - -export const DropdownContentText = styled.span<{ - $selected: boolean; -}>` - display: flex; - gap: 0.4rem; - align-items: center; - align-self: stretch; - justify-content: flex-start; - - color: ${({ theme }) => theme.colors.gray_0}; - ${({ theme }) => theme.fonts["body2-normal-medi"]}; - - ${({ $selected }) => - $selected && - css` - color: ${({ theme }) => theme.colors.pink_400}; - `} -`; diff --git a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx b/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx deleted file mode 100644 index 37d78ff1..00000000 --- a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { ReactNode, useState } from "react"; -import * as S from "./NarrowDropDown.styled"; - -interface DropdownProps { - children: ReactNode; - totalScheduleCount: number; - schedule: number; - payment: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | undefined; - setSchedule?: (param: number) => void; - setPayment?: ( - param: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | undefined - ) => void; -} - -const NarrowDropDown = ({ - children, - totalScheduleCount, - schedule, - payment, - setSchedule, - setPayment, -}: DropdownProps) => { - const [showDropdown, setShowDropdown] = useState<boolean>(false); - const [isOneChoosed, setIsOneChoosed] = useState(false); - - const handleToggle = () => { - setShowDropdown(!showDropdown); - }; - - const renderDropdownContent = (count: number, childrenNode: ReactNode) => { - const items = []; - const childrenString = childrenNode?.toString(); - if (childrenString === "모든 회차") { - const handleScheduleAll = () => { - setSchedule?.(0); - setIsOneChoosed(false); - setShowDropdown(false); - }; - items.push( - <S.DropdownContentButton - key={"dropdown-all-schedule"} - $isLast={false} - onClick={handleScheduleAll} - > - <S.DropdownContentText $selected={schedule === 0}>전체</S.DropdownContentText> - </S.DropdownContentButton> - ); - for (let i = 1; i <= count; i++) { - const handleSchedule = () => { - setSchedule?.(i); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - items.push( - <S.DropdownContentButton - key={`dropdown-${i}`} - $isLast={i === count} - onClick={handleSchedule} - > - <S.DropdownContentText $selected={schedule === i}>{i}회차</S.DropdownContentText> - </S.DropdownContentButton> - ); - } - } else if (childrenString === "입금 상태") { - const handlePaymentUndefined = () => { - setPayment?.(undefined); - setIsOneChoosed(false); - setShowDropdown(false); - }; - - const handlePaymentFalse = () => { - setPayment?.("CHECKING_PAYMENT"); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - const handlePaymentTrue = () => { - setPayment?.("BOOKING_CONFIRMED"); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - items.push( - <S.DropdownContentButton - key={"dropdown-all-payment"} - $isLast={false} - onClick={handlePaymentUndefined} - > - <S.DropdownContentText $selected={payment === undefined}>전체</S.DropdownContentText> - </S.DropdownContentButton> - ); - - items.push( - <S.DropdownContentButton key={"dropdown-1"} $isLast={false} onClick={handlePaymentFalse}> - <S.DropdownContentText $selected={payment === "CHECKING_PAYMENT"}> - 미입금 - </S.DropdownContentText> - </S.DropdownContentButton> - ); - items.push( - <S.DropdownContentButton key={"dropdown-2"} $isLast={true} onClick={handlePaymentTrue}> - <S.DropdownContentText $selected={payment === "BOOKING_CONFIRMED"}> - 입금완료 - </S.DropdownContentText> - </S.DropdownContentButton> - ); - } - - return items; - }; - - //공연별로 총 회차 값으로 넘겨주기로 함. - //각 공연별 회차는, DB 테이블 구조에 따라 enum값으로 넘겨주기로 함 - //필터링은 회차 번호(scheduleNumber : FIRST, SECOND, THIRD), 입금 완료 여부는 paymentStatus에 따라 나뉠거임 - // - - let changedChildren; - if (children === "입금 상태" && payment !== undefined) { - changedChildren = payment === "BOOKING_CONFIRMED" ? "입금완료" : "미입금"; - } else if (children === "모든 회차" && schedule !== 0) { - changedChildren = `${schedule}회차`; - } - - return ( - <S.DropdownWrapper> - <S.DropdownButton $isChoosed={isOneChoosed} onClick={handleToggle}> - <S.DropDownButtonContent> - <S.ButtonContentSpan> - {changedChildren === undefined ? children : changedChildren} - </S.ButtonContentSpan> - <S.SvgIcon $rotate={showDropdown} /> - </S.DropDownButtonContent> - </S.DropdownButton> - <S.DropdownContentWrapper $show={showDropdown}> - <S.DropdownContentLayout> - {renderDropdownContent(totalScheduleCount, children)} - </S.DropdownContentLayout> - </S.DropdownContentWrapper> - </S.DropdownWrapper> - ); -}; - -export default NarrowDropDown; diff --git a/src/pages/ticketholderlist/components/selectIcon/SelectIcon.styled.ts b/src/pages/ticketholderlist/components/selectIcon/SelectIcon.styled.ts deleted file mode 100644 index b17452d9..00000000 --- a/src/pages/ticketholderlist/components/selectIcon/SelectIcon.styled.ts +++ /dev/null @@ -1,30 +0,0 @@ -import { - IconCheckboxDisabledOn, - IconCheckboxSelectedOn, - IconCheckboxUnselectedOn, -} from "@assets/svgs"; -import styled from "styled-components"; - -export const DeleteSelectedIcon = styled(IconCheckboxSelectedOn)` - width: 1.8rem; - height: 1.8rem; - margin-right: 0.8rem; - - cursor: pointer; -`; - -export const DeleteUnselectedIcon = styled(IconCheckboxUnselectedOn)` - width: 1.8rem; - height: 1.8rem; - margin-right: 0.8rem; - - cursor: pointer; -`; - -export const CantSelectedIcon = styled(IconCheckboxDisabledOn)` - width: 1.8rem; - height: 1.8rem; - margin-right: 0.8rem; - - cursor: not-allowed; -`; diff --git a/src/pages/ticketholderlist/components/selectIcon/SelectIcon.tsx b/src/pages/ticketholderlist/components/selectIcon/SelectIcon.tsx deleted file mode 100644 index 457c0539..00000000 --- a/src/pages/ticketholderlist/components/selectIcon/SelectIcon.tsx +++ /dev/null @@ -1,25 +0,0 @@ -import * as S from "./SelectIcon.styled"; - -const SelectIcon = ({ - onClick, - isChecked, - alreadyBookingConfirmed, -}: { - onClick: () => void; - isChecked: boolean; - alreadyBookingConfirmed: boolean; -}) => { - return ( - <> - {alreadyBookingConfirmed ? ( - <S.CantSelectedIcon /> - ) : isChecked ? ( - <S.DeleteSelectedIcon onClick={onClick} /> - ) : ( - <S.DeleteUnselectedIcon onClick={onClick} /> - )} - </> - ); -}; - -export default SelectIcon; diff --git a/src/pages/ticketholderlist/components/title/Title.styled.ts b/src/pages/ticketholderlist/components/title/Title.styled.ts new file mode 100644 index 00000000..053e31ce --- /dev/null +++ b/src/pages/ticketholderlist/components/title/Title.styled.ts @@ -0,0 +1,40 @@ +import styled from "styled-components"; + +export const TitleWrapper = styled.section` + display: flex; + flex-direction: column; +`; + +export const PerformanceTeamName = styled.div` + ${({ theme }) => theme.fonts["caption1-semi"]}; + color: ${({ theme }) => theme.colors.gray_400}; +`; + +export const PerformanceTitleWrapper = styled.section` + display: flex; + justify-content: space-between; + width: 32.8rem; +`; + +// TODO : 말줄임표 작업 +export const PerformanceTitle = styled.div` + display: flex; + width: 25.8rem; + + ${({ theme }) => theme.fonts.heading2}; + color: ${({ theme }) => theme.colors.white}; +`; + +export const TicketCountWrapper = styled.section` + display: flex; +`; + +export const PurchaseTicketCount = styled.div` + ${({ theme }) => theme.fonts["body1-normal-medi"]}; + color: ${({ theme }) => theme.colors.pink_200}; +`; + +export const TotalTicketCount = styled.div` + ${({ theme }) => theme.fonts["body1-normal-medi"]}; + color: ${({ theme }) => theme.colors.gray_200}; +`; diff --git a/src/pages/ticketholderlist/components/title/Title.tsx b/src/pages/ticketholderlist/components/title/Title.tsx new file mode 100644 index 00000000..8ce5e12c --- /dev/null +++ b/src/pages/ticketholderlist/components/title/Title.tsx @@ -0,0 +1,25 @@ +import * as S from "./Title.styled"; + +interface BookingInfoProps { + title: string; + teamName: string; + totalSolidCount: number; + totalCount: number; +} + +const Title = ({ title, teamName, totalSolidCount, totalCount }: BookingInfoProps) => { + return ( + <S.TitleWrapper> + <S.PerformanceTeamName>{teamName}</S.PerformanceTeamName> + <S.PerformanceTitleWrapper> + <S.PerformanceTitle>{title}</S.PerformanceTitle> + <S.TicketCountWrapper> + <S.PurchaseTicketCount>{totalSolidCount}</S.PurchaseTicketCount> + <S.TotalTicketCount>/{totalCount}매</S.TotalTicketCount> + </S.TicketCountWrapper> + </S.PerformanceTitleWrapper> + </S.TitleWrapper> + ); +}; + +export default Title; diff --git a/src/pages/ticketholderlist/constants/silkagel.png b/src/pages/ticketholderlist/constants/silkagel.png deleted file mode 100644 index a5295d7b6ff8506474f46ce399a0782e27ccee59..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 18768 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 LNkvXXu0mjf3P{ux diff --git a/src/pages/ticketholderlist/constants/ticketholderlist.ts b/src/pages/ticketholderlist/constants/ticketholderlist.ts deleted file mode 100644 index 006bf719..00000000 --- a/src/pages/ticketholderlist/constants/ticketholderlist.ts +++ /dev/null @@ -1,101 +0,0 @@ -export interface BookingListProps { - bookingId?: number; - bookerName?: string; - bookerPhoneNumber?: string; - scheduleId?: number; - purchaseTicketCount?: number; - createdAt?: string; - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; - scheduleNumber?: string; -} - -export interface TicketHolderListProps { - performanceTitle: string; - isBooking: boolean; - totalScheduleCount: number; - bookingList: BookingListProps[]; -} - -export interface TicketHolderListDataProps { - data: TicketHolderListProps; -} - -export const RESPONSE_TICKETHOLDER = { - data: { - performanceTitle: "비트밴드 정기공연", - isBooking: true, - totalScheduleCount: 3, - bookingList: [ - { - bookingId: 1, - bookerName: "황혜린", - bookerPhoneNumber: "010-1234-5678", - scheduleId: 2, //scheduleId는 테이블의 특성에 따라 존재하는 것 - purchaseTicketCount: 3, - createdAt: "2024-07-07T12:34:56.789Z", - isPaymentCompleted: true, - scheduleNumber: "SECOND", - }, - { - bookingId: 2, - bookerName: "이동훈", - bookerPhoneNumber: "010-1234-0000", - scheduleId: 1, - purchaseTicketCount: 2, - createdAt: "2024-07-08T12:34:56.789Z", - isPaymentCompleted: false, - scheduleNumber: "FIRST", - }, - { - bookingId: 3, - bookerName: "공준혁", - bookerPhoneNumber: "010-1234-9999", - scheduleId: 1, - purchaseTicketCount: 9, - createdAt: "2024-07-08T12:34:56.789Z", - isPaymentCompleted: true, - scheduleNumber: "THIRD", - }, - { - bookingId: 4, - bookerName: "정도영", - bookerPhoneNumber: "010-1234-0000", - scheduleId: 3, - purchaseTicketCount: 4, - createdAt: "2024-07-11T12:34:56.789Z", - isPaymentCompleted: false, - scheduleNumber: "THIRD", - }, - { - bookingId: 5, - bookerName: "김채현", - bookerPhoneNumber: "010-1234-0000", - scheduleId: 3, - purchaseTicketCount: 6, - createdAt: "2024-07-15T12:34:56.789Z", - isPaymentCompleted: false, - scheduleNumber: "THIRD", - }, - { - bookingId: 6, - bookerName: "윤신지", - bookerPhoneNumber: "010-1234-0000", - scheduleId: 3, - purchaseTicketCount: 2, - createdAt: "2024-07-03T12:34:56.789Z", - isPaymentCompleted: true, - scheduleNumber: "THIRD", - }, - { - bookingId: 7, - bookerName: "익명인", - bookerPhoneNumber: "010-1000-0000", - scheduleId: 1, - purchaseTicketCount: 2, - createdAt: "2024-07-08T12:34:56.789Z", - isPaymentCompleted: true, - scheduleNumber: "SECOND", - }, - ], - }, -}; From 7b8a224c048d5992e225c40fa7f8c5b2c9d1fa4a Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sat, 23 Nov 2024 03:03:18 +0900 Subject: [PATCH 02/49] =?UTF-8?q?feat:=20=EC=83=81=ED=83=9C=EC=97=90=20?= =?UTF-8?q?=EB=94=B0=EB=9D=BC=20=EB=B2=84=ED=8A=BC=20=EB=8B=A4=EB=A5=B4?= =?UTF-8?q?=EA=B2=8C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TicketHolderList.styled.ts | 6 +-- .../ticketholderlist/TicketHolderList.tsx | 44 ++++++++++++++++--- 2 files changed, 42 insertions(+), 8 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.styled.ts b/src/pages/ticketholderlist/TicketHolderList.styled.ts index 059dcadb..b22407e3 100644 --- a/src/pages/ticketholderlist/TicketHolderList.styled.ts +++ b/src/pages/ticketholderlist/TicketHolderList.styled.ts @@ -2,14 +2,14 @@ import styled from "styled-components"; export const TicketHolderListWrpper = styled.section` display: flex; - padding: 2.4rem; + flex-direction: column; + padding: 0.8rem 2.4rem 2.6rem; `; export const FooterButtonWrapper = styled.div` position: fixed; bottom: 0; z-index: 1; - min-height: 10.4rem; - padding: 0.8rem 2.4rem 0; + padding: 2.4rem; `; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index afce6c88..a6fdaa04 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -8,7 +8,7 @@ import { CSVLink } from "react-csv"; import { useNavigate, useParams } from "react-router-dom"; import { convertingNumber } from "@constants/convertingNumber"; import * as S from "./TicketHolderList.styled"; -import { Button } from "@components/commons"; +import { BottomSheet, Button } from "@components/commons"; import Title from "@pages/ticketholderlist/components/title/Title"; const data = { @@ -93,6 +93,10 @@ const headers = [ const TicketHolderList = () => { const [paymentData, setPaymentData] = useState(); + // DEFAULT, PAYMENT, REFUND, DELETE + const [status, setStatus] = useState("DEFAULT"); + const [buttonText, setButtonText] = useState("예매자 관리하기"); + const [CSVDataArr, setCSVDataArr] = useState<CSVDataType[]>([]); const { performanceId } = useParams(); @@ -100,6 +104,36 @@ const TicketHolderList = () => { // const { data, isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); const { isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); + // const buttonText = (status) => { + // switch (status) { + // case "PAYMENT": + // return "입금 처리하기"; + // case "REFUND": + // return "환불 처리하기"; + // case "DELETE": + // return "예매자 삭제하기"; + // default: + // return "예매자 관리하기"; + // } + // }; + + useEffect(() => { + switch (status) { + case "PAYMENT": + setButtonText("입금 처리하기"); + break; + case "REFUND": + setButtonText("환불 처리하기"); + break; + case "DELETE": + setButtonText("예매자 삭제하기"); + break; + default: + setButtonText("예매자 관리하기"); + break; + } + }, [status]); + useEffect(() => { if (data?.bookingList) { //전체 데이터를 기반으로 csv 추출 데이터 구축 @@ -161,11 +195,11 @@ const TicketHolderList = () => { totalSolidCount={data?.totalPerformanceSoldTicketCount} totalCount={data?.totalPerformanceTicketCount} /> - <S.FooterButtonWrapper> - {/* TODO : 상태에 따라 텍스트 다르게 */} - <Button>예매자 관리하기</Button> - </S.FooterButtonWrapper> </S.TicketHolderListWrpper> + <S.FooterButtonWrapper> + {/* TODO : 상태에 따라 텍스트 다르게 */} + <Button>{buttonText}</Button> + </S.FooterButtonWrapper> </> )} </> From 51937c7c9e2ae293c7553db4cca2a0c35c11724c Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sat, 23 Nov 2024 03:31:09 +0900 Subject: [PATCH 03/49] =?UTF-8?q?feat:=20=EA=B2=80=EC=83=89=20=EB=B0=94=20?= =?UTF-8?q?=ED=8D=BC=EB=B8=94=EB=A6=AC=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../TicketHolderList.styled.ts | 2 +- .../ticketholderlist/TicketHolderList.tsx | 27 ++++++---------- .../components/searchBar/SearchBar.styled.ts | 32 +++++++++++++++++++ .../components/searchBar/SearchBar.tsx | 14 ++++++++ 4 files changed, 56 insertions(+), 19 deletions(-) create mode 100644 src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts create mode 100644 src/pages/ticketholderlist/components/searchBar/SearchBar.tsx diff --git a/src/pages/ticketholderlist/TicketHolderList.styled.ts b/src/pages/ticketholderlist/TicketHolderList.styled.ts index b22407e3..21348df8 100644 --- a/src/pages/ticketholderlist/TicketHolderList.styled.ts +++ b/src/pages/ticketholderlist/TicketHolderList.styled.ts @@ -11,5 +11,5 @@ export const FooterButtonWrapper = styled.div` bottom: 0; z-index: 1; min-height: 10.4rem; - padding: 2.4rem; + padding-top: 2.4rem; `; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index a6fdaa04..ad3a4224 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -8,8 +8,9 @@ import { CSVLink } from "react-csv"; import { useNavigate, useParams } from "react-router-dom"; import { convertingNumber } from "@constants/convertingNumber"; import * as S from "./TicketHolderList.styled"; -import { BottomSheet, Button } from "@components/commons"; +import { BottomSheet, Button, Spacing } from "@components/commons"; import Title from "@pages/ticketholderlist/components/title/Title"; +import SearchBar from "./components/searchBar/SearchBar"; const data = { performanceTitle: "비트밴드 정기공연", @@ -104,19 +105,7 @@ const TicketHolderList = () => { // const { data, isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); const { isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); - // const buttonText = (status) => { - // switch (status) { - // case "PAYMENT": - // return "입금 처리하기"; - // case "REFUND": - // return "환불 처리하기"; - // case "DELETE": - // return "예매자 삭제하기"; - // default: - // return "예매자 관리하기"; - // } - // }; - + // 상태에 따라 버튼 텍스트 변경 useEffect(() => { switch (status) { case "PAYMENT": @@ -195,11 +184,13 @@ const TicketHolderList = () => { totalSolidCount={data?.totalPerformanceSoldTicketCount} totalCount={data?.totalPerformanceTicketCount} /> + <Spacing marginBottom={"2.6"} /> + <SearchBar /> + <Spacing marginBottom={"1.6"} /> + <S.FooterButtonWrapper> + <Button>{buttonText}</Button> + </S.FooterButtonWrapper> </S.TicketHolderListWrpper> - <S.FooterButtonWrapper> - {/* TODO : 상태에 따라 텍스트 다르게 */} - <Button>{buttonText}</Button> - </S.FooterButtonWrapper> </> )} </> diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts new file mode 100644 index 00000000..0ca1fa87 --- /dev/null +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts @@ -0,0 +1,32 @@ +import styled from "styled-components"; + +export const SearchBarWrapper = styled.section` + display: flex; + flex-direction: row; + width: 32.7rem; +`; + +export const SearchBar = styled.input` + width: 100%; + height: 4.8rem; + padding: 1.3rem; + + color: ${({ theme }) => theme.colors.gray_600}; + ${({ theme }) => theme.fonts["body2-normal-medi"]}; + + background-color: ${({ theme }) => theme.colors.gray_800}; + border: 0.1rem solid; + border-color: ${({ theme }) => theme.colors.gray_700}; + border-radius: 4rem; +`; + +export const FilterBtn = styled.button` + width: 4.8rem; + height: 4.8rem; + margin-left: 1.2rem; + + background-color: ${({ theme }) => theme.colors.gray_800}; + border: 0.1rem solid; + border-color: ${({ theme }) => theme.colors.gray_700}; + border-radius: 50%; +`; diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx new file mode 100644 index 00000000..fff82547 --- /dev/null +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -0,0 +1,14 @@ +import React from "react"; +import * as S from "./SearchBar.styled"; + +const SearchBar = () => { + return ( + <S.SearchBarWrapper> + <S.SearchBar type="text" placeholder="예매자를 검색해보세요."></S.SearchBar> + {/* TODO: 상태 DEFAULT일 때만 필터 버튼 노출 */} + <S.FilterBtn /> + </S.SearchBarWrapper> + ); +}; + +export default SearchBar; From 755d96d3e32119a9467fe0c00b824c2cd609e419 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sun, 24 Nov 2024 17:35:27 +0900 Subject: [PATCH 04/49] =?UTF-8?q?feat:=20=EB=A9=94=EB=89=B4=EB=B0=94?= =?UTF-8?q?=ED=85=80=EC=8B=9C=ED=8A=B8=20=ED=8D=BC=EB=B8=94=EB=A6=AC?= =?UTF-8?q?=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ticketholderlist/TicketHolderList.tsx | 9 +++ .../MenuBottomSheet/MenuBottomSheet.styled.ts | 5 ++ .../MenuBottomSheet/MenuBottomsheet.tsx | 62 +++++++++++++++++++ .../components/searchBar/SearchBar.styled.ts | 6 +- 4 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomSheet.styled.ts create mode 100644 src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index ad3a4224..afa72916 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -11,6 +11,7 @@ import * as S from "./TicketHolderList.styled"; import { BottomSheet, Button, Spacing } from "@components/commons"; import Title from "@pages/ticketholderlist/components/title/Title"; import SearchBar from "./components/searchBar/SearchBar"; +import MenuBottomsheet from "./components/MenuBottomSheet/MenuBottomsheet"; const data = { performanceTitle: "비트밴드 정기공연", @@ -98,6 +99,9 @@ const TicketHolderList = () => { const [status, setStatus] = useState("DEFAULT"); const [buttonText, setButtonText] = useState("예매자 관리하기"); + const [openFilter, setOpenFilter] = useState(false); + const [openMenu, setOpenMenu] = useState(false); + const [CSVDataArr, setCSVDataArr] = useState<CSVDataType[]>([]); const { performanceId } = useParams(); @@ -123,6 +127,10 @@ const TicketHolderList = () => { } }, [status]); + const handleMenuClose = () => { + setOpenMenu(false); + }; + useEffect(() => { if (data?.bookingList) { //전체 데이터를 기반으로 csv 추출 데이터 구축 @@ -190,6 +198,7 @@ const TicketHolderList = () => { <S.FooterButtonWrapper> <Button>{buttonText}</Button> </S.FooterButtonWrapper> + <MenuBottomsheet isOpen={true} onClickOutside={handleMenuClose} /> </S.TicketHolderListWrpper> </> )} diff --git a/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomSheet.styled.ts b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomSheet.styled.ts new file mode 100644 index 00000000..7d6ee676 --- /dev/null +++ b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomSheet.styled.ts @@ -0,0 +1,5 @@ +import styled from "styled-components"; + +export const MenuBottomSheetWrapper = styled.section` + display: flex; +`; diff --git a/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx new file mode 100644 index 00000000..dc739df6 --- /dev/null +++ b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx @@ -0,0 +1,62 @@ +import { Children, isValidElement, ReactNode, useEffect } from "react"; +import * as S from "./MenuBottomSheet.styled"; +import BottomSheet from "@components/commons/bottomSheet/BottomSheet"; +import OuterLayout from "@components/commons/bottomSheet/OuterLayout"; +import { Button, Spacing } from "@components/commons"; + +interface MenuBottomSheetProps { + isOpen: boolean; + children?: ReactNode; + onClickOutside: () => void; +} + +const MenuBottomsheet = ({ isOpen, onClickOutside, children, ...rest }: MenuBottomSheetProps) => { + const childrenArray = Children.toArray(children); + + const contextChildren = childrenArray.filter( + (child) => isValidElement(child) && child.type !== OuterLayout + ); + + const remainingChildren = childrenArray.filter( + (child) => !isValidElement(child) || child.type === OuterLayout + ); + + const handleWrapperClick = () => { + onClickOutside(); + }; + + useEffect(() => { + if (isOpen) { + document.body.style.overflow = "hidden"; + } else { + document.body.style.overflow = "auto"; + } + return () => { + document.body.style.overflow = "auto"; + }; + }, [isOpen]); + + const handleStatus = (status: string) => { + // TODO : 페이지에서 setStaus 넘겨서 여기서 받아주기 + }; + + return ( + <S.MenuBottomSheetWrapper> + <BottomSheet isOpen={isOpen} paddingTop="2.4rem"> + <Button onClick={handleStatus("PAYMENT")} size="xlarge" variant="gray"> + 입금 처리하기 + </Button> + <Spacing marginBottom="1.2" /> + <Button onClick={handleStatus("REFUND")} size="xlarge" variant="gray"> + 환불 처리하기 + </Button> + <Spacing marginBottom="1.2" /> + <Button onClick={handleStatus("DELETE")} size="xlarge" variant="gray"> + 예매자 삭제하기 + </Button> + </BottomSheet> + </S.MenuBottomSheetWrapper> + ); +}; + +export default MenuBottomsheet; diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts index 0ca1fa87..595e218f 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts @@ -3,15 +3,16 @@ import styled from "styled-components"; export const SearchBarWrapper = styled.section` display: flex; flex-direction: row; + align-items: center; width: 32.7rem; `; export const SearchBar = styled.input` - width: 100%; + flex-grow: 1; height: 4.8rem; padding: 1.3rem; - color: ${({ theme }) => theme.colors.gray_600}; + color: ${({ theme }) => theme.colors.white}; ${({ theme }) => theme.fonts["body2-normal-medi"]}; background-color: ${({ theme }) => theme.colors.gray_800}; @@ -20,6 +21,7 @@ export const SearchBar = styled.input` border-radius: 4rem; `; +// 찌그러지는 거 수정하기 export const FilterBtn = styled.button` width: 4.8rem; height: 4.8rem; From e2b3ee4e0c61115c5f66cbdbededcf482a445973 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sun, 24 Nov 2024 17:35:50 +0900 Subject: [PATCH 05/49] =?UTF-8?q?fix:=20=EB=B0=94=ED=85=80=EC=8B=9C?= =?UTF-8?q?=ED=8A=B8=20=ED=83=80=EC=9D=B4=ED=8B=80=20padding=EA=B0=92=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/commons/bottomSheet/BottomSheet.styled.ts | 7 ------- src/components/commons/bottomSheet/BottomSheet.tsx | 2 +- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/components/commons/bottomSheet/BottomSheet.styled.ts b/src/components/commons/bottomSheet/BottomSheet.styled.ts index 806f7375..20fbb28a 100644 --- a/src/components/commons/bottomSheet/BottomSheet.styled.ts +++ b/src/components/commons/bottomSheet/BottomSheet.styled.ts @@ -30,10 +30,3 @@ export const BottomSheetLayout = styled.section<{ $paddingTop?: string }>` background-color: ${({ theme }) => theme.colors.gray_800}; border-radius: 2rem 2rem 0 0; `; - -export const Title = styled.h1` - margin-bottom: 2.8rem; - - color: ${({ theme }) => theme.colors.white}; - ${({ theme }) => theme.fonts.heading4}; -`; diff --git a/src/components/commons/bottomSheet/BottomSheet.tsx b/src/components/commons/bottomSheet/BottomSheet.tsx index 98da34b9..c4600f51 100644 --- a/src/components/commons/bottomSheet/BottomSheet.tsx +++ b/src/components/commons/bottomSheet/BottomSheet.tsx @@ -13,7 +13,7 @@ const BottomSheet = ({ isOpen, title, paddingTop, children }: BottomSheetPropTyp return ( <S.BottomSheetWrapper $isOpen={isOpen} onClick={(e) => e.stopPropagation()}> <S.BottomSheetLayout $paddingTop={paddingTop}> - <S.Title>{title}</S.Title> + <S.Title $title={title}>{title}</S.Title> {children} </S.BottomSheetLayout> </S.BottomSheetWrapper> From 1c3c8dc60e1f26659a8569364d67662c7bc4ac86 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sun, 24 Nov 2024 17:36:48 +0900 Subject: [PATCH 06/49] =?UTF-8?q?fix:=20=EB=B0=94=ED=85=80=EC=8B=9C?= =?UTF-8?q?=ED=8A=B8=20=ED=83=80=EC=9D=B4=ED=8B=80=20padding=EA=B0=92=20?= =?UTF-8?q?=EC=84=A0=ED=83=9D=EC=9C=BC=EB=A1=9C=20=EB=B3=80=EA=B2=BD=20-?= =?UTF-8?q?=20=EC=8A=A4=ED=83=80=EC=9D=BC=20=ED=8C=8C=EC=9D=BC=20=EC=88=98?= =?UTF-8?q?=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/commons/bottomSheet/BottomSheet.styled.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/components/commons/bottomSheet/BottomSheet.styled.ts b/src/components/commons/bottomSheet/BottomSheet.styled.ts index 20fbb28a..e0dbbe1c 100644 --- a/src/components/commons/bottomSheet/BottomSheet.styled.ts +++ b/src/components/commons/bottomSheet/BottomSheet.styled.ts @@ -30,3 +30,10 @@ export const BottomSheetLayout = styled.section<{ $paddingTop?: string }>` background-color: ${({ theme }) => theme.colors.gray_800}; border-radius: 2rem 2rem 0 0; `; + +export const Title = styled.h1<{ $title?: string }>` + margin-bottom: ${({ $title }) => ($title ? "2.8rem" : "0")}; + + color: ${({ theme }) => theme.colors.white}; + ${({ theme }) => theme.fonts.heading4}; +`; From 1d17f5c3be5c8877335a32b675c10ea2eb827fd6 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sun, 24 Nov 2024 18:10:15 +0900 Subject: [PATCH 07/49] =?UTF-8?q?feat:=20=EC=83=81=ED=83=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD=20=EB=B0=94=ED=85=80=EC=8B=9C=ED=8A=B8=20=EC=99=84?= =?UTF-8?q?=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ticketholderlist/TicketHolderList.tsx | 54 +++++++++++++------ .../MenuBottomSheet/MenuBottomSheet.styled.ts | 16 +++++- .../MenuBottomSheet/MenuBottomsheet.tsx | 21 ++++---- 3 files changed, 64 insertions(+), 27 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index afa72916..2cacd744 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -109,24 +109,40 @@ const TicketHolderList = () => { // const { data, isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); const { isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); - // 상태에 따라 버튼 텍스트 변경 + const actions = { + PAYMENT: { + text: "입금 처리하기", + action: console.log("입금 처리"), + }, + REFUND: { + text: "환불 처리하기", + action: () => console.log("환불"), + }, + DELETE: { + text: "예매자 삭제하기", + action: () => console.log("예매자 삭제"), + }, + DEFAULT: { + text: "예매자 관리하기", + action: () => setOpenMenu(true), + }, + }; + + // 상태 변경 시 버튼 텍스트 설정 useEffect(() => { - switch (status) { - case "PAYMENT": - setButtonText("입금 처리하기"); - break; - case "REFUND": - setButtonText("환불 처리하기"); - break; - case "DELETE": - setButtonText("예매자 삭제하기"); - break; - default: - setButtonText("예매자 관리하기"); - break; - } + setButtonText(actions[status]?.text || "예매자 관리하기"); }, [status]); + const handleButtonClick = () => { + actions[status]?.action?.(); + }; + + const handleStatus = (status: string) => { + setStatus(status); + setOpenMenu(false); + }; + + // 메뉴 바텀시트 관리 const handleMenuClose = () => { setOpenMenu(false); }; @@ -196,10 +212,14 @@ const TicketHolderList = () => { <SearchBar /> <Spacing marginBottom={"1.6"} /> <S.FooterButtonWrapper> - <Button>{buttonText}</Button> + <Button onClick={handleButtonClick}>{buttonText}</Button> </S.FooterButtonWrapper> - <MenuBottomsheet isOpen={true} onClickOutside={handleMenuClose} /> </S.TicketHolderListWrpper> + <MenuBottomsheet + isOpen={openMenu} + onClickOutside={handleMenuClose} + handleStatus={handleStatus} + /> </> )} </> diff --git a/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomSheet.styled.ts b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomSheet.styled.ts index 7d6ee676..30975f99 100644 --- a/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomSheet.styled.ts +++ b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomSheet.styled.ts @@ -1,5 +1,19 @@ import styled from "styled-components"; -export const MenuBottomSheetWrapper = styled.section` +export const MenuBottomSheetWrapper = styled.section<{ $isOpen: boolean }>` + position: fixed; + bottom: 0; + z-index: 30; display: flex; + justify-content: center; + width: 100%; + height: 100%; + + background-color: rgb(0 0 0 / 50%); + visibility: ${({ $isOpen }) => ($isOpen ? "visible" : "hidden")}; + opacity: ${({ $isOpen }) => ($isOpen ? 1 : 0)}; + + transition: + opacity 250ms ease-in-out, + visibility 250ms ease-in-out; `; diff --git a/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx index dc739df6..981aeba8 100644 --- a/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx +++ b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx @@ -8,9 +8,16 @@ interface MenuBottomSheetProps { isOpen: boolean; children?: ReactNode; onClickOutside: () => void; + handleStatus: (status: string) => void; } -const MenuBottomsheet = ({ isOpen, onClickOutside, children, ...rest }: MenuBottomSheetProps) => { +const MenuBottomsheet = ({ + isOpen, + onClickOutside, + children, + handleStatus, + ...rest +}: MenuBottomSheetProps) => { const childrenArray = Children.toArray(children); const contextChildren = childrenArray.filter( @@ -36,22 +43,18 @@ const MenuBottomsheet = ({ isOpen, onClickOutside, children, ...rest }: MenuBott }; }, [isOpen]); - const handleStatus = (status: string) => { - // TODO : 페이지에서 setStaus 넘겨서 여기서 받아주기 - }; - return ( - <S.MenuBottomSheetWrapper> + <S.MenuBottomSheetWrapper $isOpen={isOpen} onClick={handleWrapperClick}> <BottomSheet isOpen={isOpen} paddingTop="2.4rem"> - <Button onClick={handleStatus("PAYMENT")} size="xlarge" variant="gray"> + <Button onClick={() => handleStatus("PAYMENT")} size="xlarge" variant="gray"> 입금 처리하기 </Button> <Spacing marginBottom="1.2" /> - <Button onClick={handleStatus("REFUND")} size="xlarge" variant="gray"> + <Button onClick={() => handleStatus("REFUND")} size="xlarge" variant="gray"> 환불 처리하기 </Button> <Spacing marginBottom="1.2" /> - <Button onClick={handleStatus("DELETE")} size="xlarge" variant="gray"> + <Button onClick={() => handleStatus("DELETE")} size="xlarge" variant="gray"> 예매자 삭제하기 </Button> </BottomSheet> From ee17cfe7e561a249230bdebb583368256c945a96 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 25 Nov 2024 03:03:44 +0900 Subject: [PATCH 08/49] =?UTF-8?q?feat:=20=ED=95=84=ED=84=B0=20=EC=9E=85?= =?UTF-8?q?=EA=B8=88=20=EC=83=81=ED=83=9C=20=ED=8D=BC=EB=B8=94=EB=A6=AC?= =?UTF-8?q?=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/svgs/ic_refresh.svg | 3 + src/assets/svgs/IcRefresh.tsx | 11 +++ src/assets/svgs/index.ts | 66 ++++++++++++++ src/assets/svgs/index.tsx | 1 + .../TicketHolderList.styled.ts | 1 + .../ticketholderlist/TicketHolderList.tsx | 40 ++++++--- .../FilterBottomSheet.styled.ts | 87 +++++++++++++++++++ .../FilterBottomSheet/FilterBottomSheet.tsx | 71 +++++++++++++++ .../MenuBottomSheet/MenuBottomsheet.tsx | 21 ----- .../components/searchBar/SearchBar.tsx | 8 +- .../components/title/Title.tsx | 1 + .../ticketholderlist/types/bookingListType.ts | 13 +++ 12 files changed, 289 insertions(+), 34 deletions(-) create mode 100644 public/svgs/ic_refresh.svg create mode 100644 src/assets/svgs/IcRefresh.tsx create mode 100644 src/assets/svgs/index.ts create mode 100644 src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts create mode 100644 src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx create mode 100644 src/pages/ticketholderlist/types/bookingListType.ts diff --git a/public/svgs/ic_refresh.svg b/public/svgs/ic_refresh.svg new file mode 100644 index 00000000..bfba7c52 --- /dev/null +++ b/public/svgs/ic_refresh.svg @@ -0,0 +1,3 @@ +<svg width="22" height="22" viewBox="0 0 22 22" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M10.9987 17.6654C9.13758 17.6654 7.5612 17.0195 6.26953 15.7279C4.97786 14.4362 4.33203 12.8598 4.33203 10.9987C4.33203 9.13759 4.97786 7.5612 6.26953 6.26953C7.5612 4.97787 9.13758 4.33203 10.9987 4.33203C11.957 4.33203 12.8737 4.52981 13.7487 4.92537C14.6237 5.32092 15.3737 5.88703 15.9987 6.6237V5.16537C15.9987 4.92926 16.0787 4.73148 16.2387 4.57203C16.3987 4.41259 16.5965 4.33259 16.832 4.33203C17.0676 4.33148 17.2656 4.41148 17.4262 4.57203C17.5867 4.73259 17.6665 4.93037 17.6654 5.16537V9.33203C17.6654 9.56814 17.5854 9.7662 17.4254 9.9262C17.2654 10.0862 17.0676 10.1659 16.832 10.1654H12.6654C12.4292 10.1654 12.2315 10.0854 12.072 9.92536C11.9126 9.76536 11.8326 9.56759 11.832 9.33203C11.8315 9.09648 11.9115 8.8987 12.072 8.7387C12.2326 8.5787 12.4304 8.4987 12.6654 8.4987H15.332C14.8876 7.72092 14.2801 7.10981 13.5095 6.66537C12.739 6.22092 11.902 5.9987 10.9987 5.9987C9.6098 5.9987 8.42925 6.48481 7.45703 7.45703C6.48481 8.42925 5.9987 9.60981 5.9987 10.9987C5.9987 12.3876 6.48481 13.5681 7.45703 14.5404C8.42925 15.5126 9.6098 15.9987 10.9987 15.9987C11.9431 15.9987 12.8079 15.7592 13.5929 15.2804C14.3779 14.8015 14.9854 14.159 15.4154 13.3529C15.5265 13.1584 15.6829 13.0231 15.8845 12.947C16.0862 12.8709 16.2909 12.8673 16.4987 12.9362C16.7209 13.0056 16.8806 13.1515 16.9779 13.3737C17.0751 13.5959 17.0681 13.8042 16.957 13.9987C16.3876 15.1098 15.5751 15.9987 14.5195 16.6654C13.464 17.332 12.2904 17.6654 10.9987 17.6654Z" fill="#F4F4F4"/> +</svg> diff --git a/src/assets/svgs/IcRefresh.tsx b/src/assets/svgs/IcRefresh.tsx new file mode 100644 index 00000000..c6324986 --- /dev/null +++ b/src/assets/svgs/IcRefresh.tsx @@ -0,0 +1,11 @@ +import * as React from "react"; +import type { SVGProps } from "react"; +const SvgIcRefresh = (props: SVGProps<SVGSVGElement>) => ( + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22" {...props}> + <path + fill="#F4F4F4" + d="M10.999 17.665q-2.792 0-4.73-1.937-1.937-1.937-1.937-4.73 0-2.79 1.938-4.728t4.729-1.938q1.437 0 2.75.593a6.34 6.34 0 0 1 2.25 1.699V5.165q0-.354.24-.593a.8.8 0 0 1 .593-.24q.354 0 .594.24a.8.8 0 0 1 .24.593v4.167q0 .354-.24.594a.8.8 0 0 1-.594.24h-4.167a.8.8 0 0 1-.593-.24.8.8 0 0 1-.24-.594q0-.354.24-.593.24-.24.593-.24h2.667a4.86 4.86 0 0 0-1.823-1.834A4.94 4.94 0 0 0 11 6q-2.085 0-3.542 1.458-1.458 1.458-1.458 3.542t1.458 3.541Q8.915 16 10.999 16q1.416 0 2.594-.719a4.95 4.95 0 0 0 1.822-1.927.9.9 0 0 1 .47-.406.9.9 0 0 1 .614-.01.75.75 0 0 1 .479.437q.146.333-.021.625a6.73 6.73 0 0 1-2.437 2.666q-1.584 1-3.521 1" + /> + </svg> +); +export default SvgIcRefresh; diff --git a/src/assets/svgs/index.ts b/src/assets/svgs/index.ts new file mode 100644 index 00000000..6b73afb9 --- /dev/null +++ b/src/assets/svgs/index.ts @@ -0,0 +1,66 @@ +export { default as BannerBasic } from "./BannerBasic"; +export { default as BtnFloating } from "./BtnFloating"; +export { default as BtnModalDelete } from "./BtnModalDelete"; +export { default as ButtonDelete24 } from "./ButtonDelete24"; +export { default as CarouselPartInactive } from "./CarouselPartInactive"; +export { default as Empty } from "./Empty"; +export { default as IcomCopy } from "./IcomCopy"; +export { default as IconArrowLeft } from "./IconArrowLeft"; +export { default as IconArrowRight } from "./IconArrowRight"; +export { default as IconArrowDown } from "./IconArrowDown"; +export { default as IconArrowDown } from "./IconArrowDown"; +export { default as IconArrowUp } from "./IconArrowUp"; +export { default as IconBnk } from "./IconBnk"; +export { default as IconCalendar } from "./IconCalendar"; +export { default as IconCamera } from "./IconCamera"; +export { default as IconCheckboxDisabledOn } from "./IconCheckboxDisabledOn"; +export { default as IconCheckboxSelectedOn } from "./IconCheckboxSelectedOn"; +export { default as IconCheckboxUnselectedOn } from "./IconCheckboxUnselectedOn"; +export { default as IconChecked } from "./IconChecked"; +export { default as IconChevronBack } from "./IconChevronBack"; +export { default as IconEmpty } from "./IconEmpty"; +export { default as IconEyeOff } from "./IconEyeOff"; +export { default as IconEyeOn } from "./IconEyeOn"; +export { default as IconFooterLogo } from "./IconFooterLogo"; +export { default as IconHanna } from "./IconHanna"; +export { default as IconIbk } from "./IconIbk"; +export { default as IconIm } from "./IconIm"; +export { default as IconImg } from "./IconImg"; +export { default as IconKabank } from "./IconKabank"; +export { default as IconKb } from "./IconKb"; +export { default as IconLargeBand } from "./IconLargeBand"; +export { default as IconLargeDance } from "./IconLargeDance"; +export { default as IconLargeEtc } from "./IconLargeEtc"; +export { default as IconLargeMusical } from "./IconLargeMusical"; +export { default as IconLogo } from "./IconLogo"; +export { default as IconMinus } from "./IconMinus"; +export { default as IconNonghyup } from "./IconNonghyup"; +export { default as IconPhotoDelete } from "./IconPhotoDelete"; +export { default as IconPlus } from "./IconPlus"; +export { default as IconProfile } from "./IconProfile"; +export { default as IconRoleAdd } from "./IconRoleAdd"; +export { default as IconSaemauel } from "./IconSaemauel"; +export { default as IconSc } from "./IconSc"; +export { default as IconShinhan } from "./IconShinhan"; +export { default as IconShinhyup } from "./IconShinhyup"; +export { default as IconSmallBand } from "./IconSmallBand"; +export { default as IconSmallDance } from "./IconSmallDance"; +export { default as IconSmallEtc } from "./IconSmallEtc"; +export { default as IconSmallMusical } from "./IconSmallMusical"; +export { default as IconSoohyup } from "./IconSoohyup"; +export { default as IconTextfiedlDelete } from "./IconTextfiedlDelete"; +export { default as IconTime } from "./IconTime"; +export { default as IconToggleOff } from "./IconToggleOff"; +export { default as IconToggleOn } from "./IconToggleOn"; +export { default as IconToss } from "./IconToss"; +export { default as IconWoochaegook } from "./IconWoochaegook"; +export { default as IconWoori } from "./IconWoori"; +export { default as IconXButton } from "./IconXButton"; +export { default as IcDelete } from "./IcDelete"; +export { default as IcHamburgar } from "./IcHamburgar"; +export { default as IcOutlinePlace } from "./IcOutlinePlace"; +export { default as IcRefresh } from "./IcRefresh"; +export { default as NotFoundAsset } from "./NotFoundAsset"; +export { default as Subtract } from "./Subtract"; +export { default as Switch } from "./Switch"; +export { default as Union } from "./Union"; diff --git a/src/assets/svgs/index.tsx b/src/assets/svgs/index.tsx index d28c5347..a1390878 100644 --- a/src/assets/svgs/index.tsx +++ b/src/assets/svgs/index.tsx @@ -59,6 +59,7 @@ export { default as IconWoochaegook } from "./IconWoochaegook"; export { default as IconWoori } from "./IconWoori"; export { default as IconXButton } from "./IconXButton"; export { default as IcOutlinePlace } from "./IcOutlinePlace"; +export { default as IcRefresh } from "./IcRefresh"; export { default as NotFoundAsset } from "./NotFoundAsset"; export { default as SelectionControlCheckboxSelectedOff } from "./SelectionControlCheckboxSelectedOff"; export { default as Subtract } from "./Subtract"; diff --git a/src/pages/ticketholderlist/TicketHolderList.styled.ts b/src/pages/ticketholderlist/TicketHolderList.styled.ts index 21348df8..dbd1c057 100644 --- a/src/pages/ticketholderlist/TicketHolderList.styled.ts +++ b/src/pages/ticketholderlist/TicketHolderList.styled.ts @@ -3,6 +3,7 @@ import styled from "styled-components"; export const TicketHolderListWrpper = styled.section` display: flex; flex-direction: column; + align-items: center; padding: 0.8rem 2.4rem 2.6rem; `; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 2cacd744..91b10472 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -12,6 +12,8 @@ import { BottomSheet, Button, Spacing } from "@components/commons"; import Title from "@pages/ticketholderlist/components/title/Title"; import SearchBar from "./components/searchBar/SearchBar"; import MenuBottomsheet from "./components/MenuBottomSheet/MenuBottomsheet"; +import FilterBottomSheet from "./components/FilterBottomSheet/FilterBottomSheet"; +import { BookingListProps } from "./types/BookingListType"; const data = { performanceTitle: "비트밴드 정기공연", @@ -93,7 +95,7 @@ const headers = [ ]; const TicketHolderList = () => { - const [paymentData, setPaymentData] = useState(); + const [paymentData, setPaymentData] = useState<BookingListProps[]>(); // DEFAULT, PAYMENT, REFUND, DELETE const [status, setStatus] = useState("DEFAULT"); @@ -112,14 +114,17 @@ const TicketHolderList = () => { const actions = { PAYMENT: { text: "입금 처리하기", + // TODO : 예매 확정 팝업 action: console.log("입금 처리"), }, REFUND: { text: "환불 처리하기", + // TODO : 환불 처리 팝업 action: () => console.log("환불"), }, DELETE: { text: "예매자 삭제하기", + // TODO : 예매자 삭제 팝업 action: () => console.log("예매자 삭제"), }, DEFAULT: { @@ -142,12 +147,24 @@ const TicketHolderList = () => { setOpenMenu(false); }; - // 메뉴 바텀시트 관리 - const handleMenuClose = () => { + // 바텀시트 닫기 + const closeBottomSheet = () => { setOpenMenu(false); + setOpenFilter(false); + }; + + // 필터 바텀시트 + const handleFilter = () => { + if (!openFilter) { + setOpenFilter(true); + } else { + setOpenFilter(false); + } }; useEffect(() => { + setPaymentData(data?.bookingList ?? []); + if (data?.bookingList) { //전체 데이터를 기반으로 csv 추출 데이터 구축 const tempCSVDataArr: CSVDataType[] = []; @@ -186,8 +203,8 @@ const TicketHolderList = () => { setHeader({ headerStyle: NAVIGATION_STATE.ICON_TITLE_SUB_TEXT, title: "예매자 관리", - // TODO : 사이즈 안 맞는 거 공통컴포넌트 수정하기 - subText: "CSV 다운", + // TODO : 공통컴포넌트에 svg 들어갈 수 있도록 수정하기 + subText: "CSV", leftOnClick: handleNavigateBack, // TODO : rightOnClick CSV 다운로드로 변경 // rightOnClick: , @@ -209,17 +226,18 @@ const TicketHolderList = () => { totalCount={data?.totalPerformanceTicketCount} /> <Spacing marginBottom={"2.6"} /> - <SearchBar /> + <SearchBar handleFilter={handleFilter} /> <Spacing marginBottom={"1.6"} /> <S.FooterButtonWrapper> <Button onClick={handleButtonClick}>{buttonText}</Button> </S.FooterButtonWrapper> + <MenuBottomsheet + isOpen={openMenu} + onClickOutside={closeBottomSheet} + handleStatus={handleStatus} + /> + <FilterBottomSheet isOpen={openFilter} onClickOutside={handleFilter} /> </S.TicketHolderListWrpper> - <MenuBottomsheet - isOpen={openMenu} - onClickOutside={handleMenuClose} - handleStatus={handleStatus} - /> </> )} </> diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts new file mode 100644 index 00000000..67a916b2 --- /dev/null +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts @@ -0,0 +1,87 @@ +import styled from "styled-components"; +import { IcRefresh, IconCheckboxSelectedOn, IconCheckboxUnselectedOn } from "@assets/svgs"; + +export const FilterBottomSheetWrapper = styled.section<{ $isOpen: boolean }>` + position: fixed; + bottom: 0; + z-index: 30; + display: flex; + justify-content: center; + width: 100%; + height: 100%; + + background-color: rgb(0 0 0 / 50%); + visibility: ${({ $isOpen }) => ($isOpen ? "visible" : "hidden")}; + opacity: ${({ $isOpen }) => ($isOpen ? 1 : 0)}; + + transition: + opacity 250ms ease-in-out, + visibility 250ms ease-in-out; +`; + +export const TitleWrapper = styled.section` + display: flex; + flex-direction: row; + align-items: center; + justify-content: space-between; + margin-bottom: 1.6rem; + + ${({ theme }) => theme.fonts.heading4}; + color: ${({ theme }) => theme.colors.white}; +`; + +export const RefreshBtn = styled.button` + display: flex; + align-items: center; + justify-content: center; + width: 3.2rem; + height: 3.2rem; + + background-color: ${({ theme }) => theme.colors.gray_700}; + border-radius: 50%; +`; + +export const RefreshIcon = styled(IcRefresh)` + display: flex; + width: 2.1rem; + height: 2.1rem; +`; + +export const CheckBoxContainer = styled.section` + display: flex; + flex-direction: column; + gap: 1.2rem; + margin-bottom: 3.2rem; +`; + +export const CheckBoxRow = styled.section` + display: flex; + gap: 8.1rem; +`; + +export const CheckBoxLabel = styled.label` + display: flex; + align-items: center; + width: 9rem; +`; + +export const CheckBox = styled.input` + display: none; +`; + +export const SelectIcon = styled(IconCheckboxSelectedOn)` + width: 2rem; + height: 2rem; + margin-right: 0.8rem; +`; + +export const UnSelectIcon = styled(IconCheckboxUnselectedOn)` + width: 2rem; + height: 2rem; + margin-right: 0.8rem; +`; + +export const CheckBoxText = styled.div` + color: ${({ theme }) => theme.colors.gray_200}; + ${({ theme }) => theme.fonts["body1-normal-semi"]}; +`; diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx new file mode 100644 index 00000000..26044b50 --- /dev/null +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -0,0 +1,71 @@ +import React, { useState, ReactNode } from "react"; +import * as S from "./FilterBottomSheet.styled"; +import { BottomSheet, Button } from "@components/commons"; +import { BoxDivider } from "@components/commons/bottomSheet/viewBottomSheet/ViewBottomSheet.styled"; + +interface FilterBottomSheetProps { + isOpen: boolean; + children?: ReactNode; + onClickOutside?: () => void; +} + +const bookingStatusList = ["미입금", "입금 완료", "환불 요청", "취소 완료"]; + +const FilterBottomSheet = ({ isOpen, onClickOutside, children }: FilterBottomSheetProps) => { + const [checkedStatusList, setCheckedStatusList] = useState<string[]>([]); + + const handleWrapperClick = () => { + onClickOutside(); + }; + + const handleCheck = (status: string) => { + setCheckedStatusList((prev) => + prev.includes(status) ? prev.filter((item) => item !== status) : [...prev, status] + ); + }; + + return ( + <S.FilterBottomSheetWrapper $isOpen={isOpen} onClick={handleWrapperClick}> + <BottomSheet isOpen={isOpen}> + <S.TitleWrapper> + 회차 + <S.RefreshBtn> + <S.RefreshIcon /> + </S.RefreshBtn> + </S.TitleWrapper> + <S.TitleWrapper>입금 상태</S.TitleWrapper> + <S.CheckBoxContainer> + <S.CheckBoxRow> + {bookingStatusList.slice(0, 2).map((status, idx) => ( + <S.CheckBoxLabel key={idx}> + <S.CheckBox + type="checkbox" + checked={checkedStatusList.includes(status)} + onChange={() => handleCheck(status)} + /> + {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} + <S.CheckBoxText>{status}</S.CheckBoxText> + </S.CheckBoxLabel> + ))} + </S.CheckBoxRow> + <S.CheckBoxRow> + {bookingStatusList.slice(2, 4).map((status, idx) => ( + <S.CheckBoxLabel key={idx}> + <S.CheckBox + type="checkbox" + checked={checkedStatusList.includes(status)} + onChange={() => handleCheck(status)} + /> + {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} + <S.CheckBoxText>{status}</S.CheckBoxText> + </S.CheckBoxLabel> + ))} + </S.CheckBoxRow> + </S.CheckBoxContainer> + <Button>적용하기</Button> + </BottomSheet> + </S.FilterBottomSheetWrapper> + ); +}; + +export default FilterBottomSheet; diff --git a/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx index 981aeba8..0248b61c 100644 --- a/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx +++ b/src/pages/ticketholderlist/components/MenuBottomSheet/MenuBottomsheet.tsx @@ -18,31 +18,10 @@ const MenuBottomsheet = ({ handleStatus, ...rest }: MenuBottomSheetProps) => { - const childrenArray = Children.toArray(children); - - const contextChildren = childrenArray.filter( - (child) => isValidElement(child) && child.type !== OuterLayout - ); - - const remainingChildren = childrenArray.filter( - (child) => !isValidElement(child) || child.type === OuterLayout - ); - const handleWrapperClick = () => { onClickOutside(); }; - useEffect(() => { - if (isOpen) { - document.body.style.overflow = "hidden"; - } else { - document.body.style.overflow = "auto"; - } - return () => { - document.body.style.overflow = "auto"; - }; - }, [isOpen]); - return ( <S.MenuBottomSheetWrapper $isOpen={isOpen} onClick={handleWrapperClick}> <BottomSheet isOpen={isOpen} paddingTop="2.4rem"> diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index fff82547..065536e8 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -1,12 +1,16 @@ import React from "react"; import * as S from "./SearchBar.styled"; -const SearchBar = () => { +interface SearchBarProps { + handleFilter: () => void; +} + +const SearchBar = ({ handleFilter }: SearchBarProps) => { return ( <S.SearchBarWrapper> <S.SearchBar type="text" placeholder="예매자를 검색해보세요."></S.SearchBar> {/* TODO: 상태 DEFAULT일 때만 필터 버튼 노출 */} - <S.FilterBtn /> + <S.FilterBtn onClick={handleFilter} /> </S.SearchBarWrapper> ); }; diff --git a/src/pages/ticketholderlist/components/title/Title.tsx b/src/pages/ticketholderlist/components/title/Title.tsx index 8ce5e12c..0afb8082 100644 --- a/src/pages/ticketholderlist/components/title/Title.tsx +++ b/src/pages/ticketholderlist/components/title/Title.tsx @@ -14,6 +14,7 @@ const Title = ({ title, teamName, totalSolidCount, totalCount }: BookingInfoProp <S.PerformanceTitleWrapper> <S.PerformanceTitle>{title}</S.PerformanceTitle> <S.TicketCountWrapper> + {/* TODO : 필터링 받아올 때마다 값 다르게 설정 */} <S.PurchaseTicketCount>{totalSolidCount}</S.PurchaseTicketCount> <S.TotalTicketCount>/{totalCount}매</S.TotalTicketCount> </S.TicketCountWrapper> diff --git a/src/pages/ticketholderlist/types/bookingListType.ts b/src/pages/ticketholderlist/types/bookingListType.ts new file mode 100644 index 00000000..c6de4ab1 --- /dev/null +++ b/src/pages/ticketholderlist/types/bookingListType.ts @@ -0,0 +1,13 @@ +export interface BookingListProps { + bookingId: number; + bookerName: string; + bookerPhoneNumber: string; + scheduleId: number; + purchaseTicketCount: number; + createdAt: string; + bookingStatus: string; + scheduleNumber: string; + bankName: string; + accountNumber: string; + accountHolder: string; +} From 86749a69bf1055415e6f0fb142643f3ee1482d55 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 25 Nov 2024 03:06:55 +0900 Subject: [PATCH 09/49] =?UTF-8?q?feat:=20=EA=B8=B0=EB=B3=B8=20=EC=83=81?= =?UTF-8?q?=ED=83=9C=EC=9D=BC=20=EB=95=8C=EB=A7=8C=20=ED=95=84=ED=84=B0=20?= =?UTF-8?q?=EB=B2=84=ED=8A=BC=20=ED=99=9C=EC=84=B1=ED=99=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ticketholderlist/TicketHolderList.tsx | 2 +- .../ticketholderlist/components/searchBar/SearchBar.tsx | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 91b10472..8f678277 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -226,7 +226,7 @@ const TicketHolderList = () => { totalCount={data?.totalPerformanceTicketCount} /> <Spacing marginBottom={"2.6"} /> - <SearchBar handleFilter={handleFilter} /> + <SearchBar handleFilter={handleFilter} status={status} /> <Spacing marginBottom={"1.6"} /> <S.FooterButtonWrapper> <Button onClick={handleButtonClick}>{buttonText}</Button> diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index 065536e8..9facb26a 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -2,15 +2,16 @@ import React from "react"; import * as S from "./SearchBar.styled"; interface SearchBarProps { + status: string; handleFilter: () => void; } -const SearchBar = ({ handleFilter }: SearchBarProps) => { +const SearchBar = ({ handleFilter, status }: SearchBarProps) => { return ( <S.SearchBarWrapper> <S.SearchBar type="text" placeholder="예매자를 검색해보세요."></S.SearchBar> {/* TODO: 상태 DEFAULT일 때만 필터 버튼 노출 */} - <S.FilterBtn onClick={handleFilter} /> + {status === "DEFAULT" && <S.FilterBtn onClick={handleFilter} />} </S.SearchBarWrapper> ); }; From dd98589b3b22a19994fb67597296adf39b596ca3 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 25 Nov 2024 04:12:51 +0900 Subject: [PATCH 10/49] =?UTF-8?q?feat:=20=ED=95=84=ED=84=B0=20=EB=B0=94?= =?UTF-8?q?=ED=85=80=20=EC=8B=9C=ED=8A=B8=20=ED=8D=BC=EB=B8=94=EB=A6=AC?= =?UTF-8?q?=EC=8B=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ticketholderlist/TicketHolderList.tsx | 6 +- .../FilterBottomSheet.styled.ts | 13 +++- .../FilterBottomSheet/FilterBottomSheet.tsx | 78 +++++++++++++++++-- .../components/searchBar/SearchBar.tsx | 1 - 4 files changed, 86 insertions(+), 12 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 8f678277..86a58c5a 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -236,7 +236,11 @@ const TicketHolderList = () => { onClickOutside={closeBottomSheet} handleStatus={handleStatus} /> - <FilterBottomSheet isOpen={openFilter} onClickOutside={handleFilter} /> + <FilterBottomSheet + isOpen={openFilter} + totalScheduleCount={data.totalScheduleCount} + onClickOutside={handleFilter} + /> </S.TicketHolderListWrpper> </> )} diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts index 67a916b2..e34530e7 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts @@ -47,11 +47,20 @@ export const RefreshIcon = styled(IcRefresh)` height: 2.1rem; `; +export const BoxDivider = styled.div` + display: flex; + width: 32.7rem; + margin: 2rem 0; + + color: ${({ theme }) => theme.colors.gray_700}; + + border-top: 0.1rem solid; +`; + export const CheckBoxContainer = styled.section` display: flex; flex-direction: column; gap: 1.2rem; - margin-bottom: 3.2rem; `; export const CheckBoxRow = styled.section` @@ -83,5 +92,5 @@ export const UnSelectIcon = styled(IconCheckboxUnselectedOn)` export const CheckBoxText = styled.div` color: ${({ theme }) => theme.colors.gray_200}; - ${({ theme }) => theme.fonts["body1-normal-semi"]}; + ${({ theme }) => theme.fonts["body1-normal-medi"]}; `; diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx index 26044b50..846b1863 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -1,38 +1,99 @@ import React, { useState, ReactNode } from "react"; import * as S from "./FilterBottomSheet.styled"; -import { BottomSheet, Button } from "@components/commons"; -import { BoxDivider } from "@components/commons/bottomSheet/viewBottomSheet/ViewBottomSheet.styled"; +import { BottomSheet, Button, Spacing } from "@components/commons"; interface FilterBottomSheetProps { isOpen: boolean; + totalScheduleCount: number; children?: ReactNode; onClickOutside?: () => void; } const bookingStatusList = ["미입금", "입금 완료", "환불 요청", "취소 완료"]; -const FilterBottomSheet = ({ isOpen, onClickOutside, children }: FilterBottomSheetProps) => { +const FilterBottomSheet = ({ + isOpen, + onClickOutside, + totalScheduleCount, + children, +}: FilterBottomSheetProps) => { const [checkedStatusList, setCheckedStatusList] = useState<string[]>([]); + const [checkedScheduleList, setCheckedScheduleList] = useState<number[]>([]); const handleWrapperClick = () => { onClickOutside(); }; - const handleCheck = (status: string) => { + const splitArray = (arrayLength: number): number[][] => { + const array = Array.from({ length: arrayLength }, (_, idx) => idx + 1); + const result: number[][] = []; + + for (let i = 0; i < array.length; i += 2) { + result.push(array.slice(i, i + 2)); + } + + return result; + }; + + const scheduleArray = splitArray(totalScheduleCount); + + // 선택된 회차 확인 + const handleScheduleCheck = (schedule: number) => { + setCheckedScheduleList((prev) => + prev.includes(schedule) ? prev.filter((item) => item !== schedule) : [...prev, schedule] + ); + }; + + // 선택된 상태 확인 + const handleStatusCheck = (status: string) => { setCheckedStatusList((prev) => prev.includes(status) ? prev.filter((item) => item !== status) : [...prev, status] ); }; + const handleCilckBtn = () => { + onClickOutside(); + }; + + const handleClickRefresh = () => { + setCheckedScheduleList([]); + setCheckedStatusList([]); + }; + return ( <S.FilterBottomSheetWrapper $isOpen={isOpen} onClick={handleWrapperClick}> <BottomSheet isOpen={isOpen}> <S.TitleWrapper> 회차 - <S.RefreshBtn> + <S.RefreshBtn onClick={handleClickRefresh}> <S.RefreshIcon /> </S.RefreshBtn> </S.TitleWrapper> + + <S.CheckBoxContainer> + {scheduleArray.map((row, rowIndex) => ( + <S.CheckBoxRow key={rowIndex}> + {row.map((scheduleNumber) => ( + <S.CheckBoxLabel key={scheduleNumber}> + <S.CheckBox + type="checkbox" + checked={checkedScheduleList.includes(scheduleNumber)} + onChange={() => handleScheduleCheck(scheduleNumber)} + /> + {checkedScheduleList.includes(scheduleNumber) ? ( + <S.SelectIcon /> + ) : ( + <S.UnSelectIcon /> + )} + <S.CheckBoxText>{scheduleNumber}회차</S.CheckBoxText> + </S.CheckBoxLabel> + ))} + </S.CheckBoxRow> + ))} + </S.CheckBoxContainer> + + <S.BoxDivider /> + <S.TitleWrapper>입금 상태</S.TitleWrapper> <S.CheckBoxContainer> <S.CheckBoxRow> @@ -41,7 +102,7 @@ const FilterBottomSheet = ({ isOpen, onClickOutside, children }: FilterBottomShe <S.CheckBox type="checkbox" checked={checkedStatusList.includes(status)} - onChange={() => handleCheck(status)} + onChange={() => handleStatusCheck(status)} /> {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} <S.CheckBoxText>{status}</S.CheckBoxText> @@ -54,7 +115,7 @@ const FilterBottomSheet = ({ isOpen, onClickOutside, children }: FilterBottomShe <S.CheckBox type="checkbox" checked={checkedStatusList.includes(status)} - onChange={() => handleCheck(status)} + onChange={() => handleStatusCheck(status)} /> {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} <S.CheckBoxText>{status}</S.CheckBoxText> @@ -62,7 +123,8 @@ const FilterBottomSheet = ({ isOpen, onClickOutside, children }: FilterBottomShe ))} </S.CheckBoxRow> </S.CheckBoxContainer> - <Button>적용하기</Button> + <Spacing marginBottom="3.2" /> + <Button onClick={handleCilckBtn}>적용하기</Button> </BottomSheet> </S.FilterBottomSheetWrapper> ); diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index 9facb26a..f908921b 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -10,7 +10,6 @@ const SearchBar = ({ handleFilter, status }: SearchBarProps) => { return ( <S.SearchBarWrapper> <S.SearchBar type="text" placeholder="예매자를 검색해보세요."></S.SearchBar> - {/* TODO: 상태 DEFAULT일 때만 필터 버튼 노출 */} {status === "DEFAULT" && <S.FilterBtn onClick={handleFilter} />} </S.SearchBarWrapper> ); From c38204e1bf063dd5d5b0f15cc54953d02fd82d6f Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 26 Nov 2024 04:23:22 +0900 Subject: [PATCH 11/49] =?UTF-8?q?feat:=20ManageCard=20=ED=95=A9=EC=84=B1?= =?UTF-8?q?=20=EC=BB=B4=ED=8F=AC=EB=84=8C=ED=8A=B8=20=EC=99=84=EC=84=B1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/svgs/btn_filter.svg | 5 + src/assets/svgs/BtnFilter.tsx | 23 ++++ src/assets/svgs/index.ts | 66 ---------- src/assets/svgs/index.tsx | 1 + .../TicketHolderList.styled.ts | 26 +++- .../ticketholderlist/TicketHolderList.tsx | 116 ++++++++++++++++-- .../magageCard/ManageAccount.styled.ts | 28 +++++ .../components/magageCard/ManageAccount.tsx | 21 ++++ .../magageCard/ManageCardContainer.styled.ts | 68 ++++++++++ .../magageCard/ManageCardContainer.tsx | 38 ++++++ .../magageCard/ManageCardMain.styled.ts | 7 ++ .../components/magageCard/ManageCardMain.tsx | 12 ++ .../magageCard/ManageCheckBox.styled.ts | 22 ++++ .../components/magageCard/ManageCheckBox.tsx | 15 +++ .../components/magageCard/index.ts | 10 ++ 15 files changed, 377 insertions(+), 81 deletions(-) create mode 100644 public/svgs/btn_filter.svg create mode 100644 src/assets/svgs/BtnFilter.tsx delete mode 100644 src/assets/svgs/index.ts create mode 100644 src/pages/ticketholderlist/components/magageCard/ManageAccount.styled.ts create mode 100644 src/pages/ticketholderlist/components/magageCard/ManageAccount.tsx create mode 100644 src/pages/ticketholderlist/components/magageCard/ManageCardContainer.styled.ts create mode 100644 src/pages/ticketholderlist/components/magageCard/ManageCardContainer.tsx create mode 100644 src/pages/ticketholderlist/components/magageCard/ManageCardMain.styled.ts create mode 100644 src/pages/ticketholderlist/components/magageCard/ManageCardMain.tsx create mode 100644 src/pages/ticketholderlist/components/magageCard/ManageCheckBox.styled.ts create mode 100644 src/pages/ticketholderlist/components/magageCard/ManageCheckBox.tsx create mode 100644 src/pages/ticketholderlist/components/magageCard/index.ts diff --git a/public/svgs/btn_filter.svg b/public/svgs/btn_filter.svg new file mode 100644 index 00000000..abb22ac6 --- /dev/null +++ b/public/svgs/btn_filter.svg @@ -0,0 +1,5 @@ +<svg width="48" height="48" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M48 24C48 37.2548 37.2548 48 24 48C10.7452 48 0 37.2548 0 24C0 10.7452 10.7452 0 24 0C37.2548 0 48 10.7452 48 24Z" fill="#2A2A2A"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M24 47C36.7025 47 47 36.7025 47 24C47 11.2975 36.7025 1 24 1C11.2975 1 1 11.2975 1 24C1 36.7025 11.2975 47 24 47ZM24 48C37.2548 48 48 37.2548 48 24C48 10.7452 37.2548 0 24 0C10.7452 0 0 10.7452 0 24C0 37.2548 10.7452 48 24 48Z" fill="#3E3E3E"/> +<path fill-rule="evenodd" clip-rule="evenodd" d="M26.1422 18.1082C26.6917 17.5587 27.4369 17.25 28.214 17.25C28.5988 17.25 28.9798 17.3258 29.3353 17.473C29.6907 17.6203 30.0137 17.8361 30.2858 18.1082C30.5579 18.3803 30.7737 18.7033 30.921 19.0587C30.9711 19.1798 31.013 19.3039 31.0464 19.43H33.5C33.9142 19.43 34.25 19.7658 34.25 20.18C34.25 20.5942 33.9142 20.93 33.5 20.93H31.0464C31.013 21.0561 30.9711 21.1802 30.921 21.3013C30.7737 21.6567 30.5579 21.9797 30.2858 22.2518C30.0137 22.5239 29.6907 22.7397 29.3353 22.887C28.9798 23.0342 28.5988 23.11 28.214 23.11C27.4369 23.11 26.6917 22.8013 26.1422 22.2518C25.7733 21.8829 25.5129 21.4258 25.3816 20.93H15C14.5858 20.93 14.25 20.5942 14.25 20.18C14.25 19.7658 14.5858 19.43 15 19.43H25.3816C25.5129 18.9342 25.7733 18.4771 26.1422 18.1082ZM28.214 18.75C27.8347 18.75 27.471 18.9007 27.2028 19.1688C26.9347 19.437 26.784 19.8007 26.784 20.18C26.784 20.5593 26.9347 20.923 27.2028 21.1912C27.471 21.4593 27.8347 21.61 28.214 21.61C28.4018 21.61 28.5877 21.573 28.7612 21.5011C28.9347 21.4293 29.0924 21.3239 29.2252 21.1912C29.358 21.0584 29.4633 20.9007 29.5351 20.7272C29.607 20.5537 29.644 20.3678 29.644 20.18C29.644 19.9922 29.607 19.8063 29.5351 19.6328C29.4633 19.4593 29.358 19.3016 29.2252 19.1688C29.0924 19.036 28.9347 18.9307 28.7612 18.8589C28.5877 18.787 28.4018 18.75 28.214 18.75ZM16.8922 24.7152C17.4417 24.1657 18.1869 23.857 18.964 23.857C19.7411 23.857 20.4863 24.1657 21.0358 24.7152C21.4047 25.0841 21.6651 25.5412 21.7964 26.037H33.5C33.9142 26.037 34.25 26.3728 34.25 26.787C34.25 27.2012 33.9142 27.537 33.5 27.537H21.7964C21.6651 28.0328 21.4047 28.4899 21.0358 28.8588C20.4863 29.4083 19.7411 29.717 18.964 29.717C18.1869 29.717 17.4417 29.4083 16.8922 28.8588C16.5233 28.4899 16.2629 28.0328 16.1316 27.537H15C14.5858 27.537 14.25 27.2012 14.25 26.787C14.25 26.3728 14.5858 26.037 15 26.037H16.1316C16.2629 25.5412 16.5233 25.0841 16.8922 24.7152ZM18.964 25.357C18.5847 25.357 18.221 25.5077 17.9528 25.7758C17.6847 26.044 17.534 26.4077 17.534 26.787C17.534 27.1663 17.6847 27.53 17.9528 27.7982C18.221 28.0663 18.5847 28.217 18.964 28.217C19.3433 28.217 19.707 28.0663 19.9752 27.7982C20.2433 27.53 20.394 27.1663 20.394 26.787C20.394 26.4077 20.2433 26.044 19.9752 25.7758C19.707 25.5077 19.3433 25.357 18.964 25.357Z" fill="#F4F4F4"/> +</svg> diff --git a/src/assets/svgs/BtnFilter.tsx b/src/assets/svgs/BtnFilter.tsx new file mode 100644 index 00000000..aa0cc980 --- /dev/null +++ b/src/assets/svgs/BtnFilter.tsx @@ -0,0 +1,23 @@ +import * as React from "react"; +import type { SVGProps } from "react"; +const SvgBtnFilter = (props: SVGProps<SVGSVGElement>) => ( + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 48 48" {...props}> + <path + fill="#2A2A2A" + d="M48 24c0 13.255-10.745 24-24 24S0 37.255 0 24 10.745 0 24 0s24 10.745 24 24" + /> + <path + fill="#3E3E3E" + fillRule="evenodd" + d="M24 47c12.703 0 23-10.297 23-23S36.703 1 24 1 1 11.298 1 24s10.298 23 23 23m0 1c13.255 0 24-10.745 24-24S37.255 0 24 0 0 10.745 0 24s10.745 24 24 24" + clipRule="evenodd" + /> + <path + fill="#F4F4F4" + fillRule="evenodd" + d="M26.142 18.108a2.93 2.93 0 0 1 4.904 1.322H33.5a.75.75 0 0 1 0 1.5h-2.454a2.94 2.94 0 0 1-.76 1.322 2.932 2.932 0 0 1-4.904-1.322H15a.75.75 0 0 1 0-1.5h10.382a2.93 2.93 0 0 1 .76-1.322m2.072.642a1.43 1.43 0 1 0 0 2.86 1.43 1.43 0 0 0 0-2.86m-11.322 5.965a2.93 2.93 0 0 1 4.904 1.322H33.5a.75.75 0 0 1 0 1.5H21.796a2.93 2.93 0 0 1-5.664 0H15a.75.75 0 0 1 0-1.5h1.132a2.93 2.93 0 0 1 .76-1.322m2.072.642a1.43 1.43 0 1 0 0 2.86 1.43 1.43 0 0 0 0-2.86" + clipRule="evenodd" + /> + </svg> +); +export default SvgBtnFilter; diff --git a/src/assets/svgs/index.ts b/src/assets/svgs/index.ts deleted file mode 100644 index 6b73afb9..00000000 --- a/src/assets/svgs/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -export { default as BannerBasic } from "./BannerBasic"; -export { default as BtnFloating } from "./BtnFloating"; -export { default as BtnModalDelete } from "./BtnModalDelete"; -export { default as ButtonDelete24 } from "./ButtonDelete24"; -export { default as CarouselPartInactive } from "./CarouselPartInactive"; -export { default as Empty } from "./Empty"; -export { default as IcomCopy } from "./IcomCopy"; -export { default as IconArrowLeft } from "./IconArrowLeft"; -export { default as IconArrowRight } from "./IconArrowRight"; -export { default as IconArrowDown } from "./IconArrowDown"; -export { default as IconArrowDown } from "./IconArrowDown"; -export { default as IconArrowUp } from "./IconArrowUp"; -export { default as IconBnk } from "./IconBnk"; -export { default as IconCalendar } from "./IconCalendar"; -export { default as IconCamera } from "./IconCamera"; -export { default as IconCheckboxDisabledOn } from "./IconCheckboxDisabledOn"; -export { default as IconCheckboxSelectedOn } from "./IconCheckboxSelectedOn"; -export { default as IconCheckboxUnselectedOn } from "./IconCheckboxUnselectedOn"; -export { default as IconChecked } from "./IconChecked"; -export { default as IconChevronBack } from "./IconChevronBack"; -export { default as IconEmpty } from "./IconEmpty"; -export { default as IconEyeOff } from "./IconEyeOff"; -export { default as IconEyeOn } from "./IconEyeOn"; -export { default as IconFooterLogo } from "./IconFooterLogo"; -export { default as IconHanna } from "./IconHanna"; -export { default as IconIbk } from "./IconIbk"; -export { default as IconIm } from "./IconIm"; -export { default as IconImg } from "./IconImg"; -export { default as IconKabank } from "./IconKabank"; -export { default as IconKb } from "./IconKb"; -export { default as IconLargeBand } from "./IconLargeBand"; -export { default as IconLargeDance } from "./IconLargeDance"; -export { default as IconLargeEtc } from "./IconLargeEtc"; -export { default as IconLargeMusical } from "./IconLargeMusical"; -export { default as IconLogo } from "./IconLogo"; -export { default as IconMinus } from "./IconMinus"; -export { default as IconNonghyup } from "./IconNonghyup"; -export { default as IconPhotoDelete } from "./IconPhotoDelete"; -export { default as IconPlus } from "./IconPlus"; -export { default as IconProfile } from "./IconProfile"; -export { default as IconRoleAdd } from "./IconRoleAdd"; -export { default as IconSaemauel } from "./IconSaemauel"; -export { default as IconSc } from "./IconSc"; -export { default as IconShinhan } from "./IconShinhan"; -export { default as IconShinhyup } from "./IconShinhyup"; -export { default as IconSmallBand } from "./IconSmallBand"; -export { default as IconSmallDance } from "./IconSmallDance"; -export { default as IconSmallEtc } from "./IconSmallEtc"; -export { default as IconSmallMusical } from "./IconSmallMusical"; -export { default as IconSoohyup } from "./IconSoohyup"; -export { default as IconTextfiedlDelete } from "./IconTextfiedlDelete"; -export { default as IconTime } from "./IconTime"; -export { default as IconToggleOff } from "./IconToggleOff"; -export { default as IconToggleOn } from "./IconToggleOn"; -export { default as IconToss } from "./IconToss"; -export { default as IconWoochaegook } from "./IconWoochaegook"; -export { default as IconWoori } from "./IconWoori"; -export { default as IconXButton } from "./IconXButton"; -export { default as IcDelete } from "./IcDelete"; -export { default as IcHamburgar } from "./IcHamburgar"; -export { default as IcOutlinePlace } from "./IcOutlinePlace"; -export { default as IcRefresh } from "./IcRefresh"; -export { default as NotFoundAsset } from "./NotFoundAsset"; -export { default as Subtract } from "./Subtract"; -export { default as Switch } from "./Switch"; -export { default as Union } from "./Union"; diff --git a/src/assets/svgs/index.tsx b/src/assets/svgs/index.tsx index a1390878..61cf89c3 100644 --- a/src/assets/svgs/index.tsx +++ b/src/assets/svgs/index.tsx @@ -1,4 +1,5 @@ export { default as BannerBasic } from "./BannerBasic"; +export { default as BtnFilter } from "./BtnFilter"; export { default as BtnFloating } from "./BtnFloating"; export { default as BtnModalDelete } from "./BtnModalDelete"; export { default as ButtonDelete24 } from "./ButtonDelete24"; diff --git a/src/pages/ticketholderlist/TicketHolderList.styled.ts b/src/pages/ticketholderlist/TicketHolderList.styled.ts index dbd1c057..8478a76d 100644 --- a/src/pages/ticketholderlist/TicketHolderList.styled.ts +++ b/src/pages/ticketholderlist/TicketHolderList.styled.ts @@ -4,13 +4,35 @@ export const TicketHolderListWrpper = styled.section` display: flex; flex-direction: column; align-items: center; - padding: 0.8rem 2.4rem 2.6rem; + padding: 0 2.4rem; +`; + +export const TitleSticky = styled.section` + position: sticky; + top: 5.6rem; + + background-color: ${({ theme }) => theme.colors.gray_900}; +`; + +export const ManageCardList = styled.section` + display: flex; + flex-direction: column; + gap: 1.2rem; +`; + +export const ManageCardContainer = styled.section` + display: flex; + align-items: center; + width: 100%; `; export const FooterButtonWrapper = styled.div` - position: fixed; + position: sticky; bottom: 0; z-index: 1; + display: flex; min-height: 10.4rem; padding-top: 2.4rem; + + background-color: ${({ theme }) => theme.colors.gray_900}; `; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 86a58c5a..83b3bfea 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -13,13 +13,15 @@ import Title from "@pages/ticketholderlist/components/title/Title"; import SearchBar from "./components/searchBar/SearchBar"; import MenuBottomsheet from "./components/MenuBottomSheet/MenuBottomsheet"; import FilterBottomSheet from "./components/FilterBottomSheet/FilterBottomSheet"; -import { BookingListProps } from "./types/BookingListType"; +import { BookingListProps } from "@pages/ticketholderlist/types/bookingListType"; +import { ManageCard } from "./components/magageCard"; +import { getBankNameKr } from "@utils/getBankName"; const data = { performanceTitle: "비트밴드 정기공연", performanceTeamName: "비트밴드", isBooking: true, - totalScheduleCount: 2, + totalScheduleCount: 3, totalPerformanceTicketCount: 100, totalPerformanceSoldTicketCount: 50, bookingList: [ @@ -50,10 +52,64 @@ const data = { accountNumber: "", accountHolder: "", }, + { + bookingId: 1, + bookerName: "황혜린", + bookerPhoneNumber: "010-1234-5678", + scheduleId: 2, + purchaseTicketCount: 3, + createdAt: "2024-07-07T12:34:56.789Z", + bookingStatus: "REFUND_REQUIRED", + scheduleNumber: "SECOND", + bankName: "NH_NONGHYUP", + accountNumber: "123-12-1234-123", + accountHolder: "전희주", + }, + { + bookingId: 2, + bookerName: "이동훈", + bookerPhoneNumber: "010-1234-0000", + scheduleId: 1, + purchaseTicketCount: 2, + createdAt: "2024-07-08T12:34:56.789Z", + bookingStatus: "CHECKING_PAYMENT", + scheduleNumber: "FIRST", + // 예매 확정된 상태이므로 환불계좌 정보 없음 + bankName: "", + accountNumber: "", + accountHolder: "", + }, + { + bookingId: 1, + bookerName: "황혜린", + bookerPhoneNumber: "010-1234-5678", + scheduleId: 2, + purchaseTicketCount: 3, + createdAt: "2024-07-07T12:34:56.789Z", + bookingStatus: "REFUND_REQUIRED", + scheduleNumber: "SECOND", + bankName: "NH_NONGHYUP", + accountNumber: "123-12-1234-123", + accountHolder: "전희주", + }, + { + bookingId: 2, + bookerName: "이동훈", + bookerPhoneNumber: "010-1234-0000", + scheduleId: 1, + purchaseTicketCount: 2, + createdAt: "2024-07-08T12:34:56.789Z", + bookingStatus: "BOOKING_CANCELLED", + scheduleNumber: "FIRST", + // 예매 확정된 상태이므로 환불계좌 정보 없음 + bankName: "", + accountNumber: "", + accountHolder: "", + }, ], }; -type PaymentType = +export type PaymentType = | "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" @@ -70,7 +126,7 @@ interface CSVDataType { // 관리자 페이지에서만 사용해서 공통 type으로 안 뺌 // TODO : TicketHolderList 내 type으로 빼기 -const convertingBookingStatus = (_bookingStatus: PaymentType): string => { +export const convertingBookingStatus = (_bookingStatus: PaymentType): string => { switch (_bookingStatus) { case "CHECKING_PAYMENT": return "미입금"; @@ -219,15 +275,49 @@ const TicketHolderList = () => { ) : ( <> <S.TicketHolderListWrpper> - <Title - title={data?.performanceTitle} - teamName={data?.performanceTeamName} - totalSolidCount={data?.totalPerformanceSoldTicketCount} - totalCount={data?.totalPerformanceTicketCount} - /> - <Spacing marginBottom={"2.6"} /> - <SearchBar handleFilter={handleFilter} status={status} /> - <Spacing marginBottom={"1.6"} /> + <S.TitleSticky> + <Title + title={data?.performanceTitle} + teamName={data?.performanceTeamName} + totalSolidCount={data?.totalPerformanceSoldTicketCount} + totalCount={data?.totalPerformanceTicketCount} + /> + <Spacing marginBottom={"2.6"} /> + <SearchBar handleFilter={handleFilter} status={status} /> + <Spacing marginBottom={"1.6"} /> + </S.TitleSticky> + + <S.ManageCardList> + {paymentData.map((item, idx) => { + const date = item.createdAt.split("T")[0]; + const formattedDate = `${date.replace(/-/g, ". ")}`; + const bookingStatus = convertingBookingStatus(item.bookingStatus as PaymentType); + + return ( + <ManageCard key={idx}> + <S.ManageCardContainer> + {status !== "DEFAULT" && <ManageCard.ManageCheckBox />} + <ManageCard.ManageCardContainer + name={item.bookerName} + phoneNumber={item.bookerPhoneNumber} + ticketCount={item.purchaseTicketCount} + scheduleId={item.scheduleId} + date={formattedDate} + status={bookingStatus} + /> + </S.ManageCardContainer> + {status === "REFUND" && ( + <ManageCard.ManageAccount + bankName={getBankNameKr(item.bankName)} + accountNumber={item.accountNumber} + accountHolder={item.accountHolder} + /> + )} + </ManageCard> + ); + })} + </S.ManageCardList> + <S.FooterButtonWrapper> <Button onClick={handleButtonClick}>{buttonText}</Button> </S.FooterButtonWrapper> diff --git a/src/pages/ticketholderlist/components/magageCard/ManageAccount.styled.ts b/src/pages/ticketholderlist/components/magageCard/ManageAccount.styled.ts new file mode 100644 index 00000000..46b7939e --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/ManageAccount.styled.ts @@ -0,0 +1,28 @@ +import styled from "styled-components"; +import { IcomCopy } from "@assets/svgs"; + +export const ManageAccountWrapper = styled.button` + display: flex; + align-items: center; + justify-content: space-between; + width: 29.9rem; + height: 4.8rem; + margin: 0.8rem 0 0.4rem 2.8rem; + padding: 0.8rem 1.6rem; + + color: ${({ theme }) => theme.colors.gray_300}; + ${({ theme }) => theme.fonts["caption1-medi"]}; + + border: 0.1rem solid; + border-color: ${({ theme }) => theme.colors.gray_700}; + border-radius: 0.6rem; +`; + +export const CopyIcon = styled(IcomCopy)` + width: 2.4rem; + height: 2.4rem; + + path { + fill: ${({ theme }) => theme.colors.gray_300}; + } +`; diff --git a/src/pages/ticketholderlist/components/magageCard/ManageAccount.tsx b/src/pages/ticketholderlist/components/magageCard/ManageAccount.tsx new file mode 100644 index 00000000..5cf2188e --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/ManageAccount.tsx @@ -0,0 +1,21 @@ +import * as S from "./ManageAccount.styled"; + +interface ManageAccountProps { + bankName: string; + accountNumber: string; + accountHolder: string; +} + +export default function ManageAccount({ + bankName, + accountNumber, + accountHolder, +}: ManageAccountProps) { + return ( + // TODO : 클릭 시 계좌번호 복사 기능 추가 + <S.ManageAccountWrapper> + {bankName} ({accountHolder}) {accountNumber} + <S.CopyIcon /> + </S.ManageAccountWrapper> + ); +} diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.styled.ts b/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.styled.ts new file mode 100644 index 00000000..dba6f43d --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.styled.ts @@ -0,0 +1,68 @@ +import styled, { css } from "styled-components"; + +export const ManageCardWrapper = styled.section` + display: flex; + width: 100%; + height: 10rem; +`; + +export const InfoBox = styled.section` + display: flex; + width: 100%; + height: 100%; + padding: 1.6rem; + + background-color: ${({ theme }) => theme.colors.gray_800}; + border-radius: 0.6rem; +`; + +export const StatusBox = styled.section<{ $status: string }>` + display: flex; + justify-content: center; + min-width: 7.5rem; + height: 100%; + margin-left: 0.2rem; + padding: 4.2rem 1.6rem; + + ${({ $status }) => { + switch ($status) { + case "미입금": + return css` + color: ${({ theme }) => theme.colors.pink_200}; + `; + case "입금 완료": + return css` + color: ${({ theme }) => theme.colors.gray_400}; + `; + case "취소 완료": + return css` + color: ${({ theme }) => theme.colors.gray_400}; + `; + case "환불 요청": + return css` + color: ${({ theme }) => theme.colors.red}; + `; + } + }} + + ${({ theme }) => theme.fonts["caption2-semi"]}; + + background-color: ${({ theme }) => theme.colors.gray_800}; + border-radius: 0.6rem; +`; + +export const TextContainer = styled.section` + display: flex; + flex-direction: column; + gap: 0.4rem; +`; + +export const InfoText = styled.div` + ${({ theme }) => theme.fonts["body2-normal-medi"]}; + color: ${({ theme }) => theme.colors.white}; +`; + +export const DateText = styled.div` + ${({ theme }) => theme.fonts["caption1-medi"]}; + color: ${({ theme }) => theme.colors.gray_400}; +`; diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.tsx b/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.tsx new file mode 100644 index 00000000..ce5fe7a4 --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.tsx @@ -0,0 +1,38 @@ +import { convertingBookingStatus } from "@pages/ticketholderlist/TicketHolderList"; +import * as S from "./ManageCardContainer.styled"; +import { PaymentType } from "@pages/ticketholderlist/TicketHolderList"; + +interface ManagerCardContainerProps { + name: string; + phoneNumber: string; + ticketCount: number; + scheduleId: number; + date: string; + status: string; +} + +export default function ManageCardContainer({ + name, + phoneNumber, + ticketCount, + scheduleId, + date, + status, +}: ManagerCardContainerProps) { + return ( + <S.ManageCardWrapper> + <S.InfoBox> + <S.TextContainer> + <S.InfoText> + {name} ({phoneNumber}) + </S.InfoText> + <S.InfoText> + {scheduleId}회차 / {ticketCount}매 + </S.InfoText> + <S.DateText>{date}</S.DateText> + </S.TextContainer> + </S.InfoBox> + <S.StatusBox $status={status}>{status}</S.StatusBox> + </S.ManageCardWrapper> + ); +} diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCardMain.styled.ts b/src/pages/ticketholderlist/components/magageCard/ManageCardMain.styled.ts new file mode 100644 index 00000000..31b94720 --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/ManageCardMain.styled.ts @@ -0,0 +1,7 @@ +import styled from "styled-components"; + +export const ManageCardMainWrapper = styled.section` + display: flex; + flex-direction: column; + width: 32.7rem; +`; diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCardMain.tsx b/src/pages/ticketholderlist/components/magageCard/ManageCardMain.tsx new file mode 100644 index 00000000..e7ffd834 --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/ManageCardMain.tsx @@ -0,0 +1,12 @@ +import React, { Children, ReactNode } from "react"; +import * as S from "./ManageCardMain.styled"; + +export interface ManageCardMainProps { + children: ReactNode; +} + +const ManageCardMain = ({ children }: ManageCardMainProps) => { + return <S.ManageCardMainWrapper>{children}</S.ManageCardMainWrapper>; +}; + +export default ManageCardMain; diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCheckBox.styled.ts b/src/pages/ticketholderlist/components/magageCard/ManageCheckBox.styled.ts new file mode 100644 index 00000000..6c065124 --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/ManageCheckBox.styled.ts @@ -0,0 +1,22 @@ +import styled from "styled-components"; +import { IcRefresh, IconCheckboxSelectedOn, IconCheckboxUnselectedOn } from "@assets/svgs"; + +export const CheckBoxWrapper = styled.section` + display: flex; +`; + +export const CheckBox = styled.input` + display: none; +`; + +export const SelectIcon = styled(IconCheckboxSelectedOn)` + width: 1.8rem; + height: 1.8rem; + margin-right: 1rem; +`; + +export const UnSelectIcon = styled(IconCheckboxUnselectedOn)` + width: 1.8rem; + height: 1.8rem; + margin-right: 1rem; +`; diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCheckBox.tsx b/src/pages/ticketholderlist/components/magageCard/ManageCheckBox.tsx new file mode 100644 index 00000000..b2e22e99 --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/ManageCheckBox.tsx @@ -0,0 +1,15 @@ +import * as S from "./ManageCheckBox.styled"; + +export default function ManageCheckBox({}) { + return ( + <S.CheckBoxWrapper> + <S.CheckBox + type="checkbox" + // checked={checkedStatusList.includes(status)} + // onChange={() => handleStatusCheck(status)} + /> + {/* {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} */} + <S.UnSelectIcon /> + </S.CheckBoxWrapper> + ); +} diff --git a/src/pages/ticketholderlist/components/magageCard/index.ts b/src/pages/ticketholderlist/components/magageCard/index.ts new file mode 100644 index 00000000..9785ca3e --- /dev/null +++ b/src/pages/ticketholderlist/components/magageCard/index.ts @@ -0,0 +1,10 @@ +import ManageCardMain from "./ManageCardMain"; +import ManageCardContainer from "./ManageCardContainer"; +import ManageCheckBox from "./ManageCheckBox"; +import ManageAccount from "./ManageAccount"; + +export const ManageCard = Object.assign(ManageCardMain, { + ManageCardContainer: ManageCardContainer, + ManageCheckBox: ManageCheckBox, + ManageAccount: ManageAccount, +}); From 06722a1c5402401f7289ab9f6e217a8cba7fd07d Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 26 Nov 2024 05:24:30 +0900 Subject: [PATCH 12/49] =?UTF-8?q?feat:=20chip=20=EC=83=9D=EC=84=B1=20?= =?UTF-8?q?=EB=B0=8F=20=EC=9E=90=EC=9E=98=ED=95=9C=20=EC=88=98=EC=A0=95?= =?UTF-8?q?=EC=82=AC=ED=95=AD=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/svgs/ic_delete.svg | 5 +- src/assets/svgs/IcDelete.tsx | 7 +- src/assets/svgs/index.ts | 66 +++++++++++++++++++ .../ticketholderlist/TicketHolderList.tsx | 4 +- .../FilterBottomSheet/FilterBottomSheet.tsx | 1 + .../ManageAccount.styled.ts | 0 .../ManageAccount.tsx | 0 .../ManageCardContainer.styled.ts | 23 ++++++- .../ManageCardContainer.tsx | 6 +- .../ManageCardMain.styled.ts | 0 .../ManageCardMain.tsx | 0 .../ManageCheckBox.styled.ts | 0 .../ManageCheckBox.tsx | 0 .../{magageCard => manageCard}/index.ts | 0 .../components/searchBar/SearchBar.styled.ts | 4 +- .../components/searchBar/SearchBar.tsx | 1 + .../selectedChips/SelectedChips.styled.ts | 40 +++++++++++ .../selectedChips/SelectedChips.tsx | 19 ++++++ .../components/title/Title.styled.ts | 12 +++- 19 files changed, 170 insertions(+), 18 deletions(-) create mode 100644 src/assets/svgs/index.ts rename src/pages/ticketholderlist/components/{magageCard => manageCard}/ManageAccount.styled.ts (100%) rename src/pages/ticketholderlist/components/{magageCard => manageCard}/ManageAccount.tsx (100%) rename src/pages/ticketholderlist/components/{magageCard => manageCard}/ManageCardContainer.styled.ts (73%) rename src/pages/ticketholderlist/components/{magageCard => manageCard}/ManageCardContainer.tsx (86%) rename src/pages/ticketholderlist/components/{magageCard => manageCard}/ManageCardMain.styled.ts (100%) rename src/pages/ticketholderlist/components/{magageCard => manageCard}/ManageCardMain.tsx (100%) rename src/pages/ticketholderlist/components/{magageCard => manageCard}/ManageCheckBox.styled.ts (100%) rename src/pages/ticketholderlist/components/{magageCard => manageCard}/ManageCheckBox.tsx (100%) rename src/pages/ticketholderlist/components/{magageCard => manageCard}/index.ts (100%) create mode 100644 src/pages/ticketholderlist/components/selectedChips/SelectedChips.styled.ts create mode 100644 src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx diff --git a/public/svgs/ic_delete.svg b/public/svgs/ic_delete.svg index 176caeb0..ba67c1cf 100644 --- a/public/svgs/ic_delete.svg +++ b/public/svgs/ic_delete.svg @@ -1,4 +1,3 @@ -<svg width="32" height="32" viewBox="0 0 32 32" fill="none" xmlns="http://www.w3.org/2000/svg"> -<circle cx="16" cy="16" r="11" fill="#3E3E3E"/> -<path d="M12 20L16 16L20 20M20 12L15.9992 16L12 12" stroke="#797979" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> +<svg width="16" height="16" viewBox="0 0 16 16" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M5 11L8 8L11 11M11 5L7.99943 8L5 5" stroke="#939393" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round"/> </svg> diff --git a/src/assets/svgs/IcDelete.tsx b/src/assets/svgs/IcDelete.tsx index 76f8668a..08e96642 100644 --- a/src/assets/svgs/IcDelete.tsx +++ b/src/assets/svgs/IcDelete.tsx @@ -1,14 +1,13 @@ import * as React from "react"; import type { SVGProps } from "react"; const SvgIcDelete = (props: SVGProps<SVGSVGElement>) => ( - <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 32 32" {...props}> - <circle cx={16} cy={16} r={11} fill="#3E3E3E" /> + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 16 16" {...props}> <path - stroke="#797979" + stroke="#939393" strokeLinecap="round" strokeLinejoin="round" strokeWidth={1.5} - d="m12 20 4-4 4 4m0-8-4 4-4-4" + d="m5 11 3-3 3 3m0-6L8 8 5 5" /> </svg> ); diff --git a/src/assets/svgs/index.ts b/src/assets/svgs/index.ts new file mode 100644 index 00000000..bd1bb637 --- /dev/null +++ b/src/assets/svgs/index.ts @@ -0,0 +1,66 @@ +export { default as BannerBasic } from "./BannerBasic"; +export { default as BtnFilter } from "./BtnFilter"; +export { default as BtnFloating } from "./BtnFloating"; +export { default as BtnModalDelete } from "./BtnModalDelete"; +export { default as ButtonDelete24 } from "./ButtonDelete24"; +export { default as CarouselPartInactive } from "./CarouselPartInactive"; +export { default as Empty } from "./Empty"; +export { default as IcomCopy } from "./IcomCopy"; +export { default as IconArrowLeft } from "./IconArrowLeft"; +export { default as IconArrowRight } from "./IconArrowRight"; +export { default as IconArrowDown } from "./IconArrowDown"; +export { default as IconArrowUp } from "./IconArrowUp"; +export { default as IconBnk } from "./IconBnk"; +export { default as IconCalendar } from "./IconCalendar"; +export { default as IconCamera } from "./IconCamera"; +export { default as IconCheckboxDisabledOn } from "./IconCheckboxDisabledOn"; +export { default as IconCheckboxSelectedOn } from "./IconCheckboxSelectedOn"; +export { default as IconCheckboxUnselectedOn } from "./IconCheckboxUnselectedOn"; +export { default as IconCheck } from "./IconCheck"; +export { default as IconChevronBack } from "./IconChevronBack"; +export { default as IconEmpty } from "./IconEmpty"; +export { default as IconEyeOff } from "./IconEyeOff"; +export { default as IconEyeOn } from "./IconEyeOn"; +export { default as IconFooterLogo } from "./IconFooterLogo"; +export { default as IconHanna } from "./IconHanna"; +export { default as IconIbk } from "./IconIbk"; +export { default as IconIm } from "./IconIm"; +export { default as IconImg } from "./IconImg"; +export { default as IconKabank } from "./IconKabank"; +export { default as IconKb } from "./IconKb"; +export { default as IconLargeBand } from "./IconLargeBand"; +export { default as IconLargeDance } from "./IconLargeDance"; +export { default as IconLargeEtc } from "./IconLargeEtc"; +export { default as IconLargeMusical } from "./IconLargeMusical"; +export { default as IconLogo } from "./IconLogo"; +export { default as IconMinus } from "./IconMinus"; +export { default as IconNonghyup } from "./IconNonghyup"; +export { default as IconPhotoDelete } from "./IconPhotoDelete"; +export { default as IconPlus } from "./IconPlus"; +export { default as IconProfile } from "./IconProfile"; +export { default as IconRoleAdd } from "./IconRoleAdd"; +export { default as IconSaemauel } from "./IconSaemauel"; +export { default as IconSc } from "./IconSc"; +export { default as IconShinhan } from "./IconShinhan"; +export { default as IconShinhyup } from "./IconShinhyup"; +export { default as IconSmallBand } from "./IconSmallBand"; +export { default as IconSmallDance } from "./IconSmallDance"; +export { default as IconSmallEtc } from "./IconSmallEtc"; +export { default as IconSmallMusical } from "./IconSmallMusical"; +export { default as IconSoohyup } from "./IconSoohyup"; +export { default as IconTextfiedlDelete } from "./IconTextfiedlDelete"; +export { default as IconTime } from "./IconTime"; +export { default as IconToggleOff } from "./IconToggleOff"; +export { default as IconToggleOn } from "./IconToggleOn"; +export { default as IconToss } from "./IconToss"; +export { default as IconWoochaegook } from "./IconWoochaegook"; +export { default as IconWoori } from "./IconWoori"; +export { default as IconXButton } from "./IconXButton"; +export { default as IcDelete } from "./IcDelete"; +export { default as IcHamburgar } from "./IcHamburgar"; +export { default as IcOutlinePlace } from "./IcOutlinePlace"; +export { default as IcRefresh } from "./IcRefresh"; +export { default as NotFoundAsset } from "./NotFoundAsset"; +export { default as Subtract } from "./Subtract"; +export { default as Switch } from "./Switch"; +export { default as Union } from "./Union"; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 83b3bfea..c9b7fbad 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -14,8 +14,9 @@ import SearchBar from "./components/searchBar/SearchBar"; import MenuBottomsheet from "./components/MenuBottomSheet/MenuBottomsheet"; import FilterBottomSheet from "./components/FilterBottomSheet/FilterBottomSheet"; import { BookingListProps } from "@pages/ticketholderlist/types/bookingListType"; -import { ManageCard } from "./components/magageCard"; +import { ManageCard } from "./components/manageCard"; import { getBankNameKr } from "@utils/getBankName"; +import SelectedChips from "./components/selectedChips/SelectedChips"; const data = { performanceTitle: "비트밴드 정기공연", @@ -284,6 +285,7 @@ const TicketHolderList = () => { /> <Spacing marginBottom={"2.6"} /> <SearchBar handleFilter={handleFilter} status={status} /> + <SelectedChips /> <Spacing marginBottom={"1.6"} /> </S.TitleSticky> diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx index 846b1863..9afccb77 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -124,6 +124,7 @@ const FilterBottomSheet = ({ </S.CheckBoxRow> </S.CheckBoxContainer> <Spacing marginBottom="3.2" /> + {/* TODO : 선택된 내역 없을 때 버튼 비활성화 하기 */} <Button onClick={handleCilckBtn}>적용하기</Button> </BottomSheet> </S.FilterBottomSheetWrapper> diff --git a/src/pages/ticketholderlist/components/magageCard/ManageAccount.styled.ts b/src/pages/ticketholderlist/components/manageCard/ManageAccount.styled.ts similarity index 100% rename from src/pages/ticketholderlist/components/magageCard/ManageAccount.styled.ts rename to src/pages/ticketholderlist/components/manageCard/ManageAccount.styled.ts diff --git a/src/pages/ticketholderlist/components/magageCard/ManageAccount.tsx b/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx similarity index 100% rename from src/pages/ticketholderlist/components/magageCard/ManageAccount.tsx rename to src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.styled.ts b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.styled.ts similarity index 73% rename from src/pages/ticketholderlist/components/magageCard/ManageCardContainer.styled.ts rename to src/pages/ticketholderlist/components/manageCard/ManageCardContainer.styled.ts index dba6f43d..abd1d468 100644 --- a/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.styled.ts +++ b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.styled.ts @@ -57,12 +57,29 @@ export const TextContainer = styled.section` gap: 0.4rem; `; -export const InfoText = styled.div` +export const InfoText = styled.div<{ $status: string }>` ${({ theme }) => theme.fonts["body2-normal-medi"]}; color: ${({ theme }) => theme.colors.white}; + + ${({ $status }) => { + if ($status === "취소 완료") { + return css` + color: ${({ theme }) => theme.colors.gray_400}; + text-decoration: line-through; + `; + } + }} `; -export const DateText = styled.div` +export const DateText = styled.div<{ $status: string }>` ${({ theme }) => theme.fonts["caption1-medi"]}; - color: ${({ theme }) => theme.colors.gray_400}; + color: ${({ theme }) => theme.colors.gray_500}; + + ${({ $status }) => { + if ($status === "취소 완료") { + return css` + color: ${({ theme }) => theme.colors.gray_600}; + `; + } + }} `; diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.tsx b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx similarity index 86% rename from src/pages/ticketholderlist/components/magageCard/ManageCardContainer.tsx rename to src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx index ce5fe7a4..04808cec 100644 --- a/src/pages/ticketholderlist/components/magageCard/ManageCardContainer.tsx +++ b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx @@ -23,13 +23,13 @@ export default function ManageCardContainer({ <S.ManageCardWrapper> <S.InfoBox> <S.TextContainer> - <S.InfoText> + <S.InfoText $status={status}> {name} ({phoneNumber}) </S.InfoText> - <S.InfoText> + <S.InfoText $status={status}> {scheduleId}회차 / {ticketCount}매 </S.InfoText> - <S.DateText>{date}</S.DateText> + <S.DateText $status={status}>{date}</S.DateText> </S.TextContainer> </S.InfoBox> <S.StatusBox $status={status}>{status}</S.StatusBox> diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCardMain.styled.ts b/src/pages/ticketholderlist/components/manageCard/ManageCardMain.styled.ts similarity index 100% rename from src/pages/ticketholderlist/components/magageCard/ManageCardMain.styled.ts rename to src/pages/ticketholderlist/components/manageCard/ManageCardMain.styled.ts diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCardMain.tsx b/src/pages/ticketholderlist/components/manageCard/ManageCardMain.tsx similarity index 100% rename from src/pages/ticketholderlist/components/magageCard/ManageCardMain.tsx rename to src/pages/ticketholderlist/components/manageCard/ManageCardMain.tsx diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCheckBox.styled.ts b/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.styled.ts similarity index 100% rename from src/pages/ticketholderlist/components/magageCard/ManageCheckBox.styled.ts rename to src/pages/ticketholderlist/components/manageCard/ManageCheckBox.styled.ts diff --git a/src/pages/ticketholderlist/components/magageCard/ManageCheckBox.tsx b/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.tsx similarity index 100% rename from src/pages/ticketholderlist/components/magageCard/ManageCheckBox.tsx rename to src/pages/ticketholderlist/components/manageCard/ManageCheckBox.tsx diff --git a/src/pages/ticketholderlist/components/magageCard/index.ts b/src/pages/ticketholderlist/components/manageCard/index.ts similarity index 100% rename from src/pages/ticketholderlist/components/magageCard/index.ts rename to src/pages/ticketholderlist/components/manageCard/index.ts diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts index 595e218f..4267d3e7 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts @@ -1,4 +1,5 @@ import styled from "styled-components"; +import { BtnFilter } from "@assets/svgs"; export const SearchBarWrapper = styled.section` display: flex; @@ -21,8 +22,7 @@ export const SearchBar = styled.input` border-radius: 4rem; `; -// 찌그러지는 거 수정하기 -export const FilterBtn = styled.button` +export const FilterBtn = styled(BtnFilter)` width: 4.8rem; height: 4.8rem; margin-left: 1.2rem; diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index f908921b..a3dab2eb 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -6,6 +6,7 @@ interface SearchBarProps { handleFilter: () => void; } +// TODO: 필터 적용되었을 때 아웃라인 색상 적용 -> 기능 붙일 때 같이 하기 const SearchBar = ({ handleFilter, status }: SearchBarProps) => { return ( <S.SearchBarWrapper> diff --git a/src/pages/ticketholderlist/components/selectedChips/SelectedChips.styled.ts b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.styled.ts new file mode 100644 index 00000000..e2ef1015 --- /dev/null +++ b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.styled.ts @@ -0,0 +1,40 @@ +import styled from "styled-components"; +import { IcDelete } from "@assets/svgs"; + +export const SelectedChipsWrapper = styled.section` + display: flex; + gap: 0.8rem; + width: 32.7rem; + overflow-x: scroll; + + scrollbar-width: none; + -ms-overflow-style: none; + + &::-webkit-scrollbar { + display: none; + } + white-space: nowrap; +`; + +export const Chip = styled.section` + display: flex; + gap: 0.2rem; + align-items: center; + justify-content: center; + width: auto; + margin-top: 1.6rem; + padding: 0.8rem 1.2rem; + + ${({ theme }) => theme.fonts["body2-normal-medi"]}; + color: ${({ theme }) => theme.colors.gray_200}; + + border: 0.1rem solid; + border-color: ${({ theme }) => theme.colors.gray_700}; + border-radius: 9.9rem; +`; + +// delete icon 확인하기 +export const DeleteIcon = styled(IcDelete)` + width: 1.6rem; + height: 1.6rem; +`; diff --git a/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx new file mode 100644 index 00000000..2bae6b80 --- /dev/null +++ b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx @@ -0,0 +1,19 @@ +import React from "react"; +import * as S from "./SelectedChips.styled"; + +const SelectedChips = () => { + // TODO: delteIcon에 삭제 기능 추가하기 + const handleClickDelete = () => {}; + + return ( + // TODO : 선택된 필터 props로 받아서 map 돌리기 + <S.SelectedChipsWrapper> + <S.Chip> + 1회차 + <S.DeleteIcon onClick={handleClickDelete} /> + </S.Chip> + </S.SelectedChipsWrapper> + ); +}; + +export default SelectedChips; diff --git a/src/pages/ticketholderlist/components/title/Title.styled.ts b/src/pages/ticketholderlist/components/title/Title.styled.ts index 053e31ce..4afe4882 100644 --- a/src/pages/ticketholderlist/components/title/Title.styled.ts +++ b/src/pages/ticketholderlist/components/title/Title.styled.ts @@ -6,8 +6,14 @@ export const TitleWrapper = styled.section` `; export const PerformanceTeamName = styled.div` + display: inline; + width: 32.7rem; + overflow: hidden; + ${({ theme }) => theme.fonts["caption1-semi"]}; color: ${({ theme }) => theme.colors.gray_400}; + white-space: nowrap; + text-overflow: ellipsis; `; export const PerformanceTitleWrapper = styled.section` @@ -16,13 +22,15 @@ export const PerformanceTitleWrapper = styled.section` width: 32.8rem; `; -// TODO : 말줄임표 작업 export const PerformanceTitle = styled.div` - display: flex; + display: inline; width: 25.8rem; + overflow: hidden; ${({ theme }) => theme.fonts.heading2}; color: ${({ theme }) => theme.colors.white}; + white-space: nowrap; + text-overflow: ellipsis; `; export const TicketCountWrapper = styled.section` From 3e6b27904d04a738dc015df4a3a72937d2c64d45 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 26 Nov 2024 06:02:56 +0900 Subject: [PATCH 13/49] =?UTF-8?q?chore:=20api=20schema=20=EC=97=85?= =?UTF-8?q?=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/typings/api/schema/index.ts | 884 +++++++++++--------------------- 1 file changed, 290 insertions(+), 594 deletions(-) diff --git a/src/typings/api/schema/index.ts b/src/typings/api/schema/index.ts index 07e96584..915a306e 100644 --- a/src/typings/api/schema/index.ts +++ b/src/typings/api/schema/index.ts @@ -239,6 +239,10 @@ export interface paths { path?: never; cookie?: never; }; + /** + * 티켓 구매 가능 여부 조회 API + * @description 티켓 구매 가능 여부를 확인하는 GET API입니다. + */ get: operations["getTicketAvailability"]; put?: never; post?: never; @@ -340,8 +344,8 @@ export interface paths { cookie?: never; }; /** - * 전체공연목록, 홍보목록 조회 API - * @description 홈화면에서 전체공연목록, 홍보목록을 조회하는 GET API입니다. + * 전체 공연 및 홍보 목록 조회 + * @description 홈 화면에서 전체 공연 목록 및 홍보 목록을 조회하는 GET API */ get: operations["getHomePerformanceList"]; put?: never; @@ -479,12 +483,17 @@ export interface components { totalScheduleCount?: number; bookingList?: components["schemas"]["TicketUpdateDetail"][]; }; - SuccessResponseVoid: { + SuccessResponse: { /** Format: int32 */ status?: number; message?: string; data?: Record<string, never>; }; + ErrorResponse: { + /** Format: int32 */ + status?: number; + message?: string; + }; CastModifyRequest: { /** Format: int64 */ castId?: number; @@ -540,74 +549,7 @@ export interface components { staffRole?: string; staffPhoto?: string; }; - CastModifyResponse: { - /** Format: int64 */ - castId?: number; - castName?: string; - castRole?: string; - castPhoto?: string; - }; - PerformanceImageModifyResponse: { - /** Format: int64 */ - performanceImageId?: number; - performanceImage?: string; - }; - PerformanceModifyResponse: { - /** Format: int64 */ - userId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** @enum {string} */ - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - /** Format: int32 */ - runningTime?: number; - performanceDescription?: string; - performanceAttentionNote?: string; - /** @enum {string} */ - bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; - accountNumber?: string; - accountHolder?: string; - posterImage?: string; - performanceTeamName?: string; - performanceVenue?: string; - performanceContact?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - totalScheduleCount?: number; - scheduleModifyResponses?: components["schemas"]["ScheduleModifyResponse"][]; - castModifyResponses?: components["schemas"]["CastModifyResponse"][]; - staffModifyResponses?: components["schemas"]["StaffModifyResponse"][]; - performanceImageModifyResponses?: components["schemas"]["PerformanceImageModifyResponse"][]; - }; - ScheduleModifyResponse: { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - /** Format: int32 */ - totalTicketCount?: number; - /** Format: int32 */ - dueDate?: number; - /** @enum {string} */ - scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; - }; - StaffModifyResponse: { - /** Format: int64 */ - staffId?: number; - staffName?: string; - staffRole?: string; - staffPhoto?: string; - }; - SuccessResponsePerformanceModifyResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["PerformanceModifyResponse"]; - }; - CarouselProcessRequest: { + CarouselHandleRequest: { carousels?: (components["schemas"]["PromotionGenerateRequest"] | components["schemas"]["PromotionModifyRequest"])[]; }; PromotionGenerateRequest: { @@ -638,33 +580,10 @@ export interface components { /** Format: int64 */ performanceId?: number; }); - ErrorResponse: { - /** Format: int32 */ - status?: number; - message?: string; - }; - SuccessResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: Record<string, never>; - }; MemberLoginRequest: { /** @enum {string} */ socialType: "KAKAO"; }; - LoginSuccessResponse: { - accessToken?: string; - refreshToken?: string; - nickname?: string; - role?: string; - }; - SuccessResponseLoginSuccessResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["LoginSuccessResponse"]; - }; CastRequest: { castName?: string; castRole?: string; @@ -712,73 +631,6 @@ export interface components { staffRole?: string; staffPhoto?: string; }; - CastResponse: { - /** Format: int64 */ - castId?: number; - castName?: string; - castRole?: string; - castPhoto?: string; - }; - PerformanceImageResponse: { - /** Format: int64 */ - imageId?: number; - imageUrl?: string; - }; - PerformanceResponse: { - /** Format: int64 */ - userId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** @enum {string} */ - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - /** Format: int32 */ - runningTime?: number; - performanceDescription?: string; - performanceAttentionNote?: string; - /** @enum {string} */ - bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; - accountNumber?: string; - accountHolder?: string; - posterImage?: string; - performanceTeamName?: string; - performanceVenue?: string; - performanceContact?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - totalScheduleCount?: number; - scheduleList?: components["schemas"]["ScheduleResponse"][]; - castList?: components["schemas"]["CastResponse"][]; - staffList?: components["schemas"]["StaffResponse"][]; - performanceImageList?: components["schemas"]["PerformanceImageResponse"][]; - }; - ScheduleResponse: { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - /** Format: int32 */ - totalTicketCount?: number; - /** Format: int32 */ - dueDate?: number; - /** @enum {string} */ - scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; - }; - StaffResponse: { - /** Format: int64 */ - staffId?: number; - staffName?: string; - staffRole?: string; - staffPhoto?: string; - }; - SuccessResponsePerformanceResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["PerformanceResponse"]; - }; MemberBookingRequest: { /** Format: int64 */ scheduleId?: number; @@ -793,35 +645,6 @@ export interface components { /** Format: int32 */ totalPaymentAmount?: number; }; - MemberBookingResponse: { - /** Format: int64 */ - bookingId?: number; - /** Format: int64 */ - scheduleId?: number; - /** Format: int64 */ - userId?: number; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; - bookerName?: string; - bookerPhoneNumber?: string; - /** @enum {string} */ - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; - /** @enum {string} */ - bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; - accountNumber?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - /** Format: date-time */ - createdAt?: string; - }; - SuccessResponseMemberBookingResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["MemberBookingResponse"]; - }; GuestBookingRequest: { /** Format: int64 */ scheduleId?: number; @@ -838,359 +661,16 @@ export interface components { /** @enum {string} */ bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; }; - GuestBookingResponse: { - /** Format: int64 */ - bookingId?: number; - /** Format: int64 */ - scheduleId?: number; - /** Format: int64 */ - userId?: number; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; - bookerName?: string; - bookerPhoneNumber?: string; - /** @enum {string} */ - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; - /** @enum {string} */ - bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; - accountNumber?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - /** Format: date-time */ - createdAt?: string; - }; - SuccessResponseGuestBookingResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["GuestBookingResponse"]; - }; GuestBookingRetrieveRequest: { bookerName?: string; birthDate?: string; bookerPhoneNumber?: string; password?: string; }; - GuestBookingRetrieveResponse: { - /** Format: int64 */ - bookingId?: number; - /** Format: int64 */ - scheduleId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** Format: date-time */ - performanceDate?: string; - performanceVenue?: string; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; - bookerName?: string; - performanceContact?: string; - /** @enum {string} */ - bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; - accountNumber?: string; - accountHolder?: string; - /** Format: int32 */ - dueDate?: number; - /** @enum {string} */ - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; - /** Format: date-time */ - createdAt?: string; - posterImage?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - }; - SuccessResponseListGuestBookingRetrieveResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["GuestBookingRetrieveResponse"][]; - }; - TicketCancelRequest: { - /** Format: int64 */ - performanceId?: number; - bookingList?: number[]; - }; - AccessTokenGetSuccess: { - accessToken?: string; - }; - SuccessResponseAccessTokenGetSuccess: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["AccessTokenGetSuccess"]; - }; - SuccessResponseTicketRetrieveResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["TicketRetrieveResponse"]; - }; - TicketDetail: { - /** Format: int64 */ - bookingId?: number; - bookerName?: string; - bookerPhoneNumber?: string; - /** Format: int64 */ - scheduleId?: number; - /** Format: int32 */ - purchaseTicketCount?: number; - /** Format: date-time */ - createdAt?: string; - /** @enum {string} */ - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; - scheduleNumber?: string; - }; - TicketRetrieveResponse: { - performanceTitle?: string; - /** Format: int32 */ - totalScheduleCount?: number; - bookingList?: components["schemas"]["TicketDetail"][]; - }; - SuccessResponseTicketAvailabilityResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["TicketAvailabilityResponse"]; - }; - TicketAvailabilityResponse: { - /** Format: int64 */ - scheduleId?: number; - scheduleNumber?: string; - /** Format: int32 */ - totalTicketCount?: number; - /** Format: int32 */ - soldTicketCount?: number; - /** Format: int32 */ - availableTicketCount?: number; - /** Format: int32 */ - requestedTicketCount?: number; - isAvailable?: boolean; - }; - PerformanceModifyDetailResponse: { - /** Format: int64 */ - userId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** @enum {string} */ - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - /** Format: int32 */ - runningTime?: number; - performanceDescription?: string; - performanceAttentionNote?: string; - /** @enum {string} */ - bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; - accountNumber?: string; - accountHolder?: string; - posterImage?: string; - performanceTeamName?: string; - performanceVenue?: string; - performanceContact?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - totalScheduleCount?: number; - isBookerExist?: boolean; - scheduleList?: components["schemas"]["ScheduleResponse"][]; - castList?: components["schemas"]["CastResponse"][]; - staffList?: components["schemas"]["StaffResponse"][]; - performanceImageList?: components["schemas"]["PerformanceImageResponse"][]; - }; - SuccessResponsePerformanceModifyDetailResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["PerformanceModifyDetailResponse"]; - }; - MakerPerformanceDetailResponse: { - /** Format: int64 */ - performanceId?: number; - genre?: string; - performanceTitle?: string; - posterImage?: string; - performancePeriod?: string; - /** Format: int32 */ - minDueDate?: number; - }; - MakerPerformanceResponse: { - /** Format: int64 */ - userId?: number; - performances?: components["schemas"]["MakerPerformanceDetailResponse"][]; - }; - SuccessResponseMakerPerformanceResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["MakerPerformanceResponse"]; - }; - PerformanceDetailCastResponse: { - /** Format: int64 */ - castId?: number; - castName?: string; - castRole?: string; - castPhoto?: string; - }; - PerformanceDetailImageResponse: { - /** Format: int64 */ - performanceImageId?: number; - performanceImage?: string; - }; - PerformanceDetailResponse: { - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - performancePeriod?: string; - scheduleList?: components["schemas"]["PerformanceDetailScheduleResponse"][]; - /** Format: int32 */ - ticketPrice?: number; - genre?: string; - posterImage?: string; - /** Format: int32 */ - runningTime?: number; - performanceVenue?: string; - performanceDescription?: string; - performanceAttentionNote?: string; - performanceContact?: string; - performanceTeamName?: string; - castList?: components["schemas"]["PerformanceDetailCastResponse"][]; - staffList?: components["schemas"]["PerformanceDetailStaffResponse"][]; - /** Format: int32 */ - minDueDate?: number; - performanceImageList?: components["schemas"]["PerformanceDetailImageResponse"][]; - }; - PerformanceDetailScheduleResponse: { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - scheduleNumber?: string; - /** Format: int32 */ - dueDate?: number; - isBooking?: boolean; - }; - PerformanceDetailStaffResponse: { - /** Format: int64 */ - staffId?: number; - staffName?: string; - staffRole?: string; - staffPhoto?: string; - }; - SuccessResponsePerformanceDetailResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["PerformanceDetailResponse"]; - }; - BookingPerformanceDetailResponse: { - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - performancePeriod?: string; - scheduleList?: components["schemas"]["BookingPerformanceDetailScheduleResponse"][]; - /** Format: int32 */ - ticketPrice?: number; - genre?: string; - posterImage?: string; - performanceVenue?: string; - performanceTeamName?: string; - bankName?: string; - accountNumber?: string; - accountHolder?: string; - }; - BookingPerformanceDetailScheduleResponse: { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - scheduleNumber?: string; - /** Format: int32 */ - availableTicketCount?: number; - isBooking?: boolean; - /** Format: int32 */ - dueDate?: number; - }; - SuccessResponseBookingPerformanceDetailResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["BookingPerformanceDetailResponse"]; - }; - HomePerformanceDetail: { - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - dueDate?: number; - genre?: string; - posterImage?: string; - performanceVenue?: string; - }; - HomePromotionDetail: { - /** Format: int64 */ - promotionId?: number; - promotionPhoto?: string; - /** Format: int64 */ - performanceId?: number; - redirectUrl?: string; - isExternal?: boolean; - }; - HomeResponse: { - promotionList?: components["schemas"]["HomePromotionDetail"][]; - performanceList?: components["schemas"]["HomePerformanceDetail"][]; - }; - SuccessResponseHomeResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["HomeResponse"]; - }; - MemberBookingRetrieveResponse: { - /** Format: int64 */ - userId?: number; - /** Format: int64 */ - bookingId?: number; - /** Format: int64 */ - scheduleId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** Format: date-time */ - performanceDate?: string; - performanceVenue?: string; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; - bookerName?: string; - performanceContact?: string; - /** @enum {string} */ - bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; - accountNumber?: string; - accountHolder?: string; - /** Format: int32 */ - dueDate?: number; - /** @enum {string} */ - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; - /** Format: date-time */ - createdAt?: string; - posterImage?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - }; - SuccessResponseListMemberBookingRetrieveResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["MemberBookingRetrieveResponse"][]; + TicketCancelRequest: { + /** Format: int64 */ + performanceId?: number; + bookingList?: number[]; }; }; responses: never; @@ -1214,13 +694,31 @@ export interface operations { }; }; responses: { - /** @description OK */ + /** @description 예매자 입금여부 수정 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseVoid"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 이미 결제가 완료된 티켓의 상태는 변경할 수 없습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1238,13 +736,22 @@ export interface operations { }; }; responses: { - /** @description OK */ + /** @description 예매자 취소 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseVoid"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1268,43 +775,34 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponsePerformanceModifyResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; }; }; - /** @description 잘못된 요청 - 회차 최대 개수 초과 */ + /** @description 티켓 가격은 음수일 수 없습니다. */ 400: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponsePerformanceModifyResponse"]; + "*/*": components["schemas"]["ErrorResponse"]; }; }; - /** @description 권한 없음 - 해당 공연의 소유자가 아닙니다. */ + /** @description 해당 공연의 소유자가 아닙니다. */ 403: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponsePerformanceModifyResponse"]; + "*/*": components["schemas"]["ErrorResponse"]; }; }; - /** @description 존재하지 않는 회원 ID로 수정 요청을 보낼 수 없습니다. */ + /** @description 공연 정보를 찾을 수 없습니다. */ 404: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponsePerformanceModifyResponse"]; - }; - }; - /** @description 서버 내부 오류 */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponsePerformanceModifyResponse"]; + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1322,13 +820,31 @@ export interface operations { }; }; responses: { - /** @description OK */ - 200: { + /** @description 공연이 성공적으로 생성되었습니다. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 필수 데이터가 누락되었습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponsePerformanceResponse"]; + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1371,7 +887,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["CarouselProcessRequest"]; + "application/json": components["schemas"]["CarouselHandleRequest"]; }; }; responses: { @@ -1410,13 +926,31 @@ export interface operations { }; }; responses: { - /** @description OK */ + /** @description 로그인 또는 회원가입 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseLoginSuccessResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 로그인 요청이 유효하지 않습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회원 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1430,13 +964,22 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 로그아웃 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseVoid"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 회원 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1454,13 +997,31 @@ export interface operations { }; }; responses: { - /** @description OK */ - 200: { + /** @description 회원 예매가 성공적으로 완료되었습니다. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 필수 데이터가 누락되었습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseMemberBookingResponse"]; + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1478,13 +1039,31 @@ export interface operations { }; }; responses: { - /** @description OK */ - 200: { + /** @description 비회원 예매가 성공적으로 완료되었습니다. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 필수 데이터가 누락되었습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseGuestBookingResponse"]; + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1502,13 +1081,22 @@ export interface operations { }; }; responses: { - /** @description OK */ + /** @description 비회원 예매 조회가 성공적으로 완료되었습니다. */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseListGuestBookingRetrieveResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1544,13 +1132,22 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description access token 재발급 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseAccessTokenGetSuccess"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 유효하지 않은 토큰입니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1569,13 +1166,22 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 예매자 목록 조회 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseTicketRetrieveResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1593,13 +1199,40 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 티켓 수량 조회가 성공적으로 완료되었습니다. */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseTicketAvailabilityResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 잘못된 데이터 형식입니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 요청한 티켓 수량이 잔여 티켓 수를 초과했습니다. */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1615,13 +1248,22 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 공연 수정 페이지 정보 조회 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponsePerformanceModifyDetailResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1637,13 +1279,31 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 공연 삭제 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseVoid"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 공연의 소유자가 아니거나 예매자가 있어 삭제할 수 없습니다. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1657,13 +1317,22 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 회원이 등록한 공연 목록 조회 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseMakerPerformanceResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 회원 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1679,13 +1348,22 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 공연 상세정보 조회 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponsePerformanceDetailResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1701,13 +1379,22 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 예매하기 관련 공연 정보 조회 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseBookingPerformanceDetailResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; @@ -1715,7 +1402,7 @@ export interface operations { getHomePerformanceList: { parameters: { query?: { - genre?: string; + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; }; header?: never; path?: never; @@ -1723,13 +1410,13 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 홈 화면 공연 목록 조회가 성공적으로 완료되었습니다. */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseHomeResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; }; }; }; @@ -1777,13 +1464,22 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 회원 예매 조회가 성공적으로 완료되었습니다. */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponseListMemberBookingRetrieveResponse"]; + "*/*": components["schemas"]["SuccessResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["ErrorResponse"]; }; }; }; From 815a4057d35ea606a0ae1e70ffde0f00d3f5dd8a Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 26 Nov 2024 06:04:08 +0900 Subject: [PATCH 14/49] =?UTF-8?q?feat:=20useDebounce=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/hooks/useDebounce.ts | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 src/hooks/useDebounce.ts diff --git a/src/hooks/useDebounce.ts b/src/hooks/useDebounce.ts new file mode 100644 index 00000000..b6f68617 --- /dev/null +++ b/src/hooks/useDebounce.ts @@ -0,0 +1,19 @@ +import { useEffect, useState } from "react"; + +const useDebounce = (value: string, delay: number) => { + const [debouncedValue, setDebouncedValue] = useState(value); + + useEffect(() => { + const timer = setTimeout(() => { + setDebouncedValue(value); + }, delay); + + return () => { + clearTimeout(timer); + }; + }, [value]); + + return debouncedValue; +}; + +export default useDebounce; From e292be65c38612c426c46984b26a3520b8df6a2d Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 26 Nov 2024 06:12:28 +0900 Subject: [PATCH 15/49] =?UTF-8?q?feat:=20=EC=A1=B0=ED=9A=8C=20API=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ticketholderlist/TicketHolderList.styled.ts | 2 +- src/pages/ticketholderlist/TicketHolderList.tsx | 5 ++--- .../components/manageCard/ManageCardContainer.tsx | 6 +++--- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.styled.ts b/src/pages/ticketholderlist/TicketHolderList.styled.ts index 8478a76d..2b594afc 100644 --- a/src/pages/ticketholderlist/TicketHolderList.styled.ts +++ b/src/pages/ticketholderlist/TicketHolderList.styled.ts @@ -27,7 +27,7 @@ export const ManageCardContainer = styled.section` `; export const FooterButtonWrapper = styled.div` - position: sticky; + position: fixed; bottom: 0; z-index: 1; display: flex; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index c9b7fbad..bbc5e315 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -165,8 +165,7 @@ const TicketHolderList = () => { const { performanceId } = useParams(); - // const { data, isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); - const { isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); + const { data, isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); const actions = { PAYMENT: { @@ -303,7 +302,7 @@ const TicketHolderList = () => { name={item.bookerName} phoneNumber={item.bookerPhoneNumber} ticketCount={item.purchaseTicketCount} - scheduleId={item.scheduleId} + scheduleNumber={convertingNumber(item.scheduleNumber)} date={formattedDate} status={bookingStatus} /> diff --git a/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx index 04808cec..9fd99971 100644 --- a/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx +++ b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx @@ -6,7 +6,7 @@ interface ManagerCardContainerProps { name: string; phoneNumber: string; ticketCount: number; - scheduleId: number; + scheduleNumber: number; date: string; status: string; } @@ -15,7 +15,7 @@ export default function ManageCardContainer({ name, phoneNumber, ticketCount, - scheduleId, + scheduleNumber, date, status, }: ManagerCardContainerProps) { @@ -27,7 +27,7 @@ export default function ManageCardContainer({ {name} ({phoneNumber}) </S.InfoText> <S.InfoText $status={status}> - {scheduleId}회차 / {ticketCount}매 + {scheduleNumber}회차 / {ticketCount}매 </S.InfoText> <S.DateText $status={status}>{date}</S.DateText> </S.TextContainer> From 78c31226eb4175030879fe8d29bcc0d8d598bb2f Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Wed, 27 Nov 2024 19:51:19 +0900 Subject: [PATCH 16/49] =?UTF-8?q?style:=20=ED=95=84=ED=84=B0=EB=B0=94?= =?UTF-8?q?=ED=85=80=EC=8B=9C=ED=8A=B8=20style=20flex=20->=20grid=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/svgs/index.ts | 66 ---------------- src/assets/svgs/index.tsx | 2 +- .../FilterBottomSheet.styled.ts | 11 +-- .../FilterBottomSheet/FilterBottomSheet.tsx | 76 ++++++------------- 4 files changed, 28 insertions(+), 127 deletions(-) delete mode 100644 src/assets/svgs/index.ts diff --git a/src/assets/svgs/index.ts b/src/assets/svgs/index.ts deleted file mode 100644 index bd1bb637..00000000 --- a/src/assets/svgs/index.ts +++ /dev/null @@ -1,66 +0,0 @@ -export { default as BannerBasic } from "./BannerBasic"; -export { default as BtnFilter } from "./BtnFilter"; -export { default as BtnFloating } from "./BtnFloating"; -export { default as BtnModalDelete } from "./BtnModalDelete"; -export { default as ButtonDelete24 } from "./ButtonDelete24"; -export { default as CarouselPartInactive } from "./CarouselPartInactive"; -export { default as Empty } from "./Empty"; -export { default as IcomCopy } from "./IcomCopy"; -export { default as IconArrowLeft } from "./IconArrowLeft"; -export { default as IconArrowRight } from "./IconArrowRight"; -export { default as IconArrowDown } from "./IconArrowDown"; -export { default as IconArrowUp } from "./IconArrowUp"; -export { default as IconBnk } from "./IconBnk"; -export { default as IconCalendar } from "./IconCalendar"; -export { default as IconCamera } from "./IconCamera"; -export { default as IconCheckboxDisabledOn } from "./IconCheckboxDisabledOn"; -export { default as IconCheckboxSelectedOn } from "./IconCheckboxSelectedOn"; -export { default as IconCheckboxUnselectedOn } from "./IconCheckboxUnselectedOn"; -export { default as IconCheck } from "./IconCheck"; -export { default as IconChevronBack } from "./IconChevronBack"; -export { default as IconEmpty } from "./IconEmpty"; -export { default as IconEyeOff } from "./IconEyeOff"; -export { default as IconEyeOn } from "./IconEyeOn"; -export { default as IconFooterLogo } from "./IconFooterLogo"; -export { default as IconHanna } from "./IconHanna"; -export { default as IconIbk } from "./IconIbk"; -export { default as IconIm } from "./IconIm"; -export { default as IconImg } from "./IconImg"; -export { default as IconKabank } from "./IconKabank"; -export { default as IconKb } from "./IconKb"; -export { default as IconLargeBand } from "./IconLargeBand"; -export { default as IconLargeDance } from "./IconLargeDance"; -export { default as IconLargeEtc } from "./IconLargeEtc"; -export { default as IconLargeMusical } from "./IconLargeMusical"; -export { default as IconLogo } from "./IconLogo"; -export { default as IconMinus } from "./IconMinus"; -export { default as IconNonghyup } from "./IconNonghyup"; -export { default as IconPhotoDelete } from "./IconPhotoDelete"; -export { default as IconPlus } from "./IconPlus"; -export { default as IconProfile } from "./IconProfile"; -export { default as IconRoleAdd } from "./IconRoleAdd"; -export { default as IconSaemauel } from "./IconSaemauel"; -export { default as IconSc } from "./IconSc"; -export { default as IconShinhan } from "./IconShinhan"; -export { default as IconShinhyup } from "./IconShinhyup"; -export { default as IconSmallBand } from "./IconSmallBand"; -export { default as IconSmallDance } from "./IconSmallDance"; -export { default as IconSmallEtc } from "./IconSmallEtc"; -export { default as IconSmallMusical } from "./IconSmallMusical"; -export { default as IconSoohyup } from "./IconSoohyup"; -export { default as IconTextfiedlDelete } from "./IconTextfiedlDelete"; -export { default as IconTime } from "./IconTime"; -export { default as IconToggleOff } from "./IconToggleOff"; -export { default as IconToggleOn } from "./IconToggleOn"; -export { default as IconToss } from "./IconToss"; -export { default as IconWoochaegook } from "./IconWoochaegook"; -export { default as IconWoori } from "./IconWoori"; -export { default as IconXButton } from "./IconXButton"; -export { default as IcDelete } from "./IcDelete"; -export { default as IcHamburgar } from "./IcHamburgar"; -export { default as IcOutlinePlace } from "./IcOutlinePlace"; -export { default as IcRefresh } from "./IcRefresh"; -export { default as NotFoundAsset } from "./NotFoundAsset"; -export { default as Subtract } from "./Subtract"; -export { default as Switch } from "./Switch"; -export { default as Union } from "./Union"; diff --git a/src/assets/svgs/index.tsx b/src/assets/svgs/index.tsx index 61cf89c3..c29ceb05 100644 --- a/src/assets/svgs/index.tsx +++ b/src/assets/svgs/index.tsx @@ -65,4 +65,4 @@ export { default as NotFoundAsset } from "./NotFoundAsset"; export { default as SelectionControlCheckboxSelectedOff } from "./SelectionControlCheckboxSelectedOff"; export { default as Subtract } from "./Subtract"; export { default as Switch } from "./Switch"; -export { default as Union } from "./Union"; \ No newline at end of file +export { default as Union } from "./Union"; diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts index e34530e7..0c94eca0 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.styled.ts @@ -58,14 +58,9 @@ export const BoxDivider = styled.div` `; export const CheckBoxContainer = styled.section` - display: flex; - flex-direction: column; - gap: 1.2rem; -`; - -export const CheckBoxRow = styled.section` - display: flex; - gap: 8.1rem; + display: grid; + grid-gap: 1.4rem 8.1rem; + grid-template-columns: repeat(2, 9rem); `; export const CheckBoxLabel = styled.label` diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx index 9afccb77..0225e30d 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -24,18 +24,13 @@ const FilterBottomSheet = ({ onClickOutside(); }; - const splitArray = (arrayLength: number): number[][] => { + const scheduleNumberArray = (arrayLength: number): number[] => { const array = Array.from({ length: arrayLength }, (_, idx) => idx + 1); - const result: number[][] = []; - for (let i = 0; i < array.length; i += 2) { - result.push(array.slice(i, i + 2)); - } - - return result; + return array; }; - const scheduleArray = splitArray(totalScheduleCount); + const scheduleArray = scheduleNumberArray(totalScheduleCount); // 선택된 회차 확인 const handleScheduleCheck = (schedule: number) => { @@ -71,24 +66,16 @@ const FilterBottomSheet = ({ </S.TitleWrapper> <S.CheckBoxContainer> - {scheduleArray.map((row, rowIndex) => ( - <S.CheckBoxRow key={rowIndex}> - {row.map((scheduleNumber) => ( - <S.CheckBoxLabel key={scheduleNumber}> - <S.CheckBox - type="checkbox" - checked={checkedScheduleList.includes(scheduleNumber)} - onChange={() => handleScheduleCheck(scheduleNumber)} - /> - {checkedScheduleList.includes(scheduleNumber) ? ( - <S.SelectIcon /> - ) : ( - <S.UnSelectIcon /> - )} - <S.CheckBoxText>{scheduleNumber}회차</S.CheckBoxText> - </S.CheckBoxLabel> - ))} - </S.CheckBoxRow> + {scheduleArray.map((scheduleNumber) => ( + <S.CheckBoxLabel key={scheduleNumber}> + <S.CheckBox + type="checkbox" + checked={checkedScheduleList.includes(scheduleNumber)} + onChange={() => handleScheduleCheck(scheduleNumber)} + /> + {checkedScheduleList.includes(scheduleNumber) ? <S.SelectIcon /> : <S.UnSelectIcon />} + <S.CheckBoxText>{scheduleNumber}회차</S.CheckBoxText> + </S.CheckBoxLabel> ))} </S.CheckBoxContainer> @@ -96,32 +83,17 @@ const FilterBottomSheet = ({ <S.TitleWrapper>입금 상태</S.TitleWrapper> <S.CheckBoxContainer> - <S.CheckBoxRow> - {bookingStatusList.slice(0, 2).map((status, idx) => ( - <S.CheckBoxLabel key={idx}> - <S.CheckBox - type="checkbox" - checked={checkedStatusList.includes(status)} - onChange={() => handleStatusCheck(status)} - /> - {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} - <S.CheckBoxText>{status}</S.CheckBoxText> - </S.CheckBoxLabel> - ))} - </S.CheckBoxRow> - <S.CheckBoxRow> - {bookingStatusList.slice(2, 4).map((status, idx) => ( - <S.CheckBoxLabel key={idx}> - <S.CheckBox - type="checkbox" - checked={checkedStatusList.includes(status)} - onChange={() => handleStatusCheck(status)} - /> - {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} - <S.CheckBoxText>{status}</S.CheckBoxText> - </S.CheckBoxLabel> - ))} - </S.CheckBoxRow> + {bookingStatusList.map((status) => ( + <S.CheckBoxLabel key={status}> + <S.CheckBox + type="checkbox" + checked={checkedStatusList.includes(status)} + onChange={() => handleStatusCheck(status)} + /> + {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} + <S.CheckBoxText>{status}</S.CheckBoxText> + </S.CheckBoxLabel> + ))} </S.CheckBoxContainer> <Spacing marginBottom="3.2" /> {/* TODO : 선택된 내역 없을 때 버튼 비활성화 하기 */} From a471ec530ce9925cc2b271ece80c1ba28e8e107e Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sun, 1 Dec 2024 19:47:48 +0900 Subject: [PATCH 17/49] =?UTF-8?q?feat:=20=ED=95=84=ED=84=B0=EB=A7=81=20?= =?UTF-8?q?=EA=B8=B0=EB=8A=A5=20=EC=B9=A9-=EB=B0=94=ED=85=80=EC=8B=9C?= =?UTF-8?q?=ED=8A=B8=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ticketholderlist/TicketHolderList.tsx | 35 ++++++++++++++-- .../FilterBottomSheet/FilterBottomSheet.tsx | 37 +++++++++++++--- .../components/searchBar/SearchBar.tsx | 6 +-- .../selectedChips/SelectedChips.tsx | 42 +++++++++++++++---- 4 files changed, 99 insertions(+), 21 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index bbc5e315..da0df747 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -125,6 +125,11 @@ interface CSVDataType { bookingStatus: string; } +export interface FilterListType { + scheduleNumber: number[]; + bookingStatus: string[]; +} + // 관리자 페이지에서만 사용해서 공통 type으로 안 뺌 // TODO : TicketHolderList 내 type으로 빼기 export const convertingBookingStatus = (_bookingStatus: PaymentType): string => { @@ -158,6 +163,11 @@ const TicketHolderList = () => { const [status, setStatus] = useState("DEFAULT"); const [buttonText, setButtonText] = useState("예매자 관리하기"); + const [filterList, setFilterList] = useState<FilterListType>({ + scheduleNumber: [], + bookingStatus: [], + }); + const [openFilter, setOpenFilter] = useState(false); const [openMenu, setOpenMenu] = useState(false); @@ -210,7 +220,7 @@ const TicketHolderList = () => { }; // 필터 바텀시트 - const handleFilter = () => { + const handleFilterSheet = () => { if (!openFilter) { setOpenFilter(true); } else { @@ -218,6 +228,14 @@ const TicketHolderList = () => { } }; + const handleFilter = (scheduleNumber: number[], bookingStatus: string[]) => { + setFilterList({ + scheduleNumber, + bookingStatus, + }); + console.log(scheduleNumber, bookingStatus); + }; + useEffect(() => { setPaymentData(data?.bookingList ?? []); @@ -283,8 +301,13 @@ const TicketHolderList = () => { totalCount={data?.totalPerformanceTicketCount} /> <Spacing marginBottom={"2.6"} /> - <SearchBar handleFilter={handleFilter} status={status} /> - <SelectedChips /> + <SearchBar handleFilterSheet={handleFilterSheet} status={status} /> + <SelectedChips + filterList={filterList} + handleFilter={(scheduleNumber, bookingStatus) => + handleFilter(scheduleNumber, bookingStatus) + } + /> <Spacing marginBottom={"1.6"} /> </S.TitleSticky> @@ -330,7 +353,11 @@ const TicketHolderList = () => { <FilterBottomSheet isOpen={openFilter} totalScheduleCount={data.totalScheduleCount} - onClickOutside={handleFilter} + onClickOutside={handleFilterSheet} + filterList={filterList} + handleFilter={(scheduleNumber, bookingStatus) => + handleFilter(scheduleNumber, bookingStatus) + } /> </S.TicketHolderListWrpper> </> diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx index 0225e30d..770c364e 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -1,24 +1,39 @@ -import React, { useState, ReactNode } from "react"; +import { useState, ReactNode, useEffect } from "react"; import * as S from "./FilterBottomSheet.styled"; import { BottomSheet, Button, Spacing } from "@components/commons"; +import { + convertingBookingStatus, + FilterListType, + PaymentType, +} from "@pages/ticketholderlist/TicketHolderList"; interface FilterBottomSheetProps { isOpen: boolean; totalScheduleCount: number; children?: ReactNode; onClickOutside?: () => void; + filterList: FilterListType[]; + handleFilter: (scheduleNumber: number[], bookingStatus: string[]) => void; } -const bookingStatusList = ["미입금", "입금 완료", "환불 요청", "취소 완료"]; +const bookingStatusList = [ + "CHECKING_PAYMENT", + "BOOKING_CONFIRMED", + "REFUND_REQUIRED", + "BOOKING_CANCELLED", +]; const FilterBottomSheet = ({ isOpen, onClickOutside, totalScheduleCount, - children, + handleFilter, + filterList, }: FilterBottomSheetProps) => { - const [checkedStatusList, setCheckedStatusList] = useState<string[]>([]); - const [checkedScheduleList, setCheckedScheduleList] = useState<number[]>([]); + const [checkedStatusList, setCheckedStatusList] = useState<string[]>(filterList.bookingStatus); + const [checkedScheduleList, setCheckedScheduleList] = useState<number[]>( + filterList.scheduleNumber + ); const handleWrapperClick = () => { onClickOutside(); @@ -32,6 +47,14 @@ const FilterBottomSheet = ({ const scheduleArray = scheduleNumberArray(totalScheduleCount); + useEffect(() => { + const newScheduleNumbers = filterList.scheduleNumber.map((item) => item); + const newBookingStatuses = filterList.bookingStatus.map((item) => item); + + setCheckedScheduleList(newScheduleNumbers); + setCheckedStatusList(newBookingStatuses); + }, [filterList]); + // 선택된 회차 확인 const handleScheduleCheck = (schedule: number) => { setCheckedScheduleList((prev) => @@ -48,6 +71,8 @@ const FilterBottomSheet = ({ const handleCilckBtn = () => { onClickOutside(); + + handleFilter(checkedScheduleList, checkedStatusList); }; const handleClickRefresh = () => { @@ -91,7 +116,7 @@ const FilterBottomSheet = ({ onChange={() => handleStatusCheck(status)} /> {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} - <S.CheckBoxText>{status}</S.CheckBoxText> + <S.CheckBoxText>{convertingBookingStatus(status as PaymentType)}</S.CheckBoxText> </S.CheckBoxLabel> ))} </S.CheckBoxContainer> diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index a3dab2eb..6b7bcc30 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -3,15 +3,15 @@ import * as S from "./SearchBar.styled"; interface SearchBarProps { status: string; - handleFilter: () => void; + handleFilterSheet: () => void; } // TODO: 필터 적용되었을 때 아웃라인 색상 적용 -> 기능 붙일 때 같이 하기 -const SearchBar = ({ handleFilter, status }: SearchBarProps) => { +const SearchBar = ({ handleFilterSheet, status }: SearchBarProps) => { return ( <S.SearchBarWrapper> <S.SearchBar type="text" placeholder="예매자를 검색해보세요."></S.SearchBar> - {status === "DEFAULT" && <S.FilterBtn onClick={handleFilter} />} + {status === "DEFAULT" && <S.FilterBtn onClick={handleFilterSheet} />} </S.SearchBarWrapper> ); }; diff --git a/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx index 2bae6b80..6a74c3fd 100644 --- a/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx +++ b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx @@ -1,17 +1,43 @@ import React from "react"; import * as S from "./SelectedChips.styled"; +import { + convertingBookingStatus, + FilterListType, + PaymentType, +} from "@pages/ticketholderlist/TicketHolderList"; -const SelectedChips = () => { - // TODO: delteIcon에 삭제 기능 추가하기 - const handleClickDelete = () => {}; +interface SelectedChipsProps { + filterList: FilterListType[]; + handleFilter: (scheduleNumber: number[], bookingStatus: string[]) => void; +} + +const SelectedChips = ({ filterList, handleFilter }: SelectedChipsProps) => { + const handleClickDelete = (scheduleNumberToDelete: number, bookingStatusToDelete: string) => { + const updatedScheduleNumbers = filterList.scheduleNumber + .filter((item) => item !== scheduleNumberToDelete) + .map((item) => item); + + const updatedBookingStatuses = filterList.bookingStatus + .filter((item) => item !== bookingStatusToDelete) + .map((item) => item); + + handleFilter(updatedScheduleNumbers, updatedBookingStatuses); + }; return ( - // TODO : 선택된 필터 props로 받아서 map 돌리기 <S.SelectedChipsWrapper> - <S.Chip> - 1회차 - <S.DeleteIcon onClick={handleClickDelete} /> - </S.Chip> + {filterList.scheduleNumber.map((filter, index) => ( + <S.Chip key={index}> + {filter}회차 {/* scheduleNumber 사용 */} + <S.DeleteIcon onClick={() => handleClickDelete(filter, "")} /> + </S.Chip> + ))} + {filterList.bookingStatus.map((filter, index) => ( + <S.Chip key={index}> + {convertingBookingStatus(filter as PaymentType)} + <S.DeleteIcon onClick={() => handleClickDelete(0, filter)} /> + </S.Chip> + ))} </S.SelectedChipsWrapper> ); }; From 3ef8329c3211ee7a38c79b569a13471e26ded4ab Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sun, 1 Dec 2024 21:20:37 +0900 Subject: [PATCH 18/49] =?UTF-8?q?feat:=20=EC=98=88=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EC=A1=B0=ED=9A=8C=20=ED=95=84=ED=84=B0=EB=A7=81=20api=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/api.ts | 12 +- src/apis/domains/tickets/queries.ts | 4 +- src/constants/convertingBookingStatus.ts | 20 + src/constants/convertingScheduleNumber.ts | 26 + .../ticketholderlist/TicketHolderList.tsx | 38 +- .../FilterBottomSheet/FilterBottomSheet.tsx | 7 +- .../manageCard/ManageCardContainer.tsx | 1 - .../selectedChips/SelectedChips.tsx | 7 +- src/typings/api/schema/index.ts | 523 +++++++++++++----- 9 files changed, 472 insertions(+), 166 deletions(-) create mode 100644 src/constants/convertingBookingStatus.ts create mode 100644 src/constants/convertingScheduleNumber.ts diff --git a/src/apis/domains/tickets/api.ts b/src/apis/domains/tickets/api.ts index 1bedb136..394b8232 100644 --- a/src/apis/domains/tickets/api.ts +++ b/src/apis/domains/tickets/api.ts @@ -3,6 +3,7 @@ import { components } from "@typings/api/schema"; import { ApiResponseType } from "@typings/commonType"; import { PatchFormDataProps } from "@typings/deleteBookerFormatProps"; import { AxiosResponse } from "axios"; +import { convertingScheduleNumber } from "@constants/convertingScheduleNumber"; // 예매자 목록 조회 API (GET) export interface getTicketReq { @@ -15,11 +16,18 @@ export interface getTicketReq { type TicketRetrieveResponse = components["schemas"]["TicketRetrieveResponse"]; export const getTicketRetrieve = async ( - formData: getTicketReq + formData: getTicketReq, + filterList ): Promise<TicketRetrieveResponse | null> => { try { + const params = new URLSearchParams(); + filterList.scheduleNumber.map((item) => + params.append("scheduleNumber", convertingScheduleNumber(item)) + ); + filterList.bookingStatus.map((item) => params.append("bookingStatus", item)); + const response: AxiosResponse<ApiResponseType<TicketRetrieveResponse>> = await get( - `tickets/${formData.performanceId}` + `tickets/${formData.performanceId}?${params.toString()}` ); return response.data.data; diff --git a/src/apis/domains/tickets/queries.ts b/src/apis/domains/tickets/queries.ts index f4b1b5cb..51c1538f 100644 --- a/src/apis/domains/tickets/queries.ts +++ b/src/apis/domains/tickets/queries.ts @@ -15,10 +15,10 @@ const QUERY_KEY = { LIST: "list", }; -export const useTicketRetrive = (formData: getTicketReq) => { +export const useTicketRetrive = (formData: getTicketReq, filterList) => { return useQuery({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST], - queryFn: () => getTicketRetrieve(formData), + queryFn: () => getTicketRetrieve(formData, filterList), // staleTime: 1000 * 60 * 60, gcTime: 1000 * 60 * 60 * 24, }); diff --git a/src/constants/convertingBookingStatus.ts b/src/constants/convertingBookingStatus.ts new file mode 100644 index 00000000..5904b36e --- /dev/null +++ b/src/constants/convertingBookingStatus.ts @@ -0,0 +1,20 @@ +type PaymentType = + | "CHECKING_PAYMENT" + | "BOOKING_CONFIRMED" + | "BOOKING_CANCELLED" + | "REFUND_REQUIRED"; + +export const convertingBookingStatus = (_bookingStatus: PaymentType): string => { + switch (_bookingStatus) { + case "CHECKING_PAYMENT": + return "미입금"; + case "BOOKING_CONFIRMED": + return "입금 완료"; + case "BOOKING_CANCELLED": + return "취소 완료"; + case "REFUND_REQUIRED": + return "환불 요청"; + default: + throw new Error("알 수 없는 상태입니다."); + } +}; diff --git a/src/constants/convertingScheduleNumber.ts b/src/constants/convertingScheduleNumber.ts new file mode 100644 index 00000000..502b6104 --- /dev/null +++ b/src/constants/convertingScheduleNumber.ts @@ -0,0 +1,26 @@ +export const convertingScheduleNumber = (_scheduleNumber: number): string => { + switch (_scheduleNumber) { + case 1: + return "FIRST"; + case 2: + return "SECOND"; + case 3: + return "THIRD"; + case 4: + return "FOURTH"; + case 5: + return "FIFTH"; + case 6: + return "SIXTH"; + case 7: + return "SEVENTH"; + case 8: + return "EIGHTH"; + case 9: + return "NINTH"; + case 10: + return "TENTH"; + default: + return "UNKNOWN"; + } +}; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index da0df747..b4b9dcb4 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -17,6 +17,7 @@ import { BookingListProps } from "@pages/ticketholderlist/types/bookingListType" import { ManageCard } from "./components/manageCard"; import { getBankNameKr } from "@utils/getBankName"; import SelectedChips from "./components/selectedChips/SelectedChips"; +import { convertingBookingStatus } from "@constants/convertingBookingStatus"; const data = { performanceTitle: "비트밴드 정기공연", @@ -130,23 +131,6 @@ export interface FilterListType { bookingStatus: string[]; } -// 관리자 페이지에서만 사용해서 공통 type으로 안 뺌 -// TODO : TicketHolderList 내 type으로 빼기 -export const convertingBookingStatus = (_bookingStatus: PaymentType): string => { - switch (_bookingStatus) { - case "CHECKING_PAYMENT": - return "미입금"; - case "BOOKING_CONFIRMED": - return "입금 완료"; - case "BOOKING_CANCELLED": - return "취소 완료"; - case "REFUND_REQUIRED": - return "환불 요청"; - default: - throw new Error("알 수 없는 상태입니다."); - } -}; - const headers = [ { label: "예매일시", key: "createdAt" }, { label: "회차", key: "scheduleNumber" }, @@ -175,7 +159,10 @@ const TicketHolderList = () => { const { performanceId } = useParams(); - const { data, isLoading, refetch } = useTicketRetrive({ performanceId: Number(performanceId) }); + const { data, isLoading, refetch } = useTicketRetrive( + { performanceId: Number(performanceId) }, + filterList + ); const actions = { PAYMENT: { @@ -228,14 +215,23 @@ const TicketHolderList = () => { } }; - const handleFilter = (scheduleNumber: number[], bookingStatus: string[]) => { + const handleFilter = async (scheduleNumber: number[], bookingStatus: string[]) => { setFilterList({ scheduleNumber, bookingStatus, }); - console.log(scheduleNumber, bookingStatus); }; + // 필터 변경될 때마다 GET API 요청 + useEffect(() => { + const fetchData = async () => { + const refetchData = await refetch(); + setPaymentData(refetchData?.data?.bookingList ?? []); + }; + + fetchData(); + }, [filterList]); + useEffect(() => { setPaymentData(data?.bookingList ?? []); @@ -264,7 +260,7 @@ const TicketHolderList = () => { ); setCSVDataArr(tempCSVDataArr); } - }, [data]); + }, [data, paymentData]); const navigate = useNavigate(); diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx index 770c364e..c4eed2c4 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -1,11 +1,8 @@ import { useState, ReactNode, useEffect } from "react"; import * as S from "./FilterBottomSheet.styled"; import { BottomSheet, Button, Spacing } from "@components/commons"; -import { - convertingBookingStatus, - FilterListType, - PaymentType, -} from "@pages/ticketholderlist/TicketHolderList"; +import { FilterListType, PaymentType } from "@pages/ticketholderlist/TicketHolderList"; +import { convertingBookingStatus } from "@constants/convertingBookingStatus"; interface FilterBottomSheetProps { isOpen: boolean; diff --git a/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx index 9fd99971..414f8fd0 100644 --- a/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx +++ b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx @@ -1,4 +1,3 @@ -import { convertingBookingStatus } from "@pages/ticketholderlist/TicketHolderList"; import * as S from "./ManageCardContainer.styled"; import { PaymentType } from "@pages/ticketholderlist/TicketHolderList"; diff --git a/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx index 6a74c3fd..28f91740 100644 --- a/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx +++ b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx @@ -1,10 +1,7 @@ import React from "react"; import * as S from "./SelectedChips.styled"; -import { - convertingBookingStatus, - FilterListType, - PaymentType, -} from "@pages/ticketholderlist/TicketHolderList"; +import { FilterListType, PaymentType } from "@pages/ticketholderlist/TicketHolderList"; +import { convertingBookingStatus } from "@constants/convertingBookingStatus"; interface SelectedChipsProps { filterList: FilterListType[]; diff --git a/src/typings/api/schema/index.ts b/src/typings/api/schema/index.ts index 915a306e..2a8342fa 100644 --- a/src/typings/api/schema/index.ts +++ b/src/typings/api/schema/index.ts @@ -4,7 +4,7 @@ */ export interface paths { - "/api/tickets": { + "/api/tickets/update": { parameters: { query?: never; header?: never; @@ -21,11 +21,47 @@ export interface paths { delete?: never; options?: never; head?: never; + patch?: never; + trace?: never; + }; + "/api/tickets/refund": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; /** - * 예매자 취소 API - * @description 메이커가 자신의 공연에 대한 1명 이상의 예매자의 정보를 취소 상태로 변경하는 PATCH API입니다. + * 예매자 환불처리 API + * @description 메이커가 자신의 공연에 대한 1명 이상의 예매자의 정보를 환불완료 상태로 변경하는 PUT API입니다. */ - patch: operations["cancelTickets"]; + put: operations["refundTickets"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tickets/delete": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * 예매자 삭제 API + * @description 메이커가 자신의 공연에 대한 1명 이상의 예매자의 정보를 삭제하는 PUT API입니다. + */ + put: operations["deleteTickets"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; trace?: never; }; "/api/performances": { @@ -176,6 +212,46 @@ export interface paths { patch?: never; trace?: never; }; + "/api/bookings/refund": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** + * 유료공연 예매 환불 요청 API + * @description 유료공연 예매자가 환불 요청하는 PATCH API입니다. + */ + patch: operations["refundBookings"]; + trace?: never; + }; + "/api/bookings/cancel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** + * 무료공연/미입금 예매 취소 요청 API + * @description 무료공연/미입금 예매자가 취소 요청하는 PATCH API입니다. + */ + patch: operations["cancelBookings"]; + trace?: never; + }; "/health-check": { parameters: { query?: never; @@ -232,6 +308,26 @@ export interface paths { patch?: never; trace?: never; }; + "/api/tickets/search/{performanceId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 예매자 목록 검색 API + * @description 메이커가 자신의 공연에 대한 예매자 목록을 검색하는 GET API입니다. + */ + get: operations["searchTickets"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; "/api/schedules/{scheduleId}/availability": { parameters: { query?: never; @@ -460,7 +556,7 @@ export interface paths { export type webhooks = Record<string, never>; export interface components { schemas: { - TicketUpdateDetail: { + "com.beat.domain.booking.application.dto.TicketUpdateDetail": { /** Format: int64 */ bookingId?: number; bookerName?: string; @@ -472,41 +568,47 @@ export interface components { /** Format: date-time */ createdAt?: string; /** @enum {string} */ - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; scheduleNumber?: string; }; - TicketUpdateRequest: { + "com.beat.domain.booking.application.dto.TicketUpdateRequest": { /** Format: int64 */ performanceId?: number; performanceTitle?: string; /** Format: int32 */ totalScheduleCount?: number; - bookingList?: components["schemas"]["TicketUpdateDetail"][]; + bookingList?: components["schemas"]["com.beat.domain.booking.application.dto.TicketUpdateDetail"][]; }; - SuccessResponse: { + "com.beat.global.common.dto.ErrorResponse": { /** Format: int32 */ status?: number; message?: string; - data?: Record<string, never>; }; - ErrorResponse: { + "com.beat.global.common.dto.SuccessResponse": { /** Format: int32 */ status?: number; message?: string; + data?: Record<string, never>; }; - CastModifyRequest: { + "com.beat.domain.booking.application.dto.TicketRefundRequest": { /** Format: int64 */ - castId?: number; - castName?: string; - castRole?: string; - castPhoto?: string; + performanceId?: number; + bookingList?: components["schemas"]["com.beat.domain.booking.application.dto.TicketRefundRequest$Booking"][]; }; - PerformanceImageModifyRequest: { + "com.beat.domain.booking.application.dto.TicketRefundRequest$Booking": { /** Format: int64 */ - performanceImageId?: number; - performanceImage?: string; + bookingId?: number; }; - PerformanceModifyRequest: { + "com.beat.domain.booking.application.dto.TicketDeleteRequest": { + /** Format: int64 */ + performanceId?: number; + bookingList?: components["schemas"]["com.beat.domain.booking.application.dto.TicketDeleteRequest$Booking"][]; + }; + "com.beat.domain.booking.application.dto.TicketDeleteRequest$Booking": { + /** Format: int64 */ + bookingId?: number; + }; + "com.beat.domain.performance.application.dto.modify.PerformanceModifyRequest": { /** Format: int64 */ performanceId?: number; performanceTitle?: string; @@ -523,18 +625,34 @@ export interface components { posterImage?: string; performanceTeamName?: string; performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; performanceContact?: string; performancePeriod?: string; /** Format: int32 */ totalScheduleCount?: number; /** Format: int32 */ ticketPrice?: number; - scheduleModifyRequests?: components["schemas"]["ScheduleModifyRequest"][]; - castModifyRequests?: components["schemas"]["CastModifyRequest"][]; - staffModifyRequests?: components["schemas"]["StaffModifyRequest"][]; - performanceImageModifyRequests?: components["schemas"]["PerformanceImageModifyRequest"][]; + scheduleModifyRequests?: components["schemas"]["com.beat.domain.performance.application.dto.modify.schedule.ScheduleModifyRequest"][]; + castModifyRequests?: components["schemas"]["com.beat.domain.performance.application.dto.modify.cast.CastModifyRequest"][]; + staffModifyRequests?: components["schemas"]["com.beat.domain.performance.application.dto.modify.staff.StaffModifyRequest"][]; + performanceImageModifyRequests?: components["schemas"]["com.beat.domain.performance.application.dto.modify.performanceImage.PerformanceImageModifyRequest"][]; }; - ScheduleModifyRequest: { + "com.beat.domain.performance.application.dto.modify.cast.CastModifyRequest": { + /** Format: int64 */ + castId?: number; + castName?: string; + castRole?: string; + castPhoto?: string; + }; + "com.beat.domain.performance.application.dto.modify.performanceImage.PerformanceImageModifyRequest": { + /** Format: int64 */ + performanceImageId?: number; + performanceImage?: string; + }; + "com.beat.domain.performance.application.dto.modify.schedule.ScheduleModifyRequest": { /** Format: int64 */ scheduleId?: number; /** Format: date-time */ @@ -542,19 +660,19 @@ export interface components { /** Format: int32 */ totalTicketCount?: number; }; - StaffModifyRequest: { + "com.beat.domain.performance.application.dto.modify.staff.StaffModifyRequest": { /** Format: int64 */ staffId?: number; staffName?: string; staffRole?: string; staffPhoto?: string; }; - CarouselHandleRequest: { - carousels?: (components["schemas"]["PromotionGenerateRequest"] | components["schemas"]["PromotionModifyRequest"])[]; + "com.beat.admin.application.dto.request.CarouselHandleRequest": { + carousels?: (components["schemas"]["com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionGenerateRequest"] | components["schemas"]["com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionModifyRequest"])[]; }; - PromotionGenerateRequest: { - type: "PromotionGenerateRequest"; - } & (Omit<components["schemas"]["PromotionHandleRequest"], "type"> & { + "com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionGenerateRequest": { + type: "com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionGenerateRequest"; + } & (Omit<components["schemas"]["com.beat.admin.application.dto.request.PromotionHandleRequest"], "type"> & { /** @enum {string} */ carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; newImageUrl?: string; @@ -563,13 +681,9 @@ export interface components { /** Format: int64 */ performanceId?: number; }); - PromotionHandleRequest: { - external?: boolean; - type: string; - }; - PromotionModifyRequest: { - type: "PromotionModifyRequest"; - } & (Omit<components["schemas"]["PromotionHandleRequest"], "type"> & { + "com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionModifyRequest": { + type: "com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionModifyRequest"; + } & (Omit<components["schemas"]["com.beat.admin.application.dto.request.PromotionHandleRequest"], "type"> & { /** Format: int64 */ promotionId?: number; /** @enum {string} */ @@ -580,19 +694,23 @@ export interface components { /** Format: int64 */ performanceId?: number; }); - MemberLoginRequest: { + "com.beat.admin.application.dto.request.PromotionHandleRequest": { + external?: boolean; + type: string; + }; + "com.beat.global.auth.client.dto.MemberLoginRequest": { /** @enum {string} */ socialType: "KAKAO"; }; - CastRequest: { + "com.beat.domain.performance.application.dto.create.CastRequest": { castName?: string; castRole?: string; castPhoto?: string; }; - PerformanceImageRequest: { + "com.beat.domain.performance.application.dto.create.PerformanceImageRequest": { performanceImage?: string; }; - PerformanceRequest: { + "com.beat.domain.performance.application.dto.create.PerformanceRequest": { performanceTitle?: string; /** @enum {string} */ genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; @@ -607,18 +725,22 @@ export interface components { posterImage?: string; performanceTeamName?: string; performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; performanceContact?: string; performancePeriod?: string; /** Format: int32 */ ticketPrice?: number; /** Format: int32 */ totalScheduleCount?: number; - scheduleList?: components["schemas"]["ScheduleRequest"][]; - castList?: components["schemas"]["CastRequest"][]; - staffList?: components["schemas"]["StaffRequest"][]; - performanceImageList?: components["schemas"]["PerformanceImageRequest"][]; + scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.create.ScheduleRequest"][]; + castList?: components["schemas"]["com.beat.domain.performance.application.dto.create.CastRequest"][]; + staffList?: components["schemas"]["com.beat.domain.performance.application.dto.create.StaffRequest"][]; + performanceImageList?: components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceImageRequest"][]; }; - ScheduleRequest: { + "com.beat.domain.performance.application.dto.create.ScheduleRequest": { /** Format: date-time */ performanceDate?: string; /** Format: int32 */ @@ -626,12 +748,12 @@ export interface components { /** @enum {string} */ scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; }; - StaffRequest: { + "com.beat.domain.performance.application.dto.create.StaffRequest": { staffName?: string; staffRole?: string; staffPhoto?: string; }; - MemberBookingRequest: { + "com.beat.domain.booking.application.dto.MemberBookingRequest": { /** Format: int64 */ scheduleId?: number; /** @enum {string} */ @@ -641,11 +763,11 @@ export interface components { bookerName?: string; bookerPhoneNumber?: string; /** @enum {string} */ - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; /** Format: int32 */ totalPaymentAmount?: number; }; - GuestBookingRequest: { + "com.beat.domain.booking.application.dto.GuestBookingRequest": { /** Format: int64 */ scheduleId?: number; /** Format: int32 */ @@ -659,18 +781,25 @@ export interface components { /** Format: int32 */ totalPaymentAmount?: number; /** @enum {string} */ - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; }; - GuestBookingRetrieveRequest: { + "com.beat.domain.booking.application.dto.GuestBookingRetrieveRequest": { bookerName?: string; birthDate?: string; bookerPhoneNumber?: string; password?: string; }; - TicketCancelRequest: { + "com.beat.domain.booking.application.dto.BookingRefundRequest": { /** Format: int64 */ - performanceId?: number; - bookingList?: number[]; + bookingId?: number; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + }; + "com.beat.domain.booking.application.dto.BookingCancelRequest": { + /** Format: int64 */ + bookingId?: number; }; }; responses: never; @@ -690,7 +819,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["TicketUpdateRequest"]; + "application/json": components["schemas"]["com.beat.domain.booking.application.dto.TicketUpdateRequest"]; }; }; responses: { @@ -700,7 +829,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 이미 결제가 완료된 티켓의 상태는 변경할 수 없습니다. */ @@ -709,7 +838,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 회차 정보를 찾을 수 없습니다. */ @@ -718,12 +847,12 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; }; - cancelTickets: { + refundTickets: { parameters: { query?: never; header?: never; @@ -732,26 +861,59 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["TicketCancelRequest"]; + "application/json": components["schemas"]["com.beat.domain.booking.application.dto.TicketRefundRequest"]; }; }; responses: { - /** @description 예매자 취소 성공 */ + /** @description 예매자 환불처리 성공 */ 200: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; - /** @description 회차 정보를 찾을 수 없습니다. */ + /** @description 해당 예매 내역을 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; + }; + }; + }; + }; + deleteTickets: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["com.beat.domain.booking.application.dto.TicketDeleteRequest"]; + }; + }; + responses: { + /** @description 예매자 삭제 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + }; + }; + /** @description 해당 예매 내역을 찾을 수 없습니다. */ 404: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -765,7 +927,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["PerformanceModifyRequest"]; + "application/json": components["schemas"]["com.beat.domain.performance.application.dto.modify.PerformanceModifyRequest"]; }; }; responses: { @@ -775,7 +937,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 티켓 가격은 음수일 수 없습니다. */ @@ -784,7 +946,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 해당 공연의 소유자가 아닙니다. */ @@ -793,7 +955,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -802,7 +964,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -816,7 +978,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["PerformanceRequest"]; + "application/json": components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceRequest"]; }; }; responses: { @@ -826,7 +988,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 필수 데이터가 누락되었습니다. */ @@ -835,7 +997,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -844,7 +1006,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -864,7 +1026,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 회원이 없습니다. */ @@ -873,7 +1035,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -887,7 +1049,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["CarouselHandleRequest"]; + "application/json": components["schemas"]["com.beat.admin.application.dto.request.CarouselHandleRequest"]; }; }; responses: { @@ -897,7 +1059,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 해당 공연 정보를 찾을 수 없습니다. */ @@ -906,7 +1068,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -922,7 +1084,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["MemberLoginRequest"]; + "application/json": components["schemas"]["com.beat.global.auth.client.dto.MemberLoginRequest"]; }; }; responses: { @@ -932,7 +1094,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 로그인 요청이 유효하지 않습니다. */ @@ -941,7 +1103,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 회원 정보를 찾을 수 없습니다. */ @@ -950,7 +1112,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -970,7 +1132,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 회원 정보를 찾을 수 없습니다. */ @@ -979,7 +1141,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -993,7 +1155,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["MemberBookingRequest"]; + "application/json": components["schemas"]["com.beat.domain.booking.application.dto.MemberBookingRequest"]; }; }; responses: { @@ -1003,25 +1165,25 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; - /** @description 필수 데이터가 누락되었습니다. */ + /** @description 잘못된 요청 형식입니다. */ 400: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; - /** @description 회차 정보를 찾을 수 없습니다. */ + /** @description 회원 정보를 찾을 수 없습니다. */ 404: { headers: { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1035,7 +1197,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["GuestBookingRequest"]; + "application/json": components["schemas"]["com.beat.domain.booking.application.dto.GuestBookingRequest"]; }; }; responses: { @@ -1045,7 +1207,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 필수 데이터가 누락되었습니다. */ @@ -1054,7 +1216,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 회차 정보를 찾을 수 없습니다. */ @@ -1063,7 +1225,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1077,7 +1239,7 @@ export interface operations { }; requestBody: { content: { - "application/json": components["schemas"]["GuestBookingRetrieveRequest"]; + "application/json": components["schemas"]["com.beat.domain.booking.application.dto.GuestBookingRetrieveRequest"]; }; }; responses: { @@ -1087,7 +1249,73 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; + }; + }; + }; + }; + refundBookings: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["com.beat.domain.booking.application.dto.BookingRefundRequest"]; + }; + }; + responses: { + /** @description 유료공연 예매 환불 요청이 성공적으로 완료되었습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; + }; + }; + }; + }; + cancelBookings: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json": components["schemas"]["com.beat.domain.booking.application.dto.BookingCancelRequest"]; + }; + }; + responses: { + /** @description 무료공연/미입금 예매 취소 요청이 성공적으로 완료되었습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ @@ -1096,7 +1324,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1138,7 +1366,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 유효하지 않은 토큰입니다. */ @@ -1147,7 +1375,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1156,7 +1384,7 @@ export interface operations { parameters: { query?: { scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; - bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED"; + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; }; header?: never; path: { @@ -1172,7 +1400,42 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; + }; + }; + }; + }; + searchTickets: { + parameters: { + query: { + searchWord: string; + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + }; + header?: never; + path: { + performanceId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 예매자 목록 검색 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ @@ -1181,7 +1444,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1205,7 +1468,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 잘못된 데이터 형식입니다. */ @@ -1214,7 +1477,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 회차 정보를 찾을 수 없습니다. */ @@ -1223,7 +1486,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 요청한 티켓 수량이 잔여 티켓 수를 초과했습니다. */ @@ -1232,7 +1495,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1254,7 +1517,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -1263,7 +1526,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1285,7 +1548,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 공연의 소유자가 아니거나 예매자가 있어 삭제할 수 없습니다. */ @@ -1294,7 +1557,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -1303,7 +1566,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1323,7 +1586,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 회원 정보를 찾을 수 없습니다. */ @@ -1332,7 +1595,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1354,7 +1617,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -1363,7 +1626,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1385,7 +1648,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -1394,7 +1657,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1416,7 +1679,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; }; @@ -1441,7 +1704,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description S3 PreSigned url을 받아오기에 실패했습니다. */ @@ -1450,7 +1713,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1470,7 +1733,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ @@ -1479,7 +1742,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1499,7 +1762,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 회원이 없습니다 */ @@ -1508,7 +1771,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1530,7 +1793,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 회원이 없습니다. */ @@ -1539,7 +1802,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; @@ -1561,7 +1824,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; }; }; /** @description 회원이 없습니다. */ @@ -1570,7 +1833,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["ErrorResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; }; From 2d6eb93636004ae905098974e583525b61cb41b9 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sun, 1 Dec 2024 22:46:46 +0900 Subject: [PATCH 19/49] =?UTF-8?q?feat:=20=EC=98=88=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=EC=83=81=ED=83=9C=EC=97=90=20=EB=94=B0?= =?UTF-8?q?=EB=9D=BC=20=ED=95=84=ED=84=B0=EB=A7=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ticketholderlist/TicketHolderList.tsx | 135 +++++------------- 1 file changed, 34 insertions(+), 101 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index b4b9dcb4..33d9019e 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -19,103 +19,11 @@ import { getBankNameKr } from "@utils/getBankName"; import SelectedChips from "./components/selectedChips/SelectedChips"; import { convertingBookingStatus } from "@constants/convertingBookingStatus"; -const data = { - performanceTitle: "비트밴드 정기공연", - performanceTeamName: "비트밴드", - isBooking: true, - totalScheduleCount: 3, - totalPerformanceTicketCount: 100, - totalPerformanceSoldTicketCount: 50, - bookingList: [ - { - bookingId: 1, - bookerName: "황혜린", - bookerPhoneNumber: "010-1234-5678", - scheduleId: 2, - purchaseTicketCount: 3, - createdAt: "2024-07-07T12:34:56.789Z", - bookingStatus: "REFUND_REQUIRED", - scheduleNumber: "SECOND", - bankName: "NH_NONGHYUP", - accountNumber: "123-12-1234-123", - accountHolder: "전희주", - }, - { - bookingId: 2, - bookerName: "이동훈", - bookerPhoneNumber: "010-1234-0000", - scheduleId: 1, - purchaseTicketCount: 2, - createdAt: "2024-07-08T12:34:56.789Z", - bookingStatus: "BOOKING_CONFIRMED", - scheduleNumber: "FIRST", - // 예매 확정된 상태이므로 환불계좌 정보 없음 - bankName: "", - accountNumber: "", - accountHolder: "", - }, - { - bookingId: 1, - bookerName: "황혜린", - bookerPhoneNumber: "010-1234-5678", - scheduleId: 2, - purchaseTicketCount: 3, - createdAt: "2024-07-07T12:34:56.789Z", - bookingStatus: "REFUND_REQUIRED", - scheduleNumber: "SECOND", - bankName: "NH_NONGHYUP", - accountNumber: "123-12-1234-123", - accountHolder: "전희주", - }, - { - bookingId: 2, - bookerName: "이동훈", - bookerPhoneNumber: "010-1234-0000", - scheduleId: 1, - purchaseTicketCount: 2, - createdAt: "2024-07-08T12:34:56.789Z", - bookingStatus: "CHECKING_PAYMENT", - scheduleNumber: "FIRST", - // 예매 확정된 상태이므로 환불계좌 정보 없음 - bankName: "", - accountNumber: "", - accountHolder: "", - }, - { - bookingId: 1, - bookerName: "황혜린", - bookerPhoneNumber: "010-1234-5678", - scheduleId: 2, - purchaseTicketCount: 3, - createdAt: "2024-07-07T12:34:56.789Z", - bookingStatus: "REFUND_REQUIRED", - scheduleNumber: "SECOND", - bankName: "NH_NONGHYUP", - accountNumber: "123-12-1234-123", - accountHolder: "전희주", - }, - { - bookingId: 2, - bookerName: "이동훈", - bookerPhoneNumber: "010-1234-0000", - scheduleId: 1, - purchaseTicketCount: 2, - createdAt: "2024-07-08T12:34:56.789Z", - bookingStatus: "BOOKING_CANCELLED", - scheduleNumber: "FIRST", - // 예매 확정된 상태이므로 환불계좌 정보 없음 - bankName: "", - accountNumber: "", - accountHolder: "", - }, - ], -}; - export type PaymentType = | "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" - | "REFUND_REQUIRED"; + | "REFUND_REQUESTED"; interface CSVDataType { createdAt: string; @@ -198,6 +106,24 @@ const TicketHolderList = () => { const handleStatus = (status: string) => { setStatus(status); setOpenMenu(false); + + switch (status) { + case "PAYMENT": + setFilterList({ + scheduleNumber: [], + bookingStatus: ["CHECKING_PAYMENT"], + }); + case "REFUND": + setFilterList({ + scheduleNumber: [], + bookingStatus: ["REFUND_REQUESTED"], + }); + case "DELETE": + setFilterList({ + scheduleNumber: [], + bookingStatus: ["CHECKING_PAYMENT", "BOOKING_CONFIRMED", "REFUND_REQUESTED"], + }); + } }; // 바텀시트 닫기 @@ -230,7 +156,7 @@ const TicketHolderList = () => { }; fetchData(); - }, [filterList]); + }, [filterList, status]); useEffect(() => { setPaymentData(data?.bookingList ?? []); @@ -265,7 +191,11 @@ const TicketHolderList = () => { const navigate = useNavigate(); const handleNavigateBack = () => { - navigate("/gig-manage"); + if (status === "DEFAULT") { + navigate("/gig-manage"); + } else { + setStatus("DEFAULT"); + } }; const { setHeader } = useHeader(); @@ -298,12 +228,15 @@ const TicketHolderList = () => { /> <Spacing marginBottom={"2.6"} /> <SearchBar handleFilterSheet={handleFilterSheet} status={status} /> - <SelectedChips - filterList={filterList} - handleFilter={(scheduleNumber, bookingStatus) => - handleFilter(scheduleNumber, bookingStatus) - } - /> + {status === "DEFAULT" && ( + <SelectedChips + filterList={filterList} + handleFilter={(scheduleNumber, bookingStatus) => + handleFilter(scheduleNumber, bookingStatus) + } + /> + )} + <Spacing marginBottom={"1.6"} /> </S.TitleSticky> From a9e191286c018ec9e43f5f05b9743eacf0454647 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 2 Dec 2024 22:10:49 +0900 Subject: [PATCH 20/49] =?UTF-8?q?feat:=20=EC=B2=B4=ED=81=AC=EB=B0=95?= =?UTF-8?q?=EC=8A=A4=20=EC=9D=B4=EC=83=81=ED=95=98=EA=B2=8C=20=EB=90=98?= =?UTF-8?q?=EB=8D=98=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/constants/convertingBookingStatus.ts | 4 +- .../ticketholderlist/TicketHolderList.tsx | 45 +- .../FilterBottomSheet/FilterBottomSheet.tsx | 2 +- .../manageCard/ManageCheckBox.styled.ts | 9 +- .../components/manageCard/ManageCheckBox.tsx | 23 +- src/typings/api/schema/index.ts | 734 +++++++++++++++++- 6 files changed, 762 insertions(+), 55 deletions(-) diff --git a/src/constants/convertingBookingStatus.ts b/src/constants/convertingBookingStatus.ts index 5904b36e..968965a7 100644 --- a/src/constants/convertingBookingStatus.ts +++ b/src/constants/convertingBookingStatus.ts @@ -2,7 +2,7 @@ type PaymentType = | "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" - | "REFUND_REQUIRED"; + | "REFUND_REQUESTED"; export const convertingBookingStatus = (_bookingStatus: PaymentType): string => { switch (_bookingStatus) { @@ -12,7 +12,7 @@ export const convertingBookingStatus = (_bookingStatus: PaymentType): string => return "입금 완료"; case "BOOKING_CANCELLED": return "취소 완료"; - case "REFUND_REQUIRED": + case "REFUND_REQUESTED": return "환불 요청"; default: throw new Error("알 수 없는 상태입니다."); diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 33d9019e..ac14c8ed 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -72,21 +72,36 @@ const TicketHolderList = () => { filterList ); + // 체크된 리스트 확인 + const [checkedBookingId, setCheckedBookingId] = useState<number[]>([]); + + const handleBookingIdCheck = (bookingId: number) => { + setCheckedBookingId((prev) => + prev.includes(bookingId) ? prev.filter((id) => id !== bookingId) : [...prev, bookingId] + ); + }; + const actions = { PAYMENT: { text: "입금 처리하기", // TODO : 예매 확정 팝업 - action: console.log("입금 처리"), + action: () => { + setStatus("DEFAULT"), setFilterList({ scheduleNumber: [], bookingStatus: [] }); + }, }, REFUND: { text: "환불 처리하기", // TODO : 환불 처리 팝업 - action: () => console.log("환불"), + action: () => { + setStatus("DEFAULT"), setFilterList({ scheduleNumber: [], bookingStatus: [] }); + }, }, DELETE: { text: "예매자 삭제하기", // TODO : 예매자 삭제 팝업 - action: () => console.log("예매자 삭제"), + action: () => { + setStatus("DEFAULT"), setFilterList({ scheduleNumber: [], bookingStatus: [] }); + }, }, DEFAULT: { text: "예매자 관리하기", @@ -106,23 +121,31 @@ const TicketHolderList = () => { const handleStatus = (status: string) => { setStatus(status); setOpenMenu(false); - switch (status) { case "PAYMENT": setFilterList({ scheduleNumber: [], bookingStatus: ["CHECKING_PAYMENT"], }); + break; case "REFUND": setFilterList({ scheduleNumber: [], bookingStatus: ["REFUND_REQUESTED"], }); + break; case "DELETE": setFilterList({ scheduleNumber: [], bookingStatus: ["CHECKING_PAYMENT", "BOOKING_CONFIRMED", "REFUND_REQUESTED"], }); + break; + default: + setFilterList({ + scheduleNumber: [], + bookingStatus: [], + }); + break; } }; @@ -207,7 +230,7 @@ const TicketHolderList = () => { subText: "CSV", leftOnClick: handleNavigateBack, // TODO : rightOnClick CSV 다운로드로 변경 - // rightOnClick: , + // rightOnClick:, }); }, [setHeader]); @@ -241,15 +264,21 @@ const TicketHolderList = () => { </S.TitleSticky> <S.ManageCardList> - {paymentData.map((item, idx) => { + {paymentData.map((item) => { const date = item.createdAt.split("T")[0]; const formattedDate = `${date.replace(/-/g, ". ")}`; const bookingStatus = convertingBookingStatus(item.bookingStatus as PaymentType); return ( - <ManageCard key={idx}> + <ManageCard key={item.bookingId}> <S.ManageCardContainer> - {status !== "DEFAULT" && <ManageCard.ManageCheckBox />} + {status !== "DEFAULT" && ( + <ManageCard.ManageCheckBox + bookingId={item.bookingId} + checkedBookingId={checkedBookingId} + handleBookingIdCheck={handleBookingIdCheck} + /> + )} <ManageCard.ManageCardContainer name={item.bookerName} phoneNumber={item.bookerPhoneNumber} diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx index c4eed2c4..9a9ba3bb 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -16,7 +16,7 @@ interface FilterBottomSheetProps { const bookingStatusList = [ "CHECKING_PAYMENT", "BOOKING_CONFIRMED", - "REFUND_REQUIRED", + "REFUND_REQUESTED", "BOOKING_CANCELLED", ]; diff --git a/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.styled.ts b/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.styled.ts index 6c065124..8204392a 100644 --- a/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.styled.ts +++ b/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.styled.ts @@ -1,12 +1,17 @@ import styled from "styled-components"; -import { IcRefresh, IconCheckboxSelectedOn, IconCheckboxUnselectedOn } from "@assets/svgs"; +import { IconCheckboxSelectedOn, IconCheckboxUnselectedOn } from "@assets/svgs"; export const CheckBoxWrapper = styled.section` display: flex; `; export const CheckBox = styled.input` - display: none; + position: absolute; + + width: 1.8rem; + height: 1.8rem; + + opacity: 0; `; export const SelectIcon = styled(IconCheckboxSelectedOn)` diff --git a/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.tsx b/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.tsx index b2e22e99..1075b967 100644 --- a/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.tsx +++ b/src/pages/ticketholderlist/components/manageCard/ManageCheckBox.tsx @@ -1,15 +1,28 @@ import * as S from "./ManageCheckBox.styled"; -export default function ManageCheckBox({}) { +interface ManageCheckBoxProps { + bookingId: number; + checkedBookingId: number[]; + handleBookingIdCheck: (bookingId: number) => void; +} + +export default function ManageCheckBox({ + bookingId, + checkedBookingId, + handleBookingIdCheck, +}: ManageCheckBoxProps) { + const isChecked = checkedBookingId.includes(bookingId); + return ( <S.CheckBoxWrapper> <S.CheckBox type="checkbox" - // checked={checkedStatusList.includes(status)} - // onChange={() => handleStatusCheck(status)} + checked={isChecked} + onChange={() => { + handleBookingIdCheck(bookingId); + }} /> - {/* {checkedStatusList.includes(status) ? <S.SelectIcon /> : <S.UnSelectIcon />} */} - <S.UnSelectIcon /> + {isChecked ? <S.SelectIcon /> : <S.UnSelectIcon />} </S.CheckBoxWrapper> ); } diff --git a/src/typings/api/schema/index.ts b/src/typings/api/schema/index.ts index 2a8342fa..14719075 100644 --- a/src/typings/api/schema/index.ts +++ b/src/typings/api/schema/index.ts @@ -259,6 +259,10 @@ export interface paths { path?: never; cookie?: never; }; + /** + * 헬스 체크 조회 API + * @description 서버 상태를 확인하기 위한 헬스 체크 API로, 정상적으로 동작할 경우 'OK' 문자열을 반환합니다. + */ get: operations["healthcheck"]; put?: never; post?: never; @@ -584,7 +588,7 @@ export interface components { status?: number; message?: string; }; - "com.beat.global.common.dto.SuccessResponse": { + "com.beat.global.common.dto.SuccessResponseJava.lang.Void": { /** Format: int32 */ status?: number; message?: string; @@ -667,6 +671,77 @@ export interface components { staffRole?: string; staffPhoto?: string; }; + "com.beat.domain.performance.application.dto.modify.PerformanceModifyResponse": { + /** Format: int64 */ + userId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** @enum {string} */ + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + /** Format: int32 */ + runningTime?: number; + performanceDescription?: string; + performanceAttentionNote?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + posterImage?: string; + performanceTeamName?: string; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceContact?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + totalScheduleCount?: number; + scheduleModifyResponses?: components["schemas"]["com.beat.domain.performance.application.dto.modify.schedule.ScheduleModifyResponse"][]; + castModifyResponses?: components["schemas"]["com.beat.domain.performance.application.dto.modify.cast.CastModifyResponse"][]; + staffModifyResponses?: components["schemas"]["com.beat.domain.performance.application.dto.modify.staff.StaffModifyResponse"][]; + performanceImageModifyResponses?: components["schemas"]["com.beat.domain.performance.application.dto.modify.performanceImage.PerformanceImageModifyResponse"][]; + }; + "com.beat.domain.performance.application.dto.modify.cast.CastModifyResponse": { + /** Format: int64 */ + castId?: number; + castName?: string; + castRole?: string; + castPhoto?: string; + }; + "com.beat.domain.performance.application.dto.modify.performanceImage.PerformanceImageModifyResponse": { + /** Format: int64 */ + performanceImageId?: number; + performanceImage?: string; + }; + "com.beat.domain.performance.application.dto.modify.schedule.ScheduleModifyResponse": { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + /** Format: int32 */ + totalTicketCount?: number; + /** Format: int32 */ + dueDate?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + }; + "com.beat.domain.performance.application.dto.modify.staff.StaffModifyResponse": { + /** Format: int64 */ + staffId?: number; + staffName?: string; + staffRole?: string; + staffPhoto?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.modify.PerformanceModifyResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.performance.application.dto.modify.PerformanceModifyResponse"]; + }; "com.beat.admin.application.dto.request.CarouselHandleRequest": { carousels?: (components["schemas"]["com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionGenerateRequest"] | components["schemas"]["com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionModifyRequest"])[]; }; @@ -698,10 +773,39 @@ export interface components { external?: boolean; type: string; }; + "com.beat.admin.application.dto.response.CarouselHandleAllResponse": { + modifiedPromotions?: components["schemas"]["com.beat.admin.application.dto.response.CarouselHandleAllResponse$PromotionResponse"][]; + }; + "com.beat.admin.application.dto.response.CarouselHandleAllResponse$PromotionResponse": { + /** Format: int64 */ + promotionId?: number; + newImageUrl?: string; + isExternal?: boolean; + redirectUrl?: string; + carouselNumber?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.admin.application.dto.response.CarouselHandleAllResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.admin.application.dto.response.CarouselHandleAllResponse"]; + }; "com.beat.global.auth.client.dto.MemberLoginRequest": { /** @enum {string} */ socialType: "KAKAO"; }; + "com.beat.domain.member.dto.LoginSuccessResponse": { + accessToken?: string; + refreshToken?: string; + nickname?: string; + role?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.member.dto.LoginSuccessResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.member.dto.LoginSuccessResponse"]; + }; "com.beat.domain.performance.application.dto.create.CastRequest": { castName?: string; castRole?: string; @@ -753,6 +857,77 @@ export interface components { staffRole?: string; staffPhoto?: string; }; + "com.beat.domain.performance.application.dto.create.CastResponse": { + /** Format: int64 */ + castId?: number; + castName?: string; + castRole?: string; + castPhoto?: string; + }; + "com.beat.domain.performance.application.dto.create.PerformanceImageResponse": { + /** Format: int64 */ + imageId?: number; + imageUrl?: string; + }; + "com.beat.domain.performance.application.dto.create.PerformanceResponse": { + /** Format: int64 */ + userId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** @enum {string} */ + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + /** Format: int32 */ + runningTime?: number; + performanceDescription?: string; + performanceAttentionNote?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + posterImage?: string; + performanceTeamName?: string; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceContact?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + totalScheduleCount?: number; + scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.create.ScheduleResponse"][]; + castList?: components["schemas"]["com.beat.domain.performance.application.dto.create.CastResponse"][]; + staffList?: components["schemas"]["com.beat.domain.performance.application.dto.create.StaffResponse"][]; + performanceImageList?: components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceImageResponse"][]; + }; + "com.beat.domain.performance.application.dto.create.ScheduleResponse": { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + /** Format: int32 */ + totalTicketCount?: number; + /** Format: int32 */ + dueDate?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + }; + "com.beat.domain.performance.application.dto.create.StaffResponse": { + /** Format: int64 */ + staffId?: number; + staffName?: string; + staffRole?: string; + staffPhoto?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.create.PerformanceResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceResponse"]; + }; "com.beat.domain.booking.application.dto.MemberBookingRequest": { /** Format: int64 */ scheduleId?: number; @@ -767,6 +942,35 @@ export interface components { /** Format: int32 */ totalPaymentAmount?: number; }; + "com.beat.domain.booking.application.dto.MemberBookingResponse": { + /** Format: int64 */ + bookingId?: number; + /** Format: int64 */ + scheduleId?: number; + /** Format: int64 */ + userId?: number; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + bookerPhoneNumber?: string; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + /** Format: date-time */ + createdAt?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.MemberBookingResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.booking.application.dto.MemberBookingResponse"]; + }; "com.beat.domain.booking.application.dto.GuestBookingRequest": { /** Format: int64 */ scheduleId?: number; @@ -783,12 +987,78 @@ export interface components { /** @enum {string} */ bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; }; + "com.beat.domain.booking.application.dto.GuestBookingResponse": { + /** Format: int64 */ + bookingId?: number; + /** Format: int64 */ + scheduleId?: number; + /** Format: int64 */ + userId?: number; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + bookerPhoneNumber?: string; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + /** Format: date-time */ + createdAt?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.GuestBookingResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.booking.application.dto.GuestBookingResponse"]; + }; "com.beat.domain.booking.application.dto.GuestBookingRetrieveRequest": { bookerName?: string; birthDate?: string; bookerPhoneNumber?: string; password?: string; }; + "com.beat.domain.booking.application.dto.GuestBookingRetrieveResponse": { + /** Format: int64 */ + bookingId?: number; + /** Format: int64 */ + scheduleId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** Format: date-time */ + performanceDate?: string; + performanceVenue?: string; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + performanceContact?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + /** Format: int32 */ + dueDate?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** Format: date-time */ + createdAt?: string; + posterImage?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + }; + "com.beat.global.common.dto.SuccessResponseJava.util.ListCom.beat.domain.booking.application.dto.GuestBookingRetrieveResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.booking.application.dto.GuestBookingRetrieveResponse"][]; + }; "com.beat.domain.booking.application.dto.BookingRefundRequest": { /** Format: int64 */ bookingId?: number; @@ -797,10 +1067,400 @@ export interface components { accountNumber?: string; accountHolder?: string; }; + "com.beat.domain.booking.application.dto.BookingRefundResponse": { + /** Format: int64 */ + bookingId?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.BookingRefundResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.booking.application.dto.BookingRefundResponse"]; + }; "com.beat.domain.booking.application.dto.BookingCancelRequest": { /** Format: int64 */ bookingId?: number; }; + "com.beat.domain.booking.application.dto.BookingCancelResponse": { + /** Format: int64 */ + bookingId?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.BookingCancelResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.booking.application.dto.BookingCancelResponse"]; + }; + "com.beat.domain.member.dto.AccessTokenGetSuccess": { + accessToken?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.member.dto.AccessTokenGetSuccess": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.member.dto.AccessTokenGetSuccess"]; + }; + "com.beat.domain.booking.application.dto.TicketDetail": { + /** Format: int64 */ + bookingId?: number; + bookerName?: string; + bookerPhoneNumber?: string; + /** Format: int64 */ + scheduleId?: number; + /** Format: int32 */ + purchaseTicketCount?: number; + /** Format: date-time */ + createdAt?: string; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + scheduleNumber?: string; + bankName?: string; + accountNumber?: string; + accountHolder?: string; + }; + "com.beat.domain.booking.application.dto.TicketRetrieveResponse": { + performanceTitle?: string; + performanceTeamName?: string; + /** Format: int32 */ + totalScheduleCount?: number; + /** Format: int32 */ + totalPerformanceTicketCount?: number; + /** Format: int32 */ + totalPerformanceSoldTicketCount?: number; + bookingList?: components["schemas"]["com.beat.domain.booking.application.dto.TicketDetail"][]; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.TicketRetrieveResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.booking.application.dto.TicketRetrieveResponse"]; + }; + "com.beat.domain.schedule.application.dto.TicketAvailabilityResponse": { + /** Format: int64 */ + scheduleId?: number; + scheduleNumber?: string; + /** Format: int32 */ + totalTicketCount?: number; + /** Format: int32 */ + soldTicketCount?: number; + /** Format: int32 */ + availableTicketCount?: number; + /** Format: int32 */ + requestedTicketCount?: number; + isAvailable?: boolean; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.schedule.application.dto.TicketAvailabilityResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.schedule.application.dto.TicketAvailabilityResponse"]; + }; + "com.beat.domain.performance.application.dto.modify.PerformanceModifyDetailResponse": { + /** Format: int64 */ + userId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** @enum {string} */ + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + /** Format: int32 */ + runningTime?: number; + performanceDescription?: string; + performanceAttentionNote?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + posterImage?: string; + performanceTeamName?: string; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceContact?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + totalScheduleCount?: number; + isBookerExist?: boolean; + scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.create.ScheduleResponse"][]; + castList?: components["schemas"]["com.beat.domain.performance.application.dto.create.CastResponse"][]; + staffList?: components["schemas"]["com.beat.domain.performance.application.dto.create.StaffResponse"][]; + performanceImageList?: components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceImageResponse"][]; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.modify.PerformanceModifyDetailResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.performance.application.dto.modify.PerformanceModifyDetailResponse"]; + }; + "com.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceDetailResponse": { + /** Format: int64 */ + performanceId?: number; + genre?: string; + performanceTitle?: string; + posterImage?: string; + performancePeriod?: string; + /** Format: int32 */ + minDueDate?: number; + }; + "com.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceResponse": { + /** Format: int64 */ + userId?: number; + performances?: components["schemas"]["com.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceDetailResponse"][]; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceResponse"]; + }; + "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailCastResponse": { + /** Format: int64 */ + castId?: number; + castName?: string; + castRole?: string; + castPhoto?: string; + }; + "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailImageResponse": { + /** Format: int64 */ + performanceImageId?: number; + performanceImage?: string; + }; + "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailResponse": { + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + performancePeriod?: string; + scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailScheduleResponse"][]; + /** Format: int32 */ + ticketPrice?: number; + genre?: string; + posterImage?: string; + /** Format: int32 */ + runningTime?: number; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceDescription?: string; + performanceAttentionNote?: string; + performanceContact?: string; + performanceTeamName?: string; + castList?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailCastResponse"][]; + staffList?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailStaffResponse"][]; + /** Format: int32 */ + minDueDate?: number; + performanceImageList?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailImageResponse"][]; + }; + "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailScheduleResponse": { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + scheduleNumber?: string; + /** Format: int32 */ + dueDate?: number; + isBooking?: boolean; + }; + "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailStaffResponse": { + /** Format: int64 */ + staffId?: number; + staffName?: string; + staffRole?: string; + staffPhoto?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailResponse"]; + }; + "com.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailResponse": { + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + performancePeriod?: string; + scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailScheduleResponse"][]; + /** Format: int32 */ + ticketPrice?: number; + genre?: string; + posterImage?: string; + performanceVenue?: string; + performanceTeamName?: string; + bankName?: string; + accountNumber?: string; + accountHolder?: string; + }; + "com.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailScheduleResponse": { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + scheduleNumber?: string; + /** Format: int32 */ + availableTicketCount?: number; + isBooking?: boolean; + /** Format: int32 */ + dueDate?: number; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailResponse"]; + }; + "com.beat.domain.performance.application.dto.home.HomeFindAllResponse": { + promotionList?: components["schemas"]["com.beat.domain.performance.application.dto.home.HomePromotionDetail"][]; + performanceList?: components["schemas"]["com.beat.domain.performance.application.dto.home.HomePerformanceDetail"][]; + }; + "com.beat.domain.performance.application.dto.home.HomePerformanceDetail": { + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + dueDate?: number; + genre?: string; + posterImage?: string; + performanceVenue?: string; + }; + "com.beat.domain.performance.application.dto.home.HomePromotionDetail": { + /** Format: int64 */ + promotionId?: number; + promotionPhoto?: string; + /** Format: int64 */ + performanceId?: number; + redirectUrl?: string; + isExternal?: boolean; + /** @enum {string} */ + carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.home.HomeFindAllResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.performance.application.dto.home.HomeFindAllResponse"]; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.global.external.s3.application.dto.PerformanceMakerPresignedUrlFindAllResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.global.external.s3.application.dto.PerformanceMakerPresignedUrlFindAllResponse"]; + }; + "com.beat.global.external.s3.application.dto.PerformanceMakerPresignedUrlFindAllResponse": { + performanceMakerPresignedUrls?: { + [key: string]: { + [key: string]: string; + }; + }; + }; + "com.beat.domain.booking.application.dto.MemberBookingRetrieveResponse": { + /** Format: int64 */ + userId?: number; + /** Format: int64 */ + bookingId?: number; + /** Format: int64 */ + scheduleId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** Format: date-time */ + performanceDate?: string; + performanceVenue?: string; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + performanceContact?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + /** Format: int32 */ + dueDate?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** Format: date-time */ + createdAt?: string; + posterImage?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + }; + "com.beat.global.common.dto.SuccessResponseJava.util.ListCom.beat.domain.booking.application.dto.MemberBookingRetrieveResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.domain.booking.application.dto.MemberBookingRetrieveResponse"][]; + }; + "com.beat.admin.application.dto.response.UserFindAllResponse": { + users?: components["schemas"]["com.beat.admin.application.dto.response.UserFindAllResponse$UserFindResponse"][]; + }; + "com.beat.admin.application.dto.response.UserFindAllResponse$UserFindResponse": { + /** Format: int64 */ + id?: number; + role?: string; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.admin.application.dto.response.UserFindAllResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.admin.application.dto.response.UserFindAllResponse"]; + }; + "com.beat.admin.application.dto.response.CarouselFindAllResponse": { + carousels?: components["schemas"]["com.beat.admin.application.dto.response.CarouselFindAllResponse$CarouselFindResponse"][]; + }; + "com.beat.admin.application.dto.response.CarouselFindAllResponse$CarouselFindResponse": { + /** Format: int64 */ + promotionId?: number; + /** @enum {string} */ + carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; + newImageUrl?: string; + isExternal?: boolean; + redirectUrl?: string; + /** Format: int64 */ + performanceId?: number; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.admin.application.dto.response.CarouselFindAllResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.admin.application.dto.response.CarouselFindAllResponse"]; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.global.external.s3.application.dto.CarouselPresignedUrlFindAllResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.global.external.s3.application.dto.CarouselPresignedUrlFindAllResponse"]; + }; + "com.beat.global.external.s3.application.dto.CarouselPresignedUrlFindAllResponse": { + carouselPresignedUrls?: { + [key: string]: string; + }; + }; + "com.beat.global.common.dto.SuccessResponseCom.beat.global.external.s3.application.dto.BannerPresignedUrlFindResponse": { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["com.beat.global.external.s3.application.dto.BannerPresignedUrlFindResponse"]; + }; + "com.beat.global.external.s3.application.dto.BannerPresignedUrlFindResponse": { + bannerPresignedUrl?: string; + }; }; responses: never; parameters: never; @@ -829,7 +1489,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.lang.Void"]; }; }; /** @description 이미 결제가 완료된 티켓의 상태는 변경할 수 없습니다. */ @@ -841,7 +1501,7 @@ export interface operations { "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; - /** @description 회차 정보를 찾을 수 없습니다. */ + /** @description 공연 정보를 찾을 수 없습니다. */ 404: { headers: { [name: string]: unknown; @@ -871,7 +1531,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.lang.Void"]; }; }; /** @description 해당 예매 내역을 찾을 수 없습니다. */ @@ -904,7 +1564,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.lang.Void"]; }; }; /** @description 해당 예매 내역을 찾을 수 없습니다. */ @@ -937,10 +1597,10 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.modify.PerformanceModifyResponse"]; }; }; - /** @description 티켓 가격은 음수일 수 없습니다. */ + /** @description 예매자가 존재하여 가격을 수정할 수 없습니다. */ 400: { headers: { [name: string]: unknown; @@ -988,7 +1648,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.create.PerformanceResponse"]; }; }; /** @description 필수 데이터가 누락되었습니다. */ @@ -1026,7 +1686,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.admin.application.dto.response.CarouselFindAllResponse"]; }; }; /** @description 회원이 없습니다. */ @@ -1059,7 +1719,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.admin.application.dto.response.CarouselHandleAllResponse"]; }; }; /** @description 해당 공연 정보를 찾을 수 없습니다. */ @@ -1094,7 +1754,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.member.dto.LoginSuccessResponse"]; }; }; /** @description 로그인 요청이 유효하지 않습니다. */ @@ -1132,7 +1792,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.lang.Void"]; }; }; /** @description 회원 정보를 찾을 수 없습니다. */ @@ -1165,10 +1825,10 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.MemberBookingResponse"]; }; }; - /** @description 잘못된 요청 형식입니다. */ + /** @description 필수 데이터가 누락되었습니다. */ 400: { headers: { [name: string]: unknown; @@ -1207,7 +1867,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.GuestBookingResponse"]; }; }; /** @description 필수 데이터가 누락되었습니다. */ @@ -1219,7 +1879,7 @@ export interface operations { "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; }; }; - /** @description 회차 정보를 찾을 수 없습니다. */ + /** @description 공연 정보를 찾을 수 없습니다. */ 404: { headers: { [name: string]: unknown; @@ -1249,7 +1909,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.util.ListCom.beat.domain.booking.application.dto.GuestBookingRetrieveResponse"]; }; }; /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ @@ -1282,7 +1942,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.BookingRefundResponse"]; }; }; /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ @@ -1315,7 +1975,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.BookingCancelResponse"]; }; }; /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ @@ -1338,7 +1998,7 @@ export interface operations { }; requestBody?: never; responses: { - /** @description OK */ + /** @description 서버가 정상적으로 동작 중입니다. */ 200: { headers: { [name: string]: unknown; @@ -1366,7 +2026,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.member.dto.AccessTokenGetSuccess"]; }; }; /** @description 유효하지 않은 토큰입니다. */ @@ -1400,10 +2060,10 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.TicketRetrieveResponse"]; }; }; - /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ + /** @description 공연 정보를 찾을 수 없습니다. */ 404: { headers: { [name: string]: unknown; @@ -1435,10 +2095,10 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.TicketRetrieveResponse"]; }; }; - /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ + /** @description 공연 정보를 찾을 수 없습니다. */ 404: { headers: { [name: string]: unknown; @@ -1468,7 +2128,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.schedule.application.dto.TicketAvailabilityResponse"]; }; }; /** @description 잘못된 데이터 형식입니다. */ @@ -1517,7 +2177,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.modify.PerformanceModifyDetailResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -1548,7 +2208,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.lang.Void"]; }; }; /** @description 공연의 소유자가 아니거나 예매자가 있어 삭제할 수 없습니다. */ @@ -1586,7 +2246,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceResponse"]; }; }; /** @description 회원 정보를 찾을 수 없습니다. */ @@ -1617,7 +2277,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -1648,7 +2308,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailResponse"]; }; }; /** @description 공연 정보를 찾을 수 없습니다. */ @@ -1679,7 +2339,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.home.HomeFindAllResponse"]; }; }; }; @@ -1704,7 +2364,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.global.external.s3.application.dto.PerformanceMakerPresignedUrlFindAllResponse"]; }; }; /** @description S3 PreSigned url을 받아오기에 실패했습니다. */ @@ -1733,7 +2393,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.util.ListCom.beat.domain.booking.application.dto.MemberBookingRetrieveResponse"]; }; }; /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ @@ -1762,7 +2422,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.admin.application.dto.response.UserFindAllResponse"]; }; }; /** @description 회원이 없습니다 */ @@ -1793,7 +2453,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.global.external.s3.application.dto.CarouselPresignedUrlFindAllResponse"]; }; }; /** @description 회원이 없습니다. */ @@ -1824,7 +2484,7 @@ export interface operations { [name: string]: unknown; }; content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponse"]; + "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.global.external.s3.application.dto.BannerPresignedUrlFindResponse"]; }; }; /** @description 회원이 없습니다. */ From 3ecd6419164dc1a04648faeff442fbd6b8e84cfb Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 01:36:12 +0900 Subject: [PATCH 21/49] =?UTF-8?q?feat:=20=EC=9E=85=EA=B8=88=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20api=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/api.ts | 2 +- .../ticketholderlist/TicketHolderList.tsx | 51 ++++++++++++++++++- 2 files changed, 51 insertions(+), 2 deletions(-) diff --git a/src/apis/domains/tickets/api.ts b/src/apis/domains/tickets/api.ts index 394b8232..226d56ef 100644 --- a/src/apis/domains/tickets/api.ts +++ b/src/apis/domains/tickets/api.ts @@ -57,7 +57,7 @@ export const putTicketUpdate = async ( ): Promise<SuccessResponseVoid | null> => { try { const response: AxiosResponse<ApiResponseType<SuccessResponseVoid>> = await put( - "tickets", + "tickets/update", formData ); diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index ac14c8ed..92e7c624 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -1,6 +1,7 @@ import { useTicketPatch, useTicketRetrive, useTicketUpdate } from "@apis/domains/tickets/queries"; import Loading from "@components/commons/loading/Loading"; import MetaTag from "@components/commons/meta/MetaTag"; +import Toast from "@components/commons/toast/Toast"; import { NAVIGATION_STATE } from "@constants/navigationState"; import { useHeader, useModal, useToast } from "@hooks"; import { useEffect, useState } from "react"; @@ -71,21 +72,69 @@ const TicketHolderList = () => { { performanceId: Number(performanceId) }, filterList ); + const { showToast, isToastVisible } = useToast(); + const { openConfirm, closeConfirm } = useModal(); - // 체크된 리스트 확인 const [checkedBookingId, setCheckedBookingId] = useState<number[]>([]); + // 체크된 리스트 확인 const handleBookingIdCheck = (bookingId: number) => { setCheckedBookingId((prev) => prev.includes(bookingId) ? prev.filter((id) => id !== bookingId) : [...prev, bookingId] ); }; + const { + mutate: updateMutate, + mutateAsync: updateMutateAsync, + isPending: updateIsPending, + } = useTicketUpdate(); + + const handlePaymentFixAxiosFunc = () => { + if (updateIsPending) { + return; + } + // 예매 완료 PUT API 요청 + // paymentData에 accountHolder, accountNumber, bankName 제거 + const filteredPaymentData = paymentData.map( + ({ bankName, accountNumber, accountHolder, ...rest }) => ({ + ...rest, + bookingStatus: checkedBookingId.includes(rest.bookingId) + ? "BOOKING_CONFIRMED" + : rest.bookingStatus, + }) + ); + + updateMutate({ + performanceId: Number(performanceId), + performanceTitle: data?.performanceTitle, + totalScheduleCount: data?.totalScheduleCount, + bookingList: filteredPaymentData, + }); + closeConfirm(); + showToast(); + setTimeout(() => { + // window.location.reload(); + }, 1000); + }; + + const handlePaymentFixBtn = () => { + openConfirm({ + title: "입금 처리시 예매확정 문자가 발송돼요.", + subTitle: "예매자에게 입금이 확인되었음을 알려드릴게요!", + okText: "입금 처리하기", + noText: "아니요", + okCallback: handlePaymentFixAxiosFunc, + noCallback: closeConfirm, + }); + }; + const actions = { PAYMENT: { text: "입금 처리하기", // TODO : 예매 확정 팝업 action: () => { + handlePaymentFixBtn(); setStatus("DEFAULT"), setFilterList({ scheduleNumber: [], bookingStatus: [] }); }, }, From fd4db6241cbea85061a1ed963f2fef86b2821a42 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 02:15:46 +0900 Subject: [PATCH 22/49] =?UTF-8?q?feat:=20=ED=99=98=EB=B6=88=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20api=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/api.ts | 27 +++----- src/apis/domains/tickets/queries.ts | 9 +-- src/assets/svgs/index.ts | 68 ------------------- src/assets/svgs/index.tsx | 6 +- .../ticketholderlist/TicketHolderList.tsx | 67 ++++++++++++++++-- 5 files changed, 81 insertions(+), 96 deletions(-) delete mode 100644 src/assets/svgs/index.ts diff --git a/src/apis/domains/tickets/api.ts b/src/apis/domains/tickets/api.ts index 226d56ef..1590cc38 100644 --- a/src/apis/domains/tickets/api.ts +++ b/src/apis/domains/tickets/api.ts @@ -37,17 +37,11 @@ export const getTicketRetrieve = async ( } }; +type SuccessResponseVoid = components["schemas"]["SuccessResponseVoid"]; + // 예매자 입급 여부 수정 API (PUT) -/* -export interface putTicketReq { - performanceId: number; - performanceTitle: string; - totalScheduleCoun: number; - bookingList: BookingListProps[]; -} -*/ + export type TicketUpdateRequest = components["schemas"]["TicketUpdateRequest"]; -type SuccessResponseVoid = components["schemas"]["SuccessResponseVoid"]; //async 함수는 항상 promise로 감싸서 값을 리턴한다. //즉, 비동기 함수의 값을 사용하려면 추후 await이나 then 을 사용해야 한다던데.. @@ -68,18 +62,19 @@ export const putTicketUpdate = async ( } }; -// 예매자 취소 API (PATCH) -//이거 타입 잘못되었을 수도..? bookingList 가 number를 담은 배열로 되어 있는데, 실제로는 아니었음 -//export type TicketDeleteRequest = components["schemas"]["TicketDeleteRequest"]; +// 예매자 환불처리 (PUT) + +export type TicketRefundRequest = components["schemas"]["TicketRefundRequest"]; -export const patchTicketCancel = async ( - formData: PatchFormDataProps +export const putTicketRefund = async ( + formData: TicketRefundRequest ): Promise<SuccessResponseVoid | null> => { try { - const response: AxiosResponse<ApiResponseType<SuccessResponseVoid>> = await patch( - "tickets", + const response: AxiosResponse<ApiResponseType<SuccessResponseVoid>> = await put( + "tickets/refund", formData ); + return response.data.data; } catch (error) { console.log("error", error); diff --git a/src/apis/domains/tickets/queries.ts b/src/apis/domains/tickets/queries.ts index 51c1538f..1fbb3c29 100644 --- a/src/apis/domains/tickets/queries.ts +++ b/src/apis/domains/tickets/queries.ts @@ -3,8 +3,9 @@ import { PatchFormDataProps } from "@typings/deleteBookerFormatProps"; import { getTicketReq, getTicketRetrieve, - patchTicketCancel, + putTicketRefund, putTicketUpdate, + TicketRefundRequest, TicketUpdateRequest, } from "./api"; @@ -37,12 +38,12 @@ export const useTicketUpdate = () => { }); }; -// 예매자를 취소하는 API (PATCH)를 위한 쿼리 작성 -export const useTicketPatch = () => { +// 예매자 환불 여부 수정 API (PUT)를 위한 쿼리 작성 +export const useTicketRefund = () => { const queryClient = new QueryClient(); return useMutation({ - mutationFn: (formData: PatchFormDataProps) => patchTicketCancel(formData), + mutationFn: (formData: TicketRefundRequest) => putTicketRefund(formData), onSuccess: (res) => { queryClient.invalidateQueries({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST] }); queryClient.refetchQueries({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST] }); diff --git a/src/assets/svgs/index.ts b/src/assets/svgs/index.ts deleted file mode 100644 index d986239c..00000000 --- a/src/assets/svgs/index.ts +++ /dev/null @@ -1,68 +0,0 @@ -export { default as BannerBasic } from "./BannerBasic"; -export { default as BeatMapMarker } from "./BeatMapMarker"; -export { default as BtnFloating } from "./BtnFloating"; -export { default as BtnModalDelete } from "./BtnModalDelete"; -export { default as ButtonDelete24 } from "./ButtonDelete24"; -export { default as CarouselPartInactive } from "./CarouselPartInactive"; -export { default as Empty } from "./Empty"; -export { default as IcomCopy } from "./IcomCopy"; -export { default as IconArrowLeft } from "./IconArrowLeft"; -export { default as IconArrowRight } from "./IconArrowRight"; -export { default as IconArrowDown } from "./IconArrowDown"; -export { default as IconArrowUp } from "./IconArrowUp"; -export { default as IconBnk } from "./IconBnk"; -export { default as IconCalendar } from "./IconCalendar"; -export { default as IconCamera } from "./IconCamera"; -export { default as IconCheckboxDisabledOn } from "./IconCheckboxDisabledOn"; -export { default as IconCheckboxSelectedOn } from "./IconCheckboxSelectedOn"; -export { default as IconCheckboxUnselectedOn } from "./IconCheckboxUnselectedOn"; -export { default as IconChecked } from "./IconChecked"; -export { default as IconCheck } from "./IconCheck"; -export { default as IconChevronBack } from "./IconChevronBack"; -export { default as IconEmpty } from "./IconEmpty"; -export { default as IconEyeOff } from "./IconEyeOff"; -export { default as IconEyeOn } from "./IconEyeOn"; -export { default as IconFooterLogo } from "./IconFooterLogo"; -export { default as IconHanna } from "./IconHanna"; -export { default as IconIbk } from "./IconIbk"; -export { default as IconIm } from "./IconIm"; -export { default as IconImg } from "./IconImg"; -export { default as IconKabank } from "./IconKabank"; -export { default as IconKb } from "./IconKb"; -export { default as IconLargeBand } from "./IconLargeBand"; -export { default as IconLargeDance } from "./IconLargeDance"; -export { default as IconLargeEtc } from "./IconLargeEtc"; -export { default as IconLargeMusical } from "./IconLargeMusical"; -export { default as IconLogo } from "./IconLogo"; -export { default as IconMinus } from "./IconMinus"; -export { default as IconNonghyup } from "./IconNonghyup"; -export { default as IconPhotoDelete } from "./IconPhotoDelete"; -export { default as IconPlus } from "./IconPlus"; -export { default as IconProfile } from "./IconProfile"; -export { default as IconRoleAdd } from "./IconRoleAdd"; -export { default as IconSaemauel } from "./IconSaemauel"; -export { default as IconSc } from "./IconSc"; -export { default as IconSearch } from "./IconSearch"; -export { default as IconShinhan } from "./IconShinhan"; -export { default as IconShinhyup } from "./IconShinhyup"; -export { default as IconSmallBand } from "./IconSmallBand"; -export { default as IconSmallDance } from "./IconSmallDance"; -export { default as IconSmallEtc } from "./IconSmallEtc"; -export { default as IconSmallMusical } from "./IconSmallMusical"; -export { default as IconSoohyup } from "./IconSoohyup"; -export { default as IconTextfiedlDelete } from "./IconTextfiedlDelete"; -export { default as IconTime } from "./IconTime"; -export { default as IconToggleOff } from "./IconToggleOff"; -export { default as IconToggleOn } from "./IconToggleOn"; -export { default as IconToss } from "./IconToss"; -export { default as IconWoochaegook } from "./IconWoochaegook"; -export { default as IconWoori } from "./IconWoori"; -export { default as IconXButton } from "./IconXButton"; -export { default as IcDelete } from "./IcDelete"; -export { default as IcHamburgar } from "./IcHamburgar"; -export { default as IcOutlinePlace } from "./IcOutlinePlace"; -export { default as KakaoMapArrow } from "./KakaoMapArrow"; -export { default as NotFoundAsset } from "./NotFoundAsset"; -export { default as Subtract } from "./Subtract"; -export { default as Switch } from "./Switch"; -export { default as Union } from "./Union"; diff --git a/src/assets/svgs/index.tsx b/src/assets/svgs/index.tsx index a9e4be0a..b926ac37 100644 --- a/src/assets/svgs/index.tsx +++ b/src/assets/svgs/index.tsx @@ -1,4 +1,6 @@ export { default as BannerBasic } from "./BannerBasic"; +export { default as BeatMapMarker } from "./BeatMapMarker"; +export { default as BtnFilter } from "./BtnFilter"; export { default as BtnFloating } from "./BtnFloating"; export { default as BtnModalDelete } from "./BtnModalDelete"; export { default as ButtonDelete24 } from "./ButtonDelete24"; @@ -60,10 +62,10 @@ export { default as IconWoochaegook } from "./IconWoochaegook"; export { default as IconWoori } from "./IconWoori"; export { default as IconXButton } from "./IconXButton"; export { default as IcOutlinePlace } from "./IcOutlinePlace"; -export { default as KakaoMapArrow } from "./KakaoMapArrow"; export { default as IcRefresh } from "./IcRefresh"; +export { default as KakaoMapArrow } from "./KakaoMapArrow"; export { default as NotFoundAsset } from "./NotFoundAsset"; export { default as SelectionControlCheckboxSelectedOff } from "./SelectionControlCheckboxSelectedOff"; export { default as Subtract } from "./Subtract"; export { default as Switch } from "./Switch"; -export { default as Union } from "./Union"; +export { default as Union } from "./Union"; \ No newline at end of file diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 92e7c624..7dd86c7a 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -1,4 +1,9 @@ -import { useTicketPatch, useTicketRetrive, useTicketUpdate } from "@apis/domains/tickets/queries"; +import { + useTicketPatch, + useTicketRefund, + useTicketRetrive, + useTicketUpdate, +} from "@apis/domains/tickets/queries"; import Loading from "@components/commons/loading/Loading"; import MetaTag from "@components/commons/meta/MetaTag"; import Toast from "@components/commons/toast/Toast"; @@ -114,7 +119,7 @@ const TicketHolderList = () => { closeConfirm(); showToast(); setTimeout(() => { - // window.location.reload(); + window.location.reload(); }, 1000); }; @@ -124,25 +129,75 @@ const TicketHolderList = () => { subTitle: "예매자에게 입금이 확인되었음을 알려드릴게요!", okText: "입금 처리하기", noText: "아니요", - okCallback: handlePaymentFixAxiosFunc, + okCallback: () => { + handlePaymentFixAxiosFunc(); + // 혹시 테스트 과정에서 로그 확인을 위해 새로고침을 지운다면 아래 주석 해제 + // setStatus("DEFAULT"); + // setFilterList({ scheduleNumber: [], bookingStatus: [] }); + // setCheckedBookingId([]); + }, noCallback: closeConfirm, }); }; + // 환불 요청 + + const { + mutate: refundMutate, + mutateAsync: refundMutateAsync, + isPending: refundIsPending, + } = useTicketRefund(); + + const handlePaymentRefundBtn = () => { + openConfirm({ + title: "환불 처리 하시겠어요?", + subTitle: "예매자에게 환불 금액을 보낸 뒤 처리해 주세요.", + okText: "환불 처리하기", + noText: "아니요", + okCallback: () => { + handlePaymentRefundAxiosFunc(); + // 혹시 테스트 과정에서 로그 확인을 위해 새로고침을 지운다면 아래 주석 해제 + // setStatus("DEFAULT"); + // setFilterList({ scheduleNumber: [], bookingStatus: [] }); + // setCheckedBookingId([]); + }, + noCallback: closeConfirm, + }); + }; + + const handlePaymentRefundAxiosFunc = () => { + if (refundIsPending) { + return; + } + // 환불 요청 PUT API 요청 + // bookingId만 전달 + const filteredPaymentData = paymentData.map(({ bookingId }) => ({ + bookingId: checkedBookingId.includes(bookingId) && bookingId, + })); + + refundMutate({ + performanceId: Number(performanceId), + bookingList: filteredPaymentData, + }); + closeConfirm(); + showToast(); + setTimeout(() => { + window.location.reload(); + }, 1000); + }; + const actions = { PAYMENT: { text: "입금 처리하기", - // TODO : 예매 확정 팝업 action: () => { handlePaymentFixBtn(); - setStatus("DEFAULT"), setFilterList({ scheduleNumber: [], bookingStatus: [] }); }, }, REFUND: { text: "환불 처리하기", // TODO : 환불 처리 팝업 action: () => { - setStatus("DEFAULT"), setFilterList({ scheduleNumber: [], bookingStatus: [] }); + handlePaymentRefundBtn(); }, }, DELETE: { From cf84c44afc60bd4f7cf05ae928e38761ae164dd3 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 02:39:22 +0900 Subject: [PATCH 23/49] =?UTF-8?q?feat:=20=EC=B7=A8=EC=86=8C=20=EC=B2=98?= =?UTF-8?q?=EB=A6=AC=20api=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/api.ts | 20 ++++++++ src/apis/domains/tickets/queries.ts | 15 ++++++ .../ticketholderlist/TicketHolderList.tsx | 51 +++++++++++++++++-- 3 files changed, 82 insertions(+), 4 deletions(-) diff --git a/src/apis/domains/tickets/api.ts b/src/apis/domains/tickets/api.ts index 1590cc38..8cbb1f14 100644 --- a/src/apis/domains/tickets/api.ts +++ b/src/apis/domains/tickets/api.ts @@ -81,3 +81,23 @@ export const putTicketRefund = async ( return null; } }; + +// 예매자 삭제 (PUT) + +export type TicketDeleteRequest = components["schemas"]["TicketDeleteRequest"]; + +export const putTicketDelete = async ( + formData: TicketDeleteRequest +): Promise<SuccessResponseVoid | null> => { + try { + const response: AxiosResponse<ApiResponseType<SuccessResponseVoid>> = await put( + "tickets/delete", + formData + ); + + return response.data.data; + } catch (error) { + console.log("error", error); + return null; + } +}; diff --git a/src/apis/domains/tickets/queries.ts b/src/apis/domains/tickets/queries.ts index 1fbb3c29..3a26f50e 100644 --- a/src/apis/domains/tickets/queries.ts +++ b/src/apis/domains/tickets/queries.ts @@ -3,8 +3,10 @@ import { PatchFormDataProps } from "@typings/deleteBookerFormatProps"; import { getTicketReq, getTicketRetrieve, + putTicketDelete, putTicketRefund, putTicketUpdate, + TicketDeleteRequest, TicketRefundRequest, TicketUpdateRequest, } from "./api"; @@ -50,3 +52,16 @@ export const useTicketRefund = () => { }, }); }; + +// 예매자 삭제 여부 수정 API (PUT)를 위한 쿼리 작성 +export const useTicketDelete = () => { + const queryClient = new QueryClient(); + + return useMutation({ + mutationFn: (formData: TicketDeleteRequest) => putTicketDelete(formData), + onSuccess: (res) => { + queryClient.invalidateQueries({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST] }); + queryClient.refetchQueries({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST] }); + }, + }); +}; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 7dd86c7a..91c0c94c 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -1,4 +1,5 @@ import { + useTicketDelete, useTicketPatch, useTicketRefund, useTicketRetrive, @@ -141,7 +142,6 @@ const TicketHolderList = () => { }; // 환불 요청 - const { mutate: refundMutate, mutateAsync: refundMutateAsync, @@ -186,6 +186,51 @@ const TicketHolderList = () => { }, 1000); }; + // 취소 요청 + const { + mutate: deleteMutate, + mutateAsync: deleteMutateAsync, + isPending: deleteIsPending, + } = useTicketDelete(); + + const handlePaymentDeleteBtn = () => { + openConfirm({ + title: "예매자를 삭제하시겠어요?", + subTitle: "한 번 삭제한 예매자 정보는 다시 복구할 수 없어요.", + okText: "삭제하기", + noText: "아니요", + okCallback: () => { + handlePaymentDeleteAxiosFunc(); + // 혹시 테스트 과정에서 로그 확인을 위해 새로고침을 지운다면 아래 주석 해제 + // setStatus("DEFAULT"); + // setFilterList({ scheduleNumber: [], bookingStatus: [] }); + // setCheckedBookingId([]); + }, + noCallback: closeConfirm, + }); + }; + + const handlePaymentDeleteAxiosFunc = () => { + if (deleteIsPending) { + return; + } + // 취소 요청 PUT API 요청 + // bookingId만 전달 + const filteredPaymentData = paymentData.map(({ bookingId }) => ({ + bookingId: checkedBookingId.includes(bookingId) && bookingId, + })); + + deleteMutate({ + performanceId: Number(performanceId), + bookingList: filteredPaymentData, + }); + closeConfirm(); + showToast(); + setTimeout(() => { + window.location.reload(); + }, 1000); + }; + const actions = { PAYMENT: { text: "입금 처리하기", @@ -195,16 +240,14 @@ const TicketHolderList = () => { }, REFUND: { text: "환불 처리하기", - // TODO : 환불 처리 팝업 action: () => { handlePaymentRefundBtn(); }, }, DELETE: { text: "예매자 삭제하기", - // TODO : 예매자 삭제 팝업 action: () => { - setStatus("DEFAULT"), setFilterList({ scheduleNumber: [], bookingStatus: [] }); + handlePaymentDeleteBtn(); }, }, DEFAULT: { From 0ce87b02cff6297cef4a65c7d141c90018aa0b95 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 03:17:51 +0900 Subject: [PATCH 24/49] =?UTF-8?q?feat:=20=ED=99=98=EB=B6=88=20=EA=B3=84?= =?UTF-8?q?=EC=A2=8C=20=EB=B3=B5=EC=82=AC=20=EA=B8=B0=EB=8A=A5=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ticketholderlist/TicketHolderList.tsx | 22 +++++++++++++------ .../components/manageCard/ManageAccount.tsx | 16 +++++++++----- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 91c0c94c..21fb1606 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -7,9 +7,8 @@ import { } from "@apis/domains/tickets/queries"; import Loading from "@components/commons/loading/Loading"; import MetaTag from "@components/commons/meta/MetaTag"; -import Toast from "@components/commons/toast/Toast"; import { NAVIGATION_STATE } from "@constants/navigationState"; -import { useHeader, useModal, useToast } from "@hooks"; +import { useHeader, useModal } from "@hooks"; import { useEffect, useState } from "react"; import { CSVLink } from "react-csv"; import { useNavigate, useParams } from "react-router-dom"; @@ -25,6 +24,9 @@ import { ManageCard } from "./components/manageCard"; import { getBankNameKr } from "@utils/getBankName"; import SelectedChips from "./components/selectedChips/SelectedChips"; import { convertingBookingStatus } from "@constants/convertingBookingStatus"; +import { IconCheck } from "@assets/svgs"; +import Toast from "@components/commons/toast/Toast"; +import { useToast } from "@hooks"; export type PaymentType = | "CHECKING_PAYMENT" @@ -78,11 +80,10 @@ const TicketHolderList = () => { { performanceId: Number(performanceId) }, filterList ); - const { showToast, isToastVisible } = useToast(); const { openConfirm, closeConfirm } = useModal(); const [checkedBookingId, setCheckedBookingId] = useState<number[]>([]); - + const { showToast, isToastVisible } = useToast(); // 체크된 리스트 확인 const handleBookingIdCheck = (bookingId: number) => { setCheckedBookingId((prev) => @@ -118,7 +119,6 @@ const TicketHolderList = () => { bookingList: filteredPaymentData, }); closeConfirm(); - showToast(); setTimeout(() => { window.location.reload(); }, 1000); @@ -180,7 +180,6 @@ const TicketHolderList = () => { bookingList: filteredPaymentData, }); closeConfirm(); - showToast(); setTimeout(() => { window.location.reload(); }, 1000); @@ -225,7 +224,6 @@ const TicketHolderList = () => { bookingList: filteredPaymentData, }); closeConfirm(); - showToast(); setTimeout(() => { window.location.reload(); }, 1000); @@ -381,6 +379,12 @@ const TicketHolderList = () => { }); }, [setHeader]); + const handleCopyClipBoard = (text: string) => { + navigator.clipboard.writeText(text); + + showToast(); + }; + return ( <> <MetaTag title="예매자 확인 및 상태변경" /> @@ -440,6 +444,7 @@ const TicketHolderList = () => { bankName={getBankNameKr(item.bankName)} accountNumber={item.accountNumber} accountHolder={item.accountHolder} + handleCopyClipBoard={handleCopyClipBoard} /> )} </ManageCard> @@ -464,6 +469,9 @@ const TicketHolderList = () => { handleFilter(scheduleNumber, bookingStatus) } /> + <Toast icon={<IconCheck />} isVisible={isToastVisible} toastBottom={30}> + 클립보드에 복사되었습니다! + </Toast> </S.TicketHolderListWrpper> </> )} diff --git a/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx b/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx index 5cf2188e..617652aa 100644 --- a/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx +++ b/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx @@ -1,21 +1,27 @@ import * as S from "./ManageAccount.styled"; +import { IconCheck } from "@assets/svgs"; +import Toast from "@components/commons/toast/Toast"; +import { useToast } from "@hooks"; interface ManageAccountProps { bankName: string; accountNumber: string; accountHolder: string; + handleCopyClipBoard: (number) => void; } export default function ManageAccount({ bankName, accountNumber, accountHolder, + handleCopyClipBoard, }: ManageAccountProps) { return ( - // TODO : 클릭 시 계좌번호 복사 기능 추가 - <S.ManageAccountWrapper> - {bankName} ({accountHolder}) {accountNumber} - <S.CopyIcon /> - </S.ManageAccountWrapper> + <> + <S.ManageAccountWrapper onClick={() => handleCopyClipBoard(accountNumber)}> + {bankName} ({accountHolder}) {accountNumber} + <S.CopyIcon /> + </S.ManageAccountWrapper> + </> ); } From a0be558621cd64147a1886cd4da802b629a5ec25 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 03:43:27 +0900 Subject: [PATCH 25/49] =?UTF-8?q?fix:=20react-query=20=EA=B4=80=EB=A0=A8?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/queries.ts | 2 -- src/pages/ticketholderlist/TicketHolderList.tsx | 14 +------------- .../components/manageCard/ManageAccount.tsx | 3 --- 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/src/apis/domains/tickets/queries.ts b/src/apis/domains/tickets/queries.ts index 3a26f50e..75b94493 100644 --- a/src/apis/domains/tickets/queries.ts +++ b/src/apis/domains/tickets/queries.ts @@ -1,5 +1,4 @@ import { QueryClient, useMutation, useQuery } from "@tanstack/react-query"; -import { PatchFormDataProps } from "@typings/deleteBookerFormatProps"; import { getTicketReq, getTicketRetrieve, @@ -22,7 +21,6 @@ export const useTicketRetrive = (formData: getTicketReq, filterList) => { return useQuery({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST], queryFn: () => getTicketRetrieve(formData, filterList), - // staleTime: 1000 * 60 * 60, gcTime: 1000 * 60 * 60 * 24, }); }; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 21fb1606..df4e3420 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -132,10 +132,6 @@ const TicketHolderList = () => { noText: "아니요", okCallback: () => { handlePaymentFixAxiosFunc(); - // 혹시 테스트 과정에서 로그 확인을 위해 새로고침을 지운다면 아래 주석 해제 - // setStatus("DEFAULT"); - // setFilterList({ scheduleNumber: [], bookingStatus: [] }); - // setCheckedBookingId([]); }, noCallback: closeConfirm, }); @@ -156,10 +152,6 @@ const TicketHolderList = () => { noText: "아니요", okCallback: () => { handlePaymentRefundAxiosFunc(); - // 혹시 테스트 과정에서 로그 확인을 위해 새로고침을 지운다면 아래 주석 해제 - // setStatus("DEFAULT"); - // setFilterList({ scheduleNumber: [], bookingStatus: [] }); - // setCheckedBookingId([]); }, noCallback: closeConfirm, }); @@ -200,10 +192,6 @@ const TicketHolderList = () => { noText: "아니요", okCallback: () => { handlePaymentDeleteAxiosFunc(); - // 혹시 테스트 과정에서 로그 확인을 위해 새로고침을 지운다면 아래 주석 해제 - // setStatus("DEFAULT"); - // setFilterList({ scheduleNumber: [], bookingStatus: [] }); - // setCheckedBookingId([]); }, noCallback: closeConfirm, }); @@ -415,7 +403,7 @@ const TicketHolderList = () => { </S.TitleSticky> <S.ManageCardList> - {paymentData.map((item) => { + {paymentData?.map((item) => { const date = item.createdAt.split("T")[0]; const formattedDate = `${date.replace(/-/g, ". ")}`; const bookingStatus = convertingBookingStatus(item.bookingStatus as PaymentType); diff --git a/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx b/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx index 617652aa..eb6b4b9f 100644 --- a/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx +++ b/src/pages/ticketholderlist/components/manageCard/ManageAccount.tsx @@ -1,7 +1,4 @@ import * as S from "./ManageAccount.styled"; -import { IconCheck } from "@assets/svgs"; -import Toast from "@components/commons/toast/Toast"; -import { useToast } from "@hooks"; interface ManageAccountProps { bankName: string; From 0ea1d5011f432f6cc2e3ccfcef0ba1007db71093 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 04:29:15 +0900 Subject: [PATCH 26/49] =?UTF-8?q?feat:=20=EC=98=88=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EA=B2=80=EC=83=89=20api=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/api.ts | 24 +++++++++ src/apis/domains/tickets/queries.ts | 11 ++++ .../ticketholderlist/TicketHolderList.tsx | 50 ++++++++++++------- .../components/searchBar/SearchBar.tsx | 16 +++++- 4 files changed, 80 insertions(+), 21 deletions(-) diff --git a/src/apis/domains/tickets/api.ts b/src/apis/domains/tickets/api.ts index 8cbb1f14..9143aaaa 100644 --- a/src/apis/domains/tickets/api.ts +++ b/src/apis/domains/tickets/api.ts @@ -37,6 +37,30 @@ export const getTicketRetrieve = async ( } }; +export const getTicketRetrieveSearch = async ( + formData: getTicketReq, + searchWord, + filterList +): Promise<TicketRetrieveResponse | null> => { + try { + const params = new URLSearchParams(); + params.append("searchWord", searchWord); + filterList.scheduleNumber.map((item) => + params.append("scheduleNumber", convertingScheduleNumber(item)) + ); + filterList.bookingStatus.map((item) => params.append("bookingStatus", item)); + + const response: AxiosResponse<ApiResponseType<TicketRetrieveResponse>> = await get( + `tickets/search/${formData.performanceId}?${params.toString()}` + ); + + return response.data.data; + } catch (error) { + console.log("error", error); + return null; + } +}; + type SuccessResponseVoid = components["schemas"]["SuccessResponseVoid"]; // 예매자 입급 여부 수정 API (PUT) diff --git a/src/apis/domains/tickets/queries.ts b/src/apis/domains/tickets/queries.ts index 75b94493..628234b8 100644 --- a/src/apis/domains/tickets/queries.ts +++ b/src/apis/domains/tickets/queries.ts @@ -2,6 +2,7 @@ import { QueryClient, useMutation, useQuery } from "@tanstack/react-query"; import { getTicketReq, getTicketRetrieve, + getTicketRetrieveSearch, putTicketDelete, putTicketRefund, putTicketUpdate, @@ -25,6 +26,16 @@ export const useTicketRetrive = (formData: getTicketReq, filterList) => { }); }; +// 예매자 목록 검색 API (GET)를 위한 쿼리 작성 + +export const useTicketRetriveSearch = (formData: getTicketReq, searchWord, filterList) => { + return useQuery({ + queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST], + queryFn: () => getTicketRetrieveSearch(formData, searchWord, filterList), + gcTime: 1000 * 60 * 60 * 24, + }); +}; + // 예매자 입급 여부 수정 API (PUT)를 위한 쿼리 작성 export const useTicketUpdate = () => { const queryClient = new QueryClient(); diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index df4e3420..4c2f5ac8 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -1,14 +1,15 @@ import { useTicketDelete, - useTicketPatch, useTicketRefund, useTicketRetrive, + useTicketRetriveSearch, useTicketUpdate, } from "@apis/domains/tickets/queries"; import Loading from "@components/commons/loading/Loading"; import MetaTag from "@components/commons/meta/MetaTag"; import { NAVIGATION_STATE } from "@constants/navigationState"; import { useHeader, useModal } from "@hooks"; +import useDebounce from "src/hooks/useDebounce"; import { useEffect, useState } from "react"; import { CSVLink } from "react-csv"; import { useNavigate, useParams } from "react-router-dom"; @@ -68,6 +69,7 @@ const TicketHolderList = () => { scheduleNumber: [], bookingStatus: [], }); + const [searchWord, setSearchWord] = useState(""); const [openFilter, setOpenFilter] = useState(false); const [openMenu, setOpenMenu] = useState(false); @@ -80,6 +82,11 @@ const TicketHolderList = () => { { performanceId: Number(performanceId) }, filterList ); + const { data: searchData, refetch: searchRefetch } = useTicketRetriveSearch( + { performanceId: Number(performanceId) }, + searchWord, + filterList + ); const { openConfirm, closeConfirm } = useModal(); const [checkedBookingId, setCheckedBookingId] = useState<number[]>([]); @@ -91,11 +98,7 @@ const TicketHolderList = () => { ); }; - const { - mutate: updateMutate, - mutateAsync: updateMutateAsync, - isPending: updateIsPending, - } = useTicketUpdate(); + const { mutate: updateMutate, isPending: updateIsPending } = useTicketUpdate(); const handlePaymentFixAxiosFunc = () => { if (updateIsPending) { @@ -138,11 +141,7 @@ const TicketHolderList = () => { }; // 환불 요청 - const { - mutate: refundMutate, - mutateAsync: refundMutateAsync, - isPending: refundIsPending, - } = useTicketRefund(); + const { mutate: refundMutate, isPending: refundIsPending } = useTicketRefund(); const handlePaymentRefundBtn = () => { openConfirm({ @@ -178,11 +177,7 @@ const TicketHolderList = () => { }; // 취소 요청 - const { - mutate: deleteMutate, - mutateAsync: deleteMutateAsync, - isPending: deleteIsPending, - } = useTicketDelete(); + const { mutate: deleteMutate, isPending: deleteIsPending } = useTicketDelete(); const handlePaymentDeleteBtn = () => { openConfirm({ @@ -304,15 +299,27 @@ const TicketHolderList = () => { }); }; + const debouncedQuery = useDebounce(searchWord, 500); + + const handleInputChange = (event) => { + setSearchWord(event.target.value); + }; + // 필터 변경될 때마다 GET API 요청 + // 검색될 때마다 GET API 요청 useEffect(() => { const fetchData = async () => { const refetchData = await refetch(); setPaymentData(refetchData?.data?.bookingList ?? []); }; - fetchData(); - }, [filterList, status]); + const fetchSearchData = async () => { + const refetchSearchData = await searchRefetch(); + setPaymentData(refetchSearchData?.data?.bookingList ?? []); + }; + + searchWord ? fetchSearchData() : fetchData(); + }, [filterList, status, debouncedQuery]); useEffect(() => { setPaymentData(data?.bookingList ?? []); @@ -389,7 +396,12 @@ const TicketHolderList = () => { totalCount={data?.totalPerformanceTicketCount} /> <Spacing marginBottom={"2.6"} /> - <SearchBar handleFilterSheet={handleFilterSheet} status={status} /> + <SearchBar + handleFilterSheet={handleFilterSheet} + handleInputChange={handleInputChange} + searchWord={searchWord} + status={status} + /> {status === "DEFAULT" && ( <SelectedChips filterList={filterList} diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index 6b7bcc30..e397dc22 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -3,14 +3,26 @@ import * as S from "./SearchBar.styled"; interface SearchBarProps { status: string; + searchWord: string; handleFilterSheet: () => void; + handleInputChange: () => void; } // TODO: 필터 적용되었을 때 아웃라인 색상 적용 -> 기능 붙일 때 같이 하기 -const SearchBar = ({ handleFilterSheet, status }: SearchBarProps) => { +const SearchBar = ({ + handleFilterSheet, + status, + handleInputChange, + searchWord, +}: SearchBarProps) => { return ( <S.SearchBarWrapper> - <S.SearchBar type="text" placeholder="예매자를 검색해보세요."></S.SearchBar> + <S.SearchBar + type="text" + placeholder="예매자를 검색해보세요." + value={searchWord} + onChange={handleInputChange} + ></S.SearchBar> {status === "DEFAULT" && <S.FilterBtn onClick={handleFilterSheet} />} </S.SearchBarWrapper> ); From 7ac3d72a0b6b804d1896512a667f8f04cb46568b Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 04:35:59 +0900 Subject: [PATCH 27/49] =?UTF-8?q?fix:=20=EA=B2=80=EC=83=89=EC=96=B4?= =?UTF-8?q?=EA=B0=80=201=EC=9E=90=EC=9D=BC=20=EB=95=8C=20=EC=83=9D?= =?UTF-8?q?=EA=B8=B0=EB=8A=94=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ticketholderlist/TicketHolderList.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 4c2f5ac8..20df7c48 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -318,7 +318,8 @@ const TicketHolderList = () => { setPaymentData(refetchSearchData?.data?.bookingList ?? []); }; - searchWord ? fetchSearchData() : fetchData(); + // TODO : 서버에서 검색어 2글자 이상으로 넘겨줬는데, 기-디에 화면에 어떻게 표현할지 물어보기 + searchWord.length >= 2 ? fetchSearchData() : fetchData(); }, [filterList, status, debouncedQuery]); useEffect(() => { @@ -462,7 +463,7 @@ const TicketHolderList = () => { /> <FilterBottomSheet isOpen={openFilter} - totalScheduleCount={data.totalScheduleCount} + totalScheduleCount={data?.totalScheduleCount} onClickOutside={handleFilterSheet} filterList={filterList} handleFilter={(scheduleNumber, bookingStatus) => From 4ea14119364cfd7061e9aac6343293167156d37d Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 05:05:04 +0900 Subject: [PATCH 28/49] =?UTF-8?q?feat:=20=EC=98=88=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EC=97=86=EC=9D=84=20=EB=96=84=20=ED=99=94=EB=A9=B4=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ticketholderlist/TicketHolderList.tsx | 76 ++++++++++--------- .../components/nonExistent/NonExistent..tsx | 25 ++++++ .../nonExistent/NonExistent.styled.ts | 35 +++++++++ 3 files changed, 100 insertions(+), 36 deletions(-) create mode 100644 src/pages/ticketholderlist/components/nonExistent/NonExistent..tsx create mode 100644 src/pages/ticketholderlist/components/nonExistent/NonExistent.styled.ts diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 20df7c48..c60381ff 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -28,6 +28,7 @@ import { convertingBookingStatus } from "@constants/convertingBookingStatus"; import { IconCheck } from "@assets/svgs"; import Toast from "@components/commons/toast/Toast"; import { useToast } from "@hooks"; +import NonExistent from "./components/nonExistent/NonExistent."; export type PaymentType = | "CHECKING_PAYMENT" @@ -414,44 +415,47 @@ const TicketHolderList = () => { <Spacing marginBottom={"1.6"} /> </S.TitleSticky> - - <S.ManageCardList> - {paymentData?.map((item) => { - const date = item.createdAt.split("T")[0]; - const formattedDate = `${date.replace(/-/g, ". ")}`; - const bookingStatus = convertingBookingStatus(item.bookingStatus as PaymentType); - - return ( - <ManageCard key={item.bookingId}> - <S.ManageCardContainer> - {status !== "DEFAULT" && ( - <ManageCard.ManageCheckBox - bookingId={item.bookingId} - checkedBookingId={checkedBookingId} - handleBookingIdCheck={handleBookingIdCheck} + {paymentData?.length ? ( + <S.ManageCardList> + {paymentData?.map((item) => { + const date = item.createdAt.split("T")[0]; + const formattedDate = `${date.replace(/-/g, ". ")}`; + const bookingStatus = convertingBookingStatus(item.bookingStatus as PaymentType); + + return ( + <ManageCard key={item.bookingId}> + <S.ManageCardContainer> + {status !== "DEFAULT" && ( + <ManageCard.ManageCheckBox + bookingId={item.bookingId} + checkedBookingId={checkedBookingId} + handleBookingIdCheck={handleBookingIdCheck} + /> + )} + <ManageCard.ManageCardContainer + name={item.bookerName} + phoneNumber={item.bookerPhoneNumber} + ticketCount={item.purchaseTicketCount} + scheduleNumber={convertingNumber(item.scheduleNumber)} + date={formattedDate} + status={bookingStatus} + /> + </S.ManageCardContainer> + {status === "REFUND" && ( + <ManageCard.ManageAccount + bankName={getBankNameKr(item.bankName)} + accountNumber={item.accountNumber} + accountHolder={item.accountHolder} + handleCopyClipBoard={handleCopyClipBoard} /> )} - <ManageCard.ManageCardContainer - name={item.bookerName} - phoneNumber={item.bookerPhoneNumber} - ticketCount={item.purchaseTicketCount} - scheduleNumber={convertingNumber(item.scheduleNumber)} - date={formattedDate} - status={bookingStatus} - /> - </S.ManageCardContainer> - {status === "REFUND" && ( - <ManageCard.ManageAccount - bankName={getBankNameKr(item.bankName)} - accountNumber={item.accountNumber} - accountHolder={item.accountHolder} - handleCopyClipBoard={handleCopyClipBoard} - /> - )} - </ManageCard> - ); - })} - </S.ManageCardList> + </ManageCard> + ); + })} + </S.ManageCardList> + ) : ( + <NonExistent status={status} /> + )} <S.FooterButtonWrapper> <Button onClick={handleButtonClick}>{buttonText}</Button> diff --git a/src/pages/ticketholderlist/components/nonExistent/NonExistent..tsx b/src/pages/ticketholderlist/components/nonExistent/NonExistent..tsx new file mode 100644 index 00000000..9c8a6ce7 --- /dev/null +++ b/src/pages/ticketholderlist/components/nonExistent/NonExistent..tsx @@ -0,0 +1,25 @@ +import React from "react"; +import * as S from "./NonExistent.styled"; + +interface NonExistentProps { + status: string; +} + +const NonExistent = ({ status }: NonExistentProps) => { + return ( + <S.NonExistentWrapper> + <S.NonExistenLayout> + <S.EmptyImg /> + <S.EmptyText> + {status === "PAYMENT" + ? "미입금한 예매자가 없어요." + : status === "REFUND" + ? "환불 요청이 없어요." + : "아직 예매자가 없어요."} + </S.EmptyText> + </S.NonExistenLayout> + </S.NonExistentWrapper> + ); +}; + +export default NonExistent; diff --git a/src/pages/ticketholderlist/components/nonExistent/NonExistent.styled.ts b/src/pages/ticketholderlist/components/nonExistent/NonExistent.styled.ts new file mode 100644 index 00000000..8bb851ac --- /dev/null +++ b/src/pages/ticketholderlist/components/nonExistent/NonExistent.styled.ts @@ -0,0 +1,35 @@ +import styled from "styled-components"; +import { Empty } from "@assets/svgs"; + +export const NonExistentWrapper = styled.section` + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + width: 37.4rem; + height: 100%; + padding: 2.4rem; + + background-color: ${({ theme }) => theme.colors.gray_900}; +`; + +export const NonExistenLayout = styled.section` + top: 19.2rem; + display: flex; + flex-direction: column; + gap: 2.4rem; + align-items: center; + width: 32.6rem; + margin-top: 14.2rem; +`; + +export const EmptyImg = styled(Empty)` + width: 15rem; + height: 15rem; +`; + +export const EmptyText = styled.div` + color: ${({ theme }) => theme.colors.gray_300}; + ${({ theme }) => theme.fonts["body2-normal-medi"]}; + text-align: center; +`; From 776b6fefd66ac9e95fe43ed50cda484332fe598f Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 21:35:44 +0900 Subject: [PATCH 29/49] =?UTF-8?q?fix:=20=ED=83=80=EC=9E=85=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ticketholderlist/TicketHolderList.tsx | 10 +++++----- .../components/FilterBottomSheet/FilterBottomSheet.tsx | 2 +- .../components/manageCard/ManageCardContainer.tsx | 1 - .../components/manageCard/ManageCardMain.tsx | 2 +- .../components/searchBar/SearchBar.tsx | 2 +- .../components/selectedChips/SelectedChips.tsx | 3 +-- 6 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index c60381ff..4e8f327a 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -10,7 +10,7 @@ import MetaTag from "@components/commons/meta/MetaTag"; import { NAVIGATION_STATE } from "@constants/navigationState"; import { useHeader, useModal } from "@hooks"; import useDebounce from "src/hooks/useDebounce"; -import { useEffect, useState } from "react"; +import { useEffect, useState, ChangeEvent } from "react"; import { CSVLink } from "react-csv"; import { useNavigate, useParams } from "react-router-dom"; import { convertingNumber } from "@constants/convertingNumber"; @@ -302,7 +302,7 @@ const TicketHolderList = () => { const debouncedQuery = useDebounce(searchWord, 500); - const handleInputChange = (event) => { + const handleInputChange = (event: ChangeEvent<HTMLInputElement>) => { setSearchWord(event.target.value); }; @@ -356,10 +356,10 @@ const TicketHolderList = () => { const navigate = useNavigate(); const handleNavigateBack = () => { - if (status === "DEFAULT") { - navigate("/gig-manage"); - } else { + if (status !== "DEFAULT") { setStatus("DEFAULT"); + } else { + navigate("/gig-manage"); } }; diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx index 9a9ba3bb..a2aae9b5 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -9,7 +9,7 @@ interface FilterBottomSheetProps { totalScheduleCount: number; children?: ReactNode; onClickOutside?: () => void; - filterList: FilterListType[]; + filterList: FilterListType; handleFilter: (scheduleNumber: number[], bookingStatus: string[]) => void; } diff --git a/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx index 414f8fd0..329ffdee 100644 --- a/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx +++ b/src/pages/ticketholderlist/components/manageCard/ManageCardContainer.tsx @@ -1,5 +1,4 @@ import * as S from "./ManageCardContainer.styled"; -import { PaymentType } from "@pages/ticketholderlist/TicketHolderList"; interface ManagerCardContainerProps { name: string; diff --git a/src/pages/ticketholderlist/components/manageCard/ManageCardMain.tsx b/src/pages/ticketholderlist/components/manageCard/ManageCardMain.tsx index e7ffd834..03c95de9 100644 --- a/src/pages/ticketholderlist/components/manageCard/ManageCardMain.tsx +++ b/src/pages/ticketholderlist/components/manageCard/ManageCardMain.tsx @@ -1,4 +1,4 @@ -import React, { Children, ReactNode } from "react"; +import { ReactNode } from "react"; import * as S from "./ManageCardMain.styled"; export interface ManageCardMainProps { diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index e397dc22..20cbe122 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -5,7 +5,7 @@ interface SearchBarProps { status: string; searchWord: string; handleFilterSheet: () => void; - handleInputChange: () => void; + handleInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void; } // TODO: 필터 적용되었을 때 아웃라인 색상 적용 -> 기능 붙일 때 같이 하기 diff --git a/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx index 28f91740..0e326c38 100644 --- a/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx +++ b/src/pages/ticketholderlist/components/selectedChips/SelectedChips.tsx @@ -1,10 +1,9 @@ -import React from "react"; import * as S from "./SelectedChips.styled"; import { FilterListType, PaymentType } from "@pages/ticketholderlist/TicketHolderList"; import { convertingBookingStatus } from "@constants/convertingBookingStatus"; interface SelectedChipsProps { - filterList: FilterListType[]; + filterList: FilterListType; handleFilter: (scheduleNumber: number[], bookingStatus: string[]) => void; } From 0c53546c76fbdc9069b432f30cb41383cc6bcec7 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 22:23:37 +0900 Subject: [PATCH 30/49] =?UTF-8?q?design:=20=ED=95=84=ED=84=B0=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9=20=EC=8B=9C=20border=20white=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/ticketholderlist/TicketHolderList.tsx | 3 +++ .../components/searchBar/SearchBar.styled.ts | 6 +++--- .../ticketholderlist/components/searchBar/SearchBar.tsx | 4 +++- 3 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 4e8f327a..1d1a67e8 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -403,6 +403,9 @@ const TicketHolderList = () => { handleInputChange={handleInputChange} searchWord={searchWord} status={status} + isFilter={ + filterList.scheduleNumber.length > 0 || filterList.bookingStatus.length > 0 + } /> {status === "DEFAULT" && ( <SelectedChips diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts index 4267d3e7..613fb5bf 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts @@ -22,13 +22,13 @@ export const SearchBar = styled.input` border-radius: 4rem; `; -export const FilterBtn = styled(BtnFilter)` +export const FilterBtn = styled(BtnFilter)<{ $isFilter: boolean }>` width: 4.8rem; height: 4.8rem; margin-left: 1.2rem; background-color: ${({ theme }) => theme.colors.gray_800}; - border: 0.1rem solid; - border-color: ${({ theme }) => theme.colors.gray_700}; + border: 0.1rem solid + ${({ theme, $isFilter }) => ($isFilter ? theme.colors.white : theme.colors.gray_700)}; border-radius: 50%; `; diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index 20cbe122..ef1a41a2 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -6,6 +6,7 @@ interface SearchBarProps { searchWord: string; handleFilterSheet: () => void; handleInputChange: (event: React.ChangeEvent<HTMLInputElement>) => void; + isFilter: boolean; } // TODO: 필터 적용되었을 때 아웃라인 색상 적용 -> 기능 붙일 때 같이 하기 @@ -14,6 +15,7 @@ const SearchBar = ({ status, handleInputChange, searchWord, + isFilter, }: SearchBarProps) => { return ( <S.SearchBarWrapper> @@ -23,7 +25,7 @@ const SearchBar = ({ value={searchWord} onChange={handleInputChange} ></S.SearchBar> - {status === "DEFAULT" && <S.FilterBtn onClick={handleFilterSheet} />} + {status === "DEFAULT" && <S.FilterBtn onClick={handleFilterSheet} $isFilter={isFilter} />} </S.SearchBarWrapper> ); }; From 830720485eede60939a4bdba67fa57081a1a7b96 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Tue, 3 Dec 2024 22:53:21 +0900 Subject: [PATCH 31/49] =?UTF-8?q?fix:=20api=20params=20=EC=9D=B4=EB=A6=84?= =?UTF-8?q?=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/api.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/apis/domains/tickets/api.ts b/src/apis/domains/tickets/api.ts index 9143aaaa..c0f4e965 100644 --- a/src/apis/domains/tickets/api.ts +++ b/src/apis/domains/tickets/api.ts @@ -22,9 +22,9 @@ export const getTicketRetrieve = async ( try { const params = new URLSearchParams(); filterList.scheduleNumber.map((item) => - params.append("scheduleNumber", convertingScheduleNumber(item)) + params.append("scheduleNumbers", convertingScheduleNumber(item)) ); - filterList.bookingStatus.map((item) => params.append("bookingStatus", item)); + filterList.bookingStatus.map((item) => params.append("bookingStatuses", item)); const response: AxiosResponse<ApiResponseType<TicketRetrieveResponse>> = await get( `tickets/${formData.performanceId}?${params.toString()}` @@ -46,9 +46,9 @@ export const getTicketRetrieveSearch = async ( const params = new URLSearchParams(); params.append("searchWord", searchWord); filterList.scheduleNumber.map((item) => - params.append("scheduleNumber", convertingScheduleNumber(item)) + params.append("scheduleNumbers", convertingScheduleNumber(item)) ); - filterList.bookingStatus.map((item) => params.append("bookingStatus", item)); + filterList.bookingStatus.map((item) => params.append("bookingStatuses", item)); const response: AxiosResponse<ApiResponseType<TicketRetrieveResponse>> = await get( `tickets/search/${formData.performanceId}?${params.toString()}` From 8b85e37357bd546de4a77b2c6523e034f98abb36 Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Wed, 4 Dec 2024 05:59:24 +0900 Subject: [PATCH 32/49] =?UTF-8?q?feat:=20=EA=B8=80=EC=9E=90=EC=88=98=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/modifyManage/ModifyManage.tsx | 4 ++-- src/pages/register/Register.tsx | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/pages/modifyManage/ModifyManage.tsx b/src/pages/modifyManage/ModifyManage.tsx index d6d374ad..a6ee46a0 100644 --- a/src/pages/modifyManage/ModifyManage.tsx +++ b/src/pages/modifyManage/ModifyManage.tsx @@ -661,7 +661,7 @@ const ModifyManage = () => { value={dataState.performanceDescription} onChange={(e) => handleInputChange("performanceDescription", e.target.value)} placeholder="공연을 예매할 예매자들에게 공연을 소개해주세요." - maxLength={500} + maxLength={1500} /> </InputModifyManageBox> <S.Divider /> @@ -747,7 +747,7 @@ const ModifyManage = () => { value={dataState.performanceAttentionNote} onChange={(e) => handleInputChange("performanceAttentionNote", e.target.value)} placeholder="입장 안내, 공연 중 인터미션, 공연장 반입금지 물품, 촬영 가능 여부, 주차 안내 등 예매자들이 꼭 알고 있어야할 유의사항을 입력해주세요." - maxLength={250} + maxLength={1500} /> </InputModifyManageBox> <S.Divider /> diff --git a/src/pages/register/Register.tsx b/src/pages/register/Register.tsx index 01b7e940..58ae1e93 100644 --- a/src/pages/register/Register.tsx +++ b/src/pages/register/Register.tsx @@ -448,7 +448,7 @@ const Register = () => { value={performanceDescription} onChange={(e) => handleChange(e, setGigInfo)} placeholder="공연을 예매할 예매자들에게 공연을 소개해주세요." - maxLength={500} + maxLength={1500} /> </InputRegisterBox> <S.Divider /> @@ -512,7 +512,7 @@ const Register = () => { value={performanceAttentionNote} onChange={(e) => handleChange(e, setGigInfo)} placeholder="입장 안내, 공연 중 인터미션, 공연장 반입금지 물품, 촬영 가능 여부, 주차 안내 등 예매자들이 꼭 알고 있어야할 유의사항을 입력해주세요." - maxLength={500} + maxLength={1500} /> </InputRegisterBox> <S.Divider /> From 7ada53d8974108c71de746a6a47ed249c9d3b042 Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Wed, 4 Dec 2024 06:57:50 +0900 Subject: [PATCH 33/49] =?UTF-8?q?feat:=20=EA=B3=B5=EC=97=B0=EC=A7=84=20?= =?UTF-8?q?=EC=9D=B4=EB=AF=B8=EC=A7=80=20=EC=84=A0=ED=83=9D=EC=9C=BC?= =?UTF-8?q?=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../gig/components/peopleCard/PeopleCard.tsx | 2 +- src/pages/modifyManage/ModifyMaker.tsx | 4 ++-- src/pages/modifyManage/ModifyManage.tsx | 23 +++++++++++++------ src/pages/register/Register.tsx | 19 +++++++++------ src/pages/register/RegisterMaker.tsx | 8 ++----- 5 files changed, 33 insertions(+), 23 deletions(-) diff --git a/src/pages/gig/components/peopleCard/PeopleCard.tsx b/src/pages/gig/components/peopleCard/PeopleCard.tsx index e5cb0691..42060668 100644 --- a/src/pages/gig/components/peopleCard/PeopleCard.tsx +++ b/src/pages/gig/components/peopleCard/PeopleCard.tsx @@ -9,7 +9,7 @@ interface PeopleCardProps { const PeopleCard = ({ photo, role, name }: PeopleCardProps) => { return ( <S.PeopleCardContainer> - <S.PeopleCardPhoto src={photo} /> + {photo && <S.PeopleCardPhoto src={photo} />} <S.PeopleCardTextBox> <S.PeopleCardRole>{role}</S.PeopleCardRole> <S.PeopleCardName>{name}</S.PeopleCardName> diff --git a/src/pages/modifyManage/ModifyMaker.tsx b/src/pages/modifyManage/ModifyMaker.tsx index d3b3bb31..04bcf084 100644 --- a/src/pages/modifyManage/ModifyMaker.tsx +++ b/src/pages/modifyManage/ModifyMaker.tsx @@ -25,11 +25,11 @@ const ModifyManageMaker = ({ useEffect(() => { const allCastFieldsFilled = castModifyRequests.every( - (cast) => cast.castName && cast.castRole && cast.castPhoto + (cast) => cast.castName && cast.castRole ); const allStaffFieldsFilled = staffModifyRequests.every( - (staff) => staff.staffName && staff.staffRole && staff.staffPhoto + (staff) => staff.staffName && staff.staffRole ); setIsButtonDisabled( diff --git a/src/pages/modifyManage/ModifyManage.tsx b/src/pages/modifyManage/ModifyManage.tsx index a6ee46a0..31822a40 100644 --- a/src/pages/modifyManage/ModifyManage.tsx +++ b/src/pages/modifyManage/ModifyManage.tsx @@ -333,11 +333,16 @@ const ModifyManage = () => { const extractUrls = (data: PresignedResponse) => { //앞부분(유효한 부분)만 떼어내서 저장(뒷 부분은 사진이 뜨는 url이 아님) posterUrls = Object.values(data.poster).map((url) => url.split("?")[0]); - castUrls = Object.values(data.cast).map((url) => url.split("?")[0]); - staffUrls = Object.values(data.staff).map((url) => url.split("?")[0]); + castUrls = Object.values(data.cast).map((url) => (url !== "" ? url.split("?")[0] : null)); + staffUrls = Object.values(data.staff).map((url) => (url !== "" ? url.split("?")[0] : null)); performanceUrls = Object.values(data.performance).map((url) => url.split("?")[0]); - return [...posterUrls, ...castUrls, ...staffUrls, ...performanceUrls]; + return [ + ...posterUrls, + ...castUrls.filter((url) => url !== null), + ...staffUrls.filter((url) => url !== null), + ...performanceUrls, + ]; }; //배열 형태로 추출된 모든 presignedUrls @@ -346,8 +351,12 @@ const ModifyManage = () => { //기존에 갖고 있던 이미지들의 주소들 -> files const files = [ dataState.posterImage, - ...dataState.castModifyRequests.map((cast) => cast.castPhoto), - ...dataState.staffModifyRequests.map((staff) => staff.staffPhoto), + ...dataState.castModifyRequests + .map((cast) => cast.castPhoto) + .filter((photo) => photo !== ""), + ...dataState.staffModifyRequests + .map((staff) => staff.staffPhoto) + .filter((photo) => photo !== ""), ...dataState.performanceImageModifyRequests.map((obj) => obj.performanceImage), ]; @@ -400,7 +409,7 @@ const ModifyManage = () => { castModifyRequests: dataState.castModifyRequests.map((cast, index) => { const modifiedCast = { ...cast, - castPhoto: castUrls[index] || cast.castPhoto, + castPhoto: cast.castPhoto === "" ? "" : castUrls[index] || cast.castPhoto, }; if (modifiedCast.castId === -1) { delete modifiedCast.castId; // castId가 -1인 경우 castId를 삭제(새롭게 추가된 경우에는 id 안보내야 함) @@ -410,7 +419,7 @@ const ModifyManage = () => { staffModifyRequests: dataState.staffModifyRequests.map((staff, index) => { const modifiedStaff = { ...staff, - staffPhoto: staffUrls[index] || staff.staffPhoto, + staffPhoto: staff.staffPhoto === "" ? "" : staffUrls[index] || staff.staffPhoto, }; if (modifiedStaff.staffId === -1) { delete modifiedStaff.staffId; // staffId가 -1인 경우 staffId를 삭제(새롭게 추가된 경우에는 id 안보내야 함) diff --git a/src/pages/register/Register.tsx b/src/pages/register/Register.tsx index 58ae1e93..49f88276 100644 --- a/src/pages/register/Register.tsx +++ b/src/pages/register/Register.tsx @@ -195,18 +195,23 @@ const Register = () => { if (isSuccess) { const extractUrls = (data: PresignedResponse) => { posterUrls = Object.values(data.poster).map((url) => url.split("?")[0]); - castUrls = Object.values(data.cast).map((url) => url.split("?")[0]); - staffUrls = Object.values(data.staff).map((url) => url.split("?")[0]); + castUrls = Object.values(data.cast).map((url) => (url !== "" ? url.split("?")[0] : null)); + staffUrls = Object.values(data.staff).map((url) => (url !== "" ? url.split("?")[0] : null)); performanceUrls = Object.values(data.performance).map((url) => url.split("?")[0]); - return [...posterUrls, ...castUrls, ...staffUrls, ...performanceUrls]; + return [ + ...posterUrls, + ...castUrls.filter((url) => url !== null), + ...staffUrls.filter((url) => url !== null), + ...performanceUrls, + ]; }; const S3Urls = extractUrls(data); const files = [ gigInfo.posterImage, - ...gigInfo.castList.map((cast) => cast.castPhoto), - ...gigInfo.staffList.map((staff) => staff.staffPhoto), + ...gigInfo.castList.map((cast) => cast.castPhoto).filter((photo) => photo !== ""), + ...gigInfo.staffList.map((staff) => staff.staffPhoto).filter((photo) => photo !== ""), ...gigInfo.performanceImageList.map((image) => image.performanceImage), ]; @@ -228,11 +233,11 @@ const Register = () => { posterImage: posterUrls[0], castList: gigInfo.castList.map((cast, index) => ({ ...cast, - castPhoto: castUrls[index] || cast.castPhoto, + castPhoto: cast.castPhoto === "" ? "" : castUrls[index] || cast.castPhoto, })), staffList: gigInfo.staffList.map((staff, index) => ({ ...staff, - staffPhoto: staffUrls[index] || staff.staffPhoto, + staffPhoto: staff.staffPhoto === "" ? "" : staffUrls[index] || staff.staffPhoto, })), scheduleList: gigInfo.scheduleList.map((schedule) => { const date = dayjs(schedule.performanceDate).toDate(); diff --git a/src/pages/register/RegisterMaker.tsx b/src/pages/register/RegisterMaker.tsx index c76a7055..3a73c0ba 100644 --- a/src/pages/register/RegisterMaker.tsx +++ b/src/pages/register/RegisterMaker.tsx @@ -24,13 +24,9 @@ const RegisterMaker = ({ const [isButtonDisabled, setIsButtonDisabled] = useState(true); useEffect(() => { - const allCastFieldsFilled = castList.every( - (cast) => cast.castName && cast.castRole && cast.castPhoto - ); + const allCastFieldsFilled = castList.every((cast) => cast.castName && cast.castRole); - const allStaffFieldsFilled = staffList.every( - (staff) => staff.staffName && staff.staffRole && staff.staffPhoto - ); + const allStaffFieldsFilled = staffList.every((staff) => staff.staffName && staff.staffRole); setIsButtonDisabled( !( From 77a69ff895394217b0ba019b88318bbc1bf8c234 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Thu, 5 Dec 2024 13:45:12 +0900 Subject: [PATCH 34/49] =?UTF-8?q?feat:=20csv=20=EB=B2=84=ED=8A=BC=20?= =?UTF-8?q?=EC=9E=AC=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- public/svgs/icon_download.svg | 3 +++ src/assets/svgs/IconDownload.tsx | 11 +++++++++ src/assets/svgs/index.tsx | 1 + .../commons/navigation/Navigation.styled.ts | 18 ++++++++++++-- .../commons/navigation/Navigation.tsx | 13 ++++++++++ src/constants/navigationState.ts | 1 + .../ticketholderlist/TicketHolderList.tsx | 24 ++++++++++++++----- 7 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 public/svgs/icon_download.svg create mode 100644 src/assets/svgs/IconDownload.tsx diff --git a/public/svgs/icon_download.svg b/public/svgs/icon_download.svg new file mode 100644 index 00000000..60f11990 --- /dev/null +++ b/public/svgs/icon_download.svg @@ -0,0 +1,3 @@ +<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg"> +<path d="M9.9987 13.333L5.83203 9.16634L6.9987 7.95801L9.16536 10.1247V3.33301H10.832V10.1247L12.9987 7.95801L14.1654 9.16634L9.9987 13.333ZM4.9987 16.6663C4.54036 16.6663 4.14814 16.5033 3.82203 16.1772C3.49592 15.8511 3.33259 15.4586 3.33203 14.9997V12.4997H4.9987V14.9997H14.9987V12.4997H16.6654V14.9997C16.6654 15.458 16.5023 15.8505 16.1762 16.1772C15.8501 16.5038 15.4576 16.6669 14.9987 16.6663H4.9987Z" fill="#FB247F"/> +</svg> diff --git a/src/assets/svgs/IconDownload.tsx b/src/assets/svgs/IconDownload.tsx new file mode 100644 index 00000000..6a448b89 --- /dev/null +++ b/src/assets/svgs/IconDownload.tsx @@ -0,0 +1,11 @@ +import * as React from "react"; +import type { SVGProps } from "react"; +const SvgIconDownload = (props: SVGProps<SVGSVGElement>) => ( + <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20" {...props}> + <path + fill="#FB247F" + d="M9.999 13.333 5.832 9.166l1.167-1.208 2.166 2.167V3.333h1.667v6.792l2.167-2.167 1.166 1.208zm-5 3.333q-.687 0-1.177-.489A1.6 1.6 0 0 1 3.332 15v-2.5h1.667V15h10v-2.5h1.666V15q0 .687-.489 1.177a1.6 1.6 0 0 1-1.177.49z" + /> + </svg> +); +export default SvgIconDownload; diff --git a/src/assets/svgs/index.tsx b/src/assets/svgs/index.tsx index b926ac37..7e734705 100644 --- a/src/assets/svgs/index.tsx +++ b/src/assets/svgs/index.tsx @@ -22,6 +22,7 @@ export { default as IconCheckboxSelectedOn } from "./IconCheckboxSelectedOn"; export { default as IconCheckboxUnselectedOn } from "./IconCheckboxUnselectedOn"; export { default as IconChecked } from "./IconChecked"; export { default as IconChevronBack } from "./IconChevronBack"; +export { default as IconDownload } from "./IconDownload"; export { default as IconEmpty } from "./IconEmpty"; export { default as IconEyeOff } from "./IconEyeOff"; export { default as IconEyeOn } from "./IconEyeOn"; diff --git a/src/components/commons/navigation/Navigation.styled.ts b/src/components/commons/navigation/Navigation.styled.ts index 6ff7038d..c2d03ed3 100644 --- a/src/components/commons/navigation/Navigation.styled.ts +++ b/src/components/commons/navigation/Navigation.styled.ts @@ -1,4 +1,11 @@ -import { IcHamburgar, IconArrowLeft, IconArrowRight, IconLogo, IconXButton } from "@assets/svgs"; +import { + IcHamburgar, + IconArrowLeft, + IconArrowRight, + IconLogo, + IconXButton, + IconDownload, +} from "@assets/svgs"; import styled from "styled-components"; export const NavigationWrapper = styled.div` @@ -38,6 +45,13 @@ export const HamburgarButton = styled(IcHamburgar)` cursor: pointer; `; +export const DownloadButton = styled(IconDownload)` + width: 2rem; + height: 2rem; + + cursor: pointer; +`; + export const NavigationLeftButton = styled(IconArrowLeft)` box-sizing: content-box; width: 2.4rem; @@ -67,7 +81,7 @@ export const NavigationXButton = styled(IconXButton)` // TODO: 뷰에 띄워보니 padding이 없어 스타일링 이상함 디자이너 분께 물어보기 export const SubTextButton = styled.button` - width: 3.2rem; + display: flex; margin: 0 0.4rem 0 0; ${({ theme }) => theme.fonts["body1-normal-semi"]}; diff --git a/src/components/commons/navigation/Navigation.tsx b/src/components/commons/navigation/Navigation.tsx index 4e832e8d..7e03ad4f 100644 --- a/src/components/commons/navigation/Navigation.tsx +++ b/src/components/commons/navigation/Navigation.tsx @@ -83,6 +83,19 @@ const Navigation = () => { ); } + if (headerStyle === NAVIGATION_STATE.ICON_TITLE_DOWNLOAD) { + return ( + <S.NavigationWrapper> + <S.NavigationLeftButton onClick={leftOnClick} /> + <S.NavigationTitle>{title}</S.NavigationTitle> + <S.SubTextButton onClick={rightOnClick}> + {subText} + <S.DownloadButton /> + </S.SubTextButton> + </S.NavigationWrapper> + ); + } + if (!headerStyle) { return null; } diff --git a/src/constants/navigationState.ts b/src/constants/navigationState.ts index c4673cc4..36bc9239 100644 --- a/src/constants/navigationState.ts +++ b/src/constants/navigationState.ts @@ -7,6 +7,7 @@ export const NAVIGATION_STATE = { ICON: "icon", LOGO_HAMBURGAR: "logoHamburgar", ICON_ICON: "iconIcon", + ICON_TITLE_DOWNLOAD: "iconTitleDownload", } as const; export type NavigationState = (typeof NAVIGATION_STATE)[keyof typeof NAVIGATION_STATE]; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index 1d1a67e8..e9ff0084 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -10,7 +10,7 @@ import MetaTag from "@components/commons/meta/MetaTag"; import { NAVIGATION_STATE } from "@constants/navigationState"; import { useHeader, useModal } from "@hooks"; import useDebounce from "src/hooks/useDebounce"; -import { useEffect, useState, ChangeEvent } from "react"; +import { useEffect, useState, ChangeEvent, useRef } from "react"; import { CSVLink } from "react-csv"; import { useNavigate, useParams } from "react-router-dom"; import { convertingNumber } from "@constants/convertingNumber"; @@ -77,6 +77,8 @@ const TicketHolderList = () => { const [CSVDataArr, setCSVDataArr] = useState<CSVDataType[]>([]); + const csvLinkRef = useRef(null); + const { performanceId } = useParams(); const { data, isLoading, refetch } = useTicketRetrive( @@ -363,16 +365,20 @@ const TicketHolderList = () => { } }; + const handleCSVDownload = () => { + if (csvLinkRef.current) { + csvLinkRef.current.link.click(); + } + }; + const { setHeader } = useHeader(); useEffect(() => { setHeader({ - headerStyle: NAVIGATION_STATE.ICON_TITLE_SUB_TEXT, + headerStyle: NAVIGATION_STATE.ICON_TITLE_DOWNLOAD, title: "예매자 관리", - // TODO : 공통컴포넌트에 svg 들어갈 수 있도록 수정하기 - subText: "CSV", + subText: "리스트", leftOnClick: handleNavigateBack, - // TODO : rightOnClick CSV 다운로드로 변경 - // rightOnClick:, + rightOnClick: handleCSVDownload, }); }, [setHeader]); @@ -477,6 +483,12 @@ const TicketHolderList = () => { handleFilter(scheduleNumber, bookingStatus) } /> + <CSVLink + data={CSVDataArr} + headers={headers} + filename={`${data.performanceTitle}_예매자 목록.csv`} + ref={csvLinkRef} + /> <Toast icon={<IconCheck />} isVisible={isToastVisible} toastBottom={30}> 클립보드에 복사되었습니다! </Toast> From 4b80f453ad50b6067d794add71c9e666a208718e Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Fri, 6 Dec 2024 03:03:34 +0900 Subject: [PATCH 35/49] =?UTF-8?q?fix:=20cancel=20=ED=8E=98=EC=9D=B4?= =?UTF-8?q?=EC=A7=80=20=EC=A0=91=EA=B7=BC=20=EC=98=A4=EB=A5=98=20=ED=95=B4?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/svgs/index.ts | 2 ++ src/pages/cancel/Cancel.tsx | 32 ++++++++++++++++++++------------ src/pages/lookup/Lookup.tsx | 2 +- src/routes/LookupRoutes.tsx | 4 +++- src/routes/Router.tsx | 2 -- 5 files changed, 26 insertions(+), 16 deletions(-) diff --git a/src/assets/svgs/index.ts b/src/assets/svgs/index.ts index d986239c..5577c682 100644 --- a/src/assets/svgs/index.ts +++ b/src/assets/svgs/index.ts @@ -66,3 +66,5 @@ export { default as NotFoundAsset } from "./NotFoundAsset"; export { default as Subtract } from "./Subtract"; export { default as Switch } from "./Switch"; export { default as Union } from "./Union"; +export { default as IcRadioSelected } from "./IcRadioSelected"; +export { default as IcRadioUnselected } from "./IcRadioUnselected"; diff --git a/src/pages/cancel/Cancel.tsx b/src/pages/cancel/Cancel.tsx index 20aa30e3..69636db8 100644 --- a/src/pages/cancel/Cancel.tsx +++ b/src/pages/cancel/Cancel.tsx @@ -21,7 +21,11 @@ const Cancel = () => { const { setHeader } = useHeader(); const { openAlert } = useModal(); const { state } = useLocation(); - const { confirmCancelAction } = useCancelBooking(state.bookerName, state.number, state.password); + const { confirmCancelAction } = useCancelBooking( + state?.bookerName, + state?.number, + state?.password + ); const navigate = useNavigate(); const [isDeposit, setIsDeposit] = useState<boolean | null>(null); const [bankOpen, setBankOpen] = useState(false); @@ -29,6 +33,21 @@ const Cancel = () => { const [accountNumber, setAccountNumber] = useState(""); const [accountHolder, setAccountHolder] = useState(""); + useEffect(() => { + if (!state) { + const user = localStorage.getItem("user"); + openAlert({ + title: "잘못된 접근입니다.", + okText: "확인", + okCallback: () => navigate(user ? "/lookup" : "/main"), + }); + } + }, []); + + if (!state) { + return; + } + const performanceDateArray = state.bookingDetails.performanceDate.split("-"); const performanceDataDate = performanceDateArray[2].split("T"); @@ -48,17 +67,6 @@ const Cancel = () => { }); }, [setHeader]); - useEffect(() => { - if (!state) { - openAlert({ - title: "잘못된 접근입니다.", - subTitle: "이전 페이지로 이동합니다.", - okText: "확인", - okCallback: () => navigate(-1), - }); - } - }, [state, openAlert, navigate]); - const handleCancelClick = (isDeposit) => { const requestData = { bookingId: state.bookingDetails.bookingId, diff --git a/src/pages/lookup/Lookup.tsx b/src/pages/lookup/Lookup.tsx index 35d572d0..333abec8 100644 --- a/src/pages/lookup/Lookup.tsx +++ b/src/pages/lookup/Lookup.tsx @@ -62,7 +62,7 @@ const Lookup = () => { const bookingDetails = (memberData ?? cachedData)?.find((item) => item.bookingId === bookingId); if (bookingDetails) { - navigate("/cancel", { state: { ...state, bookingDetails } }); + navigate("/lookup/cancel", { state: { ...state, bookingDetails } }); } }; diff --git a/src/routes/LookupRoutes.tsx b/src/routes/LookupRoutes.tsx index cb44b268..579c4912 100644 --- a/src/routes/LookupRoutes.tsx +++ b/src/routes/LookupRoutes.tsx @@ -1,9 +1,11 @@ import Lookup from "@pages/lookup/Lookup"; import NonMbLookup from "@pages/nonMbLookup/NonMbLookup"; +import Cancel from "@pages/cancel/Cancel"; const LOOKUP_ROUTES = [ { path: "nonmb-lookup", element: <NonMbLookup /> }, { path: "lookup", element: <Lookup /> }, + { path: "lookup/cancel", element: <Cancel /> }, ]; -export default LOOKUP_ROUTES; \ No newline at end of file +export default LOOKUP_ROUTES; diff --git a/src/routes/Router.tsx b/src/routes/Router.tsx index 33ea7758..44115650 100644 --- a/src/routes/Router.tsx +++ b/src/routes/Router.tsx @@ -12,7 +12,6 @@ import ADMIN_ROUTES from "./AdminRoutes"; import Admin from "@admin/pages/admin/Admin"; import DesktopGlobalStyle from "@styles/desktop"; import TokenRefresher from "src/hooks/useTokenRefresher"; -import Cancel from "@pages/cancel/Cancel"; const router = createBrowserRouter([ { @@ -34,7 +33,6 @@ const router = createBrowserRouter([ ...LOOKUP_ROUTES, ...MANAGE_ROUTES, ...REGISTER_ROUTES, - { path: "cancel", element: <Cancel /> }, { path: "*", element: <NotFound /> }, ], }, From 8c013ffa347458b5c3a6562aa6c0c742e21646ca Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Fri, 6 Dec 2024 04:03:03 +0900 Subject: [PATCH 36/49] =?UTF-8?q?design:=20table=20=EA=B0=84=EA=B2=A9=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/cancel/Cancel.styled.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/pages/cancel/Cancel.styled.ts b/src/pages/cancel/Cancel.styled.ts index 3f8323cc..3a76459b 100644 --- a/src/pages/cancel/Cancel.styled.ts +++ b/src/pages/cancel/Cancel.styled.ts @@ -34,6 +34,7 @@ export const PerformBox = styled.div` table { width: 100%; + margin: -0.4rem; border-collapse: separate; border-spacing: 0.4rem 0.4rem; From 2a905d28e0ff398f8157ebe965b5db64b8924401 Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Fri, 6 Dec 2024 04:06:14 +0900 Subject: [PATCH 37/49] =?UTF-8?q?style:=20=EC=BD=94=EB=93=9C=20=EC=8A=A4?= =?UTF-8?q?=ED=83=80=EC=9D=BC=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/cancel/Cancel.tsx | 3 ++- src/pages/cancel/utils/index.ts | 12 ++++++------ 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/pages/cancel/Cancel.tsx b/src/pages/cancel/Cancel.tsx index 69636db8..9fa55e0d 100644 --- a/src/pages/cancel/Cancel.tsx +++ b/src/pages/cancel/Cancel.tsx @@ -16,6 +16,7 @@ import * as S from "./Cancel.styled"; import RadioButton from "./../cancel/components/select/RadioButton"; import { handleChange, handleBankClick, isFormValid } from "./utils"; import { useCancelBooking } from "../../hooks/useCancelBooking"; +import { numericFilter } from "@utils/useInputFilter"; const Cancel = () => { const { setHeader } = useHeader(); @@ -141,7 +142,7 @@ const Cancel = () => { name="accountNumber" value={accountNumber} onChange={(e) => handleChange(e, setAccountNumber)} - filter={(value: string) => value.replace(/[^0-9]/g, "")} // 숫자만 허용 + filter={numericFilter} placeholder="입금 받으실 계좌번호를 (-) 제외 숫자만 입력해주세요." inputMode="numeric" /> diff --git a/src/pages/cancel/utils/index.ts b/src/pages/cancel/utils/index.ts index 29299cbe..0d32c13f 100644 --- a/src/pages/cancel/utils/index.ts +++ b/src/pages/cancel/utils/index.ts @@ -1,17 +1,17 @@ -import React from "react"; +import React, { ChangeEvent, Dispatch, SetStateAction } from "react"; export const handleChange = ( - e: React.ChangeEvent<HTMLInputElement>, - setState: React.Dispatch<React.SetStateAction<string>> + e: ChangeEvent<HTMLInputElement>, + setState: Dispatch<SetStateAction<string>> ) => { setState(e.target.value); }; export const handleBankClick = ( value: string, - setState: React.Dispatch<React.SetStateAction<string>>, - setbankName: React.Dispatch<React.SetStateAction<string>>, - setOpen: React.Dispatch<React.SetStateAction<boolean>> + setState: Dispatch<SetStateAction<string>>, + setbankName: Dispatch<SetStateAction<string>>, + setOpen: Dispatch<SetStateAction<boolean>> ) => { setbankName(value); setState(value); From 1518a715cb13bd30b78349c9ee720dc5d1e59c6f Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Fri, 6 Dec 2024 04:53:37 +0900 Subject: [PATCH 38/49] =?UTF-8?q?style:=20state=20=EC=9D=B4=EB=A6=84=20?= =?UTF-8?q?=EB=A7=9E=EC=B6=94=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/lookup/Lookup.tsx | 26 +++++++++---------- src/pages/nonMbLookup/NonMbLookup.tsx | 24 +++++------------ .../nonMbLookup/components/InputWrapper.tsx | 14 +++++----- 3 files changed, 26 insertions(+), 38 deletions(-) diff --git a/src/pages/lookup/Lookup.tsx b/src/pages/lookup/Lookup.tsx index 333abec8..c399af26 100644 --- a/src/pages/lookup/Lookup.tsx +++ b/src/pages/lookup/Lookup.tsx @@ -26,7 +26,7 @@ interface LookupProps { performanceVenue: string; purchaseTicketCount: number; scheduleNumber: string; - bookerName: string; + name: string; bookerPhoneNumber: string; bankName: string; performanceContact: string; @@ -45,14 +45,16 @@ const Lookup = () => { const navigate = useNavigate(); const { confirmCancelAction, toastMessage } = useCancelBooking( - state?.bookerName, - state?.number, + state?.name, + state?.phone, state?.password ); - + const [isFetching, setIsFetching] = useState(false); const { data: memberData, isLoading: isMemberLoading } = useGetMemberBookingList(); // 회원 예매 조회 const { getCachedBookingList, fetchBookingList } = useLazyPostGuestBookingList(); - const cachedData = getCachedBookingList(state?.bookerName, state?.number, state?.password); // 비회원 예매 조회 + const [cachedData, setCachedData] = useState( + getCachedBookingList(state?.name, state?.phone, state?.password) + ); // 비회원 예매 조회 const handleCancel = (bookingId: number, totalPaymentAmount: number) => { if (totalPaymentAmount === 0) { @@ -67,16 +69,14 @@ const Lookup = () => { }; useEffect(() => { - if (state?.bookerName && state?.number && state?.password && !cachedData) { + if (state?.name && state?.phone && state?.password && !cachedData && !isFetching) { // 비회원 데이터가 캐시에 없을 경우 새로 가져옴 - fetchBookingList({ - name: state.bookerName, - phone: state.number, - password: state.password, - birth: state.birth || "", + fetchBookingList(state).finally(() => { + setIsFetching(false); + setCachedData(getCachedBookingList(state.name, state.phone, state.password)); }); } - }, [state, cachedData, fetchBookingList]); + }, [state, cachedData, fetchBookingList, isFetching]); useEffect(() => { if (state?.toastMessage) { @@ -86,7 +86,7 @@ const Lookup = () => { return () => clearTimeout(timer); } - }, [state, navigate]); + }, [state]); const { setHeader } = useHeader(); useEffect(() => { diff --git a/src/pages/nonMbLookup/NonMbLookup.tsx b/src/pages/nonMbLookup/NonMbLookup.tsx index 56e94281..c30138bf 100644 --- a/src/pages/nonMbLookup/NonMbLookup.tsx +++ b/src/pages/nonMbLookup/NonMbLookup.tsx @@ -17,9 +17,9 @@ const NonMbLookup = () => { const { fetchBookingList } = useLazyPostGuestBookingList(); const [formData, setFormData] = useState({ - bookerName: "", + name: "", birth: "", - number: "", + phone: "", password: "", }); const [btnActive, setBtnActive] = useState(false); @@ -32,8 +32,8 @@ const NonMbLookup = () => { // 버튼 상태 활성화/비활성화 useEffect(() => { - const { bookerName, birth, number, password } = formData; - if (bookerName && birth.length === 6 && number.length === 13 && password.length === 4) { + const { name, birth, phone, password } = formData; + if (name && birth.length === 6 && phone.length === 13 && password.length === 4) { setBtnActive(true); } else { setBtnActive(false); @@ -42,26 +42,14 @@ const NonMbLookup = () => { // 버튼 클릭 시 요청 실행 const handleBtnClick = async () => { - const { bookerName, birth, number, password } = formData; - try { setIsFetching(true); - const bookingData = await fetchBookingList({ - name: bookerName, - phone: number, - password, - birth, - }); + const bookingData = await fetchBookingList(formData); if (bookingData) { navigate("/lookup", { - state: { - bookerName, - number, - password, - birth, - }, + state: formData, }); } else { openAlert({ diff --git a/src/pages/nonMbLookup/components/InputWrapper.tsx b/src/pages/nonMbLookup/components/InputWrapper.tsx index 6b89b246..d2ee12c0 100644 --- a/src/pages/nonMbLookup/components/InputWrapper.tsx +++ b/src/pages/nonMbLookup/components/InputWrapper.tsx @@ -6,16 +6,16 @@ import { nameFilter, numericFilter, phoneNumberFilter } from "@utils/useInputFil interface InputWrapperProps { formData: { - bookerName: string; + name: string; birth: string; - number: string; + phone: string; password: string; }; onInputChange: (field: string, value: string) => void; } const InputWrapper = ({ formData, onInputChange }: InputWrapperProps) => { - const { bookerName, birth, number, password } = formData; + const { name, birth, phone, password } = formData; const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => { const { name: fieldName, value } = e.target; @@ -25,9 +25,9 @@ const InputWrapper = ({ formData, onInputChange }: InputWrapperProps) => { return ( <S.InputWrapperLayout> <TextField - name="bookerName" + name="name" type="input" - value={bookerName} + value={name} placeholder="이름" onChange={handleChange} filter={nameFilter} @@ -44,8 +44,8 @@ const InputWrapper = ({ formData, onInputChange }: InputWrapperProps) => { /> <TextField type="input" - name="number" - value={number} + name="phone" + value={phone} onChange={handleChange} placeholder="휴대폰 번호 '-' 없이 입력" filter={phoneNumberFilter} From fe263c479fd81a297bb2da8af3975a2665562e4d Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Fri, 6 Dec 2024 04:54:40 +0900 Subject: [PATCH 39/49] =?UTF-8?q?chore:=20=EC=95=88=EC=93=B0=EB=8A=94=20im?= =?UTF-8?q?ort=20=EC=82=AD=EC=A0=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/cancel/Cancel.tsx | 2 +- src/pages/lookup/Lookup.tsx | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/pages/cancel/Cancel.tsx b/src/pages/cancel/Cancel.tsx index 9fa55e0d..7801dd14 100644 --- a/src/pages/cancel/Cancel.tsx +++ b/src/pages/cancel/Cancel.tsx @@ -8,7 +8,7 @@ import { Toast, } from "@components/commons"; import { NAVIGATION_STATE } from "@constants/navigationState"; -import { useHeader, useModal, useToast } from "@hooks"; +import { useHeader, useModal } from "@hooks"; import React, { useEffect, useState } from "react"; import { useLocation, useNavigate } from "react-router-dom"; import { convertingNumber } from "@constants/convertingNumber"; diff --git a/src/pages/lookup/Lookup.tsx b/src/pages/lookup/Lookup.tsx index c399af26..0e17cdd9 100644 --- a/src/pages/lookup/Lookup.tsx +++ b/src/pages/lookup/Lookup.tsx @@ -14,7 +14,6 @@ import { useHeader } from "@hooks"; import { useCancelBooking } from "src/hooks/useCancelBooking"; import { Toast } from "@components/commons"; import { IconCheck } from "@assets/svgs"; -import { ToastMessage } from "./../../components/commons/toast/Toast.styled"; interface LookupProps { userId: number; From ad2ecbe037c5cb638ec8a597eac6ee4b13e7c990 Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Fri, 6 Dec 2024 05:18:52 +0900 Subject: [PATCH 40/49] =?UTF-8?q?style:=20=ED=8C=90=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EA=B8=B0=EC=A4=80=20=EC=98=88=EB=A7=A4=EC=9E=90=20=EB=AA=A9?= =?UTF-8?q?=EB=A1=9D=20=EC=BF=BC=EB=A6=AC=ED=82=A4=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/queries.ts | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/apis/domains/tickets/queries.ts b/src/apis/domains/tickets/queries.ts index f4b1b5cb..133d8dd4 100644 --- a/src/apis/domains/tickets/queries.ts +++ b/src/apis/domains/tickets/queries.ts @@ -8,16 +8,14 @@ import { TicketUpdateRequest, } from "./api"; -import { BOOKING_QUERY_KEY } from "../bookings/queries"; - // 예매자 목록 조회 API (GET)를 위한 쿼리 작성 const QUERY_KEY = { - LIST: "list", + SELLER_BOOKING_LIST: "sellerBookingList", }; export const useTicketRetrive = (formData: getTicketReq) => { return useQuery({ - queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST], + queryKey: [QUERY_KEY.SELLER_BOOKING_LIST], queryFn: () => getTicketRetrieve(formData), // staleTime: 1000 * 60 * 60, gcTime: 1000 * 60 * 60 * 24, @@ -31,8 +29,8 @@ export const useTicketUpdate = () => { return useMutation({ mutationFn: (formData: TicketUpdateRequest) => putTicketUpdate(formData), onSuccess: (res) => { - queryClient.invalidateQueries({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST] }); - queryClient.refetchQueries({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST] }); + queryClient.invalidateQueries({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST] }); + queryClient.refetchQueries({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST] }); }, }); }; @@ -44,8 +42,8 @@ export const useTicketPatch = () => { return useMutation({ mutationFn: (formData: PatchFormDataProps) => patchTicketCancel(formData), onSuccess: (res) => { - queryClient.invalidateQueries({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST] }); - queryClient.refetchQueries({ queryKey: [QUERY_KEY.LIST, BOOKING_QUERY_KEY.BOOKING_LIST] }); + queryClient.invalidateQueries({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST] }); + queryClient.refetchQueries({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST] }); }, }); }; From 680cd700274a285311979697ca8459f938498fa9 Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Fri, 6 Dec 2024 05:24:11 +0900 Subject: [PATCH 41/49] =?UTF-8?q?chore:=20=EB=B9=84=ED=9A=8C=EC=9B=90=20?= =?UTF-8?q?=EC=98=88=EB=A7=A4=20=EB=A6=AC=EC=95=A1=ED=8A=B8=20=EC=BF=BC?= =?UTF-8?q?=EB=A6=AC=20=EC=9D=B8=EC=9E=90=20=EB=84=98=EA=B2=A8=EC=A3=BC?= =?UTF-8?q?=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/test/TestPage.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/pages/test/TestPage.tsx b/src/pages/test/TestPage.tsx index 5a8485c2..0d962e63 100644 --- a/src/pages/test/TestPage.tsx +++ b/src/pages/test/TestPage.tsx @@ -1,4 +1,4 @@ -import { useGuestBook } from "@apis/domains/bookings/queries"; +// import { useGuestBook } from "@apis/domains/bookings/queries"; import { IconCheck, IconTextfiedlDelete } from "@assets/svgs"; import Button from "@components/commons/button/Button"; import Chip from "@components/commons/chip/Chip"; @@ -38,7 +38,7 @@ const TestPage = () => { }; // 3. 훅 불러와서 사용 - const { mutate, mutateAsync } = useGuestBook(); + // const { mutate, mutateAsync } = useGuestBook(); const handleClick = () => { const formData = { From 248e54a92e0543461ea89cec170eebf0b7615466 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Fri, 6 Dec 2024 18:06:59 +0900 Subject: [PATCH 42/49] =?UTF-8?q?fix:=20narrowDropDown=20=EC=BB=B4?= =?UTF-8?q?=ED=8F=AC=EB=84=8C=ED=8A=B8=20=ED=8F=B4=EB=8D=94=20=EC=A0=9C?= =?UTF-8?q?=EA=B1=B0=20=EC=95=88=20=EB=90=98=EC=96=B4=EC=84=9C=20=EC=83=9D?= =?UTF-8?q?=EA=B8=B0=EB=8A=94=20=EC=98=A4=EB=A5=98=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../narrowDropDown/NarrowDropDown.styled.ts | 107 ------------- .../narrowDropDown/NarrowDropDown.tsx | 144 ------------------ 2 files changed, 251 deletions(-) delete mode 100644 src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.styled.ts delete mode 100644 src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx diff --git a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.styled.ts b/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.styled.ts deleted file mode 100644 index 4b37b8bc..00000000 --- a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.styled.ts +++ /dev/null @@ -1,107 +0,0 @@ -import SvgIconChevronBack from "@assets/svgs/IconChevronBack"; -import styled, { css } from "styled-components"; - -export const DropdownWrapper = styled.div` - position: relative; -`; - -export const DropdownButton = styled.button<{ $isChoosed: boolean }>` - display: inline-flex; - flex-shrink: 0; - gap: 0.6rem; - align-items: center; - min-width: 9.3rem; - height: 4rem; - padding: 0.8rem 0.8rem 0.8rem 1.2rem; - - /* border: 1px solid - ${({ theme, $isChoosed }) => ($isChoosed ? theme.colors.gray_0 : theme.colors.gray_700)}; */ - border-radius: 0.4rem; -`; - -export const DropDownButtonContent = styled.div` - display: flex; - gap: 0.4rem; - align-items: center; - justify-content: space-between; - width: 100%; -`; - -export const ButtonContentSpan = styled.span` - color: ${({ theme }) => theme.colors.gray_0}; - ${({ theme }) => theme.fonts["body2-normal-medi"]}; -`; - -export const SvgIcon = styled(SvgIconChevronBack)<{ $rotate: boolean }>` - width: 16px; - height: 16px; - - transform: rotate(180deg); - - ${(prop) => - prop.$rotate && - css` - transform: rotate(360deg); - `} -`; - -export const DropdownContentWrapper = styled.div<{ $show: boolean }>` - position: absolute; - top: 4.06rem; /* 버튼의 높이 3.26rem + 간격 0.8rem */ - z-index: 1; - display: ${(props) => (props.$show ? "flex" : "none")}; - flex-shrink: 0; - gap: 0.6rem; - align-items: center; - width: 9.2rem; - margin-top: 0.8rem; - padding: 0.8rem 0.8rem 0.8rem 1.2rem; - - background-color: ${({ theme }) => theme.colors.black}; - border: 1px solid ${({ theme }) => theme.colors.gray_400}; - border-radius: 0.4rem; -`; - -export const DropdownContentLayout = styled.div` - display: flex; - flex-direction: column; - gap: 0.6rem; - align-items: flex-start; - justify-content: center; -`; - -export const DropdownContentButton = styled.button<{ $isLast: boolean }>` - display: flex; - flex-direction: column; - gap: 0.8rem; - align-items: flex-start; - width: 6.8rem; - - /* 피그마에서는 겹치는 부분이 제대로 계산 안되서, 개발하면서 적당히 줄여둠 */ - padding: 0.2rem 0 0.6rem; - - ${({ $isLast }) => - !$isLast && - css` - border-bottom: 1px solid ${({ theme }) => theme.colors.gray_700}; - `} -`; - -export const DropdownContentText = styled.span<{ - $selected: boolean; -}>` - display: flex; - gap: 0.4rem; - align-items: center; - align-self: stretch; - justify-content: flex-start; - - color: ${({ theme }) => theme.colors.gray_0}; - ${({ theme }) => theme.fonts["body2-normal-medi"]}; - - ${({ $selected }) => - $selected && - css` - color: ${({ theme }) => theme.colors.pink_400}; - `} -`; diff --git a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx b/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx deleted file mode 100644 index 37d78ff1..00000000 --- a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx +++ /dev/null @@ -1,144 +0,0 @@ -import { ReactNode, useState } from "react"; -import * as S from "./NarrowDropDown.styled"; - -interface DropdownProps { - children: ReactNode; - totalScheduleCount: number; - schedule: number; - payment: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | undefined; - setSchedule?: (param: number) => void; - setPayment?: ( - param: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | undefined - ) => void; -} - -const NarrowDropDown = ({ - children, - totalScheduleCount, - schedule, - payment, - setSchedule, - setPayment, -}: DropdownProps) => { - const [showDropdown, setShowDropdown] = useState<boolean>(false); - const [isOneChoosed, setIsOneChoosed] = useState(false); - - const handleToggle = () => { - setShowDropdown(!showDropdown); - }; - - const renderDropdownContent = (count: number, childrenNode: ReactNode) => { - const items = []; - const childrenString = childrenNode?.toString(); - if (childrenString === "모든 회차") { - const handleScheduleAll = () => { - setSchedule?.(0); - setIsOneChoosed(false); - setShowDropdown(false); - }; - items.push( - <S.DropdownContentButton - key={"dropdown-all-schedule"} - $isLast={false} - onClick={handleScheduleAll} - > - <S.DropdownContentText $selected={schedule === 0}>전체</S.DropdownContentText> - </S.DropdownContentButton> - ); - for (let i = 1; i <= count; i++) { - const handleSchedule = () => { - setSchedule?.(i); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - items.push( - <S.DropdownContentButton - key={`dropdown-${i}`} - $isLast={i === count} - onClick={handleSchedule} - > - <S.DropdownContentText $selected={schedule === i}>{i}회차</S.DropdownContentText> - </S.DropdownContentButton> - ); - } - } else if (childrenString === "입금 상태") { - const handlePaymentUndefined = () => { - setPayment?.(undefined); - setIsOneChoosed(false); - setShowDropdown(false); - }; - - const handlePaymentFalse = () => { - setPayment?.("CHECKING_PAYMENT"); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - const handlePaymentTrue = () => { - setPayment?.("BOOKING_CONFIRMED"); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - items.push( - <S.DropdownContentButton - key={"dropdown-all-payment"} - $isLast={false} - onClick={handlePaymentUndefined} - > - <S.DropdownContentText $selected={payment === undefined}>전체</S.DropdownContentText> - </S.DropdownContentButton> - ); - - items.push( - <S.DropdownContentButton key={"dropdown-1"} $isLast={false} onClick={handlePaymentFalse}> - <S.DropdownContentText $selected={payment === "CHECKING_PAYMENT"}> - 미입금 - </S.DropdownContentText> - </S.DropdownContentButton> - ); - items.push( - <S.DropdownContentButton key={"dropdown-2"} $isLast={true} onClick={handlePaymentTrue}> - <S.DropdownContentText $selected={payment === "BOOKING_CONFIRMED"}> - 입금완료 - </S.DropdownContentText> - </S.DropdownContentButton> - ); - } - - return items; - }; - - //공연별로 총 회차 값으로 넘겨주기로 함. - //각 공연별 회차는, DB 테이블 구조에 따라 enum값으로 넘겨주기로 함 - //필터링은 회차 번호(scheduleNumber : FIRST, SECOND, THIRD), 입금 완료 여부는 paymentStatus에 따라 나뉠거임 - // - - let changedChildren; - if (children === "입금 상태" && payment !== undefined) { - changedChildren = payment === "BOOKING_CONFIRMED" ? "입금완료" : "미입금"; - } else if (children === "모든 회차" && schedule !== 0) { - changedChildren = `${schedule}회차`; - } - - return ( - <S.DropdownWrapper> - <S.DropdownButton $isChoosed={isOneChoosed} onClick={handleToggle}> - <S.DropDownButtonContent> - <S.ButtonContentSpan> - {changedChildren === undefined ? children : changedChildren} - </S.ButtonContentSpan> - <S.SvgIcon $rotate={showDropdown} /> - </S.DropDownButtonContent> - </S.DropdownButton> - <S.DropdownContentWrapper $show={showDropdown}> - <S.DropdownContentLayout> - {renderDropdownContent(totalScheduleCount, children)} - </S.DropdownContentLayout> - </S.DropdownContentWrapper> - </S.DropdownWrapper> - ); -}; - -export default NarrowDropDown; From 45255014156ea3add461cc84becff9726e855966 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 9 Dec 2024 20:45:58 +0900 Subject: [PATCH 43/49] =?UTF-8?q?fix:=20#454=20PR=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EB=B0=98=EC=98=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/apis/domains/tickets/queries.ts | 10 ++++------ src/assets/svgs/index.tsx | 3 --- src/pages/ticketholderlist/TicketHolderList.tsx | 6 +----- 3 files changed, 5 insertions(+), 14 deletions(-) diff --git a/src/apis/domains/tickets/queries.ts b/src/apis/domains/tickets/queries.ts index be201983..1088484b 100644 --- a/src/apis/domains/tickets/queries.ts +++ b/src/apis/domains/tickets/queries.ts @@ -20,6 +20,7 @@ export const useTicketRetrive = (formData: getTicketReq, filterList) => { return useQuery({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST], queryFn: () => getTicketRetrieve(formData, filterList), + staleTime: 1000 * 60 * 60, gcTime: 1000 * 60 * 60 * 24, }); }; @@ -30,14 +31,15 @@ export const useTicketRetriveSearch = (formData: getTicketReq, searchWord, filte return useQuery({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST], queryFn: () => getTicketRetrieveSearch(formData, searchWord, filterList), + staleTime: 1000 * 60 * 60, gcTime: 1000 * 60 * 60 * 24, }); }; +const queryClient = new QueryClient(); + // 예매자 입급 여부 수정 API (PUT)를 위한 쿼리 작성 export const useTicketUpdate = () => { - const queryClient = new QueryClient(); - return useMutation({ mutationFn: (formData: TicketUpdateRequest) => putTicketUpdate(formData), onSuccess: (res) => { @@ -49,8 +51,6 @@ export const useTicketUpdate = () => { // 예매자 환불 여부 수정 API (PUT)를 위한 쿼리 작성 export const useTicketRefund = () => { - const queryClient = new QueryClient(); - return useMutation({ mutationFn: (formData: TicketRefundRequest) => putTicketRefund(formData), onSuccess: (res) => { @@ -62,8 +62,6 @@ export const useTicketRefund = () => { // 예매자 삭제 여부 수정 API (PUT)를 위한 쿼리 작성 export const useTicketDelete = () => { - const queryClient = new QueryClient(); - return useMutation({ mutationFn: (formData: TicketDeleteRequest) => putTicketDelete(formData), onSuccess: (res) => { diff --git a/src/assets/svgs/index.tsx b/src/assets/svgs/index.tsx index 73ee71f1..86a470ce 100644 --- a/src/assets/svgs/index.tsx +++ b/src/assets/svgs/index.tsx @@ -63,11 +63,8 @@ export { default as IconWoochaegook } from "./IconWoochaegook"; export { default as IconWoori } from "./IconWoori"; export { default as IconXButton } from "./IconXButton"; export { default as IcOutlinePlace } from "./IcOutlinePlace"; -<<<<<<< HEAD -======= export { default as IcRadioSelected } from "./IcRadioSelected"; export { default as IcRadioUnselected } from "./IcRadioUnselected"; ->>>>>>> c37fa02533a10b8b687d8dbca84207cab84d4a9f export { default as IcRefresh } from "./IcRefresh"; export { default as KakaoMapArrow } from "./KakaoMapArrow"; export { default as NotFoundAsset } from "./NotFoundAsset"; diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index e9ff0084..ef917726 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -288,11 +288,7 @@ const TicketHolderList = () => { // 필터 바텀시트 const handleFilterSheet = () => { - if (!openFilter) { - setOpenFilter(true); - } else { - setOpenFilter(false); - } + setOpenFilter((prev) => !prev); }; const handleFilter = async (scheduleNumber: number[], bookingStatus: string[]) => { From eed838963ef65b72d32a230f3f3c3d660adcb725 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 9 Dec 2024 21:25:30 +0900 Subject: [PATCH 44/49] =?UTF-8?q?feat:=20=EC=84=A0=ED=83=9D=EB=90=9C=20?= =?UTF-8?q?=EB=82=B4=EC=97=AD=20=EC=97=86=EC=9D=84=20=EB=95=8C=20=EB=B9=84?= =?UTF-8?q?=ED=99=9C=EC=84=B1=ED=99=94=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FilterBottomSheet/FilterBottomSheet.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx index a2aae9b5..05776658 100644 --- a/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx +++ b/src/pages/ticketholderlist/components/FilterBottomSheet/FilterBottomSheet.tsx @@ -32,6 +32,8 @@ const FilterBottomSheet = ({ filterList.scheduleNumber ); + const initList = filterList; + const handleWrapperClick = () => { onClickOutside(); }; @@ -77,6 +79,12 @@ const FilterBottomSheet = ({ setCheckedStatusList([]); }; + const isAllEmpty = + initList.scheduleNumber.length === 0 && + initList.bookingStatus.length === 0 && + checkedStatusList.length === 0 && + checkedScheduleList.length === 0; + return ( <S.FilterBottomSheetWrapper $isOpen={isOpen} onClick={handleWrapperClick}> <BottomSheet isOpen={isOpen}> @@ -118,8 +126,11 @@ const FilterBottomSheet = ({ ))} </S.CheckBoxContainer> <Spacing marginBottom="3.2" /> - {/* TODO : 선택된 내역 없을 때 버튼 비활성화 하기 */} - <Button onClick={handleCilckBtn}>적용하기</Button> + {isAllEmpty ? ( + <Button variant="gray">적용하기</Button> + ) : ( + <Button onClick={handleCilckBtn}>적용하기</Button> + )} </BottomSheet> </S.FilterBottomSheetWrapper> ); From 9d726037ce6a6333563f2517659a7e3e5e50470a Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 9 Dec 2024 23:06:19 +0900 Subject: [PATCH 45/49] =?UTF-8?q?design:=20=EA=B2=80=EC=83=89=20=EB=B0=94?= =?UTF-8?q?=20=EB=82=B4=20=EB=88=84=EB=9D=BD=EB=90=9C=20=EC=95=84=EC=9D=B4?= =?UTF-8?q?=EC=BD=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/svgs/IconSearch.tsx | 2 +- .../components/searchBar/SearchBar.styled.ts | 30 +++++++++++++++---- .../components/searchBar/SearchBar.tsx | 16 +++++----- 3 files changed, 34 insertions(+), 14 deletions(-) diff --git a/src/assets/svgs/IconSearch.tsx b/src/assets/svgs/IconSearch.tsx index 9ee48803..6305f24d 100644 --- a/src/assets/svgs/IconSearch.tsx +++ b/src/assets/svgs/IconSearch.tsx @@ -3,7 +3,7 @@ import type { SVGProps } from "react"; const SvgIconSearch = (props: SVGProps<SVGSVGElement>) => ( <svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" {...props}> <path - fill="#F4F4F4" + fill="current" fillRule="evenodd" d="M6.964 6.964a5 5 0 1 1 7.072 7.071 5 5 0 0 1-7.072-7.07m-1.06-1.06a6.5 6.5 0 0 0 8.631 9.692l3.934 3.934a.75.75 0 1 0 1.06-1.06l-3.934-3.934a6.5 6.5 0 0 0-9.691-8.632" clipRule="evenodd" diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts index 613fb5bf..afd067f5 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts @@ -1,5 +1,5 @@ import styled from "styled-components"; -import { BtnFilter } from "@assets/svgs"; +import { BtnFilter, IconSearch } from "@assets/svgs"; export const SearchBarWrapper = styled.section` display: flex; @@ -7,19 +7,37 @@ export const SearchBarWrapper = styled.section` align-items: center; width: 32.7rem; `; - -export const SearchBar = styled.input` +export const SearchBarLayout = styled.section` + display: flex; flex-grow: 1; height: 4.8rem; - padding: 1.3rem; + padding: 1.2rem 1.3rem; - color: ${({ theme }) => theme.colors.white}; - ${({ theme }) => theme.fonts["body2-normal-medi"]}; background-color: ${({ theme }) => theme.colors.gray_800}; border: 0.1rem solid; border-color: ${({ theme }) => theme.colors.gray_700}; border-radius: 4rem; + + align-items: center; +`; + +export const SearchIcon = styled(IconSearch)` + width: 2.4rem; + height: 2.4rem; + + path { + fill: ${({ theme }) => theme.colors.gray_300}; + } +`; + +export const SearchBar = styled.input` + height: 2.4rem; + + color: ${({ theme }) => theme.colors.white}; + ${({ theme }) => theme.fonts["body2-normal-medi"]}; + + background-color: ${({ theme }) => theme.colors.gray_800}; `; export const FilterBtn = styled(BtnFilter)<{ $isFilter: boolean }>` diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx index ef1a41a2..88f66bf2 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.tsx @@ -9,7 +9,6 @@ interface SearchBarProps { isFilter: boolean; } -// TODO: 필터 적용되었을 때 아웃라인 색상 적용 -> 기능 붙일 때 같이 하기 const SearchBar = ({ handleFilterSheet, status, @@ -19,12 +18,15 @@ const SearchBar = ({ }: SearchBarProps) => { return ( <S.SearchBarWrapper> - <S.SearchBar - type="text" - placeholder="예매자를 검색해보세요." - value={searchWord} - onChange={handleInputChange} - ></S.SearchBar> + <S.SearchBarLayout> + <S.SearchIcon /> + <S.SearchBar + type="text" + placeholder="예매자를 검색해보세요." + value={searchWord} + onChange={handleInputChange} + ></S.SearchBar> + </S.SearchBarLayout> {status === "DEFAULT" && <S.FilterBtn onClick={handleFilterSheet} $isFilter={isFilter} />} </S.SearchBarWrapper> ); From 6d7bd4726765fa907dd06ab5965cdda6b1269363 Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 9 Dec 2024 23:20:39 +0900 Subject: [PATCH 46/49] =?UTF-8?q?delete:=20narrowDropDown=20=ED=8F=B4?= =?UTF-8?q?=EB=8D=94=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../narrowDropDown/NarrowDropDown.tsx | 156 ------------------ 1 file changed, 156 deletions(-) delete mode 100644 src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx diff --git a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx b/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx deleted file mode 100644 index b99ec93a..00000000 --- a/src/pages/ticketholderlist/components/narrowDropDown/NarrowDropDown.tsx +++ /dev/null @@ -1,156 +0,0 @@ -import { ReactNode, useState } from "react"; -import * as S from "./NarrowDropDown.styled"; - -interface DropdownProps { - children: ReactNode; - totalScheduleCount: number; - schedule: number; - payment: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED" - | undefined; - setSchedule?: (param: number) => void; - setPayment?: ( - param: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED" - | undefined - ) => void; -} - -const NarrowDropDown = ({ - children, - totalScheduleCount, - schedule, - payment, - setSchedule, - setPayment, -}: DropdownProps) => { - const [showDropdown, setShowDropdown] = useState<boolean>(false); - const [isOneChoosed, setIsOneChoosed] = useState(false); - - const handleToggle = () => { - setShowDropdown(!showDropdown); - }; - - const renderDropdownContent = (count: number, childrenNode: ReactNode) => { - const items = []; - const childrenString = childrenNode?.toString(); - if (childrenString === "모든 회차") { - const handleScheduleAll = () => { - setSchedule?.(0); - setIsOneChoosed(false); - setShowDropdown(false); - }; - items.push( - <S.DropdownContentButton - key={"dropdown-all-schedule"} - $isLast={false} - onClick={handleScheduleAll} - > - <S.DropdownContentText $selected={schedule === 0}>전체</S.DropdownContentText> - </S.DropdownContentButton> - ); - for (let i = 1; i <= count; i++) { - const handleSchedule = () => { - setSchedule?.(i); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - items.push( - <S.DropdownContentButton - key={`dropdown-${i}`} - $isLast={i === count} - onClick={handleSchedule} - > - <S.DropdownContentText $selected={schedule === i}>{i}회차</S.DropdownContentText> - </S.DropdownContentButton> - ); - } - } else if (childrenString === "입금 상태") { - const handlePaymentUndefined = () => { - setPayment?.(undefined); - setIsOneChoosed(false); - setShowDropdown(false); - }; - - const handlePaymentFalse = () => { - setPayment?.("CHECKING_PAYMENT"); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - const handlePaymentTrue = () => { - setPayment?.("BOOKING_CONFIRMED"); - setIsOneChoosed(true); - setShowDropdown(false); - }; - - items.push( - <S.DropdownContentButton - key={"dropdown-all-payment"} - $isLast={false} - onClick={handlePaymentUndefined} - > - <S.DropdownContentText $selected={payment === undefined}>전체</S.DropdownContentText> - </S.DropdownContentButton> - ); - - items.push( - <S.DropdownContentButton key={"dropdown-1"} $isLast={false} onClick={handlePaymentFalse}> - <S.DropdownContentText $selected={payment === "CHECKING_PAYMENT"}> - 미입금 - </S.DropdownContentText> - </S.DropdownContentButton> - ); - items.push( - <S.DropdownContentButton key={"dropdown-2"} $isLast={true} onClick={handlePaymentTrue}> - <S.DropdownContentText $selected={payment === "BOOKING_CONFIRMED"}> - 입금완료 - </S.DropdownContentText> - </S.DropdownContentButton> - ); - } - - return items; - }; - - //공연별로 총 회차 값으로 넘겨주기로 함. - //각 공연별 회차는, DB 테이블 구조에 따라 enum값으로 넘겨주기로 함 - //필터링은 회차 번호(scheduleNumber : FIRST, SECOND, THIRD), 입금 완료 여부는 paymentStatus에 따라 나뉠거임 - // - - let changedChildren; - if (children === "입금 상태" && payment !== undefined) { - changedChildren = payment === "BOOKING_CONFIRMED" ? "입금완료" : "미입금"; - } else if (children === "모든 회차" && schedule !== 0) { - changedChildren = `${schedule}회차`; - } - - return ( - <S.DropdownWrapper> - <S.DropdownButton $isChoosed={isOneChoosed} onClick={handleToggle}> - <S.DropDownButtonContent> - <S.ButtonContentSpan> - {changedChildren === undefined ? children : changedChildren} - </S.ButtonContentSpan> - <S.SvgIcon $rotate={showDropdown} /> - </S.DropDownButtonContent> - </S.DropdownButton> - <S.DropdownContentWrapper $show={showDropdown}> - <S.DropdownContentLayout> - {renderDropdownContent(totalScheduleCount, children)} - </S.DropdownContentLayout> - </S.DropdownContentWrapper> - </S.DropdownWrapper> - ); -}; - -export default NarrowDropDown; From 8aea7a0c6a85ca35676c57e4fc15e36de616c32f Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Mon, 9 Dec 2024 23:46:33 +0900 Subject: [PATCH 47/49] =?UTF-8?q?HOTFIX:=20yarn=20build=20=EC=8B=9C=20?= =?UTF-8?q?=EB=82=98=EC=98=A4=EB=8A=94=20=ED=83=80=EC=9E=85=20=EC=97=90?= =?UTF-8?q?=EB=9F=AC=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../components/searchBar/SearchBar.styled.ts | 4 +- .../ticketholderlist/types/bookingListType.ts | 29 +- src/typings/api/schema/index.ts | 5368 ++++++++--------- 3 files changed, 2500 insertions(+), 2901 deletions(-) diff --git a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts index afd067f5..51a9defd 100644 --- a/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts +++ b/src/pages/ticketholderlist/components/searchBar/SearchBar.styled.ts @@ -10,16 +10,14 @@ export const SearchBarWrapper = styled.section` export const SearchBarLayout = styled.section` display: flex; flex-grow: 1; + align-items: center; height: 4.8rem; padding: 1.2rem 1.3rem; - background-color: ${({ theme }) => theme.colors.gray_800}; border: 0.1rem solid; border-color: ${({ theme }) => theme.colors.gray_700}; border-radius: 4rem; - - align-items: center; `; export const SearchIcon = styled(IconSearch)` diff --git a/src/pages/ticketholderlist/types/bookingListType.ts b/src/pages/ticketholderlist/types/bookingListType.ts index c6de4ab1..7028d775 100644 --- a/src/pages/ticketholderlist/types/bookingListType.ts +++ b/src/pages/ticketholderlist/types/bookingListType.ts @@ -1,13 +1,20 @@ +type PaymentType = + | "CHECKING_PAYMENT" + | "BOOKING_CONFIRMED" + | "BOOKING_CANCELLED" + | "REFUND_REQUESTED" + | "BOOKING_DELETED"; + export interface BookingListProps { - bookingId: number; - bookerName: string; - bookerPhoneNumber: string; - scheduleId: number; - purchaseTicketCount: number; - createdAt: string; - bookingStatus: string; - scheduleNumber: string; - bankName: string; - accountNumber: string; - accountHolder: string; + bookingId?: number; + bookerName?: string; + bookerPhoneNumber?: string; + scheduleId?: number; + purchaseTicketCount?: number; + createdAt?: string; + bookingStatus?: PaymentType; + scheduleNumber?: string; + bankName?: string; + accountNumber?: string; + accountHolder?: string; } diff --git a/src/typings/api/schema/index.ts b/src/typings/api/schema/index.ts index ce317b37..67e0a120 100644 --- a/src/typings/api/schema/index.ts +++ b/src/typings/api/schema/index.ts @@ -4,2900 +4,2494 @@ */ export interface paths { - "/api/tickets/update": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; + "/api/tickets/update": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * 예매자 입금여부 수정 및 웹발신 API + * @description 메이커가 자신의 공연에 대한 예매자의 입금여부 정보를 수정한 뒤 예매확정 웹발신을 보내는 PUT API입니다. + */ + put: operations["updateTickets"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tickets/refund": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * 예매자 환불처리 API + * @description 메이커가 자신의 공연에 대한 1명 이상의 예매자의 정보를 환불완료 상태로 변경하는 PUT API입니다. + */ + put: operations["refundTickets"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tickets/delete": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * 예매자 삭제 API + * @description 메이커가 자신의 공연에 대한 1명 이상의 예매자의 정보를 삭제하는 PUT API입니다. + */ + put: operations["deleteTickets"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/performances": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + /** + * 공연 정보 수정 API + * @description 공연 정보를 수정하는 PUT API입니다. + */ + put: operations["updatePerformance"]; + /** + * 공연 생성 API + * @description 공연을 생성하는 POST API입니다. + */ + post: operations["createPerformance"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/admin/carousels": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 캐러셀에 등록된 모든 공연 정보 조회 + * @description 관리자가 현재 캐러셀에 등록된 모든 공연 정보를 조회하는 GET API + */ + get: operations["readAllCarouselImages"]; + /** + * 캐러셀 이미지 수정 + * @description 관리자가 캐러셀 이미지를 수정하는 PUT API + */ + put: operations["processCarouselImages"]; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/sign-up": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 로그인/회원가입 API + * @description 로그인/회원가입하는 POST API입니다. + */ + post: operations["signUp"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/sign-out": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 로그아웃 API + * @description 로그아웃하는 POST API입니다. + */ + post: operations["signOut"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/bookings/member": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 회원 예매 API + * @description 회원이 예매를 요청하는 POST API입니다. + */ + post: operations["createMemberBooking"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/bookings/guest": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 비회원 예매 API + * @description 비회원이 예매를 요청하는 POST API입니다. + */ + post: operations["createGuestBookings"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/bookings/guest/retrieve": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + /** + * 비회원 예매 조회 API + * @description 비회원이 예매를 조회하는 POST API입니다. + */ + post: operations["getGuestBookings"]; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/bookings/refund": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** + * 유료공연 예매 환불 요청 API + * @description 유료공연 예매자가 환불 요청하는 PATCH API입니다. + */ + patch: operations["refundBookings"]; + trace?: never; + }; + "/api/bookings/cancel": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + get?: never; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + /** + * 무료공연/미입금 예매 취소 요청 API + * @description 무료공연/미입금 예매자가 취소 요청하는 PATCH API입니다. + */ + patch: operations["cancelBookings"]; + trace?: never; + }; + "/health-check": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 헬스 체크 조회 API + * @description 서버 상태를 확인하기 위한 헬스 체크 API로, 정상적으로 동작할 경우 'OK' 문자열을 반환합니다. + */ + get: operations["healthcheck"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/users/refresh-token": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * access token 재발급 API + * @description refresh token으로 access token을 재발급하는 GET API입니다. + */ + get: operations["issueAccessTokenUsingRefreshToken"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tickets/{performanceId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 예매자 목록 조회 API + * @description 메이커가 자신의 공연에 대한 예매자 목록을 조회하는 GET API입니다. + */ + get: operations["getTickets"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/tickets/search/{performanceId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 예매자 목록 검색 API + * @description 메이커가 자신의 공연에 대한 예매자 목록을 검색하는 GET API입니다. + */ + get: operations["searchTickets"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/schedules/{scheduleId}/availability": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 티켓 구매 가능 여부 조회 API + * @description 티켓 구매 가능 여부를 확인하는 GET API입니다. + */ + get: operations["getTicketAvailability"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/performances/{performanceId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 공연 수정 페이지 정보 조회 API + * @description 공연 정보를 조회하는 GET API입니다. + */ + get: operations["getPerformanceForEdit"]; + put?: never; + post?: never; + /** + * 공연 삭제 API + * @description 공연을 삭제하는 DELETE API입니다. + */ + delete: operations["deletePerformance"]; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/performances/user": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 회원이 등록한 공연 목록 조회 API + * @description 회원이 등록한 공연 목록을 조회하는 GET API입니다. + */ + get: operations["getUserPerformances"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/performances/detail/{performanceId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 공연 상세정보 조회 API + * @description 공연 상세페이지의 공연 상세정보를 조회하는 GET API입니다. + */ + get: operations["getPerformanceDetail"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/performances/booking/{performanceId}": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 예매하기 관련 공연 정보 조회 API + * @description 예매하기 페이지에서 필요한 예매 관련 공연 정보를 조회하는 GET API입니다. + */ + get: operations["getBookingPerformanceDetail"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/main": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 전체 공연 및 홍보 목록 조회 + * @description 홈 화면에서 전체 공연 목록 및 홍보 목록을 조회하는 GET API + */ + get: operations["getHomePerformanceList"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/files/presigned-url": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 공연 이미지 업로드 Presigned URL 발급 + * @description 공연 등록 시 업로드할 이미지에 대한 presigned URL을 발급 받는 GET API + */ + get: operations["generateAllPresignedUrls"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/bookings/member/retrieve": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 회원 예매 조회 API + * @description 회원이 예매를 조회하는 GET API입니다. + */ + get: operations["getMemberBookings"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/admin/users": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 유저 정보 조회 + * @description 관리자가 유저들의 정보를 조회하는 GET API + */ + get: operations["readAllUsers"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/admin/carousels/presigned-url": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 캐러셀에 업로드 할 이미지에 대한 presigned URL 발급 + * @description 관리자가 캐러셀에 업로드 할 이미지에 대한 presigned URL을 발급 받는 GET API + */ + get: operations["createAllCarouselPresignedUrls"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; + }; + "/api/admin/banner/presigned-url": { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + /** + * 배너에 업로드 할 이미지에 대한 presigned URL 발급 + * @description 관리자가 배너에 업로드 할 이미지에 대한 presigned URL을 발급 받는 GET API + */ + get: operations["createBannerPresignedUrl"]; + put?: never; + post?: never; + delete?: never; + options?: never; + head?: never; + patch?: never; + trace?: never; }; - get?: never; - /** - * 예매자 입금여부 수정 및 웹발신 API - * @description 메이커가 자신의 공연에 대한 예매자의 입금여부 정보를 수정한 뒤 예매확정 웹발신을 보내는 PUT API입니다. - */ - put: operations["updateTickets"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/tickets/refund": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** - * 예매자 환불처리 API - * @description 메이커가 자신의 공연에 대한 1명 이상의 예매자의 정보를 환불완료 상태로 변경하는 PUT API입니다. - */ - put: operations["refundTickets"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/tickets/delete": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** - * 예매자 삭제 API - * @description 메이커가 자신의 공연에 대한 1명 이상의 예매자의 정보를 삭제하는 PUT API입니다. - */ - put: operations["deleteTickets"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/performances": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - /** - * 공연 정보 수정 API - * @description 공연 정보를 수정하는 PUT API입니다. - */ - put: operations["updatePerformance"]; - /** - * 공연 생성 API - * @description 공연을 생성하는 POST API입니다. - */ - post: operations["createPerformance"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/admin/carousels": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 캐러셀에 등록된 모든 공연 정보 조회 - * @description 관리자가 현재 캐러셀에 등록된 모든 공연 정보를 조회하는 GET API - */ - get: operations["readAllCarouselImages"]; - /** - * 캐러셀 이미지 수정 - * @description 관리자가 캐러셀 이미지를 수정하는 PUT API - */ - put: operations["processCarouselImages"]; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/users/sign-up": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * 로그인/회원가입 API - * @description 로그인/회원가입하는 POST API입니다. - */ - post: operations["signUp"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/users/sign-out": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * 로그아웃 API - * @description 로그아웃하는 POST API입니다. - */ - post: operations["signOut"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/bookings/member": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * 회원 예매 API - * @description 회원이 예매를 요청하는 POST API입니다. - */ - post: operations["createMemberBooking"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/bookings/guest": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * 비회원 예매 API - * @description 비회원이 예매를 요청하는 POST API입니다. - */ - post: operations["createGuestBookings"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/bookings/guest/retrieve": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - /** - * 비회원 예매 조회 API - * @description 비회원이 예매를 조회하는 POST API입니다. - */ - post: operations["getGuestBookings"]; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/bookings/refund": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** - * 유료공연 예매 환불 요청 API - * @description 유료공연 예매자가 환불 요청하는 PATCH API입니다. - */ - patch: operations["refundBookings"]; - trace?: never; - }; - "/api/bookings/cancel": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - get?: never; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - /** - * 무료공연/미입금 예매 취소 요청 API - * @description 무료공연/미입금 예매자가 취소 요청하는 PATCH API입니다. - */ - patch: operations["cancelBookings"]; - trace?: never; - }; - "/health-check": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 헬스 체크 조회 API - * @description 서버 상태를 확인하기 위한 헬스 체크 API로, 정상적으로 동작할 경우 'OK' 문자열을 반환합니다. - */ - get: operations["healthcheck"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/users/refresh-token": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * access token 재발급 API - * @description refresh token으로 access token을 재발급하는 GET API입니다. - */ - get: operations["refreshToken"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/tickets/{performanceId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 예매자 목록 조회 API - * @description 메이커가 자신의 공연에 대한 예매자 목록을 조회하는 GET API입니다. - */ - get: operations["getTickets"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/tickets/search/{performanceId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 예매자 목록 검색 API - * @description 메이커가 자신의 공연에 대한 예매자 목록을 검색하는 GET API입니다. - */ - get: operations["searchTickets"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/schedules/{scheduleId}/availability": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 티켓 구매 가능 여부 조회 API - * @description 티켓 구매 가능 여부를 확인하는 GET API입니다. - */ - get: operations["getTicketAvailability"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/performances/{performanceId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 공연 수정 페이지 정보 조회 API - * @description 공연 정보를 조회하는 GET API입니다. - */ - get: operations["getPerformanceForEdit"]; - put?: never; - post?: never; - /** - * 공연 삭제 API - * @description 공연을 삭제하는 DELETE API입니다. - */ - delete: operations["deletePerformance"]; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/performances/user": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 회원이 등록한 공연 목록 조회 API - * @description 회원이 등록한 공연 목록을 조회하는 GET API입니다. - */ - get: operations["getUserPerformances"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/performances/detail/{performanceId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 공연 상세정보 조회 API - * @description 공연 상세페이지의 공연 상세정보를 조회하는 GET API입니다. - */ - get: operations["getPerformanceDetail"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/performances/booking/{performanceId}": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 예매하기 관련 공연 정보 조회 API - * @description 예매하기 페이지에서 필요한 예매 관련 공연 정보를 조회하는 GET API입니다. - */ - get: operations["getBookingPerformanceDetail"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/main": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 전체 공연 및 홍보 목록 조회 - * @description 홈 화면에서 전체 공연 목록 및 홍보 목록을 조회하는 GET API - */ - get: operations["getHomePerformanceList"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/files/presigned-url": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 공연 이미지 업로드 Presigned URL 발급 - * @description 공연 등록 시 업로드할 이미지에 대한 presigned URL을 발급 받는 GET API - */ - get: operations["generateAllPresignedUrls"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/bookings/member/retrieve": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 회원 예매 조회 API - * @description 회원이 예매를 조회하는 GET API입니다. - */ - get: operations["getMemberBookings"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/admin/users": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 유저 정보 조회 - * @description 관리자가 유저들의 정보를 조회하는 GET API - */ - get: operations["readAllUsers"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/admin/carousels/presigned-url": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 캐러셀에 업로드 할 이미지에 대한 presigned URL 발급 - * @description 관리자가 캐러셀에 업로드 할 이미지에 대한 presigned URL을 발급 받는 GET API - */ - get: operations["createAllCarouselPresignedUrls"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; - "/api/admin/banner/presigned-url": { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - /** - * 배너에 업로드 할 이미지에 대한 presigned URL 발급 - * @description 관리자가 배너에 업로드 할 이미지에 대한 presigned URL을 발급 받는 GET API - */ - get: operations["createBannerPresignedUrl"]; - put?: never; - post?: never; - delete?: never; - options?: never; - head?: never; - patch?: never; - trace?: never; - }; } export type webhooks = Record<string, never>; export interface components { - schemas: { - "com.beat.domain.booking.application.dto.TicketUpdateDetail": { - /** Format: int64 */ - bookingId?: number; - bookerName?: string; - bookerPhoneNumber?: string; - /** Format: int64 */ - scheduleId?: number; - /** Format: int32 */ - purchaseTicketCount?: number; - /** Format: date-time */ - createdAt?: string; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - scheduleNumber?: string; - }; - "com.beat.domain.booking.application.dto.TicketUpdateRequest": { - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** Format: int32 */ - totalScheduleCount?: number; - bookingList?: components["schemas"]["com.beat.domain.booking.application.dto.TicketUpdateDetail"][]; - }; - ErrorResponse: { - /** Format: int32 */ - status?: number; - message?: string; - }; - SuccessResponseVoid: { - /** Format: int32 */ - status?: number; - message?: string; - data?: Record<string, never>; - }; - Booking: { - /** Format: int64 */ - bookingId?: number; - }; - TicketRefundRequest: { - /** Format: int64 */ - performanceId?: number; - bookingList?: components["schemas"]["Booking"][]; - }; - TicketDeleteRequest: { - /** Format: int64 */ - performanceId?: number; - bookingList?: components["schemas"]["Booking"][]; - }; - CastModifyRequest: { - /** Format: int64 */ - performanceId?: number; - bookingList?: components["schemas"]["com.beat.domain.booking.application.dto.TicketRefundRequest$Booking"][]; - }; - "com.beat.domain.booking.application.dto.TicketRefundRequest$Booking": { - /** Format: int64 */ - bookingId?: number; - }; - "com.beat.domain.booking.application.dto.TicketDeleteRequest": { - /** Format: int64 */ - performanceId?: number; - bookingList?: components["schemas"]["com.beat.domain.booking.application.dto.TicketDeleteRequest$Booking"][]; - }; - "com.beat.domain.booking.application.dto.TicketDeleteRequest$Booking": { - /** Format: int64 */ - bookingId?: number; - }; - "com.beat.domain.performance.application.dto.modify.PerformanceModifyRequest": { - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** @enum {string} */ - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - /** Format: int32 */ - runningTime?: number; - performanceDescription?: string; - performanceAttentionNote?: string; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - posterImage?: string; - performanceTeamName?: string; - performanceVenue?: string; - roadAddressName?: string; - placeDetailAddress?: string; - latitude?: string; - longitude?: string; - performanceContact?: string; - performancePeriod?: string; - /** Format: int32 */ - totalScheduleCount?: number; - /** Format: int32 */ - ticketPrice?: number; - scheduleModifyRequests?: components["schemas"]["com.beat.domain.performance.application.dto.modify.schedule.ScheduleModifyRequest"][]; - castModifyRequests?: components["schemas"]["com.beat.domain.performance.application.dto.modify.cast.CastModifyRequest"][]; - staffModifyRequests?: components["schemas"]["com.beat.domain.performance.application.dto.modify.staff.StaffModifyRequest"][]; - performanceImageModifyRequests?: components["schemas"]["com.beat.domain.performance.application.dto.modify.performanceImage.PerformanceImageModifyRequest"][]; - }; - "com.beat.domain.performance.application.dto.modify.cast.CastModifyRequest": { - /** Format: int64 */ - castId?: number; - castName?: string; - castRole?: string; - castPhoto?: string; - }; - "com.beat.domain.performance.application.dto.modify.performanceImage.PerformanceImageModifyRequest": { - /** Format: int64 */ - performanceImageId?: number; - performanceImage?: string; - }; - "com.beat.domain.performance.application.dto.modify.schedule.ScheduleModifyRequest": { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - /** Format: int32 */ - totalTicketCount?: number; - }; - "com.beat.domain.performance.application.dto.modify.staff.StaffModifyRequest": { - /** Format: int64 */ - staffId?: number; - staffName?: string; - staffRole?: string; - staffPhoto?: string; - }; - "com.beat.domain.performance.application.dto.modify.PerformanceModifyResponse": { - /** Format: int64 */ - userId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** @enum {string} */ - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - /** Format: int32 */ - runningTime?: number; - performanceDescription?: string; - performanceAttentionNote?: string; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - posterImage?: string; - performanceTeamName?: string; - performanceVenue?: string; - roadAddressName?: string; - placeDetailAddress?: string; - latitude?: string; - longitude?: string; - performanceContact?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - totalScheduleCount?: number; - scheduleModifyResponses?: components["schemas"]["com.beat.domain.performance.application.dto.modify.schedule.ScheduleModifyResponse"][]; - castModifyResponses?: components["schemas"]["com.beat.domain.performance.application.dto.modify.cast.CastModifyResponse"][]; - staffModifyResponses?: components["schemas"]["com.beat.domain.performance.application.dto.modify.staff.StaffModifyResponse"][]; - performanceImageModifyResponses?: components["schemas"]["com.beat.domain.performance.application.dto.modify.performanceImage.PerformanceImageModifyResponse"][]; - }; - "com.beat.domain.performance.application.dto.modify.cast.CastModifyResponse": { - /** Format: int64 */ - castId?: number; - castName?: string; - castRole?: string; - castPhoto?: string; - }; - "com.beat.domain.performance.application.dto.modify.performanceImage.PerformanceImageModifyResponse": { - /** Format: int64 */ - performanceImageId?: number; - performanceImage?: string; - }; - "com.beat.domain.performance.application.dto.modify.schedule.ScheduleModifyResponse": { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - /** Format: int32 */ - totalTicketCount?: number; - /** Format: int32 */ - dueDate?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - }; - "com.beat.domain.performance.application.dto.modify.staff.StaffModifyResponse": { - /** Format: int64 */ - staffId?: number; - staffName?: string; - staffRole?: string; - staffPhoto?: string; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.modify.PerformanceModifyResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.performance.application.dto.modify.PerformanceModifyResponse"]; - }; - CarouselHandleRequest: { - carousels?: ( - | components["schemas"]["PromotionGenerateRequest"] - | components["schemas"]["PromotionModifyRequest"] - )[]; - }; - "com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionGenerateRequest": { - type: "com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionGenerateRequest"; - } & (Omit< - components["schemas"]["com.beat.admin.application.dto.request.PromotionHandleRequest"], - "type" - > & { - /** @enum {string} */ - carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; - newImageUrl?: string; - isExternal?: boolean; - redirectUrl?: string; - /** Format: int64 */ - performanceId?: number; - }); - "com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionModifyRequest": { - type: "com.beat.admin.application.dto.request.CarouselHandleRequest$PromotionModifyRequest"; - } & (Omit< - components["schemas"]["com.beat.admin.application.dto.request.PromotionHandleRequest"], - "type" - > & { - /** Format: int64 */ - promotionId?: number; - /** @enum {string} */ - carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; - newImageUrl?: string; - isExternal?: boolean; - redirectUrl?: string; - /** Format: int64 */ - performanceId?: number; - }); - CarouselHandleAllResponse: { - modifiedPromotions?: components["schemas"]["PromotionResponse"][]; - }; - PromotionResponse: { - /** Format: int64 */ - promotionId?: number; - newImageUrl?: string; - isExternal?: boolean; - redirectUrl?: string; - carouselNumber?: string; - }; - SuccessResponseCarouselHandleAllResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["CarouselHandleAllResponse"]; - }; - "com.beat.global.auth.client.dto.MemberLoginRequest": { - /** @enum {string} */ - socialType: "KAKAO"; - }; - "com.beat.domain.member.dto.LoginSuccessResponse": { - accessToken?: string; - refreshToken?: string; - nickname?: string; - role?: string; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.member.dto.LoginSuccessResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.member.dto.LoginSuccessResponse"]; - }; - "com.beat.domain.performance.application.dto.create.CastRequest": { - castName?: string; - castRole?: string; - castPhoto?: string; - }; - "com.beat.domain.performance.application.dto.create.PerformanceImageRequest": { - performanceImage?: string; - }; - "com.beat.domain.performance.application.dto.create.PerformanceRequest": { - performanceTitle?: string; - /** @enum {string} */ - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - /** Format: int32 */ - runningTime?: number; - performanceDescription?: string; - performanceAttentionNote?: string; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - posterImage?: string; - performanceTeamName?: string; - performanceVenue?: string; - roadAddressName?: string; - placeDetailAddress?: string; - latitude?: string; - longitude?: string; - performanceContact?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - totalScheduleCount?: number; - scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.create.ScheduleRequest"][]; - castList?: components["schemas"]["com.beat.domain.performance.application.dto.create.CastRequest"][]; - staffList?: components["schemas"]["com.beat.domain.performance.application.dto.create.StaffRequest"][]; - performanceImageList?: components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceImageRequest"][]; - }; - "com.beat.domain.performance.application.dto.create.ScheduleRequest": { - /** Format: date-time */ - performanceDate?: string; - /** Format: int32 */ - totalTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - }; - "com.beat.domain.performance.application.dto.create.StaffRequest": { - staffName?: string; - staffRole?: string; - staffPhoto?: string; - }; - "com.beat.domain.performance.application.dto.create.CastResponse": { - /** Format: int64 */ - castId?: number; - castName?: string; - castRole?: string; - castPhoto?: string; - }; - "com.beat.domain.performance.application.dto.create.PerformanceImageResponse": { - /** Format: int64 */ - imageId?: number; - imageUrl?: string; - }; - "com.beat.domain.performance.application.dto.create.PerformanceResponse": { - /** Format: int64 */ - userId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** @enum {string} */ - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - /** Format: int32 */ - runningTime?: number; - performanceDescription?: string; - performanceAttentionNote?: string; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - posterImage?: string; - performanceTeamName?: string; - performanceVenue?: string; - roadAddressName?: string; - placeDetailAddress?: string; - latitude?: string; - longitude?: string; - performanceContact?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - totalScheduleCount?: number; - scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.create.ScheduleResponse"][]; - castList?: components["schemas"]["com.beat.domain.performance.application.dto.create.CastResponse"][]; - staffList?: components["schemas"]["com.beat.domain.performance.application.dto.create.StaffResponse"][]; - performanceImageList?: components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceImageResponse"][]; - }; - "com.beat.domain.performance.application.dto.create.ScheduleResponse": { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - /** Format: int32 */ - totalTicketCount?: number; - /** Format: int32 */ - dueDate?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - }; - "com.beat.domain.performance.application.dto.create.StaffResponse": { - /** Format: int64 */ - staffId?: number; - staffName?: string; - staffRole?: string; - staffPhoto?: string; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.create.PerformanceResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceResponse"]; - }; - "com.beat.domain.booking.application.dto.MemberBookingRequest": { - /** Format: int64 */ - scheduleId?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - /** Format: int32 */ - purchaseTicketCount?: number; - bookerName?: string; - bookerPhoneNumber?: string; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - /** Format: int32 */ - totalPaymentAmount?: number; - }; - "com.beat.domain.booking.application.dto.MemberBookingResponse": { - /** Format: int64 */ - bookingId?: number; - /** Format: int64 */ - scheduleId?: number; - /** Format: int64 */ - userId?: number; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - bookerName?: string; - bookerPhoneNumber?: string; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - /** Format: date-time */ - createdAt?: string; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.MemberBookingResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.booking.application.dto.MemberBookingResponse"]; - }; - "com.beat.domain.booking.application.dto.GuestBookingRequest": { - /** Format: int64 */ - scheduleId?: number; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - bookerName?: string; - bookerPhoneNumber?: string; - birthDate?: string; - password?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - }; - "com.beat.domain.booking.application.dto.GuestBookingResponse": { - /** Format: int64 */ - bookingId?: number; - /** Format: int64 */ - scheduleId?: number; - /** Format: int64 */ - userId?: number; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - bookerName?: string; - bookerPhoneNumber?: string; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - /** Format: date-time */ - createdAt?: string; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.GuestBookingResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.booking.application.dto.GuestBookingResponse"]; - }; - "com.beat.domain.booking.application.dto.GuestBookingRetrieveRequest": { - bookerName?: string; - birthDate?: string; - bookerPhoneNumber?: string; - password?: string; - }; - "com.beat.domain.booking.application.dto.GuestBookingRetrieveResponse": { - /** Format: int64 */ - bookingId?: number; - /** Format: int64 */ - scheduleId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** Format: date-time */ - performanceDate?: string; - performanceVenue?: string; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - bookerName?: string; - performanceContact?: string; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - /** Format: int32 */ - dueDate?: number; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - /** Format: date-time */ - createdAt?: string; - posterImage?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - }; - "com.beat.global.common.dto.SuccessResponseJava.util.ListCom.beat.domain.booking.application.dto.GuestBookingRetrieveResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.booking.application.dto.GuestBookingRetrieveResponse"][]; - }; - BookingRefundRequest: { - /** Format: int64 */ - bookingId?: number; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - }; - BookingRefundResponse: { - /** Format: int64 */ - bookingId?: number; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - }; - SuccessResponseBookingRefundResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["BookingRefundResponse"]; - }; - BookingCancelRequest: { - /** Format: int64 */ - bookingId?: number; - }; - BookingCancelResponse: { - /** Format: int64 */ - bookingId?: number; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - }; - SuccessResponseBookingCancelResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["BookingCancelResponse"]; - }; - AccessTokenGetSuccess: { - accessToken?: string; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.BookingRefundResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.booking.application.dto.BookingRefundResponse"]; - }; - "com.beat.domain.booking.application.dto.BookingCancelRequest": { - /** Format: int64 */ - bookingId?: number; - }; - "com.beat.domain.booking.application.dto.BookingCancelResponse": { - /** Format: int64 */ - bookingId?: number; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.BookingCancelResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.booking.application.dto.BookingCancelResponse"]; - }; - "com.beat.domain.member.dto.AccessTokenGetSuccess": { - accessToken?: string; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.member.dto.AccessTokenGetSuccess": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.member.dto.AccessTokenGetSuccess"]; - }; - "com.beat.domain.booking.application.dto.TicketDetail": { - /** Format: int64 */ - bookingId?: number; - bookerName?: string; - bookerPhoneNumber?: string; - /** Format: int64 */ - scheduleId?: number; - /** Format: int32 */ - purchaseTicketCount?: number; - /** Format: date-time */ - createdAt?: string; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - scheduleNumber?: string; - bankName?: string; - accountNumber?: string; - accountHolder?: string; - }; - "com.beat.domain.booking.application.dto.TicketRetrieveResponse": { - performanceTitle?: string; - performanceTeamName?: string; - /** Format: int32 */ - totalScheduleCount?: number; - /** Format: int32 */ - totalPerformanceTicketCount?: number; - /** Format: int32 */ - totalPerformanceSoldTicketCount?: number; - bookingList?: components["schemas"]["TicketDetail"][]; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.booking.application.dto.TicketRetrieveResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.booking.application.dto.TicketRetrieveResponse"]; - }; - "com.beat.domain.schedule.application.dto.TicketAvailabilityResponse": { - /** Format: int64 */ - scheduleId?: number; - scheduleNumber?: string; - /** Format: int32 */ - totalTicketCount?: number; - /** Format: int32 */ - soldTicketCount?: number; - /** Format: int32 */ - availableTicketCount?: number; - /** Format: int32 */ - requestedTicketCount?: number; - isAvailable?: boolean; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.schedule.application.dto.TicketAvailabilityResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.schedule.application.dto.TicketAvailabilityResponse"]; - }; - "com.beat.domain.performance.application.dto.modify.PerformanceModifyDetailResponse": { - /** Format: int64 */ - userId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** @enum {string} */ - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - /** Format: int32 */ - runningTime?: number; - performanceDescription?: string; - performanceAttentionNote?: string; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - posterImage?: string; - performanceTeamName?: string; - performanceVenue?: string; - roadAddressName?: string; - placeDetailAddress?: string; - latitude?: string; - longitude?: string; - performanceContact?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - totalScheduleCount?: number; - isBookerExist?: boolean; - scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.create.ScheduleResponse"][]; - castList?: components["schemas"]["com.beat.domain.performance.application.dto.create.CastResponse"][]; - staffList?: components["schemas"]["com.beat.domain.performance.application.dto.create.StaffResponse"][]; - performanceImageList?: components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceImageResponse"][]; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.modify.PerformanceModifyDetailResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.performance.application.dto.modify.PerformanceModifyDetailResponse"]; - }; - "com.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceDetailResponse": { - /** Format: int64 */ - performanceId?: number; - genre?: string; - performanceTitle?: string; - posterImage?: string; - performancePeriod?: string; - /** Format: int32 */ - minDueDate?: number; - }; - "com.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceResponse": { - /** Format: int64 */ - userId?: number; - performances?: components["schemas"]["com.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceDetailResponse"][]; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.performance.application.dto.makerPerformance.MakerPerformanceResponse"]; - }; - "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailCastResponse": { - /** Format: int64 */ - castId?: number; - castName?: string; - castRole?: string; - castPhoto?: string; - }; - "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailImageResponse": { - /** Format: int64 */ - performanceImageId?: number; - performanceImage?: string; - }; - "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailResponse": { - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - performancePeriod?: string; - scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailScheduleResponse"][]; - /** Format: int32 */ - ticketPrice?: number; - genre?: string; - posterImage?: string; - /** Format: int32 */ - runningTime?: number; - performanceVenue?: string; - roadAddressName?: string; - placeDetailAddress?: string; - latitude?: string; - longitude?: string; - performanceDescription?: string; - performanceAttentionNote?: string; - performanceContact?: string; - performanceTeamName?: string; - castList?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailCastResponse"][]; - staffList?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailStaffResponse"][]; - /** Format: int32 */ - minDueDate?: number; - performanceImageList?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailImageResponse"][]; - }; - "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailScheduleResponse": { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - scheduleNumber?: string; - /** Format: int32 */ - dueDate?: number; - isBooking?: boolean; - }; - "com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailStaffResponse": { - /** Format: int64 */ - staffId?: number; - staffName?: string; - staffRole?: string; - staffPhoto?: string; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.performance.application.dto.performanceDetail.PerformanceDetailResponse"]; - }; - "com.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailResponse": { - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - performancePeriod?: string; - scheduleList?: components["schemas"]["com.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailScheduleResponse"][]; - /** Format: int32 */ - ticketPrice?: number; - genre?: string; - posterImage?: string; - performanceVenue?: string; - performanceTeamName?: string; - bankName?: string; - accountNumber?: string; - accountHolder?: string; - }; - "com.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailScheduleResponse": { - /** Format: int64 */ - scheduleId?: number; - /** Format: date-time */ - performanceDate?: string; - scheduleNumber?: string; - /** Format: int32 */ - availableTicketCount?: number; - isBooking?: boolean; - /** Format: int32 */ - dueDate?: number; - }; - "com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["com.beat.domain.performance.application.dto.bookingPerformanceDetail.BookingPerformanceDetailResponse"]; - }; - HomeFindAllResponse: { - promotionList?: components["schemas"]["HomePromotionDetail"][]; - performanceList?: components["schemas"]["HomePerformanceDetail"][]; - }; - HomePerformanceDetail: { - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - performancePeriod?: string; - /** Format: int32 */ - ticketPrice?: number; - /** Format: int32 */ - dueDate?: number; - genre?: string; - posterImage?: string; - performanceVenue?: string; - }; - "com.beat.domain.performance.application.dto.home.HomePromotionDetail": { - /** Format: int64 */ - promotionId?: number; - promotionPhoto?: string; - /** Format: int64 */ - performanceId?: number; - redirectUrl?: string; - isExternal?: boolean; - /** @enum {string} */ - carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; - }; - SuccessResponseHomeFindAllResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["HomeFindAllResponse"]; - }; - PerformanceMakerPresignedUrlFindAllResponse: { - performanceMakerPresignedUrls?: { - [key: string]: { - [key: string]: string; - }; - }; - }; - SuccessResponsePerformanceMakerPresignedUrlFindAllResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["PerformanceMakerPresignedUrlFindAllResponse"]; - }; - "com.beat.global.external.s3.application.dto.PerformanceMakerPresignedUrlFindAllResponse": { - performanceMakerPresignedUrls?: { - [key: string]: { - [key: string]: string; - }; - }; - }; - "com.beat.domain.booking.application.dto.MemberBookingRetrieveResponse": { - /** Format: int64 */ - userId?: number; - /** Format: int64 */ - bookingId?: number; - /** Format: int64 */ - scheduleId?: number; - /** Format: int64 */ - performanceId?: number; - performanceTitle?: string; - /** Format: date-time */ - performanceDate?: string; - performanceVenue?: string; - /** Format: int32 */ - purchaseTicketCount?: number; - /** @enum {string} */ - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - bookerName?: string; - performanceContact?: string; - /** @enum {string} */ - bankName?: - | "NH_NONGHYUP" - | "KAKAOBANK" - | "KB_KOOKMIN" - | "TOSSBANK" - | "SHINHAN" - | "WOORI" - | "IBK_GIUP" - | "HANA" - | "SAEMAUL" - | "BUSAN" - | "IMBANK_DAEGU" - | "SINHYEOP" - | "WOOCHAEGUK" - | "SCJEIL" - | "SUHYEOP" - | "NONE"; - accountNumber?: string; - accountHolder?: string; - /** Format: int32 */ - dueDate?: number; - /** @enum {string} */ - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - /** Format: date-time */ - createdAt?: string; - posterImage?: string; - /** Format: int32 */ - totalPaymentAmount?: number; - }; - "com.beat.global.common.dto.SuccessResponseJava.util.ListCom.beat.domain.booking.application.dto.MemberBookingRetrieveResponse": { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["MemberBookingRetrieveResponse"][]; - }; - SuccessResponseUserFindAllResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["UserFindAllResponse"]; - }; - UserFindAllResponse: { - users?: components["schemas"]["UserFindResponse"][]; - }; - UserFindResponse: { - /** Format: int64 */ - id?: number; - role?: string; - }; - CarouselFindAllResponse: { - carousels?: components["schemas"]["CarouselFindResponse"][]; - }; - CarouselFindResponse: { - /** Format: int64 */ - promotionId?: number; - /** @enum {string} */ - carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; - newImageUrl?: string; - isExternal?: boolean; - redirectUrl?: string; - /** Format: int64 */ - performanceId?: number; - }; - SuccessResponseCarouselFindAllResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["CarouselFindAllResponse"]; - }; - CarouselPresignedUrlFindAllResponse: { - carouselPresignedUrls?: { - [key: string]: string; - }; - }; - SuccessResponseCarouselPresignedUrlFindAllResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["CarouselPresignedUrlFindAllResponse"]; - }; - BannerPresignedUrlFindResponse: { - bannerPresignedUrl?: string; - }; - SuccessResponseBannerPresignedUrlFindResponse: { - /** Format: int32 */ - status?: number; - message?: string; - data?: components["schemas"]["BannerPresignedUrlFindResponse"]; - }; - }; - responses: never; - parameters: never; - requestBodies: never; - headers: never; - pathItems: never; + schemas: { + TicketUpdateDetail: { + /** Format: int64 */ + bookingId?: number; + bookerName?: string; + bookerPhoneNumber?: string; + /** Format: int64 */ + scheduleId?: number; + /** Format: int32 */ + purchaseTicketCount?: number; + /** Format: date-time */ + createdAt?: string; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + scheduleNumber?: string; + }; + TicketUpdateRequest: { + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** Format: int32 */ + totalScheduleCount?: number; + bookingList?: components["schemas"]["TicketUpdateDetail"][]; + }; + ErrorResponse: { + /** Format: int32 */ + status?: number; + message?: string; + }; + SuccessResponseVoid: { + /** Format: int32 */ + status?: number; + message?: string; + data?: Record<string, never>; + }; + Booking: { + /** Format: int64 */ + bookingId?: number; + }; + TicketRefundRequest: { + /** Format: int64 */ + performanceId?: number; + bookingList?: components["schemas"]["Booking"][]; + }; + TicketDeleteRequest: { + /** Format: int64 */ + performanceId?: number; + bookingList?: components["schemas"]["Booking"][]; + }; + CastModifyRequest: { + /** Format: int64 */ + castId?: number; + castName?: string; + castRole?: string; + castPhoto?: string; + }; + PerformanceImageModifyRequest: { + /** Format: int64 */ + performanceImageId?: number; + performanceImage?: string; + }; + PerformanceModifyRequest: { + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** @enum {string} */ + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + /** Format: int32 */ + runningTime?: number; + performanceDescription?: string; + performanceAttentionNote?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + posterImage?: string; + performanceTeamName?: string; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceContact?: string; + performancePeriod?: string; + /** Format: int32 */ + totalScheduleCount?: number; + /** Format: int32 */ + ticketPrice?: number; + scheduleModifyRequests?: components["schemas"]["ScheduleModifyRequest"][]; + castModifyRequests?: components["schemas"]["CastModifyRequest"][]; + staffModifyRequests?: components["schemas"]["StaffModifyRequest"][]; + performanceImageModifyRequests?: components["schemas"]["PerformanceImageModifyRequest"][]; + }; + ScheduleModifyRequest: { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + /** Format: int32 */ + totalTicketCount?: number; + }; + StaffModifyRequest: { + /** Format: int64 */ + staffId?: number; + staffName?: string; + staffRole?: string; + staffPhoto?: string; + }; + CastModifyResponse: { + /** Format: int64 */ + castId?: number; + castName?: string; + castRole?: string; + castPhoto?: string; + }; + PerformanceImageModifyResponse: { + /** Format: int64 */ + performanceImageId?: number; + performanceImage?: string; + }; + PerformanceModifyResponse: { + /** Format: int64 */ + userId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** @enum {string} */ + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + /** Format: int32 */ + runningTime?: number; + performanceDescription?: string; + performanceAttentionNote?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + posterImage?: string; + performanceTeamName?: string; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceContact?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + totalScheduleCount?: number; + scheduleModifyResponses?: components["schemas"]["ScheduleModifyResponse"][]; + castModifyResponses?: components["schemas"]["CastModifyResponse"][]; + staffModifyResponses?: components["schemas"]["StaffModifyResponse"][]; + performanceImageModifyResponses?: components["schemas"]["PerformanceImageModifyResponse"][]; + }; + ScheduleModifyResponse: { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + /** Format: int32 */ + totalTicketCount?: number; + /** Format: int32 */ + dueDate?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + }; + StaffModifyResponse: { + /** Format: int64 */ + staffId?: number; + staffName?: string; + staffRole?: string; + staffPhoto?: string; + }; + SuccessResponsePerformanceModifyResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["PerformanceModifyResponse"]; + }; + CarouselHandleRequest: { + carousels?: (components["schemas"]["PromotionGenerateRequest"] | components["schemas"]["PromotionModifyRequest"])[]; + }; + PromotionGenerateRequest: { + type: "PromotionGenerateRequest"; + } & (Omit<components["schemas"]["PromotionHandleRequest"], "type"> & { + /** @enum {string} */ + carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; + newImageUrl?: string; + isExternal?: boolean; + redirectUrl?: string; + /** Format: int64 */ + performanceId?: number; + }); + PromotionHandleRequest: { + external?: boolean; + type: string; + }; + PromotionModifyRequest: { + type: "PromotionModifyRequest"; + } & (Omit<components["schemas"]["PromotionHandleRequest"], "type"> & { + /** Format: int64 */ + promotionId?: number; + /** @enum {string} */ + carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; + newImageUrl?: string; + isExternal?: boolean; + redirectUrl?: string; + /** Format: int64 */ + performanceId?: number; + }); + CarouselHandleAllResponse: { + modifiedPromotions?: components["schemas"]["PromotionResponse"][]; + }; + PromotionResponse: { + /** Format: int64 */ + promotionId?: number; + newImageUrl?: string; + isExternal?: boolean; + redirectUrl?: string; + carouselNumber?: string; + }; + SuccessResponseCarouselHandleAllResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["CarouselHandleAllResponse"]; + }; + MemberLoginRequest: { + /** @enum {string} */ + socialType: "KAKAO"; + }; + LoginSuccessResponse: { + accessToken?: string; + refreshToken?: string; + nickname?: string; + role?: string; + }; + SuccessResponseLoginSuccessResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["LoginSuccessResponse"]; + }; + CastRequest: { + castName?: string; + castRole?: string; + castPhoto?: string; + }; + PerformanceImageRequest: { + performanceImage?: string; + }; + PerformanceRequest: { + performanceTitle?: string; + /** @enum {string} */ + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + /** Format: int32 */ + runningTime?: number; + performanceDescription?: string; + performanceAttentionNote?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + posterImage?: string; + performanceTeamName?: string; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceContact?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + totalScheduleCount?: number; + scheduleList?: components["schemas"]["ScheduleRequest"][]; + castList?: components["schemas"]["CastRequest"][]; + staffList?: components["schemas"]["StaffRequest"][]; + performanceImageList?: components["schemas"]["PerformanceImageRequest"][]; + }; + ScheduleRequest: { + /** Format: date-time */ + performanceDate?: string; + /** Format: int32 */ + totalTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + }; + StaffRequest: { + staffName?: string; + staffRole?: string; + staffPhoto?: string; + }; + CastResponse: { + /** Format: int64 */ + castId?: number; + castName?: string; + castRole?: string; + castPhoto?: string; + }; + PerformanceImageResponse: { + /** Format: int64 */ + imageId?: number; + imageUrl?: string; + }; + PerformanceResponse: { + /** Format: int64 */ + userId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** @enum {string} */ + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + /** Format: int32 */ + runningTime?: number; + performanceDescription?: string; + performanceAttentionNote?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + posterImage?: string; + performanceTeamName?: string; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceContact?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + totalScheduleCount?: number; + scheduleList?: components["schemas"]["ScheduleResponse"][]; + castList?: components["schemas"]["CastResponse"][]; + staffList?: components["schemas"]["StaffResponse"][]; + performanceImageList?: components["schemas"]["PerformanceImageResponse"][]; + }; + ScheduleResponse: { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + /** Format: int32 */ + totalTicketCount?: number; + /** Format: int32 */ + dueDate?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + }; + StaffResponse: { + /** Format: int64 */ + staffId?: number; + staffName?: string; + staffRole?: string; + staffPhoto?: string; + }; + SuccessResponsePerformanceResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["PerformanceResponse"]; + }; + MemberBookingRequest: { + /** Format: int64 */ + scheduleId?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + /** Format: int32 */ + purchaseTicketCount?: number; + bookerName?: string; + bookerPhoneNumber?: string; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** Format: int32 */ + totalPaymentAmount?: number; + }; + MemberBookingResponse: { + /** Format: int64 */ + bookingId?: number; + /** Format: int64 */ + scheduleId?: number; + /** Format: int64 */ + userId?: number; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + bookerPhoneNumber?: string; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + /** Format: date-time */ + createdAt?: string; + }; + SuccessResponseMemberBookingResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["MemberBookingResponse"]; + }; + GuestBookingRequest: { + /** Format: int64 */ + scheduleId?: number; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + bookerPhoneNumber?: string; + birthDate?: string; + password?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + }; + GuestBookingResponse: { + /** Format: int64 */ + bookingId?: number; + /** Format: int64 */ + scheduleId?: number; + /** Format: int64 */ + userId?: number; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + bookerPhoneNumber?: string; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + /** Format: date-time */ + createdAt?: string; + }; + SuccessResponseGuestBookingResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["GuestBookingResponse"]; + }; + GuestBookingRetrieveRequest: { + bookerName?: string; + birthDate?: string; + bookerPhoneNumber?: string; + password?: string; + }; + GuestBookingRetrieveResponse: { + /** Format: int64 */ + bookingId?: number; + /** Format: int64 */ + scheduleId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** Format: date-time */ + performanceDate?: string; + performanceVenue?: string; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + performanceContact?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + /** Format: int32 */ + dueDate?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** Format: date-time */ + createdAt?: string; + posterImage?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + }; + SuccessResponseListGuestBookingRetrieveResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["GuestBookingRetrieveResponse"][]; + }; + BookingRefundRequest: { + /** Format: int64 */ + bookingId?: number; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + }; + BookingRefundResponse: { + /** Format: int64 */ + bookingId?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + }; + SuccessResponseBookingRefundResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["BookingRefundResponse"]; + }; + BookingCancelRequest: { + /** Format: int64 */ + bookingId?: number; + }; + BookingCancelResponse: { + /** Format: int64 */ + bookingId?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + }; + SuccessResponseBookingCancelResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["BookingCancelResponse"]; + }; + AccessTokenGetSuccess: { + accessToken?: string; + }; + SuccessResponseAccessTokenGetSuccess: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["AccessTokenGetSuccess"]; + }; + SuccessResponseTicketRetrieveResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["TicketRetrieveResponse"]; + }; + TicketDetail: { + /** Format: int64 */ + bookingId?: number; + bookerName?: string; + bookerPhoneNumber?: string; + /** Format: int64 */ + scheduleId?: number; + /** Format: int32 */ + purchaseTicketCount?: number; + /** Format: date-time */ + createdAt?: string; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + scheduleNumber?: string; + bankName?: string; + accountNumber?: string; + accountHolder?: string; + }; + TicketRetrieveResponse: { + performanceTitle?: string; + performanceTeamName?: string; + /** Format: int32 */ + totalScheduleCount?: number; + /** Format: int32 */ + totalPerformanceTicketCount?: number; + /** Format: int32 */ + totalPerformanceSoldTicketCount?: number; + bookingList?: components["schemas"]["TicketDetail"][]; + }; + SuccessResponseTicketAvailabilityResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["TicketAvailabilityResponse"]; + }; + TicketAvailabilityResponse: { + /** Format: int64 */ + scheduleId?: number; + scheduleNumber?: string; + /** Format: int32 */ + totalTicketCount?: number; + /** Format: int32 */ + soldTicketCount?: number; + /** Format: int32 */ + availableTicketCount?: number; + /** Format: int32 */ + requestedTicketCount?: number; + isAvailable?: boolean; + }; + PerformanceModifyDetailResponse: { + /** Format: int64 */ + userId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** @enum {string} */ + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + /** Format: int32 */ + runningTime?: number; + performanceDescription?: string; + performanceAttentionNote?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + posterImage?: string; + performanceTeamName?: string; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceContact?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + totalScheduleCount?: number; + isBookerExist?: boolean; + scheduleList?: components["schemas"]["ScheduleResponse"][]; + castList?: components["schemas"]["CastResponse"][]; + staffList?: components["schemas"]["StaffResponse"][]; + performanceImageList?: components["schemas"]["PerformanceImageResponse"][]; + }; + SuccessResponsePerformanceModifyDetailResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["PerformanceModifyDetailResponse"]; + }; + MakerPerformanceDetailResponse: { + /** Format: int64 */ + performanceId?: number; + genre?: string; + performanceTitle?: string; + posterImage?: string; + performancePeriod?: string; + /** Format: int32 */ + minDueDate?: number; + }; + MakerPerformanceResponse: { + /** Format: int64 */ + userId?: number; + performances?: components["schemas"]["MakerPerformanceDetailResponse"][]; + }; + SuccessResponseMakerPerformanceResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["MakerPerformanceResponse"]; + }; + PerformanceDetailCastResponse: { + /** Format: int64 */ + castId?: number; + castName?: string; + castRole?: string; + castPhoto?: string; + }; + PerformanceDetailImageResponse: { + /** Format: int64 */ + performanceImageId?: number; + performanceImage?: string; + }; + PerformanceDetailResponse: { + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + performancePeriod?: string; + scheduleList?: components["schemas"]["PerformanceDetailScheduleResponse"][]; + /** Format: int32 */ + ticketPrice?: number; + genre?: string; + posterImage?: string; + /** Format: int32 */ + runningTime?: number; + performanceVenue?: string; + roadAddressName?: string; + placeDetailAddress?: string; + latitude?: string; + longitude?: string; + performanceDescription?: string; + performanceAttentionNote?: string; + performanceContact?: string; + performanceTeamName?: string; + castList?: components["schemas"]["PerformanceDetailCastResponse"][]; + staffList?: components["schemas"]["PerformanceDetailStaffResponse"][]; + /** Format: int32 */ + minDueDate?: number; + performanceImageList?: components["schemas"]["PerformanceDetailImageResponse"][]; + }; + PerformanceDetailScheduleResponse: { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + scheduleNumber?: string; + /** Format: int32 */ + dueDate?: number; + isBooking?: boolean; + }; + PerformanceDetailStaffResponse: { + /** Format: int64 */ + staffId?: number; + staffName?: string; + staffRole?: string; + staffPhoto?: string; + }; + SuccessResponsePerformanceDetailResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["PerformanceDetailResponse"]; + }; + BookingPerformanceDetailResponse: { + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + performancePeriod?: string; + scheduleList?: components["schemas"]["BookingPerformanceDetailScheduleResponse"][]; + /** Format: int32 */ + ticketPrice?: number; + genre?: string; + posterImage?: string; + performanceVenue?: string; + performanceTeamName?: string; + bankName?: string; + accountNumber?: string; + accountHolder?: string; + }; + BookingPerformanceDetailScheduleResponse: { + /** Format: int64 */ + scheduleId?: number; + /** Format: date-time */ + performanceDate?: string; + scheduleNumber?: string; + /** Format: int32 */ + availableTicketCount?: number; + isBooking?: boolean; + /** Format: int32 */ + dueDate?: number; + }; + SuccessResponseBookingPerformanceDetailResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["BookingPerformanceDetailResponse"]; + }; + HomeFindAllResponse: { + promotionList?: components["schemas"]["HomePromotionDetail"][]; + performanceList?: components["schemas"]["HomePerformanceDetail"][]; + }; + HomePerformanceDetail: { + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + performancePeriod?: string; + /** Format: int32 */ + ticketPrice?: number; + /** Format: int32 */ + dueDate?: number; + genre?: string; + posterImage?: string; + performanceVenue?: string; + }; + HomePromotionDetail: { + /** Format: int64 */ + promotionId?: number; + promotionPhoto?: string; + /** Format: int64 */ + performanceId?: number; + redirectUrl?: string; + isExternal?: boolean; + /** @enum {string} */ + carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; + }; + SuccessResponseHomeFindAllResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["HomeFindAllResponse"]; + }; + PerformanceMakerPresignedUrlFindAllResponse: { + performanceMakerPresignedUrls?: { + [key: string]: { + [key: string]: string; + }; + }; + }; + SuccessResponsePerformanceMakerPresignedUrlFindAllResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["PerformanceMakerPresignedUrlFindAllResponse"]; + }; + MemberBookingRetrieveResponse: { + /** Format: int64 */ + userId?: number; + /** Format: int64 */ + bookingId?: number; + /** Format: int64 */ + scheduleId?: number; + /** Format: int64 */ + performanceId?: number; + performanceTitle?: string; + /** Format: date-time */ + performanceDate?: string; + performanceVenue?: string; + /** Format: int32 */ + purchaseTicketCount?: number; + /** @enum {string} */ + scheduleNumber?: "FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH"; + bookerName?: string; + performanceContact?: string; + /** @enum {string} */ + bankName?: "NH_NONGHYUP" | "KAKAOBANK" | "KB_KOOKMIN" | "TOSSBANK" | "SHINHAN" | "WOORI" | "IBK_GIUP" | "HANA" | "SAEMAUL" | "BUSAN" | "IMBANK_DAEGU" | "SINHYEOP" | "WOOCHAEGUK" | "SCJEIL" | "SUHYEOP" | "NONE"; + accountNumber?: string; + accountHolder?: string; + /** Format: int32 */ + dueDate?: number; + /** @enum {string} */ + bookingStatus?: "CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED"; + /** Format: date-time */ + createdAt?: string; + posterImage?: string; + /** Format: int32 */ + totalPaymentAmount?: number; + }; + SuccessResponseListMemberBookingRetrieveResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["MemberBookingRetrieveResponse"][]; + }; + SuccessResponseUserFindAllResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["UserFindAllResponse"]; + }; + UserFindAllResponse: { + users?: components["schemas"]["UserFindResponse"][]; + }; + UserFindResponse: { + /** Format: int64 */ + id?: number; + role?: string; + }; + CarouselFindAllResponse: { + carousels?: components["schemas"]["CarouselFindResponse"][]; + }; + CarouselFindResponse: { + /** Format: int64 */ + promotionId?: number; + /** @enum {string} */ + carouselNumber?: "ONE" | "TWO" | "THREE" | "FOUR" | "FIVE" | "SIX" | "SEVEN"; + newImageUrl?: string; + isExternal?: boolean; + redirectUrl?: string; + /** Format: int64 */ + performanceId?: number; + }; + SuccessResponseCarouselFindAllResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["CarouselFindAllResponse"]; + }; + CarouselPresignedUrlFindAllResponse: { + carouselPresignedUrls?: { + [key: string]: string; + }; + }; + SuccessResponseCarouselPresignedUrlFindAllResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["CarouselPresignedUrlFindAllResponse"]; + }; + BannerPresignedUrlFindResponse: { + bannerPresignedUrl?: string; + }; + SuccessResponseBannerPresignedUrlFindResponse: { + /** Format: int32 */ + status?: number; + message?: string; + data?: components["schemas"]["BannerPresignedUrlFindResponse"]; + }; + }; + responses: never; + parameters: never; + requestBodies: never; + headers: never; + pathItems: never; } export type $defs = Record<string, never>; export interface operations { - updateTickets: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["com.beat.domain.booking.application.dto.TicketUpdateRequest"]; - }; - }; - responses: { - /** @description 예매자 입금여부 수정 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.lang.Void"]; - }; - }; - /** @description 이미 결제가 완료된 티켓의 상태는 변경할 수 없습니다. */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 공연 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - refundTickets: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["TicketRefundRequest"]; - }; - }; - responses: { - /** @description 예매자 환불처리 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseJava.lang.Void"]; - }; - }; - /** @description 해당 예매 내역을 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - deleteTickets: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["TicketDeleteRequest"]; - }; - }; - responses: { - /** @description 예매자 삭제 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseVoid"]; - }; - }; - /** @description 해당 예매 내역을 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; + updateTickets: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["TicketUpdateRequest"]; + }; + }; + responses: { + /** @description 예매자 입금여부 수정 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseVoid"]; + }; + }; + /** @description 이미 결제가 완료된 티켓의 상태는 변경할 수 없습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + refundTickets: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["TicketRefundRequest"]; + }; + }; + responses: { + /** @description 예매자 환불처리 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseVoid"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + deleteTickets: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["TicketDeleteRequest"]; + }; + }; + responses: { + /** @description 예매자 삭제 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseVoid"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + updatePerformance: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["PerformanceModifyRequest"]; + }; + }; + responses: { + /** @description 공연 정보 수정 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponsePerformanceModifyResponse"]; + }; + }; + /** @description 예매자가 존재하여 가격을 수정할 수 없습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 해당 공연의 소유자가 아닙니다. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + createPerformance: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["PerformanceRequest"]; + }; + }; + responses: { + /** @description 공연이 성공적으로 생성되었습니다. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponsePerformanceResponse"]; + }; + }; + /** @description 필수 데이터가 누락되었습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + readAllCarouselImages: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 관리자 권한으로 현재 캐러셀에 등록된 모든 공연 조회에 성공하였습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseCarouselFindAllResponse"]; + }; + }; + /** @description 회원이 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + processCarouselImages: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["CarouselHandleRequest"]; + }; + }; + responses: { + /** @description 캐러셀 이미지 수정 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseCarouselHandleAllResponse"]; + }; + }; + /** @description 회원이 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + signUp: { + parameters: { + query: { + authorizationCode: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["MemberLoginRequest"]; + }; + }; + responses: { + /** @description 로그인 또는 회원가입 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseLoginSuccessResponse"]; + }; + }; + /** @description 로그인 요청이 유효하지 않습니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회원 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + signOut: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 로그아웃 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseVoid"]; + }; + }; + /** @description 회원 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + createMemberBooking: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["MemberBookingRequest"]; + }; + }; + responses: { + /** @description 회원 예매가 성공적으로 완료되었습니다. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseMemberBookingResponse"]; + }; + }; + /** @description 잘못된 데이터 형식입니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + createGuestBookings: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["GuestBookingRequest"]; + }; + }; + responses: { + /** @description 비회원 예매가 성공적으로 완료되었습니다. */ + 201: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseGuestBookingResponse"]; + }; + }; + /** @description 잘못된 데이터 형식입니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getGuestBookings: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["GuestBookingRetrieveRequest"]; + }; + }; + responses: { + /** @description 비회원 예매 조회가 성공적으로 완료되었습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseListGuestBookingRetrieveResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + refundBookings: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["BookingRefundRequest"]; + }; + }; + responses: { + /** @description 유료공연 예매 환불 요청이 성공적으로 완료되었습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseBookingRefundResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + cancelBookings: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody: { + content: { + "application/json;charset=UTF-8": components["schemas"]["BookingCancelRequest"]; + }; + }; + responses: { + /** @description 무료공연/미입금 예매 취소 요청이 성공적으로 완료되었습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseBookingCancelResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + healthcheck: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 서버가 정상적으로 동작 중입니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": string; + }; + }; + }; + }; + issueAccessTokenUsingRefreshToken: { + parameters: { + query?: never; + header: { + Authorization_Refresh: string; + }; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description access token 재발급 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseAccessTokenGetSuccess"]; + }; + }; + /** @description 유효하지 않은 토큰입니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getTickets: { + parameters: { + query?: { + scheduleNumbers?: ("FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH")[]; + bookingStatuses?: ("CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED")[]; + }; + header?: never; + path: { + performanceId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 예매자 목록 조회 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseTicketRetrieveResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + searchTickets: { + parameters: { + query: { + searchWord: string; + scheduleNumbers?: ("FIRST" | "SECOND" | "THIRD" | "FOURTH" | "FIFTH" | "SIXTH" | "SEVENTH" | "EIGHTH" | "NINTH" | "TENTH")[]; + bookingStatuses?: ("CHECKING_PAYMENT" | "BOOKING_CONFIRMED" | "BOOKING_CANCELLED" | "REFUND_REQUESTED" | "BOOKING_DELETED")[]; + }; + header?: never; + path: { + performanceId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 예매자 목록 검색 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseTicketRetrieveResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getTicketAvailability: { + parameters: { + query: { + purchaseTicketCount: number; + }; + header?: never; + path: { + scheduleId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 티켓 수량 조회가 성공적으로 완료되었습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseTicketAvailabilityResponse"]; + }; + }; + /** @description 잘못된 데이터 형식입니다. */ + 400: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 회차 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 요청한 티켓 수량이 잔여 티켓 수를 초과했습니다. */ + 409: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getPerformanceForEdit: { + parameters: { + query?: never; + header?: never; + path: { + performanceId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 공연 수정 페이지 정보 조회 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponsePerformanceModifyDetailResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + deletePerformance: { + parameters: { + query?: never; + header?: never; + path: { + performanceId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 공연 삭제 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseVoid"]; + }; + }; + /** @description 공연의 소유자가 아니거나 예매자가 있어 삭제할 수 없습니다. */ + 403: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getUserPerformances: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 회원이 등록한 공연 목록 조회 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseMakerPerformanceResponse"]; + }; + }; + /** @description 회원 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getPerformanceDetail: { + parameters: { + query?: never; + header?: never; + path: { + performanceId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 공연 상세정보 조회 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponsePerformanceDetailResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getBookingPerformanceDetail: { + parameters: { + query?: never; + header?: never; + path: { + performanceId: number; + }; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 예매하기 관련 공연 정보 조회 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseBookingPerformanceDetailResponse"]; + }; + }; + /** @description 공연 정보를 찾을 수 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getHomePerformanceList: { + parameters: { + query?: { + genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 홈 화면 공연 목록 조회가 성공적으로 완료되었습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseHomeFindAllResponse"]; + }; + }; + }; + }; + generateAllPresignedUrls: { + parameters: { + query: { + posterImage: string; + castImages?: string[]; + staffImages?: string[]; + performanceImages?: string[]; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 공연 메이커를 위한 Presigned URL 발급 성공. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponsePerformanceMakerPresignedUrlFindAllResponse"]; + }; + }; + /** @description S3 PreSigned url을 받아오기에 실패했습니다. */ + 500: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + getMemberBookings: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 회원 예매 조회가 성공적으로 완료되었습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseListMemberBookingRetrieveResponse"]; + }; + }; + /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + readAllUsers: { + parameters: { + query?: never; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 관리자 권한으로 모든 유저 조회에 성공하였습니다. */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseUserFindAllResponse"]; + }; + }; + /** @description 회원이 없습니다 */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + createAllCarouselPresignedUrls: { + parameters: { + query: { + carouselImages: string[]; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 캐러셀 Presigned URL 발급 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseCarouselPresignedUrlFindAllResponse"]; + }; + }; + /** @description 회원이 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; + }; + }; + createBannerPresignedUrl: { + parameters: { + query: { + bannerImage: string; + }; + header?: never; + path?: never; + cookie?: never; + }; + requestBody?: never; + responses: { + /** @description 배너 Presigned URL 발급 성공 */ + 200: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["SuccessResponseBannerPresignedUrlFindResponse"]; + }; + }; + /** @description 회원이 없습니다. */ + 404: { + headers: { + [name: string]: unknown; + }; + content: { + "application/json;charset=UTF-8": components["schemas"]["ErrorResponse"]; + }; + }; }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - updatePerformance: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["PerformanceModifyRequest"]; - }; - }; - responses: { - /** @description 공연 정보 수정 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.SuccessResponseCom.beat.domain.performance.application.dto.modify.PerformanceModifyResponse"]; - }; - }; - /** @description 예매자가 존재하여 가격을 수정할 수 없습니다. */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 해당 공연의 소유자가 아닙니다. */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 공연 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - createPerformance: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["com.beat.domain.performance.application.dto.create.PerformanceRequest"]; - }; - }; - responses: { - /** @description 공연이 성공적으로 생성되었습니다. */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponsePerformanceResponse"]; - }; - }; - /** @description 필수 데이터가 누락되었습니다. */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 공연 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - readAllCarouselImages: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 관리자 권한으로 현재 캐러셀에 등록된 모든 공연 조회에 성공하였습니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseCarouselFindAllResponse"]; - }; - }; - /** @description 회원이 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; - }; - }; - }; - }; - processCarouselImages: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["CarouselHandleRequest"]; - }; - }; - responses: { - /** @description 캐러셀 이미지 수정 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseCarouselHandleAllResponse"]; - }; - }; - /** @description 해당 홍보 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; - }; - }; - }; - }; - signUp: { - parameters: { - query: { - authorizationCode: string; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["com.beat.global.auth.client.dto.MemberLoginRequest"]; - }; - }; - responses: { - /** @description 로그인 또는 회원가입 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseLoginSuccessResponse"]; - }; - }; - /** @description 로그인 요청이 유효하지 않습니다. */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 회원 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - signOut: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 로그아웃 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseVoid"]; - }; - }; - /** @description 회원 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - createMemberBooking: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["com.beat.domain.booking.application.dto.MemberBookingRequest"]; - }; - }; - responses: { - /** @description 회원 예매가 성공적으로 완료되었습니다. */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseMemberBookingResponse"]; - }; - }; - /** @description 잘못된 데이터 형식입니다. */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 회원 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - createGuestBookings: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["com.beat.domain.booking.application.dto.GuestBookingRequest"]; - }; - }; - responses: { - /** @description 비회원 예매가 성공적으로 완료되었습니다. */ - 201: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseGuestBookingResponse"]; - }; - }; - /** @description 잘못된 데이터 형식입니다. */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 공연 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - getGuestBookings: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["com.beat.domain.booking.application.dto.GuestBookingRetrieveRequest"]; - }; - }; - responses: { - /** @description 비회원 예매 조회가 성공적으로 완료되었습니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseListGuestBookingRetrieveResponse"]; - }; - }; - /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - refundBookings: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["BookingRefundRequest"]; - }; - }; - responses: { - /** @description 유료공연 예매 환불 요청이 성공적으로 완료되었습니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseBookingRefundResponse"]; - }; - }; - /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - cancelBookings: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody: { - content: { - "application/json": components["schemas"]["BookingCancelRequest"]; - }; - }; - responses: { - /** @description 무료공연/미입금 예매 취소 요청이 성공적으로 완료되었습니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseBookingCancelResponse"]; - }; - }; - /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - healthcheck: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 서버가 정상적으로 동작 중입니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": string; - }; - }; - }; - }; - refreshToken: { - parameters: { - query: { - refreshToken: string; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description access token 재발급 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseAccessTokenGetSuccess"]; - }; - }; - /** @description 유효하지 않은 토큰입니다. */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - getTickets: { - parameters: { - query?: { - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - }; - header?: never; - path: { - performanceId: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 예매자 목록 조회 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseTicketRetrieveResponse"]; - }; - }; - /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - searchTickets: { - parameters: { - query: { - searchWord: string; - scheduleNumber?: - | "FIRST" - | "SECOND" - | "THIRD" - | "FOURTH" - | "FIFTH" - | "SIXTH" - | "SEVENTH" - | "EIGHTH" - | "NINTH" - | "TENTH"; - bookingStatus?: - | "CHECKING_PAYMENT" - | "BOOKING_CONFIRMED" - | "BOOKING_CANCELLED" - | "REFUND_REQUESTED" - | "BOOKING_DELETED"; - }; - header?: never; - path: { - performanceId: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 예매자 목록 검색 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseTicketRetrieveResponse"]; - }; - }; - /** @description 입력하신 정보와 일치하는 예매자 목록이 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - getTicketAvailability: { - parameters: { - query: { - purchaseTicketCount: number; - }; - header?: never; - path: { - scheduleId: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 티켓 수량 조회가 성공적으로 완료되었습니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseTicketAvailabilityResponse"]; - }; - }; - /** @description 잘못된 데이터 형식입니다. */ - 400: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 회차 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 요청한 티켓 수량이 잔여 티켓 수를 초과했습니다. */ - 409: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - getPerformanceForEdit: { - parameters: { - query?: never; - header?: never; - path: { - performanceId: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 공연 수정 페이지 정보 조회 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponsePerformanceModifyDetailResponse"]; - }; - }; - /** @description 공연 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - deletePerformance: { - parameters: { - query?: never; - header?: never; - path: { - performanceId: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 공연 삭제 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseVoid"]; - }; - }; - /** @description 공연의 소유자가 아니거나 예매자가 있어 삭제할 수 없습니다. */ - 403: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - /** @description 공연 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - getUserPerformances: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 회원이 등록한 공연 목록 조회 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseMakerPerformanceResponse"]; - }; - }; - /** @description 회원 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - getPerformanceDetail: { - parameters: { - query?: never; - header?: never; - path: { - performanceId: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 공연 상세정보 조회 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponsePerformanceDetailResponse"]; - }; - }; - /** @description 공연 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - getBookingPerformanceDetail: { - parameters: { - query?: never; - header?: never; - path: { - performanceId: number; - }; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 예매하기 관련 공연 정보 조회 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseBookingPerformanceDetailResponse"]; - }; - }; - /** @description 공연 정보를 찾을 수 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - getHomePerformanceList: { - parameters: { - query?: { - genre?: "BAND" | "PLAY" | "DANCE" | "ETC"; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 홈 화면 공연 목록 조회가 성공적으로 완료되었습니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseHomeFindAllResponse"]; - }; - }; - }; - }; - generateAllPresignedUrls: { - parameters: { - query: { - posterImage: string; - castImages?: string[]; - staffImages?: string[]; - performanceImages?: string[]; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 공연 메이커를 위한 Presigned URL 발급 성공. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponsePerformanceMakerPresignedUrlFindAllResponse"]; - }; - }; - /** @description S3 PreSigned url을 받아오기에 실패했습니다. */ - 500: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; - }; - }; - }; - }; - getMemberBookings: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 회원 예매 조회가 성공적으로 완료되었습니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseListMemberBookingRetrieveResponse"]; - }; - }; - /** @description 입력하신 정보와 일치하는 예매 내역이 없습니다. 확인 후 다시 조회해주세요. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["ErrorResponse"]; - }; - }; - }; - }; - readAllUsers: { - parameters: { - query?: never; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 관리자 권한으로 모든 유저 조회에 성공하였습니다. */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseUserFindAllResponse"]; - }; - }; - /** @description 회원이 없습니다 */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; - }; - }; - }; - }; - createAllCarouselPresignedUrls: { - parameters: { - query: { - carouselImages: string[]; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 캐러셀 Presigned URL 발급 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseCarouselPresignedUrlFindAllResponse"]; - }; - }; - /** @description 회원이 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; - }; - }; - }; - }; - createBannerPresignedUrl: { - parameters: { - query: { - bannerImage: string; - }; - header?: never; - path?: never; - cookie?: never; - }; - requestBody?: never; - responses: { - /** @description 배너 Presigned URL 발급 성공 */ - 200: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["SuccessResponseBannerPresignedUrlFindResponse"]; - }; - }; - /** @description 회원이 없습니다. */ - 404: { - headers: { - [name: string]: unknown; - }; - content: { - "*/*": components["schemas"]["com.beat.global.common.dto.ErrorResponse"]; - }; - }; }; - }; } From adad35952c9e47b6425391513c9672e4ceaf68ec Mon Sep 17 00:00:00 2001 From: Sinji <sinzi031012@naver.com> Date: Sun, 15 Dec 2024 18:24:49 +0900 Subject: [PATCH 48/49] =?UTF-8?q?fix:=20=EC=98=88=EB=A7=A4=EC=9E=90=20?= =?UTF-8?q?=EA=B4=80=EB=A6=AC=20=ED=8E=98=EC=9D=B4=EC=A7=80=20=ED=99=98?= =?UTF-8?q?=EB=B6=88/=EC=B7=A8=EC=86=8C=20=EC=95=88=20=EB=90=98=EB=8D=98?= =?UTF-8?q?=20=EC=98=A4=EB=A5=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .yarn/releases/yarn-4.1.0.cjs | 2 +- src/pages/ticketholderlist/TicketHolderList.tsx | 15 +++++++++------ 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/.yarn/releases/yarn-4.1.0.cjs b/.yarn/releases/yarn-4.1.0.cjs index 3832537a..738adce5 100755 --- a/.yarn/releases/yarn-4.1.0.cjs +++ b/.yarn/releases/yarn-4.1.0.cjs @@ -1,5 +1,5 @@ #!/usr/bin/env node - +/* eslint-disable */ //prettier-ignore (()=>{var Z3e=Object.create;var NR=Object.defineProperty;var $3e=Object.getOwnPropertyDescriptor;var e_e=Object.getOwnPropertyNames;var t_e=Object.getPrototypeOf,r_e=Object.prototype.hasOwnProperty;var ve=(t=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(t,{get:(e,r)=>(typeof require<"u"?require:e)[r]}):t)(function(t){if(typeof require<"u")return require.apply(this,arguments);throw new Error('Dynamic require of "'+t+'" is not supported')});var Et=(t,e)=>()=>(t&&(e=t(t=0)),e);var _=(t,e)=>()=>(e||t((e={exports:{}}).exports,e),e.exports),Vt=(t,e)=>{for(var r in e)NR(t,r,{get:e[r],enumerable:!0})},n_e=(t,e,r,o)=>{if(e&&typeof e=="object"||typeof e=="function")for(let a of e_e(e))!r_e.call(t,a)&&a!==r&&NR(t,a,{get:()=>e[a],enumerable:!(o=$3e(e,a))||o.enumerable});return t};var $e=(t,e,r)=>(r=t!=null?Z3e(t_e(t)):{},n_e(e||!t||!t.__esModule?NR(r,"default",{value:t,enumerable:!0}):r,t));var vi={};Vt(vi,{SAFE_TIME:()=>x7,S_IFDIR:()=>wD,S_IFLNK:()=>ID,S_IFMT:()=>Ou,S_IFREG:()=>jw});var Ou,wD,jw,ID,x7,k7=Et(()=>{Ou=61440,wD=16384,jw=32768,ID=40960,x7=456789e3});var ar={};Vt(ar,{EBADF:()=>Io,EBUSY:()=>i_e,EEXIST:()=>u_e,EINVAL:()=>o_e,EISDIR:()=>c_e,ENOENT:()=>a_e,ENOSYS:()=>s_e,ENOTDIR:()=>l_e,ENOTEMPTY:()=>f_e,EOPNOTSUPP:()=>p_e,EROFS:()=>A_e,ERR_DIR_CLOSED:()=>LR});function Tl(t,e){return Object.assign(new Error(`${t}: ${e}`),{code:t})}function i_e(t){return Tl("EBUSY",t)}function s_e(t,e){return Tl("ENOSYS",`${t}, ${e}`)}function o_e(t){return Tl("EINVAL",`invalid argument, ${t}`)}function Io(t){return Tl("EBADF",`bad file descriptor, ${t}`)}function a_e(t){return Tl("ENOENT",`no such file or directory, ${t}`)}function l_e(t){return Tl("ENOTDIR",`not a directory, ${t}`)}function c_e(t){return Tl("EISDIR",`illegal operation on a directory, ${t}`)}function u_e(t){return Tl("EEXIST",`file already exists, ${t}`)}function A_e(t){return Tl("EROFS",`read-only filesystem, ${t}`)}function f_e(t){return Tl("ENOTEMPTY",`directory not empty, ${t}`)}function p_e(t){return Tl("EOPNOTSUPP",`operation not supported, ${t}`)}function LR(){return Tl("ERR_DIR_CLOSED","Directory handle was closed")}var BD=Et(()=>{});var Ea={};Vt(Ea,{BigIntStatsEntry:()=>ty,DEFAULT_MODE:()=>UR,DirEntry:()=>OR,StatEntry:()=>ey,areStatsEqual:()=>_R,clearStats:()=>vD,convertToBigIntStats:()=>g_e,makeDefaultStats:()=>Q7,makeEmptyStats:()=>h_e});function Q7(){return new ey}function h_e(){return vD(Q7())}function vD(t){for(let e in t)if(Object.hasOwn(t,e)){let r=t[e];typeof r=="number"?t[e]=0:typeof r=="bigint"?t[e]=BigInt(0):MR.types.isDate(r)&&(t[e]=new Date(0))}return t}function g_e(t){let e=new ty;for(let r in t)if(Object.hasOwn(t,r)){let o=t[r];typeof o=="number"?e[r]=BigInt(o):MR.types.isDate(o)&&(e[r]=new Date(o))}return e.atimeNs=e.atimeMs*BigInt(1e6),e.mtimeNs=e.mtimeMs*BigInt(1e6),e.ctimeNs=e.ctimeMs*BigInt(1e6),e.birthtimeNs=e.birthtimeMs*BigInt(1e6),e}function _R(t,e){if(t.atimeMs!==e.atimeMs||t.birthtimeMs!==e.birthtimeMs||t.blksize!==e.blksize||t.blocks!==e.blocks||t.ctimeMs!==e.ctimeMs||t.dev!==e.dev||t.gid!==e.gid||t.ino!==e.ino||t.isBlockDevice()!==e.isBlockDevice()||t.isCharacterDevice()!==e.isCharacterDevice()||t.isDirectory()!==e.isDirectory()||t.isFIFO()!==e.isFIFO()||t.isFile()!==e.isFile()||t.isSocket()!==e.isSocket()||t.isSymbolicLink()!==e.isSymbolicLink()||t.mode!==e.mode||t.mtimeMs!==e.mtimeMs||t.nlink!==e.nlink||t.rdev!==e.rdev||t.size!==e.size||t.uid!==e.uid)return!1;let r=t,o=e;return!(r.atimeNs!==o.atimeNs||r.mtimeNs!==o.mtimeNs||r.ctimeNs!==o.ctimeNs||r.birthtimeNs!==o.birthtimeNs)}var MR,UR,OR,ey,ty,HR=Et(()=>{MR=$e(ve("util")),UR=33188,OR=class{constructor(){this.name="";this.path="";this.mode=0}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},ey=class{constructor(){this.uid=0;this.gid=0;this.size=0;this.blksize=0;this.atimeMs=0;this.mtimeMs=0;this.ctimeMs=0;this.birthtimeMs=0;this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=0;this.ino=0;this.mode=UR;this.nlink=1;this.rdev=0;this.blocks=1}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&61440)===16384}isFIFO(){return!1}isFile(){return(this.mode&61440)===32768}isSocket(){return!1}isSymbolicLink(){return(this.mode&61440)===40960}},ty=class{constructor(){this.uid=BigInt(0);this.gid=BigInt(0);this.size=BigInt(0);this.blksize=BigInt(0);this.atimeMs=BigInt(0);this.mtimeMs=BigInt(0);this.ctimeMs=BigInt(0);this.birthtimeMs=BigInt(0);this.atimeNs=BigInt(0);this.mtimeNs=BigInt(0);this.ctimeNs=BigInt(0);this.birthtimeNs=BigInt(0);this.atime=new Date(0);this.mtime=new Date(0);this.ctime=new Date(0);this.birthtime=new Date(0);this.dev=BigInt(0);this.ino=BigInt(0);this.mode=BigInt(UR);this.nlink=BigInt(1);this.rdev=BigInt(0);this.blocks=BigInt(1)}isBlockDevice(){return!1}isCharacterDevice(){return!1}isDirectory(){return(this.mode&BigInt(61440))===BigInt(16384)}isFIFO(){return!1}isFile(){return(this.mode&BigInt(61440))===BigInt(32768)}isSocket(){return!1}isSymbolicLink(){return(this.mode&BigInt(61440))===BigInt(40960)}}});function C_e(t){let e,r;if(e=t.match(y_e))t=e[1];else if(r=t.match(E_e))t=`\\\\${r[1]?".\\":""}${r[2]}`;else return t;return t.replace(/\//g,"\\")}function w_e(t){t=t.replace(/\\/g,"/");let e,r;return(e=t.match(d_e))?t=`/${e[1]}`:(r=t.match(m_e))&&(t=`/unc/${r[1]?".dot/":""}${r[2]}`),t}function DD(t,e){return t===ue?R7(e):jR(e)}var Gw,Bt,dr,ue,V,F7,d_e,m_e,y_e,E_e,jR,R7,Ca=Et(()=>{Gw=$e(ve("path")),Bt={root:"/",dot:".",parent:".."},dr={home:"~",nodeModules:"node_modules",manifest:"package.json",lockfile:"yarn.lock",virtual:"__virtual__",pnpJs:".pnp.js",pnpCjs:".pnp.cjs",pnpData:".pnp.data.json",pnpEsmLoader:".pnp.loader.mjs",rc:".yarnrc.yml",env:".env"},ue=Object.create(Gw.default),V=Object.create(Gw.default.posix);ue.cwd=()=>process.cwd();V.cwd=process.platform==="win32"?()=>jR(process.cwd()):process.cwd;process.platform==="win32"&&(V.resolve=(...t)=>t.length>0&&V.isAbsolute(t[0])?Gw.default.posix.resolve(...t):Gw.default.posix.resolve(V.cwd(),...t));F7=function(t,e,r){return e=t.normalize(e),r=t.normalize(r),e===r?".":(e.endsWith(t.sep)||(e=e+t.sep),r.startsWith(e)?r.slice(e.length):null)};ue.contains=(t,e)=>F7(ue,t,e);V.contains=(t,e)=>F7(V,t,e);d_e=/^([a-zA-Z]:.*)$/,m_e=/^\/\/(\.\/)?(.*)$/,y_e=/^\/([a-zA-Z]:.*)$/,E_e=/^\/unc\/(\.dot\/)?(.*)$/;jR=process.platform==="win32"?w_e:t=>t,R7=process.platform==="win32"?C_e:t=>t;ue.fromPortablePath=R7;ue.toPortablePath=jR});async function SD(t,e){let r="0123456789abcdef";await t.mkdirPromise(e.indexPath,{recursive:!0});let o=[];for(let a of r)for(let n of r)o.push(t.mkdirPromise(t.pathUtils.join(e.indexPath,`${a}${n}`),{recursive:!0}));return await Promise.all(o),e.indexPath}async function T7(t,e,r,o,a){let n=t.pathUtils.normalize(e),u=r.pathUtils.normalize(o),A=[],p=[],{atime:h,mtime:E}=a.stableTime?{atime:Og,mtime:Og}:await r.lstatPromise(u);await t.mkdirpPromise(t.pathUtils.dirname(e),{utimes:[h,E]}),await GR(A,p,t,n,r,u,{...a,didParentExist:!0});for(let I of A)await I();await Promise.all(p.map(I=>I()))}async function GR(t,e,r,o,a,n,u){let A=u.didParentExist?await N7(r,o):null,p=await a.lstatPromise(n),{atime:h,mtime:E}=u.stableTime?{atime:Og,mtime:Og}:p,I;switch(!0){case p.isDirectory():I=await B_e(t,e,r,o,A,a,n,p,u);break;case p.isFile():I=await S_e(t,e,r,o,A,a,n,p,u);break;case p.isSymbolicLink():I=await P_e(t,e,r,o,A,a,n,p,u);break;default:throw new Error(`Unsupported file type (${p.mode})`)}return(u.linkStrategy?.type!=="HardlinkFromIndex"||!p.isFile())&&((I||A?.mtime?.getTime()!==E.getTime()||A?.atime?.getTime()!==h.getTime())&&(e.push(()=>r.lutimesPromise(o,h,E)),I=!0),(A===null||(A.mode&511)!==(p.mode&511))&&(e.push(()=>r.chmodPromise(o,p.mode&511)),I=!0)),I}async function N7(t,e){try{return await t.lstatPromise(e)}catch{return null}}async function B_e(t,e,r,o,a,n,u,A,p){if(a!==null&&!a.isDirectory())if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;let h=!1;a===null&&(t.push(async()=>{try{await r.mkdirPromise(o,{mode:A.mode})}catch(v){if(v.code!=="EEXIST")throw v}}),h=!0);let E=await n.readdirPromise(u),I=p.didParentExist&&!a?{...p,didParentExist:!1}:p;if(p.stableSort)for(let v of E.sort())await GR(t,e,r,r.pathUtils.join(o,v),n,n.pathUtils.join(u,v),I)&&(h=!0);else(await Promise.all(E.map(async x=>{await GR(t,e,r,r.pathUtils.join(o,x),n,n.pathUtils.join(u,x),I)}))).some(x=>x)&&(h=!0);return h}async function v_e(t,e,r,o,a,n,u,A,p,h){let E=await n.checksumFilePromise(u,{algorithm:"sha1"}),I=420,v=A.mode&511,x=`${E}${v!==I?v.toString(8):""}`,C=r.pathUtils.join(h.indexPath,E.slice(0,2),`${x}.dat`),R;(ce=>(ce[ce.Lock=0]="Lock",ce[ce.Rename=1]="Rename"))(R||={});let L=1,U=await N7(r,C);if(a){let ae=U&&a.dev===U.dev&&a.ino===U.ino,fe=U?.mtimeMs!==I_e;if(ae&&fe&&h.autoRepair&&(L=0,U=null),!ae)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1}let J=!U&&L===1?`${C}.${Math.floor(Math.random()*4294967296).toString(16).padStart(8,"0")}`:null,te=!1;return t.push(async()=>{if(!U&&(L===0&&await r.lockPromise(C,async()=>{let ae=await n.readFilePromise(u);await r.writeFilePromise(C,ae)}),L===1&&J)){let ae=await n.readFilePromise(u);await r.writeFilePromise(J,ae);try{await r.linkPromise(J,C)}catch(fe){if(fe.code==="EEXIST")te=!0,await r.unlinkPromise(J);else throw fe}}a||await r.linkPromise(C,o)}),e.push(async()=>{U||(await r.lutimesPromise(C,Og,Og),v!==I&&await r.chmodPromise(C,v)),J&&!te&&await r.unlinkPromise(J)}),!1}async function D_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;return t.push(async()=>{let h=await n.readFilePromise(u);await r.writeFilePromise(o,h)}),!0}async function S_e(t,e,r,o,a,n,u,A,p){return p.linkStrategy?.type==="HardlinkFromIndex"?v_e(t,e,r,o,a,n,u,A,p,p.linkStrategy):D_e(t,e,r,o,a,n,u,A,p)}async function P_e(t,e,r,o,a,n,u,A,p){if(a!==null)if(p.overwrite)t.push(async()=>r.removePromise(o)),a=null;else return!1;return t.push(async()=>{await r.symlinkPromise(DD(r.pathUtils,await n.readlinkPromise(u)),o)}),!0}var Og,I_e,qR=Et(()=>{Ca();Og=new Date(456789e3*1e3),I_e=Og.getTime()});function PD(t,e,r,o){let a=()=>{let n=r.shift();if(typeof n>"u")return null;let u=t.pathUtils.join(e,n);return Object.assign(t.statSync(u),{name:n,path:void 0})};return new qw(e,a,o)}var qw,L7=Et(()=>{BD();qw=class{constructor(e,r,o={}){this.path=e;this.nextDirent=r;this.opts=o;this.closed=!1}throwIfClosed(){if(this.closed)throw LR()}async*[Symbol.asyncIterator](){try{let e;for(;(e=await this.read())!==null;)yield e}finally{await this.close()}}read(e){let r=this.readSync();return typeof e<"u"?e(null,r):Promise.resolve(r)}readSync(){return this.throwIfClosed(),this.nextDirent()}close(e){return this.closeSync(),typeof e<"u"?e(null):Promise.resolve()}closeSync(){this.throwIfClosed(),this.opts.onClose?.(),this.closed=!0}}});function O7(t,e){if(t!==e)throw new Error(`Invalid StatWatcher status: expected '${e}', got '${t}'`)}var M7,ry,U7=Et(()=>{M7=ve("events");HR();ry=class extends M7.EventEmitter{constructor(r,o,{bigint:a=!1}={}){super();this.status="ready";this.changeListeners=new Map;this.startTimeout=null;this.fakeFs=r,this.path=o,this.bigint=a,this.lastStats=this.stat()}static create(r,o,a){let n=new ry(r,o,a);return n.start(),n}start(){O7(this.status,"ready"),this.status="running",this.startTimeout=setTimeout(()=>{this.startTimeout=null,this.fakeFs.existsSync(this.path)||this.emit("change",this.lastStats,this.lastStats)},3)}stop(){O7(this.status,"running"),this.status="stopped",this.startTimeout!==null&&(clearTimeout(this.startTimeout),this.startTimeout=null),this.emit("stop")}stat(){try{return this.fakeFs.statSync(this.path,{bigint:this.bigint})}catch{let o=this.bigint?new ty:new ey;return vD(o)}}makeInterval(r){let o=setInterval(()=>{let a=this.stat(),n=this.lastStats;_R(a,n)||(this.lastStats=a,this.emit("change",a,n))},r.interval);return r.persistent?o:o.unref()}registerChangeListener(r,o){this.addListener("change",r),this.changeListeners.set(r,this.makeInterval(o))}unregisterChangeListener(r){this.removeListener("change",r);let o=this.changeListeners.get(r);typeof o<"u"&&clearInterval(o),this.changeListeners.delete(r)}unregisterAllChangeListeners(){for(let r of this.changeListeners.keys())this.unregisterChangeListener(r)}hasChangeListeners(){return this.changeListeners.size>0}ref(){for(let r of this.changeListeners.values())r.ref();return this}unref(){for(let r of this.changeListeners.values())r.unref();return this}}});function ny(t,e,r,o){let a,n,u,A;switch(typeof r){case"function":a=!1,n=!0,u=5007,A=r;break;default:({bigint:a=!1,persistent:n=!0,interval:u=5007}=r),A=o;break}let p=bD.get(t);typeof p>"u"&&bD.set(t,p=new Map);let h=p.get(e);return typeof h>"u"&&(h=ry.create(t,e,{bigint:a}),p.set(e,h)),h.registerChangeListener(A,{persistent:n,interval:u}),h}function Mg(t,e,r){let o=bD.get(t);if(typeof o>"u")return;let a=o.get(e);typeof a>"u"||(typeof r>"u"?a.unregisterAllChangeListeners():a.unregisterChangeListener(r),a.hasChangeListeners()||(a.stop(),o.delete(e)))}function Ug(t){let e=bD.get(t);if(!(typeof e>"u"))for(let r of e.keys())Mg(t,r)}var bD,YR=Et(()=>{U7();bD=new WeakMap});function b_e(t){let e=t.match(/\r?\n/g);if(e===null)return H7.EOL;let r=e.filter(a=>a===`\r `).length,o=e.length-r;return r>o?`\r diff --git a/src/pages/ticketholderlist/TicketHolderList.tsx b/src/pages/ticketholderlist/TicketHolderList.tsx index ef917726..1ae7b189 100644 --- a/src/pages/ticketholderlist/TicketHolderList.tsx +++ b/src/pages/ticketholderlist/TicketHolderList.tsx @@ -165,14 +165,16 @@ const TicketHolderList = () => { } // 환불 요청 PUT API 요청 // bookingId만 전달 - const filteredPaymentData = paymentData.map(({ bookingId }) => ({ - bookingId: checkedBookingId.includes(bookingId) && bookingId, - })); + + const filteredPaymentData = paymentData + .filter(({ bookingId }) => checkedBookingId.includes(bookingId)) + .map(({ bookingId }) => ({ bookingId })); refundMutate({ performanceId: Number(performanceId), bookingList: filteredPaymentData, }); + closeConfirm(); setTimeout(() => { window.location.reload(); @@ -201,9 +203,10 @@ const TicketHolderList = () => { } // 취소 요청 PUT API 요청 // bookingId만 전달 - const filteredPaymentData = paymentData.map(({ bookingId }) => ({ - bookingId: checkedBookingId.includes(bookingId) && bookingId, - })); + + const filteredPaymentData = paymentData + .filter(({ bookingId }) => checkedBookingId.includes(bookingId)) + .map(({ bookingId }) => ({ bookingId })); deleteMutate({ performanceId: Number(performanceId), From 8df2df5525a72d6e3a35c6217ac2000d8e2dad76 Mon Sep 17 00:00:00 2001 From: imddoy <imddoy@duksung.ac.kr> Date: Sun, 15 Dec 2024 19:38:16 +0900 Subject: [PATCH 49/49] =?UTF-8?q?fix:=20=EB=B2=84=ED=8A=BC=20position=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/pages/cancel/Cancel.styled.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/cancel/Cancel.styled.ts b/src/pages/cancel/Cancel.styled.ts index 3a76459b..052c83b8 100644 --- a/src/pages/cancel/Cancel.styled.ts +++ b/src/pages/cancel/Cancel.styled.ts @@ -97,7 +97,7 @@ export const RadioWrapper = styled.div` `; export const ButtonWrapper = styled.div` - position: absolute; + position: fixed; bottom: 2.4rem; `;