데이터 표시 오류 수정
This commit is contained in:
parent
1503dd87bb
commit
e4b1f7e4d8
|
|
@ -48,6 +48,12 @@ interface SplitPanelContextValue {
|
|||
|
||||
// screenId로 위치 찾기
|
||||
getPositionByScreenId: (screenId: number) => SplitPanelPosition | null;
|
||||
|
||||
// 🆕 우측에 추가된 항목 ID 관리 (좌측 테이블에서 필터링용)
|
||||
addedItemIds: Set<string>;
|
||||
addItemIds: (ids: string[]) => void;
|
||||
removeItemIds: (ids: string[]) => void;
|
||||
clearItemIds: () => void;
|
||||
}
|
||||
|
||||
const SplitPanelContext = createContext<SplitPanelContextValue | null>(null);
|
||||
|
|
@ -74,6 +80,9 @@ export function SplitPanelProvider({
|
|||
|
||||
// 강제 리렌더링용 상태
|
||||
const [, forceUpdate] = useState(0);
|
||||
|
||||
// 🆕 우측에 추가된 항목 ID 상태
|
||||
const [addedItemIds, setAddedItemIds] = useState<Set<string>>(new Set());
|
||||
|
||||
/**
|
||||
* 데이터 수신자 등록
|
||||
|
|
@ -191,6 +200,38 @@ export function SplitPanelProvider({
|
|||
[leftScreenId, rightScreenId]
|
||||
);
|
||||
|
||||
/**
|
||||
* 🆕 추가된 항목 ID 등록
|
||||
*/
|
||||
const addItemIds = useCallback((ids: string[]) => {
|
||||
setAddedItemIds((prev) => {
|
||||
const newSet = new Set(prev);
|
||||
ids.forEach((id) => newSet.add(id));
|
||||
logger.debug(`[SplitPanelContext] 항목 ID 추가: ${ids.length}개`, { ids });
|
||||
return newSet;
|
||||
});
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* 🆕 추가된 항목 ID 제거
|
||||
*/
|
||||
const removeItemIds = useCallback((ids: string[]) => {
|
||||
setAddedItemIds((prev) => {
|
||||
const newSet = new Set(prev);
|
||||
ids.forEach((id) => newSet.delete(id));
|
||||
logger.debug(`[SplitPanelContext] 항목 ID 제거: ${ids.length}개`, { ids });
|
||||
return newSet;
|
||||
});
|
||||
}, []);
|
||||
|
||||
/**
|
||||
* 🆕 모든 항목 ID 초기화
|
||||
*/
|
||||
const clearItemIds = useCallback(() => {
|
||||
setAddedItemIds(new Set());
|
||||
logger.debug(`[SplitPanelContext] 항목 ID 초기화`);
|
||||
}, []);
|
||||
|
||||
// 🆕 useMemo로 value 객체 메모이제이션 (무한 루프 방지)
|
||||
const value = React.useMemo<SplitPanelContextValue>(() => ({
|
||||
splitPanelId,
|
||||
|
|
@ -202,6 +243,10 @@ export function SplitPanelProvider({
|
|||
getOtherSideReceivers,
|
||||
isInSplitPanel: true,
|
||||
getPositionByScreenId,
|
||||
addedItemIds,
|
||||
addItemIds,
|
||||
removeItemIds,
|
||||
clearItemIds,
|
||||
}), [
|
||||
splitPanelId,
|
||||
leftScreenId,
|
||||
|
|
@ -211,6 +256,10 @@ export function SplitPanelProvider({
|
|||
transferToOtherSide,
|
||||
getOtherSideReceivers,
|
||||
getPositionByScreenId,
|
||||
addedItemIds,
|
||||
addItemIds,
|
||||
removeItemIds,
|
||||
clearItemIds,
|
||||
]);
|
||||
|
||||
return (
|
||||
|
|
|
|||
|
|
@ -120,10 +120,15 @@ const RepeaterFieldGroupComponent: React.FC<ComponentRendererProps> = (props) =>
|
|||
setGroupedData(items);
|
||||
|
||||
// 🆕 원본 데이터 ID 목록 저장 (삭제 추적용)
|
||||
const itemIds = items.map((item: any) => item.id).filter(Boolean);
|
||||
const itemIds = items.map((item: any) => String(item.id || item.po_item_id || item.item_id)).filter(Boolean);
|
||||
setOriginalItemIds(itemIds);
|
||||
console.log("📋 [RepeaterFieldGroup] 원본 데이터 ID 목록 저장:", itemIds);
|
||||
|
||||
// 🆕 SplitPanelContext에 기존 항목 ID 등록 (좌측 테이블 필터링용)
|
||||
if (splitPanelContext?.addItemIds && itemIds.length > 0) {
|
||||
splitPanelContext.addItemIds(itemIds);
|
||||
}
|
||||
|
||||
// onChange 호출하여 부모에게 알림
|
||||
if (onChange && items.length > 0) {
|
||||
const dataWithMeta = items.map((item: any) => ({
|
||||
|
|
@ -285,6 +290,14 @@ const RepeaterFieldGroupComponent: React.FC<ComponentRendererProps> = (props) =>
|
|||
// 🆕 groupedData 상태도 직접 업데이트 (UI 즉시 반영)
|
||||
setGroupedData(newItems);
|
||||
|
||||
// 🆕 SplitPanelContext에 추가된 항목 ID 등록 (좌측 테이블 필터링용)
|
||||
if (splitPanelContext?.addItemIds && addedCount > 0) {
|
||||
const newItemIds = newItems
|
||||
.map((item: any) => String(item.id || item.po_item_id || item.item_id))
|
||||
.filter(Boolean);
|
||||
splitPanelContext.addItemIds(newItemIds);
|
||||
}
|
||||
|
||||
// JSON 문자열로 변환하여 저장
|
||||
const jsonValue = JSON.stringify(newItems);
|
||||
console.log("📥 [RepeaterFieldGroup] onChange/onFormDataChange 호출:", {
|
||||
|
|
@ -380,14 +393,44 @@ const RepeaterFieldGroupComponent: React.FC<ComponentRendererProps> = (props) =>
|
|||
};
|
||||
}, [screenContext?.splitPanelPosition, handleReceiveData, component.id]);
|
||||
|
||||
// 🆕 RepeaterInput에서 항목 변경 시 SplitPanelContext의 addedItemIds 동기화
|
||||
const handleRepeaterChange = useCallback((newValue: any[]) => {
|
||||
// 배열을 JSON 문자열로 변환하여 저장
|
||||
const jsonValue = JSON.stringify(newValue);
|
||||
onChange?.(jsonValue);
|
||||
|
||||
// 🆕 groupedData 상태도 업데이트
|
||||
setGroupedData(newValue);
|
||||
|
||||
// 🆕 SplitPanelContext의 addedItemIds 동기화
|
||||
if (splitPanelContext?.isInSplitPanel && screenContext?.splitPanelPosition === "right") {
|
||||
// 현재 항목들의 ID 목록
|
||||
const currentIds = newValue
|
||||
.map((item: any) => String(item.id || item.po_item_id || item.item_id))
|
||||
.filter(Boolean);
|
||||
|
||||
// 기존 addedItemIds와 비교하여 삭제된 ID 찾기
|
||||
const addedIds = splitPanelContext.addedItemIds;
|
||||
const removedIds = Array.from(addedIds).filter(id => !currentIds.includes(id));
|
||||
|
||||
if (removedIds.length > 0) {
|
||||
console.log("🗑️ [RepeaterFieldGroup] 삭제된 항목 ID 제거:", removedIds);
|
||||
splitPanelContext.removeItemIds(removedIds);
|
||||
}
|
||||
|
||||
// 새로 추가된 ID가 있으면 등록
|
||||
const newIds = currentIds.filter((id: string) => !addedIds.has(id));
|
||||
if (newIds.length > 0) {
|
||||
console.log("➕ [RepeaterFieldGroup] 새 항목 ID 추가:", newIds);
|
||||
splitPanelContext.addItemIds(newIds);
|
||||
}
|
||||
}
|
||||
}, [onChange, splitPanelContext, screenContext?.splitPanelPosition]);
|
||||
|
||||
return (
|
||||
<RepeaterInput
|
||||
value={parsedValue}
|
||||
onChange={(newValue) => {
|
||||
// 배열을 JSON 문자열로 변환하여 저장
|
||||
const jsonValue = JSON.stringify(newValue);
|
||||
onChange?.(jsonValue);
|
||||
}}
|
||||
onChange={handleRepeaterChange}
|
||||
config={config}
|
||||
disabled={disabled}
|
||||
readonly={readonly}
|
||||
|
|
|
|||
|
|
@ -330,6 +330,25 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
const [data, setData] = useState<Record<string, any>[]>([]);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [error, setError] = useState<string | null>(null);
|
||||
|
||||
// 🆕 분할 패널에서 우측에 이미 추가된 항목 필터링 (좌측 테이블에만 적용)
|
||||
const filteredData = useMemo(() => {
|
||||
// 분할 패널 좌측에 있고, 우측에 추가된 항목이 있는 경우에만 필터링
|
||||
if (splitPanelPosition === "left" && splitPanelContext?.addedItemIds && splitPanelContext.addedItemIds.size > 0) {
|
||||
const addedIds = splitPanelContext.addedItemIds;
|
||||
const filtered = data.filter((row) => {
|
||||
const rowId = String(row.id || row.po_item_id || row.item_id || "");
|
||||
return !addedIds.has(rowId);
|
||||
});
|
||||
console.log("🔍 [TableList] 우측 추가 항목 필터링:", {
|
||||
originalCount: data.length,
|
||||
filteredCount: filtered.length,
|
||||
addedIdsCount: addedIds.size,
|
||||
});
|
||||
return filtered;
|
||||
}
|
||||
return data;
|
||||
}, [data, splitPanelPosition, splitPanelContext?.addedItemIds]);
|
||||
const [currentPage, setCurrentPage] = useState(1);
|
||||
const [totalPages, setTotalPages] = useState(0);
|
||||
const [totalItems, setTotalItems] = useState(0);
|
||||
|
|
@ -438,8 +457,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
componentType: "table-list",
|
||||
|
||||
getSelectedData: () => {
|
||||
// 선택된 행의 실제 데이터 반환
|
||||
const selectedData = data.filter((row) => {
|
||||
// 🆕 필터링된 데이터에서 선택된 행만 반환 (우측에 추가된 항목 제외)
|
||||
const selectedData = filteredData.filter((row) => {
|
||||
const rowId = String(row.id || row[tableConfig.selectedTable + "_id"] || "");
|
||||
return selectedRows.has(rowId);
|
||||
});
|
||||
|
|
@ -447,7 +466,8 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
},
|
||||
|
||||
getAllData: () => {
|
||||
return data;
|
||||
// 🆕 필터링된 데이터 반환
|
||||
return filteredData;
|
||||
},
|
||||
|
||||
clearSelection: () => {
|
||||
|
|
@ -1375,31 +1395,31 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
});
|
||||
}
|
||||
|
||||
const allRowsSelected = data.every((row, index) => newSelectedRows.has(getRowKey(row, index)));
|
||||
setIsAllSelected(allRowsSelected && data.length > 0);
|
||||
const allRowsSelected = filteredData.every((row, index) => newSelectedRows.has(getRowKey(row, index)));
|
||||
setIsAllSelected(allRowsSelected && filteredData.length > 0);
|
||||
};
|
||||
|
||||
const handleSelectAll = (checked: boolean) => {
|
||||
if (checked) {
|
||||
const allKeys = data.map((row, index) => getRowKey(row, index));
|
||||
const allKeys = filteredData.map((row, index) => getRowKey(row, index));
|
||||
const newSelectedRows = new Set(allKeys);
|
||||
setSelectedRows(newSelectedRows);
|
||||
setIsAllSelected(true);
|
||||
|
||||
if (onSelectedRowsChange) {
|
||||
onSelectedRowsChange(Array.from(newSelectedRows), data, sortColumn || undefined, sortDirection);
|
||||
onSelectedRowsChange(Array.from(newSelectedRows), filteredData, sortColumn || undefined, sortDirection);
|
||||
}
|
||||
if (onFormDataChange) {
|
||||
onFormDataChange({
|
||||
selectedRows: Array.from(newSelectedRows),
|
||||
selectedRowsData: data,
|
||||
selectedRowsData: filteredData,
|
||||
});
|
||||
}
|
||||
|
||||
// 🆕 modalDataStore에 전체 데이터 저장
|
||||
if (tableConfig.selectedTable && data.length > 0) {
|
||||
if (tableConfig.selectedTable && filteredData.length > 0) {
|
||||
import("@/stores/modalDataStore").then(({ useModalDataStore }) => {
|
||||
const modalItems = data.map((row, idx) => ({
|
||||
const modalItems = filteredData.map((row, idx) => ({
|
||||
id: getRowKey(row, idx),
|
||||
originalData: row,
|
||||
additionalData: {},
|
||||
|
|
@ -2003,11 +2023,11 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
|
||||
// 데이터 그룹화
|
||||
const groupedData = useMemo((): GroupedData[] => {
|
||||
if (groupByColumns.length === 0 || data.length === 0) return [];
|
||||
if (groupByColumns.length === 0 || filteredData.length === 0) return [];
|
||||
|
||||
const grouped = new Map<string, any[]>();
|
||||
|
||||
data.forEach((item) => {
|
||||
filteredData.forEach((item) => {
|
||||
// 그룹 키 생성: "통화:KRW > 단위:EA"
|
||||
const keyParts = groupByColumns.map((col) => {
|
||||
// 카테고리/엔티티 타입인 경우 _name 필드 사용
|
||||
|
|
@ -2706,7 +2726,7 @@ export const TableListComponent: React.FC<TableListComponentProps> = ({
|
|||
})
|
||||
) : (
|
||||
// 일반 렌더링 (그룹 없음)
|
||||
data.map((row, index) => (
|
||||
filteredData.map((row, index) => (
|
||||
<tr
|
||||
key={index}
|
||||
className={cn(
|
||||
|
|
|
|||
Loading…
Reference in New Issue