summaryrefslogtreecommitdiff
path: root/lib/material/table/material-table.tsx
diff options
context:
space:
mode:
authorjoonhoekim <26rote@gmail.com>2025-09-01 10:22:55 +0000
committerjoonhoekim <26rote@gmail.com>2025-09-01 10:22:55 +0000
commitf72142f6cc46c7be5bf90803d365c2ecd144c53d (patch)
tree6cfefba8edc8573bc99bee14ae7ed95914692430 /lib/material/table/material-table.tsx
parent20ba04d8588a7dfa6f65b1c080d6373631449f59 (diff)
(김준회) MDG 자재마스터 정보 조회 기능 및 메뉴 추가, 회원가입시 공급품목 선택 기능 추가
Diffstat (limited to 'lib/material/table/material-table.tsx')
-rw-r--r--lib/material/table/material-table.tsx199
1 files changed, 199 insertions, 0 deletions
diff --git a/lib/material/table/material-table.tsx b/lib/material/table/material-table.tsx
new file mode 100644
index 00000000..6870a030
--- /dev/null
+++ b/lib/material/table/material-table.tsx
@@ -0,0 +1,199 @@
+"use client"
+
+import * as React from "react"
+import type {
+ DataTableAdvancedFilterField,
+ DataTableFilterField,
+ DataTableRowAction,
+} from "@/types/table"
+
+import { useDataTable } from "@/hooks/use-data-table"
+import { DataTable } from "@/components/data-table/data-table"
+import { InfiniteDataTable } from "@/components/data-table/infinite-data-table"
+import { DataTableAdvancedToolbar } from "@/components/data-table/data-table-advanced-toolbar"
+import { Button } from "@/components/ui/button"
+import { Alert, AlertDescription } from "@/components/ui/alert"
+
+import { getMaterials } from "../services"
+import { getColumns } from "./material-table-columns"
+import { MaterialDetailDialog } from "./material-detail-dialog"
+import { ViewModeToggle } from "@/components/data-table/view-mode-toggle"
+
+// Material 타입 정의 (서비스에서 반환되는 타입과 일치)
+type Material = {
+ id: number;
+ MATKL: string | null; // 자재그룹(=자재그룹코드)
+ MATNR: string | null; // 자재코드
+ ZZNAME: string | null; // 자재명
+ ZZPJT: string | null; // 프로젝트
+ createdAt: Date;
+ updatedAt: Date;
+}
+
+interface MaterialTableProps {
+ promises?: Promise<
+ [
+ Awaited<ReturnType<typeof getMaterials>>,
+ ]
+ >
+}
+
+export function MaterialTable({ promises }: MaterialTableProps) {
+ // 페이지네이션 모드 데이터
+ const paginationData = promises ? React.use(promises) : null
+ const [{ data = [], pageCount = 0 }] = paginationData || [{ data: [], pageCount: 0 }]
+
+ console.log('MaterialTable data:', data.length, 'materials')
+
+ const [rowAction, setRowAction] =
+ React.useState<DataTableRowAction<Material> | null>(null)
+
+ const columns = React.useMemo(
+ () => getColumns({ setRowAction }),
+ [setRowAction]
+ )
+
+ // 기존 필터 필드들
+ const filterFields: DataTableFilterField<Material>[] = [
+ {
+ id: "MATKL",
+ label: "자재그룹",
+ },
+ {
+ id: "MATNR",
+ label: "자재코드",
+ },
+ ]
+
+ const advancedFilterFields: DataTableAdvancedFilterField<Material>[] = [
+ {
+ id: "MATKL",
+ label: "자재그룹",
+ type: "text",
+ },
+ {
+ id: "MATNR",
+ label: "자재코드",
+ type: "text",
+ },
+ {
+ id: "ZZNAME",
+ label: "자재명",
+ type: "text",
+ },
+ {
+ id: "ZZPJT",
+ label: "프로젝트",
+ type: "text",
+ },
+ ]
+
+ // 확장된 useDataTable 훅 사용 (pageSize 기반 자동 전환)
+ const {
+ table,
+ infiniteScroll,
+ isInfiniteMode,
+ handlePageSizeChange,
+ } = useDataTable({
+ data,
+ columns,
+ pageCount,
+ filterFields,
+ enablePinning: true,
+ enableAdvancedFilter: true,
+ initialState: {
+ sorting: [{ id: "createdAt", desc: true }],
+ columnPinning: { left: ["select"], right: ["actions"] },
+ },
+ getRowId: (originalRow) => String(originalRow.id),
+ shallow: false,
+ clearOnDefault: true,
+ // 무한 스크롤 설정
+ infiniteScrollConfig: {
+ apiEndpoint: "/api/table/materials/infinite",
+ tableName: "materials",
+ maxPageSize: 100,
+ },
+ })
+
+ return (
+ <div className="w-full space-y-2.5 overflow-x-auto" style={{maxWidth:'100vw'}}>
+
+ {/* 모드 토글 */}
+ <div className="flex items-center justify-between">
+ <ViewModeToggle
+ isInfiniteMode={isInfiniteMode}
+ onSwitch={handlePageSizeChange}
+ />
+ </div>
+
+ {/* 에러 상태 (무한 스크롤 모드) */}
+ {isInfiniteMode && infiniteScroll?.error && (
+ <Alert variant="destructive">
+ <AlertDescription>
+ 데이터를 불러오는 중 오류가 발생했습니다.
+ <Button
+ variant="link"
+ size="sm"
+ onClick={() => infiniteScroll.reset()}
+ className="ml-2 p-0 h-auto"
+ >
+ 다시 시도
+ </Button>
+ </AlertDescription>
+ </Alert>
+ )}
+
+ {/* 로딩 상태가 아닐 때만 테이블 렌더링 */}
+ {!(isInfiniteMode && infiniteScroll?.isLoading && infiniteScroll?.isEmpty) ? (
+ <>
+ {/* 도구 모음 */}
+ <DataTableAdvancedToolbar
+ table={table}
+ filterFields={advancedFilterFields}
+ shallow={false}
+ />
+
+ {/* 테이블 렌더링 */}
+ {isInfiniteMode ? (
+ // 무한 스크롤 모드: InfiniteDataTable 사용
+ <InfiniteDataTable
+ table={table}
+ hasNextPage={infiniteScroll?.hasNextPage || false}
+ isLoadingMore={infiniteScroll?.isLoadingMore || false}
+ onLoadMore={infiniteScroll?.onLoadMore}
+ totalCount={infiniteScroll?.totalCount}
+ isEmpty={infiniteScroll?.isEmpty || false}
+ compact={false}
+ autoSizeColumns={true}
+ />
+ ) : (
+ // 페이지네이션 모드: DataTable 사용
+ <DataTable
+ table={table}
+ compact={false}
+ autoSizeColumns={true}
+ />
+ )}
+ </>
+ ) : (
+ /* 로딩 스켈레톤 (무한 스크롤 초기 로딩) */
+ <div className="space-y-3">
+ <div className="text-sm text-muted-foreground mb-4">
+ 무한 스크롤 모드로 데이터를 로드하고 있습니다...
+ </div>
+ {Array.from({ length: 10 }).map((_, i) => (
+ <div key={i} className="h-12 w-full bg-muted animate-pulse rounded" />
+ ))}
+ </div>
+ )}
+
+ {/* 상세보기 다이얼로그 */}
+ <MaterialDetailDialog
+ open={rowAction?.type === "view"}
+ onOpenChange={() => setRowAction(null)}
+ matnr={rowAction?.row.original?.MATNR || null}
+ />
+ </div>
+ )
+}