feat: Improve selected rows data management in TabsWidget and SplitPanelLayoutComponent

- Refactored TabsWidget to manage local selected rows data, enhancing responsiveness to user interactions.
- Introduced a new callback for handling selected rows changes, ensuring updates are reflected in both local and parent states.
- Updated SplitPanelLayoutComponent to share selected rows data between tabs and buttons, improving data consistency across components.
- Enhanced overall user experience by ensuring immediate recognition of selection changes within the tabbed interface.
This commit is contained in:
kjs 2026-02-12 11:42:32 +09:00
parent 5c6efa861d
commit 14d6406a61
2 changed files with 62 additions and 5 deletions

View File

@ -1,6 +1,6 @@
"use client"; "use client";
import React, { useState, useEffect, useMemo } from "react"; import React, { useState, useEffect, useCallback } from "react";
import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs"; import { Tabs, TabsContent, TabsList, TabsTrigger } from "@/components/ui/tabs";
import { Button } from "@/components/ui/button"; import { Button } from "@/components/ui/button";
import { X, Loader2 } from "lucide-react"; import { X, Loader2 } from "lucide-react";
@ -35,6 +35,8 @@ interface TabsWidgetProps {
sortOrder?: "asc" | "desc", sortOrder?: "asc" | "desc",
columnOrder?: string[], columnOrder?: string[],
) => void; ) => void;
// 추가 props (부모에서 전달받은 나머지 props)
[key: string]: any;
} }
export function TabsWidget({ export function TabsWidget({
@ -47,8 +49,9 @@ export function TabsWidget({
isDesignMode = false, isDesignMode = false,
onComponentSelect, onComponentSelect,
selectedComponentId, selectedComponentId,
selectedRowsData, selectedRowsData: _externalSelectedRowsData,
onSelectedRowsChange, onSelectedRowsChange: externalOnSelectedRowsChange,
...restProps
}: TabsWidgetProps) { }: TabsWidgetProps) {
const { setActiveTab, removeTabsComponent } = useActiveTab(); const { setActiveTab, removeTabsComponent } = useActiveTab();
const { const {
@ -62,6 +65,30 @@ export function TabsWidget({
const storageKey = `tabs-${component.id}-selected`; const storageKey = `tabs-${component.id}-selected`;
// 탭 내부 자체 selectedRowsData 상태 관리 (항상 로컬 상태 사용)
// 부모에서 빈 배열 []이 전달되어도 로컬 상태를 우선하여 탭 내부 버튼이 즉시 인식
const [localSelectedRowsData, setLocalSelectedRowsData] = useState<any[]>([]);
// 선택 변경 핸들러: 로컬 상태 업데이트 + 부모 콜백 호출
const handleSelectedRowsChange = useCallback(
(
selectedRows: any[],
selectedRowsDataNew: any[],
sortBy?: string,
sortOrder?: "asc" | "desc",
columnOrder?: string[],
) => {
// 로컬 상태 업데이트 (탭 내부 버튼이 즉시 인식)
setLocalSelectedRowsData(selectedRowsDataNew);
// 부모 콜백 호출 (부모 상태도 업데이트)
if (externalOnSelectedRowsChange) {
externalOnSelectedRowsChange(selectedRows, selectedRowsDataNew, sortBy, sortOrder, columnOrder);
}
},
[externalOnSelectedRowsChange],
);
// 초기 선택 탭 결정 // 초기 선택 탭 결정
const getInitialTab = () => { const getInitialTab = () => {
if (persistSelection && typeof window !== "undefined") { if (persistSelection && typeof window !== "undefined") {
@ -342,6 +369,7 @@ export function TabsWidget({
}} }}
> >
<DynamicComponentRenderer <DynamicComponentRenderer
{...restProps}
component={{ component={{
id: comp.id, id: comp.id,
componentType: comp.componentType, componentType: comp.componentType,
@ -356,8 +384,8 @@ export function TabsWidget({
menuObjid={menuObjid} menuObjid={menuObjid}
isDesignMode={isDesignMode} isDesignMode={isDesignMode}
isInteractive={!isDesignMode} isInteractive={!isDesignMode}
selectedRowsData={selectedRowsData} selectedRowsData={localSelectedRowsData}
onSelectedRowsChange={onSelectedRowsChange} onSelectedRowsChange={handleSelectedRowsChange}
/> />
</div> </div>
); );

View File

@ -194,6 +194,17 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
const [selectedLeftItem, setSelectedLeftItem] = useState<any>(null); const [selectedLeftItem, setSelectedLeftItem] = useState<any>(null);
const [expandedRightItems, setExpandedRightItems] = useState<Set<string | number>>(new Set()); // 확장된 우측 아이템 const [expandedRightItems, setExpandedRightItems] = useState<Set<string | number>>(new Set()); // 확장된 우측 아이템
const [customLeftSelectedData, setCustomLeftSelectedData] = useState<Record<string, any>>({}); // 커스텀 모드: 좌측 선택 데이터 const [customLeftSelectedData, setCustomLeftSelectedData] = useState<Record<string, any>>({}); // 커스텀 모드: 좌측 선택 데이터
// 커스텀 모드: 탭/버튼 간 공유할 selectedRowsData 자체 관리 (항상 로컬 상태 사용)
const [localSelectedRowsData, setLocalSelectedRowsData] = useState<any[]>([]);
const handleLocalSelectedRowsChange = useCallback(
(selectedRows: any[], selectedRowsDataNew: any[], sortBy?: string, sortOrder?: "asc" | "desc", columnOrder?: string[]) => {
setLocalSelectedRowsData(selectedRowsDataNew);
if ((props as any).onSelectedRowsChange) {
(props as any).onSelectedRowsChange(selectedRows, selectedRowsDataNew, sortBy, sortOrder, columnOrder);
}
},
[(props as any).onSelectedRowsChange],
);
const [leftSearchQuery, setLeftSearchQuery] = useState(""); const [leftSearchQuery, setLeftSearchQuery] = useState("");
const [rightSearchQuery, setRightSearchQuery] = useState(""); const [rightSearchQuery, setRightSearchQuery] = useState("");
const [isLoadingLeft, setIsLoadingLeft] = useState(false); const [isLoadingLeft, setIsLoadingLeft] = useState(false);
@ -2757,8 +2768,17 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<DynamicComponentRenderer <DynamicComponentRenderer
component={componentData as any} component={componentData as any}
isDesignMode={false} isDesignMode={false}
isInteractive={true}
formData={{}} formData={{}}
tableName={componentConfig.leftPanel?.tableName} tableName={componentConfig.leftPanel?.tableName}
menuObjid={(props as any).menuObjid}
screenId={(props as any).screenId}
userId={(props as any).userId}
userName={(props as any).userName}
companyCode={companyCode}
allComponents={(props as any).allComponents}
selectedRowsData={localSelectedRowsData}
onSelectedRowsChange={handleLocalSelectedRowsChange}
onFormDataChange={(data: any) => { onFormDataChange={(data: any) => {
// 커스텀 모드: 좌측 카드/테이블 선택 시 데이터 캡처 // 커스텀 모드: 좌측 카드/테이블 선택 시 데이터 캡처
if (data?.selectedRowsData && data.selectedRowsData.length > 0) { if (data?.selectedRowsData && data.selectedRowsData.length > 0) {
@ -3645,8 +3665,17 @@ export const SplitPanelLayoutComponent: React.FC<SplitPanelLayoutComponentProps>
<DynamicComponentRenderer <DynamicComponentRenderer
component={componentData as any} component={componentData as any}
isDesignMode={false} isDesignMode={false}
isInteractive={true}
formData={customLeftSelectedData} formData={customLeftSelectedData}
tableName={componentConfig.rightPanel?.tableName || componentConfig.leftPanel?.tableName} tableName={componentConfig.rightPanel?.tableName || componentConfig.leftPanel?.tableName}
menuObjid={(props as any).menuObjid}
screenId={(props as any).screenId}
userId={(props as any).userId}
userName={(props as any).userName}
companyCode={companyCode}
allComponents={(props as any).allComponents}
selectedRowsData={localSelectedRowsData}
onSelectedRowsChange={handleLocalSelectedRowsChange}
/> />
</div> </div>
); );