diff options
Diffstat (limited to 'components/po-rfq/po-rfq-container.tsx')
| -rw-r--r-- | components/po-rfq/po-rfq-container.tsx | 261 |
1 files changed, 0 insertions, 261 deletions
diff --git a/components/po-rfq/po-rfq-container.tsx b/components/po-rfq/po-rfq-container.tsx deleted file mode 100644 index e5159242..00000000 --- a/components/po-rfq/po-rfq-container.tsx +++ /dev/null @@ -1,261 +0,0 @@ -"use client" - -import { useState, useEffect, useCallback, useRef } from "react" -import { useSearchParams, useRouter } from "next/navigation" -import { Button } from "@/components/ui/button" -import { PanelLeft, PanelLeftClose, PanelLeftOpen } from "lucide-react" - -// shadcn/ui components -import { - ResizablePanelGroup, - ResizablePanel, - ResizableHandle, -} from "@/components/ui/resizable" - -import { cn } from "@/lib/utils" -import { ProcurementRfqsView } from "@/db/schema" -import { RFQListTable } from "@/lib/procurement-rfqs/table/rfq-table" -import { getPORfqs } from "@/lib/procurement-rfqs/services" -import { RFQFilterSheet } from "./rfq-filter-sheet" -import { DataTableSkeleton } from "@/components/data-table/data-table-skeleton" -import { RfqDetailTables } from "./detail-table/rfq-detail-table" - -interface RfqContainerProps { - // 초기 데이터 (필수) - initialData: Awaited<ReturnType<typeof getPORfqs>> - // 서버 액션으로 데이터를 가져오는 함수 - fetchData: (params: any) => Promise<Awaited<ReturnType<typeof getPORfqs>>> -} - -export default function RFQContainer({ - initialData, - fetchData -}: RfqContainerProps) { - const router = useRouter() - const searchParams = useSearchParams() - - // Whether the filter panel is open (now a side panel instead of sheet) - const [isFilterPanelOpen, setIsFilterPanelOpen] = useState(false) - - // 데이터 상태 관리 - 초기 데이터로 시작 - const [data, setData] = useState<Awaited<ReturnType<typeof getPORfqs>>>(initialData) - const [isLoading, setIsLoading] = useState(false) - - // 선택된 문서를 이 state로 관리 - const [selectedRfq, setSelectedRfq] = useState<ProcurementRfqsView | null>(null) - - // 패널 collapse - const [isTopCollapsed, setIsTopCollapsed] = useState(false) - - // 이전 URL 파라미터를 저장하기 위한 ref - const prevParamsRef = useRef<string>(searchParams.toString()) - - // 현재 URL 파라미터로부터 필터 데이터 구성 - const getFilterParams = useCallback(() => { - return { - page: searchParams.get('page') || '1', - perPage: searchParams.get('perPage') || '10', - sort: searchParams.get('sort') || JSON.stringify([{ id: "updatedAt", desc: true }]), - basicFilters: searchParams.get('basicFilters') || null, - basicJoinOperator: searchParams.get('basicJoinOperator') || 'and', - filters: searchParams.get('filters') || null, - joinOperator: searchParams.get('joinOperator') || 'and', - search: searchParams.get('search') || '', - } - }, [searchParams]) - - // 데이터 로드 함수 - const loadData = useCallback(async () => { - try { - setIsLoading(true) - const filterParams = getFilterParams() - - console.log("데이터 로드 시작:", filterParams) - - // 서버 액션으로 데이터 가져오는 함수 - const newData = await fetchData(filterParams) - - console.log("데이터 로드 완료:", newData.data.length, "건") - - setData(newData) - } catch (error) { - console.error("데이터 로드 오류:", error) - } finally { - setIsLoading(false) - } - }, [fetchData, getFilterParams]) - - const refreshData = useCallback(() => { - // 현재 파라미터로 데이터 다시 로드 - loadData(); - }, [loadData]); - - // URL 파라미터 변경 감지 - useEffect(() => { - const currentParams = searchParams.toString() - - // 파라미터가 변경되었을 때만 데이터 로드 - if (currentParams !== prevParamsRef.current) { - console.log("URL 파라미터 변경 감지:", { - previous: prevParamsRef.current, - current: currentParams, - }) - - prevParamsRef.current = currentParams - loadData() - } - }, [searchParams, loadData]) - - // 문서 선택 핸들러 - const handleSelectRfq = (rfq: ProcurementRfqsView | null) => { - setSelectedRfq(rfq) - } - - // 조회 버튼 클릭 핸들러 - RFQFilterSheet에 전달 - // 페이지 리라우팅을 통해 처리하므로 별도 로직 불필요 - const handleSearch = () => { - // Close the panel after search - setIsFilterPanelOpen(false) - } - - const [panelHeight, setPanelHeight] = useState<number>(400) - - // Get active filter count for UI display - const getActiveFilterCount = () => { - try { - const basicFilters = searchParams.get('basicFilters') - return basicFilters ? JSON.parse(basicFilters).length : 0 - } catch (e) { - console.error("Error parsing filters:", e) - return 0 - } - } - - // Filter panel width in pixels - const FILTER_PANEL_WIDTH = 400; - - // Table refresh key - 패널 상태가 변경되면 테이블을 강제로 재렌더링 - const [tableRefreshKey, setTableRefreshKey] = useState(0); - - useEffect(() => { - // 패널 상태가 변경될 때 테이블 강제 재렌더링 - setTableRefreshKey(prev => prev + 1); - }, [isFilterPanelOpen]); - - return ( - <div className="h-[calc(100vh-220px)] w-full overflow-hidden relative"> - {/* Fixed Filter Panel - 가장 왼쪽부터 시작, 전체 높이 맞춤 */} - <div - className={cn( - "fixed left-0 bg-background border-r overflow-hidden flex flex-col transition-all duration-300 ease-in-out z-30", - isFilterPanelOpen ? "border-r" : "border-r-0" - )} - style={{ - width: isFilterPanelOpen ? `${FILTER_PANEL_WIDTH}px` : '0px', - height: 'calc(100vh - 130px)' // 나머지 높이 전체 사용 - }} - > - {/* Filter Content - 제목 포함하여 내부에서 처리 */} - <div className="h-full"> - <RFQFilterSheet - isOpen={isFilterPanelOpen} - onClose={() => setIsFilterPanelOpen(false)} - onSearch={handleSearch} - isLoading={isLoading} - /> - </div> - </div> - - {/* Main Content Panel - 패널이 열릴 때 오른쪽으로 이동 */} - <div - className="h-full overflow-hidden transition-all duration-300 ease-in-out" - style={{ - marginLeft: isFilterPanelOpen ? `${FILTER_PANEL_WIDTH}px` : '0px' - }} - > - {/* Filter Toggle Button - 메인 콘텐츠 상단에 위치 */} - <div className="flex items-center p-4 border-b bg-background pl-0"> - <Button - variant="outline" - size="sm" - type='button' - onClick={() => setIsFilterPanelOpen(!isFilterPanelOpen)} - className="flex items-center shadow-md" - > - { - isFilterPanelOpen ? <PanelLeftClose className="size-4"/> : <PanelLeftOpen className="size-4"/> - } - {/* 검색 필터 */} - {getActiveFilterCount() > 0 && ( - <span className="ml-2 bg-primary text-primary-foreground rounded-full px-2 py-0.5 text-xs"> - {getActiveFilterCount()} - </span> - )} - </Button> - - {/* 추가적인 헤더 정보나 버튼들을 여기에 배치할 수 있음 */} - <div className="flex-1" /> - <div className="text-sm text-muted-foreground"> - {data && !isLoading && ( - <span>총 {data.total || 0}건</span> - )} - </div> - </div> - - {/* Main Content Area */} - <div className="h-[calc(100%-64px)] w-full overflow-hidden"> - {isLoading ? ( - // 로딩 중 상태 - <DataTableSkeleton - columnCount={6} - searchableColumnCount={1} - filterableColumnCount={2} - cellWidths={["10rem", "40rem", "12rem", "12rem", "8rem", "8rem"]} - shrinkZero - /> - ) : ( - // 데이터 로드 완료 상태 - <ResizablePanelGroup direction="vertical" className="h-full"> - <ResizablePanel - defaultSize={55} - minSize={0} - maxSize={95} - collapsible - collapsedSize={10} - onCollapse={() => setIsTopCollapsed(true)} - onExpand={() => setIsTopCollapsed(false)} - onResize={(size) => { - setPanelHeight(size) - }} - className={cn("overflow-y-auto overflow-x-hidden border-b", isTopCollapsed && "transition-all")} - > - <div className="flex h-full min-h-0 flex-col"> - <RFQListTable - key={tableRefreshKey} // Force re-render when panel toggles - maxHeight={`${panelHeight*0.5}vh`} - data={data} - onSelectRFQ={handleSelectRfq} - onDataRefresh={refreshData} - /> - </div> - </ResizablePanel> - - <ResizableHandle - withHandle - className="pointer-events-none data-[resize-handle]:pointer-events-auto" - /> - - <ResizablePanel - minSize={0} - defaultSize={35} - className="overflow-y-auto overflow-x-hidden" - > - <RfqDetailTables selectedRfq={selectedRfq} /> - </ResizablePanel> - </ResizablePanelGroup> - )} - </div> - </div> - </div> - ) -}
\ No newline at end of file |
