138 lines
4.6 KiB
TypeScript
138 lines
4.6 KiB
TypeScript
"use client";
|
|
|
|
import React, { useState, useEffect } from "react";
|
|
import { Button } from "@/components/ui/button";
|
|
import { Plus } from "lucide-react";
|
|
import { ItemSelectionModal } from "./ItemSelectionModal";
|
|
import { RepeaterTable } from "./RepeaterTable";
|
|
import { ModalRepeaterTableProps } from "./types";
|
|
import { useCalculation } from "./useCalculation";
|
|
import { cn } from "@/lib/utils";
|
|
|
|
interface ModalRepeaterTableComponentProps extends Partial<ModalRepeaterTableProps> {
|
|
config?: ModalRepeaterTableProps;
|
|
}
|
|
|
|
export function ModalRepeaterTableComponent({
|
|
config,
|
|
sourceTable: propSourceTable,
|
|
sourceColumns: propSourceColumns,
|
|
sourceSearchFields: propSourceSearchFields,
|
|
modalTitle: propModalTitle,
|
|
modalButtonText: propModalButtonText,
|
|
multiSelect: propMultiSelect,
|
|
columns: propColumns,
|
|
calculationRules: propCalculationRules,
|
|
value: propValue,
|
|
onChange: propOnChange,
|
|
uniqueField: propUniqueField,
|
|
filterCondition: propFilterCondition,
|
|
companyCode: propCompanyCode,
|
|
className,
|
|
}: ModalRepeaterTableComponentProps) {
|
|
// config prop 우선, 없으면 개별 prop 사용
|
|
const sourceTable = config?.sourceTable || propSourceTable || "";
|
|
const sourceColumns = config?.sourceColumns || propSourceColumns || [];
|
|
const sourceSearchFields = config?.sourceSearchFields || propSourceSearchFields || [];
|
|
const modalTitle = config?.modalTitle || propModalTitle || "항목 검색";
|
|
const modalButtonText = config?.modalButtonText || propModalButtonText || "품목 검색";
|
|
const multiSelect = config?.multiSelect ?? propMultiSelect ?? true;
|
|
const columns = config?.columns || propColumns || [];
|
|
const calculationRules = config?.calculationRules || propCalculationRules || [];
|
|
const value = config?.value || propValue || [];
|
|
const onChange = config?.onChange || propOnChange || (() => {});
|
|
const uniqueField = config?.uniqueField || propUniqueField;
|
|
const filterCondition = config?.filterCondition || propFilterCondition || {};
|
|
const companyCode = config?.companyCode || propCompanyCode;
|
|
const [modalOpen, setModalOpen] = useState(false);
|
|
const { calculateRow, calculateAll } = useCalculation(calculationRules);
|
|
|
|
// 초기 데이터에 계산 필드 적용
|
|
useEffect(() => {
|
|
if (value.length > 0 && calculationRules.length > 0) {
|
|
const calculated = calculateAll(value);
|
|
// 값이 실제로 변경된 경우만 업데이트
|
|
if (JSON.stringify(calculated) !== JSON.stringify(value)) {
|
|
onChange(calculated);
|
|
}
|
|
}
|
|
}, []);
|
|
|
|
const handleAddItems = (items: any[]) => {
|
|
// 기본값 적용
|
|
const itemsWithDefaults = items.map((item) => {
|
|
const newItem = { ...item };
|
|
columns.forEach((col) => {
|
|
if (col.defaultValue !== undefined && newItem[col.field] === undefined) {
|
|
newItem[col.field] = col.defaultValue;
|
|
}
|
|
});
|
|
return newItem;
|
|
});
|
|
|
|
// 계산 필드 업데이트
|
|
const calculatedItems = calculateAll(itemsWithDefaults);
|
|
|
|
// 기존 데이터에 추가
|
|
onChange([...value, ...calculatedItems]);
|
|
};
|
|
|
|
const handleRowChange = (index: number, newRow: any) => {
|
|
// 계산 필드 업데이트
|
|
const calculatedRow = calculateRow(newRow);
|
|
|
|
// 데이터 업데이트
|
|
const newData = [...value];
|
|
newData[index] = calculatedRow;
|
|
onChange(newData);
|
|
};
|
|
|
|
const handleRowDelete = (index: number) => {
|
|
const newData = value.filter((_, i) => i !== index);
|
|
onChange(newData);
|
|
};
|
|
|
|
return (
|
|
<div className={cn("space-y-4", className)}>
|
|
{/* 추가 버튼 */}
|
|
<div className="flex justify-between items-center">
|
|
<div className="text-sm text-muted-foreground">
|
|
{value.length > 0 && `${value.length}개 항목`}
|
|
</div>
|
|
<Button
|
|
onClick={() => setModalOpen(true)}
|
|
className="h-8 text-xs sm:h-10 sm:text-sm"
|
|
>
|
|
<Plus className="h-4 w-4 mr-2" />
|
|
{modalButtonText}
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Repeater 테이블 */}
|
|
<RepeaterTable
|
|
columns={columns}
|
|
data={value}
|
|
onDataChange={onChange}
|
|
onRowChange={handleRowChange}
|
|
onRowDelete={handleRowDelete}
|
|
/>
|
|
|
|
{/* 항목 선택 모달 */}
|
|
<ItemSelectionModal
|
|
open={modalOpen}
|
|
onOpenChange={setModalOpen}
|
|
sourceTable={sourceTable}
|
|
sourceColumns={sourceColumns}
|
|
sourceSearchFields={sourceSearchFields}
|
|
multiSelect={multiSelect}
|
|
filterCondition={filterCondition}
|
|
modalTitle={modalTitle}
|
|
alreadySelected={value}
|
|
uniqueField={uniqueField}
|
|
onSelect={handleAddItems}
|
|
/>
|
|
</div>
|
|
);
|
|
}
|
|
|