Facturas de cliente
This commit is contained in:
parent
04e3b835a0
commit
18c37692ea
@ -3,13 +3,14 @@ import { Button, Checkbox, Table, TableBody, TableCell, TableFooter, TableHead,
|
|||||||
import { ArrowDown, ArrowUp, CopyIcon, Trash2 } from "lucide-react";
|
import { ArrowDown, ArrowUp, CopyIcon, Trash2 } from "lucide-react";
|
||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Controller, useFormContext } from "react-hook-form";
|
import { Controller, useFormContext } from "react-hook-form";
|
||||||
import { useCalculateItemAmounts, useItemsTableNavigation } from '../../../hooks';
|
import { useItemsTableNavigation } from '../../../hooks';
|
||||||
import { useTranslation } from '../../../i18n';
|
import { useTranslation } from '../../../i18n';
|
||||||
import { CustomerInvoiceItemFormData, defaultCustomerInvoiceItemFormData } from '../../../schemas';
|
import { CustomerInvoiceItemFormData, defaultCustomerInvoiceItemFormData } from '../../../schemas';
|
||||||
import { CustomerInvoiceTaxesMultiSelect } from '../../customer-invoice-taxes-multi-select';
|
import { CustomerInvoiceTaxesMultiSelect } from '../../customer-invoice-taxes-multi-select';
|
||||||
import { AmountDTOInputField } from './amount-dto-input-field';
|
import { AmountDTOInputField } from './amount-dto-input-field';
|
||||||
import { HoverCardTotalsSummary } from './hover-card-total-summary';
|
import { HoverCardTotalsSummary } from './hover-card-total-summary';
|
||||||
import { ItemsEditorToolbar } from './items-editor-toolbar';
|
import { ItemsEditorToolbar } from './items-editor-toolbar';
|
||||||
|
import { LastCellTabHook } from './last-cell-tab-hook';
|
||||||
import { PercentageDTOInputField } from './percentage-dto-input-field';
|
import { PercentageDTOInputField } from './percentage-dto-input-field';
|
||||||
import { QuantityDTOInputField } from './quantity-dto-input-field';
|
import { QuantityDTOInputField } from './quantity-dto-input-field';
|
||||||
|
|
||||||
@ -38,11 +39,6 @@ export const ItemsEditor = ({ value = [], onChange, readOnly = false }: ItemsEdi
|
|||||||
const selectedIdx = React.useMemo(() => [...selection].sort((a, b) => a - b), [selection]);
|
const selectedIdx = React.useMemo(() => [...selection].sort((a, b) => a - b), [selection]);
|
||||||
const resetSelection = () => setSelection(new Set());
|
const resetSelection = () => setSelection(new Set());
|
||||||
|
|
||||||
const calculateItemAmounts = useCalculateItemAmounts({
|
|
||||||
currencyCode: 'EUR',
|
|
||||||
locale: 'es',
|
|
||||||
taxCatalog
|
|
||||||
});
|
|
||||||
|
|
||||||
// Emitir cambios a quien consuma el componente
|
// Emitir cambios a quien consuma el componente
|
||||||
React.useEffect(() => {
|
React.useEffect(() => {
|
||||||
@ -298,37 +294,8 @@ export const ItemsEditor = ({ value = [], onChange, readOnly = false }: ItemsEdi
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
{/* Navegación por TAB: último campo de la fila */}
|
{/* Navegación por TAB: último campo de la fila */}
|
||||||
<LastCellTabHook linesLen={tableNav.fa.fields.length} onTabFromLast={tableNav.onTabFromLastCell} />
|
<LastCellTabHook itemsLength={tableNav.fa.fields.length} onTabFromLast={tableNav.onTabFromLastCell} />
|
||||||
</div >
|
</div >
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Navegación por TAB desde el último control de la fila
|
|
||||||
function LastCellTabHook({
|
|
||||||
linesLen,
|
|
||||||
onTabFromLast,
|
|
||||||
}: {
|
|
||||||
linesLen: number;
|
|
||||||
onTabFromLast: (row: number) => void;
|
|
||||||
}) {
|
|
||||||
React.useEffect(() => {
|
|
||||||
const handler = (e: KeyboardEvent) => {
|
|
||||||
if (e.key !== "Tab" || e.shiftKey) return;
|
|
||||||
const target = e.target as HTMLElement | null;
|
|
||||||
if (!target) return;
|
|
||||||
const tr = target.closest<HTMLTableRowElement>("tr[data-row-index]");
|
|
||||||
if (!tr) return;
|
|
||||||
// Asumimos el trigger de impuestos como último focusable de la fila
|
|
||||||
const isTaxTrigger = target.getAttribute("aria-label")?.toLowerCase().includes("tax");
|
|
||||||
if (!isTaxTrigger) return;
|
|
||||||
const rowIndex = Number(tr.dataset.rowIndex ?? -1);
|
|
||||||
if (rowIndex >= 0) {
|
|
||||||
e.preventDefault();
|
|
||||||
onTabFromLast(rowIndex);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
document.addEventListener("keydown", handler);
|
|
||||||
return () => document.removeEventListener("keydown", handler);
|
|
||||||
}, [linesLen, onTabFromLast]);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
import { useEffect } from 'react';
|
||||||
|
|
||||||
|
// Navegación por TAB desde el último control de la fila
|
||||||
|
export const LastCellTabHook = ({
|
||||||
|
itemsLength,
|
||||||
|
onTabFromLast,
|
||||||
|
}: {
|
||||||
|
itemsLength: number;
|
||||||
|
onTabFromLast: (row: number) => void;
|
||||||
|
}) => {
|
||||||
|
useEffect(() => {
|
||||||
|
const handler = (e: KeyboardEvent) => {
|
||||||
|
if (e.key !== "Tab" || e.shiftKey) return;
|
||||||
|
const target = e.target as HTMLElement | null;
|
||||||
|
if (!target) return;
|
||||||
|
const tr = target.closest<HTMLTableRowElement>("tr[data-row-index]");
|
||||||
|
if (!tr) return;
|
||||||
|
|
||||||
|
// Asumimos el trigger de impuestos como último focusable de la fila
|
||||||
|
const isTaxTrigger = target.getAttribute("aria-label")?.toLowerCase().includes("tax");
|
||||||
|
|
||||||
|
if (!isTaxTrigger) return;
|
||||||
|
|
||||||
|
const rowIndex = Number(tr.dataset.rowIndex ?? -1);
|
||||||
|
if (rowIndex >= 0) {
|
||||||
|
e.preventDefault();
|
||||||
|
onTabFromLast(rowIndex);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
document.addEventListener("keydown", handler);
|
||||||
|
return () => document.removeEventListener("keydown", handler);
|
||||||
|
}, [itemsLength, onTabFromLast]);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user