ERP-node/frontend/lib/meta-components/DataView/views/TableView.tsx

137 lines
3.7 KiB
TypeScript
Raw Normal View History

2026-03-01 03:39:00 +09:00
/**
* TableView - DataView의
* -
* - , ,
*/
"use client";
import React from "react";
import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/components/ui/table";
import { Checkbox } from "@/components/ui/checkbox";
import { Skeleton } from "@/components/ui/skeleton";
import { cn } from "@/lib/utils";
interface TableViewProps {
data: any[];
columns: string[];
tableName: string;
loading?: boolean;
selectedRows?: Set<string>;
onRowSelect?: (rowId: string) => void;
onRowDoubleClick?: (row: any) => void;
}
export function TableView({
data,
columns,
tableName,
loading = false,
selectedRows = new Set(),
onRowSelect,
onRowDoubleClick,
}: TableViewProps) {
// 로딩 스켈레톤
if (loading) {
return (
<div className="space-y-2 p-4">
{Array.from({ length: 5 }).map((_, i) => (
<Skeleton key={i} className="h-10 w-full" />
))}
</div>
);
}
// 데이터 없음
if (data.length === 0) {
return (
<div className="flex flex-col items-center justify-center py-12 text-center">
<div className="mb-2 text-sm font-semibold"> </div>
<p className="text-xs text-muted-foreground"> </p>
</div>
);
}
return (
<div className="overflow-auto">
<Table>
<TableHeader>
<TableRow>
{onRowSelect && (
<TableHead className="w-12">
<Checkbox
checked={selectedRows.size === data.length && data.length > 0}
onCheckedChange={(checked) => {
if (checked) {
data.forEach((row) => onRowSelect(row.id || String(row)));
} else {
data.forEach((row) => onRowSelect(row.id || String(row)));
}
}}
/>
</TableHead>
)}
{columns.map((column) => (
<TableHead key={column} className="text-xs font-medium sm:text-sm">
{column}
</TableHead>
))}
</TableRow>
</TableHeader>
<TableBody>
{data.map((row, rowIndex) => {
const rowId = row.id || String(rowIndex);
const isSelected = selectedRows.has(rowId);
return (
<TableRow
key={rowId}
className={cn(
"cursor-pointer transition-colors hover:bg-muted/50",
isSelected && "bg-muted"
)}
onDoubleClick={() => onRowDoubleClick?.(row)}
>
{onRowSelect && (
<TableCell className="w-12">
<Checkbox
checked={isSelected}
onCheckedChange={() => onRowSelect(rowId)}
/>
</TableCell>
)}
{columns.map((column) => (
<TableCell key={column} className="text-xs sm:text-sm">
{formatCellValue(row[column])}
</TableCell>
))}
</TableRow>
);
})}
</TableBody>
</Table>
</div>
);
}
// 셀 값 포맷팅
function formatCellValue(value: any): string {
if (value === null || value === undefined) {
return "";
}
if (typeof value === "boolean") {
return value ? "O" : "X";
}
if (value instanceof Date) {
return value.toLocaleDateString("ko-KR");
}
if (typeof value === "object") {
return JSON.stringify(value);
}
return String(value);
}