From 2b9a5b0b3862a87222f098d0fe743d13fcdcafac Mon Sep 17 00:00:00 2001 From: JIN921 Date: Tue, 7 Apr 2026 23:00:07 +0900 Subject: [PATCH 01/13] =?UTF-8?q?feat:=20=EC=95=84=EC=9D=B4=EC=BD=98=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 3 +- src/assets/icons/admin/ic_admin_fileout.svg | 4 + src/assets/icons/admin/ic_admin_forum.svg | 3 + src/assets/icons/admin/ic_admin_light.svg | 3 + src/assets/icons/admin/ic_admin_setting.svg | 3 + src/assets/icons/admin/index.ts | 4 + src/assets/icons/index.ts | 2 + src/assets/icons/nav_toggle.svg | 5 + src/components/admin/layout/LNB.tsx | 243 ++++++++++-------- .../admin/layout/ThemeModeSelector.tsx | 79 ++++++ src/proxy.ts | 2 +- 11 files changed, 246 insertions(+), 105 deletions(-) create mode 100644 src/assets/icons/admin/ic_admin_fileout.svg create mode 100644 src/assets/icons/admin/ic_admin_forum.svg create mode 100644 src/assets/icons/admin/ic_admin_light.svg create mode 100644 src/assets/icons/admin/ic_admin_setting.svg create mode 100644 src/assets/icons/nav_toggle.svg create mode 100644 src/components/admin/layout/ThemeModeSelector.tsx diff --git a/.claude/settings.local.json b/.claude/settings.local.json index bb5a248c..b84ef7f9 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -16,7 +16,8 @@ "Bash(ls -la \"D:\\\\project\\\\weeth-client\\\\src\\\\app\\\\\\(private\\)\\\\\\(main\\)\\\\mypage\\\\edit\")", "Bash(find D:projectweeth-clientsrccomponentsui -type f \\\\\\(-name *.tsx -o -name *.ts \\\\\\))", "Bash(find D:/project/weeth-client/src/constants -name *.ts)", - "Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)" + "Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)", + "Bash(find D:/project/weeth-client -type f -name *.css -o -name tailwind.config.* -o -name global.css)" ] } } diff --git a/src/assets/icons/admin/ic_admin_fileout.svg b/src/assets/icons/admin/ic_admin_fileout.svg new file mode 100644 index 00000000..907e2a35 --- /dev/null +++ b/src/assets/icons/admin/ic_admin_fileout.svg @@ -0,0 +1,4 @@ + + + + diff --git a/src/assets/icons/admin/ic_admin_forum.svg b/src/assets/icons/admin/ic_admin_forum.svg new file mode 100644 index 00000000..4f5862f3 --- /dev/null +++ b/src/assets/icons/admin/ic_admin_forum.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/admin/ic_admin_light.svg b/src/assets/icons/admin/ic_admin_light.svg new file mode 100644 index 00000000..ac4bb88a --- /dev/null +++ b/src/assets/icons/admin/ic_admin_light.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/admin/ic_admin_setting.svg b/src/assets/icons/admin/ic_admin_setting.svg new file mode 100644 index 00000000..0e89b250 --- /dev/null +++ b/src/assets/icons/admin/ic_admin_setting.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/admin/index.ts b/src/assets/icons/admin/index.ts index e7df19ee..6ebc8eea 100644 --- a/src/assets/icons/admin/index.ts +++ b/src/assets/icons/admin/index.ts @@ -9,3 +9,7 @@ export { default as AdminCheckboxIcon } from './ic_admin_checkbox.svg'; export { default as AdminUncheckboxIcon } from './ic_admin_uncheckbox.svg'; export { default as AdminUserIcon } from './ic_admin_user.svg'; export { default as AdminCloseIcon } from './ic_admin_close.svg'; +export { default as AdminSettinIcon } from './ic_admin_setting.svg'; +export { default as AdminFileoutIcon } from './ic_admin_fileout.svg'; +export { default as AdminLightIcon } from './ic_admin_light.svg'; +export { default as AdminForumIcon } from './ic_admin_forum.svg'; diff --git a/src/assets/icons/index.ts b/src/assets/icons/index.ts index e5df5a6c..0edac0be 100644 --- a/src/assets/icons/index.ts +++ b/src/assets/icons/index.ts @@ -48,3 +48,5 @@ export { default as TooltipIcon } from './tooltip.svg'; export { default as CopyIcon } from './copy.svg'; export { default as BasicAvatarIcon } from './basic_avatar.svg'; export { default as QuestionMarkIcon } from './question_mark.svg'; + +export { default as NavToggleIcon } from './nav_toggle.svg'; diff --git a/src/assets/icons/nav_toggle.svg b/src/assets/icons/nav_toggle.svg new file mode 100644 index 00000000..80e54fef --- /dev/null +++ b/src/assets/icons/nav_toggle.svg @@ -0,0 +1,5 @@ + + + + + diff --git a/src/components/admin/layout/LNB.tsx b/src/components/admin/layout/LNB.tsx index ce247be4..451d6fd7 100644 --- a/src/components/admin/layout/LNB.tsx +++ b/src/components/admin/layout/LNB.tsx @@ -1,136 +1,173 @@ 'use client'; import Link from 'next/link'; -import type { StaticImageData } from 'next/image'; import { usePathname } from 'next/navigation'; - -import logoIcon from '@/assets/icons/logo/logo_initial_Origin.svg'; -import userIcon from '@/assets/icons/admin/ic_admin_user.svg'; -import checkIcon from '@/assets/icons/admin/ic_admin_attendance.svg'; -//import penaltyIcon from '@/assets/icons/admin/ic_admin_penalty.svg'; -// import dueIcon from '@/assets/icons/admin/ic_admin_due.svg'; -import arrowIcon from '@/assets/icons/admin/ic_admin_service_transfer.svg'; -import manualIcon from '@/assets/icons/admin/ic_admin_manual.svg'; +import { + Calendar, + CheckCircle, + CircleUserRound, + ExternalLink, + FileText, + Info, + MessageSquare, + Users, +} from 'lucide-react'; import { cn } from '@/lib/cn'; +import { ThemeModeSelector } from '@/components/admin/layout/ThemeModeSelector'; + +const managementNavItems = [ + { id: 'member', icon: Users, label: '멤버 관리', path: '/admin/member' }, + { id: 'schedule', icon: Calendar, label: '일정 관리', path: '/admin/schedule' }, + { id: 'attendance', icon: CheckCircle, label: '출석 관리', path: '/admin/attendance' }, + { id: 'board', icon: MessageSquare, label: '게시판 관리', path: '/admin/board' }, +]; -const mainNavItems = [ - { id: 'member', icon: userIcon, label: '멤버 관리', path: '/admin/member' }, - { id: 'attendance', icon: checkIcon, label: '출석 관리', path: '/admin/attendance' }, - // { id: 'penalty', icon: penaltyIcon, label: '페널티 관리', path: '/admin/penalty' }, - // { id: 'dues', icon: dueIcon, label: '회비 관리', path: '/admin/dues' }, +const infoNavItems = [ + { id: 'club-info', icon: Info, label: '동아리 정보', path: '/admin/club-info' }, ]; const moveNavItems = [ - { id: 'service', icon: arrowIcon, label: '서비스로 이동', path: 'https://weeth.kr' }, + { id: 'service', icon: ExternalLink, label: 'Weeth로 이동', path: 'https://weeth.kr' }, { id: 'manual', - icon: manualIcon, + icon: FileText, label: '관리자 매뉴얼', path: 'https://weeth-develop-2.s3.ap-northeast-2.amazonaws.com/Weeth_%E1%84%80%E1%85%AA%E1%86%AB%E1%84%85%E1%85%B5%E1%84%8C%E1%85%A1_%E1%84%86%E1%85%A6%E1%84%82%E1%85%B2%E1%84%8B%E1%85%A5%E1%86%AF_v3.pdf', }, ]; -function NavIcon({ src, isActive }: { src: StaticImageData | string; isActive: boolean }) { - const url = typeof src === 'string' ? src : (src as StaticImageData).src; +const navItemClass = + 'typo-sub1 flex h-12 items-center gap-300 px-300 transition-colors text-text-alternative hover:bg-container-neutral-interaction'; + +interface NavSectionProps { + label?: string; + children: React.ReactNode; +} + +function NavSection({ label, children }: NavSectionProps) { return ( - +
+ {label && ( + {label} + )} + {children} +
); } -const navItemClass = - 'typo-sub1 flex h-12 items-center gap-300 px-300 transition-colors text-text-alternative hover:bg-container-neutral-interaction'; +interface InternalNavItemProps { + icon: React.ElementType; + label: string; + path: string; + isActive: boolean; +} + +function InternalNavItem({ icon: Icon, label, path, isActive }: InternalNavItemProps) { + return ( + + + {label} + + ); +} + +interface ExternalNavItemProps { + icon: React.ElementType; + label: string; + path: string; + openInWindow?: boolean; +} + +function ExternalNavItem({ icon: Icon, label, path, openInWindow }: ExternalNavItemProps) { + if (openInWindow) { + return ( + + ); + } + + return ( + + + {label} + + ); +} -export function LNB() { +function LNB() { const pathname = usePathname(); return ( ); } + +export { LNB }; diff --git a/src/components/admin/layout/ThemeModeSelector.tsx b/src/components/admin/layout/ThemeModeSelector.tsx new file mode 100644 index 00000000..56e35a17 --- /dev/null +++ b/src/components/admin/layout/ThemeModeSelector.tsx @@ -0,0 +1,79 @@ +'use client'; + +import { useState } from 'react'; +import { ChevronDown, Moon, Sun, SunMoon } from 'lucide-react'; + +import { + DropdownMenu, + DropdownMenuContent, + DropdownMenuItem, + DropdownMenuTrigger, +} from '@/components/ui'; +import { cn } from '@/lib/cn'; +import { useThemeStore } from '@/stores/theme-store'; + +type ThemeMode = 'auto' | 'light' | 'dark'; + +const THEME_OPTIONS: { value: ThemeMode; label: string; icon: typeof Sun }[] = [ + { value: 'auto', label: '자동', icon: SunMoon }, + { value: 'light', label: '라이트', icon: Sun }, + { value: 'dark', label: '다크', icon: Moon }, +]; + +const TRIGGER_LABELS: Record = { + auto: '자동 모드', + light: '라이트 모드', + dark: '다크 모드', +}; + +function ThemeModeSelector() { + const setDark = useThemeStore((state) => state.setDark); + + const [mode, setMode] = useState(() => { + if (typeof window === 'undefined') return 'light'; + return useThemeStore.getState().isDark ? 'dark' : 'light'; + }); + + const handleSelect = (value: ThemeMode) => { + setMode(value); + + if (value === 'light') { + setDark(false); + } else if (value === 'dark') { + setDark(true); + } else { + const prefersDark = window.matchMedia('(prefers-color-scheme: dark)').matches; + setDark(prefersDark); + } + }; + + const currentOption = THEME_OPTIONS.find((o) => o.value === mode)!; + const TriggerIcon = currentOption.icon; + + return ( + + + + + + + {THEME_OPTIONS.map(({ value, label }) => ( + handleSelect(value)}> + {label} + + ))} + + + ); +} + +export { ThemeModeSelector }; diff --git a/src/proxy.ts b/src/proxy.ts index 52079d84..337e66ea 100644 --- a/src/proxy.ts +++ b/src/proxy.ts @@ -4,7 +4,7 @@ import { ACCESS_TOKEN_KEY } from '@/lib/apis/cookies'; const PUBLIC_PATHS = ['/', '/login', '/terms', '/landing']; // TODO: 런칭 후 PRE_LAUNCH 플래그 및 관련 분기 제거 -const PRE_LAUNCH = true; +const PRE_LAUNCH = false; export function proxy(request: NextRequest) { const { pathname } = request.nextUrl; From 6abbc54c2c6d9976f0904a842eefe79285183e5a Mon Sep 17 00:00:00 2001 From: JIN921 Date: Tue, 7 Apr 2026 23:08:25 +0900 Subject: [PATCH 02/13] =?UTF-8?q?fix:=20=ED=94=BC=EA=B7=B8=EB=A7=88=20?= =?UTF-8?q?=EC=95=84=EC=9D=B4=EC=BD=98=EC=9C=BC=EB=A1=9C=20=EB=B3=80?= =?UTF-8?q?=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/assets/icons/admin/ic_admin_calendar.svg | 3 ++ src/assets/icons/admin/index.ts | 3 +- src/components/admin/layout/LNB.tsx | 39 +++++++++----------- 3 files changed, 23 insertions(+), 22 deletions(-) create mode 100644 src/assets/icons/admin/ic_admin_calendar.svg diff --git a/src/assets/icons/admin/ic_admin_calendar.svg b/src/assets/icons/admin/ic_admin_calendar.svg new file mode 100644 index 00000000..4962aac5 --- /dev/null +++ b/src/assets/icons/admin/ic_admin_calendar.svg @@ -0,0 +1,3 @@ + + + diff --git a/src/assets/icons/admin/index.ts b/src/assets/icons/admin/index.ts index 6ebc8eea..9a802e24 100644 --- a/src/assets/icons/admin/index.ts +++ b/src/assets/icons/admin/index.ts @@ -9,7 +9,8 @@ export { default as AdminCheckboxIcon } from './ic_admin_checkbox.svg'; export { default as AdminUncheckboxIcon } from './ic_admin_uncheckbox.svg'; export { default as AdminUserIcon } from './ic_admin_user.svg'; export { default as AdminCloseIcon } from './ic_admin_close.svg'; -export { default as AdminSettinIcon } from './ic_admin_setting.svg'; +export { default as AdminSettingIcon } from './ic_admin_setting.svg'; export { default as AdminFileoutIcon } from './ic_admin_fileout.svg'; export { default as AdminLightIcon } from './ic_admin_light.svg'; export { default as AdminForumIcon } from './ic_admin_forum.svg'; +export { default as AdminCalendarIcon } from './ic_admin_calendar.svg'; diff --git a/src/components/admin/layout/LNB.tsx b/src/components/admin/layout/LNB.tsx index 451d6fd7..2bc49b4f 100644 --- a/src/components/admin/layout/LNB.tsx +++ b/src/components/admin/layout/LNB.tsx @@ -3,35 +3,32 @@ import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { - Calendar, - CheckCircle, - CircleUserRound, - ExternalLink, - FileText, - Info, - MessageSquare, - Users, -} from 'lucide-react'; + AdminForumIcon, + AdminCalendarIcon, + AdminSettingIcon, + AdminFileoutIcon, +} from '@/assets/icons/admin'; +import { CheckRoundIcon, ExitToAppIcon, NavToggleIcon, PeopleIcon } from '@/assets/icons'; import { cn } from '@/lib/cn'; import { ThemeModeSelector } from '@/components/admin/layout/ThemeModeSelector'; const managementNavItems = [ - { id: 'member', icon: Users, label: '멤버 관리', path: '/admin/member' }, - { id: 'schedule', icon: Calendar, label: '일정 관리', path: '/admin/schedule' }, - { id: 'attendance', icon: CheckCircle, label: '출석 관리', path: '/admin/attendance' }, - { id: 'board', icon: MessageSquare, label: '게시판 관리', path: '/admin/board' }, + { id: 'member', icon: PeopleIcon, label: '멤버 관리', path: '/admin/member' }, + { id: 'schedule', icon: AdminCalendarIcon, label: '일정 관리', path: '/admin/schedule' }, + { id: 'attendance', icon: CheckRoundIcon, label: '출석 관리', path: '/admin/attendance' }, + { id: 'board', icon: AdminForumIcon, label: '게시판 관리', path: '/admin/board' }, ]; const infoNavItems = [ - { id: 'club-info', icon: Info, label: '동아리 정보', path: '/admin/club-info' }, + { id: 'club-info', icon: AdminSettingIcon, label: '동아리 정보', path: '/admin/club-info' }, ]; const moveNavItems = [ - { id: 'service', icon: ExternalLink, label: 'Weeth로 이동', path: 'https://weeth.kr' }, + { id: 'service', icon: ExitToAppIcon, label: 'Weeth로 이동', path: 'https://weeth.kr' }, { id: 'manual', - icon: FileText, + icon: AdminFileoutIcon, label: '관리자 매뉴얼', path: 'https://weeth-develop-2.s3.ap-northeast-2.amazonaws.com/Weeth_%E1%84%80%E1%85%AA%E1%86%AB%E1%84%85%E1%85%B5%E1%84%8C%E1%85%A1_%E1%84%86%E1%85%A6%E1%84%82%E1%85%B2%E1%84%8B%E1%85%A5%E1%86%AF_v3.pdf', }, @@ -69,7 +66,9 @@ function InternalNavItem({ icon: Icon, label, path, isActive }: InternalNavItemP href={path} className={cn(navItemClass, isActive && 'bg-container-neutral-interaction text-text-strong')} > - + {label} ); @@ -110,7 +109,7 @@ function LNB() { From 52794ecb5be8bdec9d7fe19dbe1e855850945eab Mon Sep 17 00:00:00 2001 From: JIN921 Date: Tue, 7 Apr 2026 23:20:42 +0900 Subject: [PATCH 03/13] =?UTF-8?q?fix:=20=EC=95=84=EC=9D=B4=EC=BD=98=20?= =?UTF-8?q?=EC=BB=AC=EB=9F=AC=20=EB=B3=80=EA=B2=BD=20=EB=90=98=EB=8F=84?= =?UTF-8?q?=EB=A1=9D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../icons/admin/ic_admin_attendance.svg | 6 ++-- src/assets/icons/admin/ic_admin_calendar.svg | 2 +- src/assets/icons/admin/ic_admin_due.svg | 4 +-- src/assets/icons/admin/ic_admin_fileout.svg | 4 +-- src/assets/icons/admin/ic_admin_forum.svg | 2 +- src/assets/icons/admin/ic_admin_light.svg | 2 +- src/assets/icons/admin/ic_admin_manual.svg | 6 ++-- src/assets/icons/admin/ic_admin_penalty.svg | 4 +-- .../icons/admin/ic_admin_service_transfer.svg | 4 +-- src/assets/icons/admin/ic_admin_setting.svg | 2 +- src/assets/icons/admin/ic_admin_user.svg | 4 +-- src/assets/icons/nav_toggle.svg | 6 ++-- src/components/admin/layout/LNB.tsx | 32 +++++++++---------- .../admin/layout/ThemeModeSelector.tsx | 2 +- 14 files changed, 39 insertions(+), 41 deletions(-) diff --git a/src/assets/icons/admin/ic_admin_attendance.svg b/src/assets/icons/admin/ic_admin_attendance.svg index 837e944e..87f99d3b 100644 --- a/src/assets/icons/admin/ic_admin_attendance.svg +++ b/src/assets/icons/admin/ic_admin_attendance.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/src/assets/icons/admin/ic_admin_calendar.svg b/src/assets/icons/admin/ic_admin_calendar.svg index 4962aac5..6af182a3 100644 --- a/src/assets/icons/admin/ic_admin_calendar.svg +++ b/src/assets/icons/admin/ic_admin_calendar.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/icons/admin/ic_admin_due.svg b/src/assets/icons/admin/ic_admin_due.svg index 82bf7460..40ac4d2f 100644 --- a/src/assets/icons/admin/ic_admin_due.svg +++ b/src/assets/icons/admin/ic_admin_due.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/assets/icons/admin/ic_admin_fileout.svg b/src/assets/icons/admin/ic_admin_fileout.svg index 907e2a35..e0ba79bd 100644 --- a/src/assets/icons/admin/ic_admin_fileout.svg +++ b/src/assets/icons/admin/ic_admin_fileout.svg @@ -1,4 +1,4 @@ - - + + diff --git a/src/assets/icons/admin/ic_admin_forum.svg b/src/assets/icons/admin/ic_admin_forum.svg index 4f5862f3..69078333 100644 --- a/src/assets/icons/admin/ic_admin_forum.svg +++ b/src/assets/icons/admin/ic_admin_forum.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/icons/admin/ic_admin_light.svg b/src/assets/icons/admin/ic_admin_light.svg index ac4bb88a..0a083e46 100644 --- a/src/assets/icons/admin/ic_admin_light.svg +++ b/src/assets/icons/admin/ic_admin_light.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/icons/admin/ic_admin_manual.svg b/src/assets/icons/admin/ic_admin_manual.svg index a02c3432..5e2fd0be 100644 --- a/src/assets/icons/admin/ic_admin_manual.svg +++ b/src/assets/icons/admin/ic_admin_manual.svg @@ -1,4 +1,4 @@ - - - + + + diff --git a/src/assets/icons/admin/ic_admin_penalty.svg b/src/assets/icons/admin/ic_admin_penalty.svg index 265f55f3..69ccb9e5 100644 --- a/src/assets/icons/admin/ic_admin_penalty.svg +++ b/src/assets/icons/admin/ic_admin_penalty.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/assets/icons/admin/ic_admin_service_transfer.svg b/src/assets/icons/admin/ic_admin_service_transfer.svg index 137d4a4f..da7f8b42 100644 --- a/src/assets/icons/admin/ic_admin_service_transfer.svg +++ b/src/assets/icons/admin/ic_admin_service_transfer.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/assets/icons/admin/ic_admin_setting.svg b/src/assets/icons/admin/ic_admin_setting.svg index 0e89b250..09cd128d 100644 --- a/src/assets/icons/admin/ic_admin_setting.svg +++ b/src/assets/icons/admin/ic_admin_setting.svg @@ -1,3 +1,3 @@ - + diff --git a/src/assets/icons/admin/ic_admin_user.svg b/src/assets/icons/admin/ic_admin_user.svg index 7f44dd9a..2db41f01 100644 --- a/src/assets/icons/admin/ic_admin_user.svg +++ b/src/assets/icons/admin/ic_admin_user.svg @@ -1,3 +1,3 @@ - - + + diff --git a/src/assets/icons/nav_toggle.svg b/src/assets/icons/nav_toggle.svg index 80e54fef..56808d15 100644 --- a/src/assets/icons/nav_toggle.svg +++ b/src/assets/icons/nav_toggle.svg @@ -1,5 +1,5 @@ - - - + + + diff --git a/src/components/admin/layout/LNB.tsx b/src/components/admin/layout/LNB.tsx index 2bc49b4f..02dbb411 100644 --- a/src/components/admin/layout/LNB.tsx +++ b/src/components/admin/layout/LNB.tsx @@ -8,8 +8,9 @@ import { AdminSettingIcon, AdminFileoutIcon, } from '@/assets/icons/admin'; -import { CheckRoundIcon, ExitToAppIcon, NavToggleIcon, PeopleIcon } from '@/assets/icons'; +import { CheckRoundIcon, ExitIcon, NavToggleIcon, PeopleIcon } from '@/assets/icons'; +import { Avatar, Icon } from '@/components/ui'; import { cn } from '@/lib/cn'; import { ThemeModeSelector } from '@/components/admin/layout/ThemeModeSelector'; @@ -25,7 +26,7 @@ const infoNavItems = [ ]; const moveNavItems = [ - { id: 'service', icon: ExitToAppIcon, label: 'Weeth로 이동', path: 'https://weeth.kr' }, + { id: 'service', icon: ExitIcon, label: 'Weeth로 이동', path: 'https://weeth.kr' }, { id: 'manual', icon: AdminFileoutIcon, @@ -54,20 +55,22 @@ function NavSection({ label, children }: NavSectionProps) { } interface InternalNavItemProps { - icon: React.ElementType; + icon: typeof PeopleIcon; label: string; path: string; isActive: boolean; } -function InternalNavItem({ icon: Icon, label, path, isActive }: InternalNavItemProps) { +function InternalNavItem({ icon, label, path, isActive }: InternalNavItemProps) { return ( {label} @@ -75,20 +78,20 @@ function InternalNavItem({ icon: Icon, label, path, isActive }: InternalNavItemP } interface ExternalNavItemProps { - icon: React.ElementType; + icon: typeof PeopleIcon; label: string; path: string; openInWindow?: boolean; } -function ExternalNavItem({ icon: Icon, label, path, openInWindow }: ExternalNavItemProps) { +function ExternalNavItem({ icon, label, path, openInWindow }: ExternalNavItemProps) { if (openInWindow) { return ( ); @@ -96,7 +99,7 @@ function ExternalNavItem({ icon: Icon, label, path, openInWindow }: ExternalNavI return ( - + {label} ); @@ -109,13 +112,13 @@ function LNB() {
- + Weeth admin
{/* 동아리 정보 */}
- 가입대학교 + 가천대 검도부
@@ -156,13 +159,8 @@ function LNB() { openInWindow={id === 'manual'} /> ))} - - - {/* 모드 */} -
- 모드 -
+ ); } diff --git a/src/components/admin/layout/ThemeModeSelector.tsx b/src/components/admin/layout/ThemeModeSelector.tsx index 56e35a17..7f4f0a80 100644 --- a/src/components/admin/layout/ThemeModeSelector.tsx +++ b/src/components/admin/layout/ThemeModeSelector.tsx @@ -55,7 +55,7 @@ function ThemeModeSelector() { - + {THEME_OPTIONS.map(({ value, label }) => ( handleSelect(value)}> {label} diff --git a/src/hooks/queries/admin/useAdminClubQuery.ts b/src/hooks/queries/admin/useAdminClubQuery.ts new file mode 100644 index 00000000..e104e95d --- /dev/null +++ b/src/hooks/queries/admin/useAdminClubQuery.ts @@ -0,0 +1,15 @@ +import { useQuery } from '@tanstack/react-query'; +import { adminClubApi } from '@/lib/apis/adminClub'; +import { useClubId } from '@/stores'; + +export function useAdminClubQuery() { + const clubId = useClubId(); + + return useQuery({ + queryKey: ['admin', 'club', clubId], + queryFn: () => adminClubApi.getDetail(clubId!).then((res) => res.data.data), + enabled: !!clubId, + staleTime: 30 * 60 * 1000, + gcTime: 60 * 60 * 1000, + }); +} diff --git a/src/lib/apis/adminClub.ts b/src/lib/apis/adminClub.ts new file mode 100644 index 00000000..793eebf9 --- /dev/null +++ b/src/lib/apis/adminClub.ts @@ -0,0 +1,8 @@ +import { apiClient } from '@/lib/apis/client'; +import type { Club } from '@/types/club'; +import type { ApiResponse } from '@/types/common'; + +export const adminClubApi = { + getDetail: (clubId: string) => + apiClient.get>(`/admin/clubs/${clubId}`), +}; diff --git a/src/types/club.ts b/src/types/club.ts index 2794b705..8e1c3aad 100644 --- a/src/types/club.ts +++ b/src/types/club.ts @@ -1,8 +1,12 @@ -// club 관련 타입 정의 - export interface Club { id: string; name: string; + code: string; + schoolName: string; description: string; - logoUrl?: string; + contactEmail: string; + contactPhoneNumber: string; + primaryContact: 'PHONE' | 'EMAIL'; + profileImageUrl: string; + backgroundImageUrl: string; } From b4ea5da34bf333a662172fa760097c45104be655 Mon Sep 17 00:00:00 2001 From: JIN921 Date: Wed, 8 Apr 2026 23:25:19 +0900 Subject: [PATCH 05/13] =?UTF-8?q?style:=20=EB=8F=99=EC=95=84=EB=A6=AC=20?= =?UTF-8?q?=EC=A0=95=EB=B3=B4=20=EC=98=81=EC=97=AD=20=EB=94=94=EC=9E=90?= =?UTF-8?q?=EC=9D=B8=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/admin/layout/LNB.tsx | 6 +++--- src/components/ui/avatar.tsx | 18 +++++++++++++++--- 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/src/components/admin/layout/LNB.tsx b/src/components/admin/layout/LNB.tsx index 5bdf87e1..27e52177 100644 --- a/src/components/admin/layout/LNB.tsx +++ b/src/components/admin/layout/LNB.tsx @@ -119,14 +119,14 @@ function LNB() { {/* 동아리 정보 */} -
- +
+ {club?.profileImageUrl && } {club?.name?.charAt(0)}
{club?.schoolName} - {club?.name} + {club?.name}
diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx index e27e6ea2..fb564fbe 100644 --- a/src/components/ui/avatar.tsx +++ b/src/components/ui/avatar.tsx @@ -14,25 +14,33 @@ const avatarVariants = cva('group/avatar relative flex shrink-0 overflow-hidden size: { 128: 'size-32', 64: 'size-16', + 40: 'size-10', 24: 'size-6', }, + color: { + default: '', + primary: '', + secondary: '', + }, }, defaultVariants: { type: 'round', size: 64, + color: 'default', }, }); interface AvatarProps extends React.ComponentProps, VariantProps {} -function Avatar({ className, type, size, ...props }: AvatarProps) { +function Avatar({ className, type, size, color, ...props }: AvatarProps) { return ( ); @@ -56,10 +64,14 @@ function AvatarFallback({ Date: Wed, 8 Apr 2026 23:51:46 +0900 Subject: [PATCH 06/13] =?UTF-8?q?fix:=20=EA=B5=AC=EB=B6=84=EC=82=B0=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/components/admin/layout/LNB.tsx | 245 ++++++++++++------ .../admin/layout/ThemeModeSelector.tsx | 49 +++- 2 files changed, 201 insertions(+), 93 deletions(-) diff --git a/src/components/admin/layout/LNB.tsx b/src/components/admin/layout/LNB.tsx index 27e52177..6254b5eb 100644 --- a/src/components/admin/layout/LNB.tsx +++ b/src/components/admin/layout/LNB.tsx @@ -1,5 +1,6 @@ 'use client'; +import { useState } from 'react'; import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { @@ -10,7 +11,16 @@ import { } from '@/assets/icons/admin'; import { CheckRoundIcon, ExitIcon, NavToggleIcon, PeopleIcon } from '@/assets/icons'; -import { Avatar, AvatarFallback, AvatarImage, Icon } from '@/components/ui'; +import { + Avatar, + AvatarFallback, + AvatarImage, + Icon, + Tooltip, + TooltipContent, + TooltipProvider, + TooltipTrigger, +} from '@/components/ui'; import { cn } from '@/lib/cn'; import { ThemeModeSelector } from '@/components/admin/layout/ThemeModeSelector'; import { useAdminClubQuery } from '@/hooks/queries/admin/useAdminClubQuery'; @@ -36,18 +46,16 @@ const moveNavItems = [ }, ]; -const navItemClass = - 'typo-sub1 flex h-12 items-center gap-300 px-300 transition-colors text-text-alternative hover:bg-container-neutral-interaction'; - interface NavSectionProps { label?: string; + collapsed?: boolean; children: React.ReactNode; } -function NavSection({ label, children }: NavSectionProps) { +function NavSection({ label, collapsed, children }: NavSectionProps) { return (
- {label && ( + {label && !collapsed && ( {label} )} {children} @@ -60,22 +68,38 @@ interface InternalNavItemProps { label: string; path: string; isActive: boolean; + collapsed?: boolean; } -function InternalNavItem({ icon, label, path, isActive }: InternalNavItemProps) { - return ( +function InternalNavItem({ icon, label, path, isActive, collapsed }: InternalNavItemProps) { + const content = ( - {label} + {!collapsed && {label}} ); + + if (collapsed) { + return ( + + {content} + {label} + + ); + } + + return content; } interface ExternalNavItemProps { @@ -83,93 +107,154 @@ interface ExternalNavItemProps { label: string; path: string; openInWindow?: boolean; + collapsed?: boolean; } -function ExternalNavItem({ icon, label, path, openInWindow }: ExternalNavItemProps) { +function ExternalNavItem({ icon, label, path, openInWindow, collapsed }: ExternalNavItemProps) { + const iconEl = ; + + const cls = cn( + 'flex h-12 items-center transition-colors text-text-alternative hover:bg-container-neutral-interaction', + collapsed ? 'justify-center px-200' : 'gap-300 px-300', + ); + + let el: React.ReactNode; + if (openInWindow) { - return ( + el = ( ); + } else { + el = ( + + {iconEl} + {!collapsed && {label}} + + ); } - return ( - - - {label} - - ); + if (collapsed) { + return ( + + {el} + {label} + + ); + } + + return el; } function LNB() { const pathname = usePathname(); const { data: club } = useAdminClubQuery(); + const [collapsed, setCollapsed] = useState(false); return ( - + + {/* 관리 메뉴 */} + + {managementNavItems.map(({ id, icon, label, path }) => ( + + ))} + + + {collapsed &&
} + + {/* 동아리 정보 메뉴 */} + + {infoNavItems.map(({ id, icon, label, path }) => ( + + ))} + + + {collapsed &&
} + + {/* 이동 */} + + {moveNavItems.map(({ id, icon, label, path }) => ( + + ))} + + {collapsed &&
} + + {/* 라이트 모드 */} + + + + ); } diff --git a/src/components/admin/layout/ThemeModeSelector.tsx b/src/components/admin/layout/ThemeModeSelector.tsx index 818887fa..846b859f 100644 --- a/src/components/admin/layout/ThemeModeSelector.tsx +++ b/src/components/admin/layout/ThemeModeSelector.tsx @@ -8,6 +8,9 @@ import { DropdownMenuContent, DropdownMenuItem, DropdownMenuTrigger, + Tooltip, + TooltipContent, + TooltipTrigger, } from '@/components/ui'; import { cn } from '@/lib/cn'; import { useThemeStore } from '@/stores/theme-store'; @@ -26,7 +29,11 @@ const TRIGGER_LABELS: Record = { dark: '다크 모드', }; -function ThemeModeSelector() { +interface ThemeModeSelectorProps { + collapsed?: boolean; +} + +function ThemeModeSelector({ collapsed }: ThemeModeSelectorProps) { const setDark = useThemeStore((state) => state.setDark); const [mode, setMode] = useState(() => { @@ -50,20 +57,36 @@ function ThemeModeSelector() { const currentOption = THEME_OPTIONS.find((o) => o.value === mode)!; const TriggerIcon = currentOption.icon; + const trigger = ( + + + + ); + return ( - - - + {collapsed ? ( + + {trigger} + {TRIGGER_LABELS[mode]} + + ) : ( + trigger + )} {THEME_OPTIONS.map(({ value, label }) => ( From 0dafded6a941dfd585f21321ec2c64c2a894e673 Mon Sep 17 00:00:00 2001 From: JIN921 Date: Thu, 9 Apr 2026 00:03:54 +0900 Subject: [PATCH 07/13] =?UTF-8?q?fix:=20=EC=BB=B4=ED=8F=AC=EB=84=8C?= =?UTF-8?q?=ED=8A=B8=20=EB=B6=84=EB=A6=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/layout/CollapsedDivider.tsx | 11 + src/components/admin/layout/LNB.tsx | 193 ++---------------- src/components/admin/layout/LNBClubInfo.tsx | 35 ++++ src/components/admin/layout/LNBHeader.tsx | 35 ++++ src/components/admin/layout/NavItem.tsx | 85 ++++++++ src/components/admin/layout/NavSection.tsx | 18 ++ 6 files changed, 205 insertions(+), 172 deletions(-) create mode 100644 src/components/admin/layout/CollapsedDivider.tsx create mode 100644 src/components/admin/layout/LNBClubInfo.tsx create mode 100644 src/components/admin/layout/LNBHeader.tsx create mode 100644 src/components/admin/layout/NavItem.tsx create mode 100644 src/components/admin/layout/NavSection.tsx diff --git a/src/components/admin/layout/CollapsedDivider.tsx b/src/components/admin/layout/CollapsedDivider.tsx new file mode 100644 index 00000000..56d6661b --- /dev/null +++ b/src/components/admin/layout/CollapsedDivider.tsx @@ -0,0 +1,11 @@ +interface CollapsedDividerProps { + collapsed?: boolean; +} + +function CollapsedDivider({ collapsed }: CollapsedDividerProps) { + if (!collapsed) return null; + + return
; +} + +export { CollapsedDivider, type CollapsedDividerProps }; diff --git a/src/components/admin/layout/LNB.tsx b/src/components/admin/layout/LNB.tsx index 6254b5eb..5882d9e4 100644 --- a/src/components/admin/layout/LNB.tsx +++ b/src/components/admin/layout/LNB.tsx @@ -1,7 +1,6 @@ 'use client'; import { useState } from 'react'; -import Link from 'next/link'; import { usePathname } from 'next/navigation'; import { AdminForumIcon, @@ -9,21 +8,16 @@ import { AdminSettingIcon, AdminFileoutIcon, } from '@/assets/icons/admin'; -import { CheckRoundIcon, ExitIcon, NavToggleIcon, PeopleIcon } from '@/assets/icons'; +import { CheckRoundIcon, ExitIcon, PeopleIcon } from '@/assets/icons'; -import { - Avatar, - AvatarFallback, - AvatarImage, - Icon, - Tooltip, - TooltipContent, - TooltipProvider, - TooltipTrigger, -} from '@/components/ui'; +import { TooltipProvider } from '@/components/ui'; import { cn } from '@/lib/cn'; +import { LNBHeader } from '@/components/admin/layout/LNBHeader'; +import { LNBClubInfo } from '@/components/admin/layout/LNBClubInfo'; +import { NavSection } from '@/components/admin/layout/NavSection'; +import { NavItem } from '@/components/admin/layout/NavItem'; +import { CollapsedDivider } from '@/components/admin/layout/CollapsedDivider'; import { ThemeModeSelector } from '@/components/admin/layout/ThemeModeSelector'; -import { useAdminClubQuery } from '@/hooks/queries/admin/useAdminClubQuery'; const managementNavItems = [ { id: 'member', icon: PeopleIcon, label: '멤버 관리', path: '/admin/member' }, @@ -37,123 +31,19 @@ const infoNavItems = [ ]; const moveNavItems = [ - { id: 'service', icon: ExitIcon, label: 'Weeth로 이동', path: 'https://weeth.kr' }, + { id: 'service', icon: ExitIcon, label: 'Weeth로 이동', path: 'https://weeth.kr', external: true }, { id: 'manual', icon: AdminFileoutIcon, label: '관리자 매뉴얼', path: 'https://weeth-develop-2.s3.ap-northeast-2.amazonaws.com/Weeth_%E1%84%80%E1%85%AA%E1%86%AB%E1%84%85%E1%85%B5%E1%84%8C%E1%85%A1_%E1%84%86%E1%85%A6%E1%84%82%E1%85%B2%E1%84%8B%E1%85%A5%E1%86%AF_v3.pdf', + external: true, + openInWindow: true, }, ]; -interface NavSectionProps { - label?: string; - collapsed?: boolean; - children: React.ReactNode; -} - -function NavSection({ label, collapsed, children }: NavSectionProps) { - return ( -
- {label && !collapsed && ( - {label} - )} - {children} -
- ); -} - -interface InternalNavItemProps { - icon: typeof PeopleIcon; - label: string; - path: string; - isActive: boolean; - collapsed?: boolean; -} - -function InternalNavItem({ icon, label, path, isActive, collapsed }: InternalNavItemProps) { - const content = ( - - - {!collapsed && {label}} - - ); - - if (collapsed) { - return ( - - {content} - {label} - - ); - } - - return content; -} - -interface ExternalNavItemProps { - icon: typeof PeopleIcon; - label: string; - path: string; - openInWindow?: boolean; - collapsed?: boolean; -} - -function ExternalNavItem({ icon, label, path, openInWindow, collapsed }: ExternalNavItemProps) { - const iconEl = ; - - const cls = cn( - 'flex h-12 items-center transition-colors text-text-alternative hover:bg-container-neutral-interaction', - collapsed ? 'justify-center px-200' : 'gap-300 px-300', - ); - - let el: React.ReactNode; - - if (openInWindow) { - el = ( - - ); - } else { - el = ( - - {iconEl} - {!collapsed && {label}} - - ); - } - - if (collapsed) { - return ( - - {el} - {label} - - ); - } - - return el; -} - function LNB() { const pathname = usePathname(); - const { data: club } = useAdminClubQuery(); const [collapsed, setCollapsed] = useState(false); return ( @@ -164,49 +54,12 @@ function LNB() { collapsed ? 'w-14' : 'w-56', )} > - {/* 헤더 */} -
- - - - - - {collapsed ? '사이드바 열기' : '사이드바 닫기'} - - - {!collapsed && Weeth admin} -
+ setCollapsed((prev) => !prev)} /> + - {/* 동아리 정보 */} -
- - {club?.profileImageUrl && } - {club?.name?.charAt(0)} - - {!collapsed && ( -
- {club?.schoolName} - {club?.name} -
- )} -
- - {/* 관리 메뉴 */} {managementNavItems.map(({ id, icon, label, path }) => ( - - {collapsed &&
} + - {/* 동아리 정보 메뉴 */} {infoNavItems.map(({ id, icon, label, path }) => ( - - {collapsed &&
} + - {/* 이동 */} - {moveNavItems.map(({ id, icon, label, path }) => ( - ( + ))} - - {collapsed &&
} - - {/* 라이트 모드 */} + diff --git a/src/components/admin/layout/LNBClubInfo.tsx b/src/components/admin/layout/LNBClubInfo.tsx new file mode 100644 index 00000000..3bc78a51 --- /dev/null +++ b/src/components/admin/layout/LNBClubInfo.tsx @@ -0,0 +1,35 @@ +'use client'; + +import { Avatar, AvatarFallback, AvatarImage } from '@/components/ui'; +import { cn } from '@/lib/cn'; +import { useAdminClubQuery } from '@/hooks/queries/admin/useAdminClubQuery'; + +interface LNBClubInfoProps { + collapsed: boolean; +} + +function LNBClubInfo({ collapsed }: LNBClubInfoProps) { + const { data: club } = useAdminClubQuery(); + + return ( +
+ + {club?.profileImageUrl && } + {club?.name?.charAt(0)} + + {!collapsed && ( +
+ {club?.schoolName} + {club?.name} +
+ )} +
+ ); +} + +export { LNBClubInfo, type LNBClubInfoProps }; diff --git a/src/components/admin/layout/LNBHeader.tsx b/src/components/admin/layout/LNBHeader.tsx new file mode 100644 index 00000000..6ee28f54 --- /dev/null +++ b/src/components/admin/layout/LNBHeader.tsx @@ -0,0 +1,35 @@ +'use client'; + +import { Icon, Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui'; +import { NavToggleIcon } from '@/assets/icons'; +import { cn } from '@/lib/cn'; + +interface LNBHeaderProps { + collapsed: boolean; + onToggle: () => void; +} + +function LNBHeader({ collapsed, onToggle }: LNBHeaderProps) { + return ( +
+ + + + + + {collapsed ? '사이드바 열기' : '사이드바 닫기'} + + + {!collapsed && Weeth admin} +
+ ); +} + +export { LNBHeader, type LNBHeaderProps }; diff --git a/src/components/admin/layout/NavItem.tsx b/src/components/admin/layout/NavItem.tsx new file mode 100644 index 00000000..327bc1cc --- /dev/null +++ b/src/components/admin/layout/NavItem.tsx @@ -0,0 +1,85 @@ +'use client'; + +import Link from 'next/link'; + +import { Icon, Tooltip, TooltipContent, TooltipTrigger } from '@/components/ui'; +import { cn } from '@/lib/cn'; +import type { PeopleIcon } from '@/assets/icons'; + +const baseClass = + 'flex h-12 items-center transition-colors text-text-alternative hover:bg-container-neutral-interaction'; + +interface NavItemProps { + icon: typeof PeopleIcon; + label: string; + path: string; + isActive?: boolean; + collapsed?: boolean; + external?: boolean; + openInWindow?: boolean; +} + +function NavItem({ + icon, + label, + path, + isActive = false, + collapsed = false, + external = false, + openInWindow = false, +}: NavItemProps) { + const iconEl = ( + + ); + + const cls = cn( + baseClass, + collapsed ? 'justify-center px-200' : 'gap-300 px-300', + isActive && 'bg-container-neutral-interaction text-text-strong', + ); + + let el: React.ReactNode; + + if (openInWindow) { + el = ( + + ); + } else if (external) { + el = ( + + {iconEl} + {!collapsed && {label}} + + ); + } else { + el = ( + + {iconEl} + {!collapsed && {label}} + + ); + } + + if (collapsed) { + return ( + + {el} + {label} + + ); + } + + return el; +} + +export { NavItem, type NavItemProps }; diff --git a/src/components/admin/layout/NavSection.tsx b/src/components/admin/layout/NavSection.tsx new file mode 100644 index 00000000..22f024ab --- /dev/null +++ b/src/components/admin/layout/NavSection.tsx @@ -0,0 +1,18 @@ +interface NavSectionProps { + label?: string; + collapsed?: boolean; + children: React.ReactNode; +} + +function NavSection({ label, collapsed, children }: NavSectionProps) { + return ( +
+ {label && !collapsed && ( + {label} + )} + {children} +
+ ); +} + +export { NavSection, type NavSectionProps }; From 3b7ee6f1887c8e292a02a77ec738b7c249a42c6c Mon Sep 17 00:00:00 2001 From: JIN921 Date: Thu, 9 Apr 2026 23:38:04 +0900 Subject: [PATCH 08/13] =?UTF-8?q?fix:=20re-export=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/settings.local.json | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index b84ef7f9..bb5a248c 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -16,8 +16,7 @@ "Bash(ls -la \"D:\\\\project\\\\weeth-client\\\\src\\\\app\\\\\\(private\\)\\\\\\(main\\)\\\\mypage\\\\edit\")", "Bash(find D:projectweeth-clientsrccomponentsui -type f \\\\\\(-name *.tsx -o -name *.ts \\\\\\))", "Bash(find D:/project/weeth-client/src/constants -name *.ts)", - "Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)", - "Bash(find D:/project/weeth-client -type f -name *.css -o -name tailwind.config.* -o -name global.css)" + "Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)" ] } } From 188feece0ecbd4f6bd946f5f80c188614e5584a6 Mon Sep 17 00:00:00 2001 From: JIN921 Date: Thu, 9 Apr 2026 23:41:50 +0900 Subject: [PATCH 09/13] =?UTF-8?q?fix:=20=EB=B6=88=ED=95=84=EC=9A=94?= =?UTF-8?q?=ED=95=9C=20=EC=BD=94=EB=93=9C=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/lib/apis/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib/apis/index.ts b/src/lib/apis/index.ts index 758a720c..1ed82008 100644 --- a/src/lib/apis/index.ts +++ b/src/lib/apis/index.ts @@ -9,3 +9,4 @@ export { fileApi } from './file'; export { homeApi } from './home'; export { attendanceApi } from './attendance'; export { inquiryApi } from './inquiry'; +export { adminClubApi } from './adminClub'; From 272cb7a4f6f2993a7c2bd085ace5a60a3756788f Mon Sep 17 00:00:00 2001 From: JIN921 Date: Fri, 10 Apr 2026 00:11:31 +0900 Subject: [PATCH 10/13] =?UTF-8?q?fix:=20Club=20=ED=83=80=EC=9E=85=20?= =?UTF-8?q?=EB=B3=80=EA=B2=BD=EC=97=90=20=EB=94=B0=EB=A5=B8=20logoUrl=20?= =?UTF-8?q?=E2=86=92=20profileImageUrl=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?avatar=20color=20prop=20=EC=B6=A9=EB=8F=8C=20=ED=95=B4=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - logoUrl을 profileImageUrl로 일괄 변경 - Radix AvatarProps의 color와 cva color variant 충돌 → colorScheme으로 rename Co-Authored-By: Claude Opus 4.6 (1M context) --- src/components/admin/layout/LNBClubInfo.tsx | 2 +- src/components/auth/hub/ClubSearchDropdown.tsx | 4 ++-- src/components/auth/hub/ClubSelectedCard.tsx | 4 ++-- src/components/auth/invite/ClubAccessPage.tsx | 4 ++-- src/components/auth/invite/ClubConfirmCard.tsx | 4 ++-- src/components/ui/avatar.tsx | 10 +++++----- 6 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/admin/layout/LNBClubInfo.tsx b/src/components/admin/layout/LNBClubInfo.tsx index 3bc78a51..aa611e26 100644 --- a/src/components/admin/layout/LNBClubInfo.tsx +++ b/src/components/admin/layout/LNBClubInfo.tsx @@ -18,7 +18,7 @@ function LNBClubInfo({ collapsed }: LNBClubInfoProps) { collapsed ? 'justify-center' : 'flex-col gap-300 px-400', )} > - + {club?.profileImageUrl && } {club?.name?.charAt(0)} diff --git a/src/components/auth/hub/ClubSearchDropdown.tsx b/src/components/auth/hub/ClubSearchDropdown.tsx index a9507c1c..44187896 100644 --- a/src/components/auth/hub/ClubSearchDropdown.tsx +++ b/src/components/auth/hub/ClubSearchDropdown.tsx @@ -30,8 +30,8 @@ function ClubSearchDropdown({ clubs, onSelect, className }: ClubSearchDropdownPr className="border-line bg-container-neutral flex w-full cursor-pointer items-center gap-400 rounded-[10px] border px-200 py-200 transition-colors" > - {club.logoUrl && ( - + {club.profileImageUrl && ( + )} {club.name.charAt(0)} diff --git a/src/components/auth/hub/ClubSelectedCard.tsx b/src/components/auth/hub/ClubSelectedCard.tsx index 3eb42f78..4436cd91 100644 --- a/src/components/auth/hub/ClubSelectedCard.tsx +++ b/src/components/auth/hub/ClubSelectedCard.tsx @@ -16,8 +16,8 @@ function ClubSelectedCard({ club, onRemove }: ClubSelectedCardProps) { type="square" className="border-line h-10 w-10 shrink-0 rounded-lg border" > - {club.logoUrl && ( - + {club.profileImageUrl && ( + )} {club.name.charAt(0)} diff --git a/src/components/auth/invite/ClubAccessPage.tsx b/src/components/auth/invite/ClubAccessPage.tsx index f2729084..56d7d4f4 100644 --- a/src/components/auth/invite/ClubAccessPage.tsx +++ b/src/components/auth/invite/ClubAccessPage.tsx @@ -14,8 +14,8 @@ function ClubAccessPage({ club }: ClubAccessPageProps) {

이 사이트는 동아리 회원만 이용할 수 있어요.

- {club.logoUrl && ( - + {club.profileImageUrl && ( + )} {club.name.charAt(0)} diff --git a/src/components/auth/invite/ClubConfirmCard.tsx b/src/components/auth/invite/ClubConfirmCard.tsx index 81e28f8c..a09ea828 100644 --- a/src/components/auth/invite/ClubConfirmCard.tsx +++ b/src/components/auth/invite/ClubConfirmCard.tsx @@ -14,8 +14,8 @@ function ClubConfirmCard({ club, confirmHref }: ClubConfirmCardProps) {
가입하려는 동아리가 맞나요? - {club.logoUrl && ( - + {club.profileImageUrl && ( + )} {club.name.charAt(0)} diff --git a/src/components/ui/avatar.tsx b/src/components/ui/avatar.tsx index fb564fbe..58a31489 100644 --- a/src/components/ui/avatar.tsx +++ b/src/components/ui/avatar.tsx @@ -17,7 +17,7 @@ const avatarVariants = cva('group/avatar relative flex shrink-0 overflow-hidden 40: 'size-10', 24: 'size-6', }, - color: { + colorScheme: { default: '', primary: '', secondary: '', @@ -26,21 +26,21 @@ const avatarVariants = cva('group/avatar relative flex shrink-0 overflow-hidden defaultVariants: { type: 'round', size: 64, - color: 'default', + colorScheme: 'default', }, }); interface AvatarProps extends React.ComponentProps, VariantProps {} -function Avatar({ className, type, size, color, ...props }: AvatarProps) { +function Avatar({ className, type, size, colorScheme, ...props }: AvatarProps) { return ( ); From bda904cbf0012010a434a2f64e3e16630e1f724b Mon Sep 17 00:00:00 2001 From: JIN921 Date: Fri, 10 Apr 2026 00:11:39 +0900 Subject: [PATCH 11/13] =?UTF-8?q?style:=20Prettier=20=EC=A0=84=EC=B2=B4=20?= =?UTF-8?q?=ED=8F=AC=EB=A7=B7=ED=8C=85=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Opus 4.6 (1M context) --- .claude/settings.local.json | 3 ++- src/components/admin/layout/LNB.tsx | 8 +++++++- src/components/admin/layout/LNBHeader.tsx | 4 +--- src/lib/apis/adminClub.ts | 3 +-- 4 files changed, 11 insertions(+), 7 deletions(-) diff --git a/.claude/settings.local.json b/.claude/settings.local.json index bb5a248c..f7124cb4 100644 --- a/.claude/settings.local.json +++ b/.claude/settings.local.json @@ -16,7 +16,8 @@ "Bash(ls -la \"D:\\\\project\\\\weeth-client\\\\src\\\\app\\\\\\(private\\)\\\\\\(main\\)\\\\mypage\\\\edit\")", "Bash(find D:projectweeth-clientsrccomponentsui -type f \\\\\\(-name *.tsx -o -name *.ts \\\\\\))", "Bash(find D:/project/weeth-client/src/constants -name *.ts)", - "Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)" + "Bash(grep -r \"POSTHOG\\\\|PostHog\" D:projectweeth-client/.env*)", + "Bash(gh run:*)" ] } } diff --git a/src/components/admin/layout/LNB.tsx b/src/components/admin/layout/LNB.tsx index 5882d9e4..7249339b 100644 --- a/src/components/admin/layout/LNB.tsx +++ b/src/components/admin/layout/LNB.tsx @@ -31,7 +31,13 @@ const infoNavItems = [ ]; const moveNavItems = [ - { id: 'service', icon: ExitIcon, label: 'Weeth로 이동', path: 'https://weeth.kr', external: true }, + { + id: 'service', + icon: ExitIcon, + label: 'Weeth로 이동', + path: 'https://weeth.kr', + external: true, + }, { id: 'manual', icon: AdminFileoutIcon, diff --git a/src/components/admin/layout/LNBHeader.tsx b/src/components/admin/layout/LNBHeader.tsx index 6ee28f54..79e27dd5 100644 --- a/src/components/admin/layout/LNBHeader.tsx +++ b/src/components/admin/layout/LNBHeader.tsx @@ -11,9 +11,7 @@ interface LNBHeaderProps { function LNBHeader({ collapsed, onToggle }: LNBHeaderProps) { return ( -
+
); } else if (external) { el = ( {iconEl} - {!collapsed && {label}} + {!collapsed && {label}} ); } else { el = ( {iconEl} - {!collapsed && {label}} + {!collapsed && {label}} ); } diff --git a/src/components/admin/layout/ThemeModeSelector.tsx b/src/components/admin/layout/ThemeModeSelector.tsx index 846b859f..ca5ccf73 100644 --- a/src/components/admin/layout/ThemeModeSelector.tsx +++ b/src/components/admin/layout/ThemeModeSelector.tsx @@ -61,7 +61,7 @@ function ThemeModeSelector({ collapsed }: ThemeModeSelectorProps) {