diff --git a/packages/webapp/src/components/Forms/BlueprintFormik.tsx b/packages/webapp/src/components/Forms/BlueprintFormik.tsx
index 09b14967d..93313abcf 100644
--- a/packages/webapp/src/components/Forms/BlueprintFormik.tsx
+++ b/packages/webapp/src/components/Forms/BlueprintFormik.tsx
@@ -10,7 +10,7 @@ import {
EditableText,
TextArea,
} from '@blueprintjs-formik/core';
-import { MultiSelect } from '@blueprintjs-formik/select';
+import { MultiSelect, SuggestField } from '@blueprintjs-formik/select';
import { DateInput } from '@blueprintjs-formik/datetime';
import { FSelect } from './Select';
@@ -24,6 +24,7 @@ export {
FSelect,
MultiSelect as FMultiSelect,
EditableText as FEditableText,
+ SuggestField as FSuggest,
TextArea as FTextArea,
DateInput as FDateInput,
};
diff --git a/packages/webapp/src/components/TaxRates/TaxRatesSuggestInputCell.tsx b/packages/webapp/src/components/TaxRates/TaxRatesSuggestInputCell.tsx
new file mode 100644
index 000000000..e6fed6bb4
--- /dev/null
+++ b/packages/webapp/src/components/TaxRates/TaxRatesSuggestInputCell.tsx
@@ -0,0 +1,41 @@
+// @ts-nocheck
+import React, { useCallback } from 'react';
+import { Suggest } from '@blueprintjs-formik/select';
+import { FormGroup } from '@blueprintjs/core';
+import { CellType } from '@/constants';
+
+export function TaxRatesSuggestInputCell({
+ column: { id, suggestProps, formGroupProps },
+ row: { index },
+ cell: { value: cellValue },
+ payload: { errors, updateData, taxRates },
+}) {
+ const error = errors?.[index]?.[id];
+
+ // Handle the item selected.
+ const handleItemSelected = useCallback(
+ (value, taxRate) => {
+ updateData(index, id, taxRate.id);
+ },
+ [updateData, index, id],
+ );
+
+ return (
+
+
+ selectedValue={cellValue}
+ items={taxRates}
+ valueAccessor={'id'}
+ labelAccessor={'code'}
+ textAccessor={'name'}
+ popoverProps={{ minimal: true, boundary: 'window' }}
+ inputProps={{ placeholder: '' }}
+ fill={true}
+ onItemChange={handleItemSelected}
+ {...suggestProps}
+ />
+
+ );
+}
+
+TaxRatesSuggestInputCell.cellType = CellType.Field;
diff --git a/packages/webapp/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailTableFooter.tsx b/packages/webapp/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailTableFooter.tsx
index 69f512145..c9a9fe704 100644
--- a/packages/webapp/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailTableFooter.tsx
+++ b/packages/webapp/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailTableFooter.tsx
@@ -23,22 +23,30 @@ export function InvoiceDetailTableFooter() {
}
- value={}
+ value={}
borderStyle={TotalLineBorderStyle.SingleDark}
/>
+ {invoice.taxes.map((taxRate) => (
+
+ ))}
}
- value={invoice.formatted_amount}
+ value={invoice.total_formatted}
borderStyle={TotalLineBorderStyle.DoubleDark}
textStyle={TotalLineTextStyle.Bold}
/>
}
- value={invoice.formatted_payment_amount}
+ value={invoice.payment_amount_formatted}
/>
}
- value={invoice.formatted_due_amount}
+ value={invoice.due_amount_formatted}
textStyle={TotalLineTextStyle.Bold}
/>
diff --git a/packages/webapp/src/containers/Entries/ItemEntriesTableProvider.tsx b/packages/webapp/src/containers/Entries/ItemEntriesTableProvider.tsx
new file mode 100644
index 000000000..9d9c88edd
--- /dev/null
+++ b/packages/webapp/src/containers/Entries/ItemEntriesTableProvider.tsx
@@ -0,0 +1,20 @@
+// @ts-nocheck
+import React, { createContext } from 'react';
+
+const ItemEntriesTableContext = createContext();
+
+function ItemEntriesTableProvider({ children, value }) {
+ const provider = {
+ ...value,
+ };
+ return (
+
+ {children}
+
+ );
+}
+
+const useItemEntriesTableContext = () =>
+ React.useContext(ItemEntriesTableContext);
+
+export { ItemEntriesTableProvider, useItemEntriesTableContext };
diff --git a/packages/webapp/src/containers/Entries/ItemsEntriesTable.tsx b/packages/webapp/src/containers/Entries/ItemsEntriesTable.tsx
index 6b51f8566..4a881cfec 100644
--- a/packages/webapp/src/containers/Entries/ItemsEntriesTable.tsx
+++ b/packages/webapp/src/containers/Entries/ItemsEntriesTable.tsx
@@ -1,103 +1,104 @@
// @ts-nocheck
-import React, { useEffect, useCallback } from 'react';
+import React, { useCallback } from 'react';
import classNames from 'classnames';
import { CLASSES } from '@/constants/classes';
import { DataTableEditable } from '@/components';
import { useEditableItemsEntriesColumns } from './components';
-import {
- saveInvoke,
- compose,
- updateMinEntriesLines,
- updateRemoveLineByIndex,
-} from '@/utils';
import {
useFetchItemRow,
composeRowsOnNewRow,
- composeRowsOnEditCell,
+ useComposeRowsOnEditTableCell,
+ useComposeRowsOnRemoveTableRow,
} from './utils';
+import {
+ ItemEntriesTableProvider,
+ useItemEntriesTableContext,
+} from './ItemEntriesTableProvider';
+import { useUncontrolled } from '@/hooks/useUncontrolled';
/**
* Items entries table.
*/
-function ItemsEntriesTable({
- // #ownProps
- items,
- entries,
- initialEntries,
- defaultEntry,
- errors,
- onUpdateData,
- currencyCode,
- itemType, // sellable or purchasable
- landedCost = false,
- minLinesNumber
-}) {
- const [rows, setRows] = React.useState(initialEntries);
+function ItemsEntriesTable(props) {
+ const { value, initialValue, onChange } = props;
- // Allows to observes `entries` to make table rows outside controlled.
- useEffect(() => {
- if (entries && entries !== rows) {
- setRows(entries);
- }
- }, [entries, rows]);
+ const [localValue, handleChange] = useUncontrolled({
+ value,
+ initialValue,
+ finalValue: [],
+ onChange,
+ });
+ return (
+
+
+
+ );
+}
+
+/**
+ * Items entries table logic.
+ * @returns {JSX.Element}
+ */
+function ItemEntriesTableRoot() {
+ const {
+ localValue,
+ defaultEntry,
+ handleChange,
+ items,
+ errors,
+ currencyCode,
+ landedCost,
+ taxRates,
+ } = useItemEntriesTableContext();
// Editiable items entries columns.
- const columns = useEditableItemsEntriesColumns({ landedCost });
+ const columns = useEditableItemsEntriesColumns();
+
+ const composeRowsOnEditCell = useComposeRowsOnEditTableCell();
+ const composeRowsOnDeleteRow = useComposeRowsOnRemoveTableRow();
// Handle the fetch item row details.
const { setItemRow, cellsLoading, isItemFetching } = useFetchItemRow({
landedCost,
- itemType,
+ itemType: null,
notifyNewRow: (newRow, rowIndex) => {
// Update the rate, description and quantity data of the row.
- const newRows = composeRowsOnNewRow(rowIndex, newRow, rows);
-
- setRows(newRows);
- onUpdateData(newRows);
+ const newRows = composeRowsOnNewRow(rowIndex, newRow, localValue);
+ handleChange(newRows);
},
});
-
// Handles the editor data update.
const handleUpdateData = useCallback(
(rowIndex, columnId, value) => {
if (columnId === 'item_id') {
setItemRow({ rowIndex, columnId, itemId: value });
}
- const composeEditCell = composeRowsOnEditCell(rowIndex, columnId);
- const newRows = composeEditCell(value, defaultEntry, rows);
-
- setRows(newRows);
- onUpdateData(newRows);
+ const newRows = composeRowsOnEditCell(rowIndex, columnId, value);
+ handleChange(newRows);
},
- [rows, defaultEntry, onUpdateData, setItemRow],
+ [localValue, defaultEntry, handleChange],
);
// Handle table rows removing by index.
const handleRemoveRow = (rowIndex) => {
- const newRows = compose(
- // Ensure minimum lines count.
- updateMinEntriesLines(minLinesNumber, defaultEntry),
- // Remove the line by the given index.
- updateRemoveLineByIndex(rowIndex),
- )(rows);
-
- setRows(newRows);
- saveInvoke(onUpdateData, newRows);
+ const newRows = composeRowsOnDeleteRow(rowIndex);
+ handleChange(newRows);
};
return (
{
removeRow(index);
};
-
const exampleMenu = (