diff --git a/public/icons/chevron_vector.svg b/public/icons/chevron_vector.svg new file mode 100644 index 00000000..53c91346 --- /dev/null +++ b/public/icons/chevron_vector.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/app/gathering/[id]/page.tsx b/src/app/gathering/[id]/page.tsx index f32bad56..84f0a97b 100644 --- a/src/app/gathering/[id]/page.tsx +++ b/src/app/gathering/[id]/page.tsx @@ -38,20 +38,22 @@ export default function GatheringDetail({ return (
{`모여방 | ${gatheringData.name}`} -
-
-
+
+ {/* Main section과 JoinBox를 포함하는 컨테이너 */} +
+ {/* Main section 컨테이너 */} +
-
+
- {hostData ? ( -
+ {hostData && ( +
- ) : null} + )} -
+ {/* Review section */} +
diff --git a/src/components/gatheringDetail/GatheringDetailSection.tsx b/src/components/gatheringDetail/GatheringDetailSection.tsx index ba87026b..99ecbe34 100644 --- a/src/components/gatheringDetail/GatheringDetailSection.tsx +++ b/src/components/gatheringDetail/GatheringDetailSection.tsx @@ -2,6 +2,7 @@ import { levels } from '@/constants/themeList'; import Image from 'next/image'; interface GatheringDetailSectionProps { + message: string; synopsis: string; level: string; themeName: string; @@ -13,6 +14,7 @@ interface GatheringDetailSectionProps { } export default function GatheringDetailSection({ + message, synopsis, level, themeName, @@ -36,32 +38,86 @@ export default function GatheringDetailSection({ levels.find((item) => item.value === level)?.label || level; return ( -
+
{/* 방탈출 정보 섹션 */}
-

+

방탈출 정보

-
-
-

테마명

- {themeName} +
+
+

+ 테마명 +

+ {themeName}
-
-

시놉시스

-

{synopsis}

+
+

+ 시놉시스 +

+

+ {synopsis} +

-
-

플레이타임

- {playtime}분 +
+

+ 플레이타임 +

+ {playtime}분
-
-

난이도

+
+

+ 난이도 +

- {levelsLabel} + {levelsLabel}
@@ -69,30 +125,96 @@ export default function GatheringDetailSection({ {/* 모임 안내 섹션 */}
-

모임 안내

-
-
-

모임 일시

- {formatDate(dateTime)} +

+ 모임 안내 +

+
+
+

+ 모집글 +

+ {message} +
+ +
+

+ 모임 일시 +

+ {formatDate(dateTime)}
-
-

신청 마감

- {formatDate(registrationEnd)} +
+

+ 신청 마감 +

+ + {formatDate(registrationEnd)} +
-
-

모임 정원

- {capacity}명 +
+

+ 모임 정원 +

+ {capacity}명
-
-

참여 유저

+
+

+ 참여 유저 +

{Array.from({ length: participantCount }, (_, i) => (
item.value === location)?.label || location; useEffect(() => { - const favorites = localStorage.getItem('favorites'); + const favorites = localStorage.getItem(STORAGE_KEYS.FAVORITES); if (favorites) { const favoritesList = JSON.parse(favorites); setIsLiked(favoritesList.includes(gatheringId)); } }, [gatheringId]); - useEffect( - function T() { - if (showToast) { - const timer = setTimeout(() => { - setShowToast(false); - }, 3000); - - return function cleanup() { - clearTimeout(timer); - }; - } - }, - [showToast] - ); + // eslint-disable-next-line consistent-return + useEffect(() => { + if (showToast) { + const timer = setTimeout(() => { + setShowToast(false); + }, 3000); + + return function cleanup() { + clearTimeout(timer); + }; + } + }, [showToast]); const handleLike = () => { - const token = localStorage.getItem('accessToken'); + const token = localStorage.getItem(STORAGE_KEYS.ACCESS_TOKEN); if (!token) { return; } - const favorites = localStorage.getItem('favorites'); + const favorites = localStorage.getItem(STORAGE_KEYS.FAVORITES); let favoritesList = favorites ? JSON.parse(favorites) : []; if (isLiked) { @@ -70,7 +74,7 @@ export default function GatheringMainSection({ favoritesList.push(gatheringId); } - localStorage.setItem('favorites', JSON.stringify(favoritesList)); + localStorage.setItem(STORAGE_KEYS.FAVORITES, JSON.stringify(favoritesList)); setIsLiked(!isLiked); }; @@ -79,7 +83,6 @@ export default function GatheringMainSection({ await navigator.clipboard.writeText(window.location.href); setShowToast(true); } catch (error) { - // eslint-disable-next-line no-console console.error('공유하기 실패:', error); } }; @@ -97,30 +100,57 @@ export default function GatheringMainSection({ } as const; return ( - <> -
-
-
- {themeName} -
- -
-
+
+
+ {/* 이미지 컨테이너 */} +
+ {themeName} setImageError(true)} + /> +
+ + {/* 뱃지 및 버튼 컨테이너 */} +
+
+ {/* 뱃지 그룹 */} +
{levelLabels[level as keyof typeof levelLabels]} - {locationLabel} - + + {locationLabel} + + {new Date(dateTime).toLocaleDateString('ko-KR', { month: 'long', day: 'numeric', @@ -128,7 +158,8 @@ export default function GatheringMainSection({
-
+ {/* 버튼 그룹 */} +
- -
- -

- {name} -

- -
-
- 위치 아이콘 - {locationLabel} -
+
+ + {/* 구분선 */} +
+ {/* 제목 */} +

+ {name} +

+ + {/* 위치 정보 */} +
+
+ 위치 아이콘 + {locationLabel}
-
-
+
+
{/* Toast 알림 */} {showToast && } - +
); } diff --git a/src/components/gatheringDetail/GatheringReviewSection.tsx b/src/components/gatheringDetail/GatheringReviewSection.tsx index 2858bef2..d8285fa9 100644 --- a/src/components/gatheringDetail/GatheringReviewSection.tsx +++ b/src/components/gatheringDetail/GatheringReviewSection.tsx @@ -33,7 +33,7 @@ export default function GatheringReviewSection({ width={16} height={16} alt="" - className="h-4 w-4" + className="h-3 w-3 md:h-4 md:w-4" /> ))}
@@ -42,9 +42,9 @@ export default function GatheringReviewSection({ if (isLoading) { return ( -
+
-

+

방탈출 리뷰

@@ -56,9 +56,9 @@ export default function GatheringReviewSection({ if (isError) { return ( -
+
-

+

방탈출 리뷰

@@ -69,36 +69,36 @@ export default function GatheringReviewSection({ } return ( -
- {/* 구분선 */} -
+
+
+

+ 방탈출 리뷰 +

- {/* 제목 */} -

방탈출 리뷰

- - {/* 리뷰 목록 */} -
+
{reviews && reviews.length > 0 ? ( reviews.map((review) => (
-
-
+
+
프로필 이미지
-

{review.user.nickname}

+

+ {review.user.nickname} +

{renderStars(review.score)}
- + {new Date(review.createdAt).toLocaleDateString('ko-KR', { year: 'numeric', month: 'long', @@ -106,11 +106,15 @@ export default function GatheringReviewSection({ })}
-

{review.comment}

+

+ {review.comment} +

)) ) : ( - 아직 리뷰가 없습니다. + + 아직 리뷰가 없습니다. + )}
diff --git a/src/components/gatheringDetail/JoinBoxSection.tsx b/src/components/gatheringDetail/JoinBoxSection.tsx index 4de29272..bce019ed 100644 --- a/src/components/gatheringDetail/JoinBoxSection.tsx +++ b/src/components/gatheringDetail/JoinBoxSection.tsx @@ -151,13 +151,16 @@ export default function JoinBoxSection({ return ( <> -