diff --git a/src/app/(private)/[clubId]/admin/layout.tsx b/src/app/(private)/[clubId]/admin/layout.tsx index ac3829b0..51a66fa8 100644 --- a/src/app/(private)/[clubId]/admin/layout.tsx +++ b/src/app/(private)/[clubId]/admin/layout.tsx @@ -38,7 +38,7 @@ export default async function AdminLayout({
-
+
{children}
diff --git a/src/components/admin/club-info/AdminInfoCard.tsx b/src/components/admin/club-info/AdminInfoCard.tsx index 97bdbb46..c3a4f9b2 100644 --- a/src/components/admin/club-info/AdminInfoCard.tsx +++ b/src/components/admin/club-info/AdminInfoCard.tsx @@ -17,13 +17,15 @@ function AdminInfoCard({ return (
-

{title}

-
+

{title}

+
{children}
diff --git a/src/components/admin/club-info/ClubInfoBasicSection.tsx b/src/components/admin/club-info/ClubInfoBasicSection.tsx index b1b02368..b18f0c2c 100644 --- a/src/components/admin/club-info/ClubInfoBasicSection.tsx +++ b/src/components/admin/club-info/ClubInfoBasicSection.tsx @@ -40,21 +40,41 @@ function ClubInfoBasicSection({ - onNameChange(e.target.value)} - className="bg-container-neutral-alternative rounded-sm border-transparent px-400 py-300" - /> +
+ onNameChange(e.target.value)} + maxLength={30} + className="bg-container-neutral-alternative rounded-sm border-transparent px-400 py-300" + /> +
+ + {clubName.length}/30 + +
+
- - onDescriptionChange(e.target.value)} - maxLength={30} - placeholder="동아리를 소개하는 짧은 글을 작성해주세요" - className="bg-container-neutral-alternative rounded-sm border-transparent px-400 py-300" - /> + +
+ onDescriptionChange(e.target.value)} + maxLength={30} + placeholder="동아리를 소개하는 짧은 글을 작성해주세요" + className="bg-container-neutral-alternative rounded-sm border-transparent px-400 py-300" + /> +
+ {descriptionError ? ( + {descriptionError} + ) : ( + + )} + + {description.length}/30 + +
+
diff --git a/src/components/admin/club-info/ClubInfoContactSection.tsx b/src/components/admin/club-info/ClubInfoContactSection.tsx index 55689566..ccd4277e 100644 --- a/src/components/admin/club-info/ClubInfoContactSection.tsx +++ b/src/components/admin/club-info/ClubInfoContactSection.tsx @@ -32,7 +32,7 @@ function ClubInfoContactSection({ title="연락처" titleGapClassName="mt-[58px]" contentClassName="gap-0" - className="pb-[70px]" + className="pb-[40px]" >
diff --git a/src/components/admin/club-info/ClubInfoPageContent.tsx b/src/components/admin/club-info/ClubInfoPageContent.tsx index 1270ff5f..8a1268d0 100644 --- a/src/components/admin/club-info/ClubInfoPageContent.tsx +++ b/src/components/admin/club-info/ClubInfoPageContent.tsx @@ -129,7 +129,7 @@ function ClubInfoPageContent({ schoolNames }: ClubInfoPageContentProps) { ); return ( -
+
{isEditMode && ( - {label} +
+ {label} {children} {error ? ( {error} diff --git a/src/components/attendance/AttendanceHistoryContent.tsx b/src/components/attendance/AttendanceHistoryContent.tsx index cd69256d..e720797f 100644 --- a/src/components/attendance/AttendanceHistoryContent.tsx +++ b/src/components/attendance/AttendanceHistoryContent.tsx @@ -81,7 +81,7 @@ function AttendanceHistoryContent({ summary, errorMessage }: AttendanceHistoryCo
- +
diff --git a/src/components/auth/hub/CreateClubForm.tsx b/src/components/auth/hub/CreateClubForm.tsx index 33698538..adbb7838 100644 --- a/src/components/auth/hub/CreateClubForm.tsx +++ b/src/components/auth/hub/CreateClubForm.tsx @@ -60,6 +60,8 @@ function CreateClubForm({ schoolNames, schoolLoadError = false }: CreateClubForm const contactType = useWatch({ control, name: 'contactType' }); const email = useWatch({ control, name: 'email' }); + const clubName = useWatch({ control, name: 'name' }); + const description = useWatch({ control, name: 'description' }); const hasValidEmail = Boolean(email?.trim()) && !errors.email; const isEmailContactDisabled = !hasValidEmail; @@ -143,19 +145,49 @@ function CreateClubForm({ schoolNames, schoolLoadError = false }: CreateClubForm {/* 동아리 이름 */} - - + + +
+
+ {errors.name?.message ? ( + + {errors.name.message} + + ) : null} +
+ + {(clubName ?? '').length}/30 + +
{/* 동아리 소개 */} - + - 30자 제한 +
+
+ {errors.description?.message ? ( + + {errors.description.message} + + ) : null} +
+ + {(description ?? '').length}/30 + +
{/* 동아리 기수 */} diff --git a/src/components/ui/Input.tsx b/src/components/ui/Input.tsx index b5d69866..45988cb1 100644 --- a/src/components/ui/Input.tsx +++ b/src/components/ui/Input.tsx @@ -19,10 +19,19 @@ interface InputProps extends InputHTMLAttributes { clearable?: boolean; error?: boolean; wrapperClassName?: string; + clearButtonClassName?: string; ref?: React.Ref; } -function Input({ className, clearable, error, wrapperClassName, ref, ...props }: InputProps) { +function Input({ + className, + clearable, + error, + wrapperClassName, + clearButtonClassName, + ref, + ...props +}: InputProps) { const hasTypo = className?.split(' ').some((c) => c.startsWith('typo-')); const typoClass = hasTypo ? undefined : 'typo-body2'; const innerRef = useRef(null); @@ -99,6 +108,7 @@ function Input({ className, clearable, error, wrapperClassName, ref, ...props }: 'flex items-center', 'text-icon-normal', 'cursor-pointer transition-colors', + clearButtonClassName, )} aria-label="입력 내용 지우기" > diff --git a/src/hooks/home/useHomeGuard.ts b/src/hooks/home/useHomeGuard.ts index e2290307..961f89bd 100644 --- a/src/hooks/home/useHomeGuard.ts +++ b/src/hooks/home/useHomeGuard.ts @@ -3,13 +3,12 @@ import { useEffect, useSyncExternalStore } from 'react'; import { useRouter } from 'next/navigation'; import { isAxiosError } from 'axios'; -import { useClubActions, useClubId, useClubName, useClubStore } from '@/stores/useClubStore'; +import { useClubActions, useClubId, useClubStore } from '@/stores/useClubStore'; import { useHomeQuery } from './useHomeQuery'; export function useHomeGuard() { const router = useRouter(); const clubId = useClubId(); - const clubName = useClubName(); const { reset } = useClubActions(); const { error } = useHomeQuery(); @@ -21,11 +20,11 @@ export function useHomeGuard() { useEffect(() => { if (!hydrated) return; - if (!clubId || !clubName) { + if (!clubId) { reset(); router.replace('/hub'); } - }, [hydrated, clubId, clubName, reset, router]); + }, [hydrated, clubId, reset, router]); useEffect(() => { if (isAxiosError(error) && error.response?.status === 404) {