ERP-node/frontend/components/screen/table-options/GroupingPanel.tsx

160 lines
5.2 KiB
TypeScript

import React, { useState } from "react";
import { useTableOptions } from "@/contexts/TableOptionsContext";
import {
Dialog,
DialogContent,
DialogDescription,
DialogFooter,
DialogHeader,
DialogTitle,
} from "@/components/ui/dialog";
import { Button } from "@/components/ui/button";
import { Checkbox } from "@/components/ui/checkbox";
import { ScrollArea } from "@/components/ui/scroll-area";
import { ArrowRight } from "lucide-react";
interface Props {
tableId: string;
open: boolean;
onOpenChange: (open: boolean) => void;
}
export const GroupingPanel: React.FC<Props> = ({
tableId,
open,
onOpenChange,
}) => {
const { getTable } = useTableOptions();
const table = getTable(tableId);
const [selectedColumns, setSelectedColumns] = useState<string[]>([]);
const toggleColumn = (columnName: string) => {
if (selectedColumns.includes(columnName)) {
setSelectedColumns(selectedColumns.filter((c) => c !== columnName));
} else {
setSelectedColumns([...selectedColumns, columnName]);
}
};
const applyGrouping = () => {
table?.onGroupChange(selectedColumns);
onOpenChange(false);
};
const clearGrouping = () => {
setSelectedColumns([]);
table?.onGroupChange([]);
};
return (
<Dialog open={open} onOpenChange={onOpenChange}>
<DialogContent className="max-w-[95vw] sm:max-w-xl">
<DialogHeader>
<DialogTitle className="text-base sm:text-lg"> </DialogTitle>
<DialogDescription className="text-xs sm:text-sm">
</DialogDescription>
</DialogHeader>
<div className="space-y-3 sm:space-y-4">
{/* 상태 표시 */}
<div className="flex items-center justify-between rounded-lg border bg-muted/50 p-3">
<div className="text-xs text-muted-foreground sm:text-sm">
{selectedColumns.length}
</div>
<Button
variant="ghost"
size="sm"
onClick={clearGrouping}
className="h-7 text-xs"
>
</Button>
</div>
{/* 컬럼 리스트 */}
<ScrollArea className="h-[250px] sm:h-[300px]">
<div className="space-y-2 pr-4">
{table?.columns.map((col) => {
const isSelected = selectedColumns.includes(col.columnName);
const order = selectedColumns.indexOf(col.columnName) + 1;
return (
<div
key={col.columnName}
className="flex items-center gap-3 rounded-lg border bg-background p-3 transition-colors hover:bg-muted/50"
>
<Checkbox
checked={isSelected}
onCheckedChange={() => toggleColumn(col.columnName)}
/>
<div className="flex-1">
<div className="text-xs font-medium sm:text-sm">
{col.columnLabel}
</div>
<div className="text-[10px] text-muted-foreground sm:text-xs">
{col.columnName}
</div>
</div>
{isSelected && (
<div className="flex items-center gap-1 rounded-full bg-primary px-2 py-0.5 text-xs text-primary-foreground">
{order}
</div>
)}
</div>
);
})}
</div>
</ScrollArea>
{/* 그룹 순서 미리보기 */}
{selectedColumns.length > 0 && (
<div className="rounded-lg border bg-muted/30 p-3">
<div className="mb-2 text-xs font-medium sm:text-sm">
</div>
<div className="flex flex-wrap items-center gap-2 text-xs sm:text-sm">
{selectedColumns.map((colName, index) => {
const col = table?.columns.find(
(c) => c.columnName === colName
);
return (
<React.Fragment key={colName}>
<div className="rounded bg-primary/10 px-2 py-1 font-medium">
{col?.columnLabel}
</div>
{index < selectedColumns.length - 1 && (
<ArrowRight className="h-3 w-3 text-muted-foreground" />
)}
</React.Fragment>
);
})}
</div>
</div>
)}
</div>
<DialogFooter className="gap-2 sm:gap-0">
<Button
variant="outline"
onClick={() => onOpenChange(false)}
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
>
</Button>
<Button
onClick={applyGrouping}
className="h-8 flex-1 text-xs sm:h-10 sm:flex-none sm:text-sm"
>
</Button>
</DialogFooter>
</DialogContent>
</Dialog>
);
};