feat(WEB): DevToolbar - 견적→수주→작업지시→출하 테스트 자동화 도구

- DevFillContext: 전역 상태 관리 (활성화/페이지 타입/폼 채우기 함수)
- DevToolbar: 플로팅 UI 컴포넌트 (토글/자동 채우기 버튼)
- useDevFill: 각 폼에서 자동 채우기 함수 등록 커스텀 훅
- 데이터 생성기: 견적/수주/작업지시/출하 샘플 데이터
- 환경변수 제어: NEXT_PUBLIC_DEV_TOOLBAR_ENABLED로 On/Off
- 통합: QuoteRegistration, OrderRegistration, WorkOrderCreate, ShipmentCreate
- Hydration 불일치 방지: useState 초기값 false + useEffect 패턴
This commit is contained in:
2026-01-20 20:38:29 +09:00
parent c101b8bf7e
commit eae23d4457
15 changed files with 1048 additions and 5 deletions

View File

@@ -8,7 +8,7 @@
import { useState, useEffect, useCallback } from 'react';
import { useRouter } from 'next/navigation';
import { X, Edit2, FileText } from 'lucide-react';
import { ArrowLeft, FileText, X, Edit2, Loader2 } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Input } from '@/components/ui/input';
import { Label } from '@/components/ui/label';
@@ -28,9 +28,12 @@ import { AssigneeSelectModal } from './AssigneeSelectModal';
import { toast } from 'sonner';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { createWorkOrder, getProcessOptions, type ProcessOption } from './actions';
import { type SalesOrder } from './types';
import { PROCESS_TYPE_LABELS, type ProcessType, type SalesOrder } from './types';
import { workOrderCreateConfig } from './workOrderConfig';
import { useDevFill } from '@/components/dev';
import { generateWorkOrderData } from '@/components/dev/generators/workOrderData';
// Validation 에러 타입
interface ValidationErrors {
[key: string]: string;
@@ -113,6 +116,32 @@ export function WorkOrderCreate() {
loadProcessOptions();
}, []);
// DevToolbar 자동 채우기
useDevFill(
'workOrder',
useCallback(() => {
const sampleData = generateWorkOrderData({ processOptions });
// 수동 등록 모드로 변경
setMode('manual');
// 폼 데이터 채우기
setFormData(prev => ({
...prev,
client: '테스트 거래처',
projectName: '테스트 현장',
orderNo: '',
itemCount: 0,
processId: sampleData.processId,
shipmentDate: sampleData.shipmentDate,
priority: sampleData.priority,
note: sampleData.note,
}));
toast.success('[Dev] 작업지시 폼이 자동으로 채워졌습니다.');
}, [processOptions])
);
// 수주 선택 핸들러
const handleSelectOrder = (order: SalesOrder) => {
setFormData({