149 lines
5.2 KiB
TypeScript
149 lines
5.2 KiB
TypeScript
import { X, Check } from "lucide-react";
|
||
import { Dialog, DialogContent, DialogDescription, DialogHeader, DialogTitle } from "@/components/ui/dialog";
|
||
import { Checkbox } from "@/components/ui/checkbox";
|
||
import { Button } from "@/components/ui/button";
|
||
import { cn } from "@/lib/utils";
|
||
import { ALL_COLUMNS, COLUMN_GROUPS, DEFAULT_VISIBLE_COLUMNS } from "@/lib/config/placement-columns";
|
||
|
||
interface ColumnSelectorDialogProps {
|
||
open: boolean;
|
||
onOpenChange: (open: boolean) => void;
|
||
visibleColumns: Set<string>;
|
||
onVisibleColumnsChange: (columns: Set<string>) => void;
|
||
}
|
||
|
||
export function ColumnSelectorDialog({
|
||
open,
|
||
onOpenChange,
|
||
visibleColumns,
|
||
onVisibleColumnsChange,
|
||
}: ColumnSelectorDialogProps) {
|
||
const handleToggleColumn = (columnId: string) => {
|
||
const next = new Set(visibleColumns);
|
||
if (next.has(columnId)) {
|
||
// Don't allow hiding required columns
|
||
const column = ALL_COLUMNS.find((c) => c.id === columnId);
|
||
if (column?.required) return;
|
||
next.delete(columnId);
|
||
} else {
|
||
next.add(columnId);
|
||
}
|
||
onVisibleColumnsChange(next);
|
||
};
|
||
|
||
const handleToggleGroup = (groupId: string, select: boolean) => {
|
||
const groupColumns = ALL_COLUMNS.filter((c) => c.group === groupId);
|
||
const next = new Set(visibleColumns);
|
||
|
||
groupColumns.forEach((column) => {
|
||
if (column.required) return;
|
||
if (select) {
|
||
next.add(column.id);
|
||
} else {
|
||
next.delete(column.id);
|
||
}
|
||
});
|
||
|
||
onVisibleColumnsChange(next);
|
||
};
|
||
|
||
const isGroupFullySelected = (groupId: string): boolean => {
|
||
const groupColumns = ALL_COLUMNS.filter((c) => c.group === groupId);
|
||
return groupColumns.every((c) => c.required || visibleColumns.has(c.id));
|
||
};
|
||
|
||
const isGroupPartiallySelected = (groupId: string): boolean => {
|
||
const groupColumns = ALL_COLUMNS.filter((c) => c.group === groupId);
|
||
return groupColumns.some((c) => visibleColumns.has(c.id)) && !isGroupFullySelected(groupId);
|
||
};
|
||
|
||
const handleReset = () => {
|
||
onVisibleColumnsChange(new Set(DEFAULT_VISIBLE_COLUMNS));
|
||
};
|
||
|
||
const handleSelectAll = () => {
|
||
onVisibleColumnsChange(new Set(ALL_COLUMNS.map((c) => c.id)));
|
||
};
|
||
|
||
const handleSelectNone = () => {
|
||
onVisibleColumnsChange(
|
||
new Set(ALL_COLUMNS.filter((c) => c.required).map((c) => c.id))
|
||
);
|
||
};
|
||
|
||
return (
|
||
<Dialog open={open} onOpenChange={onOpenChange}>
|
||
<DialogContent className="max-w-2xl max-h-[80vh] overflow-y-auto">
|
||
<DialogHeader>
|
||
<DialogTitle>Выбор колонок</DialogTitle>
|
||
<DialogDescription>
|
||
Выберите колонки для отображения в таблице размещений
|
||
</DialogDescription>
|
||
</DialogHeader>
|
||
|
||
<div className="space-y-6 py-4">
|
||
{/* Quick actions */}
|
||
<div className="flex gap-2">
|
||
<Button variant="outline" size="sm" onClick={handleReset}>
|
||
По умолчанию
|
||
</Button>
|
||
<Button variant="outline" size="sm" onClick={handleSelectAll}>
|
||
Выбрать все
|
||
</Button>
|
||
<Button variant="outline" size="sm" onClick={handleSelectNone}>
|
||
Снять выбор
|
||
</Button>
|
||
</div>
|
||
|
||
{/* Column groups */}
|
||
{COLUMN_GROUPS.map((group) => {
|
||
const groupColumns = ALL_COLUMNS.filter((c) => c.group === group.id);
|
||
return (
|
||
<div key={group.id} className="space-y-3">
|
||
<div className="flex items-center gap-3">
|
||
<Checkbox
|
||
id={`group-${group.id}`}
|
||
checked={isGroupFullySelected(group.id)}
|
||
onCheckedChange={(checked) => handleToggleGroup(group.id, !!checked)}
|
||
/>
|
||
<label
|
||
htmlFor={`group-${group.id}`}
|
||
className="text-sm font-medium cursor-pointer"
|
||
>
|
||
{group.label}
|
||
</label>
|
||
{isGroupPartiallySelected(group.id) && (
|
||
<span className="text-xs text-muted-foreground">(частично выбрано)</span>
|
||
)}
|
||
</div>
|
||
|
||
<div className="grid grid-cols-2 md:grid-cols-3 gap-2 ml-6">
|
||
{groupColumns.map((column) => (
|
||
<div key={column.id} className="flex items-center gap-2">
|
||
<Checkbox
|
||
id={`col-${column.id}`}
|
||
checked={visibleColumns.has(column.id)}
|
||
onCheckedChange={() => handleToggleColumn(column.id)}
|
||
disabled={column.required}
|
||
/>
|
||
<label
|
||
htmlFor={`col-${column.id}`}
|
||
className={cn(
|
||
"text-xs cursor-pointer truncate",
|
||
column.required && "font-medium"
|
||
)}
|
||
>
|
||
{column.label}
|
||
</label>
|
||
</div>
|
||
))}
|
||
</div>
|
||
</div>
|
||
);
|
||
})}
|
||
</div>
|
||
</DialogContent>
|
||
</Dialog>
|
||
);
|
||
}
|