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

@@ -37,6 +37,9 @@ import type {
VehicleTonnageOption,
} from './types';
import { isNextRedirectError } from '@/lib/utils/redirect-error';
import { toast } from 'sonner';
import { useDevFill } from '@/components/dev';
import { generateShipmentData } from '@/components/dev/generators/shipmentData';
// 고정 옵션 (클라이언트에서 관리)
const priorityOptions: { value: ShipmentPriority; label: string }[] = [
@@ -115,6 +118,38 @@ export function ShipmentCreate() {
loadOptions();
}, [loadOptions]);
// DevToolbar 자동 채우기
useDevFill(
'shipment',
useCallback(() => {
// lotOptions를 generateShipmentData에 전달하기 위해 변환
const lotOptionsForGenerator = lotOptions.map(o => ({
lotNo: o.value,
customerName: o.customerName,
siteName: o.siteName,
}));
const logisticsOptionsForGenerator = logisticsOptions.map(o => ({
id: o.value,
name: o.label,
}));
const tonnageOptionsForGenerator = vehicleTonnageOptions.map(o => ({
value: o.value,
label: o.label,
}));
const sampleData = generateShipmentData({
lotOptions: lotOptionsForGenerator,
logisticsOptions: logisticsOptionsForGenerator,
tonnageOptions: tonnageOptionsForGenerator,
});
setFormData(sampleData);
toast.success('[Dev] 출하 폼이 자동으로 채워졌습니다.');
}, [lotOptions, logisticsOptions, vehicleTonnageOptions])
);
// 폼 입력 핸들러
const handleInputChange = (field: keyof ShipmentCreateFormData, value: string) => {
setFormData(prev => ({ ...prev, [field]: value }));