diff options
| author | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-24 11:06:32 +0000 |
|---|---|---|
| committer | dujinkim <dujin.kim@dtsolution.co.kr> | 2025-07-24 11:06:32 +0000 |
| commit | 1dc24d48e52f2e490f5603ceb02842586ecae533 (patch) | |
| tree | 8fca2c5b5b52cc10557b5ba6e55b937ae3c57cf6 /components/data-table | |
| parent | ed0d6fcc98f671280c2ccde797b50693da88152e (diff) | |
(대표님) 정기평가 피드백 반영, 설계 피드백 반영, (최겸) 기술영업 피드백 반영
Diffstat (limited to 'components/data-table')
| -rw-r--r-- | components/data-table/data-table-advanced-toolbar.tsx | 50 | ||||
| -rw-r--r-- | components/data-table/data-table-filter-list.tsx | 49 | ||||
| -rw-r--r-- | components/data-table/data-table-view-options.tsx | 2 |
3 files changed, 71 insertions, 30 deletions
diff --git a/components/data-table/data-table-advanced-toolbar.tsx b/components/data-table/data-table-advanced-toolbar.tsx index 256dc125..7ae331bc 100644 --- a/components/data-table/data-table-advanced-toolbar.tsx +++ b/components/data-table/data-table-advanced-toolbar.tsx @@ -7,7 +7,7 @@ import { LayoutGrid, TableIcon } from "lucide-react" import { Button } from "@/components/ui/button" import { cn } from "@/lib/utils" -import { DataTableFilterList } from "@/components/data-table/data-table-filter-list" +import { DataTableFilterList } from "@/components/data-table/data-table-filter-list" // ✅ 확장된 버전 사용 import { DataTableSortList } from "@/components/data-table/data-table-sort-list" import { DataTableViewOptions } from "@/components/data-table/data-table-view-options" import { DataTablePinList } from "./data-table-pin" @@ -57,24 +57,6 @@ interface DataTableAdvancedToolbarProps<TData> /** * An array of filter field configurations for the data table. * @type DataTableAdvancedFilterField<TData>[] - * @example - * const filterFields = [ - * { - * id: 'name', - * label: 'Name', - * type: 'text', - * placeholder: 'Filter by name...' - * }, - * { - * id: 'status', - * label: 'Status', - * type: 'select', - * options: [ - * { label: 'Active', value: 'active', count: 10 }, - * { label: 'Inactive', value: 'inactive', count: 5 } - * ] - * } - * ] */ filterFields: DataTableAdvancedFilterField<TData>[] @@ -113,6 +95,22 @@ interface DataTableAdvancedToolbarProps<TData> * @default "dataTableCompact" */ compactStorageKey?: string + + // ✅ 외부 필터 지원을 위한 새로운 props + /** + * 외부에서 전달받은 필터 (예: 폼에서 생성된 필터) + */ + externalFilters?: any[] + + /** + * 외부에서 전달받은 조인 연산자 + */ + externalJoinOperator?: "and" | "or" + + /** + * 필터 변경 시 호출될 콜백 + */ + onFiltersChange?: (filters: any[], joinOperator: "and" | "or") => void } export function DataTableAdvancedToolbar<TData>({ @@ -124,6 +122,9 @@ export function DataTableAdvancedToolbar<TData>({ initialCompact = false, onCompactChange, compactStorageKey = "dataTableCompact", + externalFilters, + externalJoinOperator, + onFiltersChange, children, className, ...props @@ -153,7 +154,7 @@ export function DataTableAdvancedToolbar<TData>({ {...props} > <div className="flex items-center gap-2"> - {enableCompactToggle && ( + {enableCompactToggle && ( <Button variant="outline" size="sm" @@ -162,16 +163,21 @@ export function DataTableAdvancedToolbar<TData>({ className="h-8 px-2" > {isCompact ? <LayoutGrid size={16} /> : <TableIcon size={16} />} - {/* <span className="ml-2 text-xs">{isCompact ? "확장 보기" : "컴팩트 보기"}</span> */} </Button> )} <DataTableViewOptions table={table} /> + + {/* ✅ 확장된 DataTableFilterList 사용 */} <DataTableFilterList table={table} filterFields={filterFields} debounceMs={debounceMs} shallow={shallow} + externalFilters={externalFilters} + externalJoinOperator={externalJoinOperator} + onFiltersChange={onFiltersChange} /> + <DataTableSortList table={table} debounceMs={debounceMs} @@ -183,8 +189,6 @@ export function DataTableAdvancedToolbar<TData>({ <DataTableGlobalFilter /> </div> <div className="flex items-center gap-2"> - {/* 컴팩트 모드 토글 버튼 */} - {children} </div> </div> diff --git a/components/data-table/data-table-filter-list.tsx b/components/data-table/data-table-filter-list.tsx index db9f8af9..3efa02ed 100644 --- a/components/data-table/data-table-filter-list.tsx +++ b/components/data-table/data-table-filter-list.tsx @@ -72,6 +72,10 @@ interface DataTableFilterListProps<TData> { filterFields: DataTableAdvancedFilterField<TData>[] debounceMs: number shallow?: boolean + // ✅ 외부에서 전달받은 필터를 적용하기 위한 props + externalFilters?: Filter<TData>[] + externalJoinOperator?: JoinOperator + onFiltersChange?: (filters: Filter<TData>[], joinOperator: JoinOperator) => void } export function DataTableFilterList<TData>({ @@ -79,6 +83,9 @@ export function DataTableFilterList<TData>({ filterFields, debounceMs, shallow, + externalFilters, + externalJoinOperator, + onFiltersChange, }: DataTableFilterListProps<TData>) { const params = useParams(); @@ -87,6 +94,8 @@ export function DataTableFilterList<TData>({ const { t, i18n } = useTranslation(lng); const id = React.useId() + + // ✅ 기존 URL 상태 관리 const [filters, setFilters] = useQueryState( "filters", getFiltersStateParser(table.getRowModel().rows[0]?.original) @@ -105,6 +114,28 @@ export function DataTableFilterList<TData>({ }) ) + // ✅ 외부 필터가 전달되면 URL 상태를 업데이트 + React.useEffect(() => { + if (externalFilters && externalFilters.length > 0) { + console.log("=== 외부 필터 적용 ===", externalFilters); + setFilters(externalFilters); + } + }, [externalFilters, setFilters]); + + React.useEffect(() => { + if (externalJoinOperator) { + console.log("=== 외부 조인 연산자 적용 ===", externalJoinOperator); + setJoinOperator(externalJoinOperator); + } + }, [externalJoinOperator, setJoinOperator]); + + // ✅ 필터 변경 시 부모에게 알림 + React.useEffect(() => { + if (onFiltersChange) { + onFiltersChange(filters, joinOperator); + } + }, [filters, joinOperator, onFiltersChange]); + const debouncedSetFilters = useDebouncedCallback(setFilters, debounceMs) function addFilter() { @@ -163,6 +194,12 @@ export function DataTableFilterList<TData>({ }) } + // ✅ 모든 필터 초기화 (외부 필터 포함) + function resetAllFilters() { + void setFilters([]) + void setJoinOperator("and") + } + function renderFilterInput({ filter, inputId, @@ -198,7 +235,9 @@ export function DataTableFilterList<TData>({ placeholder={filterField.placeholder ?? t('filterInputPlaceholder')} className="h-8 w-full focus:outline-none !important focus:ring-offset-4 !important" defaultValue={ - typeof filter.value === "string" ? filter.value : undefined + filter.value !== null && filter.value !== undefined + ? String(filter.value) + : "" } onChange={(event) => updateFilter({ @@ -771,10 +810,8 @@ export function DataTableFilterList<TData>({ size="sm" variant="outline" className="rounded" - onClick={() => { - void setFilters(null) - void setJoinOperator("and") - }} + onClick={resetAllFilters} + data-filter-reset // ✅ 외부에서 프로그래밍적으로 접근할 수 있도록 data attribute 추가 > {t('resetFilters')} </Button> @@ -784,4 +821,4 @@ export function DataTableFilterList<TData>({ </Popover> </Sortable> ) -} +}
\ No newline at end of file diff --git a/components/data-table/data-table-view-options.tsx b/components/data-table/data-table-view-options.tsx index 50bb50dd..c4167b47 100644 --- a/components/data-table/data-table-view-options.tsx +++ b/components/data-table/data-table-view-options.tsx @@ -154,7 +154,7 @@ export function DataTableViewOptions<TData>({ {columnOrder.map((colId) => { // find column instance const column = hideableCols.find((c) => c.id === colId) - + if (!column) return null const columnLabel = column?.columnDef?.meta?.excelHeader || column.id |
