feat(WEB): DevToolbar 페이지 이동 기능 추가 및 locale 처리 수정
- 비활성화 버튼 클릭 시 해당 페이지로 이동 기능 추가 - 활성화 버튼 클릭 시 폼 자동 채우기 (기존 동작 유지) - locale 추출 로직 수정: 유효한 locale(ko, en)만 인식 - 잘못된 경로 생성 문제 해결 (/production/sales/... → /sales/...)
This commit is contained in:
@@ -6,12 +6,16 @@
|
|||||||
* 화면 하단에 플로팅으로 표시되며,
|
* 화면 하단에 플로팅으로 표시되며,
|
||||||
* 각 단계(견적→수주→작업지시→완료→출하)의 폼을 자동으로 채울 수 있습니다.
|
* 각 단계(견적→수주→작업지시→완료→출하)의 폼을 자동으로 채울 수 있습니다.
|
||||||
*
|
*
|
||||||
|
* 기능:
|
||||||
|
* - 현재 페이지에서 활성화: 버튼 클릭 시 폼 자동 채우기
|
||||||
|
* - 다른 페이지에서 비활성화: 버튼 클릭 시 해당 페이지로 이동
|
||||||
|
*
|
||||||
* 환경변수로 활성화/비활성화:
|
* 환경변수로 활성화/비활성화:
|
||||||
* NEXT_PUBLIC_DEV_TOOLBAR_ENABLED=true
|
* NEXT_PUBLIC_DEV_TOOLBAR_ENABLED=true
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { useState } from 'react';
|
import { useState } from 'react';
|
||||||
import { usePathname } from 'next/navigation';
|
import { usePathname, useRouter } from 'next/navigation';
|
||||||
import {
|
import {
|
||||||
FileText, // 견적
|
FileText, // 견적
|
||||||
ClipboardList, // 수주
|
ClipboardList, // 수주
|
||||||
@@ -53,6 +57,7 @@ const FLOW_STEPS: { type: DevFillPageType; label: string; icon: typeof FileText;
|
|||||||
|
|
||||||
export function DevToolbar() {
|
export function DevToolbar() {
|
||||||
const pathname = usePathname();
|
const pathname = usePathname();
|
||||||
|
const router = useRouter();
|
||||||
const {
|
const {
|
||||||
isEnabled,
|
isEnabled,
|
||||||
isVisible,
|
isVisible,
|
||||||
@@ -67,6 +72,11 @@ export function DevToolbar() {
|
|||||||
const [isExpanded, setIsExpanded] = useState(true);
|
const [isExpanded, setIsExpanded] = useState(true);
|
||||||
const [isLoading, setIsLoading] = useState<DevFillPageType | null>(null);
|
const [isLoading, setIsLoading] = useState<DevFillPageType | null>(null);
|
||||||
|
|
||||||
|
// 현재 locale 추출 (유효한 locale만 인식)
|
||||||
|
const VALID_LOCALES = ['ko', 'en'];
|
||||||
|
const firstSegment = pathname.split('/')[1];
|
||||||
|
const locale = VALID_LOCALES.includes(firstSegment) ? firstSegment : '';
|
||||||
|
|
||||||
// 비활성화 시 렌더링하지 않음
|
// 비활성화 시 렌더링하지 않음
|
||||||
if (!isEnabled) return null;
|
if (!isEnabled) return null;
|
||||||
|
|
||||||
@@ -108,6 +118,13 @@ export function DevToolbar() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// 페이지 이동
|
||||||
|
const handleNavigate = (path: string) => {
|
||||||
|
if (path) {
|
||||||
|
router.push(locale ? `/${locale}${path}` : path);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// 플로우 데이터 표시
|
// 플로우 데이터 표시
|
||||||
const hasFlowData = flowData.quoteId || flowData.orderId || flowData.workOrderId || flowData.lotNo;
|
const hasFlowData = flowData.quoteId || flowData.orderId || flowData.workOrderId || flowData.lotNo;
|
||||||
|
|
||||||
@@ -172,8 +189,9 @@ export function DevToolbar() {
|
|||||||
const isActive = activePage === step.type;
|
const isActive = activePage === step.type;
|
||||||
const isRegistered = hasRegisteredForm(step.type);
|
const isRegistered = hasRegisteredForm(step.type);
|
||||||
const isCurrentLoading = isLoading === step.type;
|
const isCurrentLoading = isLoading === step.type;
|
||||||
|
const hasPath = !!step.path;
|
||||||
|
|
||||||
// 완료 버튼은 상세 페이지에서만 활성화
|
// 완료 버튼은 상세 페이지에서만 활성화 (이동 경로 없음)
|
||||||
if (step.type === 'workOrderComplete' && !isActive) {
|
if (step.type === 'workOrderComplete' && !isActive) {
|
||||||
return (
|
return (
|
||||||
<div key={step.type} className="flex items-center">
|
<div key={step.type} className="flex items-center">
|
||||||
@@ -183,6 +201,7 @@ export function DevToolbar() {
|
|||||||
variant="outline"
|
variant="outline"
|
||||||
disabled
|
disabled
|
||||||
className="opacity-50"
|
className="opacity-50"
|
||||||
|
title="작업지시 상세 페이지에서 사용 가능"
|
||||||
>
|
>
|
||||||
<Icon className="w-4 h-4 mr-1" />
|
<Icon className="w-4 h-4 mr-1" />
|
||||||
{step.label}
|
{step.label}
|
||||||
@@ -191,27 +210,44 @@ export function DevToolbar() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 활성화된 페이지: 폼 채우기
|
||||||
|
if (isActive) {
|
||||||
|
return (
|
||||||
|
<div key={step.type} className="flex items-center">
|
||||||
|
{index > 0 && <span className="text-yellow-400 mx-1">→</span>}
|
||||||
|
<Button
|
||||||
|
size="sm"
|
||||||
|
variant="default"
|
||||||
|
disabled={!isRegistered || isCurrentLoading}
|
||||||
|
className="bg-yellow-500 hover:bg-yellow-600 text-white border-yellow-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>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 비활성화된 페이지: 해당 페이지로 이동
|
||||||
return (
|
return (
|
||||||
<div key={step.type} className="flex items-center">
|
<div key={step.type} className="flex items-center">
|
||||||
{index > 0 && <span className="text-yellow-400 mx-1">→</span>}
|
{index > 0 && <span className="text-yellow-400 mx-1">→</span>}
|
||||||
<Button
|
<Button
|
||||||
size="sm"
|
size="sm"
|
||||||
variant={isActive ? 'default' : 'outline'}
|
variant="outline"
|
||||||
disabled={!isActive || !isRegistered || isCurrentLoading}
|
disabled={!hasPath}
|
||||||
className={
|
className="border-yellow-300 text-yellow-700 hover:bg-yellow-100 hover:border-yellow-500"
|
||||||
isActive
|
onClick={() => handleNavigate(step.path)}
|
||||||
? 'bg-yellow-500 hover:bg-yellow-600 text-white border-yellow-600'
|
title={hasPath ? `${step.label} 페이지로 이동` : '이동 경로 없음'}
|
||||||
: 'border-yellow-300 text-yellow-700 hover:bg-yellow-100'
|
|
||||||
}
|
|
||||||
onClick={() => handleFillForm(step.type)}
|
|
||||||
>
|
>
|
||||||
{isCurrentLoading ? (
|
<Icon className="w-4 h-4 mr-1" />
|
||||||
<Loader2 className="w-4 h-4 mr-1 animate-spin" />
|
|
||||||
) : (
|
|
||||||
<Icon className="w-4 h-4 mr-1" />
|
|
||||||
)}
|
|
||||||
{step.label}
|
{step.label}
|
||||||
{isActive && ' 채우기'}
|
|
||||||
</Button>
|
</Button>
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
|
|||||||
Reference in New Issue
Block a user