diff --git a/client/src/app/catalog/components/CatalogDataTable.tsx b/client/src/app/catalog/components/CatalogDataTable.tsx index a476b8f..59a8b06 100644 --- a/client/src/app/catalog/components/CatalogDataTable.tsx +++ b/client/src/app/catalog/components/CatalogDataTable.tsx @@ -29,27 +29,19 @@ export const CatalogDataTable = () => { { id: "id" as const, accessorKey: "id", - enableResizing: false, - size: 10, }, { id: "article_id" as const, accessorKey: "id_article", - enableResizing: false, - size: 10, }, { id: "catalog_name" as const, accessorKey: "catalog_name", - enableResizing: false, - size: 10, }, { id: "description" as const, accessorKey: "description", header: () => <>{t("catalog.list.columns.description")}, - enableResizing: false, - size: 100, }, { id: "points" as const, @@ -58,8 +50,6 @@ export const CatalogDataTable = () => { cell: ({ renderValue }: { renderValue: () => any }) => (
{renderValue()}
), - enableResizing: false, - size: 20, }, { id: "retail_price" as const, @@ -69,8 +59,6 @@ export const CatalogDataTable = () => { const price = MoneyValue.create(row.original.retail_price).object; return
{price.toFormat()}
; }, - enableResizing: false, - size: 20, }, ], [] diff --git a/client/src/app/quotes/components/AppendCatalogArticleRowButton.tsx b/client/src/app/quotes/components/AppendCatalogArticleRowButton.tsx index d675286..409644e 100644 --- a/client/src/app/quotes/components/AppendCatalogArticleRowButton.tsx +++ b/client/src/app/quotes/components/AppendCatalogArticleRowButton.tsx @@ -1,4 +1,3 @@ -import { cn } from "@/lib/utils"; import { Button, ButtonProps } from "@/ui"; import { t } from "i18next"; import { PackagePlusIcon } from "lucide-react"; @@ -13,16 +12,8 @@ export const AppendCatalogArticleRowButton = ({ className, ...props }: AppendCatalogArticleRowButtonProps): JSX.Element => ( - diff --git a/client/src/app/quotes/components/AppendEmptyRowButton.tsx b/client/src/app/quotes/components/AppendEmptyRowButton.tsx index 87a2e16..9524d9a 100644 --- a/client/src/app/quotes/components/AppendEmptyRowButton.tsx +++ b/client/src/app/quotes/components/AppendEmptyRowButton.tsx @@ -1,4 +1,3 @@ -import { cn } from "@/lib/utils"; import { Button, ButtonProps } from "@/ui"; import { t } from "i18next"; import { PlusCircleIcon } from "lucide-react"; @@ -13,16 +12,7 @@ export const AppendEmptyRowButton = ({ className, ...props }: AppendEmptyRowButtonProps): JSX.Element => ( - diff --git a/client/src/app/quotes/components/CatalogPickerDataTable.tsx b/client/src/app/quotes/components/CatalogPickerDataTable.tsx index f186e00..f388dff 100644 --- a/client/src/app/quotes/components/CatalogPickerDataTable.tsx +++ b/client/src/app/quotes/components/CatalogPickerDataTable.tsx @@ -4,10 +4,11 @@ import { useCatalogList } from "@/app/catalog/hooks"; import { DataTable } from "@/components"; import { DataTableToolbar } from "@/components/DataTable/DataTableToolbar"; import { useDataTable, useDataTableContext } from "@/lib/hooks"; -import { cn } from "@/lib/utils"; +import { Button } from "@/ui"; import { IListArticles_Response_DTO, MoneyValue } from "@shared/contexts"; import { ColumnDef, Row } from "@tanstack/react-table"; import { t } from "i18next"; +import { PackagePlusIcon } from "lucide-react"; import { useMemo } from "react"; import { useNavigate } from "react-router-dom"; @@ -28,58 +29,45 @@ export const CatalogPickerDataTable = ({ onSelect }: { onSelect: (data: unknown) { id: "description" as const, accessorKey: "description", - enableResizing: false, - header: () => null, - cell: ({ - row, - renderValue, - }: { - row: Row; - renderValue: () => any; - }) => { + header: () => <>{t("catalog.list.columns.description")}, + }, + { + id: "points" as const, + accessorKey: "points", + header: () =>
{t("catalog.list.columns.points")}
, + cell: ({ renderValue }: { renderValue: () => any }) => ( +
{renderValue()}
+ ), + }, + { + id: "retail_price" as const, + accessorKey: "retail_price", + header: () =>
{t("catalog.list.columns.retail_price")}
, + cell: ({ row }: { row: Row }) => { const price = MoneyValue.create(row.original.retail_price).object; - const points = row.original.points; - return ( - - ); + return
{price.toFormat()}
; }, }, + { + id: "row-actions", + header: () => null, + cell: ({ row }: { row: Row }) => ( + + ), + }, ]; }, []); @@ -119,12 +107,8 @@ export const CatalogPickerDataTable = ({ onSelect }: { onSelect: (data: unknown) diff --git a/client/src/app/quotes/components/QuoteItemsSortableDataTable.tsx b/client/src/app/quotes/components/QuoteItemsSortableDataTable.tsx index 24b83ca..fbf809e 100644 --- a/client/src/app/quotes/components/QuoteItemsSortableDataTable.tsx +++ b/client/src/app/quotes/components/QuoteItemsSortableDataTable.tsx @@ -1,14 +1,6 @@ -import { DataTableColumnHeader } from "@/components"; -import { Badge } from "@/ui"; -import { - Table, - TableBody, - TableCell, - TableFooter, - TableHead, - TableHeader, - TableRow, -} from "@/ui/table"; +import { ButtonGroup, DataTableColumnHeader } from "@/components"; +import { Badge, Card, CardContent, CardFooter, CardHeader, CardTitle } from "@/ui"; +import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from "@/ui/table"; import { DndContext, DragEndEvent, @@ -30,6 +22,7 @@ import { SortableContext, verticalListSortingStrategy } from "@dnd-kit/sortable" import { CSS } from "@dnd-kit/utilities"; import { ColumnDef, + InitialTableState, Row, RowData, RowSelectionState, @@ -65,6 +58,7 @@ export type QuoteItemsSortableDataTableProps = { columns: ColumnDef[]; data: Record<"id", string>[]; defaultValues: Readonly<{ [x: string]: any }> | undefined; + initialState?: InitialTableState; actions: Omit, "fields"> & Record; }; @@ -101,13 +95,17 @@ export function QuoteItemsSortableDataTable({ columns, data, defaultValues, + initialState, actions, }: QuoteItemsSortableDataTableProps) { const [rowSelection, setRowSelection] = useState({}); const [activeId, setActiveId] = useState(); // eslint-disable-next-line @typescript-eslint/no-unused-vars - const [columnVisibility, setColumnVisibility] = useState({}); + const [columnVisibility, setColumnVisibility] = useState( + initialState?.columnVisibility || {} + ); + const sorteableRowIds = useMemo(() => data.map((item) => item.id), [data]); const table = useReactTable({ @@ -116,6 +114,8 @@ export function QuoteItemsSortableDataTable({ enableColumnResizing: false, columnResizeMode: "onChange", //defaultColumn, + + initialState, state: { rowSelection, columnVisibility, @@ -124,16 +124,21 @@ export function QuoteItemsSortableDataTable({ enableMultiRowSelection: true, enableSorting: false, enableHiding: true, + onRowSelectionChange: setRowSelection, getCoreRowModel: getCoreRowModel(), getRowId: (originalRow: unknown) => originalRow?.id, + + debugTable: false, debugHeaders: false, debugColumns: false, + defaultColumn: { - size: 8, //starting column size - minSize: 1, //enforced during column resizing - maxSize: 96, //enforced during column resizing + minSize: 0, //starting column size + size: Number.MAX_SAFE_INTEGER, //enforced during column resizing + maxSize: Number.MAX_SAFE_INTEGER, //enforced during column resizing }, + meta: { insertItem: (rowIndex: number, data?: unknown) => { actions.insert(rowIndex, data || defaultValues?.items[0], { shouldFocus: true }); @@ -154,7 +159,7 @@ export function QuoteItemsSortableDataTable({ const data = table .getSelectedRowModel() - .rows.map((row) => ({ ...row.original, id: undefined })); + .rows.map((row: Row) => ({ ...row.original, id: undefined })); if (table.getRowModel().rows.length < lastIndex + 1) { actions.append(data); @@ -184,7 +189,7 @@ export function QuoteItemsSortableDataTable({ actions.remove(); } }, - updateItem: (rowIndex: number, rowData: unknown, fieldName: string, value: unknown) => { + updateItem: (rowIndex: number, rowData: any, fieldName: string, value: unknown) => { // Skip page index reset until after next rerender // skipAutoResetPageIndex(); actions.update(rowIndex, { ...rowData, [`${fieldName}`]: value }); @@ -264,169 +269,189 @@ export function QuoteItemsSortableDataTable({ onDragCancel={handleDragCancel} collisionDetection={closestCenter} > - - - - {table.getHeaderGroups().map((headerGroup) => ( - - {headerGroup.headers.map((header) => { - return ( - - {header.isPlaceholder ? null : ( - - )} - - ); - })} - - ))} - - - - {filterItems(table.getRowModel().rows).map((row) => ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - + + + + + + + +
+ + {table.getHeaderGroups().map((headerGroup) => ( + + {headerGroup.headers.map((header) => { + return ( + + {header.isPlaceholder ? null : ( + + )} + + ); + })} + + ))} + + + + {filterItems(table.getRowModel().rows).map((row) => ( + ).id} id={(row as Row).id}> + {(row as Row).getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + ))} - - ))} - - - - - - -
- table.options.meta?.appendItem()} /> - table.options.meta?.pickCatalogArticle()} - /> -
-
- -
-
-
+ + + - {createPortal( - - {activeId && ( -
- {table.getSelectedRowModel().rows.length ? ( - - {table.getSelectedRowModel().rows.length} - - ) : null} -
- - - {table.getRowModel().rows.map( - (row) => - row.id === activeId && ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - ) - )} - -
-
+ {createPortal( + + {activeId && ( +
+ {table.getSelectedRowModel().rows.length ? ( + + {table.getSelectedRowModel().rows.length} + + ) : null} +
+ + + {table.getRowModel().rows.map( + (row) => + row.id === activeId && ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + ) + )} + +
+
- {table.getSelectedRowModel().rows.length > 1 && ( -
- - - {table.getRowModel().rows.map( - (row) => - row.id === activeId && ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - ) - )} - -
+ {table.getSelectedRowModel().rows.length > 1 && ( +
+ + + {table.getRowModel().rows.map( + (row) => + row.id === activeId && ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + ) + )} + +
+
+ )} + + {table.getSelectedRowModel().rows.length > 2 && ( +
+ + + {table.getRowModel().rows.map( + (row) => + row.id === activeId && ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + ) + )} + +
+
+ )} + + {table.getSelectedRowModel().rows.length > 3 && ( +
+ + + {table.getRowModel().rows.map( + (row) => + row.id === activeId && ( + + {row.getVisibleCells().map((cell) => ( + + {flexRender(cell.column.columnDef.cell, cell.getContext())} + + ))} + + ) + )} + +
+
+ )}
)} - - {table.getSelectedRowModel().rows.length > 2 && ( -
- - - {table.getRowModel().rows.map( - (row) => - row.id === activeId && ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - ) - )} - -
-
- )} - - {table.getSelectedRowModel().rows.length > 3 && ( -
- - - {table.getRowModel().rows.map( - (row) => - row.id === activeId && ( - - {row.getVisibleCells().map((cell) => ( - - {flexRender(cell.column.columnDef.cell, cell.getContext())} - - ))} - - ) - )} - -
-
- )} -
+
, + document.body )} - , - document.body - )} + + + + table.options.meta?.appendItem()} /> + table.options.meta?.pickCatalogArticle()} + /> + + + ); } diff --git a/client/src/app/quotes/components/QuoteItemsSortableDataTableToolbar.tsx b/client/src/app/quotes/components/QuoteItemsSortableDataTableToolbar.tsx index 1c4474a..456922d 100644 --- a/client/src/app/quotes/components/QuoteItemsSortableDataTableToolbar.tsx +++ b/client/src/app/quotes/components/QuoteItemsSortableDataTableToolbar.tsx @@ -1,102 +1,92 @@ import { Button, Separator, Tooltip, TooltipContent, TooltipTrigger } from "@/ui"; import { Table } from "@tanstack/react-table"; import { t } from "i18next"; -import { CirclePlusIcon, CopyPlusIcon, PackagePlusIcon, ScanIcon, Trash2Icon } from "lucide-react"; +import { CopyPlusIcon, ScanIcon, Trash2Icon } from "lucide-react"; +import { AppendCatalogArticleRowButton } from "./AppendCatalogArticleRowButton"; +import { AppendEmptyRowButton } from "./AppendEmptyRowButton"; export const QuoteItemsSortableDataTableToolbar = ({ table }: { table: Table }) => { const selectedRowsCount = table.getSelectedRowModel().rows.length; if (selectedRowsCount) { return ( - - ); - } - - return ( -
), - enableResizing: false, - size: 640, + size: 600, }, { @@ -152,13 +148,12 @@ export const QuotesDataTable = ({
{price.isSuccess ? price.object.toFormat() : "-"}
); }, - enableResizing: false, }, { id: "row-actions", header: () => null, cell: ({ row }: { row: Row }) => ( -
+
+ ), - enableResizing: false, }, ], // eslint-disable-next-line react-hooks/exhaustive-deps diff --git a/client/src/app/quotes/components/editors/CatalogPickerDialog.tsx b/client/src/app/quotes/components/editors/CatalogPickerDialog.tsx index f5732c6..49f85f7 100644 --- a/client/src/app/quotes/components/editors/CatalogPickerDialog.tsx +++ b/client/src/app/quotes/components/editors/CatalogPickerDialog.tsx @@ -33,7 +33,9 @@ export const CatalogPickerDialog = ({ - + diff --git a/client/src/app/quotes/components/editors/QuoteDetailsCardEditor.tsx b/client/src/app/quotes/components/editors/QuoteDetailsCardEditor.tsx index 9beedc1..3a192ba 100644 --- a/client/src/app/quotes/components/editors/QuoteDetailsCardEditor.tsx +++ b/client/src/app/quotes/components/editors/QuoteDetailsCardEditor.tsx @@ -11,7 +11,7 @@ import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/ui"; import { CurrencyData, Language, Quantity } from "@shared/contexts"; import { ColumnDef } from "@tanstack/react-table"; import { t } from "i18next"; -import { ChevronDownIcon, ChevronUpIcon, CopyIcon, Trash2Icon } from "lucide-react"; +import { ChevronDownIcon, ChevronUpIcon, Trash2Icon } from "lucide-react"; import { useCallback, useState } from "react"; import { useFieldArray, useFormContext } from "react-hook-form"; import { useDetailColumns } from "../../hooks"; @@ -46,21 +46,20 @@ export const QuoteDetailsCardEditor = ({ header: () => ( ), - accessorFn: (originalRow: unknown, index: number) => index + 1, + accessorFn: (_: unknown, index: number) => index + 1, size: 5, enableHiding: false, enableSorting: false, enableResizing: false, },*/ - { id: "description" as const, accessorKey: "description", header: t("quotes.form_fields.items.description.label"), - size: 24, cell: ({ row: { index } }) => { return ; }, + size: 500, }, { id: "quantity" as const, @@ -68,7 +67,6 @@ export const QuoteDetailsCardEditor = ({ header: () => (
{t("quotes.form_fields.items.quantity.label")}
), - size: 6, cell: ({ row: { index } }) => { return ( (
{t("quotes.form_fields.items.subtotal_price.label")}
), - size: 12, cell: ({ row: { index } }) => { return ( (
{t("quotes.form_fields.items.discount.label")}
), @@ -140,7 +136,6 @@ export const QuoteDetailsCardEditor = ({ header: () => (
{t("quotes.form_fields.items.total_price.label")}
), - size: 12, cell: ({ row: { index } }) => { return ( { const { table, row } = props; return [ - { + /*{ label: t("common.duplicate_row"), icon: , onClick: () => table.options.meta?.duplicateItems(row.index), - }, + },*/ { label: t("common.insert_row_above"), icon: , diff --git a/client/src/app/quotes/hooks/useDetailColumns.tsx b/client/src/app/quotes/hooks/useDetailColumns.tsx index 323e2f2..cdf7d28 100644 --- a/client/src/app/quotes/hooks/useDetailColumns.tsx +++ b/client/src/app/quotes/hooks/useDetailColumns.tsx @@ -36,12 +36,9 @@ export function useDetailColumns( ),*/ header: () => null, cell: (info) => , - size: 2, - minSize: 2, - maxSize: 2, - enableSorting: false, enableHiding: false, + size: 40, }); } @@ -74,9 +71,7 @@ export function useDetailColumns( ), enableSorting: false, enableHiding: false, - size: 2, - minSize: 2, - maxSize: 2, + size: 40, }); } @@ -90,18 +85,11 @@ export function useDetailColumns( /> ),*/ cell: (props) => { - return ( -
- -
- ); + return ; }, - size: 4, - minSize: 4, - maxSize: 4, - enableSorting: false, enableHiding: false, + size: 48, }); } diff --git a/client/src/components/ButtonGroup/ButtonGroup.tsx b/client/src/components/ButtonGroup/ButtonGroup.tsx index 91fcfc2..9d2d23a 100644 --- a/client/src/components/ButtonGroup/ButtonGroup.tsx +++ b/client/src/components/ButtonGroup/ButtonGroup.tsx @@ -1,14 +1,9 @@ import { cn } from "@/lib/utils"; import React from "react"; -export const ButtonGroup = React.forwardRef< - HTMLDivElement, - React.HTMLAttributes ->(({ className, ...props }, ref) => ( -
-)); +export const ButtonGroup = React.forwardRef>( + ({ className, ...props }, ref) => ( +
+ ) +); ButtonGroup.displayName = "ButtonGroup"; diff --git a/client/src/components/DataTable/DataTable.tsx b/client/src/components/DataTable/DataTable.tsx index 3bad817..44407dc 100644 --- a/client/src/components/DataTable/DataTable.tsx +++ b/client/src/components/DataTable/DataTable.tsx @@ -89,17 +89,18 @@ export function DataTable({ {table.getHeaderGroups().map((headerGroup) => ( - {headerGroup.headers.map((header) => { - return ( - - - - ); - })} + {headerGroup.headers.map((header) => ( + + + + ))} ))} @@ -124,7 +125,16 @@ export function DataTable({ )} > {row.getVisibleCells().map((cell) => ( - + {flexRender(cell.column.columnDef.cell, cell.getContext())} ))} diff --git a/client/src/components/DataTable/DataTableColumnHeader.tsx b/client/src/components/DataTable/DataTableColumnHeader.tsx index 15fa1c7..7915f2f 100644 --- a/client/src/components/DataTable/DataTableColumnHeader.tsx +++ b/client/src/components/DataTable/DataTableColumnHeader.tsx @@ -32,7 +32,7 @@ export function DataTableColumnHeader({ : flexRender(header.column.columnDef.header, header.getContext())}
- {header.column.getCanResize() && ( + {false && header.column.getCanResize() && ( ({ enablePageSizeSelector ? "justify-end" : "justify-between" )} > -
+

{t("common.num_page_of_total", { count: table.getState().pagination.pageIndex + 1, diff --git a/client/src/components/DataTable/DataTableRowActions.tsx b/client/src/components/DataTable/DataTableRowActions.tsx index b942e1d..9f92679 100644 --- a/client/src/components/DataTable/DataTableRowActions.tsx +++ b/client/src/components/DataTable/DataTableRowActions.tsx @@ -1,6 +1,5 @@ "use client"; -import { cn } from "@/lib/utils"; import { Button, DropdownMenu, @@ -42,13 +41,8 @@ export function DataTableRowActions({ return ( - diff --git a/client/src/components/SorteableDataTable/SortableDataTable.tsx b/client/src/components/SorteableDataTable/SortableDataTable.tsx index 08f4da1..676ff9b 100644 --- a/client/src/components/SorteableDataTable/SortableDataTable.tsx +++ b/client/src/components/SorteableDataTable/SortableDataTable.tsx @@ -134,7 +134,11 @@ export function SortableDataTable({ columns, data, actions }: SortableDataTableP columns, enableColumnResizing: false, columnResizeMode: "onChange", - //defaultColumn, + defaultColumn: { + minSize: 0, + size: Number.MAX_SAFE_INTEGER, + maxSize: Number.MAX_SAFE_INTEGER, + }, state: { rowSelection, columnVisibility, diff --git a/client/src/lib/hooks/useDataTable/useDataTable.tsx b/client/src/lib/hooks/useDataTable/useDataTable.tsx index ebc0708..92c0796 100644 --- a/client/src/lib/hooks/useDataTable/useDataTable.tsx +++ b/client/src/lib/hooks/useDataTable/useDataTable.tsx @@ -207,9 +207,9 @@ export function useDataTable({ debugColumns: false, defaultColumn: { - size: 96, //starting column size - minSize: 96, //enforced during column resizing - maxSize: 500, //enforced during column resizing + minSize: 0, //starting column size + size: Number.MAX_SAFE_INTEGER, //enforced during column resizing + maxSize: Number.MAX_SAFE_INTEGER, //enforced during column resizing }, }); diff --git a/client/src/locales/en.json b/client/src/locales/en.json index 0fcbd7a..902db6b 100644 --- a/client/src/locales/en.json +++ b/client/src/locales/en.json @@ -13,6 +13,7 @@ "upload": "Upload", "continue": "Continue", "close": "Close", + "add": "Add", "sort_asc": "Asc", "sort_asc_description": "In ascending order. Click to sort descending order.", "sort_desc": "Desc", diff --git a/client/src/locales/es.json b/client/src/locales/es.json index 872cd1e..70d9f1d 100644 --- a/client/src/locales/es.json +++ b/client/src/locales/es.json @@ -13,6 +13,7 @@ "upload": "Cargar", "continue": "Continuar", "close": "Cerrar", + "add": "AƱadir", "sort_asc": "Asc", "sort_asc_description": "En order ascendente. Click para ordenar descendentemente.", "sort_desc": "Desc",