summaryrefslogtreecommitdiff
path: root/components/client-data-table/data-table.tsx
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-06-01 13:52:21 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-06-01 13:52:21 +0000
commitbac0228d21b7195065e9cddcc327ae33659c7bcc (patch)
tree8f3016ae4533c8706d0c00a605d9b1d41968c2bc /components/client-data-table/data-table.tsx
parent2fdce8d7a57c792bba0ac36fa554dca9c9cc31e3 (diff)
(대표님) 20250601까지 작업사항
Diffstat (limited to 'components/client-data-table/data-table.tsx')
-rw-r--r--components/client-data-table/data-table.tsx74
1 files changed, 65 insertions, 9 deletions
diff --git a/components/client-data-table/data-table.tsx b/components/client-data-table/data-table.tsx
index b7851bb8..675fe192 100644
--- a/components/client-data-table/data-table.tsx
+++ b/components/client-data-table/data-table.tsx
@@ -27,7 +27,7 @@ import {
TableHeader,
TableRow,
} from "@/components/ui/table"
-import { getCommonPinningStyles } from "@/lib/data-table"
+import { getCommonPinningStylesWithBorder } from "@/lib/data-table"
import { ChevronRight, ChevronUp } from "lucide-react"
import { ClientDataTableAdvancedToolbar } from "./data-table-toolbar"
@@ -45,6 +45,8 @@ interface DataTableProps<TData, TValue> {
maxHeight?: string | number
/** 추가로 표시할 버튼/컴포넌트 */
children?: React.ReactNode
+ /** 선택 상태 초기화 트리거 */
+ clearSelection?: boolean
}
export function ClientDataTable<TData, TValue>({
@@ -55,7 +57,8 @@ export function ClientDataTable<TData, TValue>({
compact = true, // 기본값 true
children,
maxHeight,
- onSelectedRowsChange
+ onSelectedRowsChange,
+ clearSelection
}: DataTableProps<TData, TValue>) {
// (1) React Table 상태
@@ -66,10 +69,13 @@ export function ClientDataTable<TData, TValue>({
const [grouping, setGrouping] = React.useState<string[]>([])
const [columnSizing, setColumnSizing] = React.useState<ColumnSizingState>({})
const [columnPinning, setColumnPinning] = React.useState<ColumnPinningState>({
- left: ["TAG_NO", "TAG_DESC"],
+ left: ["select","TAG_NO", "TAG_DESC", "status"],
right: ["update", 'actions'],
})
+ // 🎯 스크롤 상태 감지 추가
+ const [isScrolled, setIsScrolled] = React.useState(false)
+
const table = useReactTable({
data,
columns,
@@ -113,6 +119,48 @@ export function ClientDataTable<TData, TValue>({
onSelectedRowsChange(selectedRows)
}, [rowSelection, table, onSelectedRowsChange])
+ // clearSelection prop이 변경되면 선택 상태 초기화
+ React.useEffect(() => {
+ setRowSelection({})
+ }, [clearSelection])
+
+ // 🎯 스크롤 핸들러 추가
+ const handleScroll = (e: React.UIEvent<HTMLDivElement>) => {
+ const scrollLeft = e.currentTarget.scrollLeft
+ setIsScrolled(scrollLeft > 0)
+ }
+
+ // 🎯 동적 핀 스타일 함수 (width 중복 제거)
+ const getPinnedStyle = (column: any, isHeader: boolean = false) => {
+ const baseStyle = getCommonPinningStylesWithBorder({ column })
+ const pinnedSide = column.getIsPinned()
+
+ // width를 제외한 나머지 스타일만 반환
+ const { width, ...restBaseStyle } = baseStyle
+
+ return {
+ ...restBaseStyle,
+ // 헤더는 핀 여부와 관계없이 항상 배경 유지 (sticky로 고정되어 있기 때문)
+ ...(isHeader && {
+ background: "hsl(var(--background))",
+ transition: "none",
+ }),
+ // 바디 셀은 핀된 경우에만 스크롤 상태에 따라 동적 변경
+ ...(!isHeader && pinnedSide && {
+ background: isScrolled
+ ? "hsl(var(--background))"
+ : "transparent",
+ transition: "background-color 0.15s ease-out",
+ }),
+ }
+ }
+
+ // 🎯 테이블 총 너비 계산
+ const getTableWidth = React.useCallback(() => {
+ const totalSize = table.getCenterTotalSize() + table.getLeftTotalSize() + table.getRightTotalSize()
+ return Math.max(totalSize, 800) // 최소 800px 보장
+ }, [table])
+
// 컴팩트 모드를 위한 클래스 정의
const compactStyles = compact ? {
row: "h-7", // 행 높이 축소
@@ -143,9 +191,17 @@ export function ClientDataTable<TData, TValue>({
</ClientDataTableAdvancedToolbar>
<div className="rounded-md border">
- <div className="overflow-auto" style={{ maxHeight: maxHeight || '34rem' }} >
+ <div
+ className="overflow-auto"
+ style={{ maxHeight: maxHeight || '34rem' }}
+ onScroll={handleScroll} // 🎯 스크롤 이벤트 핸들러 추가
+ >
<UiTable
- className="[&>thead]:sticky [&>thead]:top-0 [&>thead]:z-10 table-fixed"
+ className="[&>thead]:sticky [&>thead]:top-0 [&>thead]:z-10"
+ style={{
+ width: getTableWidth(), // 🎯 동적 너비 계산
+ minWidth: '100%'
+ }}
>
<TableHeader>
{table.getHeaderGroups().map((headerGroup) => (
@@ -163,8 +219,8 @@ export function ClientDataTable<TData, TValue>({
data-column-id={header.column.id}
className={compactStyles.header}
style={{
- ...getCommonPinningStyles({ column: header.column }),
- width: header.getSize()
+ ...getPinnedStyle(header.column, true), // 🎯 헤더임을 명시
+ width: header.getSize() // 🎯 width 별도 설정
}}
>
<div style={{ position: "relative" }}>
@@ -269,8 +325,8 @@ export function ClientDataTable<TData, TValue>({
data-column-id={cell.column.id}
className={compactStyles.cell}
style={{
- ...getCommonPinningStyles({ column: cell.column }),
- width: cell.column.getSize()
+ ...getPinnedStyle(cell.column, false), // 🎯 바디 셀임을 명시
+ width: cell.column.getSize() // 🎯 width 별도 설정
}}
>
{flexRender(