feat(WEB): 거래처 DevFill 자동 채우기 기능 추가

- 거래처 샘플 데이터 생성기 추가 (clientData.ts)
- DevFillContext에 'client' 페이지 타입 추가
- DevToolbar에 기준정보 섹션 (녹색 테마) 추가
- IntegratedDetailTemplate forwardRef 지원으로 외부 폼 데이터 조작 가능
- ClientDetailClientV2에서 DevFill 등록 로직 구현
This commit is contained in:
2026-01-22 23:03:45 +09:00
parent 2e9aa74b72
commit 1ba0561ee9
6 changed files with 339 additions and 24 deletions

View File

@@ -33,6 +33,8 @@ import {
ArrowUpFromLine, // 출금
Receipt, // 매입(지출결의서)
CreditCard, // 카드
// 기준정보 아이콘
Building2, // 거래처
} from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Badge } from '@/components/ui/badge';
@@ -55,6 +57,8 @@ const PAGE_PATTERNS: { pattern: RegExp; type: DevFillPageType; label: string }[]
{ pattern: /\/accounting\/withdrawals\/new/, type: 'withdrawal', label: '출금' },
{ pattern: /\/approval\/draft\/new/, type: 'purchaseApproval', label: '매입' },
{ pattern: /\/accounting\/card-transactions\/new/, type: 'cardTransaction', label: '카드' },
// 기준정보
{ pattern: /\/client-management-sales-admin\/new/, type: 'client', label: '거래처' },
];
// 플로우 단계 정의
@@ -74,6 +78,11 @@ const ACCOUNTING_STEPS: { type: DevFillPageType; label: string; icon: typeof Fil
{ type: 'cardTransaction', label: '카드', icon: CreditCard, path: '/accounting/card-transactions/new', fillEnabled: true },
];
// 기준정보 단계 정의
const MASTER_DATA_STEPS: { type: DevFillPageType; label: string; icon: typeof FileText; path: string; fillEnabled: boolean }[] = [
{ type: 'client', label: '거래처', icon: Building2, path: '/sales/client-management-sales-admin/new', fillEnabled: true },
];
export function DevToolbar() {
const pathname = usePathname();
const router = useRouter();
@@ -324,11 +333,61 @@ export function DevToolbar() {
</div>
)}
{/* 기준정보 버튼 영역 */}
{isExpanded && (
<div className="flex items-center gap-2 px-3 pb-3 border-t border-yellow-300 pt-3">
<span className="text-xs text-yellow-600 font-medium mr-1">:</span>
{MASTER_DATA_STEPS.map((step) => {
const Icon = step.icon;
const isActive = activePage === step.type;
const isRegistered = hasRegisteredForm(step.type);
const isCurrentLoading = isLoading === step.type;
// 활성화된 페이지: 폼 채우기 (fillEnabled가 true인 경우만)
if (isActive && step.fillEnabled) {
return (
<Button
key={step.type}
size="sm"
variant="default"
disabled={!isRegistered || isCurrentLoading}
className="bg-green-500 hover:bg-green-600 text-white border-green-600"
onClick={() => handleFillForm(step.type)}
title="폼 자동 채우기"
>
{isCurrentLoading ? (
<Loader2 className="w-4 h-4 mr-1 animate-spin" />
) : (
<Icon className="w-4 h-4 mr-1" />
)}
{step.label}
</Button>
);
}
// 비활성화된 페이지: 해당 페이지로 이동
return (
<Button
key={step.type}
size="sm"
variant="outline"
className={`border-green-300 text-green-700 hover:bg-green-100 hover:border-green-500 ${isActive ? 'bg-green-100 border-green-500' : ''}`}
onClick={() => handleNavigate(step.path)}
title={`${step.label} 페이지로 이동`}
>
<Icon className="w-4 h-4 mr-1" />
{step.label}
</Button>
);
})}
</div>
)}
{/* 안내 메시지 */}
{isExpanded && !activePage && (
<div className="px-3 pb-3">
<p className="text-xs text-yellow-600">
//////
///////
</p>
</div>
)}