summaryrefslogtreecommitdiff
path: root/lib/pq/pq-review-table-new/pq-container.tsx
blob: 01b7aab1645166cc38e2f5b9b39248bf454873f6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
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>
    </>
  )
}