From 2356921f27e3dd494c9987a2c0fb87e7feee8bc6 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Mon, 18 Sep 2023 01:35:53 +0200 Subject: [PATCH] feat(webapp): wip tax rate form dialog --- .../TaxRates/alerts/TaxRateDeleteAlert.tsx | 8 +- .../containers/TaxRatesLandingTable.tsx | 50 +++++++- .../TaxRates/containers/_components.tsx | 17 ++- .../containers/TaxRates/containers/_utils.tsx | 18 ++- .../TaxRateFormDialog/TaxRateForm.schema.ts | 7 +- .../TaxRateFormDialog/TaxRateFormDialog.tsx | 7 +- .../TaxRateFormDialogBoot.tsx | 49 ++++++-- .../TaxRateFormDialogContent.tsx | 12 +- .../TaxRateFormDialogForm.tsx | 48 ++----- .../TaxRateFormDialogFormContent.tsx | 117 ++++++++++++++---- .../TaxRateFormDialogFormFooter.tsx | 1 + .../dialogs/TaxRateFormDialog/utils.ts | 57 ++++++++- .../TaxRateDetailsContentDetails.tsx | 24 +++- packages/webapp/src/hooks/query/taxRates.ts | 52 ++++++-- 14 files changed, 348 insertions(+), 119 deletions(-) diff --git a/packages/webapp/src/containers/TaxRates/alerts/TaxRateDeleteAlert.tsx b/packages/webapp/src/containers/TaxRates/alerts/TaxRateDeleteAlert.tsx index 6b66e250d..d6574cea2 100644 --- a/packages/webapp/src/containers/TaxRates/alerts/TaxRateDeleteAlert.tsx +++ b/packages/webapp/src/containers/TaxRates/alerts/TaxRateDeleteAlert.tsx @@ -1,12 +1,7 @@ // @ts-nocheck import React from 'react'; -import intl from 'react-intl-universal'; import { Intent, Alert } from '@blueprintjs/core'; -import { - AppToaster, - FormattedMessage as T, - FormattedHTMLMessage, -} from '@/components'; +import { AppToaster, FormattedMessage as T } from '@/components'; import { useDeleteTaxRate } from '@/hooks/query/taxRates'; @@ -40,7 +35,6 @@ function TaxRateDeleteAlert({ const handleCancelItemDelete = () => { closeAlert(name); }; - // Handle confirm delete item. const handleConfirmDeleteItem = () => { deleteTaxRate(taxRateId) diff --git a/packages/webapp/src/containers/TaxRates/containers/TaxRatesLandingTable.tsx b/packages/webapp/src/containers/TaxRates/containers/TaxRatesLandingTable.tsx index c20ad9bc7..6af00de39 100644 --- a/packages/webapp/src/containers/TaxRates/containers/TaxRatesLandingTable.tsx +++ b/packages/webapp/src/containers/TaxRates/containers/TaxRatesLandingTable.tsx @@ -1,11 +1,12 @@ // @ts-nocheck -import React, { useCallback } from 'react'; -import { useHistory } from 'react-router-dom'; +import React from 'react'; +import { Intent } from '@blueprintjs/core'; import { DataTable, DashboardContentTable, TableSkeletonHeader, TableSkeletonRows, + AppToaster, } from '@/components'; import withAlertsActions from '@/containers/Alert/withAlertActions'; @@ -14,10 +15,6 @@ import withDialogActions from '@/containers/Dialog/withDialogActions'; import withDashboardActions from '@/containers/Dashboard/withDashboardActions'; import withSettings from '@/containers/Settings/withSettings'; -// import { useMemorizedColumnsWidths } from '@/hooks'; -// import { ActionsMenu } from './components'; -// import { useInvoicesListContext } from './InvoicesListProvider'; - import { useTaxRatesTableColumns } from './_utils'; import { useTaxRatesLandingContext } from './TaxRatesLandingProvider'; import { TaxRatesLandingEmptyState } from './TaxRatesLandingEmptyState'; @@ -26,6 +23,10 @@ import { TaxRatesTableActionsMenu } from './_components'; import { compose } from '@/utils'; import { DRAWERS } from '@/constants/drawers'; import { DialogsName } from '@/constants/dialogs'; +import { + useActivateTaxRate, + useInactivateTaxRate, +} from '@/hooks/query/taxRates'; /** * Invoices datatable. @@ -47,6 +48,9 @@ function TaxRatesDataTable({ // Invoices table columns. const columns = useTaxRatesTableColumns(); + const { mutateAsync: activateTaxRateMutate } = useActivateTaxRate(); + const { mutateAsync: inactivateTaxRateMutate } = useInactivateTaxRate(); + // Handle delete tax rate. const handleDeleteTaxRate = ({ id }) => { openAlert('tax-rate-delete', { taxRateId: id }); @@ -63,6 +67,38 @@ function TaxRatesDataTable({ const handleCellClick = (cell, event) => { openDrawer(DRAWERS.TAX_RATE_DETAILS, { taxRateId: cell.row.original.id }); }; + // Handles activating the given tax rate. + const handleActivateTaxRate = (taxRate) => { + activateTaxRateMutate(taxRate.id) + .then(() => { + AppToaster.show({ + message: 'The tax rate has been activated successfully.', + intent: Intent.SUCCESS, + }); + }) + .catch(() => { + AppToaster.show({ + message: 'Something went wrong.', + intent: Intent.DANGER, + }); + }); + }; + // Handles inactivating the given tax rate. + const handleInactivateTaxRate = (taxRate) => { + inactivateTaxRateMutate(taxRate.id) + .then(() => { + AppToaster.show({ + message: 'The tax rate has been inactivated successfully.', + intent: Intent.SUCCESS, + }); + }) + .catch(() => { + AppToaster.show({ + message: 'Something went wrong.', + intent: Intent.DANGER, + }); + }); + }; // Display invoice empty status instead of the table. if (isEmptyStatus) { return ; @@ -93,6 +129,8 @@ function TaxRatesDataTable({ onViewDetails: handleViewDetails, onDelete: handleDeleteTaxRate, onEdit: handleEditTaxRate, + onActivate: handleActivateTaxRate, + onInactivate: handleInactivateTaxRate, }} /> diff --git a/packages/webapp/src/containers/TaxRates/containers/_components.tsx b/packages/webapp/src/containers/TaxRates/containers/_components.tsx index 5c3e50a34..0442c5047 100644 --- a/packages/webapp/src/containers/TaxRates/containers/_components.tsx +++ b/packages/webapp/src/containers/TaxRates/containers/_components.tsx @@ -10,7 +10,7 @@ import { Intent, Menu, MenuDivider, MenuItem } from '@blueprintjs/core'; * @returns {JSX.Element} */ export function TaxRatesTableActionsMenu({ - payload: { onEdit, onDelete, onViewDetails }, + payload: { onEdit, onDelete, onViewDetails, onActivate, onInactivate }, row: { original }, }) { return ( @@ -28,6 +28,21 @@ export function TaxRatesTableActionsMenu({ onClick={safeCallback(onEdit, original)} /> + + {!original.active && ( + } + text={'Activate Tax Rate'} + onClick={safeCallback(onActivate, original)} + /> + )} + {original.active && ( + } + text={'Inactivate Tax Rate'} + onClick={safeCallback(onInactivate, original)} + /> + )} { return ( @@ -13,19 +12,26 @@ const codeAccessor = (taxRate) => { }; const statusAccessor = (taxRate) => { - return ( + return taxRate.active ? ( Active + ) : ( + + Inactive + ); }; +/** + * Retrieves the tax rates table columns. + */ export const useTaxRatesTableColumns = () => { return [ { Header: 'Name', accessor: 'name', - width: 40, + width: 50, }, { Header: 'Code', @@ -40,8 +46,8 @@ export const useTaxRatesTableColumns = () => { }, { Header: 'Description', - accessor: () => Specital tax for certain goods and services., - width: 120, + accessor: 'description', + width: 110, }, { Header: 'Status', diff --git a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateForm.schema.ts b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateForm.schema.ts index 929197460..020346ced 100644 --- a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateForm.schema.ts +++ b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateForm.schema.ts @@ -7,9 +7,14 @@ const getSchema = () => code: Yup.string().required().label('Code'), active: Yup.boolean().optional().label('Active'), describtion: Yup.string().optional().label('Description'), - rate: Yup.number().required().label('Rate'), + rate: Yup.number() + .min(0.01, 'Enter a rate percentage of at least 0.01%') + .max(100, 'Enter a rate percentage of at most 100%') + .required() + .label('Rate'), is_compound: Yup.boolean().optional().label('Is Compound'), is_non_recoverable: Yup.boolean().optional().label('Is Non Recoverable'), + confirm_edit: Yup.boolean().optional(), }); export const CreateTaxRateFormSchema = getSchema; diff --git a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialog.tsx b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialog.tsx index 4a48c4f16..328920567 100644 --- a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialog.tsx +++ b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialog.tsx @@ -24,13 +24,16 @@ function TaxRateFormDialog({ return ( - + ); diff --git a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogBoot.tsx b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogBoot.tsx index 5fc9dbbfe..6c3981016 100644 --- a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogBoot.tsx +++ b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogBoot.tsx @@ -1,28 +1,51 @@ // @ts-nocheck -import React, { useState } from 'react'; +import React from 'react'; import { DialogContent } from '@/components'; -import { useTaxRates } from '@/hooks/query/taxRates'; +import { useTaxRate, useTaxRates } from '@/hooks/query/taxRates'; +import { DialogsName } from '@/constants/dialogs'; const TaxRateFormDialogContext = React.createContext(); +interface TaxRateFormDialogBootProps { + taxRateId: number; + children?: JSX.Element; +} + +interface TaxRateFormDialogBootContext { + taxRateId: number; + taxRate: any; + isTaxRateLoading: boolean; + isTaxRateSuccess: boolean; + isNewMode: boolean; +} + /** * Money in dialog provider. */ -function TaxRateFormDialogBoot({ ...props }) { +function TaxRateFormDialogBoot({ + taxRateId, + ...props +}: TaxRateFormDialogBootProps) { const { - data: taxRates, - isLoading: isTaxRatesLoading, - isSuccess: isTaxRatesSuccess, - } = useTaxRates({}); + data: taxRate, + isLoading: isTaxRateLoading, + isSuccess: isTaxRateSuccess, + } = useTaxRate(taxRateId, { + enabled: !!taxRateId, + }); + + const isNewMode = !taxRateId; // Provider data. const provider = { - taxRates, - isTaxRatesLoading, - isTaxRatesSuccess, + taxRateId, + taxRate, + isTaxRateLoading, + isTaxRateSuccess, + isNewMode, + dialogName: DialogsName.TaxRateForm, }; - - const isLoading = isTaxRatesLoading; + const isLoading = isTaxRateLoading; return ( @@ -32,6 +55,6 @@ function TaxRateFormDialogBoot({ ...props }) { } const useTaxRateFormDialogContext = () => - React.useContext(TaxRateFormDialogContext); + React.useContext(TaxRateFormDialogContext); export { TaxRateFormDialogBoot, useTaxRateFormDialogContext }; diff --git a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogContent.tsx b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogContent.tsx index ecfd37a4f..ecda9994c 100644 --- a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogContent.tsx +++ b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogContent.tsx @@ -3,12 +3,20 @@ import React from 'react'; import TaxRateFormDialogForm from './TaxRateFormDialogForm'; import { TaxRateFormDialogBoot } from './TaxRateFormDialogBoot'; +interface TaxRateFormDialogContentProps { + dialogName: string; + taxRateId: number; +} + /** * Account dialog content. */ -export default function TaxRateFormDialogContent({ dialogName, payload }) { +export default function TaxRateFormDialogContent({ + dialogName, + taxRateId, +}: TaxRateFormDialogContentProps) { return ( - + ); diff --git a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogForm.tsx b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogForm.tsx index 74933746b..53a818c86 100644 --- a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogForm.tsx +++ b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogForm.tsx @@ -1,5 +1,5 @@ // @ts-nocheck -import React, { useCallback } from 'react'; +import React from 'react'; import { Classes, Intent } from '@blueprintjs/core'; import { Form, Formik } from 'formik'; import { AppToaster } from '@/components'; @@ -11,21 +11,12 @@ import { CreateTaxRateFormSchema, EditTaxRateFormSchema, } from './TaxRateForm.schema'; -import { transformApiErrors, transformFormToReq } from './utils'; +import { transformApiErrors, transformFormToReq, transformTaxRateToForm } from './utils'; import { useCreateTaxRate, useEditTaxRate } from '@/hooks/query/taxRates'; import { useTaxRateFormDialogContext } from './TaxRateFormDialogBoot'; import { TaxRateFormDialogFormFooter } from './TaxRateFormDialogFormFooter'; import { compose, transformToForm } from '@/utils'; -// Default initial form values. -const defaultInitialValues = { - name: '', - code: '', - rate: '', - description: '', - is_compound: false, - is_non_recoverable: false, -}; /** * Tax rate form dialog content. @@ -35,13 +26,8 @@ function TaxRateFormDialogForm({ closeDialog, }) { // Account form context. - const { - account, - - payload, - isNewMode, - dialogName, - } = useTaxRateFormDialogContext(); + const { taxRate, taxRateId, isNewMode, dialogName } = + useTaxRateFormDialogContext(); // Form validation schema in create and edit mode. const validationSchema = isNewMode @@ -76,30 +62,18 @@ function TaxRateFormDialogForm({ setErrors({ ...errorsTransformed }); setSubmitting(false); }; - if (payload.accountId) { - editTaxRateMutate([payload.accountId, form]) + if (isNewMode) { + createTaxRateMutate({ ...form }) .then(handleSuccess) .catch(handleError); } else { - createTaxRateMutate({ ...form }) + editTaxRateMutate([taxRateId, { ...form }]) .then(handleSuccess) .catch(handleError); } }; // Form initial values in create and edit mode. - const initialValues = { - ...defaultInitialValues, - /** - * We only care about the fields in the form. Previously unfilled optional - * values such as `notes` come back from the API as null, so remove those - * as well. - */ - ...transformToForm(account, defaultInitialValues), - }; - // Handles dialog close. - const handleClose = () => { - closeDialog(dialogName); - }; + const initialValues = transformTaxRateToForm(taxRate); return (
- +
diff --git a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogFormContent.tsx b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogFormContent.tsx index 0c3bc540c..10633249a 100644 --- a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogFormContent.tsx +++ b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogFormContent.tsx @@ -1,17 +1,15 @@ -import { - FCheckbox, - FFormGroup, - FInputGroup, - FieldHint, - Hint, -} from '@/components'; -import { Tag } from '@blueprintjs/core'; +// @ts-nocheck import React from 'react'; +import { useFormikContext } from 'formik'; +import { Tag, Text } from '@blueprintjs/core'; import styled from 'styled-components'; +import { FCheckbox, FFormGroup, FInputGroup, Hint } from '@/components'; +import { transformTaxRateCodeValue, useIsTaxRateChanged } from './utils'; +import { useTaxRateFormDialogContext } from './TaxRateFormDialogBoot'; /** - * - * @returns + * Tax rate form content. + * @returns {JSX.Element} */ export default function TaxRateFormDialogContent() { return ( @@ -23,27 +21,23 @@ export default function TaxRateFormDialogContent() { subLabel={ 'The name as you would like it to appear in customers invoices.' } + fastField={true} > - - - - Required} - > - + + Required} + fastField={true} > %} fill={false} + fastField={true} /> @@ -51,23 +45,81 @@ export default function TaxRateFormDialogContent() { name={'description'} label={'Description'} labelInfo={ - + } + fastField={true} > - + - - + + - - + + + + ); } +/** + * Tax rate code input group + * @returns {JSX.Element} + */ +function TaxRateCodeField() { + const { setFieldValue } = useFormikContext(); + + // Handle the field change. + const handleChange = (event) => { + const transformedValue = transformTaxRateCodeValue(event.target.value); + setFieldValue('code', transformedValue); + }; + + return ( + Required} + fastField={true} + > + + + ); +} + +function ConfirmEditingTaxRate() { + const isTaxRateChanged = useIsTaxRateChanged(); + const { isNewMode } = useTaxRateFormDialogContext(); + + // Can't continue if it is new mode or tax rate not changed. + if (!isTaxRateChanged || isNewMode) return null; + + return ( + + Please Note: + + + + + ); +} + const RateFormGroup = styled(FInputGroup)` max-width: 100px; `; @@ -75,3 +127,18 @@ const RateFormGroup = styled(FInputGroup)` const CompoundFormGroup = styled(FFormGroup)` margin-bottom: 0; `; + +const EditWarningWrap = styled(`div`)` + background: #fcf8ec; + margin-left: -20px; + margin-right: -20px; + padding: 14px 20px; + font-size: 13px; + margin-top: 8px; + border-top: 1px solid #f2eddf; + border-bottom: 1px solid #f2eddf; +`; + +const ConfirmEditFormGroup = styled(FFormGroup)` + margin-bottom: 0; +`; diff --git a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogFormFooter.tsx b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogFormFooter.tsx index b49bdc7eb..3cf7f9ec3 100644 --- a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogFormFooter.tsx +++ b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/TaxRateFormDialogFormFooter.tsx @@ -1,3 +1,4 @@ +// @ts-nocheck import React from 'react'; import * as R from 'ramda'; import { useFormikContext } from 'formik'; diff --git a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/utils.ts b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/utils.ts index 7a746cb6d..d3ef98025 100644 --- a/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/utils.ts +++ b/packages/webapp/src/containers/TaxRates/dialogs/TaxRateFormDialog/utils.ts @@ -1,7 +1,60 @@ +// @ts-nocheck +import { useFormikContext } from 'formik'; +import * as R from 'ramda'; +import { omit } from 'lodash'; +import { transformToForm } from '@/utils'; + +// Default initial form values. +export const defaultInitialValues = { + name: '', + code: '', + rate: '', + description: '', + is_compound: false, + is_non_recoverable: false, + confirm_edit: false, +}; + export const transformApiErrors = () => { return {}; }; -export const transformFormToReq = () => { - return {}; +export const transformFormToReq = (form) => { + return omit({ ...form }, ['confirm_edit']); +}; + +export const useIsTaxRateChanged = () => { + const { initialValues, values } = useFormikContext(); + + return initialValues.rate !== values.rate; +}; + +const convertFormAttrsToBoolean = (form) => { + return { + ...form, + is_compound: !!form.is_compound, + is_non_recoverable: !!form.is_non_recoverable, + }; +}; + +export const transformTaxRateToForm = (taxRate) => { + return R.compose(convertFormAttrsToBoolean)({ + ...defaultInitialValues, + /** + * We only care about the fields in the form. Previously unfilled optional + * values such as `notes` come back from the API as null, so remove those + * as well. + */ + ...transformToForm(taxRate, defaultInitialValues), + }); +}; + +export const transformTaxRateCodeValue = (input: string) => { + // Remove non-alphanumeric characters and spaces using a regular expression + const cleanedString = input.replace(/\s+/g, ''); + + // Convert the cleaned string to uppercase + const uppercasedString = cleanedString.toUpperCase(); + + return uppercasedString; }; diff --git a/packages/webapp/src/containers/TaxRates/drawers/TaxRateDetailsDrawer/TaxRateDetailsContentDetails.tsx b/packages/webapp/src/containers/TaxRates/drawers/TaxRateDetailsDrawer/TaxRateDetailsContentDetails.tsx index 298bcd411..9c5901fc8 100644 --- a/packages/webapp/src/containers/TaxRates/drawers/TaxRateDetailsDrawer/TaxRateDetailsContentDetails.tsx +++ b/packages/webapp/src/containers/TaxRates/drawers/TaxRateDetailsDrawer/TaxRateDetailsContentDetails.tsx @@ -27,17 +27,29 @@ export default function TaxRateDetailsContentDetails() { - Enabled - + taxRate.is_non_recoverable ? ( + + Enabled + + ) : ( + + Disabled + + ) } /> - Enabled - + taxRate.is_compound ? ( + + Enabled + + ) : ( + + Disabled + + ) } /> diff --git a/packages/webapp/src/hooks/query/taxRates.ts b/packages/webapp/src/hooks/query/taxRates.ts index b48de88a7..552ab9a8c 100644 --- a/packages/webapp/src/hooks/query/taxRates.ts +++ b/packages/webapp/src/hooks/query/taxRates.ts @@ -4,6 +4,11 @@ import { useRequestQuery } from '../useQueryRequest'; import QUERY_TYPES from './types'; import useApiRequest from '../useRequest'; +// Common invalidate queries. +const commonInvalidateQueries = (queryClient) => { + queryClient.invalidateQueries(QUERY_TYPES.TAX_RATES); +}; + /** * Retrieves tax rates. * @param {number} customerId - Customer id. @@ -52,9 +57,8 @@ export function useEditTaxRate(props) { ([id, values]) => apiRequest.post(`tax-rates/${id}`, values), { onSuccess: (res, id) => { - // Invalidate specific item. + commonInvalidateQueries(queryClient); queryClient.invalidateQueries([QUERY_TYPES.TAX_RATES, id]); - queryClient.invalidateQueries([QUERY_TYPES.TAX_RATES]); }, ...props, }, @@ -68,28 +72,58 @@ export function useCreateTaxRate(props) { const queryClient = useQueryClient(); const apiRequest = useApiRequest(); - return useMutation(([values]) => apiRequest.post('tax-rates', values), { + return useMutation((values) => apiRequest.post('tax-rates', values), { onSuccess: (res, id) => { - // Invalidate specific item. + commonInvalidateQueries(queryClient); queryClient.invalidateQueries([QUERY_TYPES.TAX_RATES, id]); - queryClient.invalidateQueries([QUERY_TYPES.TAX_RATES]); }, ...props, }); } /** - * Deletes a new tax rate. + * Delete the given tax rate. */ export function useDeleteTaxRate(props) { const queryClient = useQueryClient(); const apiRequest = useApiRequest(); - return useMutation(([id]) => apiRequest.delete(`tax-rates/${id}`), { + return useMutation((id) => apiRequest.post(`tax-rates/${id}`), { onSuccess: (res, id) => { - // Invalidate specific item. + commonInvalidateQueries(queryClient); + queryClient.invalidateQueries([QUERY_TYPES.TAX_RATES, id]); + }, + ...props, + }); +} + +/** + * Activate the given tax rate. + */ +export function useActivateTaxRate(props) { + const queryClient = useQueryClient(); + const apiRequest = useApiRequest(); + + return useMutation((id) => apiRequest.post(`tax-rates/${id}/active`), { + onSuccess: (res, id) => { + commonInvalidateQueries(queryClient); + queryClient.invalidateQueries([QUERY_TYPES.TAX_RATES, id]); + }, + ...props, + }); +} + +/** + * Inactivate the given tax rate. + */ +export function useInactivateTaxRate(props) { + const queryClient = useQueryClient(); + const apiRequest = useApiRequest(); + + return useMutation((id) => apiRequest.delete(`tax-rates/${id}/inactive`), { + onSuccess: (res, id) => { + commonInvalidateQueries(queryClient); queryClient.invalidateQueries([QUERY_TYPES.TAX_RATES, id]); - queryClient.invalidateQueries([QUERY_TYPES.TAX_RATES]); }, ...props, });