feat(WEB): 전체 페이지 ?mode= URL 네비게이션 패턴 적용
- 등록(?mode=new), 상세(?mode=view), 수정(?mode=edit) URL 패턴 일괄 적용
- 중복 패턴 제거: /edit?mode=edit → ?mode=edit (16개 파일)
- 제목 일관성: {기능} 등록/상세/수정 패턴 적용
- 검수 체크리스트 문서 추가 (79개 페이지)
- UniversalListPage, IntegratedDetailTemplate 공통 컴포넌트 개선
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -137,7 +137,7 @@ export function BadDebtDetail({ mode, recordId, initialData }: BadDebtDetailProp
|
||||
if (isNewMode) {
|
||||
router.push('/ko/accounting/bad-debt-collection');
|
||||
} else {
|
||||
router.push(`/ko/accounting/bad-debt-collection/${recordId}`);
|
||||
router.push(`/ko/accounting/bad-debt-collection/${recordId}?mode=view`);
|
||||
}
|
||||
}, [router, recordId, isNewMode]);
|
||||
|
||||
@@ -163,7 +163,7 @@ export function BadDebtDetail({ mode, recordId, initialData }: BadDebtDetailProp
|
||||
const result = await updateBadDebt(recordId!, formData);
|
||||
if (result.success) {
|
||||
toast.success('악성채권이 수정되었습니다.');
|
||||
router.push(`/ko/accounting/bad-debt-collection/${recordId}`);
|
||||
router.push(`/ko/accounting/bad-debt-collection/${recordId}?mode=view`);
|
||||
} else {
|
||||
toast.error(result.error || '수정에 실패했습니다.');
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ export function BadDebtCollection({ initialData, initialSummary }: BadDebtCollec
|
||||
// ===== 핸들러 =====
|
||||
const handleRowClick = useCallback(
|
||||
(item: BadDebtRecord) => {
|
||||
router.push(`/ko/accounting/bad-debt-collection/${item.id}`);
|
||||
router.push(`/ko/accounting/bad-debt-collection/${item.id}?mode=view`);
|
||||
},
|
||||
[router]
|
||||
);
|
||||
|
||||
@@ -163,7 +163,7 @@ export function BillDetail({ billId, mode }: BillDetailProps) {
|
||||
if (isNewMode) {
|
||||
router.push('/ko/accounting/bills');
|
||||
} else {
|
||||
router.push(`/ko/accounting/bills/${billId}`);
|
||||
router.push(`/ko/accounting/bills/${billId}?mode=view`);
|
||||
}
|
||||
return { success: true };
|
||||
} else {
|
||||
@@ -434,10 +434,12 @@ export function BillDetail({ billId, mode }: BillDetailProps) {
|
||||
);
|
||||
|
||||
// ===== 템플릿 모드 및 동적 설정 =====
|
||||
// IntegratedDetailTemplate: create → "{title} 등록", view → "{title}", edit → "{title} 수정"
|
||||
// view 모드에서 "어음 상세"로 표시하려면 직접 설정 필요
|
||||
const templateMode = isNewMode ? 'create' : mode;
|
||||
const dynamicConfig = {
|
||||
...billConfig,
|
||||
title: isNewMode ? '어음 등록' : '어음 상세',
|
||||
title: isViewMode ? '어음 상세' : '어음',
|
||||
actions: {
|
||||
...billConfig.actions,
|
||||
submitLabel: isNewMode ? '등록' : '저장',
|
||||
|
||||
@@ -150,7 +150,7 @@ export function BillManagementClient({
|
||||
|
||||
// ===== 액션 핸들러 =====
|
||||
const handleRowClick = useCallback((item: BillRecord) => {
|
||||
router.push(`/ko/accounting/bills/${item.id}`);
|
||||
router.push(`/ko/accounting/bills/${item.id}?mode=view`);
|
||||
}, [router]);
|
||||
|
||||
const handleDeleteClick = useCallback((id: string) => {
|
||||
@@ -425,7 +425,7 @@ export function BillManagementClient({
|
||||
// 등록 버튼
|
||||
createButton: {
|
||||
label: '어음 등록',
|
||||
onClick: () => router.push('/ko/accounting/bills/new'),
|
||||
onClick: () => router.push('/ko/accounting/bills?mode=new'),
|
||||
icon: Plus,
|
||||
},
|
||||
|
||||
|
||||
@@ -169,7 +169,7 @@ export function BillManagement({ initialVendorId, initialBillType }: BillManagem
|
||||
|
||||
// ===== 핸들러 =====
|
||||
const handleRowClick = useCallback((item: BillRecord) => {
|
||||
router.push(`/ko/accounting/bills/${item.id}`);
|
||||
router.push(`/ko/accounting/bills/${item.id}?mode=view`);
|
||||
}, [router]);
|
||||
|
||||
const handleEdit = useCallback((item: BillRecord) => {
|
||||
@@ -177,7 +177,7 @@ export function BillManagement({ initialVendorId, initialBillType }: BillManagem
|
||||
}, [router]);
|
||||
|
||||
const handleCreate = useCallback(() => {
|
||||
router.push('/ko/accounting/bills/new');
|
||||
router.push('/ko/accounting/bills?mode=new');
|
||||
}, [router]);
|
||||
|
||||
// 저장 핸들러 (선택된 항목의 상태 일괄 변경)
|
||||
|
||||
@@ -115,7 +115,7 @@ export default function CardTransactionDetailClient({
|
||||
const handleModeChange = useCallback(
|
||||
(newMode: DetailMode) => {
|
||||
if (newMode === 'edit' && transactionId) {
|
||||
router.push(`/ko/accounting/card-transactions/${transactionId}/edit`);
|
||||
router.push(`/ko/accounting/card-transactions/${transactionId}?mode=edit`);
|
||||
} else {
|
||||
setMode(newMode);
|
||||
}
|
||||
|
||||
@@ -382,7 +382,7 @@ export function CardTransactionInquiry({
|
||||
|
||||
// 헤더 액션 (등록 버튼)
|
||||
headerActions: () => (
|
||||
<Button className="ml-auto" onClick={() => router.push('/ko/accounting/card-transactions/new')}>
|
||||
<Button className="ml-auto" onClick={() => router.push('/ko/accounting/card-transactions?mode=new')}>
|
||||
<Plus className="w-4 h-4 mr-2" />
|
||||
카드내역 등록
|
||||
</Button>
|
||||
|
||||
@@ -129,7 +129,7 @@ export function DepositDetail({ depositId, mode }: DepositDetailProps) {
|
||||
if (isNewMode) {
|
||||
router.push('/ko/accounting/deposits');
|
||||
} else {
|
||||
router.push(`/ko/accounting/deposits/${depositId}`);
|
||||
router.push(`/ko/accounting/deposits/${depositId}?mode=view`);
|
||||
}
|
||||
}, [router, depositId, isNewMode]);
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ export default function DepositDetailClientV2({
|
||||
const handleModeChange = useCallback(
|
||||
(newMode: DetailMode) => {
|
||||
if (newMode === 'edit' && depositId) {
|
||||
router.push(`/ko/accounting/deposits/${depositId}/edit`);
|
||||
router.push(`/ko/accounting/deposits/${depositId}?mode=edit`);
|
||||
} else {
|
||||
setMode(newMode);
|
||||
}
|
||||
@@ -120,9 +120,17 @@ export default function DepositDetailClientV2({
|
||||
[depositId, router]
|
||||
);
|
||||
|
||||
// 타이틀 동적 설정
|
||||
// IntegratedDetailTemplate: create → "{title} 등록", view → "{title}", edit → "{title} 수정"
|
||||
// view 모드에서 "입금 상세"로 표시하려면 직접 설정 필요
|
||||
const dynamicConfig = {
|
||||
...depositDetailConfig,
|
||||
title: mode === 'view' ? '입금 상세' : '입금',
|
||||
};
|
||||
|
||||
return (
|
||||
<IntegratedDetailTemplate
|
||||
config={depositDetailConfig as Parameters<typeof IntegratedDetailTemplate>[0]['config']}
|
||||
config={dynamicConfig as Parameters<typeof IntegratedDetailTemplate>[0]['config']}
|
||||
mode={mode}
|
||||
initialData={deposit as unknown as Record<string, unknown> | undefined}
|
||||
itemId={depositId}
|
||||
|
||||
@@ -144,7 +144,7 @@ export function DepositManagement({ initialData, initialPagination }: DepositMan
|
||||
|
||||
// ===== 핸들러 =====
|
||||
const handleRowClick = useCallback((item: DepositRecord) => {
|
||||
router.push(`/ko/accounting/deposits/${item.id}`);
|
||||
router.push(`/ko/accounting/deposits/${item.id}?mode=view`);
|
||||
}, [router]);
|
||||
|
||||
const handleEdit = useCallback((item: DepositRecord) => {
|
||||
|
||||
@@ -196,7 +196,7 @@ export function PurchaseManagement() {
|
||||
|
||||
// ===== 핸들러 =====
|
||||
const handleRowClick = useCallback((item: PurchaseRecord) => {
|
||||
router.push(`/ko/accounting/purchase/${item.id}`);
|
||||
router.push(`/ko/accounting/purchase/${item.id}?mode=view`);
|
||||
}, [router]);
|
||||
|
||||
const handleEdit = useCallback((item: PurchaseRecord) => {
|
||||
|
||||
@@ -555,9 +555,11 @@ export function SalesDetail({ mode, salesId }: SalesDetailProps) {
|
||||
const templateMode = isNewMode ? 'create' : mode;
|
||||
|
||||
// ===== 동적 config =====
|
||||
// IntegratedDetailTemplate: create → "{title} 등록", view → "{title}", edit → "{title} 수정"
|
||||
// view 모드에서 "매출 상세"로 표시하려면 직접 설정 필요
|
||||
const dynamicConfig = {
|
||||
...salesConfig,
|
||||
title: isNewMode ? '매출' : '매출 상세',
|
||||
title: isViewMode ? '매출 상세' : '매출',
|
||||
actions: {
|
||||
...salesConfig.actions,
|
||||
submitLabel: isNewMode ? '등록' : '저장',
|
||||
|
||||
@@ -180,7 +180,7 @@ export function SalesManagement({ initialData, initialPagination }: SalesManagem
|
||||
|
||||
// ===== 핸들러 =====
|
||||
const handleRowClick = useCallback((item: SalesRecord) => {
|
||||
router.push(`/ko/accounting/sales/${item.id}`);
|
||||
router.push(`/ko/accounting/sales/${item.id}?mode=view`);
|
||||
}, [router]);
|
||||
|
||||
const handleEdit = useCallback((item: SalesRecord) => {
|
||||
|
||||
@@ -112,7 +112,7 @@ export function VendorLedgerDetail({
|
||||
const handleEditTransaction = useCallback((entry: TransactionEntry) => {
|
||||
// 어음 관련 항목일 경우 어음 상세로 이동
|
||||
if (entry.type === 'note' && entry.noteInfo) {
|
||||
router.push(`/ko/accounting/bills/${entry.id}`);
|
||||
router.push(`/ko/accounting/bills/${entry.id}?mode=view`);
|
||||
}
|
||||
}, [router]);
|
||||
|
||||
|
||||
@@ -646,9 +646,11 @@ export function VendorDetail({ mode, vendorId, openModal }: VendorDetailProps) {
|
||||
);
|
||||
|
||||
// config 동적 수정 (등록 모드일 때 타이틀 변경)
|
||||
// IntegratedDetailTemplate: create → "{title} 등록", view → "{title}", edit → "{title} 수정"
|
||||
// view 모드에서 "거래처 상세"로 표시하려면 직접 설정 필요
|
||||
const dynamicConfig = {
|
||||
...vendorConfig,
|
||||
title: isNewMode ? '거래처 등록' : '거래처 상세',
|
||||
title: isViewMode ? '거래처 상세' : '거래처',
|
||||
description: isNewMode ? '새로운 거래처를 등록합니다' : '거래처 상세 정보 및 신용등급을 관리합니다',
|
||||
actions: {
|
||||
...vendorConfig.actions,
|
||||
|
||||
@@ -549,9 +549,11 @@ export function VendorDetailClient({ mode, vendorId, initialData }: VendorDetail
|
||||
);
|
||||
|
||||
// config 동적 수정 (등록 모드일 때 타이틀 변경)
|
||||
// IntegratedDetailTemplate: create → "{title} 등록", view → "{title}", edit → "{title} 수정"
|
||||
// view 모드에서 "거래처 상세"로 표시하려면 직접 설정 필요
|
||||
const dynamicConfig = {
|
||||
...vendorConfig,
|
||||
title: isNewMode ? '거래처 등록' : '거래처',
|
||||
title: isViewMode ? '거래처 상세' : '거래처',
|
||||
description: isNewMode ? '새로운 거래처를 등록합니다' : '거래처 상세 정보 및 신용등급을 관리합니다',
|
||||
actions: {
|
||||
...vendorConfig.actions,
|
||||
|
||||
@@ -171,7 +171,7 @@ export function VendorManagementClient({ initialData, initialTotal }: VendorMana
|
||||
|
||||
// ===== 액션 핸들러 =====
|
||||
const handleRowClick = useCallback((item: Vendor) => {
|
||||
router.push(`/ko/accounting/vendors/${item.id}`);
|
||||
router.push(`/ko/accounting/vendors/${item.id}?mode=view`);
|
||||
}, [router]);
|
||||
|
||||
const handleEdit = useCallback((item: Vendor) => {
|
||||
|
||||
@@ -88,7 +88,7 @@ export function VendorManagement({ initialData, initialTotal }: VendorManagement
|
||||
// ===== 핸들러 =====
|
||||
const handleRowClick = useCallback(
|
||||
(vendor: Vendor) => {
|
||||
router.push(`/ko/accounting/vendors/${vendor.id}`);
|
||||
router.push(`/ko/accounting/vendors/${vendor.id}?mode=view`);
|
||||
},
|
||||
[router]
|
||||
);
|
||||
|
||||
@@ -129,7 +129,7 @@ export function WithdrawalDetail({ withdrawalId, mode }: WithdrawalDetailProps)
|
||||
if (isNewMode) {
|
||||
router.push('/ko/accounting/withdrawals');
|
||||
} else {
|
||||
router.push(`/ko/accounting/withdrawals/${withdrawalId}`);
|
||||
router.push(`/ko/accounting/withdrawals/${withdrawalId}?mode=view`);
|
||||
}
|
||||
}, [router, withdrawalId, isNewMode]);
|
||||
|
||||
|
||||
@@ -112,7 +112,7 @@ export default function WithdrawalDetailClientV2({
|
||||
const handleModeChange = useCallback(
|
||||
(newMode: DetailMode) => {
|
||||
if (newMode === 'edit' && withdrawalId) {
|
||||
router.push(`/ko/accounting/withdrawals/${withdrawalId}/edit`);
|
||||
router.push(`/ko/accounting/withdrawals/${withdrawalId}?mode=edit`);
|
||||
} else {
|
||||
setMode(newMode);
|
||||
}
|
||||
@@ -120,9 +120,17 @@ export default function WithdrawalDetailClientV2({
|
||||
[withdrawalId, router]
|
||||
);
|
||||
|
||||
// 타이틀 동적 설정
|
||||
// IntegratedDetailTemplate: create → "{title} 등록", view → "{title}", edit → "{title} 수정"
|
||||
// view 모드에서 "출금 상세"로 표시하려면 직접 설정 필요
|
||||
const dynamicConfig = {
|
||||
...withdrawalDetailConfig,
|
||||
title: mode === 'view' ? '출금 상세' : '출금',
|
||||
};
|
||||
|
||||
return (
|
||||
<IntegratedDetailTemplate
|
||||
config={withdrawalDetailConfig as Parameters<typeof IntegratedDetailTemplate>[0]['config']}
|
||||
config={dynamicConfig as Parameters<typeof IntegratedDetailTemplate>[0]['config']}
|
||||
mode={mode}
|
||||
initialData={withdrawal as unknown as Record<string, unknown> | undefined}
|
||||
itemId={withdrawalId}
|
||||
|
||||
@@ -160,7 +160,7 @@ export function WithdrawalManagement({ initialData, initialPagination }: Withdra
|
||||
|
||||
// ===== 핸들러 =====
|
||||
const handleRowClick = useCallback((item: WithdrawalRecord) => {
|
||||
router.push(`/ko/accounting/withdrawals/${item.id}`);
|
||||
router.push(`/ko/accounting/withdrawals/${item.id}?mode=view`);
|
||||
}, [router]);
|
||||
|
||||
const handleEdit = useCallback((item: WithdrawalRecord) => {
|
||||
|
||||
Reference in New Issue
Block a user