목표 금액의 {percentage}%가 납부되었어요.
diff --git a/src/components/admin/dues/DuesSettingPageContent.tsx b/src/components/admin/dues/DuesSettingPageContent.tsx
new file mode 100644
index 00000000..d661f922
--- /dev/null
+++ b/src/components/admin/dues/DuesSettingPageContent.tsx
@@ -0,0 +1,123 @@
+'use client';
+
+import { useState, type ReactNode } from 'react';
+
+import { useParams } from 'next/navigation';
+
+import { useQuery } from '@tanstack/react-query';
+
+import { Switch } from '@/components/ui';
+import { useCardinalSelector } from '@/hooks';
+import { useDuesVisibilityToggle } from '@/hooks/admin';
+import {
+ duesRegistrationStatusQueryOptions,
+ useDuesDashboardQuery,
+ useDuesPaymentTargetsQuery,
+} from '@/hooks/queries/admin';
+
+import { BackButton } from './BackButton';
+import { PaymentTargetModal } from './modal/PaymentTargetModal';
+import { SettingResultCardGrid } from './setup/components';
+
+const MAX_AVATAR_DISPLAY = 4;
+
+interface SettingSectionProps {
+ title: string;
+ children: ReactNode;
+}
+
+// 흰색 카드 컨테이너 + 리스트 헤더 (총 회비 설정 / 회비 공개 범위 공통 래퍼)
+function SettingSection({ title, children }: SettingSectionProps) {
+ return (
+
+
+ {title}
+
+
{children}
+
+ );
+}
+
+function DuesSettingPageContent() {
+ const { clubId } = useParams<{ clubId: string }>();
+ const { activeCardinal } = useCardinalSelector({ autoSelectLatest: true });
+
+ // 대시보드로 accountId를 확보한 뒤 등록 상태·납부 대상 목록을 조회한다.
+ const { data: dashboard } = useDuesDashboardQuery(clubId, activeCardinal?.cardinalNumber ?? null);
+ const accountId = dashboard?.accountId ?? null;
+
+ const { data: status } = useQuery(duesRegistrationStatusQueryOptions(clubId, accountId));
+ const { data: paymentTargets } = useDuesPaymentTargetsQuery(clubId, accountId);
+
+ const [isPaymentTargetModalOpen, setIsPaymentTargetModalOpen] = useState(false);
+
+ const { isPublic, handlePublicChange } = useDuesVisibilityToggle(clubId, accountId);
+
+ const cardinalNumber = activeCardinal?.cardinalNumber ?? 0;
+
+ const targetedMembers = (paymentTargets?.targets.content ?? []).filter(
+ (t) => t.targetStatus === 'TARGETED',
+ );
+ const selectedMemberIds = targetedMembers.map((t) => t.paymentTargetInfo.clubMemberId);
+ const displayedAvatars = targetedMembers.slice(0, MAX_AVATAR_DISPLAY);
+ const remainingCount = Math.max(0, targetedMembers.length - MAX_AVATAR_DISPLAY);
+
+ const hasPreviousBalance = status?.previousAccountBalance != null;
+
+ return (
+
+ {/* 헤더 */}
+
+
+
회비 관리 설정
+
+
+
+
+ setIsPaymentTargetModalOpen(true)}
+ hasPreviousBalance={hasPreviousBalance}
+ previousGeneration={
+ status?.previousAccountBalance?.cardinalNumber ?? cardinalNumber - 1
+ }
+ previousBalance={status?.previousAccountBalance?.balance ?? 0}
+ carryOverOption={status?.carryOver?.enabled ? 'carry' : 'none'}
+ carryOverDescription={status?.carryOver?.memo ?? undefined}
+ isAccountPublic={status?.bankAccount?.bankAccountVisible ?? false}
+ accountNumber={status?.bankAccount?.bankAccount?.accountNumber ?? undefined}
+ bankName={status?.bankAccount?.bankAccount?.bankName ?? undefined}
+ accountHolder={status?.bankAccount?.bankAccount?.holder ?? undefined}
+ accountGuide={status?.bankAccount?.bankAccount?.guide ?? undefined}
+ />
+
+
+
+
+
+ 전체 회비 내역 공개
+
+ 부원이 회비 사용 내역을 볼 수 있어요
+
+
+
+
+
+
+
+
+
+ );
+}
+
+export { DuesSettingPageContent };
diff --git a/src/components/admin/dues/DuesTopBar.tsx b/src/components/admin/dues/DuesTopBar.tsx
index 04bb3eca..b2ee6feb 100644
--- a/src/components/admin/dues/DuesTopBar.tsx
+++ b/src/components/admin/dues/DuesTopBar.tsx
@@ -55,7 +55,7 @@ function DuesTopBar({
)}
+ {memo && (
+