573 lines
23 KiB
TypeScript
573 lines
23 KiB
TypeScript
"use client";
|
||
|
||
import React, { useState } from "react";
|
||
import {
|
||
Dialog,
|
||
DialogContent,
|
||
DialogDescription,
|
||
DialogFooter,
|
||
DialogHeader,
|
||
DialogTitle,
|
||
} from "@/components/ui/dialog";
|
||
import { Button } from "@/components/ui/button";
|
||
import { Label } from "@/components/ui/label";
|
||
import {
|
||
Select,
|
||
SelectContent,
|
||
SelectItem,
|
||
SelectTrigger,
|
||
SelectValue,
|
||
} from "@/components/ui/select";
|
||
import { OrderCustomerSearch } from "./OrderCustomerSearch";
|
||
import { OrderItemRepeaterTable } from "./OrderItemRepeaterTable";
|
||
import { toast } from "sonner";
|
||
import { apiClient } from "@/lib/api/client";
|
||
|
||
interface OrderRegistrationModalProps {
|
||
open: boolean;
|
||
onOpenChange: (open: boolean) => void;
|
||
onSuccess?: () => void;
|
||
}
|
||
|
||
export function OrderRegistrationModal({
|
||
open,
|
||
onOpenChange,
|
||
onSuccess,
|
||
}: OrderRegistrationModalProps) {
|
||
// 입력 방식
|
||
const [inputMode, setInputMode] = useState<string>("customer_first");
|
||
|
||
// 판매 유형 (국내/해외)
|
||
const [salesType, setSalesType] = useState<string>("domestic");
|
||
|
||
// 단가 기준 (기준단가/거래처별단가)
|
||
const [priceType, setPriceType] = useState<string>("standard");
|
||
|
||
// 폼 데이터
|
||
const [formData, setFormData] = useState<any>({
|
||
customerCode: "",
|
||
customerName: "",
|
||
contactPerson: "",
|
||
deliveryDestination: "",
|
||
deliveryAddress: "",
|
||
deliveryDate: "",
|
||
memo: "",
|
||
// 무역 정보 (해외 판매 시)
|
||
incoterms: "",
|
||
paymentTerms: "",
|
||
currency: "KRW",
|
||
portOfLoading: "",
|
||
portOfDischarge: "",
|
||
hsCode: "",
|
||
});
|
||
|
||
// 선택된 품목 목록
|
||
const [selectedItems, setSelectedItems] = useState<any[]>([]);
|
||
|
||
// 납기일 일괄 적용 플래그 (딱 한 번만 실행)
|
||
const [isDeliveryDateApplied, setIsDeliveryDateApplied] = useState(false);
|
||
|
||
// 저장 중
|
||
const [isSaving, setIsSaving] = useState(false);
|
||
|
||
// 저장 처리
|
||
const handleSave = async () => {
|
||
try {
|
||
// 유효성 검사
|
||
if (!formData.customerCode) {
|
||
toast.error("거래처를 선택해주세요");
|
||
return;
|
||
}
|
||
|
||
if (selectedItems.length === 0) {
|
||
toast.error("품목을 추가해주세요");
|
||
return;
|
||
}
|
||
|
||
setIsSaving(true);
|
||
|
||
// 수주 등록 API 호출
|
||
const orderData: any = {
|
||
inputMode,
|
||
salesType,
|
||
priceType,
|
||
customerCode: formData.customerCode,
|
||
contactPerson: formData.contactPerson,
|
||
deliveryDestination: formData.deliveryDestination,
|
||
deliveryAddress: formData.deliveryAddress,
|
||
deliveryDate: formData.deliveryDate,
|
||
items: selectedItems,
|
||
memo: formData.memo,
|
||
};
|
||
|
||
// 해외 판매 시 무역 정보 추가
|
||
if (salesType === "export") {
|
||
orderData.tradeInfo = {
|
||
incoterms: formData.incoterms,
|
||
paymentTerms: formData.paymentTerms,
|
||
currency: formData.currency,
|
||
portOfLoading: formData.portOfLoading,
|
||
portOfDischarge: formData.portOfDischarge,
|
||
hsCode: formData.hsCode,
|
||
};
|
||
}
|
||
|
||
const response = await apiClient.post("/orders", orderData);
|
||
|
||
if (response.data.success) {
|
||
toast.success("수주가 등록되었습니다");
|
||
onOpenChange(false);
|
||
onSuccess?.();
|
||
|
||
// 폼 초기화
|
||
resetForm();
|
||
} else {
|
||
toast.error(response.data.message || "수주 등록에 실패했습니다");
|
||
}
|
||
} catch (error: any) {
|
||
console.error("수주 등록 오류:", error);
|
||
toast.error(
|
||
error.response?.data?.message || "수주 등록 중 오류가 발생했습니다"
|
||
);
|
||
} finally {
|
||
setIsSaving(false);
|
||
}
|
||
};
|
||
|
||
// 취소 처리
|
||
const handleCancel = () => {
|
||
onOpenChange(false);
|
||
resetForm();
|
||
};
|
||
|
||
// 폼 초기화
|
||
const resetForm = () => {
|
||
setInputMode("customer_first");
|
||
setSalesType("domestic");
|
||
setPriceType("standard");
|
||
setFormData({
|
||
customerCode: "",
|
||
customerName: "",
|
||
contactPerson: "",
|
||
deliveryDestination: "",
|
||
deliveryAddress: "",
|
||
deliveryDate: "",
|
||
memo: "",
|
||
incoterms: "",
|
||
paymentTerms: "",
|
||
currency: "KRW",
|
||
portOfLoading: "",
|
||
portOfDischarge: "",
|
||
hsCode: "",
|
||
});
|
||
setSelectedItems([]);
|
||
setIsDeliveryDateApplied(false); // 플래그 초기화
|
||
};
|
||
|
||
// 품목 목록 변경 핸들러 (납기일 일괄 적용 로직 포함)
|
||
const handleItemsChange = (newItems: any[]) => {
|
||
// 1️⃣ 플래그가 이미 true면 그냥 업데이트만 (일괄 적용 완료 상태)
|
||
if (isDeliveryDateApplied) {
|
||
setSelectedItems(newItems);
|
||
return;
|
||
}
|
||
|
||
// 2️⃣ 품목이 없으면 그냥 업데이트
|
||
if (newItems.length === 0) {
|
||
setSelectedItems(newItems);
|
||
return;
|
||
}
|
||
|
||
// 3️⃣ 현재 상태: 납기일이 있는 행과 없는 행 개수 체크
|
||
const itemsWithDate = newItems.filter((item) => item.delivery_date);
|
||
const itemsWithoutDate = newItems.filter((item) => !item.delivery_date);
|
||
|
||
// 4️⃣ 조건: 정확히 1개만 날짜가 있고, 나머지는 모두 비어있을 때 일괄 적용
|
||
if (itemsWithDate.length === 1 && itemsWithoutDate.length > 0) {
|
||
// 5️⃣ 전체 일괄 적용
|
||
const selectedDate = itemsWithDate[0].delivery_date;
|
||
const updatedItems = newItems.map((item) => ({
|
||
...item,
|
||
delivery_date: selectedDate, // 모든 행에 동일한 납기일 적용
|
||
}));
|
||
|
||
setSelectedItems(updatedItems);
|
||
setIsDeliveryDateApplied(true); // 플래그 활성화 (다음부터는 일괄 적용 안 함)
|
||
|
||
console.log("✅ 납기일 일괄 적용 완료:", selectedDate);
|
||
console.log(` - 대상: ${itemsWithoutDate.length}개 행에 ${selectedDate} 적용`);
|
||
} else {
|
||
// 그냥 업데이트
|
||
setSelectedItems(newItems);
|
||
}
|
||
};
|
||
|
||
// 전체 금액 계산
|
||
const totalAmount = selectedItems.reduce(
|
||
(sum, item) => sum + (item.amount || 0),
|
||
0
|
||
);
|
||
|
||
return (
|
||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||
<DialogContent className="max-w-[95vw] sm:max-w-[1200px] max-h-[90vh] overflow-hidden">
|
||
<DialogHeader>
|
||
<DialogTitle className="text-base sm:text-lg">수주 등록</DialogTitle>
|
||
<DialogDescription className="text-xs sm:text-sm">
|
||
새로운 수주를 등록합니다
|
||
</DialogDescription>
|
||
</DialogHeader>
|
||
|
||
<div className="space-y-6">
|
||
{/* 상단 셀렉트 박스 3개 */}
|
||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||
{/* 입력 방식 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="inputMode" className="text-xs sm:text-sm flex items-center gap-1">
|
||
<span className="text-amber-500">📝</span> 입력 방식
|
||
</Label>
|
||
<Select value={inputMode} onValueChange={setInputMode}>
|
||
<SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm">
|
||
<SelectValue placeholder="입력 방식 선택" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="customer_first">거래처 우선</SelectItem>
|
||
<SelectItem value="quotation">견대 방식</SelectItem>
|
||
<SelectItem value="unit_price">단가 방식</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
{/* 판매 유형 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="salesType" className="text-xs sm:text-sm flex items-center gap-1">
|
||
<span className="text-blue-500">🌏</span> 판매 유형
|
||
</Label>
|
||
<Select value={salesType} onValueChange={setSalesType}>
|
||
<SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm">
|
||
<SelectValue placeholder="판매 유형 선택" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="domestic">국내 판매</SelectItem>
|
||
<SelectItem value="export">해외 판매</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
{/* 단가 기준 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="priceType" className="text-xs sm:text-sm flex items-center gap-1">
|
||
<span className="text-green-500">💰</span> 단가 방식
|
||
</Label>
|
||
<Select value={priceType} onValueChange={setPriceType}>
|
||
<SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm">
|
||
<SelectValue placeholder="단가 방식 선택" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="standard">기준 단가</SelectItem>
|
||
<SelectItem value="customer">거래처별 단가</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
|
||
{/* 거래처 정보 (항상 표시) */}
|
||
{inputMode === "customer_first" && (
|
||
<div className="rounded-lg border border-gray-200 bg-gray-50/50 p-4 space-y-4">
|
||
<div className="flex items-center gap-2 text-sm font-semibold text-gray-700">
|
||
<span>🏢</span>
|
||
<span>거래처 정보</span>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||
{/* 거래처 */}
|
||
<div className="space-y-2">
|
||
<Label className="text-xs sm:text-sm">거래처 *</Label>
|
||
<OrderCustomerSearch
|
||
value={formData.customerCode}
|
||
onChange={(code, fullData) => {
|
||
setFormData({
|
||
...formData,
|
||
customerCode: code || "",
|
||
customerName: fullData?.customer_name || "",
|
||
});
|
||
}}
|
||
/>
|
||
</div>
|
||
|
||
{/* 담당자 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="contactPerson" className="text-xs sm:text-sm">
|
||
담당자
|
||
</Label>
|
||
<input
|
||
type="text"
|
||
id="contactPerson"
|
||
placeholder="담당자"
|
||
value={formData.contactPerson}
|
||
onChange={(e) =>
|
||
setFormData({ ...formData, contactPerson: e.target.value })
|
||
}
|
||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||
/>
|
||
</div>
|
||
|
||
{/* 납품처 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="deliveryDestination" className="text-xs sm:text-sm">
|
||
납품처
|
||
</Label>
|
||
<input
|
||
type="text"
|
||
id="deliveryDestination"
|
||
placeholder="납품처"
|
||
value={formData.deliveryDestination}
|
||
onChange={(e) =>
|
||
setFormData({ ...formData, deliveryDestination: e.target.value })
|
||
}
|
||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||
/>
|
||
</div>
|
||
|
||
{/* 납품장소 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="deliveryAddress" className="text-xs sm:text-sm">
|
||
납품장소
|
||
</Label>
|
||
<input
|
||
type="text"
|
||
id="deliveryAddress"
|
||
placeholder="납품장소"
|
||
value={formData.deliveryAddress}
|
||
onChange={(e) =>
|
||
setFormData({ ...formData, deliveryAddress: e.target.value })
|
||
}
|
||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{inputMode === "quotation" && (
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label className="text-xs sm:text-sm">견대 번호 *</Label>
|
||
<input
|
||
type="text"
|
||
placeholder="견대 번호를 입력하세요"
|
||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{inputMode === "unit_price" && (
|
||
<div className="grid grid-cols-1 sm:grid-cols-2 gap-4">
|
||
<div className="space-y-2">
|
||
<Label className="text-xs sm:text-sm">단가 방식 설정</Label>
|
||
<input
|
||
type="text"
|
||
placeholder="단가 정보 입력"
|
||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* 추가된 품목 */}
|
||
<div className="space-y-2">
|
||
<Label className="text-xs sm:text-sm">추가된 품목</Label>
|
||
<OrderItemRepeaterTable
|
||
value={selectedItems}
|
||
onChange={handleItemsChange}
|
||
/>
|
||
</div>
|
||
|
||
{/* 전체 금액 표시 */}
|
||
{selectedItems.length > 0 && (
|
||
<div className="flex justify-end">
|
||
<div className="text-sm sm:text-base font-semibold">
|
||
전체 금액: {totalAmount.toLocaleString()}원
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* 무역 정보 (해외 판매 시에만 표시) */}
|
||
{salesType === "export" && (
|
||
<div className="rounded-lg border border-blue-200 bg-blue-50/50 p-4 space-y-4">
|
||
<div className="flex items-center gap-2 text-sm font-semibold text-blue-700">
|
||
<span>🌏</span>
|
||
<span>무역 정보</span>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||
{/* 인코텀즈 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="incoterms" className="text-xs sm:text-sm">
|
||
인코텀즈
|
||
</Label>
|
||
<Select
|
||
value={formData.incoterms}
|
||
onValueChange={(value) =>
|
||
setFormData({ ...formData, incoterms: value })
|
||
}
|
||
>
|
||
<SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm">
|
||
<SelectValue placeholder="선택" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="EXW">EXW</SelectItem>
|
||
<SelectItem value="FOB">FOB</SelectItem>
|
||
<SelectItem value="CIF">CIF</SelectItem>
|
||
<SelectItem value="DDP">DDP</SelectItem>
|
||
<SelectItem value="DAP">DAP</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
{/* 결제 조건 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="paymentTerms" className="text-xs sm:text-sm">
|
||
결제 조건
|
||
</Label>
|
||
<Select
|
||
value={formData.paymentTerms}
|
||
onValueChange={(value) =>
|
||
setFormData({ ...formData, paymentTerms: value })
|
||
}
|
||
>
|
||
<SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm">
|
||
<SelectValue placeholder="선택" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="advance">선결제</SelectItem>
|
||
<SelectItem value="cod">착불</SelectItem>
|
||
<SelectItem value="lc">신용장(L/C)</SelectItem>
|
||
<SelectItem value="net30">NET 30</SelectItem>
|
||
<SelectItem value="net60">NET 60</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
|
||
{/* 통화 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="currency" className="text-xs sm:text-sm">
|
||
통화
|
||
</Label>
|
||
<Select
|
||
value={formData.currency}
|
||
onValueChange={(value) =>
|
||
setFormData({ ...formData, currency: value })
|
||
}
|
||
>
|
||
<SelectTrigger className="h-8 text-xs sm:h-10 sm:text-sm">
|
||
<SelectValue placeholder="통화 선택" />
|
||
</SelectTrigger>
|
||
<SelectContent>
|
||
<SelectItem value="KRW">KRW (원)</SelectItem>
|
||
<SelectItem value="USD">USD (달러)</SelectItem>
|
||
<SelectItem value="EUR">EUR (유로)</SelectItem>
|
||
<SelectItem value="JPY">JPY (엔)</SelectItem>
|
||
<SelectItem value="CNY">CNY (위안)</SelectItem>
|
||
</SelectContent>
|
||
</Select>
|
||
</div>
|
||
</div>
|
||
|
||
<div className="grid grid-cols-1 sm:grid-cols-3 gap-4">
|
||
{/* 선적항 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="portOfLoading" className="text-xs sm:text-sm">
|
||
선적항
|
||
</Label>
|
||
<input
|
||
type="text"
|
||
id="portOfLoading"
|
||
placeholder="선적항"
|
||
value={formData.portOfLoading}
|
||
onChange={(e) =>
|
||
setFormData({ ...formData, portOfLoading: e.target.value })
|
||
}
|
||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||
/>
|
||
</div>
|
||
|
||
{/* 도착항 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="portOfDischarge" className="text-xs sm:text-sm">
|
||
도착항
|
||
</Label>
|
||
<input
|
||
type="text"
|
||
id="portOfDischarge"
|
||
placeholder="도착항"
|
||
value={formData.portOfDischarge}
|
||
onChange={(e) =>
|
||
setFormData({ ...formData, portOfDischarge: e.target.value })
|
||
}
|
||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||
/>
|
||
</div>
|
||
|
||
{/* HS Code */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="hsCode" className="text-xs sm:text-sm">
|
||
HS Code
|
||
</Label>
|
||
<input
|
||
type="text"
|
||
id="hsCode"
|
||
placeholder="HS Code"
|
||
value={formData.hsCode}
|
||
onChange={(e) =>
|
||
setFormData({ ...formData, hsCode: e.target.value })
|
||
}
|
||
className="flex h-8 w-full rounded-md border border-input bg-background px-3 py-2 text-xs ring-offset-background file:border-0 file:bg-transparent file:text-sm file:font-medium placeholder:text-muted-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 disabled:cursor-not-allowed disabled:opacity-50 sm:h-10 sm:text-sm"
|
||
/>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
)}
|
||
|
||
{/* 메모 */}
|
||
<div className="space-y-2">
|
||
<Label htmlFor="memo" className="text-xs sm:text-sm">
|
||
메모
|
||
</Label>
|
||
<textarea
|
||
id="memo"
|
||
placeholder="메모를 입력하세요"
|
||
value={formData.memo}
|
||
onChange={(e) =>
|
||
setFormData({ ...formData, memo: e.target.value })
|
||
}
|
||
className="border-input bg-background ring-offset-background placeholder:text-muted-foreground focus-visible:ring-ring flex min-h-[80px] w-full rounded-md border px-3 py-2 text-sm focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50"
|
||
rows={3}
|
||
/>
|
||
</div>
|
||
</div>
|
||
|
||
<DialogFooter className="gap-2 sm:gap-0">
|
||
<Button
|
||
variant="outline"
|
||
onClick={handleCancel}
|
||
disabled={isSaving}
|
||
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
|
||
>
|
||
취소
|
||
</Button>
|
||
<Button
|
||
onClick={handleSave}
|
||
disabled={isSaving}
|
||
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
|
||
>
|
||
{isSaving ? "저장 중..." : "저장"}
|
||
</Button>
|
||
</DialogFooter>
|
||
</DialogContent>
|
||
</Dialog>
|
||
);
|
||
}
|
||
|