.
This commit is contained in:
parent
95882ee10d
commit
0b5f180b6f
@ -54,6 +54,7 @@
|
||||
"lucide-react": "^0.379.0",
|
||||
"react": "^18.2.0",
|
||||
"react-beautiful-dnd": "^13.1.1",
|
||||
"react-currency-input-field": "^3.8.0",
|
||||
"react-day-picker": "^8.10.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-hook-form": "^7.51.5",
|
||||
|
||||
@ -47,7 +47,6 @@ export const CatalogPickerDataTable = ({ onClick }: { onClick: (data: unknown) =
|
||||
className={cn("rounded-lg border p-3 transition-all hover:bg-accent w-full", "")}
|
||||
onClick={
|
||||
(event) => {
|
||||
console.log("hola");
|
||||
event.preventDefault();
|
||||
onClick && onClick(row.original);
|
||||
}
|
||||
|
||||
@ -3,12 +3,7 @@ import { TableRow } from "@/ui/table";
|
||||
import { DraggableSyntheticListeners } from "@dnd-kit/core";
|
||||
import { defaultAnimateLayoutChanges, useSortable } from "@dnd-kit/sortable";
|
||||
import { CSS } from "@dnd-kit/utilities";
|
||||
import {
|
||||
CSSProperties,
|
||||
PropsWithChildren,
|
||||
createContext,
|
||||
useMemo,
|
||||
} from "react";
|
||||
import { CSSProperties, PropsWithChildren, createContext, useMemo } from "react";
|
||||
import { SortableProps } from "./SortableDataTable";
|
||||
|
||||
interface Context {
|
||||
@ -30,10 +25,7 @@ function animateLayoutChanges(args) {
|
||||
return true;
|
||||
}
|
||||
|
||||
export function SortableTableRow({
|
||||
id,
|
||||
children,
|
||||
}: PropsWithChildren<SortableProps>) {
|
||||
export function SortableTableRow({ id, children }: PropsWithChildren<SortableProps>) {
|
||||
const {
|
||||
attributes,
|
||||
isDragging,
|
||||
@ -58,7 +50,7 @@ export function SortableTableRow({
|
||||
listeners,
|
||||
ref: setActivatorNodeRef,
|
||||
}),
|
||||
[attributes, listeners, setActivatorNodeRef],
|
||||
[attributes, listeners, setActivatorNodeRef]
|
||||
);
|
||||
|
||||
return (
|
||||
@ -66,10 +58,7 @@ export function SortableTableRow({
|
||||
<TableRow
|
||||
key={id}
|
||||
id={String(id)}
|
||||
className={cn(
|
||||
isDragging ? "opacity-40" : "opacity-100",
|
||||
"hover:bg-muted/30 m-0",
|
||||
)}
|
||||
className={cn(isDragging ? "opacity-40" : "opacity-100", "hover:bg-muted/30 m-0")}
|
||||
ref={setNodeRef}
|
||||
style={style}
|
||||
>
|
||||
|
||||
@ -1,21 +1,21 @@
|
||||
import {
|
||||
FormMoneyField,
|
||||
FormPercentageField,
|
||||
FormCurrencyField,
|
||||
FormQuantityField,
|
||||
FormTextAreaField,
|
||||
FormTextField,
|
||||
} from "@/components";
|
||||
import { DataTableProvider } from "@/lib/hooks";
|
||||
import { cn } from "@/lib/utils";
|
||||
import { ResizableHandle, ResizablePanel, ResizablePanelGroup } from "@/ui";
|
||||
import { Quantity } from "@shared/contexts";
|
||||
import { CurrencyData, Quantity } from "@shared/contexts";
|
||||
import { useCallback, useState } from "react";
|
||||
import { useFieldArray, useFormContext } from "react-hook-form";
|
||||
import { useDetailColumns } from "../../hooks";
|
||||
import { CatalogPickerDataTable } from "../CatalogPickerDataTable";
|
||||
import { SortableDataTable } from "../SortableDataTable";
|
||||
|
||||
export const QuoteDetailsCardEditor = () => {
|
||||
const { control, register, watch, getValues, setValue } = useFormContext();
|
||||
export const QuoteDetailsCardEditor = ({ currency }: { currency: CurrencyData }) => {
|
||||
const { control, register } = useFormContext();
|
||||
|
||||
const { fields, ...fieldActions } = useFieldArray({
|
||||
control,
|
||||
@ -59,7 +59,14 @@ export const QuoteDetailsCardEditor = () => {
|
||||
header: "unit_price",
|
||||
size: 10,
|
||||
cell: ({ row: { index }, column: { id } }) => {
|
||||
return <FormMoneyField {...register(`items.${index}.unit_price`)} />;
|
||||
return (
|
||||
<FormCurrencyField
|
||||
variant='outline'
|
||||
currency={currency}
|
||||
precision={4}
|
||||
{...register(`items.${index}.unit_price`)}
|
||||
/>
|
||||
);
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -68,7 +75,7 @@ export const QuoteDetailsCardEditor = () => {
|
||||
header: "subtotal_price",
|
||||
size: 10,
|
||||
cell: ({ row: { index }, column: { id } }) => {
|
||||
return <FormMoneyField {...register(`items.${index}.subtotal_price`)} />;
|
||||
return <FormTextField {...register(`items.${index}.subtotal_price`)} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -77,7 +84,7 @@ export const QuoteDetailsCardEditor = () => {
|
||||
header: "discount",
|
||||
size: 5,
|
||||
cell: ({ row: { index }, column: { id } }) => {
|
||||
return <FormPercentageField {...register(`items.${index}.discount`)} />;
|
||||
return <FormTextField {...register(`items.${index}.discount`)} />;
|
||||
},
|
||||
},
|
||||
{
|
||||
@ -86,7 +93,7 @@ export const QuoteDetailsCardEditor = () => {
|
||||
header: "total_price",
|
||||
size: 10,
|
||||
cell: ({ row: { index }, column: { id } }) => {
|
||||
return <FormMoneyField {...register(`items.${index}.total_price`)} />;
|
||||
return <FormTextField {...register(`items.${index}.total_price`)} />;
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
@ -1,8 +1,8 @@
|
||||
import { ErrorOverlay, FormMoneyField, LoadingOverlay, SubmitButton } from "@/components";
|
||||
import { ErrorOverlay, FormTextField, LoadingOverlay, SubmitButton } from "@/components";
|
||||
import { calculateItemTotals } from "@/lib/calc";
|
||||
import { useUrlId } from "@/lib/hooks/useUrlId";
|
||||
import { Badge, Button, Form, Tabs, TabsContent, TabsList, TabsTrigger } from "@/ui";
|
||||
import { IUpdateQuote_Request_DTO, MoneyValue } from "@shared/contexts";
|
||||
import { CurrencyData, IUpdateQuote_Request_DTO, MoneyValue } from "@shared/contexts";
|
||||
import { t } from "i18next";
|
||||
import { ChevronLeftIcon } from "lucide-react";
|
||||
import { useEffect, useState } from "react";
|
||||
@ -15,40 +15,28 @@ type EndsWith<T, b extends string> = T extends `${infer f}${b}` ? T : never;
|
||||
const endsWith = <T extends string, b extends string>(str: T, prefix: b): str is EndsWith<T, b> =>
|
||||
str.endsWith(prefix);
|
||||
|
||||
interface QuoteDataForm extends IUpdateQuote_Request_DTO {
|
||||
/*status: string;
|
||||
date: string;
|
||||
reference: string;
|
||||
customer_information: string;
|
||||
lang_code: string;
|
||||
currency_code: string;
|
||||
payment_method: string;
|
||||
notes: string;
|
||||
validity: string;
|
||||
discount: IPercentage;
|
||||
|
||||
subtotal: IMoney;
|
||||
|
||||
items: {
|
||||
quantity: IQuantity;
|
||||
description: string;
|
||||
unit_price: IMoney;
|
||||
price: IMoney;
|
||||
discount: IPercentage;
|
||||
total: IMoney;
|
||||
}[];*/
|
||||
}
|
||||
interface QuoteDataForm extends IUpdateQuote_Request_DTO {}
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
export const QuoteEdit = () => {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const quoteId = useUrlId();
|
||||
const [quoteCurrency, setQuoteCurrency] = useState<CurrencyData>(
|
||||
CurrencyData.createDefaultCode().object
|
||||
);
|
||||
|
||||
//const { data: userIdentity } = useGetIdentity();
|
||||
/*const { data: userIdentity } = useGetIdentity();
|
||||
console.log(userIdentity);
|
||||
|
||||
const { flag } = useLocalization({
|
||||
locale: userIdentity?.language ?? "es-es",
|
||||
});
|
||||
|
||||
console.log(flag);*/
|
||||
|
||||
const { useOne, useUpdate } = useQuotes();
|
||||
|
||||
const { data, status } = useOne(quoteId);
|
||||
const { data, status, error: queryError } = useOne(quoteId);
|
||||
|
||||
const { mutate } = useUpdate(String(quoteId));
|
||||
|
||||
const form = useForm<QuoteDataForm>({
|
||||
@ -63,7 +51,11 @@ export const QuoteEdit = () => {
|
||||
payment_method: "",
|
||||
notes: "",
|
||||
validity: "",
|
||||
subtotal_price: "",
|
||||
subtotal_price: {
|
||||
amount: "",
|
||||
precision: "",
|
||||
currency_code: "",
|
||||
},
|
||||
items: [],
|
||||
},
|
||||
});
|
||||
@ -72,32 +64,32 @@ export const QuoteEdit = () => {
|
||||
const { isSubmitting } = formState;
|
||||
|
||||
const onSubmit: SubmitHandler<QuoteDataForm> = async (data) => {
|
||||
console.debug(JSON.stringify(data));
|
||||
|
||||
try {
|
||||
setLoading(true);
|
||||
// Transformación del form -> typo de request
|
||||
mutate(data, {
|
||||
onError: (error) => {
|
||||
alert(error);
|
||||
},
|
||||
//onSettled: () => {},
|
||||
onSuccess: () => {
|
||||
alert("guardado");
|
||||
},
|
||||
});
|
||||
} finally {
|
||||
setLoading(false);
|
||||
}
|
||||
// Transformación del form -> typo de request
|
||||
mutate(data, {
|
||||
onError: (error) => {
|
||||
alert(error.message);
|
||||
},
|
||||
//onSettled: () => {},
|
||||
onSuccess: () => {
|
||||
alert("guardado");
|
||||
},
|
||||
});
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
const { unsubscribe } = watch((_, { name, type }) => {
|
||||
const value = getValues();
|
||||
|
||||
console.debug({ name, type });
|
||||
//console.debug({ name, type });
|
||||
|
||||
if (name) {
|
||||
if (name === "currency_code") {
|
||||
setQuoteCurrency(
|
||||
CurrencyData.createFromCode(value.lang_code ?? CurrencyData.DEFAULT_CURRENCY_CODE)
|
||||
.object
|
||||
);
|
||||
}
|
||||
|
||||
if (name === "items") {
|
||||
const { items } = value;
|
||||
let quoteSubtotal = MoneyValue.create().object;
|
||||
@ -111,18 +103,17 @@ export const QuoteEdit = () => {
|
||||
setValue(`items.${index}.total_price`, itemTotals.totalPrice.toObject());
|
||||
});
|
||||
|
||||
console.log(quoteSubtotal.toFormat());
|
||||
|
||||
// Recálculo completo
|
||||
setValue("subtotal", quoteSubtotal.toObject());
|
||||
setValue("subtotal_price", quoteSubtotal.toObject());
|
||||
}
|
||||
|
||||
if (
|
||||
endsWith(name, "quantity") ||
|
||||
endsWith(name, "retail_price") ||
|
||||
endsWith(name, "unit_price") ||
|
||||
endsWith(name, "discount")
|
||||
) {
|
||||
const { items } = value;
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
const [, indexString, fieldName] = String(name).split(".");
|
||||
const index = parseInt(indexString);
|
||||
|
||||
@ -150,6 +141,8 @@ export const QuoteEdit = () => {
|
||||
return <LoadingOverlay />;
|
||||
}
|
||||
|
||||
console.log(quoteCurrency);
|
||||
|
||||
return (
|
||||
<Form {...form}>
|
||||
<form onSubmit={form.handleSubmit(onSubmit)}>
|
||||
@ -175,7 +168,7 @@ export const QuoteEdit = () => {
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<FormMoneyField
|
||||
<FormTextField
|
||||
label={"subtotal_price"}
|
||||
disabled={form.formState.disabled}
|
||||
{...form.register("subtotal_price")}
|
||||
@ -191,7 +184,7 @@ export const QuoteEdit = () => {
|
||||
<QuoteGeneralCardEditor />
|
||||
</TabsContent>
|
||||
<TabsContent value='items'>
|
||||
<QuoteDetailsCardEditor />
|
||||
<QuoteDetailsCardEditor currency={quoteCurrency} />
|
||||
</TabsContent>
|
||||
|
||||
<TabsContent value='history'></TabsContent>
|
||||
|
||||
@ -5,7 +5,7 @@ import {
|
||||
} from "@/components";
|
||||
import { Checkbox } from "@/ui";
|
||||
import { ColumnDef, Row, Table } from "@tanstack/react-table";
|
||||
import { MoreHorizontalIcon, UnfoldVertical } from "lucide-react";
|
||||
import { MoreHorizontalIcon } from "lucide-react";
|
||||
|
||||
import { useMemo } from "react";
|
||||
|
||||
@ -41,7 +41,7 @@ export function useDetailColumns<TData, TValue>(
|
||||
if (enableSelectionColumn) {
|
||||
columns.unshift({
|
||||
id: "select",
|
||||
header: ({ table }) => (
|
||||
/*header: ({ table }) => (
|
||||
<Checkbox
|
||||
id='select-all'
|
||||
checked={
|
||||
@ -50,9 +50,10 @@ export function useDetailColumns<TData, TValue>(
|
||||
}
|
||||
onCheckedChange={(value) => table.toggleAllPageRowsSelected(!!value)}
|
||||
aria-label='Seleccionar todo'
|
||||
className='translate-y-[2px]'
|
||||
className='translate-y-[0px]'
|
||||
/>
|
||||
),
|
||||
),*/
|
||||
header: () => null,
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
cell: ({ row, table }: { row: Row<TData>; table: Table<TData> }) => (
|
||||
<Checkbox
|
||||
@ -61,25 +62,7 @@ export function useDetailColumns<TData, TValue>(
|
||||
disabled={!row.getCanSelect()}
|
||||
onCheckedChange={row.getToggleSelectedHandler()}
|
||||
aria-label='Seleccionar fila'
|
||||
className='translate-y-[2px]'
|
||||
/*onClick={(e) => {
|
||||
if (e.shiftKey) {
|
||||
const { rows, rowsById } = table.getRowModel();
|
||||
const rowsToToggle = getSelectedRowRange(
|
||||
rows,
|
||||
Number(row.id),
|
||||
Number(lastSelectedId),
|
||||
);
|
||||
const isCellSelected = rowsById[row.id].getIsSelected();
|
||||
rowsToToggle.forEach((_row) =>
|
||||
_row.toggleSelected(!isCellSelected),
|
||||
);
|
||||
} else {
|
||||
row.toggleSelected();
|
||||
}
|
||||
|
||||
lastSelectedId = row.id;
|
||||
}}*/
|
||||
className='mt-2'
|
||||
/>
|
||||
),
|
||||
enableSorting: false,
|
||||
@ -91,10 +74,11 @@ export function useDetailColumns<TData, TValue>(
|
||||
if (enableDragHandleColumn) {
|
||||
columns.unshift({
|
||||
id: "row_drag_handle",
|
||||
header: () => (
|
||||
/*header: () => (
|
||||
<UnfoldVertical aria-label='Mover fila' className='items-center justify-center w-4 h-4' />
|
||||
),
|
||||
cell: ({ row }: { row: Row<TData> }) => <DataTableRowDragHandleCell rowId={row.id} />,
|
||||
),*/
|
||||
header: () => null,
|
||||
cell: (info) => <DataTableRowDragHandleCell rowId={info.row.id} />,
|
||||
size: 16,
|
||||
enableSorting: false,
|
||||
enableHiding: false,
|
||||
|
||||
@ -3,7 +3,15 @@ import { Button } from "@/ui";
|
||||
import { useSortable } from "@dnd-kit/sortable";
|
||||
import { GripVerticalIcon } from "lucide-react";
|
||||
|
||||
export const DataTableRowDragHandleCell = ({ rowId }: { rowId: string }) => {
|
||||
export interface DataTableRowDragHandleCellProps {
|
||||
rowId: string;
|
||||
className?: string;
|
||||
}
|
||||
|
||||
export const DataTableRowDragHandleCell = ({
|
||||
rowId,
|
||||
className,
|
||||
}: DataTableRowDragHandleCellProps) => {
|
||||
const { attributes, listeners, isDragging } = useSortable({
|
||||
id: rowId,
|
||||
});
|
||||
@ -14,17 +22,18 @@ export const DataTableRowDragHandleCell = ({ rowId }: { rowId: string }) => {
|
||||
event.preventDefault();
|
||||
return;
|
||||
}}
|
||||
size="icon"
|
||||
variant="link"
|
||||
size='icon'
|
||||
variant='link'
|
||||
className={cn(
|
||||
isDragging ? "cursor-grabbing" : "cursor-grab",
|
||||
"w-4 h-4 translate-y-[2px]"
|
||||
"w-4 h-4 mt-2 text-ring hover:text-muted-foreground",
|
||||
className
|
||||
)}
|
||||
{...attributes}
|
||||
{...listeners}
|
||||
>
|
||||
<GripVerticalIcon className="w-4 h-4" />
|
||||
<span className="sr-only">Mover fila</span>
|
||||
<GripVerticalIcon className='w-4 h-4' />
|
||||
<span className='sr-only'>Mover fila</span>
|
||||
</Button>
|
||||
);
|
||||
};
|
||||
|
||||
122
client/src/components/Forms/FormCurrencyField.tsx
Normal file
122
client/src/components/Forms/FormCurrencyField.tsx
Normal file
@ -0,0 +1,122 @@
|
||||
import { cn } from "@/lib/utils";
|
||||
import { FormControl, FormDescription, FormField, FormItem, InputProps } from "@/ui";
|
||||
import { CurrencyData, MoneyValue } from "@shared/contexts";
|
||||
import { cva, type VariantProps } from "class-variance-authority";
|
||||
import * as React from "react";
|
||||
import CurrencyInput from "react-currency-input-field";
|
||||
import { FieldPath, FieldValues, UseControllerProps, useFormContext } from "react-hook-form";
|
||||
import { FormErrorMessage } from "./FormErrorMessage";
|
||||
import { FormLabel, FormLabelProps } from "./FormLabel";
|
||||
import { FormInputProps, FormInputWithIconProps } from "./FormProps";
|
||||
|
||||
export const formCurrencyFieldVariants = cva(
|
||||
"flex h-10 w-full rounded-md bg-background px-3 py-2 text-sm placeholder:text-muted-foreground focus-visible:outline-none disabled:cursor-not-allowed disabled:opacity-50",
|
||||
{
|
||||
variants: {
|
||||
variant: {
|
||||
default:
|
||||
"border border-input ring-offset-background focus-visible:ring-2 focus-visible:ring-ring focus-visible:ring-offset-2 ",
|
||||
outline:
|
||||
"ring-offset-background focus-visible:ring-1 focus-visible:ring-ring focus-visible:ring-offset-2 ",
|
||||
},
|
||||
},
|
||||
defaultVariants: {
|
||||
variant: "default",
|
||||
},
|
||||
}
|
||||
);
|
||||
|
||||
export type FormCurrencyFieldProps<
|
||||
TFieldValues extends FieldValues = FieldValues,
|
||||
TName extends FieldPath<TFieldValues> = FieldPath<TFieldValues>
|
||||
> = {
|
||||
button?: (props?: React.PropsWithChildren) => React.ReactNode;
|
||||
} & InputProps &
|
||||
FormInputProps &
|
||||
Partial<FormLabelProps> &
|
||||
FormInputWithIconProps &
|
||||
UseControllerProps<TFieldValues, TName> &
|
||||
VariantProps<typeof formCurrencyFieldVariants> & {
|
||||
currency: CurrencyData;
|
||||
precision: number;
|
||||
};
|
||||
|
||||
export const FormCurrencyField = React.forwardRef<HTMLInputElement, FormCurrencyFieldProps>(
|
||||
(props, ref) => {
|
||||
const {
|
||||
name,
|
||||
label,
|
||||
hint,
|
||||
description,
|
||||
className,
|
||||
disabled,
|
||||
defaultValue,
|
||||
rules,
|
||||
precision,
|
||||
currency,
|
||||
variant,
|
||||
} = props;
|
||||
|
||||
const { control } = useFormContext();
|
||||
|
||||
const transformToInput = (value: any) => {
|
||||
if (typeof value !== "object") {
|
||||
return value;
|
||||
}
|
||||
|
||||
const moneyOrError = MoneyValue.create(value);
|
||||
if (moneyOrError.isFailure) {
|
||||
throw moneyOrError.error;
|
||||
}
|
||||
|
||||
return moneyOrError.object
|
||||
.convertPrecision(precision ?? value.precision)
|
||||
.toUnit()
|
||||
.toString();
|
||||
};
|
||||
|
||||
return (
|
||||
<FormField
|
||||
defaultValue={defaultValue}
|
||||
control={control}
|
||||
name={name}
|
||||
disabled={disabled}
|
||||
rules={rules}
|
||||
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
||||
render={({ field, fieldState, formState }) => {
|
||||
return (
|
||||
<FormItem ref={ref} className={cn(className, "space-y-3")}>
|
||||
{label && <FormLabel label={label} hint={hint} required={rules?.required ?? false} />}
|
||||
<FormControl>
|
||||
<CurrencyInput
|
||||
name={field.name}
|
||||
//ref={field.ref} <-- no activar que hace cosas raras
|
||||
onBlur={field.onBlur}
|
||||
disabled={field.disabled}
|
||||
className={cn(formCurrencyFieldVariants({ variant, className }))}
|
||||
suffix={` ${currency?.symbol}`}
|
||||
groupSeparator='.'
|
||||
decimalSeparator=','
|
||||
//placeholder={`0 ${fieldCurrenty.value?.symbol}`}
|
||||
|
||||
//fixedDecimalLength={precision} <- no activar para que sea más cómodo escribir las cantidades
|
||||
decimalsLimit={precision}
|
||||
decimalScale={precision}
|
||||
value={transformToInput(field.value)}
|
||||
onValueChange={(value) => {
|
||||
// "value" ya viene con los "0" de la precisión
|
||||
field.onChange(value ?? "");
|
||||
}}
|
||||
/>
|
||||
</FormControl>
|
||||
{description && <FormDescription>{description}</FormDescription>}
|
||||
<FormErrorMessage />
|
||||
</FormItem>
|
||||
);
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
||||
);
|
||||
|
||||
FormCurrencyField.displayName = "FormCurrencyField";
|
||||
@ -36,6 +36,8 @@ export const FormTextField = React.forwardRef<
|
||||
trailIcon,
|
||||
button,
|
||||
|
||||
defaultValue,
|
||||
|
||||
type,
|
||||
} = props;
|
||||
|
||||
@ -43,6 +45,7 @@ export const FormTextField = React.forwardRef<
|
||||
|
||||
return (
|
||||
<FormField
|
||||
defaultValue={defaultValue}
|
||||
control={control}
|
||||
name={name}
|
||||
rules={{ required }}
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
export * from "./FormCurrencyField";
|
||||
export * from "./FormDatePickerField";
|
||||
export * from "./FormErrorMessage";
|
||||
export * from "./FormGroup";
|
||||
|
||||
@ -28,7 +28,6 @@ export const AuthProvider = ({
|
||||
};
|
||||
|
||||
const handleCheck = async () => {
|
||||
console.trace("check");
|
||||
try {
|
||||
return Promise.resolve(authActions.check?.());
|
||||
} catch (error) {
|
||||
|
||||
@ -187,9 +187,9 @@ export function useDataTable<TData, TValue>({
|
||||
getFacetedRowModel: getFacetedRowModel(),
|
||||
getFacetedUniqueValues: getFacetedUniqueValues(),
|
||||
|
||||
debugTable: true,
|
||||
debugHeaders: true,
|
||||
debugColumns: true,
|
||||
debugTable: false,
|
||||
debugHeaders: false,
|
||||
debugColumns: false,
|
||||
});
|
||||
|
||||
return { table };
|
||||
|
||||
@ -19,9 +19,9 @@ export interface ICreateQuote_Request_DTO {
|
||||
notes: string;
|
||||
validity: string;
|
||||
|
||||
subtotal: IMoney_Response_DTO;
|
||||
subtotal_price: IMoney_Response_DTO;
|
||||
discount: IPercentage_Response_DTO;
|
||||
total: IMoney_Response_DTO;
|
||||
total_price: IMoney_Response_DTO;
|
||||
|
||||
items: ICreateQuoteItem_Request_DTO[];
|
||||
|
||||
|
||||
@ -1,8 +1,6 @@
|
||||
import Joi from "joi";
|
||||
import {
|
||||
IMoney_Request_DTO,
|
||||
IMoney_Response_DTO,
|
||||
IPercentage_Request_DTO,
|
||||
IPercentage_Response_DTO,
|
||||
IQuantity_Response_DTO,
|
||||
Result,
|
||||
@ -20,9 +18,13 @@ export interface IUpdateQuote_Request_DTO {
|
||||
notes: string;
|
||||
validity: string;
|
||||
|
||||
subtotal: IMoney_Request_DTO;
|
||||
discount: IPercentage_Request_DTO;
|
||||
subtotal_price: IMoney_Response_DTO;
|
||||
discount: IPercentage_Response_DTO;
|
||||
total_price: IMoney_Response_DTO;
|
||||
|
||||
items: IUpdateQuoteItem_Request_DTO[];
|
||||
|
||||
dealer_id: string;
|
||||
}
|
||||
|
||||
export interface IUpdateQuoteItem_Request_DTO {
|
||||
|
||||
Loading…
Reference in New Issue
Block a user