refactor: IntegratedDetailTemplate 마이그레이션 (수주/견적)
- order-management-sales/[id]/page.tsx: PageLayout → IntegratedDetailTemplate (view) - order-management-sales/[id]/edit/page.tsx: PageLayout → IntegratedDetailTemplate (edit) - EstimateDetailForm.tsx: PageLayout → IntegratedDetailTemplate (view/edit) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,7 @@
|
||||
* - 품목 내역 (생산 시작 후 수정 불가)
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Textarea } from "@/components/ui/textarea";
|
||||
@@ -31,11 +31,10 @@ import {
|
||||
TableHeader,
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import { FileText, AlertTriangle } from "lucide-react";
|
||||
import { AlertTriangle } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { PageLayout } from "@/components/organisms/PageLayout";
|
||||
import { PageHeader } from "@/components/organisms/PageHeader";
|
||||
import { FormActions } from "@/components/organisms/FormActions";
|
||||
import { IntegratedDetailTemplate } from "@/components/templates/IntegratedDetailTemplate";
|
||||
import { orderSalesConfig } from "@/components/orders/orderSalesConfig";
|
||||
import { BadgeSm } from "@/components/atoms/BadgeSm";
|
||||
import { formatAmount } from "@/utils/formatAmount";
|
||||
import {
|
||||
@@ -119,7 +118,6 @@ export default function OrderEditPage() {
|
||||
|
||||
const [form, setForm] = useState<EditFormData | null>(null);
|
||||
const [loading, setLoading] = useState(true);
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
||||
// 데이터 로드 (API)
|
||||
useEffect(() => {
|
||||
@@ -177,28 +175,25 @@ export default function OrderEditPage() {
|
||||
router.push(`/sales/order-management-sales/${orderId}`);
|
||||
};
|
||||
|
||||
const handleSave = async () => {
|
||||
if (!form) return;
|
||||
// onSubmit wrapper for IntegratedDetailTemplate
|
||||
const handleSubmit = useCallback(async (): Promise<{ success: boolean; error?: string }> => {
|
||||
if (!form) return { success: false, error: "폼 데이터가 없습니다." };
|
||||
|
||||
// 유효성 검사
|
||||
if (!form.deliveryRequestDate) {
|
||||
toast.error("납품요청일을 입력해주세요.");
|
||||
return;
|
||||
return { success: false, error: "납품요청일을 입력해주세요." };
|
||||
}
|
||||
if (!form.receiver.trim()) {
|
||||
toast.error("수신(반장/업체)을 입력해주세요.");
|
||||
return;
|
||||
return { success: false, error: "수신(반장/업체)을 입력해주세요." };
|
||||
}
|
||||
if (!form.receiverContact.trim()) {
|
||||
toast.error("수신처 연락처를 입력해주세요.");
|
||||
return;
|
||||
return { success: false, error: "수신처 연락처를 입력해주세요." };
|
||||
}
|
||||
|
||||
setIsSaving(true);
|
||||
try {
|
||||
// API 연동
|
||||
// 주의: clientId를 보내지 않으면 기존 값 유지됨
|
||||
// clientName과 clientContact는 반드시 보내야 기존 값이 유지됨
|
||||
const result = await updateOrder(orderId, {
|
||||
clientName: form.client,
|
||||
clientContact: form.contact,
|
||||
@@ -226,44 +221,32 @@ export default function OrderEditPage() {
|
||||
if (result.success) {
|
||||
toast.success("수주가 수정되었습니다.");
|
||||
router.push(`/sales/order-management-sales/${orderId}`);
|
||||
return { success: true };
|
||||
} else {
|
||||
toast.error(result.error || "수주 수정에 실패했습니다.");
|
||||
return { success: false, error: result.error };
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("Error updating order:", error);
|
||||
toast.error("수주 수정 중 오류가 발생했습니다.");
|
||||
} finally {
|
||||
setIsSaving(false);
|
||||
return { success: false, error: "수주 수정 중 오류가 발생했습니다." };
|
||||
}
|
||||
};
|
||||
}, [form, orderId, router]);
|
||||
|
||||
// 폼 컨텐츠 렌더링
|
||||
const renderFormContent = useCallback(() => {
|
||||
if (!form) return null;
|
||||
|
||||
if (loading || !form) {
|
||||
return (
|
||||
<PageLayout>
|
||||
<div className="flex items-center justify-center h-64">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
|
||||
</div>
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
{/* 헤더 */}
|
||||
<PageHeader
|
||||
title="수주 수정"
|
||||
icon={FileText}
|
||||
actions={
|
||||
<div className="flex items-center gap-2">
|
||||
<code className="text-sm font-mono bg-gray-100 px-2 py-1 rounded">
|
||||
{form.lotNumber}
|
||||
</code>
|
||||
{getOrderStatusBadge(form.status)}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* 상태 뱃지 */}
|
||||
<div className="flex items-center gap-2">
|
||||
<code className="text-sm font-mono bg-gray-100 px-2 py-1 rounded">
|
||||
{form.lotNumber}
|
||||
</code>
|
||||
{getOrderStatusBadge(form.status)}
|
||||
</div>
|
||||
|
||||
{/* 기본 정보 (읽기전용) */}
|
||||
<Card>
|
||||
<CardHeader>
|
||||
@@ -545,18 +528,26 @@ export default function OrderEditPage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}, [form]);
|
||||
|
||||
{/* 하단 버튼 */}
|
||||
<div className="sticky bottom-0 bg-background/95 backdrop-blur supports-[backdrop-filter]:bg-background/60 border-t pt-4 pb-4 -mx-3 md:-mx-6 px-3 md:px-6 mt-6">
|
||||
<FormActions
|
||||
onSave={handleSave}
|
||||
onCancel={handleCancel}
|
||||
saveLabel="저장"
|
||||
cancelLabel="취소"
|
||||
saveLoading={isSaving}
|
||||
saveDisabled={isSaving}
|
||||
/>
|
||||
</div>
|
||||
</PageLayout>
|
||||
// Edit mode config override
|
||||
const editConfig = {
|
||||
...orderSalesConfig,
|
||||
title: '수주 수정',
|
||||
};
|
||||
|
||||
return (
|
||||
<IntegratedDetailTemplate
|
||||
config={editConfig}
|
||||
mode="edit"
|
||||
initialData={form}
|
||||
itemId={orderId}
|
||||
isLoading={loading || !form}
|
||||
onSubmit={handleSubmit}
|
||||
onCancel={handleCancel}
|
||||
onBack={handleCancel}
|
||||
renderForm={renderFormContent}
|
||||
/>
|
||||
);
|
||||
}
|
||||
@@ -9,7 +9,7 @@
|
||||
* - 상태별 버튼 차이
|
||||
*/
|
||||
|
||||
import { useState, useEffect } from "react";
|
||||
import { useState, useEffect, useCallback } from "react";
|
||||
import { useRouter, useParams } from "next/navigation";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
@@ -22,8 +22,6 @@ import {
|
||||
TableRow,
|
||||
} from "@/components/ui/table";
|
||||
import {
|
||||
FileText,
|
||||
ArrowLeft,
|
||||
Edit,
|
||||
Factory,
|
||||
XCircle,
|
||||
@@ -39,8 +37,8 @@ import {
|
||||
ChevronsUpDown,
|
||||
} from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
import { PageLayout } from "@/components/organisms/PageLayout";
|
||||
import { PageHeader } from "@/components/organisms/PageHeader";
|
||||
import { IntegratedDetailTemplate } from "@/components/templates/IntegratedDetailTemplate";
|
||||
import { orderSalesConfig } from "@/components/orders/orderSalesConfig";
|
||||
import { BadgeSm } from "@/components/atoms/BadgeSm";
|
||||
import { formatAmount } from "@/utils/formatAmount";
|
||||
import {
|
||||
@@ -339,105 +337,11 @@ export default function OrderDetailPage() {
|
||||
return order.items.filter((item) => !matchedIds.has(item.id));
|
||||
};
|
||||
|
||||
if (loading) {
|
||||
// 상세 컨텐츠 렌더링
|
||||
const renderViewContent = useCallback(() => {
|
||||
if (!order) return null;
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
<div className="flex items-center justify-center h-64">
|
||||
<div className="animate-spin rounded-full h-8 w-8 border-b-2 border-primary" />
|
||||
</div>
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
||||
if (!order) {
|
||||
return (
|
||||
<PageLayout>
|
||||
<div className="text-center py-12">
|
||||
<p className="text-muted-foreground">수주 정보를 찾을 수 없습니다.</p>
|
||||
<Button variant="outline" onClick={handleBack} className="mt-4">
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
목록으로
|
||||
</Button>
|
||||
</div>
|
||||
</PageLayout>
|
||||
);
|
||||
}
|
||||
|
||||
// 상태별 버튼 표시 여부
|
||||
const showEditButton = order.status !== "shipped" && order.status !== "cancelled";
|
||||
// 수주 확정 버튼: 수주등록 상태에서만 표시
|
||||
const showConfirmButton = order.status === "order_registered";
|
||||
// 생산지시 생성 버튼: 수주확정 상태에서만 표시
|
||||
const showProductionCreateButton = order.status === "order_confirmed";
|
||||
// 생산지시 보기 버튼: 생산지시완료 상태에서 숨김 (기획서 오류로 제거)
|
||||
const showProductionViewButton = false;
|
||||
// 생산지시 되돌리기 버튼: 생산지시완료 상태에서만 표시
|
||||
const showRevertButton = order.status === "production_ordered";
|
||||
// 수주확정 되돌리기 버튼: 수주확정 상태에서만 표시
|
||||
const showRevertConfirmButton = order.status === "order_confirmed";
|
||||
const showCancelButton =
|
||||
order.status !== "shipped" &&
|
||||
order.status !== "cancelled" &&
|
||||
order.status !== "production_ordered";
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
{/* 헤더 */}
|
||||
<PageHeader
|
||||
title="수주 상세"
|
||||
icon={FileText}
|
||||
actions={
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
<Button variant="outline" onClick={handleBack}>
|
||||
<ArrowLeft className="h-4 w-4 mr-2" />
|
||||
목록
|
||||
</Button>
|
||||
{showEditButton && (
|
||||
<Button variant="outline" onClick={handleEdit}>
|
||||
<Edit className="h-4 w-4 mr-2" />
|
||||
수정
|
||||
</Button>
|
||||
)}
|
||||
{showConfirmButton && (
|
||||
<Button onClick={handleConfirmOrder} className="bg-green-600 hover:bg-green-700">
|
||||
<CheckCircle2 className="h-4 w-4 mr-2" />
|
||||
수주 확정
|
||||
</Button>
|
||||
)}
|
||||
{showProductionCreateButton && (
|
||||
<Button onClick={handleProductionOrder}>
|
||||
<Factory className="h-4 w-4 mr-2" />
|
||||
생산지시 생성
|
||||
</Button>
|
||||
)}
|
||||
{showProductionViewButton && (
|
||||
<Button onClick={handleViewProductionOrder}>
|
||||
<Eye className="h-4 w-4 mr-2" />
|
||||
생산지시 보기
|
||||
</Button>
|
||||
)}
|
||||
{showRevertButton && (
|
||||
<Button variant="outline" onClick={handleRevertProduction} className="border-amber-200 text-amber-600 hover:border-amber-300 hover:bg-amber-50">
|
||||
<RotateCcw className="h-4 w-4 mr-2" />
|
||||
생산지시 되돌리기
|
||||
</Button>
|
||||
)}
|
||||
{showRevertConfirmButton && (
|
||||
<Button variant="outline" onClick={handleRevertConfirmation} className="border-slate-300 text-slate-600 hover:border-slate-400 hover:bg-slate-50">
|
||||
<RotateCcw className="h-4 w-4 mr-2" />
|
||||
수주확정 되돌리기
|
||||
</Button>
|
||||
)}
|
||||
{showCancelButton && (
|
||||
<Button variant="outline" onClick={handleCancel} className="border-orange-200 text-orange-600 hover:border-orange-300">
|
||||
<XCircle className="h-4 w-4 mr-2" />
|
||||
취소
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
}
|
||||
/>
|
||||
|
||||
<div className="space-y-6">
|
||||
{/* 수주 정보 헤더 */}
|
||||
<Card>
|
||||
@@ -790,6 +694,85 @@ export default function OrderDetailPage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
</div>
|
||||
);
|
||||
}, [order, expandedProducts, expandAllProducts, collapseAllProducts, toggleProduct, getItemsForProduct, getUnmatchedItems, openDocumentModal]);
|
||||
|
||||
// 커스텀 헤더 액션 (상태별 버튼)
|
||||
const renderHeaderActions = useCallback(() => {
|
||||
if (!order) return null;
|
||||
|
||||
// 상태별 버튼 표시 여부
|
||||
const showEditButton = order.status !== "shipped" && order.status !== "cancelled";
|
||||
const showConfirmButton = order.status === "order_registered";
|
||||
const showProductionCreateButton = order.status === "order_confirmed";
|
||||
const showProductionViewButton = false;
|
||||
const showRevertButton = order.status === "production_ordered";
|
||||
const showRevertConfirmButton = order.status === "order_confirmed";
|
||||
const showCancelButton =
|
||||
order.status !== "shipped" &&
|
||||
order.status !== "cancelled" &&
|
||||
order.status !== "production_ordered";
|
||||
|
||||
return (
|
||||
<div className="flex items-center gap-2 flex-wrap">
|
||||
{showEditButton && (
|
||||
<Button variant="outline" onClick={handleEdit}>
|
||||
<Edit className="h-4 w-4 mr-2" />
|
||||
수정
|
||||
</Button>
|
||||
)}
|
||||
{showConfirmButton && (
|
||||
<Button onClick={handleConfirmOrder} className="bg-green-600 hover:bg-green-700">
|
||||
<CheckCircle2 className="h-4 w-4 mr-2" />
|
||||
수주 확정
|
||||
</Button>
|
||||
)}
|
||||
{showProductionCreateButton && (
|
||||
<Button onClick={handleProductionOrder}>
|
||||
<Factory className="h-4 w-4 mr-2" />
|
||||
생산지시 생성
|
||||
</Button>
|
||||
)}
|
||||
{showProductionViewButton && (
|
||||
<Button onClick={handleViewProductionOrder}>
|
||||
<Eye className="h-4 w-4 mr-2" />
|
||||
생산지시 보기
|
||||
</Button>
|
||||
)}
|
||||
{showRevertButton && (
|
||||
<Button variant="outline" onClick={handleRevertProduction} className="border-amber-200 text-amber-600 hover:border-amber-300 hover:bg-amber-50">
|
||||
<RotateCcw className="h-4 w-4 mr-2" />
|
||||
생산지시 되돌리기
|
||||
</Button>
|
||||
)}
|
||||
{showRevertConfirmButton && (
|
||||
<Button variant="outline" onClick={handleRevertConfirmation} className="border-slate-300 text-slate-600 hover:border-slate-400 hover:bg-slate-50">
|
||||
<RotateCcw className="h-4 w-4 mr-2" />
|
||||
수주확정 되돌리기
|
||||
</Button>
|
||||
)}
|
||||
{showCancelButton && (
|
||||
<Button variant="outline" onClick={handleCancel} className="border-orange-200 text-orange-600 hover:border-orange-300">
|
||||
<XCircle className="h-4 w-4 mr-2" />
|
||||
취소
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
);
|
||||
}, [order, handleEdit, handleConfirmOrder, handleProductionOrder, handleViewProductionOrder, handleRevertProduction, handleRevertConfirmation, handleCancel]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<IntegratedDetailTemplate
|
||||
config={orderSalesConfig}
|
||||
mode="view"
|
||||
initialData={order}
|
||||
itemId={orderId}
|
||||
isLoading={loading}
|
||||
onBack={handleBack}
|
||||
renderView={renderViewContent}
|
||||
headerActions={renderHeaderActions()}
|
||||
/>
|
||||
|
||||
{/* 문서 모달 */}
|
||||
<OrderDocumentModal
|
||||
@@ -1114,6 +1097,6 @@ export default function OrderDetailPage() {
|
||||
</DialogFooter>
|
||||
</DialogContent>
|
||||
</Dialog>
|
||||
</PageLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
import { useState, useCallback, useMemo, useRef, useEffect } from 'react';
|
||||
import { useRouter } from 'next/navigation';
|
||||
import { FileText, Loader2, List } from 'lucide-react';
|
||||
import { Loader2 } from 'lucide-react';
|
||||
import { getExpenseItemOptions, updateEstimate, type ExpenseItemOption } from './actions';
|
||||
import { createBiddingFromEstimate } from '../bidding/actions';
|
||||
import { useAuth } from '@/contexts/AuthContext';
|
||||
@@ -17,8 +17,8 @@ import {
|
||||
AlertDialogHeader,
|
||||
AlertDialogTitle,
|
||||
} from '@/components/ui/alert-dialog';
|
||||
import { PageLayout } from '@/components/organisms/PageLayout';
|
||||
import { PageHeader } from '@/components/organisms/PageHeader';
|
||||
import { IntegratedDetailTemplate } from '@/components/templates/IntegratedDetailTemplate';
|
||||
import { estimateConfig } from './estimateConfig';
|
||||
import { toast } from 'sonner';
|
||||
import type {
|
||||
EstimateDetail,
|
||||
@@ -106,9 +106,6 @@ export default function EstimateDetailForm({
|
||||
controller: number;
|
||||
} | null>(null);
|
||||
|
||||
// 조정단가 적용 여부 (전체 적용 버튼 클릭 시에만 true)
|
||||
const useAdjustedPrice = appliedPrices !== null;
|
||||
|
||||
// ===== 네비게이션 핸들러 =====
|
||||
const handleBack = useCallback(() => {
|
||||
router.push('/ko/construction/project/bidding/estimates');
|
||||
@@ -118,10 +115,6 @@ export default function EstimateDetailForm({
|
||||
router.push(`/ko/construction/project/bidding/estimates/${estimateId}/edit`);
|
||||
}, [router, estimateId]);
|
||||
|
||||
const handleCancel = useCallback(() => {
|
||||
router.push(`/ko/construction/project/bidding/estimates/${estimateId}`);
|
||||
}, [router, estimateId]);
|
||||
|
||||
// ===== 저장/삭제 핸들러 =====
|
||||
const handleSave = useCallback(() => {
|
||||
setShowSaveDialog(true);
|
||||
@@ -622,17 +615,8 @@ export default function EstimateDetailForm({
|
||||
[isViewMode]
|
||||
);
|
||||
|
||||
// ===== 타이틀 및 설명 =====
|
||||
const pageTitle = useMemo(() => {
|
||||
return isEditMode ? '견적 수정' : '견적 상세';
|
||||
}, [isEditMode]);
|
||||
|
||||
const pageDescription = useMemo(() => {
|
||||
return isEditMode ? '견적 정보를 수정합니다' : '견적 정보를 등록하고 관리합니다';
|
||||
}, [isEditMode]);
|
||||
|
||||
// ===== 헤더 버튼 =====
|
||||
const headerActions = useMemo(() => {
|
||||
const renderHeaderActions = useCallback(() => {
|
||||
if (isViewMode) {
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
@@ -645,18 +629,11 @@ export default function EstimateDetailForm({
|
||||
<Button variant="outline" onClick={handleRegisterBidding} className="text-green-600 border-green-200 hover:bg-green-50">
|
||||
입찰 등록
|
||||
</Button>
|
||||
<Button onClick={handleEdit} className="bg-blue-500 hover:bg-blue-600">
|
||||
수정
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
return (
|
||||
<div className="flex gap-2">
|
||||
<Button variant="outline" onClick={handleBack}>
|
||||
<List className="h-4 w-4 mr-2" />
|
||||
목록
|
||||
</Button>
|
||||
<Button
|
||||
variant="outline"
|
||||
className="text-red-500 border-red-200 hover:bg-red-50"
|
||||
@@ -670,18 +647,11 @@ export default function EstimateDetailForm({
|
||||
</Button>
|
||||
</div>
|
||||
);
|
||||
}, [isViewMode, isLoading, handleBack, handleEdit, handleDelete, handleSave, handleRegisterBidding]);
|
||||
|
||||
return (
|
||||
<PageLayout>
|
||||
<PageHeader
|
||||
title={pageTitle}
|
||||
description={pageDescription}
|
||||
icon={FileText}
|
||||
actions={headerActions}
|
||||
onBack={handleBack}
|
||||
/>
|
||||
}, [isViewMode, isLoading, handleDelete, handleSave, handleRegisterBidding]);
|
||||
|
||||
// ===== 컨텐츠 렌더링 =====
|
||||
const renderContent = useCallback(() => {
|
||||
return (
|
||||
<div className="space-y-8">
|
||||
{/* 견적 정보 + 현장설명회 + 입찰 정보 */}
|
||||
<EstimateInfoSection
|
||||
@@ -746,6 +716,69 @@ export default function EstimateDetailForm({
|
||||
onReset={handleDetailReset}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}, [
|
||||
formData,
|
||||
isViewMode,
|
||||
isDragging,
|
||||
documentInputRef,
|
||||
expenseOptions,
|
||||
appliedPrices,
|
||||
handleBidInfoChange,
|
||||
handleDocumentUpload,
|
||||
handleDocumentRemove,
|
||||
handleDragOver,
|
||||
handleDragLeave,
|
||||
handleDrop,
|
||||
handleAddSummaryItem,
|
||||
handleRemoveSummaryItem,
|
||||
handleSummaryItemChange,
|
||||
handleSummaryMemoChange,
|
||||
handleAddExpenseItems,
|
||||
handleRemoveSelectedExpenseItems,
|
||||
handleExpenseItemChange,
|
||||
handleExpenseSelectItem,
|
||||
handleExpenseSelectAll,
|
||||
handlePriceAdjustmentChange,
|
||||
handlePriceAdjustmentSave,
|
||||
handlePriceAdjustmentApplyAll,
|
||||
handlePriceAdjustmentReset,
|
||||
handleAddDetailItems,
|
||||
handleRemoveDetailItem,
|
||||
handleRemoveSelectedDetailItems,
|
||||
handleDetailItemChange,
|
||||
handleDetailSelectItem,
|
||||
handleDetailSelectAll,
|
||||
handleApplyAdjustedPriceToSelected,
|
||||
handleDetailReset,
|
||||
]);
|
||||
|
||||
// Edit 모드용 config (타이틀 변경)
|
||||
const currentConfig = useMemo(() => {
|
||||
if (isEditMode) {
|
||||
return {
|
||||
...estimateConfig,
|
||||
title: '견적 수정',
|
||||
description: '견적 정보를 수정합니다',
|
||||
};
|
||||
}
|
||||
return estimateConfig;
|
||||
}, [isEditMode]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<IntegratedDetailTemplate
|
||||
config={currentConfig}
|
||||
mode={mode}
|
||||
initialData={formData}
|
||||
itemId={estimateId}
|
||||
isLoading={false}
|
||||
onBack={handleBack}
|
||||
onEdit={handleEdit}
|
||||
renderView={renderContent}
|
||||
renderForm={renderContent}
|
||||
headerActions={renderHeaderActions()}
|
||||
/>
|
||||
|
||||
{/* 전자결재 모달 */}
|
||||
<ElectronicApprovalModal
|
||||
@@ -839,6 +872,6 @@ export default function EstimateDetailForm({
|
||||
</AlertDialogFooter>
|
||||
</AlertDialogContent>
|
||||
</AlertDialog>
|
||||
</PageLayout>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user