summaryrefslogtreecommitdiff
path: root/lib/pq/pq-review-table-new/pq-container.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-05-28 00:32:31 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-05-28 00:32:31 +0000
commit20800b214145ee6056f94ca18fa1054f145eb977 (patch)
treeb5c8b27febe5b126e6d9ece115ea05eace33a020 /lib/pq/pq-review-table-new/pq-container.tsx
parente1344a5da1aeef8fbf0f33e1dfd553078c064ccc (diff)
(대표님) lib 파트 커밋
Diffstat (limited to 'lib/pq/pq-review-table-new/pq-container.tsx')
-rw-r--r--lib/pq/pq-review-table-new/pq-container.tsx151
1 files changed, 151 insertions, 0 deletions
diff --git a/lib/pq/pq-review-table-new/pq-container.tsx b/lib/pq/pq-review-table-new/pq-container.tsx
new file mode 100644
index 00000000..ebe46809
--- /dev/null
+++ b/lib/pq/pq-review-table-new/pq-container.tsx
@@ -0,0 +1,151 @@
+"use client"
+
+import { useState, useEffect, useCallback, useRef } from "react"
+import { useSearchParams } from "next/navigation"
+import { Button } from "@/components/ui/button"
+import { PanelLeftClose, PanelLeftOpen } from "lucide-react"
+
+import { cn } from "@/lib/utils"
+import { getPQSubmissions } from "../service"
+import { PQSubmissionsTable } from "./vendors-table"
+import { PQFilterSheet } from "./pq-filter-sheet"
+
+interface PQContainerProps {
+ // Promise.all로 감싼 promises를 받음
+ promises: Promise<[Awaited<ReturnType<typeof getPQSubmissions>>]>
+ // 컨테이너 클래스명 (옵션)
+ className?: string
+}
+
+export default function PQContainer({
+ promises,
+ className
+}: PQContainerProps) {
+ const searchParams = useSearchParams()
+
+ // Whether the filter panel is open
+ const [isFilterPanelOpen, setIsFilterPanelOpen] = useState(false)
+
+ // Container wrapper의 위치를 측정하기 위한 ref
+ const containerRef = useRef<HTMLDivElement>(null)
+ const [containerTop, setContainerTop] = useState(0)
+
+ // Container 위치 측정 함수 - top만 측정
+ const updateContainerBounds = useCallback(() => {
+ if (containerRef.current) {
+ const rect = containerRef.current.getBoundingClientRect()
+ setContainerTop(rect.top)
+ }
+ }, [])
+
+ // 컴포넌트 마운트 시와 윈도우 리사이즈 시 위치 업데이트
+ useEffect(() => {
+ updateContainerBounds()
+
+ const handleResize = () => {
+ updateContainerBounds()
+ }
+
+ window.addEventListener('resize', handleResize)
+ window.addEventListener('scroll', updateContainerBounds)
+
+ return () => {
+ window.removeEventListener('resize', handleResize)
+ window.removeEventListener('scroll', updateContainerBounds)
+ }
+ }, [updateContainerBounds])
+
+ // 조회 버튼 클릭 핸들러 - PQFilterSheet에 전달
+ const handleSearch = () => {
+ // Close the panel after search
+ setIsFilterPanelOpen(false)
+ }
+
+ // Get active filter count for UI display (서버 사이드 필터만 계산)
+ const getActiveFilterCount = () => {
+ try {
+ // 새로운 이름 우선, 기존 이름도 지원
+ const basicFilters = searchParams.get('basicFilters') || searchParams.get('pqBasicFilters')
+ return basicFilters ? JSON.parse(basicFilters).length : 0
+ } catch (e) {
+ return 0
+ }
+ }
+
+ // Filter panel width
+ const FILTER_PANEL_WIDTH = 400;
+
+ return (
+ <>
+ {/* Filter Panel - fixed positioning으로 화면 최대 좌측에서 시작 */}
+ <div
+ className={cn(
+ "fixed left-0 bg-background border-r z-50 flex flex-col transition-all duration-300 ease-in-out overflow-hidden",
+ isFilterPanelOpen ? "border-r shadow-lg" : "border-r-0"
+ )}
+ style={{
+ width: isFilterPanelOpen ? `${FILTER_PANEL_WIDTH}px` : '0px',
+ top: `${containerTop}px`,
+ height: `calc(100vh - ${containerTop}px)`
+ }}
+ >
+ {/* Filter Content */}
+ <div className="h-full">
+ <PQFilterSheet
+ isOpen={isFilterPanelOpen}
+ onClose={() => setIsFilterPanelOpen(false)}
+ onSearch={handleSearch}
+ isLoading={false} // 로딩 상태 제거
+ />
+ </div>
+ </div>
+
+ {/* Main Content Container */}
+ <div
+ ref={containerRef}
+ className={cn("relative w-full overflow-hidden", className)}
+ >
+ <div className="flex w-full h-full">
+ {/* Main Content - 너비 조정으로 필터 패널 공간 확보 */}
+ <div
+ className="flex flex-col min-w-0 overflow-hidden transition-all duration-300 ease-in-out"
+ style={{
+ width: isFilterPanelOpen ? `calc(100% - ${FILTER_PANEL_WIDTH}px)` : '100%',
+ marginLeft: isFilterPanelOpen ? `${FILTER_PANEL_WIDTH}px` : '0px'
+ }}
+ >
+ {/* Header Bar */}
+ <div className="flex items-center justify-between p-4 bg-background shrink-0">
+ <div className="flex items-center gap-3">
+ <Button
+ variant="outline"
+ size="sm"
+ type='button'
+ onClick={() => setIsFilterPanelOpen(!isFilterPanelOpen)}
+ className="flex items-center shadow-sm"
+ >
+ {
+ 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>
+ </div>
+
+ {/* Table Content Area */}
+ <div className="flex-1 overflow-hidden" style={{ height: 'calc(100vh - 380px)' }}>
+ <div className="h-full w-full">
+ {/* Promise를 직접 전달 - Items와 동일한 패턴 */}
+ <PQSubmissionsTable promises={promises} />
+ </div>
+ </div>
+ </div>
+ </div>
+ </div>
+ </>
+ )
+} \ No newline at end of file