Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat[#224]: 마이페이지/신청한 예약 api 연동 #225

Merged
merged 8 commits into from
Mar 29, 2024
8 changes: 7 additions & 1 deletion src/components/commons/buttons/CardButton.module.scss
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

span {
display: inline-block;
width: 4.8rem;
width: 6rem;
}
}

Expand Down Expand Up @@ -46,3 +46,9 @@

color: $red;
}

.btn-color-gray {
color: $gray40;
background-color: transparent;
border: 0.1rem solid $gray50;
}
4 changes: 2 additions & 2 deletions src/components/commons/buttons/CardButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@ const cx = classNames.bind(styles);

type CardButton = {
children: string;
onClick: MouseEventHandler<HTMLButtonElement>;
color?: 'yellow' | 'red';
onClick?: MouseEventHandler<HTMLButtonElement>;
color?: 'yellow' | 'red' | 'gray';
};

export const CardButton = ({ children, onClick, color = 'yellow' }: CardButton) => {
Expand Down
16 changes: 7 additions & 9 deletions src/components/commons/cards/ReservedCard.module.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
.card {
@include responsive(PC) {
&:hover {
background-color: $black60;
border-radius: 0.8rem;
}
}

position: relative;

width: 100%;
Expand All @@ -8,15 +15,6 @@

transition: $base-transition;

&:hover {
@include responsive(M) {
background-color: $card-background;
}

background-color: $black60;
border-radius: 0.8rem;
}

&-content {
@include column-flexbox(start, start, 0.4rem);

Expand Down
8 changes: 6 additions & 2 deletions src/components/commons/cards/ReservedCard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { useMutation, useQueryClient } from '@tanstack/react-query';
import classNames from 'classnames/bind';

import { MyReservations } from '@/apis/myReservations';
import { QUERY_KEYS } from '@/apis/queryKeys';
import { SVGS } from '@/constants';
import { isExpirationDate, getFormatDate } from '@/utils';

Expand All @@ -28,6 +29,7 @@ export type ReservedCardProps = {
reservationId: number;
path: string;
status: MyReservationsStatus | string;
reviewSubmitted: boolean;
postType: ReservedPostTypesEN | string;
title: string;
address: string;
Expand All @@ -42,6 +44,7 @@ export const ReservedCard = ({
reservationId,
path,
status,
reviewSubmitted,
postType,
title,
address,
Expand All @@ -54,14 +57,14 @@ export const ReservedCard = ({
const { multiState, toggleClick } = useMultiState(['cancelReservationModal', 'submitReviewModal']);
const isOffline = postType === 'offline';
const isPending = status === 'pending';
const isReviewWritable = status === 'completed' && isExpirationDate(date, endTime);
const isReviewWritable = status === 'completed' && isExpirationDate(date, endTime) && !reviewSubmitted;
const MyReservationDate = `${date} | ${startTime}-${endTime}`;

const queryClient = useQueryClient();
const { mutate: cancelReservationMutation } = useMutation({
mutationFn: MyReservations.cancel,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['myReservations', reservationId] });
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.myReservations.get });
},
});

Expand Down Expand Up @@ -112,6 +115,7 @@ export const ReservedCard = ({
{isReviewWritable && (
<CardButton onClick={(event) => handleButtonClick(event, 'submitReviewModal')}>리뷰</CardButton>
)}
{reviewSubmitted && <CardButton color='gray'>리뷰 완료</CardButton>}
</div>
</Link>
</article>
Expand Down
21 changes: 9 additions & 12 deletions src/components/mypage/MyReservations/ReservedTabContent/index.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import { useState } from 'react';

import { useQuery } from '@tanstack/react-query';
import classNames from 'classnames/bind';

import { MY_RESERVATIONS_STATUS_FILTERS, SORT_OPTIONS } from '@/constants';
import { getMyReservations } from '@/apis/queryFunctions';
import { QUERY_KEYS } from '@/apis/queryKeys';
import { GAME_NAME_KR_TO_PATH_NAME, MY_RESERVATIONS_STATUS_FILTERS, SORT_OPTIONS } from '@/constants';
import { formatStatusToKR, splitTitleByDelimiter } from '@/utils';
import { getPostPageSize } from '@/utils/getPageSize';

Expand All @@ -11,24 +14,15 @@ import Dropdown from '@/components/commons/Dropdown';
import Filter from '@/components/commons/Filter';
import Pagination from '@/components/commons/Pagination';
import EmptyCard from '@/components/layout/empty/EmptyCard';
import myReservationsMockData from '@/constants/mockData/myReservationsMockData.json';
import { useDeviceType } from '@/hooks/useDeviceType';
import useProcessedDataList from '@/hooks/useProcessedDataList';

import { MyReservationsResponse, ReservationResponse, SortOption, Order } from '@/types';
import { ReservationResponse, SortOption, Order } from '@/types';

import styles from './ReservedTabContent.module.scss';

const cx = classNames.bind(styles);

const myReservationsData: MyReservationsResponse = {
cursorId: 0,
totalCount: 0,
reservations: myReservationsMockData,
};

const { reservations: initialDataList } = myReservationsData;

const initialFilter = {
status: MY_RESERVATIONS_STATUS_FILTERS[0].id,
};
Expand All @@ -40,6 +34,8 @@ const initialSortOption: SortOption<ReservationResponse> = {
};

const ReservedTabContent = () => {
const { data: initialDataList } = useQuery({ queryKey: QUERY_KEYS.myReservations.get, queryFn: getMyReservations });

const [page, setPage] = useState(1);
const [selectFilter, setSelectFilter] = useState(initialFilter);
const [sortOption, setSortOption] = useState(initialSortOption);
Expand Down Expand Up @@ -86,8 +82,9 @@ const ReservedTabContent = () => {
<li key={card.id}>
<ReservedCard
reservationId={card.id}
path='/'
path={`/${GAME_NAME_KR_TO_PATH_NAME[category]}/${card.activity.id}`}
status={card.status}
reviewSubmitted={card.reviewSubmitted}
postType={postType}
title={title}
address={address}
Expand Down
26 changes: 13 additions & 13 deletions src/components/mypage/MyReservations/ReviewModalContent/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { FormProvider, useForm } from 'react-hook-form';
import { z } from 'zod';

import { MyReservations } from '@/apis/myReservations';
import { QUERY_KEYS } from '@/apis/queryKeys';
import { SVGS, ERROR_MESSAGE, REGEX } from '@/constants';

import { BaseButton } from '@/components/commons/buttons';
Expand All @@ -27,17 +28,17 @@ type ReviewModalContentProps = {
reservationId: number;
title: string;
date: string;
handleModalClose: (arg: string) => void;
handleModalClose: (modalKey: string) => void;
};

const ReviewModalContent = ({ reservationId, title, date, handleModalClose }: ReviewModalContentProps) => {
const ReviewModalSchema = z.object({
rating: z.number().min(1, { message: rating.min }),
content: z
.string()
.refine((content) => content.replace(REGEX.textarea, '').length >= MIN_LENGTH_TEXTAREA, { message: review.min }),
});
const ReviewModalSchema = z.object({
rating: z.number().min(1, { message: rating.min }),
content: z
.string()
.refine((content) => content.replace(REGEX.textarea, '').length >= MIN_LENGTH_TEXTAREA, { message: review.min }),
});

const ReviewModalContent = ({ reservationId, title, date, handleModalClose }: ReviewModalContentProps) => {
const methods = useForm({
mode: 'all',
resolver: zodResolver(ReviewModalSchema),
Expand All @@ -51,7 +52,7 @@ const ReviewModalContent = ({ reservationId, title, date, handleModalClose }: Re
const { mutate: createReviewMutation } = useMutation({
mutationFn: MyReservations.createReview,
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: ['myReservations', reservationId, 'reviews'] });
queryClient.invalidateQueries({ queryKey: QUERY_KEYS.myReservations.get });
},
});

Expand All @@ -62,15 +63,14 @@ const ReviewModalContent = ({ reservationId, title, date, handleModalClose }: Re
setCurrentRating(rating);
};

const onSubmit = (data: object) => {
const newReview = { reservationId: reservationId, value: data };
createReviewMutation(newReview);
const handleReviewSubmit = (data: object) => {
createReviewMutation({ reservationId: reservationId, value: data });
handleModalClose('submitReviewModal');
};

return (
<FormProvider {...methods}>
<form className={cx('review-form')} onSubmit={handleSubmit(onSubmit)}>
<form className={cx('review-form')} onSubmit={handleSubmit(handleReviewSubmit)}>
<header className={cx('review-form-header')}>
<h2 className={cx('review-form-title')}>{title}</h2>
<div className={cx('review-form-date')}>
Expand Down
7 changes: 7 additions & 0 deletions src/constants/games.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,10 @@ export const GAME_FILTERS = [
{ id: '관광', text: '오버워치 2' },
{ id: '웰빙', text: '마인크래프트' },
];

export const GAME_NAME_KR_TO_PATH_NAME: Record<string, string> = {
리그오브레전드: 'league-of-legends',
배틀그라운드: 'battlegrounds',
'오버워치 2': 'overwatch-2',
마인크래프트: 'minecraft',
};
1 change: 1 addition & 0 deletions src/stories/ReservedCard.stories.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const Example: Story = {
reservationId: 0,
path: '/',
status: 'pending',
reviewSubmitted: false,
postType: 'offline',
title: '[PC방 대회]리그 오브 레전드 개발자들의 PC방 습격!',
address: '강남 SBXG 포탈 PC방',
Expand Down