summaryrefslogtreecommitdiff
path: root/components/data-table
diff options
context:
space:
mode:
authordujinkim <dujin.kim@dtsolution.co.kr>2025-07-24 11:06:32 +0000
committerdujinkim <dujin.kim@dtsolution.co.kr>2025-07-24 11:06:32 +0000
commit1dc24d48e52f2e490f5603ceb02842586ecae533 (patch)
tree8fca2c5b5b52cc10557b5ba6e55b937ae3c57cf6 /components/data-table
parented0d6fcc98f671280c2ccde797b50693da88152e (diff)
(대표님) 정기평가 피드백 반영, 설계 피드백 반영, (최겸) 기술영업 피드백 반영
Diffstat (limited to 'components/data-table')
-rw-r--r--components/data-table/data-table-advanced-toolbar.tsx50
-rw-r--r--components/data-table/data-table-filter-list.tsx49
-rw-r--r--components/data-table/data-table-view-options.tsx2
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