Skip to content

Commit

Permalink
Merge pull request TEAM-BEAT#454 from TEAM-BEAT/feat/TEAM-BEAT#453/Ti…
Browse files Browse the repository at this point in the history
…cketHolderListFunction

[Feat/TEAM-BEAT#453] 예매자 관리 페이지 기능 구현
  • Loading branch information
sinji2102 authored Dec 9, 2024
2 parents c37fa02 + 9d72603 commit 97a6e7e
Show file tree
Hide file tree
Showing 28 changed files with 3,795 additions and 2,802 deletions.
3 changes: 3 additions & 0 deletions public/svgs/icon_download.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
85 changes: 66 additions & 19 deletions src/apis/domains/tickets/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -15,11 +16,42 @@ 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("scheduleNumbers", convertingScheduleNumber(item))
);
filterList.bookingStatus.map((item) => params.append("bookingStatuses", item));

const response: AxiosResponse<ApiResponseType<TicketRetrieveResponse>> = await get(
`tickets/${formData.performanceId}?${params.toString()}`
);

return response.data.data;
} catch (error) {
console.log("error", error);
return null;
}
};

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("scheduleNumbers", convertingScheduleNumber(item))
);
filterList.bookingStatus.map((item) => params.append("bookingStatuses", item));

const response: AxiosResponse<ApiResponseType<TicketRetrieveResponse>> = await get(
`tickets/${formData.performanceId}`
`tickets/search/${formData.performanceId}?${params.toString()}`
);

return response.data.data;
Expand All @@ -29,17 +61,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 을 사용해야 한다던데..
Expand All @@ -49,7 +75,7 @@ export const putTicketUpdate = async (
): Promise<SuccessResponseVoid | null> => {
try {
const response: AxiosResponse<ApiResponseType<SuccessResponseVoid>> = await put(
"tickets",
"tickets/update",
formData
);

Expand All @@ -60,18 +86,39 @@ 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);
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);
Expand Down
45 changes: 34 additions & 11 deletions src/apis/domains/tickets/queries.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import { QueryClient, useMutation, useQuery } from "@tanstack/react-query";
import { PatchFormDataProps } from "@typings/deleteBookerFormatProps";
import {
getTicketReq,
getTicketRetrieve,
patchTicketCancel,
getTicketRetrieveSearch,
putTicketDelete,
putTicketRefund,
putTicketUpdate,
TicketDeleteRequest,
TicketRefundRequest,
TicketUpdateRequest,
} from "./api";

Expand All @@ -13,19 +16,30 @@ const QUERY_KEY = {
SELLER_BOOKING_LIST: "sellerBookingList",
};

export const useTicketRetrive = (formData: getTicketReq) => {
export const useTicketRetrive = (formData: getTicketReq, filterList) => {
return useQuery({
queryKey: [QUERY_KEY.SELLER_BOOKING_LIST],
queryFn: () => getTicketRetrieve(formData),
// staleTime: 1000 * 60 * 60,
queryFn: () => getTicketRetrieve(formData, filterList),
staleTime: 1000 * 60 * 60,
gcTime: 1000 * 60 * 60 * 24,
});
};

// 예매자 목록 검색 API (GET)를 위한 쿼리 작성

export const useTicketRetriveSearch = (formData: getTicketReq, searchWord, filterList) => {
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) => {
Expand All @@ -35,12 +49,21 @@ export const useTicketUpdate = () => {
});
};

// 예매자를 취소하는 API (PATCH)를 위한 쿼리 작성
export const useTicketPatch = () => {
const queryClient = new QueryClient();
// 예매자 환불 여부 수정 API (PUT)를 위한 쿼리 작성
export const useTicketRefund = () => {
return useMutation({
mutationFn: (formData: TicketRefundRequest) => putTicketRefund(formData),
onSuccess: (res) => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST] });
queryClient.refetchQueries({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST] });
},
});
};

// 예매자 삭제 여부 수정 API (PUT)를 위한 쿼리 작성
export const useTicketDelete = () => {
return useMutation({
mutationFn: (formData: PatchFormDataProps) => patchTicketCancel(formData),
mutationFn: (formData: TicketDeleteRequest) => putTicketDelete(formData),
onSuccess: (res) => {
queryClient.invalidateQueries({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST] });
queryClient.refetchQueries({ queryKey: [QUERY_KEY.SELLER_BOOKING_LIST] });
Expand Down
11 changes: 11 additions & 0 deletions src/assets/svgs/IconDownload.tsx
Original file line number Diff line number Diff line change
@@ -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;
2 changes: 1 addition & 1 deletion src/assets/svgs/IconSearch.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
70 changes: 0 additions & 70 deletions src/assets/svgs/index.ts

This file was deleted.

3 changes: 2 additions & 1 deletion src/assets/svgs/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -70,4 +71,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";
export { default as Union } from "./Union";
18 changes: 16 additions & 2 deletions src/components/commons/navigation/Navigation.styled.ts
Original file line number Diff line number Diff line change
@@ -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`
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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"]};
Expand Down
13 changes: 13 additions & 0 deletions src/components/commons/navigation/Navigation.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
20 changes: 20 additions & 0 deletions src/constants/convertingBookingStatus.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
type PaymentType =
| "CHECKING_PAYMENT"
| "BOOKING_CONFIRMED"
| "BOOKING_CANCELLED"
| "REFUND_REQUESTED";

export const convertingBookingStatus = (_bookingStatus: PaymentType): string => {
switch (_bookingStatus) {
case "CHECKING_PAYMENT":
return "미입금";
case "BOOKING_CONFIRMED":
return "입금 완료";
case "BOOKING_CANCELLED":
return "취소 완료";
case "REFUND_REQUESTED":
return "환불 요청";
default:
throw new Error("알 수 없는 상태입니다.");
}
};
Loading

0 comments on commit 97a6e7e

Please sign in to comment.