Skip to content

Commit 5a01586

Browse files
authored
Merge pull request #136 from codeit-2team/fix/130
Fix/130 QA사항 수정/리팩토링
2 parents 64ef4f4 + 0c74219 commit 5a01586

File tree

13 files changed

+122
-50
lines changed

13 files changed

+122
-50
lines changed

src/app/(with-header)/activities/[id]/components/ActivityDetailForm.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ export default function ActivityDetailForm() {
9696
);
9797

9898
return (
99-
<div className='mx-auto max-w-1200 p-4 sm:px-20 lg:p-8'>
99+
<div className='mx-auto mt-30 max-w-1200 p-4 px-20 sm:px-20 lg:p-8'>
100100
<Title
101101
title={activityData.title}
102102
category={activityData.category}

src/app/(with-header)/activities/[id]/components/ImageGrid.tsx

Lines changed: 47 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -3,44 +3,83 @@
33
import Image from 'next/image';
44
import React, { useState } from 'react';
55
import { ImageGridProps } from '@/types/activityDetailType';
6+
import { AnimatePresence, motion } from 'framer-motion';
67

78
function ImageGrid({ mainImage, subImages }: ImageGridProps) {
89
const images = [mainImage, ...subImages];
910

1011
const [currentIndex, setCurrentIndex] = useState(0);
12+
const [direction, setDirection] = useState(0);
1113

1214
const prevSlide = () => {
15+
setDirection(-1);
1316
setCurrentIndex((prev) => (prev === 0 ? images.length - 1 : prev - 1));
1417
};
1518

1619
const nextSlide = () => {
20+
setDirection(1);
1721
setCurrentIndex((prev) => (prev === images.length - 1 ? 0 : prev + 1));
1822
};
1923

24+
const variants = {
25+
enter: (direction: number) => ({
26+
x: direction > 0 ? 300 : -300,
27+
opacity: 0,
28+
}),
29+
center: {
30+
x: 0,
31+
opacity: 1,
32+
},
33+
exit: (direction: number) => ({
34+
x: direction > 0 ? -300 : 300,
35+
opacity: 0,
36+
}),
37+
};
38+
2039
return (
2140
<>
2241
{/* 모바일 */}
2342
<div className='relative block aspect-square h-[300px] w-full overflow-hidden rounded-lg md:hidden'>
24-
<Image
25-
src={images[currentIndex]}
26-
alt={`슬라이드 이미지 ${currentIndex + 1}`}
27-
fill
28-
className='object-cover hover:animate-pulse'
29-
/>
43+
<AnimatePresence custom={direction} initial={false}>
44+
<motion.div
45+
key={currentIndex}
46+
custom={direction}
47+
variants={variants}
48+
initial='enter'
49+
animate='center'
50+
exit='exit'
51+
transition={{
52+
x: { type: 'spring', stiffness: 300, damping: 30 },
53+
opacity: { duration: 0.2 },
54+
}}
55+
className='absolute inset-0'
56+
>
57+
<Image
58+
src={images[currentIndex]}
59+
alt={` ${currentIndex + 1}`}
60+
fill
61+
className='rounded-lg object-cover'
62+
priority
63+
/>
64+
</motion.div>
65+
</AnimatePresence>
66+
3067
<button
3168
onClick={prevSlide}
3269
aria-label='이전 이미지'
3370
className='absolute top-1/2 left-2 -translate-y-1/2 rounded-full bg-black/50 px-6 py-10 text-white'
3471
>
3572
3673
</button>
74+
3775
<button
3876
onClick={nextSlide}
3977
aria-label='다음 이미지'
4078
className='absolute top-1/2 right-2 -translate-y-1/2 rounded-full bg-black/50 px-6 py-10 text-white'
4179
>
4280
4381
</button>
82+
4483
<div className='absolute bottom-2 left-1/2 flex -translate-x-1/2 gap-1'>
4584
{images.map((_, i) => (
4685
<div
@@ -52,7 +91,8 @@ function ImageGrid({ mainImage, subImages }: ImageGridProps) {
5291
))}
5392
</div>
5493
</div>
55-
{/* PC 태블릿 */}
94+
95+
{/* PC/태블릿 */}
5696
<div className='hidden h-[500px] grid-cols-4 grid-rows-4 gap-6 md:grid'>
5797
<div className='relative col-span-2 row-span-4 hover:animate-pulse'>
5898
<Image
@@ -62,7 +102,6 @@ function ImageGrid({ mainImage, subImages }: ImageGridProps) {
62102
className='rounded-lg object-cover'
63103
/>
64104
</div>
65-
66105
{subImages.slice(0, 4).map((image, index) => (
67106
<div
68107
key={index}

src/app/(with-header)/activities/[id]/components/ReviewSection.tsx

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,11 @@ function ReviewSection({
8787
<div className='relative min-h-350'>
8888
<ReviewTitle reviewCount={reviewCount} rating={rating} />
8989

90-
<div className='pointer-events-none absolute inset-0 z-10 flex items-center justify-center'>
91-
<div className='flex items-center justify-center font-bold'>
92-
<p>작성된 리뷰가 없습니다</p>
90+
<div className='pointer-events-none absolute inset-0 z-10 flex h-full items-center justify-center select-none'>
91+
<div className='flex max-w-md items-center justify-center rounded-md bg-white px-20 py-20 shadow-2xl ring-1 ring-gray-200 select-none'>
92+
<p className='text-md text-center font-bold text-gray-800'>
93+
작성된 후기가 없습니다
94+
</p>
9395
</div>
9496
</div>
9597
</div>
@@ -98,20 +100,20 @@ function ReviewSection({
98100
}
99101

100102
if (isError) {
101-
throw new Error('에러발생');
103+
throw new Error('리뷰섹션에서 에러가 발생했습니다.');
102104
}
103105

104106
return (
105107
<div className='mt-10 flex flex-col space-y-8'>
106108
<ReviewTitle reviewCount={reviewCount} rating={rating} />
107109

108-
<div className='relative min-h-350'>
110+
<div className='pointer-events-none relative min-h-350 select-none'>
109111
<div className={user ? '' : 'blur-sm'}>{ReviewComponent()}</div>
110112

111113
{!user && (
112-
<div className='pointer-events-none absolute inset-0 z-10 flex items-center justify-center'>
113-
<div className='rounded-md bg-white/70 px-4 py-2 shadow-md'>
114-
<p className='text-sm font-semibold text-gray-700'>
114+
<div className='pointer-events-none absolute inset-0 z-10 flex h-full items-center justify-center select-none'>
115+
<div className='flex max-w-md items-center justify-center rounded-md bg-white px-20 py-20 shadow-2xl ring-1 ring-gray-200 select-none'>
116+
<p className='text-md text-center font-bold text-gray-800'>
115117
로그인 후 리뷰 전체 내용을 확인할 수 있어요
116118
</p>
117119
</div>

src/app/(with-header)/activities/[id]/components/ReviewTitle.tsx

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,11 @@ export default function ReviewTitle({
1515

1616
useEffect(() => {
1717
const handleSummary = () => {
18+
if (reviewCount === 0) {
19+
setSummary('작성된 후기가 없습니다');
20+
return;
21+
}
22+
1823
if (rating >= 4.5) {
1924
setSummary('매우 만족');
2025
} else if (rating >= 3) {

src/app/(with-header)/activities/[id]/components/Skeleton.tsx

Lines changed: 0 additions & 4 deletions
This file was deleted.

src/app/(with-header)/activities/[id]/components/Title.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ function Title({
4646
mutate(id as string);
4747
setIsPopupOpen(false);
4848
};
49+
4950

5051
return (
5152
<>
@@ -55,14 +56,14 @@ function Title({
5556
<h1 className='mb-2 text-2xl font-bold text-black md:text-3xl'>
5657
{title}
5758
</h1>
58-
<div className='flex items-center gap-10 text-sm text-gray-600'>
59+
<div className='flex flex-nowrap items-center gap-30 text-sm text-gray-600'>
5960
<div className='flex items-center gap-1'>
6061
<Star />
61-
<span className='font-medium'>
62+
<p className='font-medium'>
6263
{rating.toFixed(1)} ({reviewCount}명)
63-
</span>
64+
</p>
6465
</div>
65-
<span>{address}</span>
66+
<p>{address}</p>
6667
</div>
6768
</div>
6869

src/app/(with-header)/myactivity/[id]/hooks/useEditActivityForm.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import { uploadImage } from '../../utils/uploadImage';
88
import { ActivityDetailEdit, Schedule } from '@/types/activityDetailType';
99
import { AxiosError } from 'axios';
1010
import { toast } from 'sonner';
11+
import { notFound } from 'next/navigation';
1112

1213
interface SubImageType {
1314
id?: number;
@@ -32,14 +33,26 @@ export const useEditActivityForm = () => {
3233
const [originalSchedules, setOriginalSchedules] = useState<Schedule[]>([]);
3334
const [dates, setDates] = useState<Schedule[]>([]);
3435

35-
const { data, isLoading, isError } = useQuery<ActivityDetailEdit, Error>({
36+
const { data, isLoading, status, isError, error } = useQuery<
37+
ActivityDetailEdit,
38+
Error
39+
>({
3640
queryKey: ['edit-activity', id],
3741
queryFn: async () => {
3842
const res = await privateInstance.get(`/activities/${id}`);
3943
return res.data;
4044
},
4145
enabled: !!id,
4246
});
47+
if (status === 'error') {
48+
const axiosError = error as AxiosError;
49+
const httpStatus = axiosError.response?.status;
50+
51+
if (httpStatus === 404) {
52+
console.log('404 에러임');
53+
notFound();
54+
}
55+
}
4356

4457
useEffect(() => {
4558
if (data) {

src/components/FloatingBox/BookingButton.tsx

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,37 @@
11
import React from 'react';
2+
import { cn } from '@/lib/utils';
23

34
interface BookingButtonProps {
45
onClick: () => void;
56
children: React.ReactNode;
67
disabled?: boolean;
78
onBooking?: boolean;
9+
className?: string;
810
}
911

1012
export default function BookingButton({
1113
onClick,
1214
children,
1315
disabled = false,
1416
onBooking = false,
17+
className = '',
1518
}: BookingButtonProps) {
1619
return (
1720
<button
1821
onClick={onClick}
1922
disabled={disabled || onBooking}
20-
className={`relative mt-4 mb-6 w-full max-w-sm rounded-lg py-10 font-medium transition-colors ${
23+
className={cn(
24+
'relative mt-4 mb-6 w-full max-w-sm rounded-lg py-10 font-medium transition-colors',
2125
disabled || onBooking
2226
? 'cursor-not-allowed bg-gray-300 text-gray-500'
23-
: 'bg-green-800 text-white hover:bg-green-900'
24-
}`}
27+
: 'bg-green-800 text-white hover:bg-green-900',
28+
className,
29+
)}
2530
>
2631
{onBooking ? (
2732
<div className='flex items-center justify-center gap-2'>
2833
<span className='h-10 w-10 animate-spin rounded-full border-2 border-white border-t-transparent' />
29-
<p>예약 중...</p>
34+
<p>...</p>
3035
</div>
3136
) : (
3237
children

src/components/FloatingBox/BookingInterface.tsx

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -114,10 +114,10 @@ export default function BookingInterface({
114114
<h3 className='mb-4 text-lg font-semibold text-gray-900'>날짜</h3>
115115
<button
116116
onClick={() => setIsOpen(true)}
117-
className='w-full rounded-lg border border-gray-300 p-3 py-8 text-left text-black hover:bg-gray-50'
117+
className='flex w-full items-center justify-center rounded-lg border border-gray-300 p-3 py-8 text-left text-black hover:bg-gray-50'
118118
>
119119
{selectedDate && selectedTime ? (
120-
<h2>
120+
<h2 className='animate-pulse'>
121121
{selectedDate instanceof Date
122122
? selectedDate.toLocaleDateString()
123123
: selectedDate}
@@ -145,18 +145,13 @@ export default function BookingInterface({
145145
</div>
146146

147147
{/* 모바일 */}
148-
<div className='fixed right-0 bottom-0 left-0 z-50 block border border-gray-200 bg-white p-6 md:hidden'>
148+
<div className='fixed right-0 bottom-0 left-0 z-50 block h-150 border border-gray-200 bg-white px-20 md:hidden'>
149149
<div className='mb-6 flex items-start justify-between'>
150150
<div className='flex-1'>
151-
<div className='mb-1 text-xl font-bold text-gray-900'>
152-
{price}
153-
<span className='text-sm font-normal text-gray-600'>
154-
/ 총 {participants}
155-
</span>
156-
</div>
151+
<PriceDisplay price={price} />
157152
<div
158153
onClick={() => setIsOpen(true)}
159-
className='mb-4 text-sm text-gray-600'
154+
className='mb-4 animate-pulse cursor-pointer text-sm text-gray-600'
160155
>
161156
{selectedDate && selectedTime ? (
162157
<h2>

src/components/FloatingBox/PriceDisplay.tsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,8 @@ export default function PriceDisplay({ price }: { price: number }) {
22
return (
33
<div className='mt-15 mb-6'>
44
<div className='mb-1 text-2xl font-bold text-black'>
5-
{price} <span className='text-xl font-bold text-gray-800'>/ 인</span>
5+
{price.toLocaleString('ko-KR')}{' '}
6+
<span className='text-xl font-bold text-gray-800'>/ 인</span>
67
</div>
78
</div>
89
);

0 commit comments

Comments
 (0)