diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index 3b8574d8..00000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,18 +0,0 @@ -{ - "permissions": { - "allow": [ - "Bash(gh pr:*)", - "Bash(gh run:*)", - "Bash(git push:*)", - "Bash(git fetch:*)", - "mcp__figma__get_design_context", - "mcp__figma__get_screenshot", - "Bash(gh pr *)", - "Read(//c/Users/wlslw/.claude/projects/**)", - "mcp__Claude_in_Chrome__tabs_context_mcp", - "Bash(export PATH=\"C:/Users/wlslw/AppData/Local/Temp/poppler_extracted/poppler-24.08.0/Library/bin:$PATH\")", - "Bash(pdftoppm -v)", - "Bash(\"C:/Users/wlslw/AppData/Local/Temp/poppler_extracted/poppler-24.08.0/Library/bin/pdftotext.exe\" \"C:/Users/wlslw/Downloads/이유진_포트폴리오_인턴추가버전.pdf\" \"C:/Users/wlslw/AppData/Local/Temp/portfolio.txt\")" - ] - } -} diff --git a/.gitignore b/.gitignore index 6cbea637..93c7aafd 100644 --- a/.gitignore +++ b/.gitignore @@ -10,9 +10,6 @@ !.yarn/releases !.yarn/versions - -.claude/settings.local.json - # testing /coverage diff --git a/src/components/admin/layout/LNB.tsx b/src/components/admin/layout/LNB.tsx index 45c1ee97..0a4dc375 100644 --- a/src/components/admin/layout/LNB.tsx +++ b/src/components/admin/layout/LNB.tsx @@ -1,6 +1,6 @@ 'use client'; -import { useState } from 'react'; +import { useEffect, useState } from 'react'; import { useParams, usePathname, useRouter } from 'next/navigation'; import { AdminForumIcon, AdminCalendarIcon, AdminSettingIcon } from '@/assets/icons/admin'; import { CheckRoundIcon, ExitIcon, PeopleIcon } from '@/assets/icons'; @@ -11,6 +11,7 @@ import { AlertDialogCancel, TooltipProvider, } from '@/components/ui'; +import { useMediaQuery } from '@/hooks'; import { cn } from '@/lib/cn'; import { LNBHeader } from '@/components/admin/layout/LNBHeader'; import { LNBClubInfo } from '@/components/admin/layout/LNBClubInfo'; @@ -23,9 +24,16 @@ function LNB() { const pathname = usePathname(); const router = useRouter(); const { clubId } = useParams<{ clubId: string }>(); + // tablet(696px) 미만에서는 기본적으로 접힌 상태로 시작 + const isBelowTablet = useMediaQuery('(max-width: 695.98px)'); const [collapsed, setCollapsed] = useState(false); const [serviceDialogOpen, setServiceDialogOpen] = useState(false); + // 브레이크포인트를 넘나들 때 기본 접힘 상태를 동기화 + useEffect(() => { + setCollapsed(isBelowTablet); + }, [isBelowTablet]); + const servicePath = `/${clubId}/home`; const managementNavItems = [ diff --git a/src/components/admin/schedule/general/ScheduleItem.tsx b/src/components/admin/schedule/general/ScheduleItem.tsx index a9699c07..d8f77ef1 100644 --- a/src/components/admin/schedule/general/ScheduleItem.tsx +++ b/src/components/admin/schedule/general/ScheduleItem.tsx @@ -27,7 +27,7 @@ function ScheduleItem({ return (
{/* Content column */} -
+
{schedule.title}
{SCHEDULE_TYPE_LABEL[schedule.type]} @@ -50,7 +50,7 @@ function ScheduleItem({
{/* Action buttons */} -
+
diff --git a/src/components/admin/schedule/general/SchedulePageContent.tsx b/src/components/admin/schedule/general/SchedulePageContent.tsx index 3edc5c9e..3963ff5c 100644 --- a/src/components/admin/schedule/general/SchedulePageContent.tsx +++ b/src/components/admin/schedule/general/SchedulePageContent.tsx @@ -99,7 +99,7 @@ function SchedulePageContent() { }; return ( -
+
세션 - - + + {/* Month navigator */} {/* Search bar + Create button */} -
-
+
+
검색
- diff --git a/src/components/admin/schedule/modal/CreateGeneralScheduleForm.tsx b/src/components/admin/schedule/modal/CreateGeneralScheduleForm.tsx index fdaa3848..3e737a9f 100644 --- a/src/components/admin/schedule/modal/CreateGeneralScheduleForm.tsx +++ b/src/components/admin/schedule/modal/CreateGeneralScheduleForm.tsx @@ -12,6 +12,7 @@ import { isScheduleTitleValid, } from '@/utils/admin/scheduleFormUtils'; +import { SCHEDULE_MODAL_FOOTER_CLASS } from './constants'; import { isDateRangeValid, type ScheduleFormState } from './types'; const INITIAL_FORM: ScheduleFormState = { @@ -60,7 +61,7 @@ function CreateGeneralScheduleForm({ cardinalNumber, onClose }: CreateGeneralSch return ( <> -
+

일정 생성

-
+
diff --git a/src/components/admin/schedule/modal/CreateScheduleModal.tsx b/src/components/admin/schedule/modal/CreateScheduleModal.tsx index 368b6e2d..186e57aa 100644 --- a/src/components/admin/schedule/modal/CreateScheduleModal.tsx +++ b/src/components/admin/schedule/modal/CreateScheduleModal.tsx @@ -5,6 +5,7 @@ import { Dialog, DialogContent } from '@/components/ui/dialog'; import { AdminCloseIcon } from '@/assets/icons/admin'; import { CreateGeneralScheduleForm } from '@/components/admin/schedule/modal/CreateGeneralScheduleForm'; import { CreateSessionScheduleForm } from '@/components/admin/schedule/modal/CreateSessionScheduleForm'; +import { SCHEDULE_MODAL_CONTENT_CLASS } from '@/components/admin/schedule/modal/constants'; import { SCHEDULE_TYPE_LABEL } from '@/constants/admin/schedule.constants'; import type { ScheduleType } from '@/types/admin/schedule'; import type { CreateSessionBody } from '@/types/admin/session'; @@ -31,8 +32,9 @@ function CreateScheduleModal({ return ( {/* Header with tabs */}
diff --git a/src/components/admin/schedule/modal/CreateSessionScheduleForm.tsx b/src/components/admin/schedule/modal/CreateSessionScheduleForm.tsx index 3da7c139..930cfcd3 100644 --- a/src/components/admin/schedule/modal/CreateSessionScheduleForm.tsx +++ b/src/components/admin/schedule/modal/CreateSessionScheduleForm.tsx @@ -10,6 +10,7 @@ import type { CreateSessionBody } from '@/types/admin/session'; import { isScheduleTitleValid } from '@/utils/admin/scheduleFormUtils'; +import { SCHEDULE_MODAL_FOOTER_CLASS } from './constants'; import { isDateRangeValid, type ScheduleFormState, type SessionFormState } from './types'; const INITIAL_FORM: ScheduleFormState = { @@ -104,7 +105,7 @@ function CreateSessionScheduleForm({ onCreateSession, onClose }: CreateSessionSc return ( <> -
+

세션 생성

-
+
diff --git a/src/components/admin/schedule/modal/EditModalShell.tsx b/src/components/admin/schedule/modal/EditModalShell.tsx index 7da5a1b2..50ba9d3f 100644 --- a/src/components/admin/schedule/modal/EditModalShell.tsx +++ b/src/components/admin/schedule/modal/EditModalShell.tsx @@ -4,6 +4,7 @@ import { Suspense } from 'react'; import type { ReactNode, RefObject } from 'react'; import { Dialog, DialogContent } from '@/components/ui/dialog'; +import { SCHEDULE_MODAL_CONTENT_CLASS } from '@/components/admin/schedule/modal/constants'; interface EditModalShellProps { open: boolean; @@ -44,8 +45,9 @@ function EditModalShell({ }} > { if (hasChangesRef.current) e.preventDefault(); }} diff --git a/src/components/admin/schedule/modal/EditScheduleModal.tsx b/src/components/admin/schedule/modal/EditScheduleModal.tsx index 8a4ac5bb..0575130b 100644 --- a/src/components/admin/schedule/modal/EditScheduleModal.tsx +++ b/src/components/admin/schedule/modal/EditScheduleModal.tsx @@ -26,6 +26,7 @@ import { toInitialScheduleForm, } from '@/utils/admin/scheduleFormUtils'; +import { SCHEDULE_MODAL_FOOTER_CLASS } from './constants'; import { DiscardConfirmArea } from './DiscardConfirmArea'; import { EditModalShell } from './EditModalShell'; import { ScheduleFormBody } from './ScheduleFormBody'; @@ -207,7 +208,7 @@ function EditScheduleModalContent({
{/* Body */} -
+

일반 일정 수정

{/* Footer */} -
+
{/* 카드 헤더 */} -
+
세션
{/* 카드 body */} -
+
) { @@ -52,10 +51,13 @@ function DialogContent({ overlayClassName, children, showCloseButton = true, + adminMobileFullscreen = true, ...props }: React.ComponentProps & { showCloseButton?: boolean; overlayClassName?: string; + /** admin 스코프에서 tablet 미만일 때 전체화면으로 전환할지 여부 (기본 true) */ + adminMobileFullscreen?: boolean; }) { const isAdminScope = useIsAdminScope(); @@ -68,17 +70,13 @@ function DialogContent({ className={cn( 'bg-container-neutral data-[state=open]:animate-in data-[state=closed]:animate-out data-[state=closed]:fade-out-0 data-[state=open]:fade-in-0 data-[state=closed]:zoom-out-95 data-[state=open]:zoom-in-95 fixed top-[50%] left-[50%] z-[80] grid w-78.75 max-w-[calc(100%-2rem)] translate-x-[-50%] translate-y-[-50%] rounded-lg border p-400 shadow-lg duration-200 outline-none sm:max-w-lg', isAdminScope && + adminMobileFullscreen && 'max-tablet:inset-0 max-tablet:top-0 max-tablet:left-0 max-tablet:h-screen max-tablet:w-screen max-tablet:max-w-none max-tablet:translate-x-0 max-tablet:translate-y-0 max-tablet:rounded-none max-tablet:border-0 max-tablet:p-0', className, )} {...props} > {children} - {/* {isAdminScope ? ( - {children} - ) : ( - children - )} */} {showCloseButton && ( void) => { + const mql = window.matchMedia(query); + mql.addEventListener('change', callback); + return () => mql.removeEventListener('change', callback); + }; + + const getSnapshot = () => window.matchMedia(query).matches; + const getServerSnapshot = () => false; + + return useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); +} + +export { useMediaQuery };