Uecko_ERP/modules/customer-invoices/src/web/components/items/customer-invoice-items-card-editor.tsx
2025-07-16 17:47:45 +02:00

288 lines
8.7 KiB
TypeScript

import { FormControl, FormField, FormItem, FormMessage, Input } from "@repo/shadcn-ui/components";
import { TextAreaField } from "@repo/rdx-ui/components";
import { ColumnDef } from "@tanstack/react-table";
import { ChevronDownIcon, ChevronUpIcon, CopyIcon, Trash2Icon } from "lucide-react";
import { useState } from "react";
import { useFieldArray, useFormContext } from "react-hook-form";
import { useDetailColumns } from "../../hooks";
import { useTranslation } from "../../i18n";
import { formatCurrency } from "../../pages/create/utils";
import { CustomerInvoiceTaxesMultiSelect } from "../customer-invoice-taxes-multi-select";
import {
CustomerInvoiceItemsSortableDataTable,
RowIdData,
} from "./customer-invoice-items-sortable-datatable";
export const CustomerInvoiceItemsCardEditor = ({
//currency,
//language,
defaultValues,
}: {
//currency: CurrencyData;
//language: Language;
defaultValues: Readonly<{ [x: string]: any }> | undefined;
}) => {
const { t } = useTranslation();
const { control, watch, getValues } = useFormContext();
const watchedItems = watch("items");
//const [pickerMode] = useState<"dialog" | "panel">("dialog");
//const [articlePickerDialogOpen, setArticlePickerDialogOpen] = useState<boolean>(false);
//const [blockPickerDialogOpen, setBlockPickerDialogOpen] = useState<boolean>(false);
const { fields, ...fieldActions } = useFieldArray({
control,
name: "items",
});
const columns: ColumnDef<RowIdData, unknown>[] = useDetailColumns(
[
/*{
id: "row_id" as const,
header: () => (
<HashIcon aria-label='Orden de fila' className='items-center justify-center w-4 h-4' />
),
accessorFn: (_: unknown, index: number) => index + 1,
size: 5,
enableHiding: false,
enableSorting: false,
enableResizing: false,
},*/
/*{
id: "id_article" as const,
accessorKey: "id_article",
header: "artículo",
cell: ({ row: { index, original } }) => {
return (
<FormTextAreaField
readOnly={original?.id_article}
autoSize
{...register(`items.${index}.id_article`)}
/>
);
},
size: 500,
},*/
{
id: "description" as const,
accessorKey: "description",
header: t("form_fields.items.description.label"),
cell: ({ row: { index, original } }) => (
<TextAreaField
control={control}
name={`items.${index}.description`}
placeholder={t("form_fields.items.description.placeholder")}
className='md:col-span-2'
/>
),
minSize: 200,
size: 400,
},
{
id: "quantity" as const,
accessorKey: "quantity",
header: () => <div className='text-right'>{t("form_fields.items.quantity.label")}</div>,
cell: ({ row: { index } }) => (
<FormField
control={control}
name={`items.${index}.quantity.amount`}
render={({ field }) => (
<FormItem>
<FormControl>
<Input
type='number'
step='0.01'
min='0'
{...field}
onChange={(e) => field.onChange(Number(e.target.value) * 100)}
value={field.value / 100}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
),
size: 75,
},
{
id: "unit_price" as const,
accessorKey: "unit_price",
header: () => <div className='text-right'>{t("form_fields.items.unit_price.label")}</div>,
cell: ({ row: { index } }) => (
<FormField
control={control}
name={`items.${index}.unit_price.amount`}
render={({ field }) => (
<FormItem>
<FormControl>
<Input
type='number'
step='0.01'
min='0'
{...field}
onChange={(e) => field.onChange(Number(e.target.value) * 100)}
value={field.value / 100}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
),
size: 125,
},
{
id: "subtotal_price" as const,
accessorKey: "subtotal_price",
header: () => (
<div className='text-right'>{t("form_fields.items.subtotal_price.label")}</div>
),
cell: ({ row: { index } }) => {
/*return (
<FormCurrencyField
variant='ghost'
currency={currency}
language={language}
scale={2}
readOnly
className='text-right'
{...register(`items.${index}.subtotal_price`)}
/>
);*/
return null;
},
size: 150,
},
{
id: "discount" as const,
accessorKey: "discount",
header: () => <div className='text-right'>{t("form_fields.items.discount.label")}</div>,
cell: ({ row: { index } }) => (
<FormField
control={control}
name={`items.${index}.discount.amount`}
render={({ field }) => (
<FormItem>
<FormControl>
<Input
type='number'
step='0.01'
min='0'
max='100'
{...field}
onChange={(e) => field.onChange(Number(e.target.value) * 100)}
value={field.value / 100}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
),
size: 100,
},
{
id: "taxes" as const,
accessorKey: "taxes",
header: () => <div className='text-right'>{t("form_fields.items.taxes.label")}</div>,
cell: ({ row: { index } }) => (
<FormField
control={control}
name={`items.${index}.taxes.amount`}
render={({ field }) => (
<FormItem>
<FormControl>
<CustomerInvoiceTaxesMultiSelect
{...field}
//onChange={(e) => field.onChange(Number(e.target.value) * 100)}
//value={field.value / 100}
/>
</FormControl>
<FormMessage />
</FormItem>
)}
/>
),
size: 150,
},
{
id: "total_price" as const,
accessorKey: "total_price",
header: () => <div className='text-right'>{t("form_fields.items.total_price.label")}</div>,
cell: ({ row: { index } }) => (
<>
{formatCurrency(
watchedItems[index]?.total_price?.amount || 0,
2,
getValues("currency")
)}
</>
),
size: 150,
},
],
{
enableDragHandleColumn: true,
enableSelectionColumn: true,
enableActionsColumn: true,
rowActionFn: (props) => {
const { table, row } = props;
return [
{
label: t("common.duplicate_row"),
icon: <CopyIcon className='w-4 h-4 mr-2' />,
onClick: () => table.options.meta?.duplicateItems(row.index),
},
{
label: t("common.insert_row_above"),
icon: <ChevronUpIcon className='w-4 h-4 mr-2' />,
onClick: () => table.options.meta?.insertItem(row.index),
},
{
label: t("common.insert_row_below"),
icon: <ChevronDownIcon className='w-4 h-4 mr-2' />,
onClick: () => table.options.meta?.insertItem(row.index + 1),
},
{
label: "-",
},
{
label: t("common.remove_row"),
//shortcut: "⌘⌫",
icon: <Trash2Icon className='w-4 h-4 mr-2' />,
onClick: () => {
table.options.meta?.deleteItems(row.index);
},
},
];
},
}
);
const [isCollapsed, setIsCollapsed] = useState(false);
const defaultLayout = [265, 440, 655];
const navCollapsedSize = 4;
return (
<div className='relative'>
<CustomerInvoiceItemsSortableDataTable
actions={{
...fieldActions,
//pickCatalogArticle: () => setArticlePickerDialogOpen(true),
//pickBlock: () => setBlockPickerDialogOpen(true),
}}
columns={columns}
data={fields}
defaultValues={defaultValues}
/>
</div>
);
};