From 1dc24d48e52f2e490f5603ceb02842586ecae533 Mon Sep 17 00:00:00 2001 From: dujinkim Date: Thu, 24 Jul 2025 11:06:32 +0000 Subject: (대표님) 정기평가 피드백 반영, 설계 피드백 반영, (최겸) 기술영업 피드백 반영 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data-table/data-table-advanced-toolbar.tsx | 50 ++++++++++++---------- components/data-table/data-table-filter-list.tsx | 49 ++++++++++++++++++--- components/data-table/data-table-view-options.tsx | 2 +- 3 files changed, 71 insertions(+), 30 deletions(-) (limited to 'components/data-table') 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 /** * An array of filter field configurations for the data table. * @type DataTableAdvancedFilterField[] - * @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[] @@ -113,6 +95,22 @@ interface DataTableAdvancedToolbarProps * @default "dataTableCompact" */ compactStorageKey?: string + + // ✅ 외부 필터 지원을 위한 새로운 props + /** + * 외부에서 전달받은 필터 (예: 폼에서 생성된 필터) + */ + externalFilters?: any[] + + /** + * 외부에서 전달받은 조인 연산자 + */ + externalJoinOperator?: "and" | "or" + + /** + * 필터 변경 시 호출될 콜백 + */ + onFiltersChange?: (filters: any[], joinOperator: "and" | "or") => void } export function DataTableAdvancedToolbar({ @@ -124,6 +122,9 @@ export function DataTableAdvancedToolbar({ initialCompact = false, onCompactChange, compactStorageKey = "dataTableCompact", + externalFilters, + externalJoinOperator, + onFiltersChange, children, className, ...props @@ -153,7 +154,7 @@ export function DataTableAdvancedToolbar({ {...props} >
- {enableCompactToggle && ( + {enableCompactToggle && ( )} + + {/* ✅ 확장된 DataTableFilterList 사용 */} + ({
- {/* 컴팩트 모드 토글 버튼 */} - {children}
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 { filterFields: DataTableAdvancedFilterField[] debounceMs: number shallow?: boolean + // ✅ 외부에서 전달받은 필터를 적용하기 위한 props + externalFilters?: Filter[] + externalJoinOperator?: JoinOperator + onFiltersChange?: (filters: Filter[], joinOperator: JoinOperator) => void } export function DataTableFilterList({ @@ -79,6 +83,9 @@ export function DataTableFilterList({ filterFields, debounceMs, shallow, + externalFilters, + externalJoinOperator, + onFiltersChange, }: DataTableFilterListProps) { const params = useParams(); @@ -87,6 +94,8 @@ export function DataTableFilterList({ 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({ }) ) + // ✅ 외부 필터가 전달되면 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({ }) } + // ✅ 모든 필터 초기화 (외부 필터 포함) + function resetAllFilters() { + void setFilters([]) + void setJoinOperator("and") + } + function renderFilterInput({ filter, inputId, @@ -198,7 +235,9 @@ export function DataTableFilterList({ 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({ size="sm" variant="outline" className="rounded" - onClick={() => { - void setFilters(null) - void setJoinOperator("and") - }} + onClick={resetAllFilters} + data-filter-reset // ✅ 외부에서 프로그래밍적으로 접근할 수 있도록 data attribute 추가 > {t('resetFilters')} @@ -784,4 +821,4 @@ export function DataTableFilterList({ ) -} +} \ 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({ {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 -- cgit v1.2.3