feat: add package grouping UI with expand/collapse, selection, and manual grouping

- Update STL page to use listDisplayItems query for mixed package/group display
- Rewrite package-columns to handle StlTableRow union type (group headers + packages)
- Add group expand/collapse with chevron toggle and indented member rows
- Add checkbox selection with "Group N Selected" toolbar button and dialog
- Add inline group actions: rename, dissolve, send all, remove member
- Add clickable group preview thumbnail with file upload for preview images
- Extend DataTable with optional rowClassName prop for group row styling

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-25 22:39:23 +01:00
parent f6e7f5ed3c
commit d50c68f67c
4 changed files with 634 additions and 88 deletions

View File

@@ -1,6 +1,6 @@
"use client";
import { type Table as TanStackTable, flexRender } from "@tanstack/react-table";
import { type Table as TanStackTable, type Row, flexRender } from "@tanstack/react-table";
import {
Table,
TableBody,
@@ -10,13 +10,15 @@ import {
TableRow,
} from "@/components/ui/table";
import { EmptyState } from "./empty-state";
import { cn } from "@/lib/utils";
interface DataTableProps<TData> {
table: TanStackTable<TData>;
emptyMessage?: string;
rowClassName?: (row: Row<TData>) => string;
}
export function DataTable<TData>({ table, emptyMessage }: DataTableProps<TData>) {
export function DataTable<TData>({ table, emptyMessage, rowClassName }: DataTableProps<TData>) {
return (
<div className="rounded-md border border-border">
<Table>
@@ -36,7 +38,10 @@ export function DataTable<TData>({ table, emptyMessage }: DataTableProps<TData>)
<TableBody>
{table.getRowModel().rows?.length ? (
table.getRowModel().rows.map((row) => (
<TableRow key={row.id} className="h-10 border-border hover:bg-muted/50">
<TableRow
key={row.id}
className={cn("h-10 border-border hover:bg-muted/50", rowClassName?.(row))}
>
{row.getVisibleCells().map((cell) => (
<TableCell key={cell.id} className="py-1.5 text-sm">
{flexRender(cell.column.columnDef.cell, cell.getContext())}