Skip to content

Commit 48a487a

Browse files
authored
Merge pull request #86 from JECT-Study/claude/exhibition-request-access-4jvwk0
2 parents 64d5ce4 + bd5e70f commit 48a487a

3 files changed

Lines changed: 64 additions & 18 deletions

File tree

src/app/art/[id]/page.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,13 +11,14 @@ import ImageSwiper from "@/components/archive-detail/ImageSwiper";
1111
import NicknameCard from "@/components/archive-detail/NicknameCard";
1212
import RegionText from "@/components/archive-detail/RegionText";
1313
import SizeText from "@/components/archive-detail/SizeText";
14+
import ArchiveTypeBadge from "@/components/common/ArchiveTypeBadge";
15+
import BottomActionButton from "@/components/common/BottomActionButton";
1416
import { useCreateChatRoom } from "@/hooks/useCreateChatRoom";
17+
import { useMyRole } from "@/hooks/useMyRole";
1518
import { ApiError } from "@/services/apiClient";
1619
import { getArtworkDetail, getMyArtworkDetail } from "@/services/artworks";
1720
import { useAuthStore } from "@/stores/useAuthStore";
1821
import { normalizeImageUrl } from "@/utils/normalizeImageUrl";
19-
import BottomActionButton from "@/components/common/BottomActionButton";
20-
import ArchiveTypeBadge from "@/components/common/ArchiveTypeBadge";
2122

2223
function formatDate(date: string | null) {
2324
if (!date) return "-";
@@ -42,8 +43,13 @@ export default function ArtDetailPage() {
4243
const artworkId = params.id;
4344
const createChatRoom = useCreateChatRoom();
4445
const accessToken = useAuthStore(state => state.accessToken);
46+
const { role, isLoggedIn } = useMyRole();
4547
const [inquiryErrorMessage, setInquiryErrorMessage] = useState<string | null>(null);
4648

49+
// 작품 전시 문의는 공간주(SPACE_PARTNER)만 가능. 크리에이터끼리 문의 차단.
50+
// 비로그인 시에는 노출하고 클릭 시 로그인 페이지로 유도한다.
51+
const canInquire = !isLoggedIn || role === "SPACE_PARTNER";
52+
4753
const query = useQuery({
4854
queryKey: ["artwork-detail", artworkId, Boolean(accessToken)],
4955
queryFn: async ({ signal }) => {
@@ -165,13 +171,15 @@ export default function ArtDetailPage() {
165171
)}
166172
</div>
167173

168-
<BottomActionButton
169-
text="전시 문의하기"
170-
loadingText="이동 중..."
171-
isPending={createChatRoom.isPending}
172-
errorMessage={inquiryErrorMessage}
173-
onClick={handleInquiryClick}
174-
/>
174+
{canInquire && (
175+
<BottomActionButton
176+
text="전시 문의하기"
177+
loadingText="이동 중..."
178+
isPending={createChatRoom.isPending}
179+
errorMessage={inquiryErrorMessage}
180+
onClick={handleInquiryClick}
181+
/>
182+
)}
175183
</>
176184
)}
177185
</div>

src/app/space/[id]/page.tsx

Lines changed: 17 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,14 @@ import ExpandableText from "@/components/archive-detail/ExpandableText";
1010
import ImageSwiper from "@/components/archive-detail/ImageSwiper";
1111
import NicknameCard from "@/components/archive-detail/NicknameCard";
1212
import SizeText from "@/components/archive-detail/SizeText";
13+
import ArchiveTypeBadge from "@/components/common/ArchiveTypeBadge";
14+
import BottomActionButton from "@/components/common/BottomActionButton";
1315
import { useCreateChatRoom } from "@/hooks/useCreateChatRoom";
16+
import { useMyRole } from "@/hooks/useMyRole";
1417
import { ApiError } from "@/services/apiClient";
1518
import { getMySpaceDetail, getSpaceDetail } from "@/services/spaces";
1619
import { useAuthStore } from "@/stores/useAuthStore";
1720
import { normalizeImageUrl } from "@/utils/normalizeImageUrl";
18-
import BottomActionButton from "@/components/common/BottomActionButton";
19-
import ArchiveTypeBadge from "@/components/common/ArchiveTypeBadge";
2021

2122
function hasText(value?: string | null) {
2223
return Boolean(value?.trim());
@@ -36,8 +37,13 @@ export default function SpaceDetailPage() {
3637
const spaceId = params.id;
3738
const createChatRoom = useCreateChatRoom();
3839
const accessToken = useAuthStore(state => state.accessToken);
40+
const { role, isLoggedIn } = useMyRole();
3941
const [inquiryErrorMessage, setInquiryErrorMessage] = useState<string | null>(null);
4042

43+
// 공간 전시 문의는 크리에이터(CREATOR)만 가능. 공간주끼리 문의 차단.
44+
// 비로그인 시에는 노출하고 클릭 시 로그인 페이지로 유도한다.
45+
const canInquire = !isLoggedIn || role === "CREATOR";
46+
4147
const query = useQuery({
4248
queryKey: ["space-detail", spaceId, Boolean(accessToken)],
4349
queryFn: async ({ signal }) => {
@@ -155,13 +161,15 @@ export default function SpaceDetailPage() {
155161
)}
156162
</div>
157163

158-
<BottomActionButton
159-
text="전시 문의하기"
160-
loadingText="이동 중..."
161-
isPending={createChatRoom.isPending}
162-
errorMessage={inquiryErrorMessage}
163-
onClick={handleInquiryClick}
164-
/>
164+
{canInquire && (
165+
<BottomActionButton
166+
text="전시 문의하기"
167+
loadingText="이동 중..."
168+
isPending={createChatRoom.isPending}
169+
errorMessage={inquiryErrorMessage}
170+
onClick={handleInquiryClick}
171+
/>
172+
)}
165173
</>
166174
)}
167175
</div>

src/hooks/useMyRole.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
"use client";
2+
3+
import { useQuery } from "@tanstack/react-query";
4+
5+
import { getMe } from "@/services/authApi";
6+
import { useAuthStore } from "@/stores/useAuthStore";
7+
import type { UserRole } from "@/types/auth";
8+
9+
/**
10+
* 현재 로그인한 사용자의 role을 조회한다.
11+
* - 비로그인 시 쿼리를 끄고 role은 undefined.
12+
* - ["auth", "me"] 키를 공유해 다른 곳의 me 캐시를 재사용한다.
13+
*/
14+
export function useMyRole() {
15+
const accessToken = useAuthStore(state => state.accessToken);
16+
17+
const query = useQuery({
18+
queryKey: ["auth", "me"],
19+
queryFn: ({ signal }) => getMe(signal),
20+
enabled: Boolean(accessToken),
21+
retry: false,
22+
staleTime: 5 * 60 * 1000,
23+
});
24+
25+
return {
26+
role: query.data?.role as UserRole | undefined,
27+
isLoggedIn: Boolean(accessToken),
28+
isRoleLoading: query.isLoading,
29+
};
30+
}

0 commit comments

Comments
 (0)