Skip to content

Commit aec7f10

Browse files
committed
Merge remote-tracking branch 'origin/develop' into hotfix/74-Various-fixes
2 parents 2b91a0f + 1f6d7f3 commit aec7f10

7 files changed

Lines changed: 101 additions & 88 deletions

File tree

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

Lines changed: 10 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import { ApiError } from "@/services/apiClient";
1616
import { getArtworkDetail, getMyArtworkDetail } from "@/services/artworks";
1717
import { useAuthStore } from "@/stores/useAuthStore";
1818
import { normalizeImageUrl } from "@/utils/normalizeImageUrl";
19+
import BottomActionButton from "@/components/common/BottomActionButton";
20+
import ArchiveTypeBadge from "@/components/common/ArchiveTypeBadge";
1921

2022
function formatDate(date: string | null) {
2123
if (!date) return "-";
@@ -120,9 +122,7 @@ export default function ArtDetailPage() {
120122
<>
121123
<ImageSwiper images={artworkImages} altPrefix="작품 이미지" />
122124
<div className="text-text-primary flex flex-col gap-1.5 px-5 py-6">
123-
<div className="text-caption bg-object-secondary-light h-6 w-fit min-w-14 rounded-sm px-1.5 py-1 font-medium">
124-
{artwork.artworkType}
125-
</div>
125+
<ArchiveTypeBadge type={artwork.artworkType} />
126126
<div className="text-title-3 font-semibold">{artwork.title}</div>
127127

128128
<RegionText regions={artwork.availableRegions} />
@@ -165,23 +165,13 @@ export default function ArtDetailPage() {
165165
)}
166166
</div>
167167

168-
<div className="border-border-primary bg-bg-primary fixed right-0 bottom-0 left-0 z-50 border-t px-5 pt-3 pb-9">
169-
{inquiryErrorMessage && (
170-
<p
171-
role="alert"
172-
className="text-caption text-error-default mx-auto mb-2 max-w-[430px]"
173-
>
174-
{inquiryErrorMessage}
175-
</p>
176-
)}
177-
<button
178-
onClick={handleInquiryClick}
179-
disabled={createChatRoom.isPending}
180-
className="bg-object-primary text-body-1 text-text-invert flex h-12.5 w-full items-center justify-center rounded-lg font-medium disabled:opacity-50"
181-
>
182-
{createChatRoom.isPending ? "이동 중..." : "전시 문의하기"}
183-
</button>
184-
</div>
168+
<BottomActionButton
169+
text="전시 문의하기"
170+
loadingText="이동 중..."
171+
isPending={createChatRoom.isPending}
172+
errorMessage={inquiryErrorMessage}
173+
onClick={handleInquiryClick}
174+
/>
185175
</>
186176
)}
187177
</div>

src/app/art/new/page.tsx

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import { ART_TYPES } from "@/constants/art";
2121
import { useUploadImage } from "@/hooks/useImageUploader";
2222
import { createArtwork } from "@/services/artworks";
2323
import { useImageStore } from "@/stores/useImageStore";
24+
import BottomActionButton from "@/components/common/BottomActionButton";
2425

2526
function FieldWrapper({ children }: { children: React.ReactNode }) {
2627
return <div className="flex flex-col gap-2">{children}</div>;
@@ -213,25 +214,15 @@ export default function ArtCreatePage() {
213214
</FieldWrapper>
214215
</section>
215216

216-
{/* Bottom Button () */}
217-
<div className="border-border-primary fixed right-0 bottom-4 left-0 h-24.5 border-t bg-white px-5 py-4">
218-
{submitErrorMessage && (
219-
<p role="alert" className="text-caption text-error-default mb-2">
220-
{submitErrorMessage}
221-
</p>
222-
)}
223-
<button
224-
disabled={!isFormValid || isSubmitting}
225-
onClick={handleSubmit}
226-
className={`text-body-1 h-12.5 w-full rounded-lg font-medium transition-colors ${
227-
isFormValid && !isSubmitting
228-
? "bg-object-primary text-text-invert cursor-pointer"
229-
: "bg-object-disabled text-text-disabled cursor-not-allowed"
230-
}`}
231-
>
232-
{isSubmitting ? "등록 중..." : "추가하기"}
233-
</button>
234-
</div>
217+
{/* Bottom Button */}
218+
<BottomActionButton
219+
text="추가하기"
220+
loadingText="등록 중..."
221+
isPending={isSubmitting}
222+
disabled={!isFormValid}
223+
errorMessage={submitErrorMessage}
224+
onClick={handleSubmit}
225+
/>
235226
</main>
236227
);
237228
}

src/app/layout.tsx

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -38,14 +38,15 @@ export default function RootLayout({
3838
return (
3939
<html lang="en" className={`${pretendard.className} ${alata.variable} h-full antialiased`}>
4040
{/* <body className="flex min-h-full flex-col"> */}
41-
<body className="mobile:w-97.5 mx-auto min-h-screen w-full bg-white">
42-
<Providers>{children}</Providers>
43-
<Suspense fallback={null}>
44-
<ScrollManager />
45-
</Suspense>
46-
<Navbar />
47-
<Script id="clarity" strategy="afterInteractive">
48-
{`
41+
<body>
42+
<div className="mobile:w-97.5 mx-auto min-h-screen w-full bg-white">
43+
<Providers>{children}</Providers>
44+
<Suspense fallback={null}>
45+
<ScrollManager />
46+
</Suspense>
47+
<Navbar />
48+
<Script id="clarity" strategy="afterInteractive">
49+
{`
4950
(function(c,l,a,r,i,t,y){
5051
c[a]=c[a]||function(){(c[a].q=c[a].q||[]).push(arguments)};
5152
t=l.createElement(r);
@@ -55,7 +56,8 @@ export default function RootLayout({
5556
y.parentNode.insertBefore(t,y);
5657
})(window, document, "clarity", "script", "${process.env.NEXT_PUBLIC_CLARITY_ID}");
5758
`}
58-
</Script>
59+
</Script>
60+
</div>
5961
</body>
6062
</html>
6163
);

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

Lines changed: 10 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@ import { ApiError } from "@/services/apiClient";
1515
import { getMySpaceDetail, getSpaceDetail } from "@/services/spaces";
1616
import { useAuthStore } from "@/stores/useAuthStore";
1717
import { normalizeImageUrl } from "@/utils/normalizeImageUrl";
18+
import BottomActionButton from "@/components/common/BottomActionButton";
19+
import ArchiveTypeBadge from "@/components/common/ArchiveTypeBadge";
1820

1921
function hasText(value?: string | null) {
2022
return Boolean(value?.trim());
@@ -116,11 +118,7 @@ export default function SpaceDetailPage() {
116118
<ImageSwiper images={spaceImages} altPrefix="공간 이미지" />
117119

118120
<div className="text-text-primary flex flex-col gap-1.5 px-5 py-6">
119-
{hasSpaceType && (
120-
<div className="text-caption bg-object-secondary-light h-6 w-fit min-w-14 rounded-sm px-1.5 py-1 font-medium">
121-
{space.spaceType}
122-
</div>
123-
)}
121+
{hasSpaceType && <ArchiveTypeBadge type={space.spaceType} />}
124122
<div className="text-title-3 font-semibold">{space.title}</div>
125123

126124
{hasAddress && (
@@ -157,23 +155,13 @@ export default function SpaceDetailPage() {
157155
)}
158156
</div>
159157

160-
<div className="border-border-primary bg-bg-primary fixed right-0 bottom-0 left-0 z-50 border-t px-5 pt-3 pb-9">
161-
{inquiryErrorMessage && (
162-
<p
163-
role="alert"
164-
className="text-caption text-error-default mx-auto mb-2 max-w-[430px]"
165-
>
166-
{inquiryErrorMessage}
167-
</p>
168-
)}
169-
<button
170-
onClick={handleInquiryClick}
171-
disabled={createChatRoom.isPending}
172-
className="bg-object-primary text-body-1 text-text-invert flex h-12.5 w-full items-center justify-center rounded-lg font-medium disabled:opacity-50"
173-
>
174-
{createChatRoom.isPending ? "이동 중..." : "전시 문의하기"}
175-
</button>
176-
</div>
158+
<BottomActionButton
159+
text="전시 문의하기"
160+
loadingText="이동 중..."
161+
isPending={createChatRoom.isPending}
162+
errorMessage={inquiryErrorMessage}
163+
onClick={handleInquiryClick}
164+
/>
177165
</>
178166
)}
179167
</div>

src/app/space/new/page.tsx

Lines changed: 9 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { ART_TYPES } from "@/constants/art";
2020
import { useUploadImage } from "@/hooks/useImageUploader";
2121
import { createSpace } from "@/services/spaces";
2222
import { useImageStore } from "@/stores/useImageStore";
23+
import BottomActionButton from "@/components/common/BottomActionButton";
2324

2425
function FieldWrapper({ children }: { children: React.ReactNode }) {
2526
return <div className="flex flex-col gap-2">{children}</div>;
@@ -207,24 +208,14 @@ export default function SpaceCreatePage() {
207208
</section>
208209

209210
{/* Bottom Button () */}
210-
<div className="border-border-primary fixed right-0 bottom-4 left-0 h-24.5 border-t bg-white px-5 py-4">
211-
{submitErrorMessage && (
212-
<p role="alert" className="text-caption text-error-default mb-2">
213-
{submitErrorMessage}
214-
</p>
215-
)}
216-
<button
217-
disabled={!isFormValid || isSubmitting}
218-
onClick={handleSubmit}
219-
className={`text-body-1 h-12.5 w-full rounded-lg font-medium transition-colors ${
220-
isFormValid && !isSubmitting
221-
? "bg-object-primary text-text-invert cursor-pointer"
222-
: "bg-object-disabled text-text-disabled cursor-not-allowed"
223-
}`}
224-
>
225-
{isSubmitting ? "등록 중..." : "추가하기"}
226-
</button>
227-
</div>
211+
<BottomActionButton
212+
text="추가하기"
213+
loadingText="등록 중..."
214+
isPending={isSubmitting}
215+
disabled={!isFormValid}
216+
errorMessage={submitErrorMessage}
217+
onClick={handleSubmit}
218+
/>
228219
</main>
229220
);
230221
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
interface ArtTypeBadgeProps {
2+
type: string | null;
3+
}
4+
5+
export default function ArtTypeBadge({ type }: ArtTypeBadgeProps) {
6+
return (
7+
<div className="text-caption bg-object-secondary-light h-6 w-fit rounded-sm px-1.5 py-1 font-medium">
8+
{type}
9+
</div>
10+
);
11+
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
interface BottomActionButtonProps {
2+
text: string;
3+
loadingText?: string;
4+
isPending?: boolean;
5+
disabled?: boolean;
6+
errorMessage?: string | null;
7+
onClick: () => void;
8+
}
9+
10+
export default function BottomActionButton({
11+
text,
12+
loadingText = "처리 중...",
13+
isPending = false,
14+
disabled = false,
15+
errorMessage,
16+
onClick,
17+
}: BottomActionButtonProps) {
18+
return (
19+
<div className="border-border-primary bg-bg-primary fixed right-0 bottom-0 left-0 z-50 border-t">
20+
<div className="mobile:w-97.5 mx-auto px-5 pt-3 pb-9">
21+
{errorMessage && (
22+
<p role="alert" className="text-caption text-error-default mx-auto mb-2">
23+
{errorMessage}
24+
</p>
25+
)}
26+
<button
27+
onClick={onClick}
28+
disabled={disabled || isPending}
29+
className={`text-body-1 h-12.5 w-full rounded-lg font-medium transition-colors ${
30+
disabled || isPending
31+
? "bg-object-disabled text-text-disabled cursor-not-allowed"
32+
: "bg-object-primary text-text-invert cursor-pointer"
33+
}`}
34+
>
35+
{isPending ? loadingText : text}
36+
</button>
37+
</div>
38+
</div>
39+
);
40+
}

0 commit comments

Comments
 (0)