From a232399cbc917f16cb8fd828d8f06b3d3208492a Mon Sep 17 00:00:00 2001 From: kjs Date: Sat, 11 Apr 2026 13:40:01 +0900 Subject: [PATCH 1/2] refactor: Update item division handling in supplier and customer management pages - Added loading of item division categories to enhance filtering capabilities in supplier and customer management pages. - Updated filtering logic to dynamically use item division codes for improved item search results. - Ensured consistent handling of division codes across multiple company pages. These changes aim to improve the user experience and data management in supplier and customer processes across various companies. --- .../app/(main)/COMPANY_10/purchase/supplier/page.tsx | 11 ++++++++--- .../app/(main)/COMPANY_10/sales/customer/page.tsx | 6 +++++- .../app/(main)/COMPANY_16/purchase/supplier/page.tsx | 11 ++++++++--- .../app/(main)/COMPANY_16/sales/customer/page.tsx | 6 +++++- .../app/(main)/COMPANY_29/purchase/supplier/page.tsx | 11 ++++++++--- .../app/(main)/COMPANY_29/sales/customer/page.tsx | 6 +++++- .../app/(main)/COMPANY_30/purchase/supplier/page.tsx | 11 ++++++++--- .../app/(main)/COMPANY_30/sales/customer/page.tsx | 6 +++++- .../app/(main)/COMPANY_7/purchase/supplier/page.tsx | 11 ++++++++--- frontend/app/(main)/COMPANY_7/sales/customer/page.tsx | 6 +++++- .../app/(main)/COMPANY_8/purchase/supplier/page.tsx | 11 ++++++++--- frontend/app/(main)/COMPANY_8/sales/customer/page.tsx | 6 +++++- .../app/(main)/COMPANY_9/purchase/supplier/page.tsx | 11 ++++++++--- frontend/app/(main)/COMPANY_9/sales/customer/page.tsx | 6 +++++- 14 files changed, 91 insertions(+), 28 deletions(-) diff --git a/frontend/app/(main)/COMPANY_10/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_10/purchase/supplier/page.tsx index 521f770e..4ae229ab 100644 --- a/frontend/app/(main)/COMPANY_10/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_10/purchase/supplier/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -820,11 +824,12 @@ export default function SupplierManagementPage() { const allItems = res.data?.data?.data || res.data?.data?.rows || []; setItemTotalCount(allItems.length); const existingItemIds = new Set(priceItems.map((p: any) => p.item_id || p.item_number)); - const PURCHASE_CODES = ["s"]; // 구매관리 카테고리 코드 + const purchaseCode = categoryOptions["item_division"]?.find((o) => o.label === "구매관리")?.code; setItemSearchResults(allItems.filter((item: any) => { if (existingItemIds.has(item.item_number) || existingItemIds.has(item.id)) return false; - const divCodes = (item.division || "").split(",").map((c: string) => c.trim()); - return divCodes.some((code: string) => PURCHASE_CODES.includes(code)); + if (!purchaseCode) return true; + const div = item.division || ""; + return div.includes(purchaseCode); })); } catch { /* skip */ } finally { setItemSearchLoading(false); } }; diff --git a/frontend/app/(main)/COMPANY_10/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_10/sales/customer/page.tsx index c500c7ae..96e2512c 100644 --- a/frontend/app/(main)/COMPANY_10/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_10/sales/customer/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -811,7 +815,7 @@ export default function CustomerManagementPage() { const searchItems = async () => { setItemSearchLoading(true); try { - const salesCode = categoryOptions["division"]?.find((o) => o.label === "영업관리")?.code; + const salesCode = categoryOptions["item_division"]?.find((o) => o.label === "영업관리")?.code; const filters: any[] = salesCode ? [{ columnName: "division", operator: "contains", value: salesCode }] : []; diff --git a/frontend/app/(main)/COMPANY_16/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_16/purchase/supplier/page.tsx index 8f2755e5..b4dc6be0 100644 --- a/frontend/app/(main)/COMPANY_16/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_16/purchase/supplier/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -820,11 +824,12 @@ export default function SupplierManagementPage() { const allItems = res.data?.data?.data || res.data?.data?.rows || []; setItemTotalCount(allItems.length); const existingItemIds = new Set(priceItems.map((p: any) => p.item_id || p.item_number)); - const PURCHASE_CODES = ["s"]; // 구매관리 카테고리 코드 + const purchaseCode = categoryOptions["item_division"]?.find((o) => o.label === "구매관리")?.code; setItemSearchResults(allItems.filter((item: any) => { if (existingItemIds.has(item.item_number) || existingItemIds.has(item.id)) return false; - const divCodes = (item.division || "").split(",").map((c: string) => c.trim()); - return divCodes.some((code: string) => PURCHASE_CODES.includes(code)); + if (!purchaseCode) return true; + const div = item.division || ""; + return div.includes(purchaseCode); })); } catch { /* skip */ } finally { setItemSearchLoading(false); } }, [itemSearchKeyword, priceItems]); diff --git a/frontend/app/(main)/COMPANY_16/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_16/sales/customer/page.tsx index e5821403..5ae6fc77 100644 --- a/frontend/app/(main)/COMPANY_16/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_16/sales/customer/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -811,7 +815,7 @@ export default function CustomerManagementPage() { const searchItems = useCallback(async () => { setItemSearchLoading(true); try { - const salesCode = categoryOptions["division"]?.find((o) => o.label === "영업관리")?.code; + const salesCode = categoryOptions["item_division"]?.find((o) => o.label === "영업관리")?.code; const filters: any[] = salesCode ? [{ columnName: "division", operator: "contains", value: salesCode }] : []; diff --git a/frontend/app/(main)/COMPANY_29/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_29/purchase/supplier/page.tsx index 521f770e..4ae229ab 100644 --- a/frontend/app/(main)/COMPANY_29/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_29/purchase/supplier/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -820,11 +824,12 @@ export default function SupplierManagementPage() { const allItems = res.data?.data?.data || res.data?.data?.rows || []; setItemTotalCount(allItems.length); const existingItemIds = new Set(priceItems.map((p: any) => p.item_id || p.item_number)); - const PURCHASE_CODES = ["s"]; // 구매관리 카테고리 코드 + const purchaseCode = categoryOptions["item_division"]?.find((o) => o.label === "구매관리")?.code; setItemSearchResults(allItems.filter((item: any) => { if (existingItemIds.has(item.item_number) || existingItemIds.has(item.id)) return false; - const divCodes = (item.division || "").split(",").map((c: string) => c.trim()); - return divCodes.some((code: string) => PURCHASE_CODES.includes(code)); + if (!purchaseCode) return true; + const div = item.division || ""; + return div.includes(purchaseCode); })); } catch { /* skip */ } finally { setItemSearchLoading(false); } }; diff --git a/frontend/app/(main)/COMPANY_29/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_29/sales/customer/page.tsx index c500c7ae..96e2512c 100644 --- a/frontend/app/(main)/COMPANY_29/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_29/sales/customer/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -811,7 +815,7 @@ export default function CustomerManagementPage() { const searchItems = async () => { setItemSearchLoading(true); try { - const salesCode = categoryOptions["division"]?.find((o) => o.label === "영업관리")?.code; + const salesCode = categoryOptions["item_division"]?.find((o) => o.label === "영업관리")?.code; const filters: any[] = salesCode ? [{ columnName: "division", operator: "contains", value: salesCode }] : []; diff --git a/frontend/app/(main)/COMPANY_30/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_30/purchase/supplier/page.tsx index 521f770e..4ae229ab 100644 --- a/frontend/app/(main)/COMPANY_30/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_30/purchase/supplier/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -820,11 +824,12 @@ export default function SupplierManagementPage() { const allItems = res.data?.data?.data || res.data?.data?.rows || []; setItemTotalCount(allItems.length); const existingItemIds = new Set(priceItems.map((p: any) => p.item_id || p.item_number)); - const PURCHASE_CODES = ["s"]; // 구매관리 카테고리 코드 + const purchaseCode = categoryOptions["item_division"]?.find((o) => o.label === "구매관리")?.code; setItemSearchResults(allItems.filter((item: any) => { if (existingItemIds.has(item.item_number) || existingItemIds.has(item.id)) return false; - const divCodes = (item.division || "").split(",").map((c: string) => c.trim()); - return divCodes.some((code: string) => PURCHASE_CODES.includes(code)); + if (!purchaseCode) return true; + const div = item.division || ""; + return div.includes(purchaseCode); })); } catch { /* skip */ } finally { setItemSearchLoading(false); } }; diff --git a/frontend/app/(main)/COMPANY_30/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_30/sales/customer/page.tsx index c500c7ae..96e2512c 100644 --- a/frontend/app/(main)/COMPANY_30/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_30/sales/customer/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -811,7 +815,7 @@ export default function CustomerManagementPage() { const searchItems = async () => { setItemSearchLoading(true); try { - const salesCode = categoryOptions["division"]?.find((o) => o.label === "영업관리")?.code; + const salesCode = categoryOptions["item_division"]?.find((o) => o.label === "영업관리")?.code; const filters: any[] = salesCode ? [{ columnName: "division", operator: "contains", value: salesCode }] : []; diff --git a/frontend/app/(main)/COMPANY_7/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_7/purchase/supplier/page.tsx index 521f770e..4ae229ab 100644 --- a/frontend/app/(main)/COMPANY_7/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_7/purchase/supplier/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -820,11 +824,12 @@ export default function SupplierManagementPage() { const allItems = res.data?.data?.data || res.data?.data?.rows || []; setItemTotalCount(allItems.length); const existingItemIds = new Set(priceItems.map((p: any) => p.item_id || p.item_number)); - const PURCHASE_CODES = ["s"]; // 구매관리 카테고리 코드 + const purchaseCode = categoryOptions["item_division"]?.find((o) => o.label === "구매관리")?.code; setItemSearchResults(allItems.filter((item: any) => { if (existingItemIds.has(item.item_number) || existingItemIds.has(item.id)) return false; - const divCodes = (item.division || "").split(",").map((c: string) => c.trim()); - return divCodes.some((code: string) => PURCHASE_CODES.includes(code)); + if (!purchaseCode) return true; + const div = item.division || ""; + return div.includes(purchaseCode); })); } catch { /* skip */ } finally { setItemSearchLoading(false); } }; diff --git a/frontend/app/(main)/COMPANY_7/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_7/sales/customer/page.tsx index c500c7ae..96e2512c 100644 --- a/frontend/app/(main)/COMPANY_7/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_7/sales/customer/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -811,7 +815,7 @@ export default function CustomerManagementPage() { const searchItems = async () => { setItemSearchLoading(true); try { - const salesCode = categoryOptions["division"]?.find((o) => o.label === "영업관리")?.code; + const salesCode = categoryOptions["item_division"]?.find((o) => o.label === "영업관리")?.code; const filters: any[] = salesCode ? [{ columnName: "division", operator: "contains", value: salesCode }] : []; diff --git a/frontend/app/(main)/COMPANY_8/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_8/purchase/supplier/page.tsx index 521f770e..4ae229ab 100644 --- a/frontend/app/(main)/COMPANY_8/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_8/purchase/supplier/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -820,11 +824,12 @@ export default function SupplierManagementPage() { const allItems = res.data?.data?.data || res.data?.data?.rows || []; setItemTotalCount(allItems.length); const existingItemIds = new Set(priceItems.map((p: any) => p.item_id || p.item_number)); - const PURCHASE_CODES = ["s"]; // 구매관리 카테고리 코드 + const purchaseCode = categoryOptions["item_division"]?.find((o) => o.label === "구매관리")?.code; setItemSearchResults(allItems.filter((item: any) => { if (existingItemIds.has(item.item_number) || existingItemIds.has(item.id)) return false; - const divCodes = (item.division || "").split(",").map((c: string) => c.trim()); - return divCodes.some((code: string) => PURCHASE_CODES.includes(code)); + if (!purchaseCode) return true; + const div = item.division || ""; + return div.includes(purchaseCode); })); } catch { /* skip */ } finally { setItemSearchLoading(false); } }; diff --git a/frontend/app/(main)/COMPANY_8/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_8/sales/customer/page.tsx index c500c7ae..96e2512c 100644 --- a/frontend/app/(main)/COMPANY_8/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_8/sales/customer/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -811,7 +815,7 @@ export default function CustomerManagementPage() { const searchItems = async () => { setItemSearchLoading(true); try { - const salesCode = categoryOptions["division"]?.find((o) => o.label === "영업관리")?.code; + const salesCode = categoryOptions["item_division"]?.find((o) => o.label === "영업관리")?.code; const filters: any[] = salesCode ? [{ columnName: "division", operator: "contains", value: salesCode }] : []; diff --git a/frontend/app/(main)/COMPANY_9/purchase/supplier/page.tsx b/frontend/app/(main)/COMPANY_9/purchase/supplier/page.tsx index 521f770e..4ae229ab 100644 --- a/frontend/app/(main)/COMPANY_9/purchase/supplier/page.tsx +++ b/frontend/app/(main)/COMPANY_9/purchase/supplier/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -820,11 +824,12 @@ export default function SupplierManagementPage() { const allItems = res.data?.data?.data || res.data?.data?.rows || []; setItemTotalCount(allItems.length); const existingItemIds = new Set(priceItems.map((p: any) => p.item_id || p.item_number)); - const PURCHASE_CODES = ["s"]; // 구매관리 카테고리 코드 + const purchaseCode = categoryOptions["item_division"]?.find((o) => o.label === "구매관리")?.code; setItemSearchResults(allItems.filter((item: any) => { if (existingItemIds.has(item.item_number) || existingItemIds.has(item.id)) return false; - const divCodes = (item.division || "").split(",").map((c: string) => c.trim()); - return divCodes.some((code: string) => PURCHASE_CODES.includes(code)); + if (!purchaseCode) return true; + const div = item.division || ""; + return div.includes(purchaseCode); })); } catch { /* skip */ } finally { setItemSearchLoading(false); } }; diff --git a/frontend/app/(main)/COMPANY_9/sales/customer/page.tsx b/frontend/app/(main)/COMPANY_9/sales/customer/page.tsx index c500c7ae..96e2512c 100644 --- a/frontend/app/(main)/COMPANY_9/sales/customer/page.tsx +++ b/frontend/app/(main)/COMPANY_9/sales/customer/page.tsx @@ -195,6 +195,10 @@ 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 */ } setCategoryOptions(optMap); const priceOpts: Record = {}; @@ -811,7 +815,7 @@ export default function CustomerManagementPage() { const searchItems = async () => { setItemSearchLoading(true); try { - const salesCode = categoryOptions["division"]?.find((o) => o.label === "영업관리")?.code; + const salesCode = categoryOptions["item_division"]?.find((o) => o.label === "영업관리")?.code; const filters: any[] = salesCode ? [{ columnName: "division", operator: "contains", value: salesCode }] : []; From 972a0143adeb68587b7a86165bd88b54fec2dc5b Mon Sep 17 00:00:00 2001 From: kjs Date: Sat, 11 Apr 2026 14:50:18 +0900 Subject: [PATCH 2/2] refactor: Integrate ImageUpload component for mold image handling - Replaced manual image upload logic with the ImageUpload component for better management of mold images. - Updated image source handling to ensure proper display of images based on their URL format. - Enhanced error handling for image display to improve user experience. These changes aim to streamline the image upload process and enhance the overall functionality of the mold information page across multiple companies. --- .../app/(main)/COMPANY_10/mold/info/page.tsx | 61 +++++-------------- .../outsourcing/subcontractor/page.tsx | 16 ++--- .../COMPANY_10/purchase/supplier/page.tsx | 16 ++--- .../(main)/COMPANY_10/sales/customer/page.tsx | 16 ++--- .../app/(main)/COMPANY_16/mold/info/page.tsx | 61 +++++-------------- .../outsourcing/subcontractor/page.tsx | 16 ++--- .../COMPANY_16/purchase/supplier/page.tsx | 16 ++--- .../(main)/COMPANY_16/sales/customer/page.tsx | 16 ++--- .../app/(main)/COMPANY_29/mold/info/page.tsx | 61 +++++-------------- .../outsourcing/subcontractor/page.tsx | 16 ++--- .../COMPANY_29/purchase/supplier/page.tsx | 16 ++--- .../(main)/COMPANY_29/sales/customer/page.tsx | 16 ++--- .../app/(main)/COMPANY_30/mold/info/page.tsx | 61 +++++-------------- .../outsourcing/subcontractor/page.tsx | 16 ++--- .../COMPANY_30/purchase/supplier/page.tsx | 16 ++--- .../(main)/COMPANY_30/sales/customer/page.tsx | 16 ++--- .../app/(main)/COMPANY_7/mold/info/page.tsx | 61 +++++-------------- .../outsourcing/subcontractor/page.tsx | 18 +++--- .../COMPANY_7/purchase/supplier/page.tsx | 16 ++--- .../(main)/COMPANY_7/sales/customer/page.tsx | 16 ++--- .../app/(main)/COMPANY_8/mold/info/page.tsx | 61 +++++-------------- .../outsourcing/subcontractor/page.tsx | 18 +++--- .../COMPANY_8/purchase/supplier/page.tsx | 16 ++--- .../(main)/COMPANY_8/sales/customer/page.tsx | 16 ++--- .../app/(main)/COMPANY_9/mold/info/page.tsx | 61 +++++-------------- .../outsourcing/subcontractor/page.tsx | 16 ++--- .../COMPANY_9/purchase/supplier/page.tsx | 16 ++--- .../(main)/COMPANY_9/sales/customer/page.tsx | 16 ++--- frontend/next.config.mjs | 4 ++ 29 files changed, 293 insertions(+), 478 deletions(-) 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*`, + }, ]; },