diff --git a/frontend/app/(main)/COMPANY_10/mold/info/page.tsx b/frontend/app/(main)/COMPANY_10/mold/info/page.tsx index dcd92eac..126c803d 100644 --- a/frontend/app/(main)/COMPANY_10/mold/info/page.tsx +++ b/frontend/app/(main)/COMPANY_10/mold/info/page.tsx @@ -26,6 +26,7 @@ import { import { cn } from "@/lib/utils"; import { apiClient } from "@/lib/api/client"; import { previewNumberingCode, allocateNumberingCode } from "@/lib/api/numberingRule"; +import { ImageUpload } from "@/components/common/ImageUpload"; import { useAuth } from "@/hooks/useAuth"; import { toast } from "sonner"; import { useConfirmDialog } from "@/components/common/ConfirmDialog"; @@ -102,8 +103,8 @@ export default function MoldInfoPage() { const [numberingRuleId, setNumberingRuleId] = useState(null); const [previewCode, setPreviewCode] = useState(null); const [saving, setSaving] = useState(false); + // moldImagePreview는 상세 표시용으로 유지 (ImageUpload는 모달에서만 사용) const [moldImagePreview, setMoldImagePreview] = useState(null); - const moldImageRef = React.useRef(null); const [serialModalOpen, setSerialModalOpen] = useState(false); const [serialForm, setSerialForm] = useState>({}); @@ -240,17 +241,7 @@ export default function MoldInfoPage() { setMoldModalOpen(true); }; - const handleMoldImageUpload = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - const reader = new FileReader(); - reader.onloadend = () => { - const result = reader.result as string; - setMoldImagePreview(result); - setMoldForm((prev) => ({ ...prev, image_path: result })); - }; - reader.readAsDataURL(file); - }; + // 이미지 업로드는 ImageUpload 컴포넌트가 처리 → objid를 image_path에 저장 const handleSaveMold = async () => { // 등록 모드에서 채번이 없으면 수동 입력 필수 @@ -460,9 +451,10 @@ export default function MoldInfoPage() { )}> {mold.image_path ? ( {mold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -662,9 +654,10 @@ export default function MoldInfoPage() {
{selectedMold.image_path ? ( {selectedMold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -1143,39 +1136,13 @@ export default function MoldInfoPage() {
-
- {moldImagePreview ? ( - <> - 금형 이미지 -
- - -
- - ) : ( - - )} -
- setMoldForm((prev) => ({ ...prev, image_path: v }))} + tableName="mold_mng" + recordId={moldForm.id || ""} + columnName="image_path" + height="h-32" />
diff --git a/frontend/app/(main)/COMPANY_10/outsourcing/subcontractor/page.tsx b/frontend/app/(main)/COMPANY_10/outsourcing/subcontractor/page.tsx index d649ab56..46b78a03 100644 --- a/frontend/app/(main)/COMPANY_10/outsourcing/subcontractor/page.tsx +++ b/frontend/app/(main)/COMPANY_10/outsourcing/subcontractor/page.tsx @@ -141,10 +141,12 @@ export default function SubcontractorManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -1181,8 +1183,8 @@ export default function SubcontractorManagementPage() { {item.item_number} {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -1226,7 +1228,7 @@ export default function SubcontractorManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_10/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_10/purchase/supplier/page.tsx index 4ae229ab..eb9bd977 100644 --- a/frontend/app/(main)/COMPANY_10/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_10/purchase/supplier/page.tsx @@ -195,10 +195,12 @@ export default function SupplierManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2435,8 +2437,8 @@ export default function SupplierManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2478,7 +2480,7 @@ export default function SupplierManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_10/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_10/sales/customer/page.tsx index 96e2512c..57897a8a 100644 --- a/frontend/app/(main)/COMPANY_10/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_10/sales/customer/page.tsx @@ -195,10 +195,12 @@ export default function CustomerManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2438,8 +2440,8 @@ export default function CustomerManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2481,7 +2483,7 @@ export default function CustomerManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_16/mold/info/page.tsx b/frontend/app/(main)/COMPANY_16/mold/info/page.tsx index dcd92eac..126c803d 100644 --- a/frontend/app/(main)/COMPANY_16/mold/info/page.tsx +++ b/frontend/app/(main)/COMPANY_16/mold/info/page.tsx @@ -26,6 +26,7 @@ import { import { cn } from "@/lib/utils"; import { apiClient } from "@/lib/api/client"; import { previewNumberingCode, allocateNumberingCode } from "@/lib/api/numberingRule"; +import { ImageUpload } from "@/components/common/ImageUpload"; import { useAuth } from "@/hooks/useAuth"; import { toast } from "sonner"; import { useConfirmDialog } from "@/components/common/ConfirmDialog"; @@ -102,8 +103,8 @@ export default function MoldInfoPage() { const [numberingRuleId, setNumberingRuleId] = useState(null); const [previewCode, setPreviewCode] = useState(null); const [saving, setSaving] = useState(false); + // moldImagePreview는 상세 표시용으로 유지 (ImageUpload는 모달에서만 사용) const [moldImagePreview, setMoldImagePreview] = useState(null); - const moldImageRef = React.useRef(null); const [serialModalOpen, setSerialModalOpen] = useState(false); const [serialForm, setSerialForm] = useState>({}); @@ -240,17 +241,7 @@ export default function MoldInfoPage() { setMoldModalOpen(true); }; - const handleMoldImageUpload = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - const reader = new FileReader(); - reader.onloadend = () => { - const result = reader.result as string; - setMoldImagePreview(result); - setMoldForm((prev) => ({ ...prev, image_path: result })); - }; - reader.readAsDataURL(file); - }; + // 이미지 업로드는 ImageUpload 컴포넌트가 처리 → objid를 image_path에 저장 const handleSaveMold = async () => { // 등록 모드에서 채번이 없으면 수동 입력 필수 @@ -460,9 +451,10 @@ export default function MoldInfoPage() { )}> {mold.image_path ? ( {mold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -662,9 +654,10 @@ export default function MoldInfoPage() {
{selectedMold.image_path ? ( {selectedMold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -1143,39 +1136,13 @@ export default function MoldInfoPage() {
-
- {moldImagePreview ? ( - <> - 금형 이미지 -
- - -
- - ) : ( - - )} -
- setMoldForm((prev) => ({ ...prev, image_path: v }))} + tableName="mold_mng" + recordId={moldForm.id || ""} + columnName="image_path" + height="h-32" />
diff --git a/frontend/app/(main)/COMPANY_16/outsourcing/subcontractor/page.tsx b/frontend/app/(main)/COMPANY_16/outsourcing/subcontractor/page.tsx index d649ab56..46b78a03 100644 --- a/frontend/app/(main)/COMPANY_16/outsourcing/subcontractor/page.tsx +++ b/frontend/app/(main)/COMPANY_16/outsourcing/subcontractor/page.tsx @@ -141,10 +141,12 @@ export default function SubcontractorManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -1181,8 +1183,8 @@ export default function SubcontractorManagementPage() { {item.item_number} {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -1226,7 +1228,7 @@ export default function SubcontractorManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_16/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_16/purchase/supplier/page.tsx index b4dc6be0..a6453061 100644 --- a/frontend/app/(main)/COMPANY_16/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_16/purchase/supplier/page.tsx @@ -195,10 +195,12 @@ export default function SupplierManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2469,8 +2471,8 @@ export default function SupplierManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2512,7 +2514,7 @@ export default function SupplierManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_16/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_16/sales/customer/page.tsx index 5ae6fc77..4e7bdbbf 100644 --- a/frontend/app/(main)/COMPANY_16/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_16/sales/customer/page.tsx @@ -195,10 +195,12 @@ export default function CustomerManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2487,8 +2489,8 @@ export default function CustomerManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2530,7 +2532,7 @@ export default function CustomerManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_29/mold/info/page.tsx b/frontend/app/(main)/COMPANY_29/mold/info/page.tsx index dcd92eac..126c803d 100644 --- a/frontend/app/(main)/COMPANY_29/mold/info/page.tsx +++ b/frontend/app/(main)/COMPANY_29/mold/info/page.tsx @@ -26,6 +26,7 @@ import { import { cn } from "@/lib/utils"; import { apiClient } from "@/lib/api/client"; import { previewNumberingCode, allocateNumberingCode } from "@/lib/api/numberingRule"; +import { ImageUpload } from "@/components/common/ImageUpload"; import { useAuth } from "@/hooks/useAuth"; import { toast } from "sonner"; import { useConfirmDialog } from "@/components/common/ConfirmDialog"; @@ -102,8 +103,8 @@ export default function MoldInfoPage() { const [numberingRuleId, setNumberingRuleId] = useState(null); const [previewCode, setPreviewCode] = useState(null); const [saving, setSaving] = useState(false); + // moldImagePreview는 상세 표시용으로 유지 (ImageUpload는 모달에서만 사용) const [moldImagePreview, setMoldImagePreview] = useState(null); - const moldImageRef = React.useRef(null); const [serialModalOpen, setSerialModalOpen] = useState(false); const [serialForm, setSerialForm] = useState>({}); @@ -240,17 +241,7 @@ export default function MoldInfoPage() { setMoldModalOpen(true); }; - const handleMoldImageUpload = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - const reader = new FileReader(); - reader.onloadend = () => { - const result = reader.result as string; - setMoldImagePreview(result); - setMoldForm((prev) => ({ ...prev, image_path: result })); - }; - reader.readAsDataURL(file); - }; + // 이미지 업로드는 ImageUpload 컴포넌트가 처리 → objid를 image_path에 저장 const handleSaveMold = async () => { // 등록 모드에서 채번이 없으면 수동 입력 필수 @@ -460,9 +451,10 @@ export default function MoldInfoPage() { )}> {mold.image_path ? ( {mold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -662,9 +654,10 @@ export default function MoldInfoPage() {
{selectedMold.image_path ? ( {selectedMold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -1143,39 +1136,13 @@ export default function MoldInfoPage() {
-
- {moldImagePreview ? ( - <> - 금형 이미지 -
- - -
- - ) : ( - - )} -
- setMoldForm((prev) => ({ ...prev, image_path: v }))} + tableName="mold_mng" + recordId={moldForm.id || ""} + columnName="image_path" + height="h-32" />
diff --git a/frontend/app/(main)/COMPANY_29/outsourcing/subcontractor/page.tsx b/frontend/app/(main)/COMPANY_29/outsourcing/subcontractor/page.tsx index d649ab56..46b78a03 100644 --- a/frontend/app/(main)/COMPANY_29/outsourcing/subcontractor/page.tsx +++ b/frontend/app/(main)/COMPANY_29/outsourcing/subcontractor/page.tsx @@ -141,10 +141,12 @@ export default function SubcontractorManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -1181,8 +1183,8 @@ export default function SubcontractorManagementPage() { {item.item_number} {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -1226,7 +1228,7 @@ export default function SubcontractorManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_29/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_29/purchase/supplier/page.tsx index 4ae229ab..eb9bd977 100644 --- a/frontend/app/(main)/COMPANY_29/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_29/purchase/supplier/page.tsx @@ -195,10 +195,12 @@ export default function SupplierManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2435,8 +2437,8 @@ export default function SupplierManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2478,7 +2480,7 @@ export default function SupplierManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_29/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_29/sales/customer/page.tsx index 96e2512c..57897a8a 100644 --- a/frontend/app/(main)/COMPANY_29/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_29/sales/customer/page.tsx @@ -195,10 +195,12 @@ export default function CustomerManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2438,8 +2440,8 @@ export default function CustomerManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2481,7 +2483,7 @@ export default function CustomerManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_30/mold/info/page.tsx b/frontend/app/(main)/COMPANY_30/mold/info/page.tsx index dcd92eac..126c803d 100644 --- a/frontend/app/(main)/COMPANY_30/mold/info/page.tsx +++ b/frontend/app/(main)/COMPANY_30/mold/info/page.tsx @@ -26,6 +26,7 @@ import { import { cn } from "@/lib/utils"; import { apiClient } from "@/lib/api/client"; import { previewNumberingCode, allocateNumberingCode } from "@/lib/api/numberingRule"; +import { ImageUpload } from "@/components/common/ImageUpload"; import { useAuth } from "@/hooks/useAuth"; import { toast } from "sonner"; import { useConfirmDialog } from "@/components/common/ConfirmDialog"; @@ -102,8 +103,8 @@ export default function MoldInfoPage() { const [numberingRuleId, setNumberingRuleId] = useState(null); const [previewCode, setPreviewCode] = useState(null); const [saving, setSaving] = useState(false); + // moldImagePreview는 상세 표시용으로 유지 (ImageUpload는 모달에서만 사용) const [moldImagePreview, setMoldImagePreview] = useState(null); - const moldImageRef = React.useRef(null); const [serialModalOpen, setSerialModalOpen] = useState(false); const [serialForm, setSerialForm] = useState>({}); @@ -240,17 +241,7 @@ export default function MoldInfoPage() { setMoldModalOpen(true); }; - const handleMoldImageUpload = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - const reader = new FileReader(); - reader.onloadend = () => { - const result = reader.result as string; - setMoldImagePreview(result); - setMoldForm((prev) => ({ ...prev, image_path: result })); - }; - reader.readAsDataURL(file); - }; + // 이미지 업로드는 ImageUpload 컴포넌트가 처리 → objid를 image_path에 저장 const handleSaveMold = async () => { // 등록 모드에서 채번이 없으면 수동 입력 필수 @@ -460,9 +451,10 @@ export default function MoldInfoPage() { )}> {mold.image_path ? ( {mold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -662,9 +654,10 @@ export default function MoldInfoPage() {
{selectedMold.image_path ? ( {selectedMold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -1143,39 +1136,13 @@ export default function MoldInfoPage() {
-
- {moldImagePreview ? ( - <> - 금형 이미지 -
- - -
- - ) : ( - - )} -
- setMoldForm((prev) => ({ ...prev, image_path: v }))} + tableName="mold_mng" + recordId={moldForm.id || ""} + columnName="image_path" + height="h-32" />
diff --git a/frontend/app/(main)/COMPANY_30/outsourcing/subcontractor/page.tsx b/frontend/app/(main)/COMPANY_30/outsourcing/subcontractor/page.tsx index d649ab56..46b78a03 100644 --- a/frontend/app/(main)/COMPANY_30/outsourcing/subcontractor/page.tsx +++ b/frontend/app/(main)/COMPANY_30/outsourcing/subcontractor/page.tsx @@ -141,10 +141,12 @@ export default function SubcontractorManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -1181,8 +1183,8 @@ export default function SubcontractorManagementPage() { {item.item_number} {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -1226,7 +1228,7 @@ export default function SubcontractorManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_30/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_30/purchase/supplier/page.tsx index 4ae229ab..eb9bd977 100644 --- a/frontend/app/(main)/COMPANY_30/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_30/purchase/supplier/page.tsx @@ -195,10 +195,12 @@ export default function SupplierManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2435,8 +2437,8 @@ export default function SupplierManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2478,7 +2480,7 @@ export default function SupplierManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_30/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_30/sales/customer/page.tsx index 96e2512c..57897a8a 100644 --- a/frontend/app/(main)/COMPANY_30/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_30/sales/customer/page.tsx @@ -195,10 +195,12 @@ export default function CustomerManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2438,8 +2440,8 @@ export default function CustomerManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2481,7 +2483,7 @@ export default function CustomerManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_7/mold/info/page.tsx b/frontend/app/(main)/COMPANY_7/mold/info/page.tsx index dcd92eac..126c803d 100644 --- a/frontend/app/(main)/COMPANY_7/mold/info/page.tsx +++ b/frontend/app/(main)/COMPANY_7/mold/info/page.tsx @@ -26,6 +26,7 @@ import { import { cn } from "@/lib/utils"; import { apiClient } from "@/lib/api/client"; import { previewNumberingCode, allocateNumberingCode } from "@/lib/api/numberingRule"; +import { ImageUpload } from "@/components/common/ImageUpload"; import { useAuth } from "@/hooks/useAuth"; import { toast } from "sonner"; import { useConfirmDialog } from "@/components/common/ConfirmDialog"; @@ -102,8 +103,8 @@ export default function MoldInfoPage() { const [numberingRuleId, setNumberingRuleId] = useState(null); const [previewCode, setPreviewCode] = useState(null); const [saving, setSaving] = useState(false); + // moldImagePreview는 상세 표시용으로 유지 (ImageUpload는 모달에서만 사용) const [moldImagePreview, setMoldImagePreview] = useState(null); - const moldImageRef = React.useRef(null); const [serialModalOpen, setSerialModalOpen] = useState(false); const [serialForm, setSerialForm] = useState>({}); @@ -240,17 +241,7 @@ export default function MoldInfoPage() { setMoldModalOpen(true); }; - const handleMoldImageUpload = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - const reader = new FileReader(); - reader.onloadend = () => { - const result = reader.result as string; - setMoldImagePreview(result); - setMoldForm((prev) => ({ ...prev, image_path: result })); - }; - reader.readAsDataURL(file); - }; + // 이미지 업로드는 ImageUpload 컴포넌트가 처리 → objid를 image_path에 저장 const handleSaveMold = async () => { // 등록 모드에서 채번이 없으면 수동 입력 필수 @@ -460,9 +451,10 @@ export default function MoldInfoPage() { )}> {mold.image_path ? ( {mold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -662,9 +654,10 @@ export default function MoldInfoPage() {
{selectedMold.image_path ? ( {selectedMold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -1143,39 +1136,13 @@ export default function MoldInfoPage() {
-
- {moldImagePreview ? ( - <> - 금형 이미지 -
- - -
- - ) : ( - - )} -
- setMoldForm((prev) => ({ ...prev, image_path: v }))} + tableName="mold_mng" + recordId={moldForm.id || ""} + columnName="image_path" + height="h-32" />
diff --git a/frontend/app/(main)/COMPANY_7/outsourcing/subcontractor/page.tsx b/frontend/app/(main)/COMPANY_7/outsourcing/subcontractor/page.tsx index ed0e71d8..191608a8 100644 --- a/frontend/app/(main)/COMPANY_7/outsourcing/subcontractor/page.tsx +++ b/frontend/app/(main)/COMPANY_7/outsourcing/subcontractor/page.tsx @@ -141,11 +141,13 @@ export default function SubcontractorManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - // item_info의 division 카테고리도 로드 (품목 검색 시 외주관리 코드 조회용) - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + // item_info의 division/unit/material 카테고리도 로드 (품목 검색 시 외주관리 코드 조회용) + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -1182,8 +1184,8 @@ export default function SubcontractorManagementPage() { {item.item_number} {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -1227,7 +1229,7 @@ export default function SubcontractorManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_7/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_7/purchase/supplier/page.tsx index 4ae229ab..eb9bd977 100644 --- a/frontend/app/(main)/COMPANY_7/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_7/purchase/supplier/page.tsx @@ -195,10 +195,12 @@ export default function SupplierManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2435,8 +2437,8 @@ export default function SupplierManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2478,7 +2480,7 @@ export default function SupplierManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_7/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_7/sales/customer/page.tsx index 96e2512c..57897a8a 100644 --- a/frontend/app/(main)/COMPANY_7/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_7/sales/customer/page.tsx @@ -195,10 +195,12 @@ export default function CustomerManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2438,8 +2440,8 @@ export default function CustomerManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2481,7 +2483,7 @@ export default function CustomerManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_8/mold/info/page.tsx b/frontend/app/(main)/COMPANY_8/mold/info/page.tsx index dcd92eac..126c803d 100644 --- a/frontend/app/(main)/COMPANY_8/mold/info/page.tsx +++ b/frontend/app/(main)/COMPANY_8/mold/info/page.tsx @@ -26,6 +26,7 @@ import { import { cn } from "@/lib/utils"; import { apiClient } from "@/lib/api/client"; import { previewNumberingCode, allocateNumberingCode } from "@/lib/api/numberingRule"; +import { ImageUpload } from "@/components/common/ImageUpload"; import { useAuth } from "@/hooks/useAuth"; import { toast } from "sonner"; import { useConfirmDialog } from "@/components/common/ConfirmDialog"; @@ -102,8 +103,8 @@ export default function MoldInfoPage() { const [numberingRuleId, setNumberingRuleId] = useState(null); const [previewCode, setPreviewCode] = useState(null); const [saving, setSaving] = useState(false); + // moldImagePreview는 상세 표시용으로 유지 (ImageUpload는 모달에서만 사용) const [moldImagePreview, setMoldImagePreview] = useState(null); - const moldImageRef = React.useRef(null); const [serialModalOpen, setSerialModalOpen] = useState(false); const [serialForm, setSerialForm] = useState>({}); @@ -240,17 +241,7 @@ export default function MoldInfoPage() { setMoldModalOpen(true); }; - const handleMoldImageUpload = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - const reader = new FileReader(); - reader.onloadend = () => { - const result = reader.result as string; - setMoldImagePreview(result); - setMoldForm((prev) => ({ ...prev, image_path: result })); - }; - reader.readAsDataURL(file); - }; + // 이미지 업로드는 ImageUpload 컴포넌트가 처리 → objid를 image_path에 저장 const handleSaveMold = async () => { // 등록 모드에서 채번이 없으면 수동 입력 필수 @@ -460,9 +451,10 @@ export default function MoldInfoPage() { )}> {mold.image_path ? ( {mold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -662,9 +654,10 @@ export default function MoldInfoPage() {
{selectedMold.image_path ? ( {selectedMold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -1143,39 +1136,13 @@ export default function MoldInfoPage() {
-
- {moldImagePreview ? ( - <> - 금형 이미지 -
- - -
- - ) : ( - - )} -
- setMoldForm((prev) => ({ ...prev, image_path: v }))} + tableName="mold_mng" + recordId={moldForm.id || ""} + columnName="image_path" + height="h-32" />
diff --git a/frontend/app/(main)/COMPANY_8/outsourcing/subcontractor/page.tsx b/frontend/app/(main)/COMPANY_8/outsourcing/subcontractor/page.tsx index 1118d571..1f9a3d0e 100644 --- a/frontend/app/(main)/COMPANY_8/outsourcing/subcontractor/page.tsx +++ b/frontend/app/(main)/COMPANY_8/outsourcing/subcontractor/page.tsx @@ -141,11 +141,13 @@ export default function SubcontractorManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - // item_info의 division 카테고리도 로드 (품목 검색 시 외주관리 코드 조회용) - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + // item_info의 division/unit/material 카테고리도 로드 (품목 검색 시 외주관리 코드 조회용) + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -1182,8 +1184,8 @@ export default function SubcontractorManagementPage() { {item.item_number} {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -1227,7 +1229,7 @@ export default function SubcontractorManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_8/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_8/purchase/supplier/page.tsx index 4ae229ab..eb9bd977 100644 --- a/frontend/app/(main)/COMPANY_8/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_8/purchase/supplier/page.tsx @@ -195,10 +195,12 @@ export default function SupplierManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2435,8 +2437,8 @@ export default function SupplierManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2478,7 +2480,7 @@ export default function SupplierManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_8/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_8/sales/customer/page.tsx index 96e2512c..57897a8a 100644 --- a/frontend/app/(main)/COMPANY_8/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_8/sales/customer/page.tsx @@ -195,10 +195,12 @@ export default function CustomerManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2438,8 +2440,8 @@ export default function CustomerManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2481,7 +2483,7 @@ export default function CustomerManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_9/mold/info/page.tsx b/frontend/app/(main)/COMPANY_9/mold/info/page.tsx index dcd92eac..126c803d 100644 --- a/frontend/app/(main)/COMPANY_9/mold/info/page.tsx +++ b/frontend/app/(main)/COMPANY_9/mold/info/page.tsx @@ -26,6 +26,7 @@ import { import { cn } from "@/lib/utils"; import { apiClient } from "@/lib/api/client"; import { previewNumberingCode, allocateNumberingCode } from "@/lib/api/numberingRule"; +import { ImageUpload } from "@/components/common/ImageUpload"; import { useAuth } from "@/hooks/useAuth"; import { toast } from "sonner"; import { useConfirmDialog } from "@/components/common/ConfirmDialog"; @@ -102,8 +103,8 @@ export default function MoldInfoPage() { const [numberingRuleId, setNumberingRuleId] = useState(null); const [previewCode, setPreviewCode] = useState(null); const [saving, setSaving] = useState(false); + // moldImagePreview는 상세 표시용으로 유지 (ImageUpload는 모달에서만 사용) const [moldImagePreview, setMoldImagePreview] = useState(null); - const moldImageRef = React.useRef(null); const [serialModalOpen, setSerialModalOpen] = useState(false); const [serialForm, setSerialForm] = useState>({}); @@ -240,17 +241,7 @@ export default function MoldInfoPage() { setMoldModalOpen(true); }; - const handleMoldImageUpload = (e: React.ChangeEvent) => { - const file = e.target.files?.[0]; - if (!file) return; - const reader = new FileReader(); - reader.onloadend = () => { - const result = reader.result as string; - setMoldImagePreview(result); - setMoldForm((prev) => ({ ...prev, image_path: result })); - }; - reader.readAsDataURL(file); - }; + // 이미지 업로드는 ImageUpload 컴포넌트가 처리 → objid를 image_path에 저장 const handleSaveMold = async () => { // 등록 모드에서 채번이 없으면 수동 입력 필수 @@ -460,9 +451,10 @@ export default function MoldInfoPage() { )}> {mold.image_path ? ( {mold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -662,9 +654,10 @@ export default function MoldInfoPage() {
{selectedMold.image_path ? ( {selectedMold.mold_name} { (e.target as HTMLImageElement).style.display = "none"; }} /> ) : ( @@ -1143,39 +1136,13 @@ export default function MoldInfoPage() {
-
- {moldImagePreview ? ( - <> - 금형 이미지 -
- - -
- - ) : ( - - )} -
- setMoldForm((prev) => ({ ...prev, image_path: v }))} + tableName="mold_mng" + recordId={moldForm.id || ""} + columnName="image_path" + height="h-32" />
diff --git a/frontend/app/(main)/COMPANY_9/outsourcing/subcontractor/page.tsx b/frontend/app/(main)/COMPANY_9/outsourcing/subcontractor/page.tsx index d649ab56..46b78a03 100644 --- a/frontend/app/(main)/COMPANY_9/outsourcing/subcontractor/page.tsx +++ b/frontend/app/(main)/COMPANY_9/outsourcing/subcontractor/page.tsx @@ -141,10 +141,12 @@ export default function SubcontractorManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -1181,8 +1183,8 @@ export default function SubcontractorManagementPage() { {item.item_number} {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -1226,7 +1228,7 @@ export default function SubcontractorManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_9/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_9/purchase/supplier/page.tsx index 4ae229ab..eb9bd977 100644 --- a/frontend/app/(main)/COMPANY_9/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_9/purchase/supplier/page.tsx @@ -195,10 +195,12 @@ export default function SupplierManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2435,8 +2437,8 @@ export default function SupplierManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2478,7 +2480,7 @@ export default function SupplierManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/app/(main)/COMPANY_9/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_9/sales/customer/page.tsx index 96e2512c..57897a8a 100644 --- a/frontend/app/(main)/COMPANY_9/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_9/sales/customer/page.tsx @@ -195,10 +195,12 @@ export default function CustomerManagementPage() { if (res.data?.success) optMap[col] = flatten(res.data.data || []); } catch { /* skip */ } } - try { - const res = await apiClient.get(`/table-categories/item_info/division/values`); - if (res.data?.success) optMap["item_division"] = flatten(res.data.data || []); - } catch { /* skip */ } + for (const col of ["division", "unit", "material"]) { + try { + const res = await apiClient.get(`/table-categories/item_info/${col}/values`); + if (res.data?.success) optMap[`item_${col}`] = flatten(res.data.data || []); + } catch { /* skip */ } + } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -2438,8 +2440,8 @@ export default function CustomerManagementPage() { {item.item_name} {item.size} - {item.material} - {item.unit} + {categoryOptions["item_material"]?.find((o) => o.code === item.material)?.label || item.material} + {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit} ))} @@ -2481,7 +2483,7 @@ export default function CustomerManagementPage() { {/* 품목 헤더 */}
{idx + 1}. {item.item_name || itemKey}
-
{itemKey} | {item.size || ""} | {item.unit || ""}
+
{itemKey} | {item.size || ""} | {categoryOptions["item_unit"]?.find((o) => o.code === item.unit)?.label || item.unit || ""}
diff --git a/frontend/next.config.mjs b/frontend/next.config.mjs index cbc58206..441d044c 100644 --- a/frontend/next.config.mjs +++ b/frontend/next.config.mjs @@ -28,6 +28,10 @@ const nextConfig = { source: "/api/:path*", destination: `${backendUrl}/api/:path*`, }, + { + source: "/uploads/:path*", + destination: `${backendUrl}/uploads/:path*`, + }, ]; },