From ae2175298f1e46967195570aa9716f1672bbdfed Mon Sep 17 00:00:00 2001 From: nabbang6 Date: Wed, 29 Apr 2026 22:25:59 +0900 Subject: [PATCH 1/5] =?UTF-8?q?fix:=20=EA=B8=B0=EC=88=98=20=EC=A1=B0?= =?UTF-8?q?=ED=9A=8C=20=EC=8B=9C=20=EC=A0=84=EC=B2=B4=20=EA=B8=B0=EC=88=98?= =?UTF-8?q?=EB=B6=80=ED=84=B0=20=ED=99=95=EC=9D=B8=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 --- src/components/admin/attendance/AttendancePageContent.tsx | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/components/admin/attendance/AttendancePageContent.tsx b/src/components/admin/attendance/AttendancePageContent.tsx index 1b2ce9cc..09062fbc 100644 --- a/src/components/admin/attendance/AttendancePageContent.tsx +++ b/src/components/admin/attendance/AttendancePageContent.tsx @@ -11,9 +11,7 @@ import { formatKoreanDate } from '@/lib/formatTime'; import { AttendanceSessionCard } from './AttendanceSessionCard'; function AttendancePageContent() { - const { cardinals, setSelectedCardinalId, activeCardinal } = useCardinalSelector({ - autoSelectLatest: true, - }); + const { cardinals, setSelectedCardinalId, activeCardinal } = useCardinalSelector(); const [dirtyCardIds, setDirtyCardIds] = useState>(new Set()); const [pendingCardinalId, setPendingCardinalId] = useState(null); const [cardinalDialogOpen, setCardinalDialogOpen] = useState(false); @@ -31,7 +29,7 @@ function AttendancePageContent() { }, []); const handleCardinalSelect = useCallback( - (id: number) => { + (id: number | null) => { if (isDirty) { setPendingCardinalId(id); setCardinalDialogOpen(true); @@ -60,6 +58,7 @@ function AttendancePageContent() { cardinals={cardinals} activeCardinal={activeCardinal} onSelect={handleCardinalSelect} + onSelectAll={() => handleCardinalSelect(null)} /> {sessions.length > 0 ? ( From fe9a1f7c4faaeeb28ffc03108e7d85b5989e838d Mon Sep 17 00:00:00 2001 From: nabbang6 Date: Wed, 29 Apr 2026 22:56:35 +0900 Subject: [PATCH 2/5] =?UTF-8?q?refactor:=20=EC=A0=84=EC=B2=B4=20=EA=B8=B0?= =?UTF-8?q?=EC=88=98=EC=9D=BC=20=EB=95=8C=20=EB=AA=A8=EB=93=A0=20=EC=84=B8?= =?UTF-8?q?=EC=85=98=EC=9D=84=20=EB=B6=88=EB=9F=AC=EC=98=AC=20=EC=88=98=20?= =?UTF-8?q?=EC=9E=88=EB=8F=84=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 --- src/hooks/queries/admin/useAdminAttendanceQueries.ts | 4 ++-- src/lib/apis/adminAttendance.ts | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/hooks/queries/admin/useAdminAttendanceQueries.ts b/src/hooks/queries/admin/useAdminAttendanceQueries.ts index e1c2d5bc..d9d00bb8 100644 --- a/src/hooks/queries/admin/useAdminAttendanceQueries.ts +++ b/src/hooks/queries/admin/useAdminAttendanceQueries.ts @@ -13,10 +13,10 @@ export function useAdminSessions(cardinal: number | null) { return useQuery({ queryKey: ['admin', 'sessions', clubId, cardinal], queryFn: async () => { - const res = await adminAttendanceApi.getSessions(clubId!, cardinal!); + const res = await adminAttendanceApi.getSessions(clubId!, cardinal ?? undefined); return res.data.data; }, - enabled: !!clubId && cardinal !== null, + enabled: !!clubId, }); } diff --git a/src/lib/apis/adminAttendance.ts b/src/lib/apis/adminAttendance.ts index 2d0d4ce4..39d98466 100644 --- a/src/lib/apis/adminAttendance.ts +++ b/src/lib/apis/adminAttendance.ts @@ -7,9 +7,9 @@ import type { } from '@/types/admin/attendance'; export const adminAttendanceApi = { - getSessions: (clubId: string, cardinal: number) => + getSessions: (clubId: string, cardinal?: number) => apiClient.get>(`/admin/clubs/${clubId}/sessions`, { - params: { cardinal }, + params: cardinal != null ? { cardinal } : undefined, }), getAttendanceBySession: (clubId: string, sessionId: number) => From bdc097ebace075f985a346b5dad61714adff803a Mon Sep 17 00:00:00 2001 From: nabbang6 Date: Wed, 29 Apr 2026 22:57:01 +0900 Subject: [PATCH 3/5] =?UTF-8?q?refactor:=20=EC=8A=A4=EC=BC=88=EB=A0=88?= =?UTF-8?q?=ED=86=A4=20=EB=B0=8F=20=EB=B0=98=EC=9D=91=ED=98=95(=EA=B0=80?= =?UTF-8?q?=EB=A1=9C=20=EC=8A=A4=ED=81=AC=EB=A1=A4)=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../attendance/AttendancePageContent.tsx | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/src/components/admin/attendance/AttendancePageContent.tsx b/src/components/admin/attendance/AttendancePageContent.tsx index 09062fbc..558ed18d 100644 --- a/src/components/admin/attendance/AttendancePageContent.tsx +++ b/src/components/admin/attendance/AttendancePageContent.tsx @@ -2,7 +2,7 @@ import { useCallback, useState } from 'react'; -import { AlertDialog, AlertDialogAction, AlertDialogCancel, Card } from '@/components/ui'; +import { AlertDialog, AlertDialogAction, AlertDialogCancel, Card, Skeleton } from '@/components/ui'; import { CardinalDropdown } from '@/components/admin'; import { useNavigationGuard, useCardinalSelector } from '@/hooks'; import { useFlattenedSessions } from '@/hooks/admin'; @@ -50,10 +50,10 @@ function AttendancePageContent() { }; const cardinalNumber = activeCardinal?.cardinalNumber ?? null; - const { sessions } = useFlattenedSessions(cardinalNumber); + const { sessions, isLoading } = useFlattenedSessions(cardinalNumber); return ( -
+
handleCardinalSelect(null)} /> - {sessions.length > 0 ? ( - - {sessions.map((session) => ( - - ))} + {isLoading ? ( + +
+ {Array.from({ length: 4 }, (_, i) => ( + + ))} +
+
+ ) : sessions.length > 0 ? ( + +
+ {sessions.map((session) => ( + + ))} +
) : ( - - - {activeCardinal ? '등록된 정기모임이 없습니다.' : '기수를 선택해 주세요.'} - + +
+ 등록된 정기모임이 없습니다. +
)} From be9355b39109461d8c1acef34795c579b86031ad Mon Sep 17 00:00:00 2001 From: nabbang6 Date: Wed, 29 Apr 2026 23:04:47 +0900 Subject: [PATCH 4/5] =?UTF-8?q?fix:=20prettier=20=ED=8F=AC=EB=A7=B7?= =?UTF-8?q?=ED=8C=85=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/attendance/AttendancePageContent.tsx | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/components/admin/attendance/AttendancePageContent.tsx b/src/components/admin/attendance/AttendancePageContent.tsx index 558ed18d..451733c9 100644 --- a/src/components/admin/attendance/AttendancePageContent.tsx +++ b/src/components/admin/attendance/AttendancePageContent.tsx @@ -65,7 +65,7 @@ function AttendancePageContent() {
{Array.from({ length: 4 }, (_, i) => ( - + ))}
@@ -87,7 +87,7 @@ function AttendancePageContent() { ) : (
- 등록된 정기모임이 없습니다. + 등록된 정기모임이 없습니다.
)} From 435155d6a5fd6b781da85d7436bf297e2dde910d Mon Sep 17 00:00:00 2001 From: nabbang6 Date: Wed, 29 Apr 2026 23:21:35 +0900 Subject: [PATCH 5/5] =?UTF-8?q?fix:=20isMembersLoading=20prop=EC=9D=84=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80=ED=95=98=EA=B3=A0=20=EC=8A=A4=EC=BC=88?= =?UTF-8?q?=EB=A0=88=ED=86=A4=EC=9D=84=20=ED=91=9C=EC=8B=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/attendance/AttendanceCard.tsx | 17 ++++++++++++++++- .../admin/attendance/AttendanceSessionCard.tsx | 3 ++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/components/admin/attendance/AttendanceCard.tsx b/src/components/admin/attendance/AttendanceCard.tsx index b6b7a412..bd2cb16c 100644 --- a/src/components/admin/attendance/AttendanceCard.tsx +++ b/src/components/admin/attendance/AttendanceCard.tsx @@ -10,6 +10,7 @@ import { Button, Icon, Badge, + Skeleton, } from '@/components/ui'; import type { AttendanceMember } from '@/types/admin/attendance'; import { cn } from '@/lib/cn'; @@ -27,6 +28,7 @@ interface AttendanceCardProps extends React.HTMLAttributes { onDirtyChange?: (dirty: boolean) => void; onExpand?: () => void; isSaving?: boolean; + isMembersLoading?: boolean; defaultExpanded?: boolean; } @@ -40,6 +42,7 @@ function AttendanceCard({ onDirtyChange, onExpand, isSaving = false, + isMembersLoading = false, defaultExpanded = false, ...props }: AttendanceCardProps) { @@ -156,7 +159,19 @@ function AttendanceCard({ {/* Member rows */} - {filteredMembers.length > 0 ? ( + {isMembersLoading ? ( + Array.from({ length: 5 }, (_, i) => ( +
+
+ + +
+
+ +
+
+ )) + ) : filteredMembers.length > 0 ? ( filteredMembers.map((member) => ( onDirtyChange?.(sessionId, dirty); @@ -40,6 +40,7 @@ function AttendanceSessionCard({ isCurrentWeek={isCurrentWeek} defaultExpanded={defaultExpanded} members={members} + isMembersLoading={isLoading} onSave={handleSave} onDirtyChange={handleDirtyChange} onExpand={() => setExpanded(true)}