diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-20 09:01:22 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-05-20 09:01:22 +0000 |
| commit | 45f4c426c98d86a251644a4858740bec989edf83 (patch) | |
| tree | b0a3f1ce6ac3e4493ee53c93ef33841c8eb34cfb /lib/items-tech/table | |
| parent | 11f13979825d28180956fc27600176bfc47457e1 (diff) | |
(최겸) 기술영업 아이템리스트 수정 및 개발 0520
Diffstat (limited to 'lib/items-tech/table')
17 files changed, 261 insertions, 628 deletions
diff --git a/lib/items-tech/table/add-items-dialog.tsx b/lib/items-tech/table/add-items-dialog.tsx index 86333189..a3af0a8c 100644 --- a/lib/items-tech/table/add-items-dialog.tsx +++ b/lib/items-tech/table/add-items-dialog.tsx @@ -32,7 +32,6 @@ import { SelectTrigger,
SelectValue,
} from "@/components/ui/select"
-import { Textarea } from "@/components/ui/textarea"
import { toast } from "sonner"
import { createShipbuildingItem, createOffshoreTopItem, createOffshoreHullItem } from "../service"
@@ -47,14 +46,15 @@ const shipbuildingWorkTypes = [ { label: "철의", value: "철의" },
] as const
-// 선종 유형 정의
-const shipTypes = [
- { label: "A-MAX", value: "A-MAX" },
- { label: "S-MAX", value: "S-MAX" },
- { label: "LNGC", value: "LNGC" },
- { label: "VLCC", value: "VLCC" },
- { label: "CONT", value: "CONT" },
-] as const
+// // 선종 유형 정의
+// const shipTypes = [
+// { label: "A-MAX", value: "A-MAX" },
+// { label: "S-MAX", value: "S-MAX" },
+// { label: "LNGC", value: "LNGC" },
+// { label: "VLCC", value: "VLCC" },
+// { label: "CONT", value: "CONT" },
+// { label: "OPTION", value: "OPTION" },
+// ] as const
// 해양 TOP 공종 유형 정의
const offshoreTopWorkTypes = [
@@ -79,13 +79,12 @@ const itemFormSchema = z.object({ itemName: z.string().min(1, "아이템 명은 필수입니다"),
description: z.string().optional(),
workType: z.string().min(1, "공종은 필수입니다"),
+ // 조선 및 해양 아이템 공통 필드
+ itemList: z.string().optional(),
// 조선 아이템 전용 필드
shipTypes: z.string().optional(),
// 해양 아이템 전용 필드
- itemList1: z.string().optional(),
- itemList2: z.string().optional(),
- itemList3: z.string().optional(),
- itemList4: z.string().optional(),
+ subItemList: z.string().optional(),
})
type ItemFormValues = z.infer<typeof itemFormSchema>
@@ -102,18 +101,17 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { const getDefaultValues = () => {
const defaults: ItemFormValues = {
itemCode: "",
- itemName: "",
+ itemName: "기술영업",
description: "",
workType: getDefaultWorkType(),
}
if (itemType === 'shipbuilding') {
- defaults.shipTypes = "A-MAX"
+ defaults.shipTypes = "OPTION"
+ defaults.itemList = ""
} else {
- defaults.itemList1 = ""
- defaults.itemList2 = ""
- defaults.itemList3 = ""
- defaults.itemList4 = ""
+ defaults.itemList = ""
+ defaults.subItemList = ""
}
return defaults
@@ -151,7 +149,8 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { itemName: data.itemName,
workType: data.workType,
shipTypes: data.shipTypes,
- description: data.description || null
+ description: data.description || null,
+ itemList: data.itemList || null
});
break;
@@ -161,10 +160,8 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { itemName: data.itemName,
workType: data.workType as "TM" | "TS" | "TE" | "TP",
description: data.description || null,
- itemList1: data.itemList1 || null,
- itemList2: data.itemList2 || null,
- itemList3: data.itemList3 || null,
- itemList4: data.itemList4 || null
+ itemList: data.itemList || null,
+ subItemList: data.subItemList || null
});
break;
@@ -174,10 +171,8 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { itemName: data.itemName,
workType: data.workType as "HA" | "HE" | "HH" | "HM" | "NC",
description: data.description || null,
- itemList1: data.itemList1 || null,
- itemList2: data.itemList2 || null,
- itemList3: data.itemList3 || null,
- itemList4: data.itemList4 || null
+ itemList: data.itemList || null,
+ subItemList: data.subItemList || null
});
break;
@@ -256,19 +251,6 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { />
<FormField
control={form.control}
- name="itemName"
- render={({ field }) => (
- <FormItem>
- <FormLabel>아이템 명</FormLabel>
- <FormControl>
- <Input {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
name="workType"
render={({ field }) => (
<FormItem>
@@ -292,41 +274,15 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { )}
/>
{itemType === 'shipbuilding' && (
- <FormField
- control={form.control}
- name="shipTypes"
- render={({ field }) => (
- <FormItem>
- <FormLabel>선종</FormLabel>
- <Select onValueChange={field.onChange} defaultValue={field.value}>
- <FormControl>
- <SelectTrigger>
- <SelectValue placeholder="선종을 선택하세요" />
- </SelectTrigger>
- </FormControl>
- <SelectContent>
- {shipTypes.map((type) => (
- <SelectItem key={type.value} value={type.value}>
- {type.label}
- </SelectItem>
- ))}
- </SelectContent>
- </Select>
- <FormMessage />
- </FormItem>
- )}
- />
- )}
- {(itemType === 'offshoreTop' || itemType === 'offshoreHull') && (
<>
<FormField
control={form.control}
- name="itemList1"
+ name="shipTypes"
render={({ field }) => (
<FormItem>
- <FormLabel>아이템 리스트 1</FormLabel>
+ <FormLabel>선종</FormLabel>
<FormControl>
- <Input {...field} />
+ <Input placeholder="선종을 입력하세요" {...field} />
</FormControl>
<FormMessage />
</FormItem>
@@ -334,10 +290,10 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { />
<FormField
control={form.control}
- name="itemList2"
+ name="itemList"
render={({ field }) => (
<FormItem>
- <FormLabel>아이템 리스트 2</FormLabel>
+ <FormLabel>아이템 리스트</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
@@ -345,12 +301,16 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { </FormItem>
)}
/>
+ </>
+ )}
+ {(itemType === 'offshoreTop' || itemType === 'offshoreHull') && (
+ <>
<FormField
control={form.control}
- name="itemList3"
+ name="itemList"
render={({ field }) => (
<FormItem>
- <FormLabel>아이템 리스트 3</FormLabel>
+ <FormLabel>아이템 리스트</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
@@ -360,10 +320,10 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { />
<FormField
control={form.control}
- name="itemList4"
+ name="subItemList"
render={({ field }) => (
<FormItem>
- <FormLabel>아이템 리스트 4</FormLabel>
+ <FormLabel>서브 아이템 리스트</FormLabel>
<FormControl>
<Input {...field} />
</FormControl>
@@ -373,19 +333,6 @@ export function AddItemDialog({ itemType }: AddItemDialogProps) { />
</>
)}
- <FormField
- control={form.control}
- name="description"
- render={({ field }) => (
- <FormItem>
- <FormLabel>설명</FormLabel>
- <FormControl>
- <Textarea {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
<div className="flex justify-end space-x-2">
<Button type="button" variant="outline" onClick={() => setOpen(false)}>
취소
diff --git a/lib/items-tech/table/hull/import-item-handler.tsx b/lib/items-tech/table/hull/import-item-handler.tsx index 40070769..38a176cb 100644 --- a/lib/items-tech/table/hull/import-item-handler.tsx +++ b/lib/items-tech/table/hull/import-item-handler.tsx @@ -9,15 +9,11 @@ const HULL_WORK_TYPES = ["HA", "HE", "HH", "HM", "NC"] as const; // 아이템 데이터 검증을 위한 Zod 스키마 const itemSchema = z.object({ itemCode: z.string().min(1, "아이템 코드는 필수입니다"), - itemName: z.string().min(1, "아이템 명은 필수입니다"), workType: z.enum(HULL_WORK_TYPES, { required_error: "기능(공종)은 필수입니다", }), - description: z.string().nullable().optional(), - itemList1: z.string().nullable().optional(), - itemList2: z.string().nullable().optional(), - itemList3: z.string().nullable().optional(), - itemList4: z.string().nullable().optional(), + itemList: z.string().nullable().optional(), + subItemList: z.string().nullable().optional(), }); interface ProcessResult { @@ -30,7 +26,7 @@ interface ProcessResult { * Excel 파일에서 가져온 해양 HULL 아이템 데이터 처리하는 함수 */ export async function processHullFileImport( - jsonData: any[], + jsonData: Record<string, unknown>[], progressCallback?: (current: number, total: number) => void ): Promise<ProcessResult> { // 결과 카운터 초기화 @@ -65,24 +61,16 @@ export async function processHullFileImport( try { // 필드 매핑 (한글/영문 필드명 모두 지원) const itemCode = row["아이템 코드"] || row["itemCode"] || ""; - const itemName = row["아이템 명"] || row["itemName"] || ""; const workType = row["기능(공종)"] || row["workType"] || ""; - const description = row["설명"] || row["description"] || null; - const itemList1 = row["항목1"] || row["itemList1"] || null; - const itemList2 = row["항목2"] || row["itemList2"] || null; - const itemList3 = row["항목3"] || row["itemList3"] || null; - const itemList4 = row["항목4"] || row["itemList4"] || null; + const itemList = row["아이템 리스트"] || row["itemList"] || null; + const subItemList = row["서브 아이템 리스트"] || row["subItemList"] || null; // 데이터 정제 const cleanedRow = { itemCode: typeof itemCode === 'string' ? itemCode.trim() : String(itemCode).trim(), - itemName: typeof itemName === 'string' ? itemName.trim() : String(itemName).trim(), workType: typeof workType === 'string' ? workType.trim() : String(workType).trim(), - description: description ? (typeof description === 'string' ? description : String(description)) : null, - itemList1: itemList1 ? (typeof itemList1 === 'string' ? itemList1 : String(itemList1)) : null, - itemList2: itemList2 ? (typeof itemList2 === 'string' ? itemList2 : String(itemList2)) : null, - itemList3: itemList3 ? (typeof itemList3 === 'string' ? itemList3 : String(itemList3)) : null, - itemList4: itemList4 ? (typeof itemList4 === 'string' ? itemList4 : String(itemList4)) : null, + itemList: itemList ? (typeof itemList === 'string' ? itemList : String(itemList)) : null, + subItemList: subItemList ? (typeof subItemList === 'string' ? subItemList : String(subItemList)) : null, }; // 데이터 유효성 검사 @@ -101,13 +89,11 @@ export async function processHullFileImport( // 해양 HULL 아이템 생성 const result = await createOffshoreHullItem({ itemCode: cleanedRow.itemCode, - itemName: cleanedRow.itemName, + itemName: "기술영업", // 기본값 사용 workType: cleanedRow.workType as "HA" | "HE" | "HH" | "HM" | "NC", - description: cleanedRow.description, - itemList1: cleanedRow.itemList1, - itemList2: cleanedRow.itemList2, - itemList3: cleanedRow.itemList3, - itemList4: cleanedRow.itemList4, + description: null, + itemList: cleanedRow.itemList, + subItemList: cleanedRow.subItemList, }); if (result.success) { diff --git a/lib/items-tech/table/hull/item-excel-template.tsx b/lib/items-tech/table/hull/item-excel-template.tsx index f38bb9dc..61fddecc 100644 --- a/lib/items-tech/table/hull/item-excel-template.tsx +++ b/lib/items-tech/table/hull/item-excel-template.tsx @@ -19,13 +19,9 @@ export async function exportHullItemTemplate() { // 컬럼 헤더 정의 및 스타일 적용 worksheet.columns = [ { header: '아이템 코드', key: 'itemCode', width: 15 }, - { header: '아이템 명', key: 'itemName', width: 30 }, { header: '기능(공종)', key: 'workType', width: 15 }, - { header: '설명', key: 'description', width: 50 }, - { header: '항목1', key: 'itemList1', width: 20 }, - { header: '항목2', key: 'itemList2', width: 20 }, - { header: '항목3', key: 'itemList3', width: 20 }, - { header: '항목4', key: 'itemList4', width: 20 }, + { header: '아이템 리스트', key: 'itemList', width: 20 }, + { header: '서브 아이템 리스트', key: 'subItemList', width: 20 }, ]; // 헤더 스타일 적용 @@ -51,24 +47,16 @@ export async function exportHullItemTemplate() { // 샘플 데이터 추가 const sampleData = [ { - itemCode: 'HULL001', - itemName: 'HULL 샘플 아이템 1', + itemCode: 'HULL001', workType: 'HA', - description: '이것은 해양 HULL 샘플 아이템 1의 설명입니다.', - itemList1: '항목1 샘플 데이터', - itemList2: '항목2 샘플 데이터', - itemList3: '항목3 샘플 데이터', - itemList4: '항목4 샘플 데이터' + itemList: '항목1 샘플 데이터', + subItemList: '항목2 샘플 데이터', }, { - itemCode: 'HULL002', - itemName: 'HULL 샘플 아이템 2', + itemCode: 'HULL002', workType: 'HE', - description: '이것은 해양 HULL 샘플 아이템 2의 설명입니다.', - itemList1: '항목1 샘플 데이터', - itemList2: '항목2 샘플 데이터', - itemList3: '', - itemList4: '' + itemList: '항목1 샘플 데이터', + subItemList: '항목2 샘플 데이터', } ]; @@ -94,7 +82,9 @@ export async function exportHullItemTemplate() { // 워크시트에 공종 유형 관련 메모 추가 const infoRow = worksheet.addRow(['공종 유형 안내: ' + HULL_WORK_TYPES.join(', ')]); infoRow.font = { bold: true, color: { argb: 'FF0000FF' } }; - worksheet.mergeCells(`A${infoRow.number}:H${infoRow.number}`); + worksheet.mergeCells(`A${infoRow.number}:F${infoRow.number}`); + + // 워크시트 보호 (선택적) worksheet.protect('', { diff --git a/lib/items-tech/table/hull/offshore-hull-table-columns.tsx b/lib/items-tech/table/hull/offshore-hull-table-columns.tsx index f5db40d8..7bc02173 100644 --- a/lib/items-tech/table/hull/offshore-hull-table-columns.tsx +++ b/lib/items-tech/table/hull/offshore-hull-table-columns.tsx @@ -23,10 +23,8 @@ interface OffshoreHullTableItem { id: number;
itemId: number;
workType: "HA" | "HE" | "HH" | "HM" | "NC";
- itemList1: string | null;
- itemList2: string | null;
- itemList3: string | null;
- itemList4: string | null;
+ itemList: string | null;
+ subItemList: string | null;
itemCode: string;
itemName: string;
description: string | null;
@@ -107,11 +105,10 @@ export function getOffshoreHullColumns({ setRowAction }: GetColumnsProps): Colum }
// ----------------------------------------------------------------
- // 3) 데이터 컬럼들을 그룹별로 구성
+ // 3) 데이터 컬럼들 정의
// ----------------------------------------------------------------
- // 3-1) 기본 정보 그룹 컬럼
- const basicInfoColumns: ColumnDef<OffshoreHullTableItem>[] = [
+ const dataColumns: ColumnDef<OffshoreHullTableItem>[] = [
{
accessorKey: "itemCode",
header: ({ column }) => (
@@ -122,20 +119,6 @@ export function getOffshoreHullColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true,
meta: {
excelHeader: "Material Group",
- group: "기본 정보",
- },
- },
- {
- accessorKey: "itemName",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="Description" />
- ),
- cell: ({ row }) => <div>{row.original.itemName}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "Description",
- group: "기본 정보",
},
},
{
@@ -148,82 +131,32 @@ export function getOffshoreHullColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true,
meta: {
excelHeader: "기능(공종)",
- group: "기본 정보",
- },
- },
- {
- accessorKey: "description",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="Size/Dimension" />
- ),
- cell: ({ row }) => <div>{row.original.description || "-"}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "Size/Dimension",
- group: "기본 정보",
- },
- },
- ]
-
- // 3-2) 아이템 리스트 그룹 컬럼
- const itemListColumns: ColumnDef<OffshoreHullTableItem>[] = [
- {
- accessorKey: "itemList1",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템 리스트 1" />
- ),
- cell: ({ row }) => <div>{row.original.itemList1 || "-"}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "아이템 리스트 1",
- group: "아이템 리스트",
- },
- },
- {
- accessorKey: "itemList2",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템 리스트 2" />
- ),
- cell: ({ row }) => <div>{row.original.itemList2 || "-"}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "아이템 리스트 2",
- group: "아이템 리스트",
},
},
{
- accessorKey: "itemList3",
+ accessorKey: "itemList",
header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템 리스트 3" />
+ <DataTableColumnHeaderSimple column={column} title="아이템 리스트" />
),
- cell: ({ row }) => <div>{row.original.itemList3 || "-"}</div>,
+ cell: ({ row }) => <div>{row.original.itemList || "-"}</div>,
enableSorting: true,
enableHiding: true,
meta: {
- excelHeader: "아이템 리스트 3",
- group: "아이템 리스트",
+ excelHeader: "아이템 리스트",
},
},
{
- accessorKey: "itemList4",
+ accessorKey: "subItemList",
header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템 리스트 4" />
+ <DataTableColumnHeaderSimple column={column} title="서브 아이템 리스트" />
),
- cell: ({ row }) => <div>{row.original.itemList4 || "-"}</div>,
+ cell: ({ row }) => <div>{row.original.subItemList || "-"}</div>,
enableSorting: true,
enableHiding: true,
meta: {
- excelHeader: "아이템 리스트 4",
- group: "아이템 리스트",
+ excelHeader: "서브 아이템 리스트",
},
},
- ]
-
- // 3-3) 메타데이터 그룹 컬럼
- const metadataColumns: ColumnDef<OffshoreHullTableItem>[] = [
{
accessorKey: "createdAt",
header: ({ column }) => (
@@ -234,7 +167,6 @@ export function getOffshoreHullColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true,
meta: {
excelHeader: "생성일",
- group: "Metadata",
},
},
{
@@ -247,36 +179,16 @@ export function getOffshoreHullColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true,
meta: {
excelHeader: "수정일",
- group: "Metadata",
},
}
]
-
- // 3-4) 그룹별 컬럼 구성
- const groupedColumns: ColumnDef<OffshoreHullTableItem>[] = [
- {
- id: "기본 정보",
- header: "기본 정보",
- columns: basicInfoColumns,
- },
- {
- id: "아이템 리스트",
- header: "아이템 리스트",
- columns: itemListColumns,
- },
- {
- id: "Metadata",
- header: "Metadata",
- columns: metadataColumns,
- }
- ]
// ----------------------------------------------------------------
- // 4) 최종 컬럼 배열: select, groupedColumns, actions
+ // 4) 최종 컬럼 배열: select, dataColumns, actions
// ----------------------------------------------------------------
return [
selectColumn,
- ...groupedColumns,
+ ...dataColumns,
actionsColumn,
]
}
\ No newline at end of file diff --git a/lib/items-tech/table/hull/offshore-hull-table-toolbar-actions.tsx b/lib/items-tech/table/hull/offshore-hull-table-toolbar-actions.tsx index f5324cb1..ad6f86b2 100644 --- a/lib/items-tech/table/hull/offshore-hull-table-toolbar-actions.tsx +++ b/lib/items-tech/table/hull/offshore-hull-table-toolbar-actions.tsx @@ -24,10 +24,8 @@ interface OffshoreHullItem { id: number;
itemId: number;
workType: "HA" | "HE" | "HH" | "HM" | "NC";
- itemList1: string | null;
- itemList2: string | null;
- itemList3: string | null;
- itemList4: string | null;
+ itemList: string | null;
+ subItemList: string | null;
itemCode: string;
itemName: string;
description: string | null;
@@ -76,10 +74,8 @@ export function OffshoreHullTableToolbarActions({ table }: OffshoreHullTableTool { key: 'itemName', header: '아이템 명' },
{ key: 'description', header: '설명' },
{ key: 'workType', header: '기능(공종)' },
- { key: 'itemList1', header: '아이템 리스트 1' },
- { key: 'itemList2', header: '아이템 리스트 2' },
- { key: 'itemList3', header: '아이템 리스트 3' },
- { key: 'itemList4', header: '아이템 리스트 4' }
+ { key: 'itemList', header: '아이템 리스트' },
+ { key: 'subItemList', header: '서브 아이템 리스트' },
].filter(header => !excludeColumns.includes(header.key));
console.log("내보내기 헤더:", headers);
diff --git a/lib/items-tech/table/hull/offshore-hull-table.tsx b/lib/items-tech/table/hull/offshore-hull-table.tsx index 8efa9c81..00f2c466 100644 --- a/lib/items-tech/table/hull/offshore-hull-table.tsx +++ b/lib/items-tech/table/hull/offshore-hull-table.tsx @@ -21,10 +21,8 @@ type OffshoreHullItem = { id: number;
itemId: number;
workType: "HA" | "HE" | "HH" | "HM" | "NC";
- itemList1: string | null;
- itemList2: string | null;
- itemList3: string | null;
- itemList4: string | null;
+ itemList: string | null;
+ subItemList: string | null;
itemCode: string;
itemName: string;
description: string | null;
@@ -56,8 +54,12 @@ export function OffshoreHullTable({ promises }: OffshoreHullTableProps) { label: "기능(공종)",
},
{
- id: "itemList1",
- label: "아이템 리스트 1",
+ id: "itemList",
+ label: "아이템 리스트",
+ },
+ {
+ id: "subItemList",
+ label: "서브 아이템 리스트",
},
]
@@ -83,23 +85,13 @@ export function OffshoreHullTable({ promises }: OffshoreHullTableProps) { type: "text",
},
{
- id: "itemList1",
- label: "아이템 리스트 1",
- type: "text",
- },
- {
- id: "itemList2",
- label: "아이템 리스트 2",
- type: "text",
- },
- {
- id: "itemList3",
- label: "아이템 리스트 3",
+ id: "itemList",
+ label: "아이템 리스트",
type: "text",
},
{
- id: "itemList4",
- label: "아이템 리스트 4",
+ id: "subItemList",
+ label: "서브 아이템 리스트",
type: "text",
},
]
diff --git a/lib/items-tech/table/ship/Items-ship-table.tsx b/lib/items-tech/table/ship/Items-ship-table.tsx index aee90cfc..29ad8f8a 100644 --- a/lib/items-tech/table/ship/Items-ship-table.tsx +++ b/lib/items-tech/table/ship/Items-ship-table.tsx @@ -24,6 +24,7 @@ type ShipbuildingItem = { shipTypes: string;
itemCode: string;
itemName: string;
+ itemList: string | null;
description: string | null;
createdAt: Date;
updatedAt: Date;
@@ -56,6 +57,10 @@ export function ItemsShipTable({ promises }: ItemsTableProps) { id: "shipTypes",
label: "선종",
},
+ {
+ id: "itemList",
+ label: "아이템 리스트",
+ },
]
/**
@@ -95,6 +100,11 @@ export function ItemsShipTable({ promises }: ItemsTableProps) { label: "선종",
type: "text",
},
+ {
+ id: "itemList",
+ label: "아이템 리스트",
+ type: "text",
+ },
]
const { table } = useDataTable({
diff --git a/lib/items-tech/table/ship/import-item-handler.tsx b/lib/items-tech/table/ship/import-item-handler.tsx index 6ad24398..2a23d9d6 100644 --- a/lib/items-tech/table/ship/import-item-handler.tsx +++ b/lib/items-tech/table/ship/import-item-handler.tsx @@ -8,11 +8,10 @@ const SHIP_TYPES = ['A-MAX', 'S-MAX', 'LNGC', 'VLCC', 'CONT'] as const; // 아이템 데이터 검증을 위한 Zod 스키마 const itemSchema = z.object({ itemCode: z.string().min(1, "아이템 코드는 필수입니다"), - itemName: z.string().min(1, "아이템 명은 필수입니다"), workType: z.enum(["기장", "전장", "선실", "배관", "철의"], { required_error: "기능(공종)은 필수입니다", }), - description: z.string().nullable().optional(), + itemList: z.string().nullable().optional(), }); interface ProcessResult { @@ -25,7 +24,7 @@ interface ProcessResult { * Excel 파일에서 가져온 조선 아이템 데이터 처리하는 함수 */ export async function processFileImport( - jsonData: any[], + jsonData: Record<string, unknown>[], progressCallback?: (current: number, total: number) => void ): Promise<ProcessResult> { // 결과 카운터 초기화 @@ -60,16 +59,14 @@ export async function processFileImport( try { // 필드 매핑 (한글/영문 필드명 모두 지원) const itemCode = row["아이템 코드"] || row["itemCode"] || ""; - const itemName = row["아이템 명"] || row["itemName"] || ""; const workType = row["기능(공종)"] || row["workType"] || ""; - const description = row["설명"] || row["description"] || null; + const itemList = row["아이템 리스트"] || row["itemList"] || null; // 데이터 정제 const cleanedRow = { itemCode: typeof itemCode === 'string' ? itemCode.trim() : String(itemCode).trim(), - itemName: typeof itemName === 'string' ? itemName.trim() : String(itemName).trim(), workType: typeof workType === 'string' ? workType.trim() : String(workType).trim(), - description: description ? (typeof description === 'string' ? description : String(description)) : null, + itemList: itemList ? (typeof itemList === 'string' ? itemList : String(itemList)) : null, }; // 데이터 유효성 검사 @@ -88,27 +85,20 @@ export async function processFileImport( // 선종 데이터 처리 const shipTypeEntries = SHIP_TYPES.map(type => ({ type, - value: row[type]?.toUpperCase() === 'O' + value: row[type] ? String(row[type]).toUpperCase() === 'O' : false })).filter(entry => entry.value); console.log('shipTypeEntries:', shipTypeEntries); + // 선종이 없는 경우에 "option" 값을 사용 if (shipTypeEntries.length === 0) { - errors.push({ - row: rowIndex, - message: "최소 하나 이상의 선종이 'O'로 지정되어야 합니다." - }); - errorCount++; - continue; - } - - // 각 선종에 대해 아이템 생성 - for (const { type } of shipTypeEntries) { + // "option" 값으로 아이템 생성 const result = await createShipbuildingImportItem({ itemCode: cleanedRow.itemCode, - itemName: cleanedRow.itemName, + itemName: "기술영업", // 기본값 사용 workType: cleanedRow.workType as "기장" | "전장" | "선실" | "배관" | "철의", - shipTypes: { [type]: true }, - description: cleanedRow.description, + shipTypes: { "OPTION": true }, + description: null, + itemList: cleanedRow.itemList, }); if (result.success || !result.error) { @@ -116,10 +106,32 @@ export async function processFileImport( } else { errors.push({ row: rowIndex, - message: `${type}: ${result.message || result.error || "알 수 없는 오류"}` + message: `OPTION: ${result.message || result.error || "알 수 없는 오류"}` }); errorCount++; } + } else { + // 각 선종에 대해 아이템 생성 + for (const { type } of shipTypeEntries) { + const result = await createShipbuildingImportItem({ + itemCode: cleanedRow.itemCode, + itemName: "기술영업", // 기본값 사용 + workType: cleanedRow.workType as "기장" | "전장" | "선실" | "배관" | "철의", + shipTypes: { [type]: true }, + description: null, + itemList: cleanedRow.itemList, + }); + + if (result.success || !result.error) { + successCount++; + } else { + errors.push({ + row: rowIndex, + message: `${type}: ${result.message || result.error || "알 수 없는 오류"}` + }); + errorCount++; + } + } } } catch (error) { console.error(`${rowIndex}행 처리 오류:`, error); diff --git a/lib/items-tech/table/ship/item-excel-template.tsx b/lib/items-tech/table/ship/item-excel-template.tsx index 127a1dea..f6b20b6d 100644 --- a/lib/items-tech/table/ship/item-excel-template.tsx +++ b/lib/items-tech/table/ship/item-excel-template.tsx @@ -18,9 +18,8 @@ export async function exportItemTemplate() { // 컬럼 헤더 정의 및 스타일 적용 worksheet.columns = [ { header: '아이템 코드', key: 'itemCode', width: 15 }, - { header: '아이템 명', key: 'itemName', width: 30 }, { header: '기능(공종)', key: 'workType', width: 15 }, - { header: '설명', key: 'description', width: 50 }, + { header: '아이템 리스트', key: 'itemList', width: 30 }, ...SHIP_TYPES.map(type => ({ header: type, key: type, @@ -52,25 +51,33 @@ export async function exportItemTemplate() { const sampleData = [ { itemCode: 'BG0001', - itemName: '샘플 아이템 1', workType: '기장', - description: '이것은 샘플 아이템 1의 설명입니다.', + itemList: '아이템 리스트 내용', 'A-MAX': 'O', 'S-MAX': 'O', 'LNGC': 'O', - 'VLCC': 'X', - 'CONT': 'X' + 'VLCC': ' ', + 'CONT': ' ' }, { itemCode: 'BG0002', - itemName: '샘플 아이템 2', workType: '전장', - description: '이것은 샘플 아이템 2의 설명입니다.', + itemList: '아이템 리스트 내용 2', 'A-MAX': 'O', - 'S-MAX': 'X', + 'S-MAX': ' ', 'LNGC': 'O', 'VLCC': 'O', - 'CONT': 'X' + 'CONT': ' ' + }, + { + itemCode: 'BG0003', + workType: '선실', + itemList: '선종 없는 아이템', + 'A-MAX': ' ', + 'S-MAX': ' ', + 'LNGC': ' ', + 'VLCC': ' ', + 'CONT': ' ' } ]; diff --git a/lib/items-tech/table/ship/items-ship-table-columns.tsx b/lib/items-tech/table/ship/items-ship-table-columns.tsx index 2b46db92..29e1d503 100644 --- a/lib/items-tech/table/ship/items-ship-table-columns.tsx +++ b/lib/items-tech/table/ship/items-ship-table-columns.tsx @@ -24,6 +24,7 @@ interface ShipbuildingTableItem { itemId: number;
workType: "기장" | "전장" | "선실" | "배관" | "철의";
shipTypes: string;
+ itemList: string | null;
itemCode: string;
itemName: string;
description: string | null;
@@ -107,11 +108,10 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum }
// ----------------------------------------------------------------
- // 3) 데이터 컬럼들을 그룹별로 구성
+ // 3) 데이터 컬럼들 정의
// ----------------------------------------------------------------
- // 3-1) 기본 정보 그룹 컬럼
- const basicInfoColumns: ColumnDef<ShipbuildingTableItem>[] = [
+ const dataColumns: ColumnDef<ShipbuildingTableItem>[] = [
{
accessorKey: "itemCode",
header: ({ column }) => (
@@ -122,20 +122,6 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true,
meta: {
excelHeader: "Material Group",
- group: "기본 정보",
- },
- },
- {
- accessorKey: "itemName",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="Description" />
- ),
- cell: ({ row }) => <div>{row.original.itemName}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "Description",
- group: "기본 정보",
},
},
{
@@ -148,44 +134,32 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true,
meta: {
excelHeader: "기능(공종)",
- group: "기본 정보",
},
},
{
- accessorKey: "description",
+ accessorKey: "shipTypes",
header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="Size/Dimension" />
+ <DataTableColumnHeaderSimple column={column} title="선종" />
),
- cell: ({ row }) => <div>{row.original.description || "-"}</div>,
+ cell: ({ row }) => <div>{row.original.shipTypes}</div>,
enableSorting: true,
enableHiding: true,
meta: {
- excelHeader: "Size/Dimension",
- group: "기본 정보",
+ excelHeader: "선종",
},
},
- ]
-
- // 3-2) 선종 정보 그룹 컬럼
- const shipTypesColumns: ColumnDef<ShipbuildingTableItem>[] = [
{
- accessorKey: "shipTypes",
+ accessorKey: "itemList",
header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="선종" />
+ <DataTableColumnHeaderSimple column={column} title="아이템 리스트" />
),
- cell: ({ row }) => <div>{row.original.shipTypes}</div>,
+ cell: ({ row }) => <div>{row.original.itemList || "-"}</div>,
enableSorting: true,
enableHiding: true,
meta: {
- excelHeader: "선종",
- group: "선종",
+ excelHeader: "아이템 리스트",
},
},
- ]
-
- // 3-3) 메타데이터 그룹 컬럼
- const metadataColumns: ColumnDef<ShipbuildingTableItem>[] = [
-
{
accessorKey: "createdAt",
header: ({ column }) => (
@@ -196,7 +170,6 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true,
meta: {
excelHeader: "생성일",
- group: "Metadata",
},
},
{
@@ -209,36 +182,16 @@ export function getShipbuildingColumns({ setRowAction }: GetColumnsProps): Colum enableHiding: true,
meta: {
excelHeader: "수정일",
- group: "Metadata",
},
}
]
-
- // 3-4) 그룹별 컬럼 구성
- const groupedColumns: ColumnDef<ShipbuildingTableItem>[] = [
- {
- id: "기본 정보",
- header: "기본 정보",
- columns: basicInfoColumns,
- },
- {
- id: "선종",
- header: "선종",
- columns: shipTypesColumns,
- },
- {
- id: "Metadata",
- header: "Metadata",
- columns: metadataColumns,
- }
- ]
// ----------------------------------------------------------------
- // 4) 최종 컬럼 배열: select, groupedColumns, actions
+ // 4) 최종 컬럼 배열: select, dataColumns, actions
// ----------------------------------------------------------------
return [
selectColumn,
- ...groupedColumns,
+ ...dataColumns,
actionsColumn,
]
}
\ No newline at end of file diff --git a/lib/items-tech/table/ship/items-table-toolbar-actions.tsx b/lib/items-tech/table/ship/items-table-toolbar-actions.tsx index 6cae61af..677173d1 100644 --- a/lib/items-tech/table/ship/items-table-toolbar-actions.tsx +++ b/lib/items-tech/table/ship/items-table-toolbar-actions.tsx @@ -27,6 +27,7 @@ interface ShipbuildingItem { shipTypes: string; itemCode: string; itemName: string; + itemList: string | null; description: string | null; createdAt: Date; updatedAt: Date; @@ -73,7 +74,8 @@ export function ItemsTableToolbarActions({ table }: ItemsTableToolbarActionsProp { key: 'itemName', header: '아이템 명' }, { key: 'description', header: '설명' }, { key: 'workType', header: '기능(공종)' }, - { key: 'shipTypes', header: '선종' } + { key: 'shipTypes', header: '선종' }, + { key: 'itemList', header: '아이템 리스트' } ].filter(header => !excludeColumns.includes(header.key)); console.log("내보내기 헤더:", headers); diff --git a/lib/items-tech/table/top/import-item-handler.tsx b/lib/items-tech/table/top/import-item-handler.tsx index de1638a8..d6b81964 100644 --- a/lib/items-tech/table/top/import-item-handler.tsx +++ b/lib/items-tech/table/top/import-item-handler.tsx @@ -9,15 +9,11 @@ const TOP_WORK_TYPES = ["TM", "TS", "TE", "TP"] as const; // 아이템 데이터 검증을 위한 Zod 스키마 const itemSchema = z.object({ itemCode: z.string().min(1, "아이템 코드는 필수입니다"), - itemName: z.string().min(1, "아이템 명은 필수입니다"), workType: z.enum(TOP_WORK_TYPES, { required_error: "기능(공종)은 필수입니다", }), - description: z.string().nullable().optional(), - itemList1: z.string().nullable().optional(), - itemList2: z.string().nullable().optional(), - itemList3: z.string().nullable().optional(), - itemList4: z.string().nullable().optional(), + itemList: z.string().nullable().optional(), + subItemList: z.string().nullable().optional(), }); interface ProcessResult { @@ -30,7 +26,7 @@ interface ProcessResult { * Excel 파일에서 가져온 해양 TOP 아이템 데이터 처리하는 함수 */ export async function processTopFileImport( - jsonData: any[], + jsonData: Record<string, unknown>[], progressCallback?: (current: number, total: number) => void ): Promise<ProcessResult> { // 결과 카운터 초기화 @@ -65,24 +61,16 @@ export async function processTopFileImport( try { // 필드 매핑 (한글/영문 필드명 모두 지원) const itemCode = row["아이템 코드"] || row["itemCode"] || ""; - const itemName = row["아이템 명"] || row["itemName"] || ""; const workType = row["기능(공종)"] || row["workType"] || ""; - const description = row["설명"] || row["description"] || null; - const itemList1 = row["항목1"] || row["itemList1"] || null; - const itemList2 = row["항목2"] || row["itemList2"] || null; - const itemList3 = row["항목3"] || row["itemList3"] || null; - const itemList4 = row["항목4"] || row["itemList4"] || null; + const itemList = row["아이템 리스트"] || row["itemList"] || null; + const subItemList = row["서브 아이템 리스트"] || row["subItemList"] || null; // 데이터 정제 const cleanedRow = { itemCode: typeof itemCode === 'string' ? itemCode.trim() : String(itemCode).trim(), - itemName: typeof itemName === 'string' ? itemName.trim() : String(itemName).trim(), workType: typeof workType === 'string' ? workType.trim() : String(workType).trim(), - description: description ? (typeof description === 'string' ? description : String(description)) : null, - itemList1: itemList1 ? (typeof itemList1 === 'string' ? itemList1 : String(itemList1)) : null, - itemList2: itemList2 ? (typeof itemList2 === 'string' ? itemList2 : String(itemList2)) : null, - itemList3: itemList3 ? (typeof itemList3 === 'string' ? itemList3 : String(itemList3)) : null, - itemList4: itemList4 ? (typeof itemList4 === 'string' ? itemList4 : String(itemList4)) : null, + itemList: itemList ? (typeof itemList === 'string' ? itemList : String(itemList)) : null, + subItemList: subItemList ? (typeof subItemList === 'string' ? subItemList : String(subItemList)) : null, }; // 데이터 유효성 검사 @@ -101,13 +89,11 @@ export async function processTopFileImport( // 해양 TOP 아이템 생성 const result = await createOffshoreTopItem({ itemCode: cleanedRow.itemCode, - itemName: cleanedRow.itemName, + itemName: "기술영업", // 기본값 사용 workType: cleanedRow.workType as "TM" | "TS" | "TE" | "TP", - description: cleanedRow.description, - itemList1: cleanedRow.itemList1, - itemList2: cleanedRow.itemList2, - itemList3: cleanedRow.itemList3, - itemList4: cleanedRow.itemList4, + description: null, + itemList: cleanedRow.itemList, + subItemList: cleanedRow.subItemList, }); if (result.success) { diff --git a/lib/items-tech/table/top/item-excel-template.tsx b/lib/items-tech/table/top/item-excel-template.tsx index 4514af59..f0e10d82 100644 --- a/lib/items-tech/table/top/item-excel-template.tsx +++ b/lib/items-tech/table/top/item-excel-template.tsx @@ -19,13 +19,10 @@ export async function exportTopItemTemplate() { // 컬럼 헤더 정의 및 스타일 적용 worksheet.columns = [ { header: '아이템 코드', key: 'itemCode', width: 15 }, - { header: '아이템 명', key: 'itemName', width: 30 }, { header: '기능(공종)', key: 'workType', width: 15 }, - { header: '설명', key: 'description', width: 50 }, - { header: '항목1', key: 'itemList1', width: 20 }, - { header: '항목2', key: 'itemList2', width: 20 }, - { header: '항목3', key: 'itemList3', width: 20 }, - { header: '항목4', key: 'itemList4', width: 20 }, + { header: '아이템 리스트', key: 'itemList', width: 20 }, + { header: '서브 아이템 리스트', key: 'subItemList', width: 20 }, + ]; // 헤더 스타일 적용 @@ -51,25 +48,18 @@ export async function exportTopItemTemplate() { // 샘플 데이터 추가 const sampleData = [ { - itemCode: 'TOP001', - itemName: 'TOP 샘플 아이템 1', + itemCode: 'TOP001', workType: 'TM', - description: '이것은 해양 TOP 샘플 아이템 1의 설명입니다.', - itemList1: '항목1 샘플 데이터', - itemList2: '항목2 샘플 데이터', - itemList3: '항목3 샘플 데이터', - itemList4: '항목4 샘플 데이터' + itemList: '항목1 샘플 데이터', + subItemList: '항목2 샘플 데이터', }, { - itemCode: 'TOP002', - itemName: 'TOP 샘플 아이템 2', + itemCode: 'TOP002', workType: 'TS', - description: '이것은 해양 TOP 샘플 아이템 2의 설명입니다.', - itemList1: '항목1 샘플 데이터', - itemList2: '항목2 샘플 데이터', - itemList3: '', - itemList4: '' + itemList: '항목1 샘플 데이터', + subItemList: '항목2 샘플 데이터', } + ]; // 데이터 행 추가 @@ -94,7 +84,8 @@ export async function exportTopItemTemplate() { // 워크시트에 공종 유형 관련 메모 추가 const infoRow = worksheet.addRow(['공종 유형 안내: ' + TOP_WORK_TYPES.join(', ')]); infoRow.font = { bold: true, color: { argb: 'FF0000FF' } }; - worksheet.mergeCells(`A${infoRow.number}:H${infoRow.number}`); + worksheet.mergeCells(`A${infoRow.number}:F${infoRow.number}`); + // 워크시트 보호 (선택적) worksheet.protect('', { diff --git a/lib/items-tech/table/top/offshore-top-table-columns.tsx b/lib/items-tech/table/top/offshore-top-table-columns.tsx index 4ccb2003..4746f226 100644 --- a/lib/items-tech/table/top/offshore-top-table-columns.tsx +++ b/lib/items-tech/table/top/offshore-top-table-columns.tsx @@ -23,10 +23,8 @@ interface OffshoreTopTableItem { id: number;
itemId: number;
workType: "TM" | "TS" | "TE" | "TP";
- itemList1: string | null;
- itemList2: string | null;
- itemList3: string | null;
- itemList4: string | null;
+ itemList: string | null;
+ subItemList: string | null;
itemCode: string;
itemName: string;
description: string | null;
@@ -107,11 +105,10 @@ export function getOffshoreTopColumns({ setRowAction }: GetColumnsProps): Column }
// ----------------------------------------------------------------
- // 3) 데이터 컬럼들을 그룹별로 구성
+ // 3) 데이터 컬럼들 정의
// ----------------------------------------------------------------
- // 3-1) 기본 정보 그룹 컬럼
- const basicInfoColumns: ColumnDef<OffshoreTopTableItem>[] = [
+ const dataColumns: ColumnDef<OffshoreTopTableItem>[] = [
{
accessorKey: "itemCode",
header: ({ column }) => (
@@ -122,20 +119,6 @@ export function getOffshoreTopColumns({ setRowAction }: GetColumnsProps): Column enableHiding: true,
meta: {
excelHeader: "Material Group",
- group: "기본 정보",
- },
- },
- {
- accessorKey: "itemName",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="Description" />
- ),
- cell: ({ row }) => <div>{row.original.itemName}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "Description",
- group: "기본 정보",
},
},
{
@@ -148,82 +131,32 @@ export function getOffshoreTopColumns({ setRowAction }: GetColumnsProps): Column enableHiding: true,
meta: {
excelHeader: "기능(공종)",
- group: "기본 정보",
- },
- },
- {
- accessorKey: "description",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="Size/Dimension" />
- ),
- cell: ({ row }) => <div>{row.original.description || "-"}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "Size/Dimension",
- group: "기본 정보",
- },
- },
- ]
-
- // 3-2) 아이템 리스트 그룹 컬럼
- const itemListColumns: ColumnDef<OffshoreTopTableItem>[] = [
- {
- accessorKey: "itemList1",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템 리스트 1" />
- ),
- cell: ({ row }) => <div>{row.original.itemList1 || "-"}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "아이템 리스트 1",
- group: "아이템 리스트",
- },
- },
- {
- accessorKey: "itemList2",
- header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템 리스트 2" />
- ),
- cell: ({ row }) => <div>{row.original.itemList2 || "-"}</div>,
- enableSorting: true,
- enableHiding: true,
- meta: {
- excelHeader: "아이템 리스트 2",
- group: "아이템 리스트",
},
},
{
- accessorKey: "itemList3",
+ accessorKey: "itemList",
header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템 리스트 3" />
+ <DataTableColumnHeaderSimple column={column} title="아이템 리스트" />
),
- cell: ({ row }) => <div>{row.original.itemList3 || "-"}</div>,
+ cell: ({ row }) => <div>{row.original.itemList || "-"}</div>,
enableSorting: true,
enableHiding: true,
meta: {
- excelHeader: "아이템 리스트 3",
- group: "아이템 리스트",
+ excelHeader: "아이템 리스트",
},
},
{
- accessorKey: "itemList4",
+ accessorKey: "subItemList",
header: ({ column }) => (
- <DataTableColumnHeaderSimple column={column} title="아이템 리스트 4" />
+ <DataTableColumnHeaderSimple column={column} title="서브 아이템 리스트" />
),
- cell: ({ row }) => <div>{row.original.itemList4 || "-"}</div>,
+ cell: ({ row }) => <div>{row.original.subItemList || "-"}</div>,
enableSorting: true,
enableHiding: true,
meta: {
- excelHeader: "아이템 리스트 4",
- group: "아이템 리스트",
+ excelHeader: "서브 아이템 리스트",
},
},
- ]
-
- // 3-3) 메타데이터 그룹 컬럼
- const metadataColumns: ColumnDef<OffshoreTopTableItem>[] = [
{
accessorKey: "createdAt",
header: ({ column }) => (
@@ -234,7 +167,6 @@ export function getOffshoreTopColumns({ setRowAction }: GetColumnsProps): Column enableHiding: true,
meta: {
excelHeader: "생성일",
- group: "Metadata",
},
},
{
@@ -247,36 +179,16 @@ export function getOffshoreTopColumns({ setRowAction }: GetColumnsProps): Column enableHiding: true,
meta: {
excelHeader: "수정일",
- group: "Metadata",
},
}
]
-
- // 3-4) 그룹별 컬럼 구성
- const groupedColumns: ColumnDef<OffshoreTopTableItem>[] = [
- {
- id: "기본 정보",
- header: "기본 정보",
- columns: basicInfoColumns,
- },
- {
- id: "아이템 리스트",
- header: "아이템 리스트",
- columns: itemListColumns,
- },
- {
- id: "Metadata",
- header: "Metadata",
- columns: metadataColumns,
- }
- ]
// ----------------------------------------------------------------
- // 4) 최종 컬럼 배열: select, groupedColumns, actions
+ // 4) 최종 컬럼 배열: select, dataColumns, actions
// ----------------------------------------------------------------
return [
selectColumn,
- ...groupedColumns,
+ ...dataColumns,
actionsColumn,
]
}
\ No newline at end of file diff --git a/lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx b/lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx index 324312aa..f91adf96 100644 --- a/lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx +++ b/lib/items-tech/table/top/offshore-top-table-toolbar-actions.tsx @@ -24,10 +24,8 @@ interface OffshoreTopItem { id: number;
itemId: number;
workType: "TM" | "TS" | "TE" | "TP";
- itemList1: string | null;
- itemList2: string | null;
- itemList3: string | null;
- itemList4: string | null;
+ itemList: string | null;
+ subItemList: string | null;
itemCode: string;
itemName: string;
description: string | null;
@@ -76,10 +74,8 @@ export function OffshoreTopTableToolbarActions({ table }: OffshoreTopTableToolba { key: 'itemName', header: '아이템 명' },
{ key: 'description', header: '설명' },
{ key: 'workType', header: '기능(공종)' },
- { key: 'itemList1', header: '아이템 리스트 1' },
- { key: 'itemList2', header: '아이템 리스트 2' },
- { key: 'itemList3', header: '아이템 리스트 3' },
- { key: 'itemList4', header: '아이템 리스트 4' }
+ { key: 'itemList', header: '아이템 리스트' },
+ { key: 'subItemList', header: '서브 아이템 리스트' },
].filter(header => !excludeColumns.includes(header.key));
console.log("내보내기 헤더:", headers);
diff --git a/lib/items-tech/table/top/offshore-top-table.tsx b/lib/items-tech/table/top/offshore-top-table.tsx index dedf766a..689f1db3 100644 --- a/lib/items-tech/table/top/offshore-top-table.tsx +++ b/lib/items-tech/table/top/offshore-top-table.tsx @@ -21,10 +21,8 @@ type OffshoreTopItem = { id: number;
itemId: number;
workType: "TM" | "TS" | "TE" | "TP";
- itemList1: string | null;
- itemList2: string | null;
- itemList3: string | null;
- itemList4: string | null;
+ itemList: string | null;
+ subItemList: string | null;
itemCode: string;
itemName: string;
description: string | null;
@@ -56,8 +54,8 @@ export function OffshoreTopTable({ promises }: OffshoreTopTableProps) { label: "기능(공종)",
},
{
- id: "itemList1",
- label: "아이템 리스트 1",
+ id: "itemList",
+ label: "아이템 리스트",
},
]
@@ -83,25 +81,16 @@ export function OffshoreTopTable({ promises }: OffshoreTopTableProps) { type: "text",
},
{
- id: "itemList1",
- label: "아이템 리스트 1",
+ id: "itemList",
+ label: "아이템 리스트",
type: "text",
},
{
- id: "itemList2",
- label: "아이템 리스트 2",
- type: "text",
- },
- {
- id: "itemList3",
- label: "아이템 리스트 3",
- type: "text",
- },
- {
- id: "itemList4",
- label: "아이템 리스트 4",
+ id: "subItemList",
+ label: "서브 아이템 리스트",
type: "text",
},
+
]
const { table } = useDataTable({
diff --git a/lib/items-tech/table/update-items-sheet.tsx b/lib/items-tech/table/update-items-sheet.tsx index 2db3b193..efab4b1a 100644 --- a/lib/items-tech/table/update-items-sheet.tsx +++ b/lib/items-tech/table/update-items-sheet.tsx @@ -29,7 +29,6 @@ import { SelectTrigger,
SelectValue,
} from "@/components/ui/select"
-import { Textarea } from "@/components/ui/textarea"
import { toast } from "sonner"
import {
@@ -75,22 +74,19 @@ interface CommonItemFields { type ShipbuildingItem = CommonItemFields & {
workType: "기장" | "전장" | "선실" | "배관" | "철의"
shipTypes: string
+ itemList: string | null
}
type OffshoreTopItem = CommonItemFields & {
workType: "TM" | "TS" | "TE" | "TP"
- itemList1: string | null
- itemList2: string | null
- itemList3: string | null
- itemList4: string | null
+ itemList: string | null
+ subItemList: string | null
}
type OffshoreHullItem = CommonItemFields & {
workType: "HA" | "HE" | "HH" | "HM" | "NC"
- itemList1: string | null
- itemList2: string | null
- itemList3: string | null
- itemList4: string | null
+ itemList: string | null
+ subItemList: string | null
}
type UpdateItemSchema = {
@@ -99,10 +95,8 @@ type UpdateItemSchema = { description?: string
workType?: string
shipTypes?: string
- itemList1?: string
- itemList2?: string
- itemList3?: string
- itemList4?: string
+ itemList?: string
+ subItemList?: string
}
interface UpdateItemSheetProps {
@@ -118,7 +112,6 @@ export function UpdateItemSheet({ item, itemType, open, onOpenChange }: UpdateIt // 초기값 설정
const form = useForm<UpdateItemSchema>({
defaultValues: {
- itemCode: item.itemCode,
itemName: item.itemName,
description: item.description || "",
workType: item.workType,
@@ -133,16 +126,15 @@ export function UpdateItemSheet({ item, itemType, open, onOpenChange }: UpdateIt switch (itemType) {
case 'shipbuilding':
return {
- shipTypes: (item as ShipbuildingItem).shipTypes
+ shipTypes: (item as ShipbuildingItem).shipTypes,
+ itemList: (item as ShipbuildingItem).itemList || ""
};
case 'offshoreTop':
case 'offshoreHull':
const offshoreItem = item as OffshoreTopItem | OffshoreHullItem;
return {
- itemList1: offshoreItem.itemList1 || "",
- itemList2: offshoreItem.itemList2 || "",
- itemList3: offshoreItem.itemList3 || "",
- itemList4: offshoreItem.itemList4 || "",
+ itemList: offshoreItem.itemList || "",
+ subItemList: offshoreItem.subItemList || ""
};
default:
return {};
@@ -158,19 +150,22 @@ export function UpdateItemSheet({ item, itemType, open, onOpenChange }: UpdateIt case 'shipbuilding':
result = await modifyShipbuildingItem({
...data,
- id: item.id
+ id: item.id,
+ itemCode: item.itemCode // itemCode는 변경 불가, 원래 값 사용
});
break;
case 'offshoreTop':
result = await modifyOffshoreTopItem({
...data,
- id: item.id
+ id: item.id,
+ itemCode: item.itemCode // itemCode는 변경 불가, 원래 값 사용
});
break;
case 'offshoreHull':
result = await modifyOffshoreHullItem({
...data,
- id: item.id
+ id: item.id,
+ itemCode: item.itemCode // itemCode는 변경 불가, 원래 값 사용
});
break;
default:
@@ -227,34 +222,19 @@ export function UpdateItemSheet({ item, itemType, open, onOpenChange }: UpdateIt {getItemTypeLabel()} 정보를 수정합니다. 수정할 필드를 입력해주세요.
</SheetDescription>
</SheetHeader>
+
<Form {...form}>
<form onSubmit={form.handleSubmit(onSubmit)} className="space-y-4">
- <FormField
- control={form.control}
- name="itemCode"
- render={({ field }) => (
- <FormItem>
- <FormLabel>Material Group</FormLabel>
- <FormControl>
- <Input placeholder="Material Group을 입력하세요" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- <FormField
- control={form.control}
- name="itemName"
- render={({ field }) => (
- <FormItem>
- <FormLabel>Description</FormLabel>
- <FormControl>
- <Input placeholder="Description을 입력하세요" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
+ {/* Material Group을 Form 안으로 이동 */}
+ <div className="mt-4">
+ <div className="grid gap-2">
+ <label className="text-sm font-medium leading-none">
+ Material Group (수정 불가)
+ </label>
+ <Input value={item.itemCode} disabled readOnly />
+ </div>
+ </div>
+
<FormField
control={form.control}
name="workType"
@@ -285,32 +265,15 @@ export function UpdateItemSheet({ item, itemType, open, onOpenChange }: UpdateIt {/* 조선 아이템 전용 필드 */}
{itemType === 'shipbuilding' && (
- <FormField
- control={form.control}
- name="shipTypes"
- render={({ field }) => (
- <FormItem>
- <FormLabel>선종</FormLabel>
- <FormControl>
- <Input placeholder="선종을 입력하세요" {...field} />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
- )}
-
- {/* 해양 TOP 또는 HULL 아이템 전용 필드 */}
- {(itemType === 'offshoreTop' || itemType === 'offshoreHull') && (
<>
<FormField
control={form.control}
- name="itemList1"
+ name="shipTypes"
render={({ field }) => (
<FormItem>
- <FormLabel>Item List 1</FormLabel>
+ <FormLabel>선종</FormLabel>
<FormControl>
- <Input placeholder="Item List 1을 입력하세요" {...field} />
+ <Input placeholder="선종을 입력하세요" {...field} />
</FormControl>
<FormMessage />
</FormItem>
@@ -318,25 +281,31 @@ export function UpdateItemSheet({ item, itemType, open, onOpenChange }: UpdateIt />
<FormField
control={form.control}
- name="itemList2"
+ name="itemList"
render={({ field }) => (
<FormItem>
- <FormLabel>Item List 2</FormLabel>
+ <FormLabel>아이템 리스트</FormLabel>
<FormControl>
- <Input placeholder="Item List 2를 입력하세요" {...field} />
+ <Input placeholder="아이템 리스트를 입력하세요" {...field} />
</FormControl>
<FormMessage />
</FormItem>
)}
/>
+ </>
+ )}
+
+ {/* 해양 TOP 또는 HULL 아이템 전용 필드 */}
+ {(itemType === 'offshoreTop' || itemType === 'offshoreHull') && (
+ <>
<FormField
control={form.control}
- name="itemList3"
+ name="itemList"
render={({ field }) => (
<FormItem>
- <FormLabel>Item List 3</FormLabel>
+ <FormLabel>아이템 리스트</FormLabel>
<FormControl>
- <Input placeholder="Item List 3을 입력하세요" {...field} />
+ <Input placeholder="아이템 리스트를 입력하세요" {...field} />
</FormControl>
<FormMessage />
</FormItem>
@@ -344,12 +313,12 @@ export function UpdateItemSheet({ item, itemType, open, onOpenChange }: UpdateIt />
<FormField
control={form.control}
- name="itemList4"
+ name="subItemList"
render={({ field }) => (
<FormItem>
- <FormLabel>Item List 4</FormLabel>
+ <FormLabel>서브 아이템 리스트</FormLabel>
<FormControl>
- <Input placeholder="Item List 4를 입력하세요" {...field} />
+ <Input placeholder="서브 아이템 리스트를 입력하세요" {...field} />
</FormControl>
<FormMessage />
</FormItem>
@@ -357,23 +326,6 @@ export function UpdateItemSheet({ item, itemType, open, onOpenChange }: UpdateIt />
</>
)}
-
- <FormField
- control={form.control}
- name="description"
- render={({ field }) => (
- <FormItem>
- <FormLabel>Size/Dimension</FormLabel>
- <FormControl>
- <Textarea
- placeholder="Size/Dimension을 입력하세요"
- {...field}
- />
- </FormControl>
- <FormMessage />
- </FormItem>
- )}
- />
<SheetFooter>
<SheetClose asChild>
<Button variant="outline">취소</Button>
|
