'use client'; /** * DevToolbar - 개발/테스트용 플로팅 툴바 * * 화면 하단에 플로팅으로 표시되며, * 각 단계(견적→수주→작업지시→완료→출하)의 폼을 자동으로 채울 수 있습니다. * * 환경변수로 활성화/비활성화: * NEXT_PUBLIC_DEV_TOOLBAR_ENABLED=true */ import { useState } from 'react'; import { usePathname } from 'next/navigation'; import { FileText, // 견적 ClipboardList, // 수주 Wrench, // 작업지시 CheckCircle2, // 완료 Truck, // 출하 ChevronDown, ChevronUp, X, Loader2, Play, RotateCcw, } from 'lucide-react'; import { Button } from '@/components/ui/button'; import { Badge } from '@/components/ui/badge'; import { useDevFillContext, type DevFillPageType } from './DevFillContext'; // 페이지 경로와 타입 매핑 const PAGE_PATTERNS: { pattern: RegExp; type: DevFillPageType; label: string }[] = [ { pattern: /\/quote-management\/new/, type: 'quote', label: '견적' }, { pattern: /\/quote-management\/\d+\/edit/, type: 'quote', label: '견적' }, { pattern: /\/order-management-sales\/new/, type: 'order', label: '수주' }, { pattern: /\/order-management-sales\/\d+\/edit/, type: 'order', label: '수주' }, { pattern: /\/work-orders\/create/, type: 'workOrder', label: '작업지시' }, { pattern: /\/work-orders\/\d+\/edit/, type: 'workOrder', label: '작업지시' }, { pattern: /\/work-orders\/\d+$/, type: 'workOrderComplete', label: '작업완료' }, { pattern: /\/shipments\/new/, type: 'shipment', label: '출하' }, { pattern: /\/shipments\/\d+\/edit/, type: 'shipment', label: '출하' }, ]; // 플로우 단계 정의 const FLOW_STEPS: { type: DevFillPageType; label: string; icon: typeof FileText; path: string }[] = [ { type: 'quote', label: '견적', icon: FileText, path: '/sales/quote-management/new' }, { type: 'order', label: '수주', icon: ClipboardList, path: '/sales/order-management-sales/new' }, { type: 'workOrder', label: '작업지시', icon: Wrench, path: '/production/work-orders/create' }, { type: 'workOrderComplete', label: '완료', icon: CheckCircle2, path: '' }, // 상세 페이지에서 처리 { type: 'shipment', label: '출하', icon: Truck, path: '/outbound/shipments/new' }, ]; export function DevToolbar() { const pathname = usePathname(); const { isEnabled, isVisible, setIsVisible, currentPage, fillForm, hasRegisteredForm, flowData, clearFlowData, } = useDevFillContext(); const [isExpanded, setIsExpanded] = useState(true); const [isLoading, setIsLoading] = useState(null); // 비활성화 시 렌더링하지 않음 if (!isEnabled) return null; // 숨김 상태일 때 작은 버튼만 표시 if (!isVisible) { return (
); } // 현재 페이지 타입 감지 const detectedPage = PAGE_PATTERNS.find(p => p.pattern.test(pathname)); const activePage = detectedPage?.type || null; // 폼 채우기 실행 const handleFillForm = async (pageType: DevFillPageType) => { if (!hasRegisteredForm(pageType)) { console.warn(`[DevToolbar] Form not registered for: ${pageType}`); return; } setIsLoading(pageType); try { await fillForm(pageType, flowData); } catch (err) { console.error('[DevToolbar] Fill form error:', err); } finally { setIsLoading(null); } }; // 플로우 데이터 표시 const hasFlowData = flowData.quoteId || flowData.orderId || flowData.workOrderId || flowData.lotNo; return (
{/* 헤더 */}
DEV MODE {detectedPage && ( 현재: {detectedPage.label} )} {hasFlowData && ( {flowData.quoteId && `견적#${flowData.quoteId}`} {flowData.orderId && ` → 수주#${flowData.orderId}`} {flowData.workOrderId && ` → 작업#${flowData.workOrderId}`} )}
{hasFlowData && ( )}
{/* 버튼 영역 */} {isExpanded && (
{FLOW_STEPS.map((step, index) => { const Icon = step.icon; const isActive = activePage === step.type; const isRegistered = hasRegisteredForm(step.type); const isCurrentLoading = isLoading === step.type; // 완료 버튼은 상세 페이지에서만 활성화 if (step.type === 'workOrderComplete' && !isActive) { return (
{index > 0 && }
); } return (
{index > 0 && }
); })}
)} {/* 안내 메시지 */} {isExpanded && !activePage && (

견적/수주/작업지시/출하 페이지에서 활성화됩니다

)}
); } export default DevToolbar;