1
0
This commit is contained in:
Ahmed Bouhuolia
2026-03-07 19:58:00 +02:00
parent e02e143157
commit e3aeff1f9c
124 changed files with 6006 additions and 6664 deletions
+2 -2
View File
@@ -94,8 +94,8 @@
"react-intl-universal": "^2.4.7",
"react-loadable": "^5.5.0",
"react-plaid-link": "^3.2.1",
"react-query": "^3.6.0",
"react-query-devtools": "^2.1.1",
"@tanstack/react-query": "^5.62.0",
"@tanstack/react-query-devtools": "^5.62.0",
"react-redux": "^7.2.9",
"react-router": "5.3.4",
"react-router-breadcrumbs-hoc": "^3.2.10",
+2 -2
View File
@@ -2,8 +2,8 @@
import { lazy, Suspense } from 'react';
import { Router, Switch, Route } from 'react-router';
import { createBrowserHistory } from 'history';
import { QueryClientProvider, QueryClient } from 'react-query';
import { ReactQueryDevtools } from 'react-query/devtools';
import { QueryClientProvider, QueryClient } from '@tanstack/react-query';
import { ReactQueryDevtools } from '@tanstack/react-query-devtools';
import '@/style/App.scss';
import 'moment/locale/ar-ly';
@@ -1,5 +1,5 @@
import { useEffect, useRef } from 'react';
import { useQueryClient } from 'react-query';
import { useQueryClient } from '@tanstack/react-query';
import { io } from 'socket.io-client';
import t from '@/hooks/query/types';
import { AppToaster } from '@/components';
@@ -13,10 +13,10 @@ export function DashboardSockets() {
socket.current = io('/', { path: '/socket' });
socket.current.on('NEW_TRANSACTIONS_DATA', () => {
client.invalidateQueries(t.ACCOUNTS);
client.invalidateQueries(t.ACCOUNT_TRANSACTION);
client.invalidateQueries(t.CASH_FLOW_ACCOUNTS);
client.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
client.invalidateQueries({ queryKey: [t.ACCOUNTS] });
client.invalidateQueries({ queryKey: [t.ACCOUNT_TRANSACTION] });
client.invalidateQueries({ queryKey: [t.CASH_FLOW_ACCOUNTS] });
client.invalidateQueries({ queryKey: [t.CASH_FLOW_TRANSACTIONS] });
AppToaster.show({
message: 'The Plaid connected accounts have been updated.',
@@ -24,7 +24,7 @@ export function DashboardSockets() {
});
});
socket.current.on('SUBSCRIPTION_CHANGED', () => {
client.invalidateQueries('GetSubscriptions');
client.invalidateQueries({ queryKey: ['GetSubscriptions'] });
});
return () => {
socket.current.removeAllListeners();
@@ -1,7 +1,7 @@
// @ts-nocheck
import React from 'react';
import Progress from './Progress';
import {useIsFetching} from 'react-query';
import { useIsFetching } from '@tanstack/react-query';
function AppProgress() {
const isFetching = useIsFetching();
@@ -21,7 +21,7 @@ import {
DashboardActionViewsList,
DashboardActionsBar,
} from '@/components';
import { useRefreshJournals } from '@/hooks/query/manualJournals';
import { useRefreshJournals } from '@/hooks/query/manual-journals';
import { useManualJournalsContext } from './ManualJournalsListProvider';
import { ManualJournalAction, AbilitySubject } from '@/constants/abilityOption';
@@ -1,6 +1,6 @@
// @ts-nocheck
import { DialogsName } from '@/constants/dialogs';
import { useValidateBulkDeleteManualJournals } from '@/hooks/query/manualJournals';
import { useValidateBulkDeleteManualJournals } from '@/hooks/query/manual-journals';
import { useBulkDeleteDialog } from '@/hooks/dialogs/useBulkDeleteDialog';
export const useBulkDeleteManualJournalsDialog = () => {
@@ -2,7 +2,7 @@
import React, { useState } from 'react';
import intl from 'react-intl-universal';
import { Intent, Alert } from '@blueprintjs/core';
import { useQueryClient } from 'react-query';
import { useQueryClient } from '@tanstack/react-query';
import { FormattedMessage as T, AppToaster } from '@/components';
import { withAlertStoreConnect } from '@/containers/Alert/withAlertStoreConnect';
@@ -39,7 +39,7 @@ function AccountBulkActivateAlert({
message: intl.get('the_accounts_has_been_successfully_activated'),
intent: Intent.SUCCESS,
});
queryClient.invalidateQueries('accounts-table');
queryClient.invalidateQueries({ queryKey: ['accounts-table'] });
})
.catch((errors) => {})
.finally(() => {
@@ -3,7 +3,7 @@ import React, { useState } from 'react';
import { FormattedMessage as T } from '@/components';
import intl from 'react-intl-universal';
import { Intent, Alert } from '@blueprintjs/core';
import { useQueryClient } from 'react-query';
import { useQueryClient } from '@tanstack/react-query';
import { AppToaster } from '@/components';
// import { withAccountsActions } from '@/containers/Accounts/withAccountsTableActions';
@@ -39,7 +39,7 @@ function AccountBulkInactivateAlert({
message: intl.get('the_accounts_have_been_successfully_inactivated'),
intent: Intent.SUCCESS,
});
queryClient.invalidateQueries('accounts-table');
queryClient.invalidateQueries({ queryKey: ['accounts-table'] });
})
.catch((errors) => {})
.finally(() => {
@@ -3,7 +3,7 @@ import React, { useCallback } from 'react';
import intl from 'react-intl-universal';
import { AppToaster, FormattedMessage as T } from '@/components';
import { Intent, Alert } from '@blueprintjs/core';
import { useQueryClient } from 'react-query';
import { useQueryClient } from '@tanstack/react-query';
import { useApproveEstimate } from '@/hooks/query';
@@ -41,7 +41,7 @@ function EstimateApproveAlert({
message: intl.get('the_estimate_has_been_approved_successfully'),
intent: Intent.SUCCESS,
});
queryClient.invalidateQueries('estimates-table');
queryClient.invalidateQueries({ queryKey: ['estimates-table'] });
})
.catch((error) => {})
.finally(() => {
@@ -31,7 +31,7 @@ export default function Login() {
loginMutate({
email: values.crediential,
password: values.password,
}).catch(({ response }) => {
}).catch((response) => {
const { data: error } = response;
const toastMessages = transformLoginErrorsToToasts(error);
@@ -11,9 +11,9 @@ export const transformToReq = (
const matchedTransactions = Object.entries(values.matched)
.filter(([key, value]) => value)
.map(([key]) => {
const [reference_type, reference_id] = key.split('-');
const [referenceType, referenceId] = key.split('-');
return { reference_type, reference_id: parseInt(reference_id, 10) };
return { referenceType, referenceId: parseInt(referenceId, 10) };
});
return { matchedTransactions, uncategorizedTransactions };
};
@@ -1,7 +1,7 @@
// @ts-nocheck
import React from 'react';
import { DialogContent } from '@/components';
import { useQuery, useQueryClient } from 'react-query';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import ReferenceNumberForm from '@/containers/JournalNumber/ReferenceNumberForm';
@@ -32,7 +32,10 @@ function BillNumberDialogContent({
setBillNumberChanged,
}) {
const queryClient = useQueryClient();
const fetchSettings = useQuery(['settings'], () => requestFetchOptions({}));
const fetchSettings = useQuery({
queryKey: ['settings'],
queryFn: () => requestFetchOptions({}),
});
const handleSubmitForm = (values, { setSubmitting }) => {
const options = optionsMapToArray(values).map((option) => {
@@ -46,7 +49,7 @@ function BillNumberDialogContent({
setBillNumberChanged(true);
setTimeout(() => {
queryClient.invalidateQueries('settings');
queryClient.invalidateQueries({ queryKey: ['settings'] });
}, 250);
})
.catch(() => {
@@ -34,10 +34,7 @@ function BillBulkDeleteDialog({
};
const handleConfirmBulkDelete = () => {
bulkDeleteBills({
ids,
skipUndeletable: true,
})
bulkDeleteBills({ ids, skipUndeletable: true })
.then(() => {
AppToaster.show({
message: intl.get('the_bills_has_been_deleted_successfully'),
@@ -5,7 +5,7 @@ import { FormattedMessage as T, AppToaster } from '@/components';
import intl from 'react-intl-universal';
import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent';
import { useBulkDeleteCreditNotes } from '@/hooks/query/creditNote';
import { useBulkDeleteCreditNotes } from '@/hooks/query/credit-note';
import withDialogRedux from '@/components/DialogReduxConnect';
import { withDialogActions } from '@/containers/Dialog/withDialogActions';
import { withCreditNotesActions } from '@/containers/Sales/CreditNotes/CreditNotesLanding/withCreditNotesActions';
@@ -5,7 +5,7 @@ import { FormattedMessage as T, AppToaster } from '@/components';
import intl from 'react-intl-universal';
import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent';
import { useBulkDeleteManualJournals } from '@/hooks/query/manualJournals';
import { useBulkDeleteManualJournals } from '@/hooks/query/manual-journals';
import withDialogRedux from '@/components/DialogReduxConnect';
import { withDialogActions } from '@/containers/Dialog/withDialogActions';
import { withManualJournalsActions } from '@/containers/Accounting/JournalsLanding/withManualJournalsActions';
@@ -5,7 +5,7 @@ import { FormattedMessage as T, AppToaster } from '@/components';
import intl from 'react-intl-universal';
import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent';
import { useBulkDeletePaymentReceives } from '@/hooks/query/paymentReceives';
import { useBulkDeletePaymentReceives } from '@/hooks/query/payment-receives';
import withDialogRedux from '@/components/DialogReduxConnect';
import { withDialogActions } from '@/containers/Dialog/withDialogActions';
import { withPaymentsReceivedActions } from '@/containers/Sales/PaymentsReceived/PaymentsLanding/withPaymentsReceivedActions';
@@ -5,7 +5,7 @@ import { FormattedMessage as T, AppToaster } from '@/components';
import intl from 'react-intl-universal';
import BulkDeleteDialogContent from '@/containers/Dialogs/components/BulkDeleteDialogContent';
import { useBulkDeleteVendorCredits } from '@/hooks/query/vendorCredit';
import { useBulkDeleteVendorCredits } from '@/hooks/query/vendor-credit';
import withDialogRedux from '@/components/DialogReduxConnect';
import { withDialogActions } from '@/containers/Dialog/withDialogActions';
import { withVendorsCreditNotesActions } from '@/containers/Purchases/CreditNotes/CreditNotesLanding/withVendorsCreditNotesActions';
@@ -143,8 +143,7 @@ export function useEditableItemsEntriesColumns() {
},
]
: []),
{
Header: intl.get('discount'),
Header: intl.get('discount'),
accessor: 'discount',
Cell: PercentFieldCell,
disableSortBy: true,
@@ -186,8 +185,7 @@ export function useEditableItemsEntriesColumns() {
},
]
: []),
{
Header: '',
Header: '',
accessor: 'action',
Cell: ActionsCellRenderer,
disableSortBy: true,
@@ -10,7 +10,7 @@ import {
useAccounts,
} from '@/hooks/query';
import { useWatchItemError } from './utils';
import { useTaxRates } from '@/hooks/query/taxRates';
import { useTaxRates } from '@/hooks/query/tax-rates';
const ItemFormContext = createContext();
@@ -1,5 +1,5 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import { useQueryClient, useMutation } from '@tanstack/react-query';
import { useRequestQuery } from '@/hooks/useQueryRequest';
import useApiRequest from '@/hooks/useRequest';
import t from './type';
@@ -7,24 +7,17 @@ import t from './type';
// Common invalidate queries.
const commonInvalidateQueries = (queryClient) => {
// Invalidate projects.
queryClient.invalidateQueries(t.PROJECTS);
queryClient.invalidateQueries({ queryKey: [t.PROJECTS] });
// Invalidate project entries.
queryClient.invalidateQueries(t.PROJECT_TIME_ENTRIES);
queryClient.invalidateQueries({ queryKey: [t.PROJECT_TIME_ENTRIES] });
};
/**
* Create a new project time entry.
* @param props
* @returns
*/
export function useCreateProjectTimeEntry(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.post(`/projects/tasks/${id}/times`, values),
{
onSuccess: () => {
return useMutation({ mutationFn: ([id, values]) => apiRequest.post(`/projects/tasks/${id}/times`, values),
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
@@ -33,21 +26,14 @@ export function useCreateProjectTimeEntry(props) {
);
}
/**
* Edit the given project time entry.
* @param props
* @returns
*/
export function useEditProjectTimeEntry(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`projects/times/${id}`, values),
{
onSuccess: (res, [id, values]) => {
return useMutation({ mutationFn: ([id, values]) => apiRequest.put(`projects/times/${id}`, values),
onSuccess: (res, [id, values]) => {
// Invalidate specific project time entry.
queryClient.invalidateQueries([t.PROJECT_TIME_ENTRY, id]);
queryClient.invalidateQueries({ queryKey: [t.PROJECT_TIME_ENTRY, id] });
commonInvalidateQueries(queryClient);
},
@@ -56,18 +42,14 @@ export function useEditProjectTimeEntry(props) {
);
}
/**
* Delete the given project time entry
* @param props
*/
export function useDeleteProjectTimeEntry(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`projects/times/${id}`), {
onSuccess: (res, id) => {
return useMutation({ mutationFn: (id) => apiRequest.delete(`projects/times/${id}`),
onSuccess: (res, id) => {
// Invalidate specific project task.
queryClient.invalidateQueries([t.PROJECT_TASK, id]);
queryClient.invalidateQueries({ queryKey: [t.PROJECT_TASK, id] });
// Common invalidate queries.
commonInvalidateQueries(queryClient);
@@ -76,13 +58,6 @@ export function useDeleteProjectTimeEntry(props) {
});
}
/**
* Retrive the given project time entry.
* @param timeId
* @param props
* @param requestProps
* @returns
*/
export function useProjectTimeEntry(timeId, props, requestProps) {
return useRequestQuery(
[t.PROJECT_TIME_ENTRY, timeId],
@@ -99,13 +74,6 @@ const transformProjectTimeEntries = (res) => ({
projectTimeEntries: res.data.timeline,
});
/**
*
* @param taskId - Task id.
* @param props
* @param requestProps
* @returns
*/
export function useProjectTimeEntries(id, props, requestProps) {
return useRequestQuery(
[t.PROJECT_TIME_ENTRIES, id],
@@ -1,5 +1,5 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import { useQueryClient, useMutation } from '@tanstack/react-query';
import { useRequestQuery } from '@/hooks/useQueryRequest';
import { transformPagination } from '@/utils';
import useApiRequest from '@/hooks/useRequest';
@@ -8,20 +8,17 @@ import t from './type';
// Common invalidate queries.
const commonInvalidateQueries = (queryClient) => {
// Invalidate projects.
queryClient.invalidateQueries(t.PROJECT);
queryClient.invalidateQueries(t.PROJECTS);
queryClient.invalidateQueries({ queryKey: [t.PROJECT] });
queryClient.invalidateQueries({ queryKey: [t.PROJECTS] });
};
/**
* Create a new project
* @param props
*/
export function useCreateProject(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('projects', values), {
onSuccess: (res, values) => {
return useMutation({ mutationFn: (values) => apiRequest.post('projects', values),
onSuccess: (res, values) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
@@ -29,21 +26,14 @@ export function useCreateProject(props) {
});
}
/**
* Edit the given project
* @param props
* @returns
*/
export function useEditProject(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`/projects/${id}`, values),
{
onSuccess: (res, [id, values]) => {
return useMutation({ mutationFn: ([id, values]) => apiRequest.put(`/projects/${id}`, values),
onSuccess: (res, [id, values]) => {
// Invalidate specific project.
queryClient.invalidateQueries([t.PROJECT, id]);
queryClient.invalidateQueries({ queryKey: [t.PROJECT, id] });
commonInvalidateQueries(queryClient);
},
@@ -52,18 +42,14 @@ export function useEditProject(props) {
);
}
/**
* Delete the given project
* @param props
*/
export function useDeleteProject(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`projects/${id}`), {
onSuccess: (res, id) => {
return useMutation({ mutationFn: (id) => apiRequest.delete(`projects/${id}`),
onSuccess: (res, id) => {
// Invalidate specific project.
queryClient.invalidateQueries([t.PROJECT, id]);
queryClient.invalidateQueries({ queryKey: [t.PROJECT, id] });
// Common invalidate queries.
commonInvalidateQueries(queryClient);
@@ -72,13 +58,6 @@ export function useDeleteProject(props) {
});
}
/**
* Retrieve the projects details.
* @param projectId The project id
* @param props
* @param requestProps
* @returns
*/
export function useProject(projectId, props, requestProps) {
return useRequestQuery(
[t.PROJECT, projectId],
@@ -95,11 +74,6 @@ const transformProjects = (res) => ({
projects: res.data.projects,
});
/**
* Retrieve projects list with pagination meta.
* @param query
* @param props
*/
export function useProjects(query, props) {
return useRequestQuery(
[t.PROJECTS, query],
@@ -114,21 +88,14 @@ export function useProjects(query, props) {
);
}
/**
*
* @param props
* @returns
*/
export function useProjectStatus(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.patch(`projects/${id}/status`, values),
{
onSuccess: (res, [id, values]) => {
return useMutation({ mutationFn: ([id, values]) => apiRequest.patch(`projects/${id}/status`, values),
onSuccess: (res, [id, values]) => {
// Invalidate specific project.
queryClient.invalidateQueries([t.PROJECT, id]);
queryClient.invalidateQueries({ queryKey: [t.PROJECT, id] });
commonInvalidateQueries(queryClient);
},
@@ -142,7 +109,7 @@ export function useRefreshProjects() {
return {
refresh: () => {
queryClient.invalidateQueries(t.PROJECTS);
queryClient.invalidateQueries({ queryKey: [t.PROJECTS] });
},
};
}
@@ -1,5 +1,5 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import { useQueryClient, useMutation } from '@tanstack/react-query';
import { useRequestQuery } from '@/hooks/useQueryRequest';
import useApiRequest from '@/hooks/useRequest';
import t from './type';
@@ -7,9 +7,9 @@ import t from './type';
// Common invalidate queries.
const commonInvalidateQueries = (queryClient) => {
// Invalidate projects.
queryClient.invalidateQueries(t.PROJECTS);
queryClient.invalidateQueries({ queryKey: [t.PROJECTS] });
// Invalidate project tasks.
queryClient.invalidateQueries(t.PROJECT_TASKS);
queryClient.invalidateQueries({ queryKey: [t.PROJECT_TASKS] });
};
/**
@@ -20,10 +20,8 @@ export function useCreateProjectTask(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.post(`/projects/${id}/tasks`, values),
{
onSuccess: (res, [id, values]) => {
return useMutation({ mutationFn: ([id, values]) => apiRequest.post(`/projects/${id}/tasks`, values),
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
@@ -41,13 +39,13 @@ export function useEditProjectTask(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(([id, values]) => apiRequest.put(`tasks/${id}`, values), {
onSuccess: (res, [id, values]) => {
return useMutation({ mutationFn: ([id, values]) => apiRequest.put(`tasks/${id}`, values),
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate specific project task.
queryClient.invalidateQueries([t.PROJECT_TASK, id]);
queryClient.invalidateQueries({ queryKey: [t.PROJECT_TASK, id] });
},
...props,
});
@@ -61,10 +59,10 @@ export function useDeleteProjectTask(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`tasks/${id}`), {
onSuccess: (res, id) => {
return useMutation({ mutationFn: (id) => apiRequest.delete(`tasks/${id}`),
onSuccess: (res, id) => {
// Invalidate specific project task.
queryClient.invalidateQueries([t.PROJECT_TASK, id]);
queryClient.invalidateQueries({ queryKey: [t.PROJECT_TASK, id] });
// Common invalidate queries.
commonInvalidateQueries(queryClient);
@@ -15,7 +15,7 @@ import {
useCreateBill,
useEditBill,
} from '@/hooks/query';
import { useTaxRates } from '@/hooks/query/taxRates';
import { useTaxRates } from '@/hooks/query/tax-rates';
const BillFormContext = createContext();
@@ -1,6 +1,6 @@
// @ts-nocheck
import { DialogsName } from '@/constants/dialogs';
import { useValidateBulkDeleteVendorCredits } from '@/hooks/query/vendorCredit';
import { useValidateBulkDeleteVendorCredits } from '@/hooks/query/vendor-credit';
import { useBulkDeleteDialog } from '@/hooks/dialogs/useBulkDeleteDialog';
export const useBulkDeleteVendorCreditsDialog = () => {
@@ -30,7 +30,7 @@ import { withSettingsActions } from '@/containers/Settings/withSettingsActions';
import { withDialogActions } from '@/containers/Dialog/withDialogActions';
import { usePaymentMadesListContext } from './PaymentMadesListProvider';
import { useRefreshPaymentMades } from '@/hooks/query/paymentMades';
import { useRefreshPaymentMades } from '@/hooks/query/payment-mades';
import { useDownloadExportPdf } from '@/hooks/query/FinancialReports/use-export-pdf';
import { DialogsName } from '@/constants/dialogs';
@@ -1,6 +1,6 @@
// @ts-nocheck
import { DialogsName } from '@/constants/dialogs';
import { useValidateBulkDeleteCreditNotes } from '@/hooks/query/creditNote';
import { useValidateBulkDeleteCreditNotes } from '@/hooks/query/credit-note';
import { useBulkDeleteDialog } from '@/hooks/dialogs/useBulkDeleteDialog';
export const useBulkDeleteCreditNotesDialog = () => {
@@ -20,7 +20,7 @@ import {
GetSaleInvoiceStateResponse,
} from '@/hooks/query';
import { useProjects } from '@/containers/Projects/hooks';
import { useTaxRates } from '@/hooks/query/taxRates';
import { useTaxRates } from '@/hooks/query/tax-rates';
import { useGetPdfTemplates } from '@/hooks/query/pdf-templates';
import { useGetPaymentServices } from '@/hooks/query/payment-services';
@@ -38,7 +38,7 @@ import {
} from '@/constants/abilityOption';
import { usePaymentsReceivedListContext } from './PaymentsReceivedListProvider';
import { useRefreshPaymentReceive } from '@/hooks/query/paymentReceives';
import { useRefreshPaymentReceive } from '@/hooks/query/payment-receives';
import { useDownloadExportPdf } from '@/hooks/query/FinancialReports/use-export-pdf';
import { compose } from '@/utils';
@@ -189,7 +189,6 @@ function PaymentsReceivedActionsBar({
text={<T id={'export'} />}
onClick={handleExportBtnClick}
/>
<NavbarDivider />
<DashboardRowsHeightButton
initialValue={paymentReceivesTableSize}
@@ -1,6 +1,6 @@
// @ts-nocheck
import { DialogsName } from '@/constants/dialogs';
import { useValidateBulkDeletePaymentReceives } from '@/hooks/query/paymentReceives';
import { useValidateBulkDeletePaymentReceives } from '@/hooks/query/payment-receives';
import { useBulkDeleteDialog } from '@/hooks/dialogs/useBulkDeleteDialog';
export const useBulkDeletePaymentReceivesDialog = () => {
@@ -3,7 +3,7 @@ import React from 'react';
import { Intent, Alert } from '@blueprintjs/core';
import { AppToaster, FormattedMessage as T } from '@/components';
import { useDeleteTaxRate } from '@/hooks/query/taxRates';
import { useDeleteTaxRate } from '@/hooks/query/tax-rates';
import { withAlertStoreConnect } from '@/containers/Alert/withAlertStoreConnect';
import { withAlertActions } from '@/containers/Alert/withAlertActions';
@@ -2,7 +2,7 @@
import React from 'react';
import { isEmpty } from 'lodash';
import { DashboardInsider } from '@/components/Dashboard';
import { useTaxRates } from '@/hooks/query/taxRates';
import { useTaxRates } from '@/hooks/query/tax-rates';
const TaxRatesLandingContext = React.createContext();
@@ -17,16 +17,16 @@ import { withSettings } from '@/containers/Settings/withSettings';
import { useTaxRatesTableColumns } from './_utils';
import { useTaxRatesLandingContext } from './TaxRatesLandingProvider';
import {
useActivateTaxRate,
useInactivateTaxRate,
} from '@/hooks/query/tax-rates';
import { TaxRatesLandingEmptyState } from './TaxRatesLandingEmptyState';
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.
@@ -1,7 +1,7 @@
// @ts-nocheck
import React from 'react';
import { DialogContent } from '@/components';
import { useTaxRate } from '@/hooks/query/taxRates';
import { useTaxRate } from '@/hooks/query/tax-rates';
import { DialogsName } from '@/constants/dialogs';
const TaxRateFormDialogContext = React.createContext();
@@ -16,7 +16,7 @@ import {
transformFormToReq,
transformTaxRateToForm,
} from './utils';
import { useCreateTaxRate, useEditTaxRate } from '@/hooks/query/taxRates';
import { useCreateTaxRate, useEditTaxRate } from '@/hooks/query/tax-rates';
import { useTaxRateFormDialogContext } from './TaxRateFormDialogBoot';
import { TaxRateFormDialogFormFooter } from './TaxRateFormDialogFormFooter';
import { TaxRateFormDialogFormErrors } from './TaxRateFormDialogFormErrors';
@@ -23,7 +23,7 @@ import { DialogsName } from '@/constants/dialogs';
import {
useActivateTaxRate,
useInactivateTaxRate,
} from '@/hooks/query/taxRates';
} from '@/hooks/query/tax-rates';
/**
* Tax rate details content actions bar.
@@ -1,7 +1,7 @@
// @ts-nocheck
import React, { createContext, useContext } from 'react';
import { DrawerLoading } from '@/components';
import { useTaxRate } from '@/hooks/query/taxRates';
import { useTaxRate } from '@/hooks/query/tax-rates';
const TaxRateDetailsContext = createContext();
@@ -4,8 +4,8 @@ export * from './use-cashflow-sheet';
export * from './use-profit-loss-sheet';
export * from './use-general-ledger';
export * from './use-journal-sheet';
export * from './use-AP-aging-summary';
export * from './use-AR-aging-summary';
export * from './use-ap-aging-summary';
export * from './use-ar-aging-summary';
export * from './use-inventory-valuation';
export * from './use-inventory-item-details';
export * from './use-purchases-by-items';
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchPayableAgingSummaryTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,21 +10,12 @@ import t from '../types';
* Retrieve A/P aging summary report.
*/
export function useAPAgingSummaryReport(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.AP_AGING_SUMMARY, query],
{
method: 'get',
url: '/reports/payable-aging-summary',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.AP_AGING_SUMMARY, query],
queryFn: () => fetchPayableAgingSummaryTable(fetcher, query ?? {}),
...props,
});
}
export const useAPAgingSheetXlsxExport = (query, args) => {
@@ -1,27 +1,21 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchReceivableAgingSummaryTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
/**
* Retrieve A/R aging summary report.
*/
export function useARAgingSummaryReport(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.AR_AGING_SUMMARY, query],
{
method: 'get',
url: '/reports/receivable-aging-summary',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.AR_AGING_SUMMARY, query],
queryFn: () => fetchReceivableAgingSummaryTable(fetcher, query ?? {}),
...props,
});
}
export const useARAgingSheetXlsxExport = (query, args) => {
@@ -1,6 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchBalanceSheetTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -9,24 +10,15 @@ import t from '../types';
* Fetches balance sheet data.
* @param {Object} query - The query parameters for the request.
* @param {Object} props - Additional options for the request.
* @returns {Object} The response object from the useRequestQuery hook.
* @returns {Object} The response object from the useQuery hook.
*/
export function useBalanceSheet(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.BALANCE_SHEET, query],
{
method: 'get',
url: '/reports/balance-sheet',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.BALANCE_SHEET, query],
queryFn: () => fetchBalanceSheetTable(fetcher, query ?? {}),
...props,
});
}
/**
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchCashflowStatementTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,32 +10,25 @@ import t from '../types';
* Retrieve cash flow statement report.
*/
export function useCashFlowStatementReport(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.CASH_FLOW_STATEMENT, query],
{
method: 'get',
url: '/reports/cashflow-statement',
params: query,
headers: {
Accept: 'application/json+table',
},
const fetcher = useReportsApiFetcher();
const { defaultData, ...rest } = props ?? {};
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.CASH_FLOW_STATEMENT, query],
queryFn: () => fetchCashflowStatementTable(fetcher, query ?? {}),
select: (data) => ({
columns: data?.table?.columns,
query: data?.query,
meta: data?.meta,
tableRows: data?.table?.rows,
}),
placeholderData: defaultData ?? {
tableRows: [],
columns: [],
query: {},
meta: {},
},
{
select: (res) => ({
columns: res.data.table.columns,
query: res.data.query,
meta: res.data.meta,
tableRows: res.data.table.rows,
}),
defaultData: {
tableRows: [],
columns: [],
query: {},
meta: {},
},
...props,
},
);
...rest,
});
}
export const useCashFlowStatementXlsxExport = (query, args) => {
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchCustomerBalanceSummaryTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,30 +10,19 @@ import t from '../types';
* Retrieve customers balance summary report.
*/
export function useCustomerBalanceSummaryReport(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.CUSTOMERS_BALANCE_SUMMARY, query],
{
method: 'get',
url: '/reports/customer-balance-summary',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => ({
query: res.data.query,
table: res.data.table,
meta: res.data.meta,
}),
defaultData: {
table: {},
query: {},
meta: {},
},
...props,
},
);
const fetcher = useReportsApiFetcher();
const { defaultData, ...rest } = props ?? {};
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.CUSTOMERS_BALANCE_SUMMARY, query],
queryFn: () => fetchCustomerBalanceSummaryTable(fetcher, query ?? {}),
select: (data) => ({
query: data?.query,
table: data?.table,
meta: data?.meta,
}),
placeholderData: defaultData ?? { table: {}, query: {}, meta: {} },
...rest,
});
}
export const useCustomerBalanceSummaryXlsxExport = (query, args) => {
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchTransactionsByCustomersTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,30 +10,19 @@ import t from '../types';
* Retrieve customers transactions report.
*/
export function useCustomersTransactionsReport(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.CUSTOMERS_TRANSACTIONS, query],
{
method: 'get',
url: '/reports/transactions-by-customers',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => ({
data: res.data.table,
tableRows: res.data.table.rows,
meta: res.data.meta,
}),
defaultData: {
tableRows: [],
data: [],
meta: {},
},
...props,
},
);
const fetcher = useReportsApiFetcher();
const { defaultData, ...rest } = props ?? {};
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.CUSTOMERS_TRANSACTIONS, query],
queryFn: () => fetchTransactionsByCustomersTable(fetcher, query ?? {}),
select: (data) => ({
data: data?.table,
tableRows: data?.table?.rows,
meta: data?.meta,
}),
placeholderData: defaultData ?? { tableRows: [], data: [], meta: {} },
...rest,
});
}
export const useCustomersTransactionsXlsxExport = (query, args) => {
@@ -2,7 +2,7 @@
import { downloadFile } from '@/hooks/useDownloadFile';
import useApiRequest from '@/hooks/useRequest';
import { AxiosError } from 'axios';
import { useMutation } from 'react-query';
import { useMutation } from '@tanstack/react-query';
import { asyncToastProgress } from '@/utils/async-toast-progress';
interface ResourceExportValues {
@@ -2,7 +2,7 @@
import { downloadFile } from '@/hooks/useDownloadFile';
import useApiRequest from '@/hooks/useRequest';
import { AxiosError } from 'axios';
import { useMutation } from 'react-query';
import { useMutation } from '@tanstack/react-query';
interface ResourceExportValues {
resource: string;
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchGeneralLedgerTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,21 +10,12 @@ import t from '../types';
* Retrieve general ledger (GL) sheet.
*/
export function useGeneralLedgerSheet(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.GENERAL_LEDGER, query],
{
method: 'get',
url: '/reports/general-ledger',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.GENERAL_LEDGER, query],
queryFn: () => fetchGeneralLedgerTable(fetcher, query ?? {}),
...props,
});
}
export const useGeneralLedgerSheetXlsxExport = (query, args) => {
return useDownloadFile({
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchInventoryItemDetailsTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,32 +10,25 @@ import t from '../types';
* Retrieve inventory item detail report.
*/
export function useInventoryItemDetailsReport(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.INVENTORY_ITEM_DETAILS, query],
{
method: 'get',
url: '/reports/inventory-item-details',
params: query,
headers: {
Accept: 'application/json+table',
},
const fetcher = useReportsApiFetcher();
const { defaultData, ...rest } = props ?? {};
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.INVENTORY_ITEM_DETAILS, query],
queryFn: () => fetchInventoryItemDetailsTable(fetcher, query ?? {}),
select: (data) => ({
columns: data?.table?.columns,
query: data?.query,
meta: data?.meta,
tableRows: data?.table?.rows,
}),
placeholderData: defaultData ?? {
tableRows: [],
columns: [],
query: {},
meta: {},
},
{
select: (res) => ({
columns: res.data.table.columns,
query: res.data.query,
meta: res.data.meta,
tableRows: res.data.table.rows,
}),
defaultData: {
tableRows: [],
columns: [],
query: {},
meta: {},
},
...props,
},
);
...rest,
});
}
export const useInventoryItemDetailsXlsxExport = (query, args) => {
@@ -1,4 +1,7 @@
// @ts-nocheck
import { useQuery } from '@tanstack/react-query';
import { fetchInventoryValuationTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useRequestQuery } from '../../useQueryRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
@@ -24,24 +27,15 @@ export function useInventoryValuation(query, props) {
}
/**
* Retrieve inventory valuation.
* Retrieve inventory valuation (table format).
*/
export function useInventoryValuationTable(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.INVENTORY_VALUATION, query],
{
method: 'get',
url: '/reports/inventory-valuation',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.INVENTORY_VALUATION, query],
queryFn: () => fetchInventoryValuationTable(fetcher, query ?? {}),
...props,
});
}
export const useInventoryValuationXlsxExport = (query, args) => {
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchJournalTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,21 +10,12 @@ import t from '../types';
* Retrieve journal sheet.
*/
export function useJournalSheet(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.JOURNAL, query],
{
method: 'get',
url: '/reports/journal',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.JOURNAL, query],
queryFn: () => fetchJournalTable(fetcher, query ?? {}),
...props,
});
}
export const useJournalSheetXlsxExport = (query, args) => {
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchProfitLossSheetTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,21 +10,12 @@ import t from '../types';
* Retrieve profit/loss (P&L) sheet.
*/
export function useProfitLossSheet(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.PROFIT_LOSS_SHEET, query],
{
method: 'get',
url: '/reports/profit-loss-sheet',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.PROFIT_LOSS_SHEET, query],
queryFn: () => fetchProfitLossSheetTable(fetcher, query ?? {}),
...props,
});
}
export const useProfitLossSheetXlsxExport = (query, args) => {
@@ -1,4 +1,7 @@
// @ts-nocheck
import { useQuery } from '@tanstack/react-query';
import { fetchPurchasesByItemsTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useRequestQuery } from '../../useQueryRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
@@ -23,21 +26,12 @@ export function usePurchasesByItems(query, props) {
}
export function usePurchasesByItemsTable(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.PURCHASES_BY_ITEMS, query],
{
method: 'get',
url: '/reports/purchases-by-items',
params: query,
headers: {
accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.PURCHASES_BY_ITEMS, query],
queryFn: () => fetchPurchasesByItemsTable(fetcher, query ?? {}),
...props,
});
}
export const usePurchasesByItemsCsvExport = (query, args) => {
@@ -1,4 +1,7 @@
// @ts-nocheck
import { useQuery } from '@tanstack/react-query';
import { fetchSalesByItemsTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useRequestQuery } from '../../useQueryRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
@@ -25,21 +28,12 @@ export function useSalesByItems(query, props) {
* Retrieves sales by items table format.
*/
export function useSalesByItemsTable(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.SALES_BY_ITEMS, query],
{
method: 'get',
url: '/reports/sales-by-items',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.SALES_BY_ITEMS, query],
queryFn: () => fetchSalesByItemsTable(fetcher, query ?? {}),
...props,
});
}
export const useSalesByItemsCsvExport = (query, args) => {
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchSalesTaxLiabilitySummaryTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,21 +10,12 @@ import t from '../types';
* Retrieves the sales tax liability summary report.
*/
export function useSalesTaxLiabilitySummary(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.SALES_TAX_LIABILITY_SUMMARY, query],
{
method: 'get',
url: '/reports/sales-tax-liability-summary',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.SALES_TAX_LIABILITY_SUMMARY, query],
queryFn: () => fetchSalesTaxLiabilitySummaryTable(fetcher, query ?? {}),
...props,
});
}
export const useSalesTaxLiabilitySummaryXlsxExport = (query, args) => {
@@ -1,23 +1,19 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchTransactionsByReferenceTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import t from '../types';
/**
* Retrieve transactions by reference report.
*/
export function useTransactionsByReference(query, props) {
return useRequestQuery(
[t.TRANSACTIONS_BY_REFERENCE, query],
{
method: 'get',
url: `/reports/transactions-by-reference`,
params: query,
},
{
select: (res) => res.data,
defaultData: {
transactions: [],
},
...props,
},
);
const fetcher = useReportsApiFetcher();
const { defaultData, ...rest } = props ?? {};
return useQuery({
queryKey: [t.TRANSACTIONS_BY_REFERENCE, query],
queryFn: () => fetchTransactionsByReferenceTable(fetcher, query ?? {}),
placeholderData: defaultData ?? { transactions: [] },
...rest,
});
}
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchTrialBalanceSheetTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,21 +10,12 @@ import t from '../types';
* Retrieve trial balance sheet.
*/
export function useTrialBalanceSheet(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.TRIAL_BALANCE_SHEET, query],
{
method: 'get',
url: '/reports/trial-balance-sheet',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.TRIAL_BALANCE_SHEET, query],
queryFn: () => fetchTrialBalanceSheetTable(fetcher, query ?? {}),
...props,
});
}
export const useTrialBalanceSheetXlsxExport = (query, args) => {
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchVendorBalanceSummaryTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,30 +10,19 @@ import t from '../types';
* Retrieve vendors balance summary report.
*/
export function useVendorsBalanceSummaryReport(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.VENDORS_BALANCE_SUMMARY, query],
{
method: 'get',
url: '/reports/vendor-balance-summary',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => ({
query: res.data.query,
table: res.data.table,
meta: res.data.meta,
}),
defaultData: {
table: {},
query: {},
meta: {},
},
...props,
},
);
const fetcher = useReportsApiFetcher();
const { defaultData, ...rest } = props ?? {};
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.VENDORS_BALANCE_SUMMARY, query],
queryFn: () => fetchVendorBalanceSummaryTable(fetcher, query ?? {}),
select: (data) => ({
query: data?.query,
table: data?.table,
meta: data?.meta,
}),
placeholderData: defaultData ?? { table: {}, query: {}, meta: {} },
...rest,
});
}
export const useVendorBalanceSummaryXlsxExport = (args) => {
@@ -1,5 +1,7 @@
// @ts-nocheck
import { useRequestQuery } from '../../useQueryRequest';
import { useQuery } from '@tanstack/react-query';
import { fetchTransactionsByVendorsTable } from '@bigcapital/sdk-ts';
import { useReportsApiFetcher } from '../../useRequest';
import { useDownloadFile } from '../../useDownloadFile';
import { useRequestPdf } from '../../useRequestPdf';
import t from '../types';
@@ -8,21 +10,12 @@ import t from '../types';
* Retrieve vendors transactions report.
*/
export function useVendorsTransactionsReport(query, props) {
return useRequestQuery(
[t.FINANCIAL_REPORT, t.VENDORS_TRANSACTIONS, query],
{
method: 'get',
url: '/reports/transactions-by-vendors',
params: query,
headers: {
Accept: 'application/json+table',
},
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useReportsApiFetcher();
return useQuery({
queryKey: [t.FINANCIAL_REPORT, t.VENDORS_TRANSACTIONS, query],
queryFn: () => fetchTransactionsByVendorsTable(fetcher, query ?? {}),
...props,
});
}
export const useVendorsTransactionsXlsxExport = (query, args) => {
+159 -177
View File
@@ -1,215 +1,197 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type {
Account,
AccountsList,
CreateAccountBody,
EditAccountBody,
GetAccountsQuery,
ValidateBulkDeleteResponse,
} from '@bigcapital/sdk-ts';
import {
fetchAccounts,
fetchAccount,
fetchAccountTypes,
fetchAccountTransactions,
createAccount,
editAccount,
deleteAccount,
activateAccount,
inactivateAccount,
bulkDeleteAccounts,
validateBulkDeleteAccounts,
AccountTypesList,
AccountTransactionsList
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import t from './types';
import { transformToCamelCase } from '@/utils';
// Transform the account.
const transformAccount = (response) => {
return response.data;
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
queryClient.invalidateQueries({ queryKey: [t.CASH_FLOW_ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
};
const commonInvalidateQueries = (query) => {
// Invalidate accounts.
query.invalidateQueries(t.ACCOUNTS);
query.invalidateQueries(t.ACCOUNT);
// Invalidate cashflow accounts.
query.invalidateQueries(t.CASH_FLOW_ACCOUNTS);
// Invalidate financial reports.
query.invalidateQueries(t.FINANCIAL_REPORT);
};
/**
* Retrieve accounts list.
*/
export function useAccounts(query, props) {
return useRequestQuery(
[t.ACCOUNTS, query],
{ method: 'get', url: 'accounts', params: query },
{
select: (res) => res.data.accounts,
defaultData: [],
...props,
},
);
}
/**
* Retrieve the given account details.
* @param {number} id - Account id.
*/
export function useAccount(id, props) {
return useRequestQuery(
[t.ACCOUNT, id],
{ method: 'get', url: `accounts/${id}` },
{
select: transformAccount,
defaultData: {},
...props,
},
);
}
/**
* Retrieve accounts types list.
*/
export function useAccountsTypes(props) {
return useRequestQuery(
[t.ACCOUNTS_TYPES],
{ method: 'get', url: 'accounts/types' },
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
}
/**
* Creates account.
*/
export function useCreateAccount(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('accounts', values), {
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(client);
},
export function useAccounts(
query?: GetAccountsQuery | null,
props?: Omit<UseQueryOptions<AccountsList>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ACCOUNTS, query],
queryFn: () => fetchAccounts(fetcher, query ?? {}),
...props,
});
}
/**
* Edits the given account.
*/
export function useEditAccount(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`accounts/${id}`, values),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(client);
},
...props,
},
);
}
/**
* Edits the given account.
*/
export function useDeleteAccount(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`accounts/${id}`), {
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(client);
},
export function useAccount(
id: number | null | undefined,
props?: Omit<UseQueryOptions<Account>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ACCOUNT, id],
queryFn: () => fetchAccount(fetcher, id!),
enabled: id != null,
...props,
});
}
/**
* Activate the give account.
*/
export function useActivateAccount(props) {
export function useAccountsTypes(
props?: Omit<UseQueryOptions<AccountTypesList>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ACCOUNTS_TYPES],
queryFn: () => fetchAccountTypes(fetcher),
...props,
});
}
export function useCreateAccount(
props?: UseMutationOptions<void, Error, CreateAccountBody>
) {
const client = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.post(`accounts/${id}/activate`), {
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(client);
},
return useMutation({
mutationFn: (values: CreateAccountBody) => createAccount(fetcher, values),
onSuccess: () => commonInvalidateQueries(client),
...props,
});
}
/**
* Inactivate the given account.
*/
export function useInactivateAccount(props) {
const query = useQueryClient();
const apiRequest = useApiRequest();
export function useEditAccount(
props?: UseMutationOptions<void, Error, [number, EditAccountBody]>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.post(`accounts/${id}/inactivate`), {
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(query);
},
return useMutation({
mutationFn: ([id, values]: [number, EditAccountBody]) =>
editAccount(fetcher, id, values),
onSuccess: () => commonInvalidateQueries(client),
...props,
});
}
/**
* Deletes multiple accounts in bulk.
*/
export function useBulkDeleteAccounts(props) {
export function useDeleteAccount(
props?: UseMutationOptions<void, Error, number>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => deleteAccount(fetcher, id),
onSuccess: () => commonInvalidateQueries(client),
...props,
});
}
export function useActivateAccount(
props?: UseMutationOptions<void, Error, number>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => activateAccount(fetcher, id),
onSuccess: () => commonInvalidateQueries(client),
...props,
});
}
export function useInactivateAccount(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
({
return useMutation({
mutationFn: (id: number) => inactivateAccount(fetcher, id),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useBulkDeleteAccounts(
props?: UseMutationOptions<
void,
Error,
{ ids: number[]; skipUndeletable?: boolean }
>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('accounts/bulk-delete', {
ids,
skip_undeletable: skipUndeletable,
}),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}) => bulkDeleteAccounts(fetcher, { ids, skipUndeletable }),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
/**
* Validates which accounts can be deleted in bulk.
*/
export function useValidateBulkDeleteAccounts(props) {
const apiRequest = useApiRequest();
export function useValidateBulkDeleteAccounts(
props?: UseMutationOptions<ValidateBulkDeleteResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
return useMutation(
(ids: number[]) =>
apiRequest
.post('accounts/validate-bulk-delete', { ids })
.then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeleteAccounts(fetcher, ids).then((res: ValidateBulkDeleteResponse) =>
transformToCamelCase(res as unknown as Record<string, unknown>) as ValidateBulkDeleteResponse
),
...props,
});
}
/**
* Retrieve account transactions.
*/
export function useAccountTransactions(id, props) {
return useRequestQuery(
[t.ACCOUNT_TRANSACTION, id],
{ method: 'get', url: `accounts/transactions?account_id=${id}` },
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
export function useAccountTransactions(
id: number | null | undefined,
props?: Omit<
UseQueryOptions<AccountTransactionsList>,
'queryKey' | 'queryFn'
>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ACCOUNT_TRANSACTION, id],
queryFn: () => fetchAccountTransactions(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useRefreshAccounts() {
@@ -217,7 +199,7 @@ export function useRefreshAccounts() {
return {
refresh: () => {
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
},
};
}
@@ -0,0 +1,53 @@
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type { ApiKeysList, GenerateApiKeyBody } from '@bigcapital/sdk-ts';
import { fetchApiKeys, generateApiKey, revokeApiKey } from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import t from './types';
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.API_KEYS] });
};
export function useApiKeys(
props?: Omit<UseQueryOptions<ApiKeysList>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.API_KEYS],
queryFn: () => fetchApiKeys(fetcher),
select: (data: ApiKeysList) => data ?? ([] as ApiKeysList),
...props,
});
}
export function useGenerateApiKey(
props?: UseMutationOptions<void, Error, GenerateApiKeyBody>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: GenerateApiKeyBody) => generateApiKey(fetcher, values),
onSuccess: () => commonInvalidateQueries(client),
...props,
});
}
export function useRevokeApiKey(
props?: UseMutationOptions<void, Error, number>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => revokeApiKey(fetcher, id),
onSuccess: () => commonInvalidateQueries(client),
...props,
});
}
@@ -1,57 +0,0 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import t from './types';
const commonInvalidateQueries = (query) => {
query.invalidateQueries(t.API_KEYS);
};
/**
* Retrieve API keys list.
*/
export function useApiKeys(props) {
return useRequestQuery(
[t.API_KEYS],
{ method: 'get', url: 'api-keys' },
{
select: (res) => res.data || [],
defaultData: [],
...props,
},
);
}
/**
* Generates a new API key.
*/
export function useGenerateApiKey(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('api-keys/generate', values), {
onSuccess: () => {
commonInvalidateQueries(client);
},
...props,
});
}
/**
* Revokes the given API key.
*/
export function useRevokeApiKey(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(id) => apiRequest.put(`api-keys/${id}/revoke`),
{
onSuccess: () => {
commonInvalidateQueries(client);
},
...props,
},
);
}
+37 -38
View File
@@ -1,55 +1,54 @@
// @ts-nocheck
import { useMutation } from 'react-query';
import useApiRequest from '../useRequest';
import { transformToCamelCase } from '@/utils';
import { useMutation, UseMutationOptions } from '@tanstack/react-query';
import { deleteAttachment, fetchAttachmentPresignedUrl, uploadAttachment } from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
interface UploadAttachmentResponse {
createdAt: string;
id: number;
key: string;
mimeType: string;
originName: string;
size: number;
type UploadAttachmentResponse = Awaited<ReturnType<typeof uploadAttachment>>;
function toFormData(values: FormData | Record<string, unknown>): FormData {
if (values instanceof FormData) {
return values;
}
const formData = new FormData();
const record = values as Record<string, unknown>;
if (record.file instanceof File) {
formData.append('file', record.file);
}
return formData;
}
/**
* Uploads the given attachments.
*/
export function useUploadAttachments(props) {
const apiRequest = useApiRequest();
return useMutation<UploadAttachmentResponse>(
(values) =>
apiRequest
.post('attachments', values)
.then((res) => transformToCamelCase(res.data?.data)),
props,
);
export function useUploadAttachments(
props?: UseMutationOptions<UploadAttachmentResponse, Error, FormData | Record<string, unknown>>
) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values) => uploadAttachment(fetcher, toFormData(values)),
...props,
});
}
/**
* Deletes the given attachment key.
*/
export function useDeleteAttachment(props) {
const apiRequest = useApiRequest();
return useMutation(
(key: string) => apiRequest.delete(`attachments/${key}`),
props,
);
export function useDeleteAttachment(props?: UseMutationOptions<void, Error, string>) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (key: string) => deleteAttachment(fetcher, key),
...props,
});
}
/**
* Uploads the given attachments.
*/
export function useGetPresignedUrlAttachment(props) {
const apiRequest = useApiRequest();
return useMutation(
(key: string) =>
apiRequest
.get(`attachments/${key}/presigned-url`)
.then((res) => res.data),
props,
);
export function useGetPresignedUrlAttachment(
props?: UseMutationOptions<unknown, Error, string>
) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (key: string) => fetchAttachmentPresignedUrl(fetcher, key),
...props,
});
}
+124 -127
View File
@@ -1,155 +1,152 @@
// @ts-nocheck
import { useMutation } from 'react-query';
import {
useMutation,
useQuery,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import { batch } from 'react-redux';
import useApiRequest, { useAuthApiRequest } from '../useRequest';
import {
signin,
signup,
signupConfirm,
sendResetPassword,
resetPassword,
fetchAuthMeta,
resendSignupConfirm,
type AuthSigninResponse,
type AuthSigninBody,
type AuthSignupBody,
type AuthSignupVerifyBody,
type AuthSendResetPasswordBody,
type AuthResetPasswordBody,
type AuthMetaResponse,
} from '@bigcapital/sdk-ts';
import { useAuthApiFetcher, useApiFetcher } from '../useRequest';
import { setCookie } from '../../utils';
import { useRequestQuery } from '../useQueryRequest';
import t from './types';
import {
useSetAuthToken,
useSetAuthUserId,
useSetLocale,
useSetOrganizationId,
useSetTenantId,
} from '../state';
const AuthRoute = {
Signin: 'auth/signin',
Signup: 'auth/signup',
SignupVerify: 'auth/signup/verify',
SignupVerifyResend: 'auth/signup/verify/resend',
SendResetPassword: 'auth/send_reset_password',
ForgetPassword: 'auth/reset_password/:token',
AuthMeta: 'auth/meta',
};
/**
* Saves the response data to cookies.
*/
export function setAuthLoginCookies(data) {
setCookie('token', data.access_token);
setCookie('authenticated_user_id', data.user_id);
setCookie('organization_id', data.organization_id);
setCookie('tenant_id', data.tenant_id);
// if (data?.tenant?.metadata?.language)
// setCookie('locale', data.tenant.metadata.language);
export function setAuthLoginCookies(data: AuthSigninResponse): void {
setCookie('token', data.accessToken ?? '');
setCookie('authenticated_user_id', String(data.userId ?? ''));
setCookie('organization_id', data.organizationId ?? '');
setCookie('tenant_id', String(data.tenantId ?? ''));
}
/**
* Authentication login.
*/
export const useAuthLogin = (props) => {
const apiRequest = useAuthApiRequest();
export function useAuthLogin(
props?: UseMutationOptions<
AuthSigninResponse,
Error,
AuthSigninBody
>
) {
const fetcher = useAuthApiFetcher();
const setAuthToken = useSetAuthToken();
const setOrganizationId = useSetOrganizationId();
const setUserId = useSetAuthUserId();
const setTenantId = useSetTenantId();
const setLocale = useSetLocale();
return useMutation((values) => apiRequest.post(AuthRoute.Signin, values), {
onSuccess: (res) => {
// Set authentication cookies.
setAuthLoginCookies(res.data);
return useMutation({
mutationFn: (values: AuthSigninBody) => signin(fetcher, values),
onSuccess: (data, variables, context, mutation) => {
setAuthLoginCookies(data);
batch(() => {
// Sets the auth metadata to global state.
setAuthToken(res.data.access_token);
setOrganizationId(res.data.organization_id);
setTenantId(res.data.tenant_id);
setUserId(res.data.user_id);
// if (res.data?.tenant?.metadata?.language) {
// setLocale(res.data?.tenant?.metadata?.language);
// }
// @ts-ignore
setAuthToken(data.access_token ?? '');
// @ts-ignore
setOrganizationId(data.organization_id ?? '');
// @ts-ignore
setTenantId(String(data.tenant_id ?? ''));
// @ts-ignore
setUserId(String(data.user_id ?? ''));
});
props?.onSuccess && props?.onSuccess(...args);
props?.onSuccess?.(data, variables, context, mutation);
},
...props,
});
};
/**
* Authentication register.
*/
export const useAuthRegister = (props) => {
const apiRequest = useAuthApiRequest();
return useMutation(
(values) => apiRequest.post(AuthRoute.Signup, values),
props,
);
};
/**
* Authentication send reset password.
*/
export const useAuthSendResetPassword = (props) => {
const apiRequest = useAuthApiRequest();
return useMutation(
(values) => apiRequest.post(AuthRoute.SendResetPassword, values),
props,
);
};
/**
* Authentication reset password.
*/
export const useAuthResetPassword = (props) => {
const apiRequest = useAuthApiRequest();
return useMutation(
([token, values]) => apiRequest.post(`auth/reset/${token}`, values),
props,
);
};
/**
* Fetches the authentication page metadata.
*/
export const useAuthMetadata = (props = {}) => {
return useRequestQuery(
[t.AUTH_METADATA_PAGE],
{
method: 'get',
url: AuthRoute.AuthMeta,
},
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
};
/**
* Resend the mail of signup verification.
*/
export const useAuthSignUpVerifyResendMail = (props) => {
const apiRequest = useApiRequest();
return useMutation(
() => apiRequest.post(AuthRoute.SignupVerifyResend),
props,
);
};
interface AuthSignUpVerifyValues {
token: string;
email: string;
}
/**
* Signup verification.
*/
export const useAuthSignUpVerify = (props) => {
const apiRequest = useAuthApiRequest();
export function useAuthRegister(
props?: UseMutationOptions<unknown, Error, AuthSignupBody>
) {
const fetcher = useAuthApiFetcher();
return useMutation(
(values: AuthSignUpVerifyValues) =>
apiRequest.post(AuthRoute.SignupVerify, values),
props,
);
};
return useMutation({
mutationFn: (values: AuthSignupBody) => signup(fetcher, values),
...props,
});
}
export function useAuthSendResetPassword(
props?: UseMutationOptions<unknown, Error, AuthSendResetPasswordBody>
) {
const fetcher = useAuthApiFetcher();
return useMutation({
mutationFn: (values: AuthSendResetPasswordBody) =>
sendResetPassword(fetcher, values),
...props,
});
}
export function useAuthResetPassword(
props?: UseMutationOptions<
unknown,
Error,
[token: string, values: AuthResetPasswordBody]
>
) {
const fetcher = useAuthApiFetcher();
return useMutation({
mutationFn: ([token, values]: [string, AuthResetPasswordBody]) =>
resetPassword(fetcher, token, values),
...props,
});
}
export function useAuthMetadata(
props?: Omit<
UseQueryOptions<AuthMetaResponse, Error>,
'queryKey' | 'queryFn'
>
) {
const fetcher = useAuthApiFetcher();
return useQuery({
queryKey: [t.AUTH_METADATA_PAGE],
queryFn: () => fetchAuthMeta(fetcher),
...props,
});
}
export function useAuthSignUpVerifyResendMail(
props?: UseMutationOptions<void, Error, void>
) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: () => resendSignupConfirm(fetcher),
...props,
});
}
export function useAuthSignUpVerify(
props?: UseMutationOptions<unknown, Error, AuthSignupVerifyBody>
) {
const fetcher = useAuthApiFetcher();
return useMutation({
mutationFn: (values: AuthSignupVerifyBody) =>
signupConfirm(fetcher, values),
...props,
});
}
@@ -1,91 +1,58 @@
// @ts-nocheck
import {
UseMutationOptions,
UseMutationResult,
useQueryClient,
useMutation,
} from 'react-query';
import useApiRequest from '../useRequest';
} from '@tanstack/react-query';
import {
pauseBankAccount,
resumeBankAccount,
type PauseBankAccountParams,
type ResumeBankAccountParams,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import t from './types';
type PuaseFeedsBankAccountValues = { bankAccountId: number };
interface PuaseFeedsBankAccountResponse {}
/** Mutation variables for pause (hook uses bankAccountId for the API id). */
type PauseFeedsBankAccountValues = { bankAccountId: PauseBankAccountParams['id'] };
/**
* Resumes the feeds syncing of the bank account.
* @param {UseMutationResult<PuaseFeedsBankAccountResponse, Error, ExcludeBankTransactionValue>} options
* @returns {UseMutationResult<PuaseFeedsBankAccountResponse, Error, ExcludeBankTransactionValue>}
* Pauses the feeds syncing of the bank account.
*/
export function usePauseFeedsBankAccount(
options?: UseMutationOptions<
PuaseFeedsBankAccountResponse,
Error,
PuaseFeedsBankAccountValues
>,
): UseMutationResult<
PuaseFeedsBankAccountResponse,
Error,
PuaseFeedsBankAccountValues
> {
options?: UseMutationOptions<void, Error, PauseFeedsBankAccountValues>,
): UseMutationResult<void, Error, PauseFeedsBankAccountValues> {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation<
PuaseFeedsBankAccountResponse,
Error,
PuaseFeedsBankAccountValues
>(
(values) =>
apiRequest.post(
`/banking/accounts/${values.bankAccountId}/pause`,
),
{
onSuccess: (res, values) => {
queryClient.invalidateQueries([t.ACCOUNT, values.bankAccountId]);
},
...options,
return useMutation({
mutationFn: (values: PauseFeedsBankAccountValues) =>
pauseBankAccount(fetcher, values.bankAccountId),
onSuccess: (_res, values) => {
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT, values.bankAccountId] });
},
);
...options,
});
}
type ResumeFeedsBankAccountValues = { bankAccountId: number };
interface ResumeFeedsBankAccountResponse {}
/** Mutation variables for resume (hook uses bankAccountId for the API id). */
type ResumeFeedsBankAccountValues = { bankAccountId: ResumeBankAccountParams['id'] };
/**
* Resumes the feeds syncing of the bank account.
* @param {UseMutationResult<ResumeFeedsBankAccountResponse, Error, ResumeFeedsBankAccountValues>} options
* @returns {UseMutationResult<ResumeFeedsBankAccountResponse, Error, ResumeFeedsBankAccountValues>}
*/
export function useResumeFeedsBankAccount(
options?: UseMutationOptions<
ResumeFeedsBankAccountResponse,
Error,
ResumeFeedsBankAccountValues
>,
): UseMutationResult<
ResumeFeedsBankAccountResponse,
Error,
ResumeFeedsBankAccountValues
> {
options?: UseMutationOptions<void, Error, ResumeFeedsBankAccountValues>,
): UseMutationResult<void, Error, ResumeFeedsBankAccountValues> {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation<
ResumeFeedsBankAccountResponse,
Error,
ResumeFeedsBankAccountValues
>(
(values) =>
apiRequest.post(
`/banking/bank_accounts/${values.bankAccountId}/resume_feeds`,
),
{
onSuccess: (res, values) => {
queryClient.invalidateQueries([t.ACCOUNT, values.bankAccountId]);
},
...options,
return useMutation({
mutationFn: (values: ResumeFeedsBankAccountValues) =>
resumeBankAccount(fetcher, values.bankAccountId),
onSuccess: (_res, values) => {
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT, values.bankAccountId] });
},
);
...options,
});
}
File diff suppressed because it is too large Load Diff
@@ -1,28 +1,27 @@
// @ts-nocheck
import { useQuery, UseQueryOptions, UseQueryResult } from 'react-query';
import useApiRequest from '../useRequest';
import {
useQuery,
UseQueryOptions,
UseQueryResult,
} from '@tanstack/react-query';
import { fetchPendingTransactions } from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { BANK_QUERY_KEY } from '@/constants/query-keys/banking';
interface GetBankRuleRes {}
export type PendingBankAccountTransactionsResponse = Awaited<
ReturnType<typeof fetchPendingTransactions>
>;
/**
* Retrieve the given bank rule.
* @param {number} bankRuleId -
* @param {UseQueryOptions<GetBankRuleRes, Error>} options -
* @returns {UseQueryResult<GetBankRuleRes, Error>}
* Retrieve pending bank account transactions.
*/
export function usePendingBankAccountTransactions(
bankRuleId: number,
options?: UseQueryOptions<GetBankRuleRes, Error>,
): UseQueryResult<GetBankRuleRes, Error> {
const apiRequest = useApiRequest();
options?: UseQueryOptions<PendingBankAccountTransactionsResponse, Error>,
): UseQueryResult<PendingBankAccountTransactionsResponse, Error> {
const fetcher = useApiFetcher();
return useQuery<GetBankRuleRes, Error>(
[BANK_QUERY_KEY.PENDING_BANK_ACCOUNT_TRANSACTIONS],
() =>
apiRequest
.get(`/banking/bank_account/pending_transactions`)
.then((res) => res.data),
{ ...options },
);
return useQuery({
queryKey: [BANK_QUERY_KEY.PENDING_BANK_ACCOUNT_TRANSACTIONS],
queryFn: () => fetchPendingTransactions(fetcher),
...options,
});
}
@@ -1,65 +1,43 @@
// @ts-nocheck
import {
useMutation,
UseMutationOptions,
UseMutationResult,
useQueryClient,
} from 'react-query';
import useApiRequest from '../useRequest';
} from '@tanstack/react-query';
import { uncategorizeTransactionsBulk } from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { BANK_QUERY_KEY } from '@/constants/query-keys/banking';
import t from './types';
type UncategorizeTransactionsBulkValues = { ids: Array<number> };
interface UncategorizeBankTransactionsBulkResponse {}
export type UncategorizeTransactionsBulkValues = { ids: number[] };
/**
* Uncategorize the given categorized transactions in bulk.
* @param {UseMutationResult<PuaseFeedsBankAccountResponse, Error, ExcludeBankTransactionValue>} options
* @returns {UseMutationResult<PuaseFeedsBankAccountResponse, Error, ExcludeBankTransactionValue>}
* Uncategorize the given categorized bank transactions in bulk (via DELETE /api/banking/categorize/bulk).
*/
export function useUncategorizeTransactionsBulkAction(
options?: UseMutationOptions<
UncategorizeBankTransactionsBulkResponse,
Error,
UncategorizeTransactionsBulkValues
>,
): UseMutationResult<
UncategorizeBankTransactionsBulkResponse,
Error,
UncategorizeTransactionsBulkValues
> {
options?: UseMutationOptions<void, Error, UncategorizeTransactionsBulkValues>,
): UseMutationResult<void, Error, UncategorizeTransactionsBulkValues> {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation<
UncategorizeBankTransactionsBulkResponse,
Error,
UncategorizeTransactionsBulkValues
>(
(value) =>
apiRequest.post(`/cashflow/transactions/uncategorize/bulk`, {
ids: value.ids,
}),
{
onSuccess: (res, values) => {
// Invalidate the account uncategorized transactions.
queryClient.invalidateQueries(
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
);
// Invalidate the account transactions.
queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
// Invalidate bank account summary.
queryClient.invalidateQueries(BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META);
// Invalidate the recognized transactions.
queryClient.invalidateQueries([
BANK_QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY,
]);
// Invalidate the account.
queryClient.invalidateQueries(t.ACCOUNT);
},
...options,
return useMutation({
mutationFn: (values: UncategorizeTransactionsBulkValues) =>
uncategorizeTransactionsBulk(fetcher, values.ids),
onSuccess: (_res, _values) => {
queryClient.invalidateQueries({
queryKey: [t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY],
});
queryClient.invalidateQueries({
queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY],
});
queryClient.invalidateQueries({
queryKey: [BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META],
});
queryClient.invalidateQueries({
queryKey: [BANK_QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY],
});
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
},
);
...options,
});
}
+196 -200
View File
@@ -1,249 +1,245 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type {
Bill,
BillsListResponse,
CreateBillBody,
EditBillBody,
GetBillsQuery,
BulkDeleteBillsBody,
} from '@bigcapital/sdk-ts';
import {
fetchBills,
fetchBill,
createBill,
editBill,
deleteBill,
openBill,
bulkDeleteBills,
validateBulkDeleteBills,
fetchDueBills,
fetchBillPaymentTransactions,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { transformPagination } from '@/utils';
import useApiRequest from '../useRequest';
import t from './types';
const commonInvalidateQueries = (queryClient) => {
// Invalidate bills.
queryClient.invalidateQueries(t.BILLS);
// Invalidate items.
queryClient.invalidateQueries(t.ITEMS);
queryClient.invalidateQueries(t.ITEM);
// Invalidate vendors.
queryClient.invalidateQueries([t.VENDORS]);
queryClient.invalidateQueries(t.VENDOR);
// Invalidate accounts.
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
// Invalidate landed cost.
queryClient.invalidateQueries(t.LANDED_COST);
queryClient.invalidateQueries(t.LANDED_COST_TRANSACTION);
// Invalidate reconcile.
queryClient.invalidateQueries(t.RECONCILE_VENDOR_CREDIT);
queryClient.invalidateQueries(t.RECONCILE_VENDOR_CREDITS);
// Invalidate financial reports.
queryClient.invalidateQueries(t.FINANCIAL_REPORT);
// Invalidate the transactions by reference.
queryClient.invalidateQueries(t.TRANSACTIONS_BY_REFERENCE);
// Invalidate items associated bills transactions.
queryClient.invalidateQueries(t.ITEMS_ASSOCIATED_WITH_BILLS);
// Invalidate item warehouses.
queryClient.invalidateQueries(t.ITEM_WAREHOUSES_LOCATION);
// Invalidate mutate base currency abilities.
queryClient.invalidateQueries(t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES);
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.BILLS] });
queryClient.invalidateQueries({ queryKey: [t.ITEMS] });
queryClient.invalidateQueries({ queryKey: [t.ITEM] });
queryClient.invalidateQueries({ queryKey: [t.VENDORS] });
queryClient.invalidateQueries({ queryKey: [t.VENDOR] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
queryClient.invalidateQueries({ queryKey: [t.LANDED_COST] });
queryClient.invalidateQueries({ queryKey: [t.LANDED_COST_TRANSACTION] });
queryClient.invalidateQueries({ queryKey: [t.RECONCILE_VENDOR_CREDIT] });
queryClient.invalidateQueries({ queryKey: [t.RECONCILE_VENDOR_CREDITS] });
queryClient.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
queryClient.invalidateQueries({ queryKey: [t.TRANSACTIONS_BY_REFERENCE] });
queryClient.invalidateQueries({ queryKey: [t.ITEMS_ASSOCIATED_WITH_BILLS] });
queryClient.invalidateQueries({ queryKey: [t.ITEM_WAREHOUSES_LOCATION] });
queryClient.invalidateQueries({
queryKey: [t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES],
});
};
/**
* Creates a new sale invoice.
*/
export function useCreateBill(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
export type BillsListResult = {
bills: unknown[];
pagination: ReturnType<typeof transformPagination>;
filterMeta: Record<string, unknown>;
};
return useMutation((values) => apiRequest.post('bills', values), {
onSuccess: (res, values) => {
// Common invalidate queries.
export function useCreateBill(
props?: UseMutationOptions<void, Error, CreateBillBody>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreateBillBody) => createBill(fetcher, values),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useEditBill(
props?: UseMutationOptions<void, Error, [number, EditBillBody]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, EditBillBody]) =>
editBill(fetcher, id, values),
onSuccess: (_data, [id]) => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.BILL, id] });
},
...props,
});
}
/**
* Edits the given sale invoice.
*/
export function useEditBill(props) {
export function useOpenBill(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
([id, values]) => apiRequest.put(`bills/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate bill query.
queryClient.invalidateQueries([t.BILL, id]);
},
...props,
},
);
}
/**
* Marks the given bill as open.
*/
export function useOpenBill(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.patch(`bills/${id}/open`), {
onSuccess: (res, id) => {
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => openBill(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(queryClient);
// Invalidate bill query.
queryClient.invalidateQueries([t.BILL, id]);
queryClient.invalidateQueries({ queryKey: [t.BILL, id] });
},
...props,
});
}
/**
* Deletes the given sale invoice.
*/
export function useDeleteBill(props) {
export function useDeleteBill(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.delete(`bills/${id}`), {
onSuccess: (res, id) => {
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => deleteBill(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(queryClient);
// Invalidate bill query.
queryClient.invalidateQueries([t.BILL, id]);
queryClient.invalidateQueries({ queryKey: [t.BILL, id] });
},
...props,
});
}
/**
* Deletes multiple bills in bulk.
*/
export function useBulkDeleteBills(props) {
export type BulkDeleteBillsPayload = { ids: number[]; skipUndeletable?: boolean };
function toBulkDeleteBody(payload: BulkDeleteBillsPayload): BulkDeleteBillsBody {
return {
ids: payload.ids,
skipUndeletable: payload.skipUndeletable ?? false,
};
}
export function useBulkDeleteBills(
props?: UseMutationOptions<void, Error, BulkDeleteBillsPayload>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
(ids: number[]) => apiRequest.post('bills/bulk-delete', { ids }),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
return useMutation({
mutationFn: (payload: BulkDeleteBillsPayload) =>
bulkDeleteBills(fetcher, toBulkDeleteBody(payload)),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useValidateBulkDeleteBills(props) {
const apiRequest = useApiRequest();
/** Response shape from bills validate-bulk-delete endpoint (see ValidateBulkDeleteResponseDto) */
export type ValidateBulkDeleteBillsResponse = {
deletableCount: number;
nonDeletableCount: number;
deletableIds: number[];
nonDeletableIds: number[];
};
return useMutation(
(ids: number[]) =>
apiRequest
.post('bills/validate-bulk-delete', { ids })
.then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
export function useValidateBulkDeleteBills(
props?: UseMutationOptions<ValidateBulkDeleteBillsResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeleteBills(fetcher, { ids, skipUndeletable: false }),
...props,
});
}
const transformBillsResponse = (response) => ({
bills: response.data.bills,
pagination: transformPagination(response.data.pagination),
filterMeta: response.data.filter_meta,
});
/** API may return bills/data, pagination, and filter_meta (snake_case). */
type BillsListResponseShape = {
bills?: unknown[];
data?: unknown[];
pagination?: unknown;
filter_meta?: Record<string, unknown>;
};
/**
* Retrieve sale invoices list with pagination meta.
*/
export function useBills(query, props) {
return useRequestQuery(
[t.BILLS, query],
{
method: 'get',
url: 'bills',
params: query,
},
{
select: transformBillsResponse,
defaultData: {
bills: [],
pagination: {
page: 1,
page_size: 12,
total: 0,
},
filterMeta: {},
},
...props,
},
);
function isRecord(obj: unknown): obj is Record<string, unknown> {
return typeof obj === 'object' && obj !== null && !Array.isArray(obj);
}
/**
* Retrieve bill details of the given bill id.
* @param {number} id - Bill id.
*/
export function useBill(id, props) {
return useRequestQuery(
[t.BILL, id],
{ method: 'get', url: `/bills/${id}` },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
function transformBillsList(res: BillsListResponse & BillsListResponseShape): BillsListResult {
const bills = res.bills ?? res.data ?? [];
const pagination = res.pagination ?? {};
const filterMeta = res.filter_meta;
return {
bills: Array.isArray(bills) ? bills : [],
pagination: transformPagination(pagination),
filterMeta: isRecord(filterMeta) ? filterMeta : {},
};
}
export function useBills(
query?: GetBillsQuery,
props?: Omit<UseQueryOptions<BillsListResult>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.BILLS, query],
queryFn: () => fetchBills(fetcher, query).then(transformBillsList),
...props,
});
}
/**
* Retrieve the due bills of the given vendor id.
* @param {number} vendorId -
*/
export function useDueBills(vendorId, props) {
return useRequestQuery(
[t.BILLS, t.BILLS_DUE, vendorId],
{
method: 'get',
url: 'bills/due',
params: { vendor_id: vendorId },
},
{
select: (res) => res.data.bills,
defaultData: [],
...props,
},
);
export function useBill(
id: number | null | undefined,
props?: Omit<UseQueryOptions<Bill>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.BILL, id],
queryFn: () => fetchBill(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useDueBills(
vendorId: number | null | undefined,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.BILLS, t.BILLS_DUE, vendorId],
queryFn: () =>
fetchDueBills(fetcher, vendorId != null ? { vendor_id: vendorId } : undefined),
select: (data) => data ?? [],
enabled: true,
...props,
});
}
export function useRefreshBills() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries(t.BILLS);
},
refresh: () => queryClient.invalidateQueries({ queryKey: [t.BILLS] }),
};
}
export function useBillPaymentTransactions(id, props) {
return useRequestQuery(
[t.BILLS_PAYMENT_TRANSACTIONS, id],
{
method: 'get',
url: `bills/${id}/payment-transactions`,
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
export function useBillPaymentTransactions(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.BILLS_PAYMENT_TRANSACTIONS, id],
queryFn: () => fetchBillPaymentTransactions(fetcher, id!),
select: (data) => data ?? [],
enabled: id != null,
...props,
});
}
+101 -106
View File
@@ -1,135 +1,130 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type {
Branch,
BranchesListResponse,
CreateBranchBody,
EditBranchBody,
} from '@bigcapital/sdk-ts';
import {
fetchBranches,
fetchBranch,
createBranch,
editBranch,
deleteBranch,
activateBranches,
markBranchAsPrimary,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import t from './types';
// Common invalidate queries.
const commonInvalidateQueries = (queryClient) => {
// Invalidate warehouses.
queryClient.invalidateQueries(t.BRANCHES);
queryClient.invalidateQueries(t.BRANCH);
queryClient.invalidateQueries(t.DASHBOARD_META);
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.BRANCHES] });
queryClient.invalidateQueries({ queryKey: [t.BRANCH] });
queryClient.invalidateQueries({ queryKey: [t.DASHBOARD_META] });
};
/**
* Create a new branch.
*/
export function useCreateBranch(props) {
export function useCreateBranch(
props?: UseMutationOptions<void, Error, CreateBranchBody>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((values) => apiRequest.post('branches', values), {
onSuccess: (res, values) => {
// Common invalidate queries.
return useMutation({
mutationFn: (values: CreateBranchBody) => createBranch(fetcher, values),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useEditBranch(
props?: UseMutationOptions<void, Error, [number | string, EditBranchBody]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number | string, EditBranchBody]) =>
editBranch(fetcher, String(id), values),
onSuccess: (_data, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.BRANCH, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Edits the given branch.
*/
export function useEditBranch(props) {
export function useDeleteBranch(
props?: UseMutationOptions<void, Error, number | string>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
([id, values]) => apiRequest.put(`branches/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate specific branch.
queryClient.invalidateQueries([t.BRANCH, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
/**
* Deletes the given branch.
*/
export function useDeleteBranch(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`branches/${id}`), {
onSuccess: (res, id) => {
// Invalidate specific branch.
queryClient.invalidateQueries([t.BRANCH, id]);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number | string) => deleteBranch(fetcher, String(id)),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.BRANCH, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Retrieve Branches list.
*/
export function useBranches(query, props) {
return useRequestQuery(
[t.BRANCHES, query],
{ method: 'get', url: 'branches', params: query },
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
export function useBranches(
query?: Record<string, unknown>,
props?: Omit<UseQueryOptions<BranchesListResponse>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.BRANCHES, query],
queryFn: () => fetchBranches(fetcher),
select: (data: BranchesListResponse) => data,
...props,
});
}
/**
* Retrieve the branch details.
* @param {number}
*/
export function useBranch(id, props, requestProps) {
return useRequestQuery(
[t.BRANCH, id],
{ method: 'get', url: `branches/${id}`, ...requestProps },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
export function useBranch(
id: number | string | null | undefined,
props?: Omit<UseQueryOptions<Branch>, 'queryKey' | 'queryFn'>,
_requestProps?: Record<string, unknown>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.BRANCH, id],
queryFn: () => fetchBranch(fetcher, String(id!)),
enabled: id != null,
...props,
});
}
/**
* Activate the given branches.
*/
export function useActivateBranches(props) {
export function useActivateBranches(
props?: UseMutationOptions<void, Error, number | string>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.post(`branches/activate`), {
onSuccess: (res, id) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Mark primary the given branch.
*/
export function useMarkBranchAsPrimary(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.post(`branches/${id}/mark-primary`), {
onSuccess: (res, id) => {
// Invalidate specific inventory adjustment.
queryClient.invalidateQueries([t.BRANCH, id]);
const fetcher = useApiFetcher();
return useMutation({
mutationFn: () => activateBranches(fetcher),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useMarkBranchAsPrimary(
props?: UseMutationOptions<void, Error, number | string>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number | string) => markBranchAsPrimary(fetcher, String(id)),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.BRANCH, id] });
commonInvalidateQueries(queryClient);
},
...props,
@@ -0,0 +1,265 @@
import { useMutation, useQueryClient, useInfiniteQuery, useQuery } from '@tanstack/react-query';
import { useApiFetcher } from '../useRequest';
import t from './types';
import { BANK_QUERY_KEY } from '@/constants/query-keys/banking';
import { fetchBankingAccounts } from '@bigcapital/sdk-ts';
import {
fetchBankingTransactions,
getBankingTransaction,
createBankingTransaction,
deleteBankingTransaction,
fetchUncategorizedTransactions,
getUncategorizedTransaction,
categorizeTransaction,
uncategorizeTransaction,
type GetBankingTransactionsQuery,
type GetUncategorizedTransactionsQuery,
type CreateBankingTransactionBody,
type CategorizeTransactionBody,
} from '../../../../../shared/sdk-ts/src/cashflow-accounts';
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.SETTING, t.SETTING_CASHFLOW] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT_TRANSACTION] });
queryClient.invalidateQueries({ queryKey: [t.CASH_FLOW_ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.CASH_FLOW_TRANSACTIONS] });
queryClient.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY] });
queryClient.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
queryClient.invalidateQueries({ queryKey: [t.CASH_FLOW_TRANSACTION] });
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES] });
};
/** Normalize hook query (snake_case) to API query (camelCase). */
function normalizeTransactionsQuery(
accountId: number,
page: number,
query: Record<string, unknown> = {}
): GetBankingTransactionsQuery {
return {
page,
pageSize: (query.page_size as number) ?? 50,
accountId: (query.account_id as number) ?? accountId,
};
}
/** Normalize hook query (snake_case) to API query (camelCase). */
function normalizeUncategorizedQuery(
page: number,
query: Record<string, unknown> = {}
): GetUncategorizedTransactionsQuery {
const q: GetUncategorizedTransactionsQuery = {
page,
pageSize: (query.page_size as number) ?? 50,
};
if (query.min_date != null) q.minDate = query.min_date as string;
if (query.max_date != null) q.maxDate = query.max_date as string;
return q;
}
/**
* Retrieve accounts list.
*/
export function useCashflowAccounts(query?: Record<string, unknown>, props?: object) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.CASH_FLOW_ACCOUNTS, query],
queryFn: () => fetchBankingAccounts(fetcher),
...props,
});
}
/**
* Create Money in owner contribution.
*/
export function useCreateCashflowTransaction(props?: object) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreateBankingTransactionBody) =>
createBankingTransaction(fetcher, values),
onSuccess: () => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: ['BANK_TRANSACTION_MATCHES'] });
},
...props,
});
}
/**
* Retrieve account transactions list.
*/
export function useCashflowTransaction(id: string | number | null | undefined, props?: object) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.CASH_FLOW_TRANSACTIONS, id],
queryFn: () => getBankingTransaction(fetcher, id!),
enabled: id != null,
select: (data) => data ?? [],
...props,
});
}
/**
* Deletes the given cashflow transaction.
*/
export function useDeleteCashflowTransaction(props?: object) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: string | number) => deleteBankingTransaction(fetcher, id),
onSuccess: (_res, _id) => {
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Retrieve account transactions with infinite scrolling.
*/
export function useAccountTransactionsInfinity(
accountId: number,
query: Record<string, unknown> = {},
infinityProps?: object
) {
const fetcher = useApiFetcher();
type Page = { transactions?: unknown[]; pagination: { page: number; pageSize: number; total: number } };
return useInfiniteQuery({
queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY, accountId, query],
initialPageParam: 1,
queryFn: async ({ pageParam }) => {
const apiQuery = normalizeTransactionsQuery(accountId, pageParam as number, query);
const response = await fetchBankingTransactions(fetcher, apiQuery);
return response as Page;
},
getPreviousPageParam: (firstPage: Page) => firstPage.pagination?.page - 1,
getNextPageParam: (lastPage: Page) => {
const { pagination } = lastPage;
if (!pagination) return undefined;
return pagination.total > pagination.pageSize * pagination.page
? pagination.page + 1
: undefined;
},
...infinityProps,
});
}
/**
* Retrieve uncategorized account transactions with infinite scrolling.
*/
export function useAccountUncategorizedTransactionsInfinity(
accountId: number,
query: Record<string, unknown> = {},
infinityProps?: object
) {
const fetcher = useApiFetcher();
type UncategorizedPage = { data?: unknown[]; pagination: { page: number; pageSize: number; total: number } };
return useInfiniteQuery({
queryKey: [t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY, accountId, query],
initialPageParam: 1,
queryFn: async ({ pageParam }) => {
const apiQuery = normalizeUncategorizedQuery(pageParam as number, query);
return fetchUncategorizedTransactions(fetcher, accountId, apiQuery);
},
getPreviousPageParam: (firstPage: UncategorizedPage) => firstPage.pagination?.page - 1,
getNextPageParam: (lastPage: UncategorizedPage) => {
const { pagination } = lastPage;
if (!pagination) return undefined;
return pagination.total > pagination.pageSize * pagination.page
? pagination.page + 1
: undefined;
},
...infinityProps,
});
}
/**
* Refresh cashflow accounts.
*/
export function useRefreshCashflowAccounts() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries({ queryKey: [t.CASH_FLOW_ACCOUNTS] });
},
};
}
/**
* Refresh the cashflow account transactions.
*/
export function useRefreshCashflowTransactions() {
const query = useQueryClient();
return {
refresh: (accountId: number) => {
query.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY] });
query.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY] });
query.invalidateQueries({ queryKey: [BANK_QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY] });
query.invalidateQueries({ queryKey: [BANK_QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY] });
query.invalidateQueries({ queryKey: [BANK_QUERY_KEY.PENDING_BANK_ACCOUNT_TRANSACTIONS_INFINITY] });
query.invalidateQueries({ queryKey: [BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META, accountId] });
query.invalidateQueries({ queryKey: [t.ACCOUNT, accountId] });
},
};
}
/**
* Retrieves specific uncategorized transaction.
*/
export function useUncategorizedTransaction(
uncategorizedTransactionId: number | null | undefined,
props?: object
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.CASHFLOW_UNCAATEGORIZED_TRANSACTION, uncategorizedTransactionId],
queryFn: () => getUncategorizedTransaction(fetcher, uncategorizedTransactionId!),
enabled: uncategorizedTransactionId != null,
select: (data) => (data as { data?: unknown })?.data ?? data,
...props,
});
}
/**
* Categorize the cashflow transaction.
*/
export function useCategorizeTransaction(props?: object) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CategorizeTransactionBody) => categorizeTransaction(fetcher, values),
onSuccess: () => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.CASHFLOW_UNCAATEGORIZED_TRANSACTION] });
queryClient.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY] });
queryClient.invalidateQueries({ queryKey: ['BANK_ACCOUNT_SUMMARY_META'] });
},
...props,
});
}
/**
* Uncategorize the cashflow transaction.
*/
export function useUncategorizeTransaction(props?: object) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => uncategorizeTransaction(fetcher, id),
onSuccess: () => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.CASHFLOW_UNCAATEGORIZED_TRANSACTION] });
queryClient.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY] });
queryClient.invalidateQueries({ queryKey: ['BANK_ACCOUNT_SUMMARY_META'] });
},
...props,
});
}
@@ -1,292 +0,0 @@
// @ts-nocheck
import { useMutation, useQueryClient, useInfiniteQuery } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import t from './types';
import { BANK_QUERY_KEY } from '@/constants/query-keys/banking';
const commonInvalidateQueries = (queryClient) => {
// Invalidate settings.
queryClient.invalidateQueries([t.SETTING, t.SETTING_CASHFLOW]);
// Invalidate accounts.
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
// Invalidate account transactions.
queryClient.invalidateQueries(t.ACCOUNT_TRANSACTION);
// Invalidate cashflow accounts.
queryClient.invalidateQueries(t.CASH_FLOW_ACCOUNTS);
// Invalidate the cashflow transactions.
queryClient.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
// Invalidate financial reports.
queryClient.invalidateQueries(t.FINANCIAL_REPORT);
queryClient.invalidateQueries(t.CASH_FLOW_TRANSACTION);
// Invalidate mutate base currency abilities.
queryClient.invalidateQueries(t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES);
};
/**
* Retrieve accounts list.
*/
export function useCashflowAccounts(query, props) {
return useRequestQuery(
[t.CASH_FLOW_ACCOUNTS, query],
{ method: 'get', url: 'banking/accounts', params: query },
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
}
/**
* Create Money in owner contribution .
*/
export function useCreateCashflowTransaction(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(values) => apiRequest.post('banking/transactions', values),
{
onSuccess: () => {
// Invalidate queries.
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries('BANK_TRANSACTION_MATCHES');
},
...props,
},
);
}
/**
* Retrieve account transactions list.
*/
export function useCashflowTransaction(id, props) {
return useRequestQuery(
[t.CASH_FLOW_TRANSACTIONS, id],
{ method: 'get', url: `banking/transactions/${id}` },
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
}
/**
* Deletes the given sale invoice.
*/
export function useDeleteCashflowTransaction(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`banking/transactions/${id}`), {
onSuccess: (res, id) => {
// Invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Retrieve account transactions infinity scrolling.
* @param {number} accountId
* @param {*} axios
* @returns
*/
export function useAccountTransactionsInfinity(
accountId,
query,
infinityProps,
axios,
) {
const apiRequest = useApiRequest();
return useInfiniteQuery(
[t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY, accountId],
async ({ pageParam = 1 }) => {
const response = await apiRequest.http({
...axios,
method: 'get',
url: `/api/banking/transactions`,
params: { page: pageParam, ...query },
});
return response.data;
},
{
getPreviousPageParam: (firstPage) => firstPage.pagination.page - 1,
getNextPageParam: (lastPage) => {
const { pagination } = lastPage;
return pagination.total > pagination.page_size * pagination.page
? lastPage.pagination.page + 1
: undefined;
},
...infinityProps,
},
);
}
/**
* Retrieve account transactions infinity scrolling.
* @param {number} accountId
* @param {*} axios
* @returns
*/
export function useAccountUncategorizedTransactionsInfinity(
accountId,
query,
infinityProps,
axios,
) {
const apiRequest = useApiRequest();
return useInfiniteQuery(
[t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY, accountId, query],
async ({ pageParam = 1 }) => {
const response = await apiRequest.http({
...axios,
method: 'get',
url: `/api/banking/uncategorized/accounts/${accountId}`,
params: { page: pageParam, ...query },
});
return response.data;
},
{
getPreviousPageParam: (firstPage) => firstPage.pagination.page - 1,
getNextPageParam: (lastPage) => {
const { pagination } = lastPage;
return pagination.total > pagination.page_size * pagination.page
? lastPage.pagination.page + 1
: undefined;
},
...infinityProps,
},
);
}
/**
* Refresh cashflow accounts.
*/
export function useRefreshCashflowAccounts() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries(t.CASH_FLOW_ACCOUNTS);
},
};
}
/**
* Refresh the cshflow account transactions.
*/
export function useRefreshCashflowTransactions() {
const query = useQueryClient();
return {
refresh: (accountId: number) => {
query.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
query.invalidateQueries(
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
);
query.invalidateQueries(
BANK_QUERY_KEY.RECOGNIZED_BANK_TRANSACTIONS_INFINITY,
);
query.invalidateQueries(
BANK_QUERY_KEY.EXCLUDED_BANK_TRANSACTIONS_INFINITY,
);
query.invalidateQueries(
BANK_QUERY_KEY.PENDING_BANK_ACCOUNT_TRANSACTIONS_INFINITY,
);
query.invalidateQueries([
BANK_QUERY_KEY.BANK_ACCOUNT_SUMMARY_META,
accountId,
]);
query.invalidateQueries([t.ACCOUNT, accountId]);
},
};
}
/**
* Retrieves specific uncategorized transaction.
* @param {number} uncategorizedTranasctionId -
*/
export function useUncategorizedTransaction(
uncategorizedTranasctionId: nunber,
props,
) {
return useRequestQuery(
[t.CASHFLOW_UNCAATEGORIZED_TRANSACTION, uncategorizedTranasctionId],
{
method: 'get',
url: `banking/uncategorized/${uncategorizedTranasctionId}`,
},
{
select: (res) => res.data?.data,
...props,
},
);
}
/**
* Categorize the cashflow transaction.
*/
export function useCategorizeTransaction(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(values) => apiRequest.post(`banking/categorize`, values),
{
onSuccess: (res, id) => {
// Invalidate queries.
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries(t.CASHFLOW_UNCAATEGORIZED_TRANSACTION);
queryClient.invalidateQueries(
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
);
// Invalidate bank account summary.
queryClient.invalidateQueries('BANK_ACCOUNT_SUMMARY_META');
},
...props,
},
);
}
/**
* Uncategorize the cashflow transaction.
*/
export function useUncategorizeTransaction(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(id: number) => apiRequest.delete(`banking/categorize/${id}`),
{
onSuccess: (res, id) => {
// Invalidate queries.
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries(t.CASHFLOW_UNCAATEGORIZED_TRANSACTION);
queryClient.invalidateQueries(
t.CASHFLOW_ACCOUNT_UNCATEGORIZED_TRANSACTIONS_INFINITY,
);
// Invalidate bank account summary.
queryClient.invalidateQueries('BANK_ACCOUNT_SUMMARY_META');
},
...props,
},
);
}
+64 -49
View File
@@ -1,63 +1,78 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import useApiRequest from '../useRequest';
import { useQueryTenant } from '../useQueryRequest';
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import { castArray } from 'lodash';
import {
fetchContact,
fetchContactsAutoComplete,
activateContact,
inactivateContact,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { useAuthOrganizationId } from '../state';
import t from './types';
// Common invalidate queries.
const commonInvalidateQueries = (queryClient) => {
// Invalidate vendors.
queryClient.invalidateQueries(t.VENDORS);
// Invalidate customers.
queryClient.invalidateQueries(t.CUSTOMERS);
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.VENDORS] });
queryClient.invalidateQueries({ queryKey: [t.CUSTOMERS] });
};
/**
* Retrieve the contact duplicate.
*/
export function useContact(id, props) {
const apiRequest = useApiRequest();
/** Contact (customer) payload returned for form/duplicate use */
type ContactData = Record<string, unknown>;
return useQueryTenant(
['CONTACT', id],
() => apiRequest.get(`contacts/${id}`),
{
select: (res) => res.data.customer,
...props,
},
);
/**
* Retrieve the contact by ID (for duplicate/form).
*/
export function useContact(
id: number | string | undefined | null,
props?: Omit<UseQueryOptions<ContactData>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
const organizationId = useAuthOrganizationId();
const contactId = id != null ? Number(id) : 0;
return useQuery({
queryKey: [...castArray(t.CONTACT), contactId, organizationId],
queryFn: () => fetchContact(fetcher, contactId),
enabled: contactId > 0,
...props,
});
}
/**
* Retrieve the auto-complete contacts.
*/
export function useAutoCompleteContacts(props) {
const apiRequest = useApiRequest();
export function useAutoCompleteContacts(
props?: Omit<UseQueryOptions<Awaited<ReturnType<typeof fetchContactsAutoComplete>>>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
const organizationId = useAuthOrganizationId();
return useQueryTenant(
['CONTACTS', 'AUTO-COMPLETE'],
() => apiRequest.get('contacts/auto-complete'),
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
return useQuery({
queryKey: [t.CONTACTS, 'AUTO-COMPLETE', organizationId],
queryFn: () => fetchContactsAutoComplete(fetcher),
...props,
});
}
/**
* Activate the given Contact.
*/
export function useActivateContact(props) {
export function useActivateContact(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.patch(`contacts/${id}/activate`), {
onSuccess: (res, id) => {
// Invalidate specific contact.
queryClient.invalidateQueries([t.CONTACT, id]);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => activateContact(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.CONTACT, id] });
commonInvalidateQueries(queryClient);
},
...props,
@@ -67,16 +82,16 @@ export function useActivateContact(props) {
/**
* Inactivate the given contact.
*/
export function useInactivateContact(props) {
export function useInactivateContact(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.patch(`contacts/${id}/inactivate`), {
onSuccess: (res, id) => {
// Invalidate specific item.
queryClient.invalidateQueries([t.CONTACT, id]);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => inactivateContact(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.CONTACT, id] });
commonInvalidateQueries(queryClient);
},
...props,
@@ -0,0 +1,417 @@
import {
useQueryClient,
useMutation,
useQuery,
UseMutationOptions,
UseQueryOptions,
UseQueryResult,
} from '@tanstack/react-query';
import type {
CreditNote,
CreateCreditNoteBody,
EditCreditNoteBody,
CreateRefundCreditNoteBody,
ApplyCreditNoteToInvoicesBody,
ValidateBulkDeleteCreditNotesResponse,
} from '@bigcapital/sdk-ts';
import type { CreditNotesListResponse } from '@bigcapital/sdk-ts';
import {
fetchCreditNotes,
fetchCreditNote,
createCreditNote,
editCreditNote,
deleteCreditNote,
openCreditNote,
validateBulkDeleteCreditNotes,
bulkDeleteCreditNotes,
createRefundCreditNote,
deleteRefundCreditNote,
applyCreditNoteToInvoices,
deleteApplyCreditNoteToInvoices,
} from '@bigcapital/sdk-ts';
import useApiRequest, { useApiFetcher } from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import { useRequestPdf } from '../useRequestPdf';
import { transformPagination, transformToCamelCase } from '@/utils';
import t from './types';
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
// Invalidate credit note.
queryClient.invalidateQueries({ queryKey: [t.CREDIT_NOTES] });
queryClient.invalidateQueries({ queryKey: [t.CREDIT_NOTE] });
// Invalidate items.
queryClient.invalidateQueries({ queryKey: [t.ITEMS] });
queryClient.invalidateQueries({ queryKey: [t.ITEM] });
// Invalidate customers.
queryClient.invalidateQueries({ queryKey: [t.CUSTOMER] });
queryClient.invalidateQueries({ queryKey: [t.CUSTOMERS] });
// Invalidate accounts.
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
// Invalidate settings.
queryClient.invalidateQueries({ queryKey: [t.SETTING, t.SETTING_CREDIT_NOTES] });
// Invalidate refund credit
queryClient.invalidateQueries({ queryKey: [t.REFUND_CREDIT_NOTE] });
queryClient.invalidateQueries({ queryKey: [t.REFUND_CREDIT_NOTE_TRANSACTION] });
// Invalidate reconcile.
queryClient.invalidateQueries({ queryKey: [t.RECONCILE_CREDIT_NOTE] });
queryClient.invalidateQueries({ queryKey: [t.RECONCILE_CREDIT_NOTES] });
// Invalidate invoices.
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICES] });
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICE] });
// Invalidate cashflow accounts.
queryClient.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY] });
// Invalidate financial reports.
queryClient.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
// Invalidate transactions by reference.
queryClient.invalidateQueries({ queryKey: [t.TRANSACTIONS_BY_REFERENCE] });
// Invalidate mutate base currency abilities.
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES] });
};
/**
* Create a new credit note.
*/
export function useCreateCreditNote(
props?: UseMutationOptions<void, Error, CreateCreditNoteBody>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreateCreditNoteBody) => createCreditNote(fetcher, values),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
/**
* Edit the given credit note.
*/
export function useEditCreditNote(
props?: UseMutationOptions<void, Error, [number, EditCreditNoteBody]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, EditCreditNoteBody]) =>
editCreditNote(fetcher, id, values),
onSuccess: (_data, [id]) => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.CREDIT_NOTE, id] });
},
...props,
});
}
/**
* Delete the given credit note.
*/
export function useDeleteCreditNote(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => deleteCreditNote(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.CREDIT_NOTE, id] });
},
...props,
});
}
export function useBulkDeleteCreditNotes(
props?: UseMutationOptions<void, Error, { ids: number[]; skipUndeletable?: boolean }>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) => bulkDeleteCreditNotes(fetcher, { ids, skipUndeletable }),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useValidateBulkDeleteCreditNotes(
props?: UseMutationOptions<ValidateBulkDeleteCreditNotesResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeleteCreditNotes(fetcher, { ids, skipUndeletable: false }).then(
(res) => transformToCamelCase(res as Record<string, unknown>) as ValidateBulkDeleteCreditNotesResponse
),
...props,
});
}
export type CreditNotesListResult = {
creditNotes: unknown[];
pagination: ReturnType<typeof transformPagination>;
filterMeta: Record<string, unknown>;
};
function transformCreditNotesList(res: CreditNotesListResponse): CreditNotesListResult {
const data = res as { credit_notes?: unknown[]; pagination?: unknown; filter_meta?: Record<string, unknown> };
return {
creditNotes: data?.credit_notes ?? [],
pagination: transformPagination(data?.pagination ?? {}),
filterMeta: data?.filter_meta ?? {},
};
}
/**
* Retrieve credit notes list with pagination meta.
*/
export function useCreditNotes(
query?: Record<string, unknown>,
props?: Omit<UseQueryOptions<CreditNotesListResult>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.CREDIT_NOTES, query],
queryFn: () =>
(fetchCreditNotes as (f: ReturnType<typeof useApiFetcher>, q?: Record<string, unknown>) => Promise<CreditNotesListResponse>)(
fetcher,
query
).then(transformCreditNotesList),
...props,
});
}
export function useCreditNote(
id: number | null | undefined,
props?: Omit<UseQueryOptions<CreditNote>, 'queryKey' | 'queryFn'>,
_requestProps?: Record<string, unknown>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.CREDIT_NOTE, id],
queryFn: () => fetchCreditNote(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useRefreshCreditNotes() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries({ queryKey: [t.CREDIT_NOTES] });
},
};
}
export function useCreateRefundCreditNote(
props?: UseMutationOptions<void, Error, [number, CreateRefundCreditNoteBody]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, CreateRefundCreditNoteBody]) =>
createRefundCreditNote(fetcher, id, values),
onSuccess: (_data, [id]) => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.CREDIT_NOTE, id] });
},
...props,
});
}
export function useDeleteRefundCreditNote(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (refundCreditId: number) => deleteRefundCreditNote(fetcher, refundCreditId),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
/**
* Retrieve refund credit note detail of the given id.
*/
export function useRefundCreditNote(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown>, 'queryKey' | 'queryFn'>,
requestProps?: Record<string, unknown>
) {
return useRequestQuery(
[t.REFUND_CREDIT_NOTE, id],
{ method: 'get', url: `credit-notes/${id}/refunds`, ...requestProps },
{
select: (res: { data?: unknown }) => res.data ?? {},
defaultData: {},
...props,
} as UseQueryOptions<unknown>
);
}
/**
* Mark the given credit note as opened.
*/
export function useOpenCreditNote(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => openCreditNote(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.CREDIT_NOTE, id] });
},
...props,
});
}
/**
* Retrieve reconcile credit note of the given id.
*/
export function useReconcileCreditNote(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>,
requestProps?: Record<string, unknown>
) {
return useRequestQuery(
[t.RECONCILE_CREDIT_NOTE, id],
{ method: 'get', url: `credit-notes/${id}/apply-invoices`, ...requestProps },
{
select: (res: { data?: unknown }) => (res.data as unknown[]) ?? [],
defaultData: [],
...props,
} as UseQueryOptions<unknown[]>
);
}
/**
* Create Reconcile credit note.
*/
export function useCreateReconcileCreditNote(
props?: UseMutationOptions<void, Error, [number, ApplyCreditNoteToInvoicesBody]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, ApplyCreditNoteToInvoicesBody]) =>
applyCreditNoteToInvoices(fetcher, id, values),
onSuccess: (_data, [id]) => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.CREDIT_NOTE, id] });
},
...props,
});
}
/**
* Retrieve reconcile credit notes (applied invoices).
*/
export function useReconcileCreditNotes(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown>, 'queryKey' | 'queryFn'>,
requestProps?: Record<string, unknown>
) {
return useRequestQuery(
[t.RECONCILE_CREDIT_NOTES, id],
{ method: 'get', url: `credit-notes/${id}/applied-invoices`, ...requestProps },
{
select: (res: { data?: unknown }) => res.data ?? {},
defaultData: {},
...props,
} as UseQueryOptions<unknown>
);
}
/**
* Delete the given reconcile credit note (applied invoice).
*/
export function useDeleteReconcileCredit(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (applyCreditToInvoicesId: number) =>
deleteApplyCreditNoteToInvoices(fetcher, applyCreditToInvoicesId),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
/**
* Retrieve refund credit transaction detail.
*/
export function useRefundCreditTransaction(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown>, 'queryKey' | 'queryFn'>,
requestProps?: Record<string, unknown>
) {
return useRequestQuery(
[t.REFUND_CREDIT_NOTE_TRANSACTION, id],
{ method: 'get', url: `credit-notes/refunds/${id}`, ...requestProps },
{
select: (res: { data?: unknown }) => res.data ?? {},
defaultData: {},
...props,
} as UseQueryOptions<unknown>
);
}
/**
* Retrieve the credit note pdf document data.
*/
export function usePdfCreditNote(creditNoteId: number | string) {
return useRequestPdf({ url: `credit-notes/${creditNoteId}` });
}
export interface CreditNoteStateResponse {
defaultTemplateId: number;
}
export function useGetCreditNoteState(
options?: UseQueryOptions<CreditNoteStateResponse, Error>
): UseQueryResult<CreditNoteStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<CreditNoteStateResponse, Error>({
queryKey: ['CREDIT_NOTE_STATE'],
queryFn: () =>
apiRequest
.get('/credit-notes/state')
.then((res: { data?: unknown }) =>
transformToCamelCase(res.data as Record<string, unknown>) as CreditNoteStateResponse
),
...options,
});
}
@@ -1,412 +0,0 @@
// @ts-nocheck
import { useQueryClient, useMutation, useQuery } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination, transformToCamelCase } from '@/utils';
import useApiRequest from '../useRequest';
import { useRequestPdf } from '../useRequestPdf';
import t from './types';
const commonInvalidateQueries = (queryClient) => {
// Invalidate credit note.
queryClient.invalidateQueries(t.CREDIT_NOTES);
queryClient.invalidateQueries(t.CREDIT_NOTE);
// Invalidate items.
queryClient.invalidateQueries(t.ITEMS);
queryClient.invalidateQueries(t.ITEM);
// Invalidate customers.
queryClient.invalidateQueries([t.CUSTOMER]);
queryClient.invalidateQueries(t.CUSTOMERS);
// Invalidate accounts.
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
// Invalidate settings.
queryClient.invalidateQueries([t.SETTING, t.SETTING_CREDIT_NOTES]);
// Invalidate refund credit
queryClient.invalidateQueries(t.REFUND_CREDIT_NOTE);
queryClient.invalidateQueries(t.REFUND_CREDIT_NOTE_TRANSACTION);
// Invalidate reconcile.
queryClient.invalidateQueries(t.RECONCILE_CREDIT_NOTE);
queryClient.invalidateQueries(t.RECONCILE_CREDIT_NOTES);
// Invalidate invoices.
queryClient.invalidateQueries(t.SALE_INVOICES);
queryClient.invalidateQueries(t.SALE_INVOICE);
// Invalidate cashflow accounts.
queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
// Invalidate financial reports.
queryClient.invalidateQueries(t.FINANCIAL_REPORT);
// Invalidate transactions by reference.
queryClient.invalidateQueries(t.TRANSACTIONS_BY_REFERENCE);
// Invalidate mutate base currency abilities.
queryClient.invalidateQueries(t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES);
};
/**
* Create a new credit note.
*/
export function useCreateCreditNote(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('credit-notes', values), {
onSuccess: (res, values) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Edit the given credit note.
*/
export function useEditCreditNote(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`credit-notes/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate credit note query.
queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
},
...props,
},
);
}
/**
* Delete the given credit note.
*/
export function useDeleteCreditNote(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`credit-notes/${id}`), {
onSuccess: (res, id) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate vendor credit query.
queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
},
...props,
});
}
/**
* Deletes multiple credit notes in bulk.
*/
export function useBulkDeleteCreditNotes(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('credit-notes/bulk-delete', {
ids,
skip_undeletable: skipUndeletable,
}),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export function useValidateBulkDeleteCreditNotes(props) {
const apiRequest = useApiRequest();
return useMutation(
(ids: number[]) =>
apiRequest
.post('credit-notes/validate-bulk-delete', { ids })
.then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
}
const transformCreditNotes = (res) => ({
creditNotes: res.data.credit_notes,
pagination: transformPagination(res.data.pagination),
filterMeta: res.data.filter_meta,
});
/**
* Retrieve credit notes list with pagination meta.
*/
export function useCreditNotes(query, props) {
return useRequestQuery(
[t.CREDIT_NOTES, query],
{ method: 'get', url: 'credit-notes', params: query },
{
select: transformCreditNotes,
defaultData: {
creditNotes: [],
pagination: {
page: 1,
pageSize: 20,
total: 0,
},
filterMeta: {},
},
...props,
},
);
}
/**
* Retrieve credit note detail of the given id.
* @param {number} id
*
*/
export function useCreditNote(id, props, requestProps) {
return useRequestQuery(
[t.CREDIT_NOTE, id],
{ method: 'get', url: `credit-notes/${id}`, ...requestProps },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
export function useRefreshCreditNotes() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries(t.CREDIT_NOTES);
},
};
}
/**
* Create Round creidt note
*/
export function useCreateRefundCreditNote(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.post(`credit-notes/${id}/refunds`, values),
{
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate credit note query.
queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
},
...props,
},
);
}
/**
* Delete the given refund credit note.
*/
export function useDeleteRefundCreditNote(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`credit-notes/refunds/${id}`), {
onSuccess: (res, id) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate vendor credit query.
queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
},
...props,
});
}
/**
* Retrieve refund credit note detail of the given id.
* @param {number} id
*
*/
export function useRefundCreditNote(id, props, requestProps) {
return useRequestQuery(
[t.REFUND_CREDIT_NOTE, id],
{ method: 'get', url: `credit-notes/${id}/refunds`, ...requestProps },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
/**
* Mark the given credit note as opened.
*/
export function useOpenCreditNote(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.post(`credit-notes/${id}/open`), {
onSuccess: (res, id) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate specific
queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
},
...props,
});
}
/**
* Retrieve reconcile credit note of the given id.
* @param {number} id
*
*/
export function useReconcileCreditNote(id, props, requestProps) {
return useRequestQuery(
[t.RECONCILE_CREDIT_NOTE, id],
{
method: 'get',
url: `credit-notes/${id}/apply-invoices`,
...requestProps,
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
}
/**
* Create Reconcile credit note.
*/
export function useCreateReconcileCreditNote(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) =>
apiRequest.post(`credit-notes/${id}/apply-invoices`, values),
{
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate credit note query.
queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
},
...props,
},
);
}
/**
* Retrieve reconcile credit notes.
*/
export function useReconcileCreditNotes(id, props, requestProps) {
return useRequestQuery(
[t.RECONCILE_CREDIT_NOTES, id],
{
method: 'get',
url: `credit-notes/${id}/applied-invoices`,
...requestProps,
},
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
/**
* Delete the given reconcile credit note.
*/
export function useDeleteReconcileCredit(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(id) => apiRequest.delete(`credit-notes/applied-invoices/${id}`),
{
onSuccess: (res, id) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate vendor credit query.
queryClient.invalidateQueries([t.CREDIT_NOTE, id]);
},
...props,
},
);
}
/**
* Retrieve refund credit transaction detail.
* @param {number} id
*
*/
export function useRefundCreditTransaction(id, props, requestProps) {
return useRequestQuery(
[t.REFUND_CREDIT_NOTE_TRANSACTION, id],
{ method: 'get', url: `credit-notes/refunds/${id}`, ...requestProps },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
/**
* Retrieve the credit note pdf document data,
*/
export function usePdfCreditNote(creditNoteId) {
return useRequestPdf({ url: `credit-notes/${creditNoteId}` });
}
export interface CreditNoteStateResponse {
defaultTemplateId: number;
}
export function useGetCreditNoteState(
options?: UseQueryOptions<CreditNoteStateResponse, Error>,
): UseQueryResult<CreditNoteStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<CreditNoteStateResponse, Error>(
['CREDIT_NOTE_STATE'],
() =>
apiRequest
.get('/credit-notes/state')
.then((res) => transformToCamelCase(res.data)),
{ ...options },
);
}
+58 -42
View File
@@ -1,20 +1,38 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type {
CurrenciesListResponse,
CreateCurrencyBody,
EditCurrencyBody,
} from '@bigcapital/sdk-ts';
import {
fetchCurrencies,
createCurrency,
editCurrency,
deleteCurrency,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import t from './types';
/**
* Create a new currency.
*/
export function useCreateCurrency(props) {
export function useCreateCurrency(
props?: UseMutationOptions<void, Error, CreateCurrencyBody>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((values) => apiRequest.post('currencies', values), {
return useMutation({
mutationFn: (values: CreateCurrencyBody) =>
createCurrency(fetcher, values),
onSuccess: () => {
// Invalidate currencies.
queryClient.invalidateQueries(t.CURRENCIES);
queryClient.invalidateQueries({ queryKey: [t.CURRENCIES] });
},
...props,
});
@@ -23,53 +41,51 @@ export function useCreateCurrency(props) {
/**
* Edits the given currency by ID.
*/
export function useEditCurrency(props) {
export function useEditCurrency(
props?: UseMutationOptions<void, Error, [number, EditCurrencyBody]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
([currencyId, values]) =>
apiRequest.put(`currencies/${currencyId}`, values),
{
onSuccess: () => {
// Invalidate currencies.
queryClient.invalidateQueries(t.CURRENCIES);
},
...props,
return useMutation({
mutationFn: ([currencyId, values]: [number, EditCurrencyBody]) =>
editCurrency(fetcher, currencyId, values),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [t.CURRENCIES] });
},
);
...props,
});
}
/**
* Deletes the given currency.
*/
export function useDeleteCurrency(props) {
export function useDeleteCurrency(
props?: UseMutationOptions<void, Error, string>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
(currencyCode) => apiRequest.delete(`currencies/${currencyCode}`),
{
onSuccess: () => {
// Invalidate currencies.
queryClient.invalidateQueries(t.CURRENCIES);
},
...props,
return useMutation({
mutationFn: (currencyCode: string) =>
deleteCurrency(fetcher, currencyCode),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [t.CURRENCIES] });
},
);
...props,
});
}
/**
* Retrieve the currencies list.
*/
export function useCurrencies(props) {
return useRequestQuery(
[t.CURRENCIES],
{ method: 'get', url: 'currencies' },
{
select: (res) => res.data,
defaultData: [],
...props
},
);
export function useCurrencies(
props?: Omit<UseQueryOptions<CurrenciesListResponse>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.CURRENCIES],
queryFn: () => fetchCurrencies(fetcher),
...props,
});
}
+143 -153
View File
@@ -1,8 +1,28 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type {
Customer,
CreateCustomerBody,
EditCustomerBody,
ValidateBulkDeleteCustomersResponse,
} from '@bigcapital/sdk-ts';
import type { CustomersListResponse } from '@bigcapital/sdk-ts';
import {
fetchCustomers,
fetchCustomer,
createCustomer,
editCustomer,
deleteCustomer,
validateBulkDeleteCustomers,
bulkDeleteCustomers,
} from '@bigcapital/sdk-ts';
import useApiRequest, { useApiFetcher } from '../useRequest';
import { transformPagination, transformToCamelCase } from '@/utils';
import useApiRequest from '../useRequest';
import t from './types';
const defaultPagination = {
@@ -11,195 +31,165 @@ const defaultPagination = {
pagesCount: 0,
};
const commonInvalidateQueries = (queryClient) => {
// Invalidate customers.
queryClient.invalidateQueries(t.CUSTOMERS);
// Invalidate the financial reports.
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
// Invalidate the financial reports.
queryClient.invalidateQueries(t.FINANCIAL_REPORT);
// Invalidate SMS details.
queryClient.invalidateQueries(t.SALE_ESTIMATE_SMS_DETAIL);
queryClient.invalidateQueries(t.SALE_INVOICE_SMS_DETAIL);
queryClient.invalidateQueries(t.SALE_RECEIPT_SMS_DETAIL);
queryClient.invalidateQueries(t.PAYMENT_RECEIVE_SMS_DETAIL);
// Invalidate mutate base currency abilities.
queryClient.invalidateQueries(t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES);
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.CUSTOMERS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
queryClient.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATE_SMS_DETAIL] });
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICE_SMS_DETAIL] });
queryClient.invalidateQueries({ queryKey: [t.SALE_RECEIPT_SMS_DETAIL] });
queryClient.invalidateQueries({ queryKey: [t.PAYMENT_RECEIVE_SMS_DETAIL] });
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES] });
};
// Customers response selector.
const customersSelector = (response) => ({
customers: response.data.customers,
pagination: transformPagination(response.data.pagination),
filterMeta: response.data.filter_meta,
});
export type CustomersSelectorResult = {
customers: unknown[];
pagination: typeof defaultPagination;
filterMeta: Record<string, unknown>;
};
/**
* Retrieve customers list with pagination meta.
*/
export function useCustomers(query, props) {
return useRequestQuery(
[t.CUSTOMERS, query],
{ method: 'get', url: `customers`, params: query },
{
select: customersSelector,
defaultData: {
customers: [],
pagination: defaultPagination,
filterMeta: {},
},
...props,
},
);
function transformCustomersList(res: CustomersListResponse): CustomersSelectorResult {
const data = res as { customers?: unknown[]; pagination?: unknown; filter_meta?: Record<string, unknown> };
return {
customers: data?.customers ?? [],
pagination: transformPagination(data?.pagination ?? {}) as typeof defaultPagination,
filterMeta: data?.filter_meta ?? {},
};
}
/**
* Edits the given customer details.
* @param {*} props
*/
export function useEditCustomer(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`customers/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate specific customer.
queryClient.invalidateQueries([t.CUSTOMER, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
export function useCustomers(
query?: Record<string, unknown>,
props?: Omit<UseQueryOptions<CustomersSelectorResult>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.CUSTOMERS, query],
queryFn: () =>
(fetchCustomers as (f: ReturnType<typeof useApiFetcher>, q?: Record<string, unknown>) => Promise<CustomersListResponse>)(
fetcher,
query
).then(transformCustomersList),
...props,
});
}
/**
* Deletes the given customer.
*/
export function useDeleteCustomer(props) {
export function useEditCustomer(
props?: UseMutationOptions<void, Error, [number, EditCustomerBody]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.delete(`customers/${id}`), {
onSuccess: (res, id) => {
// Invalidate specific customer.
queryClient.invalidateQueries([t.CUSTOMER, id]);
// Common invalidate queries.
return useMutation({
mutationFn: ([id, values]: [number, EditCustomerBody]) =>
editCustomer(fetcher, id, values),
onSuccess: (_data, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.CUSTOMER, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Deletes multiple customers in bulk.
*/
export function useBulkDeleteCustomers(props) {
export function useDeleteCustomer(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
({
return useMutation({
mutationFn: (id: number) => deleteCustomer(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.CUSTOMER, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
export function useBulkDeleteCustomers(
props?: UseMutationOptions<void, Error, { ids: number[]; skipUndeletable?: boolean }>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('customers/bulk-delete', {
bulkDeleteCustomers(fetcher, {
ids,
skip_undeletable: skipUndeletable,
}).then((res) => transformToCamelCase(res.data)),
{
onSuccess: () => {
commonInvalidateQueries(queryClient);
},
...props,
},
);
skipUndeletable,
}),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
/**
* Validates which customers can be deleted in bulk.
*/
export function useValidateBulkDeleteCustomers(props) {
const apiRequest = useApiRequest();
export function useValidateBulkDeleteCustomers(
props?: UseMutationOptions<ValidateBulkDeleteCustomersResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
return useMutation(
(ids: number[]) =>
apiRequest.post('customers/validate-bulk-delete', { ids }).then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeleteCustomers(fetcher, { ids, skipUndeletable: false }).then(
(res) => transformToCamelCase(res as Record<string, unknown>) as ValidateBulkDeleteCustomersResponse
),
...props,
});
}
/**
* Creates a new customer.
*/
export function useCreateCustomer(props) {
export function useCreateCustomer(
props?: UseMutationOptions<void, Error, CreateCustomerBody>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreateCustomerBody) => createCustomer(fetcher, values),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useCustomer(
id: number | null | undefined,
props?: Omit<UseQueryOptions<Customer>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.CUSTOMER, id],
queryFn: () => fetchCustomer(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useEditCustomerOpeningBalance(
props?: UseMutationOptions<unknown, Error, [number, Record<string, unknown>]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('customers', values), {
onSuccess: () => {
// Common invalidate queries.
return useMutation({
mutationFn: ([id, values]: [number, Record<string, unknown>]) =>
apiRequest.put(`customers/${id}/opening-balance`, values),
onSuccess: (_data, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.CUSTOMER, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Retrieve the customer details.
*/
export function useCustomer(id, props) {
return useRequestQuery(
[t.CUSTOMER, id],
{ method: 'get', url: `customers/${id}` },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
export function useEditCustomerOpeningBalance(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) =>
apiRequest.put(`customers/${id}/opening-balance`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate specific customer.
queryClient.invalidateQueries([t.CUSTOMER, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export function useRefreshCustomers() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries(t.CUSTOMERS);
},
refresh: () => queryClient.invalidateQueries({ queryKey: [t.CUSTOMERS] }),
};
}
+227 -227
View File
@@ -1,39 +1,73 @@
// @ts-nocheck
import {
useQueryClient,
useMutation,
useQuery,
UseQueryOptions,
UseQueryResult,
} from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
UseMutationOptions,
} from '@tanstack/react-query';
import type {
SaleEstimate,
SaleEstimatesListResponse,
CreateSaleEstimateBody,
EditSaleEstimateBody,
} from '@bigcapital/sdk-ts';
import {
fetchSaleEstimates,
fetchSaleEstimate,
createSaleEstimate,
editSaleEstimate,
deleteSaleEstimate,
bulkDeleteSaleEstimates,
validateBulkDeleteSaleEstimates,
deliverSaleEstimate,
approveSaleEstimate,
rejectSaleEstimate,
notifySaleEstimateBySms,
fetchSaleEstimateSmsDetails,
fetchSaleEstimateMail,
sendSaleEstimateMail,
fetchSaleEstimatesState,
} from '@bigcapital/sdk-ts';
export type BulkDeleteEstimatesBody = { ids: number[]; skipUndeletable?: boolean };
export type ValidateBulkDeleteEstimatesResponse = {
deletableCount: number;
nonDeletableCount: number;
deletableIds: number[];
nonDeletableIds: number[];
};
import useApiRequest, { useApiFetcher } from '../useRequest';
import { transformPagination, transformToCamelCase } from '@/utils';
import t from './types';
import { useRequestPdf } from '../useRequestPdf';
const commonInvalidateQueries = (queryClient) => {
// Invalidate estimates.
queryClient.invalidateQueries(t.SALE_ESTIMATES);
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATES] });
queryClient.invalidateQueries({ queryKey: [t.ITEM_ASSOCIATED_WITH_ESTIMATES] });
};
// Invalidate
queryClient.invalidateQueries(t.ITEM_ASSOCIATED_WITH_ESTIMATES);
export type EstimatesListResult = {
estimates: unknown[];
pagination: ReturnType<typeof transformPagination>;
filterMeta: Record<string, unknown>;
};
/**
* Creates a new sale estimate.
*/
export function useCreateEstimate(props) {
export function useCreateEstimate(
props?: UseMutationOptions<void, Error, CreateSaleEstimateBody>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((values) => apiRequest.post('sale-estimates', values), {
return useMutation({
mutationFn: (values: CreateSaleEstimateBody) =>
createSaleEstimate(fetcher, values),
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate the settings.
queryClient.invalidateQueries([t.SETTING, t.SETTING_ESTIMATES]);
queryClient.invalidateQueries({ queryKey: [t.SETTING, t.SETTING_ESTIMATES] });
},
...props,
});
@@ -42,83 +76,81 @@ export function useCreateEstimate(props) {
/**
* Edits the given sale estimate.
*/
export function useEditEstimate(props) {
export function useEditEstimate(
props?: UseMutationOptions<void, Error, [number, EditSaleEstimateBody]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
([id, values]) => apiRequest.put(`sale-estimates/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
// Invalidate specific sale estimate.
queryClient.invalidateQueries([t.SALE_ESTIMATE, id]);
},
...props,
return useMutation({
mutationFn: ([id, values]: [number, EditSaleEstimateBody]) =>
editSaleEstimate(fetcher, id, values),
onSuccess: (_data, [id]) => {
commonInvalidateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATE, id] });
},
);
...props,
});
}
function transformEstimates(data: SaleEstimatesListResponse): EstimatesListResult {
const raw = data as { sales_estimates?: unknown[]; pagination?: unknown; filter_meta?: Record<string, unknown> };
return {
estimates: raw.sales_estimates ?? (raw as { data?: unknown[] }).data ?? [],
pagination: transformPagination(raw.pagination ?? {}),
filterMeta: raw.filter_meta ?? {},
};
}
/**
* Retrieve sale estimate details.
*/
export function useEstimate(id, props) {
return useRequestQuery(
[t.SALE_ESTIMATE, id],
{ method: 'get', url: `sale-estimates/${id}` },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
const transformEstimates = (res) => ({
estimates: res.data.sales_estimates,
pagination: transformPagination(res.data.pagination),
filterMeta: res.data.filter_meta,
});
/**
* Retrieve sale invoices list with pagination meta.
*/
export function useEstimates(query, props) {
return useRequestQuery(
[t.SALE_ESTIMATES, query],
{ method: 'get', url: 'sale-estimates', params: query },
{
select: transformEstimates,
defaultData: {
estimates: [],
pagination: {
page: 1,
pageSize: 20,
total: 0,
},
filterMeta: {},
},
...props,
},
);
export function useEstimate(
id: number | null | undefined,
props?: Omit<UseQueryOptions<SaleEstimate>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.SALE_ESTIMATE, id],
queryFn: () => fetchSaleEstimate(fetcher, id!),
enabled: id != null,
...props,
});
}
/**
* Deletes the given sale invoice.
* Retrieve sale estimates list with pagination meta.
*/
export function useDeleteEstimate(props) {
export function useEstimates(
query?: Record<string, unknown>,
props?: Omit<
UseQueryOptions<SaleEstimatesListResponse, Error, EstimatesListResult>,
'queryKey' | 'queryFn' | 'select'
>
) {
const fetcher = useApiFetcher();
return useQuery<SaleEstimatesListResponse, Error, EstimatesListResult>({
queryKey: [t.SALE_ESTIMATES, query],
queryFn: () => fetchSaleEstimates(fetcher),
select: transformEstimates,
...props,
});
}
/**
* Deletes the given sale estimate.
*/
export function useDeleteEstimate(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.delete(`sale-estimates/${id}`), {
onSuccess: (res, id) => {
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => deleteSaleEstimate(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(queryClient);
// Invalidate specific sale estimate.
queryClient.invalidateQueries([t.SALE_ESTIMATE, id]);
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATE, id] });
},
...props,
});
@@ -127,60 +159,48 @@ export function useDeleteEstimate(props) {
/**
* Deletes multiple sale estimates in bulk.
*/
export function useBulkDeleteEstimates(props) {
export function useBulkDeleteEstimates(
props?: UseMutationOptions<void, Error, BulkDeleteEstimatesBody>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('sale-estimates/bulk-delete', {
ids,
skip_undeletable: skipUndeletable,
}),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
return useMutation({
mutationFn: (body: BulkDeleteEstimatesBody) =>
bulkDeleteSaleEstimates(fetcher, body),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useValidateBulkDeleteEstimates(props) {
const apiRequest = useApiRequest();
export function useValidateBulkDeleteEstimates(
props?: UseMutationOptions<ValidateBulkDeleteEstimatesResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
return useMutation(
(ids: number[]) =>
apiRequest
.post('sale-estimates/validate-bulk-delete', { ids })
.then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeleteSaleEstimates(fetcher, ids).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as ValidateBulkDeleteEstimatesResponse
),
...props,
});
}
/**
* Mark the given estimate as delivered.
*/
export function useDeliverEstimate(props) {
export function useDeliverEstimate(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.post(`sale-estimates/${id}/deliver`), {
onSuccess: (res, id) => {
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => deliverSaleEstimate(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(queryClient);
// Invalidate specific sale estimate.
queryClient.invalidateQueries([t.SALE_ESTIMATE, id]);
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATE, id] });
},
...props,
});
@@ -189,17 +209,17 @@ export function useDeliverEstimate(props) {
/**
* Mark the given estimate as approved.
*/
export function useApproveEstimate(props) {
export function useApproveEstimate(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.put(`sale-estimates/${id}/approve`), {
onSuccess: (res, id) => {
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => approveSaleEstimate(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(queryClient);
// Invalidate specific sale estimate.
queryClient.invalidateQueries([t.SALE_ESTIMATE, id]);
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATE, id] });
},
...props,
});
@@ -208,27 +228,26 @@ export function useApproveEstimate(props) {
/**
* Mark the given estimate as rejected.
*/
export function useRejectEstimate(props) {
export function useRejectEstimate(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.put(`sale-estimates/${id}/reject`), {
onSuccess: (res, id) => {
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => rejectSaleEstimate(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(queryClient);
// Invalidate specific sale estimate.
queryClient.invalidateQueries([t.SALE_ESTIMATE, id]);
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATE, id] });
},
...props,
});
}
/**
* Retrieve the estimate pdf document data,
* Retrieve the estimate pdf document data.
*/
export function usePdfEstimate(estimateId) {
export function usePdfEstimate(estimateId: number) {
return useRequestPdf({
url: `sale-estimates/${estimateId}`,
});
@@ -239,71 +258,61 @@ export function useRefreshEstimates() {
return {
refresh: () => {
queryClient.invalidateQueries(t.SALE_ESTIMATES);
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATES] });
},
};
}
/**
*
* Notify estimate by SMS.
*/
export function useCreateNotifyEstimateBySMS(props) {
export function useCreateNotifyEstimateBySMS(
props?: UseMutationOptions<void, Error, [number, Record<string, unknown>]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
([id, values]) =>
apiRequest.post(`sale-estimates/${id}/notify-by-sms`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate
queryClient.invalidateQueries([t.NOTIFY_SALE_ESTIMATE_BY_SMS, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
return useMutation({
mutationFn: ([id, values]: [number, Record<string, unknown>]) =>
notifySaleEstimateBySms(fetcher, id, values),
onSuccess: (_data, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.NOTIFY_SALE_ESTIMATE_BY_SMS, id] });
commonInvalidateQueries(queryClient);
},
);
...props,
});
}
/**
*
* @param {*} estimateId
* @param {*} props
* @param {*} requestProps
* @returns
* Retrieve estimate SMS detail.
*/
export function useEstimateSMSDetail(estimateId, props, requestProps) {
return useRequestQuery(
[t.SALE_ESTIMATE_SMS_DETAIL, estimateId],
{
method: 'get',
url: `sale-estimates/${estimateId}/sms-details`,
...requestProps,
},
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
export function useEstimateSMSDetail(
estimateId: number | null | undefined,
props?: Record<string, unknown>,
requestProps?: Record<string, unknown>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.SALE_ESTIMATE_SMS_DETAIL, estimateId],
queryFn: () => fetchSaleEstimateSmsDetails(fetcher, estimateId!),
enabled: estimateId != null,
...requestProps,
...props,
});
}
export function useSendSaleEstimateMail(props = {}) {
export function useSendSaleEstimateMail(
props?: UseMutationOptions<void, Error, [number, Record<string, unknown>]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
([id, values]) => apiRequest.post(`sale-estimates/${id}/mail`, values),
{
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
return useMutation({
mutationFn: ([id, values]: [number, Record<string, unknown>]) =>
sendSaleEstimateMail(fetcher, id, values),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export interface SaleEstimateMailStateResponse {
@@ -311,61 +320,52 @@ export interface SaleEstimateMailStateResponse {
companyLogoUri: string;
companyName: string;
customerName: string;
entries: Array<any>;
entries: Array<unknown>;
estimateDate: string;
estimateDateFormatted: string;
expirationDate: string;
expirationDateFormatted: string;
primaryColor: string;
total: number;
totalFormatted: string;
subtotal: number;
subtotalFormatted: string;
discountAmount: number;
discountAmountFormatted: string;
discountLabel: string;
discountPercentage: number | null;
discountPercentageFormatted: string;
adjustment: number;
adjustmentFormatted: string;
estimateNumber: string;
formatArgs: {
customerName: string;
estimateAmount: string;
};
from: Array<string>;
fromOptions: Array<any>;
fromOptions: Array<unknown>;
message: string;
subject: string;
to: Array<string>;
toOptions: Array<any>;
toOptions: Array<unknown>;
}
/**
* Retrieves the sale estimate mail state.
* @param {number} estimateId
* @param {UseQueryOptions<SaleEstimateMailStateResponse, Error>} props
* @returns {UseQueryResult<SaleEstimateMailStateResponse, Error>}
*/
export function useSaleEstimateMailState(
estimateId: number,
props?: UseQueryOptions<SaleEstimateMailStateResponse, Error>,
props?: UseQueryOptions<SaleEstimateMailStateResponse, Error>
): UseQueryResult<SaleEstimateMailStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery([t.SALE_ESTIMATE_MAIL_OPTIONS, estimateId], () =>
apiRequest
.get(`sale-estimates/${estimateId}/mail`)
.then((res) => transformToCamelCase(res.data)),
);
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.SALE_ESTIMATE_MAIL_OPTIONS, estimateId],
queryFn: () =>
fetchSaleEstimateMail(fetcher, estimateId).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as SaleEstimateMailStateResponse
),
...props,
});
}
export interface ISaleEstimatesStateResponse {
@@ -373,44 +373,44 @@ export interface ISaleEstimatesStateResponse {
}
export function useGetSaleEstimatesState(
options?: UseQueryOptions<ISaleEstimatesStateResponse, Error>,
options?: UseQueryOptions<ISaleEstimatesStateResponse, Error>
): UseQueryResult<ISaleEstimatesStateResponse, Error> {
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useQuery<ISaleEstimatesStateResponse, Error>(
['SALE_ESTIMATE_STATE'],
() =>
apiRequest
.get('/sale-estimates/state')
.then((res) => transformToCamelCase(res.data)),
{ ...options },
);
return useQuery({
queryKey: ['SALE_ESTIMATE_STATE'],
queryFn: () =>
fetchSaleEstimatesState(fetcher).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as ISaleEstimatesStateResponse
),
...options,
});
}
interface GetEstimateHtmlResponse {
htmlContent: string;
}
/**
* Retrieves the sale estimate html content.
* @param {number} invoiceId
* @param {UseQueryOptions<GetEstimateHtmlResponse>} options
* @returns {UseQueryResult<GetEstimateHtmlResponse>}
* Uses custom Accept header; kept on apiRequest until SDK supports per-request headers.
*/
export const useGetSaleEstimateHtml = (
estimateId: number,
options?: UseQueryOptions<GetEstimateHtmlResponse>,
options?: UseQueryOptions<GetEstimateHtmlResponse>
): UseQueryResult<GetEstimateHtmlResponse> => {
const apiRequest = useApiRequest();
return useQuery<GetEstimateHtmlResponse>(
['SALE_ESTIMATE_HTML', estimateId],
() =>
return useQuery({
queryKey: ['SALE_ESTIMATE_HTML', estimateId],
queryFn: (): Promise<GetEstimateHtmlResponse> =>
apiRequest
.get(`sale-estimates/${estimateId}`, {
headers: {
Accept: 'application/json+html',
},
})
.then((res) => transformToCamelCase(res.data)),
);
.then((res) => transformToCamelCase(res.data) as GetEstimateHtmlResponse),
...options,
});
};
@@ -1,5 +1,5 @@
// @ts-nocheck
import { useQuery } from 'react-query';
import { useQuery } from '@tanstack/react-query';
import QUERY_TYPES from './types';
import useApiRequest from '../useRequest';
@@ -18,9 +18,9 @@ export function useLatestExchangeRate(
) {
const apiRequest = useApiRequest();
return useQuery(
[QUERY_TYPES.EXCHANGE_RATE, toCurrency, fromCurrency],
() =>
return useQuery({
queryKey: [QUERY_TYPES.EXCHANGE_RATE, toCurrency, fromCurrency],
queryFn: () =>
apiRequest
.http({
url: `/api/exchange_rates/latest`,
@@ -31,6 +31,6 @@ export function useLatestExchangeRate(
},
})
.then((res) => res.data),
props,
);
...props,
});
}
+114 -119
View File
@@ -1,8 +1,23 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import useApiRequest from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination, transformToCamelCase } from '@/utils';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import type {
ExpensesListResponse,
Expense,
CreateExpenseBody,
EditExpenseBody,
BulkDeleteExpensesBody,
} from '@bigcapital/sdk-ts';
import {
fetchExpenses,
fetchExpense,
createExpense,
editExpense,
deleteExpense,
publishExpense,
bulkDeleteExpenses,
validateBulkDeleteExpenses,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { transformPagination } from '@/utils';
import t from './types';
const defaultPagination = {
@@ -12,90 +27,83 @@ const defaultPagination = {
};
// Common invalidate queries.
const commonInvalidateQueries = (queryClient) => {
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
// Invalidate expenses.
queryClient.invalidateQueries(t.EXPENSES);
queryClient.invalidateQueries({ queryKey: [t.EXPENSES] });
// Invalidate accounts.
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
// Invalidate financial reports.
queryClient.invalidateQueries(t.FINANCIAL_REPORT);
queryClient.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
// Invalidate the cashflow transactions.
queryClient.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
queryClient.invalidateQueries({ queryKey: [t.CASH_FLOW_TRANSACTIONS] });
queryClient.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY] });
// Invalidate landed cost.
queryClient.invalidateQueries(t.LANDED_COST);
queryClient.invalidateQueries(t.LANDED_COST_TRANSACTION);
queryClient.invalidateQueries({ queryKey: [t.LANDED_COST] });
queryClient.invalidateQueries({ queryKey: [t.LANDED_COST_TRANSACTION] });
// Invalidate mutate base currency abilities.
queryClient.invalidateQueries(t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES);
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES] });
};
const transformExpenses = (response) => ({
expenses: response.data.expenses,
pagination: transformPagination(response.data.pagination),
filterMeta: response.data.filter_meta,
});
function transformExpensesList(response: ExpensesListResponse) {
const data = response as { expenses?: unknown[]; pagination?: unknown; filter_meta?: Record<string, unknown> };
return {
expenses: data?.expenses ?? [],
pagination: transformPagination(data?.pagination ?? {}) as typeof defaultPagination,
filterMeta: data?.filter_meta ?? {},
};
}
/**
* Retrieve the expenses list.
*/
export function useExpenses(query, props) {
return useRequestQuery(
[t.EXPENSES, query],
{
method: 'get',
url: `expenses`,
params: { ...query },
},
{
select: transformExpenses,
defaultData: {
expenses: [],
pagination: defaultPagination,
filterMeta: {},
},
...props,
},
);
export function useExpenses(
query: Parameters<typeof fetchExpenses>[1],
props?: Omit<Parameters<typeof useQuery>[0], 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.EXPENSES, query],
queryFn: () => fetchExpenses(fetcher, query).then(transformExpensesList),
...props,
});
}
/**
* Retrieve the expense details.
* @param {number} id - Expense id.
* @param id - Expense id.
*/
export function useExpense(id, props) {
return useRequestQuery(
[t.EXPENSE, id],
{
method: 'get',
url: `expenses/${id}`,
},
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
export function useExpense(
id: number | undefined | null,
props?: Omit<Parameters<typeof useQuery>[0], 'queryKey' | 'queryFn' | 'enabled'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.EXPENSE, id],
queryFn: () => fetchExpense(fetcher, id as number),
enabled: id != null,
...props,
});
}
/**
* Deletes the given expense.
*/
export function useDeleteExpense(props) {
const apiRequest = useApiRequest();
export function useDeleteExpense(
props?: Parameters<typeof useMutation<void, Error, number>>[0]
) {
const fetcher = useApiFetcher();
const queryClient = useQueryClient();
return useMutation((id) => apiRequest.delete(`expenses/${id}`), {
onSuccess: (res, id) => {
// Invalidate specific expense.
queryClient.invalidateQueries([t.EXPENSE, id]);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => deleteExpense(fetcher, id),
onSuccess: (_res, id) => {
queryClient.invalidateQueries({ queryKey: [t.EXPENSE, id] });
commonInvalidateQueries(queryClient);
},
...props,
@@ -105,78 +113,65 @@ export function useDeleteExpense(props) {
/**
* Deletes multiple expenses in bulk.
*/
export function useBulkDeleteExpenses(props) {
export function useBulkDeleteExpenses(
props?: Parameters<typeof useMutation<void, Error, BulkDeleteExpensesBody>>[0]
) {
const fetcher = useApiFetcher();
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('expenses/bulk-delete', {
ids,
skip_undeletable: skipUndeletable,
}),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
return useMutation({
mutationFn: (body: BulkDeleteExpensesBody) => bulkDeleteExpenses(fetcher, body),
onSuccess: () => {
commonInvalidateQueries(queryClient);
},
);
...props,
});
}
export function useValidateBulkDeleteExpenses(props) {
const apiRequest = useApiRequest();
export function useValidateBulkDeleteExpenses(
props?: Parameters<typeof useMutation<Awaited<ReturnType<typeof validateBulkDeleteExpenses>>, Error, number[]>>[0]
) {
const fetcher = useApiFetcher();
return useMutation(
(ids: number[]) =>
apiRequest
.post('expenses/validate-bulk-delete', { ids })
.then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeleteExpenses(fetcher, { ids }),
...props,
});
}
/**
* Edits the given expense.
*/
export function useEditExpense(props) {
export function useEditExpense(
props?: Parameters<typeof useMutation<void, Error, [number, EditExpenseBody]>>[0]
) {
const fetcher = useApiFetcher();
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`expenses/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate specific expense.
queryClient.invalidateQueries([t.EXPENSE, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
return useMutation({
mutationFn: ([id, values]: [number, EditExpenseBody]) =>
editExpense(fetcher, id, values),
onSuccess: (_res, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.EXPENSE, id] });
commonInvalidateQueries(queryClient);
},
);
...props,
});
}
/**
* Creates the new expense.
*/
export function useCreateExpense(props) {
export function useCreateExpense(
props?: Parameters<typeof useMutation<void, Error, CreateExpenseBody>>[0]
) {
const fetcher = useApiFetcher();
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('expenses', values), {
return useMutation({
mutationFn: (values: CreateExpenseBody) => createExpense(fetcher, values),
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
@@ -186,16 +181,16 @@ export function useCreateExpense(props) {
/**
* Publishes the given expense.
*/
export function usePublishExpense(props) {
export function usePublishExpense(
props?: Parameters<typeof useMutation<void, Error, number>>[0]
) {
const fetcher = useApiFetcher();
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.post(`expenses/${id}/publish`), {
onSuccess: (res, id) => {
// Invalidate specific expense.
queryClient.invalidateQueries([t.EXPENSE, id]);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => publishExpense(fetcher, id),
onSuccess: (_res, id) => {
queryClient.invalidateQueries({ queryKey: [t.EXPENSE, id] });
commonInvalidateQueries(queryClient);
},
...props,
@@ -207,7 +202,7 @@ export function useRefreshExpenses() {
return {
refresh: () => {
queryClient.invalidateQueries(t.EXPENSES);
queryClient.invalidateQueries({ queryKey: [t.EXPENSES] });
},
};
}
+21 -21
View File
@@ -4,7 +4,7 @@ import {
useMutation,
useQuery,
useQueryClient,
} from 'react-query';
} from '@tanstack/react-query';
import useApiRequest from '../useRequest';
import { transformToCamelCase } from '@/utils';
import { downloadFile, useDownloadFile } from '../useDownloadFile';
@@ -22,8 +22,8 @@ export function useImportFileUpload(props = {}) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post(`import/file`, values), {
onSuccess: (res, id) => {
return useMutation({ mutationFn: (values) => apiRequest.post(`import/file`, values),
onSuccess: (res, id) => {
// Invalidate queries.
},
...props,
@@ -34,11 +34,9 @@ export function useImportFileMapping(props = {}) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([importId, values]) =>
return useMutation({ mutationFn: ([importId, values]) =>
apiRequest.post(`import/${importId}/mapping`, values),
{
onSuccess: (res, id) => {
onSuccess: (res, id) => {
// Invalidate queries.
queryClient.invalidateQueries([QueryKeys.ImportPreview]);
queryClient.invalidateQueries([QueryKeys.ImportFileMeta]);
@@ -52,22 +50,26 @@ export function useImportFilePreview(importId: string, props = {}) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useQuery([QueryKeys.ImportPreview, importId], () =>
apiRequest
.get(`import/${importId}/preview`)
.then((res) => transformToCamelCase(res.data)),
);
return useQuery({
queryKey: [QueryKeys.ImportPreview, importId],
queryFn: () =>
apiRequest
.get(`import/${importId}/preview`)
.then((res) => transformToCamelCase(res.data)),
});
}
export function useImportFileMeta(importId: string, props = {}) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useQuery([QueryKeys.ImportFileMeta, importId], () =>
apiRequest
.get(`import/${importId}`)
.then((res) => transformToCamelCase(res.data)),
);
return useQuery({
queryKey: [QueryKeys.ImportFileMeta, importId],
queryFn: () =>
apiRequest
.get(`import/${importId}`)
.then((res) => transformToCamelCase(res.data)),
});
}
/**
@@ -77,10 +79,8 @@ export function useImportFileProcess(props = {}) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(importId) => apiRequest.post(`import/${importId}/import`),
{
onSuccess: (res, id) => {
return useMutation({ mutationFn: (importId) => apiRequest.post(`import/${importId}/import`),
onSuccess: (res, id) => {
// Invalidate queries.
invalidateResourcesOnImport(queryClient, res.data.resource);
},
+14 -14
View File
@@ -3,39 +3,39 @@ export * from './authentication';
export * from './accounts';
export * from './views';
export * from './items';
export * from './itemsCategories';
export * from './inventoryAdjustments';
export * from './items-categories';
export * from './inventory-adjustments';
export * from './expenses';
export * from './customers';
export * from './vendors';
export * from './manualJournals';
export * from './manual-journals';
export * from './currencies';
export * from './invoices';
export * from './bills';
export * from './estimates';
export * from './receipts';
export * from './paymentReceives';
export * from './paymentMades';
export * from './payment-receives';
export * from './payment-mades';
export * from './settings';
export * from './users';
export * from './invite';
export * from './exchangeRates';
export * from './exchange-rates';
export * from './contacts';
export * from './subscriptions';
export * from './organization';
export * from './landedCost';
export * from './UniversalSearch/UniversalSearch';
export * from './landed-cost';
export * from './UniversalSearch/universal-search';
export * from './GenericResource';
export * from './jobs';
export * from './misc';
export * from './cashflowAccounts';
export * from './cashflow-accounts';
export * from './roles';
export * from './creditNote';
export * from './vendorCredit';
export * from './transactionsLocking';
export * from './credit-note';
export * from './vendor-credit';
export * from './transactions-locking';
export * from './warehouses';
export * from './branches';
export * from './warehousesTransfers';
export * from './warehouses-transfers';
export * from './plaid';
export * from './FinancialReports';
export * from './apiKeys';
export * from './api-keys';
@@ -1,5 +1,5 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useMutation, useQueryClient } from '@tanstack/react-query';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination } from '@/utils';
import useApiRequest from '../useRequest';
@@ -7,22 +7,22 @@ import t from './types';
const commonInvalidateQueries = (queryClient) => {
// Invalidate inventory adjustments.
queryClient.invalidateQueries(t.INVENTORY_ADJUSTMENTS);
queryClient.invalidateQueries(t.INVENTORY_ADJUSTMENT);
queryClient.invalidateQueries({ queryKey: [t.INVENTORY_ADJUSTMENTS] });
queryClient.invalidateQueries({ queryKey: [t.INVENTORY_ADJUSTMENT] });
// Invalidate items.
queryClient.invalidateQueries(t.ITEMS);
queryClient.invalidateQueries(t.ITEM);
queryClient.invalidateQueries({ queryKey: [t.ITEMS] });
queryClient.invalidateQueries({ queryKey: [t.ITEM] });
// Invalidate accounts.
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
// Invalidate financial reports.
queryClient.invalidateQueries(t.FINANCIAL_REPORT);
queryClient.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
// Invalidate mutate base currency abilities.
queryClient.invalidateQueries(t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES);
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES] });
};
/**
@@ -32,10 +32,8 @@ export function useCreateInventoryAdjustment(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(values) => apiRequest.post('inventory-adjustments/quick', values),
{
onSuccess: () => {
return useMutation({ mutationFn: (values) => apiRequest.post('inventory-adjustments/quick', values),
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
@@ -51,8 +49,8 @@ export function useDeleteInventoryAdjustment(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`inventory-adjustments/${id}`), {
onSuccess: (res, id) => {
return useMutation({ mutationFn: (id) => apiRequest.delete(`inventory-adjustments/${id}`),
onSuccess: (res, id) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
@@ -97,12 +95,10 @@ export function usePublishInventoryAdjustment(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(id) => apiRequest.post(`inventory-adjustments/${id}/publish`),
{
onSuccess: (res, id) => {
return useMutation({ mutationFn: (id) => apiRequest.post(`inventory-adjustments/${id}/publish`),
onSuccess: (res, id) => {
// Invalidate specific inventory adjustment.
queryClient.invalidateQueries([t.INVENTORY_ADJUSTMENT, id]);
queryClient.invalidateQueries({ queryKey: [t.INVENTORY_ADJUSTMENT, id] });
commonInvalidateQueries(queryClient);
},
+36 -29
View File
@@ -1,42 +1,49 @@
// @ts-nocheck
import { useMutation } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import { useMutation, useQuery, UseMutationOptions, UseQueryOptions } from '@tanstack/react-query';
import type { AcceptInviteBody } from '@bigcapital/sdk-ts';
import { acceptInvite, fetchInviteCheck, resendInvite } from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { transformToCamelCase } from '@/utils';
/**
* Authentication invite accept.
*/
export const useAuthInviteAccept = (props) => {
const apiRequest = useApiRequest();
return useMutation(
([values, token]) => apiRequest.post(`invite/accept/${token}`, values),
props,
);
export function useAuthInviteAccept(
props?: UseMutationOptions<unknown, Error, [Record<string, unknown>, string]>
) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([values, token]: [Record<string, unknown>, string]) =>
acceptInvite(fetcher, token, values as AcceptInviteBody),
...props,
});
}
/**
* Retrieve the invite meta by the given token.
* @param {string} token - Token.
*/
export const useInviteMetaByToken = (token, props) => {
return useRequestQuery(
['INVITE_META', token],
{ method: 'get', url: `invite/check/${token}` },
{
select: (res) => transformToCamelCase(res.data),
...props
}
);
export function useInviteMetaByToken(
token: string | null | undefined,
props?: Omit<UseQueryOptions<unknown>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: ['INVITE_META', token],
queryFn: () => fetchInviteCheck(fetcher, token!),
enabled: !!token,
select: (data) => transformToCamelCase(data as Record<string, unknown>),
...props,
});
}
export const useResendInvitation = (props) => {
const apiRequest = useApiRequest();
return useMutation(
(userId) => apiRequest.post(`invite/users/${userId}/resend`),
props
)
/**
* Resend invitation to user.
*/
export function useResendInvitation(
props?: UseMutationOptions<void, Error, number>
) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (userId: number) => resendInvite(fetcher, userId),
...props,
});
}
+299 -345
View File
@@ -1,4 +1,3 @@
// @ts-nocheck
import {
useQueryClient,
useMutation,
@@ -7,70 +6,77 @@ import {
UseMutationResult,
UseQueryOptions,
UseQueryResult,
} from 'react-query';
} from '@tanstack/react-query';
import type {
SaleInvoicesListResponse,
SaleInvoice,
CreateSaleInvoiceBody,
EditSaleInvoiceBody,
GetSaleInvoicesQuery,
ValidateBulkDeleteSaleInvoicesResponse,
SaleInvoiceStateResponse,
} from '@bigcapital/sdk-ts';
import {
fetchSaleInvoices,
fetchSaleInvoice,
createSaleInvoice,
editSaleInvoice,
deleteSaleInvoice,
bulkDeleteSaleInvoices,
validateBulkDeleteSaleInvoices,
deliverSaleInvoice,
writeOffSaleInvoice,
cancelWrittenOffSaleInvoice,
fetchReceivableSaleInvoices,
fetchSaleInvoiceMailState,
sendSaleInvoiceMail,
fetchSaleInvoiceState,
fetchInvoicePayments,
fetchSaleInvoiceHtml,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination, transformToCamelCase } from '@/utils';
import useApiRequest from '../useRequest';
import { useRequestPdf } from '../useRequestPdf';
import t from './types';
// Common invalidate queries.
const commonInvalidateQueries = (queryClient) => {
// Invalidate invoices.
queryClient.invalidateQueries(t.SALE_INVOICES);
queryClient.invalidateQueries(t.SALE_INVOICE);
// Invalidate customers.
queryClient.invalidateQueries(t.CUSTOMERS);
// Invalidate accounts.
queryClient.invalidateQueries(t.ITEMS);
queryClient.invalidateQueries(t.ITEM);
// Invalidate settings.
queryClient.invalidateQueries([t.SETTING, t.SETTING_INVOICES]);
// Invalidate financial reports.
queryClient.invalidateQueries(t.FINANCIAL_REPORT);
// Invalidate transactions by reference.
queryClient.invalidateQueries(t.TRANSACTIONS_BY_REFERENCE);
// Invalidate accounts.
queryClient.invalidateQueries(t.ACCOUNTS);
queryClient.invalidateQueries(t.ACCOUNT);
// Invalidate reconcile.
queryClient.invalidateQueries(t.RECONCILE_CREDIT_NOTE);
queryClient.invalidateQueries(t.RECONCILE_CREDIT_NOTES);
// Invalidate
queryClient.invalidateQueries(t.ITEM_ASSOCIATED_WITH_INVOICES);
// Invalidate item warehouses.
queryClient.invalidateQueries(t.ITEM_WAREHOUSES_LOCATION);
// Invalidate mutate base currency abilities.
queryClient.invalidateQueries(t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES);
};
function commonInvalidateQueries(queryClient: ReturnType<typeof useQueryClient>) {
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICES] });
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICE] });
queryClient.invalidateQueries({ queryKey: [t.CUSTOMERS] });
queryClient.invalidateQueries({ queryKey: [t.ITEMS] });
queryClient.invalidateQueries({ queryKey: [t.ITEM] });
queryClient.invalidateQueries({ queryKey: [t.SETTING, t.SETTING_INVOICES] });
queryClient.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
queryClient.invalidateQueries({ queryKey: [t.TRANSACTIONS_BY_REFERENCE] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNTS] });
queryClient.invalidateQueries({ queryKey: [t.ACCOUNT] });
queryClient.invalidateQueries({ queryKey: [t.RECONCILE_CREDIT_NOTE] });
queryClient.invalidateQueries({ queryKey: [t.RECONCILE_CREDIT_NOTES] });
queryClient.invalidateQueries({ queryKey: [t.ITEM_ASSOCIATED_WITH_INVOICES] });
queryClient.invalidateQueries({ queryKey: [t.ITEM_WAREHOUSES_LOCATION] });
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATION_MUTATE_BASE_CURRENCY_ABILITIES] });
}
/**
* Creates a new sale invoice.
*/
export function useCreateInvoice(props) {
export function useCreateInvoice(
props?: UseMutationOptions<void, Error, CreateSaleInvoiceBody>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((values) => apiRequest.post('sale-invoices', values), {
onSuccess: (res, values) => {
// Invalidate invoice customer.
queryClient.invalidateQueries([t.CUSTOMER, values.customer_id]);
// Invalidate estimates.
queryClient.invalidateQueries(t.SALE_ESTIMATES);
queryClient.invalidateQueries(t.SALE_ESTIMATE);
// Common invalidate queries.
return useMutation({
mutationFn: (values: CreateSaleInvoiceBody) => createSaleInvoice(fetcher, values),
onSuccess: (_data, values) => {
const customerId = (values as { customer_id?: number }).customer_id;
if (customerId != null) {
queryClient.invalidateQueries({ queryKey: [t.CUSTOMER, customerId] });
}
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATES] });
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATE] });
commonInvalidateQueries(queryClient);
},
...props,
@@ -80,45 +86,40 @@ export function useCreateInvoice(props) {
/**
* Edits the given sale invoice.
*/
export function useEditInvoice(props) {
export function useEditInvoice(
props?: UseMutationOptions<void, Error, [number, EditSaleInvoiceBody]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
([id, values]) => apiRequest.put(`sale-invoices/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate specific sale invoice.
queryClient.invalidateQueries([t.SALE_INVOICE, id]);
// Invalidate invoice customer.
queryClient.invalidateQueries([t.CUSTOMER, values.customer_id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
return useMutation({
mutationFn: ([id, values]: [number, EditSaleInvoiceBody]) =>
editSaleInvoice(fetcher, id, values),
onSuccess: (_data, [id, values]) => {
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICE, id] });
const customerId = (values as { customer_id?: number }).customer_id;
if (customerId != null) {
queryClient.invalidateQueries({ queryKey: [t.CUSTOMER, customerId] });
}
commonInvalidateQueries(queryClient);
},
);
...props,
});
}
/**
* Deletes the given sale invoice.
*/
export function useDeleteInvoice(props) {
export function useDeleteInvoice(props?: UseMutationOptions<void, Error, number>) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.delete(`sale-invoices/${id}`), {
onSuccess: (res, id) => {
// Invalidate specific invoice.
queryClient.invalidateQueries([t.SALE_INVOICE, id]);
// Invalidate estimates.
queryClient.invalidateQueries(t.SALE_ESTIMATES);
queryClient.invalidateQueries(t.SALE_ESTIMATE);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => deleteSaleInvoice(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICE, id] });
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATES] });
queryClient.invalidateQueries({ queryKey: [t.SALE_ESTIMATE] });
commonInvalidateQueries(queryClient);
},
...props,
@@ -128,132 +129,126 @@ export function useDeleteInvoice(props) {
/**
* Deletes multiple sale invoices in bulk.
*/
export function useBulkDeleteInvoices(props) {
export function useBulkDeleteInvoices(
props?: UseMutationOptions<
void,
Error,
{ ids: number[]; skipUndeletable?: boolean }
>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
({
return useMutation({
mutationFn: ({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('sale-invoices/bulk-delete', {
ids,
skip_undeletable: skipUndeletable,
}),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}) => bulkDeleteSaleInvoices(fetcher, { ids, skipUndeletable }),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export interface ValidateBulkDeleteInvoicesResponse {
deletableCount: number;
nonDeletableCount: number;
deletableIds: number[];
nonDeletableIds: number[];
}
export type ValidateBulkDeleteInvoicesResponse = ValidateBulkDeleteSaleInvoicesResponse;
export function useValidateBulkDeleteInvoices(
props?: UseMutationOptions<
ValidateBulkDeleteInvoicesResponse,
Error,
number[]
>,
props?: UseMutationOptions<ValidateBulkDeleteInvoicesResponse, Error, number[]>
) {
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation<
ValidateBulkDeleteInvoicesResponse,
Error,
number[]
>(
(ids) =>
apiRequest
.post('sale-invoices/validate-bulk-delete', { ids })
.then((res) => transformToCamelCase(res.data)),
props,
);
return useMutation({
mutationFn: (ids: number[]) => validateBulkDeleteSaleInvoices(fetcher, ids),
...props,
});
}
const transformInvoices = (res) => ({
invoices: res.data.sales_invoices,
pagination: transformPagination(res.data.pagination),
filterMeta: res.data.filter_meta,
});
function transformInvoicesList(res: SaleInvoicesListResponse) {
const data = res as {
data?: unknown[];
sales_invoices?: unknown[];
salesInvoices?: unknown[];
pagination?: unknown;
filter_meta?: Record<string, unknown>;
filterMeta?: Record<string, unknown>;
};
const invoices =
data?.data ??
data?.sales_invoices ??
data?.salesInvoices ??
[];
return {
invoices,
pagination: transformPagination(data?.pagination ?? {}),
filterMeta: data?.filter_meta ?? data?.filterMeta ?? {},
};
}
/**
* Retrieve sale invoices list with pagination meta.
*/
export function useInvoices(query, props) {
return useRequestQuery(
[t.SALE_INVOICES, query],
{ method: 'get', url: 'sale-invoices', params: query },
export function useInvoices(
query?: GetSaleInvoicesQuery,
props?: UseQueryOptions<
{
select: transformInvoices,
defaultData: {
invoices: [],
pagination: {
page: 1,
pageSize: 20,
total: 0,
},
filterMeta: {},
},
...props,
invoices: unknown[];
pagination: ReturnType<typeof transformPagination>;
filterMeta: Record<string, unknown>;
},
);
Error
>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.SALE_INVOICES, query],
queryFn: () => fetchSaleInvoices(fetcher, query).then(transformInvoicesList),
...props,
});
}
/**
* Marks the sale invoice as delivered.
*/
export function useDeliverInvoice(props) {
export function useDeliverInvoice(props?: UseMutationOptions<void, Error, number>) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(
(invoiceId) => apiRequest.post(`sale-invoices/${invoiceId}/deliver`),
{
onSuccess: (res, invoiceId) => {
// Invalidate specific invoice.
queryClient.invalidateQueries([t.SALE_INVOICE, invoiceId]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
return useMutation({
mutationFn: (invoiceId: number) => deliverSaleInvoice(fetcher, invoiceId),
onSuccess: (_data, invoiceId) => {
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICE, invoiceId] });
commonInvalidateQueries(queryClient);
},
);
...props,
});
}
/**
* Retrieve the sale invoice details.
* @param {number} invoiceId - Invoice id.
*/
export function useInvoice(invoiceId, props, requestProps) {
return useRequestQuery(
[t.SALE_INVOICE, invoiceId],
{ method: 'get', url: `sale-invoices/${invoiceId}`, ...requestProps },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
export function useInvoice(
invoiceId: number | null | undefined,
props?: UseQueryOptions<SaleInvoice, Error>,
requestProps?: Record<string, unknown>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.SALE_INVOICE, invoiceId],
queryFn: () => fetchSaleInvoice(fetcher, invoiceId as number),
enabled: invoiceId != null,
...requestProps,
...props,
});
}
/**
* Retrieve the invoice pdf document data.
*/
export function usePdfInvoice(invoiceId) {
export function usePdfInvoice(invoiceId: number) {
return useRequestPdf({
url: `sale-invoices/${invoiceId}`,
});
@@ -262,49 +257,41 @@ export function usePdfInvoice(invoiceId) {
interface GetInvoiceHtmlResponse {
htmlContent: string;
}
/**
* Retrieves the invoice html content.
* @param {number} invoiceId
* @param {UseQueryOptions<GetInvoiceHtmlResponse>} options
* @returns {UseQueryResult<GetInvoiceHtmlResponse>}
*/
export const useInvoiceHtml = (
export function useInvoiceHtml(
invoiceId: number,
options?: UseQueryOptions<GetInvoiceHtmlResponse>,
): UseQueryResult<GetInvoiceHtmlResponse> => {
const apiRequest = useApiRequest();
options?: UseQueryOptions<GetInvoiceHtmlResponse, Error>
): UseQueryResult<GetInvoiceHtmlResponse, Error> {
const fetcher = useApiFetcher();
return useQuery<GetInvoiceHtmlResponse>(
['SALE_INVOICE_HTML', invoiceId],
() =>
apiRequest
.get(`sale-invoices/${invoiceId}`, {
headers: {
Accept: 'application/json+html',
},
})
.then((res) => transformToCamelCase(res.data)),
);
};
return useQuery({
queryKey: ['SALE_INVOICE_HTML', invoiceId],
queryFn: () =>
fetchSaleInvoiceHtml(fetcher, invoiceId).then((data: { htmlContent: string }) =>
transformToCamelCase(data) as GetInvoiceHtmlResponse
),
...options,
});
}
/**
* Retrieve due invoices of the given customer id.
* @param {number} customerId - Customer id.
* Retrieve due (receivable) invoices of the given customer id.
*/
export function useDueInvoices(customerId, props) {
return useRequestQuery(
[t.SALE_INVOICES, t.SALE_INVOICES_DUE, customerId],
{
method: 'get',
url: `sale-invoices/receivable`,
params: { customer_id: customerId },
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
export function useDueInvoices(
customerId: number | null | undefined,
props?: UseQueryOptions<unknown, Error>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.SALE_INVOICES, t.SALE_INVOICES_DUE, customerId],
queryFn: () => fetchReceivableSaleInvoices(fetcher, customerId ?? undefined),
enabled: customerId != null,
...props,
});
}
export function useRefreshInvoices() {
@@ -312,102 +299,95 @@ export function useRefreshInvoices() {
return {
refresh: () => {
queryClient.invalidateQueries(t.SALE_INVOICES);
queryClient.invalidateQueries({ queryKey: [t.SALE_INVOICES] });
},
};
}
export function useCreateBadDebt(props) {
export function useCreateBadDebt(
props?: UseMutationOptions<void, Error, [number, Record<string, unknown>]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, Record<string, unknown>]) =>
writeOffSaleInvoice(fetcher, id, values),
onSuccess: (_data, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.BAD_DEBT, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
export function useCancelBadDebt(props?: UseMutationOptions<void, Error, number>) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => cancelWrittenOffSaleInvoice(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.CANCEL_BAD_DEBT, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
// Not in OpenAPI schema for sale-invoices; keep using apiRequest.
export function useCreateNotifyInvoiceBySMS(
props?: UseMutationOptions<unknown, Error, [number, Record<string, unknown>]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.post(`sale-invoices/${id}/writeoff`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate
queryClient.invalidateQueries([t.BAD_DEBT, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
return useMutation({
mutationFn: ([id, values]: [number, Record<string, unknown>]) =>
apiRequest.post(`sale-invoices/${id}/notify-by-sms`, values, {}),
onSuccess: (_data, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.NOTIFY_SALE_INVOICE_BY_SMS, id] });
commonInvalidateQueries(queryClient);
},
);
...props,
});
}
export function useCancelBadDebt(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(id) => apiRequest.post(`sale-invoices/${id}/cancel-writeoff`),
{
onSuccess: (res, id) => {
// Invalidate
queryClient.invalidateQueries([t.CANCEL_BAD_DEBT, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export function useCreateNotifyInvoiceBySMS(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) =>
apiRequest.post(`sale-invoices/${id}/notify-by-sms`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate
queryClient.invalidateQueries([t.NOTIFY_SALE_INVOICE_BY_SMS, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export function useInvoiceSMSDetail(invoiceId, query, props) {
// Not in OpenAPI schema for sale-invoices; keep using useRequestQuery.
export function useInvoiceSMSDetail(
invoiceId: number,
query?: Record<string, unknown>,
props?: Record<string, unknown>
) {
return useRequestQuery(
[t.SALE_INVOICE_SMS_DETAIL, invoiceId, query],
{
method: 'get',
url: `sale-invoices/${invoiceId}/sms-details`,
params: query,
},
} as { method: string; url: string; params?: Record<string, unknown> },
{
select: (res) => res.data,
select: (res: { data: unknown }) => res.data,
defaultData: {},
...props,
},
}
);
}
export function useInvoicePaymentTransactions(invoiceId, props) {
return useRequestQuery(
[t.SALE_INVOICE_PAYMENT_TRANSACTIONS, invoiceId],
{
method: 'get',
url: `sale-invoices/${invoiceId}/payments`,
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
export function useInvoicePaymentTransactions(
invoiceId: number,
props?: UseQueryOptions<unknown, Error>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.SALE_INVOICE_PAYMENT_TRANSACTIONS, invoiceId],
queryFn: () => fetchInvoicePayments(fetcher, invoiceId),
...props,
});
}
// # Send sale invoice mail.
// ------------------------------
export interface SendSaleInvoiceMailValues {
id: number;
values: {
@@ -419,12 +399,9 @@ export interface SendSaleInvoiceMailValues {
attachInvoice?: boolean;
};
}
export interface SendSaleInvoiceMailResponse { }
/**
* Sends the sale invoice mail.
* @param {UseMutationOptions<SendSaleInvoiceMailValues, Error, SendSaleInvoiceMailResponse>}
* @returns {UseMutationResult<SendSaleInvoiceMailResponse, Error, SendSaleInvoiceMailValues>}
*/
export type SendSaleInvoiceMailResponse = void;
export function useSendSaleInvoiceMail(
options?: UseMutationOptions<
SendSaleInvoiceMailResponse,
@@ -437,37 +414,25 @@ export function useSendSaleInvoiceMail(
SendSaleInvoiceMailValues
> {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation<
SendSaleInvoiceMailResponse,
Error,
SendSaleInvoiceMailValues
>(
(value) => apiRequest.post(`sale-invoices/${value.id}/mail`, value.values),
{
onSuccess: (res) => {
commonInvalidateQueries(queryClient);
},
...options,
},
);
return useMutation({
mutationFn: (value: SendSaleInvoiceMailValues) =>
sendSaleInvoiceMail(fetcher, value.id, value.values),
onSuccess: () => commonInvalidateQueries(queryClient),
...options,
});
}
// # Get sale invoice default options.
// --------------------------------------
// # Get sale invoice mail state.
export interface GetSaleInvoiceDefaultOptionsResponse {
companyName: string;
companyLogoUri: string;
customerName: string;
dueDate: string;
dueDateFormatted: string;
dueAmount: number;
dueAmountFormatted: string;
entries: Array<{
quantity: number;
quantityFormatted: string;
@@ -477,76 +442,63 @@ export interface GetSaleInvoiceDefaultOptionsResponse {
totalFormatted: string;
}>;
formatArgs: Record<string, string>;
from: string[];
to: string[];
invoiceDate: string;
invoiceDateFormatted: string;
invoiceNo: string;
message: string;
subject: string;
subtotal: number;
subtotalFormatted: string;
discountAmount: number;
discountAmountFormatted: string;
discountLabel: string;
discountPercentage: number;
discountPercentageFormatted: string;
adjustment: number;
adjustmentFormatted: string;
total: number;
totalFormatted: string;
attachInvoice: boolean;
primaryColor: string;
}
export function useSaleInvoiceMailState(
invoiceId: number,
options?: UseQueryOptions<GetSaleInvoiceDefaultOptionsResponse>,
): UseQueryResult<GetSaleInvoiceDefaultOptionsResponse> {
const apiRequest = useApiRequest();
options?: UseQueryOptions<GetSaleInvoiceDefaultOptionsResponse, Error>
): UseQueryResult<GetSaleInvoiceDefaultOptionsResponse, Error> {
const fetcher = useApiFetcher();
return useQuery<GetSaleInvoiceDefaultOptionsResponse>(
[t.SALE_INVOICE_DEFAULT_OPTIONS, invoiceId],
() =>
apiRequest
.get(`/sale-invoices/${invoiceId}/mail`)
.then((res) => transformToCamelCase(res.data)),
options,
);
return useQuery({
queryKey: [t.SALE_INVOICE_DEFAULT_OPTIONS, invoiceId],
queryFn: () =>
fetchSaleInvoiceMailState(fetcher, invoiceId).then((data: unknown) =>
transformToCamelCase(data) as GetSaleInvoiceDefaultOptionsResponse
),
...options,
});
}
// # Get sale invoice state.
// -------------------------------------
export interface GetSaleInvoiceStateResponse {
defaultTemplateId: number;
}
export type GetSaleInvoiceStateResponse = SaleInvoiceStateResponse;
export function useGetSaleInvoiceState(
options?: UseQueryOptions<GetSaleInvoiceStateResponse, Error>,
options?: UseQueryOptions<GetSaleInvoiceStateResponse, Error>
): UseQueryResult<GetSaleInvoiceStateResponse, Error> {
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useQuery<GetSaleInvoiceStateResponse, Error>(
['SALE_INVOICE_STATE'],
() =>
apiRequest
.get(`/sale-invoices/state`)
.then((res) => transformToCamelCase(res.data?.data)),
{ ...options },
);
return useQuery({
queryKey: ['SALE_INVOICE_STATE'],
queryFn: () =>
fetchSaleInvoiceState(fetcher).then((data: GetSaleInvoiceStateResponse & { data?: unknown }) =>
transformToCamelCase(data?.data ?? data) as GetSaleInvoiceStateResponse
),
...options,
});
}
// # Get sale invoice branding template.
// --------------------------------------
// # Get sale invoice branding template — not in OpenAPI schema; keep apiRequest.
export interface GetSaleInvoiceBrandingTemplateResponse {
id: number;
default: number;
@@ -596,16 +548,18 @@ export interface GetSaleInvoiceBrandingTemplateResponse {
export function useGetSaleInvoiceBrandingTemplate(
invoiceId: number,
options?: UseQueryOptions<GetSaleInvoiceBrandingTemplateResponse, Error>,
options?: UseQueryOptions<GetSaleInvoiceBrandingTemplateResponse, Error>
): UseQueryResult<GetSaleInvoiceBrandingTemplateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<GetSaleInvoiceBrandingTemplateResponse, Error>(
['SALE_INVOICE_BRANDING_TEMPLATE', invoiceId],
() =>
return useQuery({
queryKey: ['SALE_INVOICE_BRANDING_TEMPLATE', invoiceId],
queryFn: () =>
apiRequest
.get(`/sale-invoices/${invoiceId}/template`)
.then((res) => transformToCamelCase(res.data?.data)),
{ ...options },
);
.get(`/sale-invoices/${invoiceId}/template`, {})
.then((res: { data?: { data?: unknown } }) =>
transformToCamelCase(res.data?.data) as GetSaleInvoiceBrandingTemplateResponse
),
...options,
});
}
@@ -0,0 +1,132 @@
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type {
ItemCategory,
ItemCategoriesListResponse,
CreateItemCategoryBody,
EditItemCategoryBody,
} from '@bigcapital/sdk-ts';
import {
fetchItemCategories,
fetchItemCategory,
createItemCategory,
editItemCategory,
deleteItemCategory,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import t from './types';
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.ITEMS_CATEGORIES] });
queryClient.invalidateQueries({ queryKey: [t.ITEMS] });
};
export type ItemsCategoriesListResult = {
itemsCategories: unknown[];
pagination: Record<string, unknown>;
};
/**
* Creates a new item category.
*/
export function useCreateItemCategory(
props?: UseMutationOptions<void, Error, CreateItemCategoryBody>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreateItemCategoryBody) =>
createItemCategory(fetcher, values),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
/**
* Edits the item category.
*/
export function useEditItemCategory(
props?: UseMutationOptions<void, Error, [number, EditItemCategoryBody]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, EditItemCategoryBody]) =>
editItemCategory(fetcher, id, values),
onSuccess: (_data, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.ITEM_CATEGORY, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Deletes the given item category.
*/
export function useDeleteItemCategory(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => deleteItemCategory(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.ITEM_CATEGORY, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
function transformCategories(data: ItemCategoriesListResponse): ItemsCategoriesListResult {
const arr = Array.isArray(data) ? data : (data as { data?: unknown[] })?.data ?? [];
const pagination = (data as { pagination?: Record<string, unknown> })?.pagination ?? {};
return {
itemsCategories: arr,
pagination,
};
}
/**
* Retrieve the items categories.
*/
export function useItemsCategories(
query?: Record<string, unknown>,
props?: Omit<
UseQueryOptions<ItemCategoriesListResponse, Error, ItemsCategoriesListResult>,
'queryKey' | 'queryFn' | 'select'
>
) {
const fetcher = useApiFetcher();
return useQuery<ItemCategoriesListResponse, Error, ItemsCategoriesListResult>({
queryKey: [t.ITEMS_CATEGORIES, query],
queryFn: () => fetchItemCategories(fetcher),
select: transformCategories,
...props,
});
}
/**
* Retrieve the item category details.
*/
export function useItemCategory(
id: number | null | undefined,
props?: Omit<UseQueryOptions<ItemCategory>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ITEM_CATEGORY, id],
queryFn: () => fetchItemCategory(fetcher, id!),
enabled: id != null,
...props,
});
}
+213 -235
View File
@@ -1,8 +1,37 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { transformPagination, transformResponse, transformToCamelCase } from '@/utils';
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type {
Item,
CreateItemBody,
EditItemBody,
BulkDeleteItemsBody,
ValidateBulkDeleteItemsResponse,
ItemsListResponse,
} from '@bigcapital/sdk-ts';
import {
fetchItems,
fetchItem,
fetchItemInvoices,
fetchItemBills,
fetchItemEstimates,
fetchItemReceipts,
fetchItemWarehouses,
createItem,
editItem,
deleteItem,
inactivateItem,
activateItem,
validateBulkDeleteItems,
bulkDeleteItems,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import { transformPagination, transformResponse, transformToCamelCase } from '@/utils';
import t from './types';
const DEFAULT_PAGINATION = {
@@ -11,306 +40,255 @@ const DEFAULT_PAGINATION = {
pagesCount: 0,
};
// Common invalidate queries.
const commonInvalidateQueries = (queryClient) => {
// Invalidate items.
queryClient.invalidateQueries(t.ITEMS);
// Invalidate items categories.
queryClient.invalidateQueries(t.ITEMS_CATEGORIES);
const commonInvalidateQueries = (queryClient: ReturnType<typeof useQueryClient>) => {
queryClient.invalidateQueries({ queryKey: [t.ITEMS] });
queryClient.invalidateQueries({ queryKey: [t.ITEMS_CATEGORIES] });
};
/**
* Creates a new item.
*/
export function useCreateItem(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
export type ItemsListResult = {
items: unknown[];
pagination: typeof DEFAULT_PAGINATION;
filterMeta: Record<string, unknown>;
};
return useMutation((values) => apiRequest.post('items', values), {
onSuccess: (res, values) => {
export function useCreateItem(
props?: UseMutationOptions<void, Error, CreateItemBody>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreateItemBody) => createItem(fetcher, values),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useEditItem(
props?: UseMutationOptions<void, Error, [number, EditItemBody]>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, EditItemBody]) =>
editItem(fetcher, id, values),
onSuccess: (_data, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.ITEM, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Edits the given item.
*/
export function useEditItem(props) {
export function useDeleteItem(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation(([id, values]) => apiRequest.put(`items/${id}`, values), {
onSuccess: (res, [id, values]) => {
// Invalidate specific item.
queryClient.invalidateQueries([t.ITEM, id]);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => deleteItem(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.ITEM, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Deletes the given item.
*/
export function useDeleteItem(props) {
export function useBulkDeleteItems(
props?: UseMutationOptions<void, Error, { ids: number[]; skipUndeletable?: boolean }>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.delete(`items/${id}`), {
onSuccess: (res, id) => {
// Invalidate specific item.
queryClient.invalidateQueries([t.ITEM, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Deletes multiple items in bulk.
*/
export function useBulkDeleteItems(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
({
return useMutation({
mutationFn: ({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('items/bulk-delete', {
ids,
skip_undeletable: skipUndeletable,
}),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}) => bulkDeleteItems(fetcher, { ids, skipUndeletable } as BulkDeleteItemsBody),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
/**
* Validates which items can be deleted in bulk.
*/
export function useValidateBulkDeleteItems(props) {
const apiRequest = useApiRequest();
export function useValidateBulkDeleteItems(
props?: UseMutationOptions<ValidateBulkDeleteItemsResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
return useMutation(
(ids: number[]) =>
apiRequest.post('items/validate-bulk-delete', { ids }).then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeleteItems(fetcher, { ids, skipUndeletable: false } as BulkDeleteItemsBody).then(
(res) => transformToCamelCase(res as Record<string, unknown>) as ValidateBulkDeleteItemsResponse
),
...props,
});
}
/**
* Activate the given item.
*/
export function useActivateItem(props) {
export function useActivateItem(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.post(`items/${id}/activate`), {
onSuccess: (res, id) => {
// Invalidate specific item.
queryClient.invalidateQueries([t.ITEM, id]);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => activateItem(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.ITEM, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Inactivate the given item.
*/
export function useInactivateItem(props) {
export function useInactivateItem(
props?: UseMutationOptions<void, Error, number>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
const fetcher = useApiFetcher();
return useMutation((id) => apiRequest.post(`items/${id}/inactivate`), {
onSuccess: (res, id) => {
// Invalidate specific item.
queryClient.invalidateQueries([t.ITEM, id]);
// Common invalidate queries.
return useMutation({
mutationFn: (id: number) => inactivateItem(fetcher, id),
onSuccess: (_data, id) => {
queryClient.invalidateQueries({ queryKey: [t.ITEM, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
// Transformes items response.
const transformItemsResponse = (response) => {
return {
items: response.data.items,
pagination: transformPagination(
transformResponse(response.data.pagination),
),
filterMeta: transformResponse(response.data.filter_meta),
function transformItemsList(res: ItemsListResponse): ItemsListResult {
const data = res as {
items?: unknown[];
pagination?: unknown;
filter_meta?: Record<string, unknown>;
};
};
return {
items: data?.items ?? [],
pagination: transformPagination(
transformResponse(data?.pagination ?? {})
) as typeof DEFAULT_PAGINATION,
filterMeta: transformResponse(data?.filter_meta ?? {}) as Record<string, unknown>,
};
}
/**
* Retrieves items list.
*/
export function useItems(query, props) {
return useRequestQuery(
[t.ITEMS, query],
{
method: 'get',
url: 'items',
params: { ...query },
},
{
select: transformItemsResponse,
defaultData: {
items: [],
pagination: DEFAULT_PAGINATION,
filterMeta: {},
},
...props,
},
);
export function useItems(
query?: Record<string, unknown>,
props?: Omit<UseQueryOptions<ItemsListResult>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ITEMS, query],
queryFn: () =>
(fetchItems as (f: ReturnType<typeof useApiFetcher>, q?: Record<string, unknown>) => Promise<ItemsListResponse>)(
fetcher,
query
).then(transformItemsList),
...props,
});
}
export function useRefreshItems() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries(t.ITEMS);
},
refresh: () => queryClient.invalidateQueries({ queryKey: [t.ITEMS] }),
};
}
/**
* Retrieve details of the given item.
* @param {number} id - Item id.
*/
export function useItem(id, props) {
return useRequestQuery(
[t.ITEM, id],
{
method: 'get',
url: `items/${id}`,
},
{
select: (response) => response.data,
defaultData: {},
...props,
},
);
export function useItem(
id: number | null | undefined,
props?: Omit<UseQueryOptions<Item>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ITEM, id],
queryFn: () => fetchItem(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useItemAssociatedInvoiceTransactions(id, props) {
return useRequestQuery(
[t.ITEM_ASSOCIATED_WITH_INVOICES, id],
{
method: 'get',
url: `items/${id}/invoices`,
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
export function useItemAssociatedInvoiceTransactions(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ITEM_ASSOCIATED_WITH_INVOICES, id],
queryFn: () => fetchItemInvoices(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useItemAssociatedEstimateTransactions(id, props) {
return useRequestQuery(
[t.ITEM_ASSOCIATED_WITH_ESTIMATES, id],
{
method: 'get',
url: `items/${id}/estimates`,
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
export function useItemAssociatedEstimateTransactions(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ITEM_ASSOCIATED_WITH_ESTIMATES, id],
queryFn: () => fetchItemEstimates(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useItemAssociatedReceiptTransactions(id, props) {
return useRequestQuery(
[t.ITEM_ASSOCIATED_WITH_RECEIPTS, id],
{
method: 'get',
url: `items/${id}/receipts`,
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
}
export function useItemAssociatedBillTransactions(id, props) {
return useRequestQuery(
[t.ITEMS_ASSOCIATED_WITH_BILLS, id],
{
method: 'get',
url: `items/${id}/bills`,
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
export function useItemAssociatedReceiptTransactions(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ITEM_ASSOCIATED_WITH_RECEIPTS, id],
queryFn: () => fetchItemReceipts(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useItemWarehouseLocation(id, props) {
return useRequestQuery(
[t.ITEM_WAREHOUSES_LOCATION, id],
{
method: 'get',
url: `items/${id}/warehouses`,
},
{
select: (res) => res.data.item_warehouses,
defaultData: [],
...props,
},
);
export function useItemAssociatedBillTransactions(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ITEMS_ASSOCIATED_WITH_BILLS, id],
queryFn: () => fetchItemBills(fetcher, id!),
enabled: id != null,
...props,
});
}
/**
*
* @param {*} id
* @param {*} query
* @param {*} props
* @returns
*/
export function useItemInventoryCost(query, props) {
export function useItemWarehouseLocation(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.ITEM_WAREHOUSES_LOCATION, id],
queryFn: () => fetchItemWarehouses(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useItemInventoryCost(
query?: Record<string, unknown>,
props?: Omit<UseQueryOptions<unknown[]>, 'queryKey' | 'queryFn'>
) {
return useRequestQuery(
[t.ITEM_INVENTORY_COST, query],
{ method: 'get', url: 'inventory-cost/items', params: { ...query } },
{
method: 'get',
url: `inventory-cost/items`,
params: { ...query },
},
{
select: (res) => res.data.costs,
select: (res: { data?: { costs?: unknown[] } }) => res.data?.costs ?? [],
defaultData: [],
...props,
},
}
);
}
@@ -1,109 +0,0 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import useApiRequest from '../useRequest';
import t from './types';
const commonInvalidateQueries = (queryClient) => {
// Invalidate items categories.
queryClient.invalidateQueries(t.ITEMS_CATEGORIES);
// Invalidate items.
queryClient.invalidateQueries(t.ITEMS);
};
/**
* Creates a new item category.
*/
export function useCreateItemCategory(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('item-categories', values), {
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Edits the item category.
*/
export function useEditItemCategory(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`item-categories/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate specific item category.
queryClient.invalidateQueries([t.ITEM_CATEGORY, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
/**
* Deletes the given item category.
*/
export function useDeleteItemCategory(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`item-categories/${id}`), {
onSuccess: (res, id) => {
// Invalidate specific item category.
queryClient.invalidateQueries([t.ITEM_CATEGORY, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
});
}
const transformCategories = (res) => ({
itemsCategories: res.data.data,
pagination: res.data.pagination,
});
/**
* Retrieve the items categories.
*/
export function useItemsCategories(query, props) {
return useRequestQuery(
[t.ITEMS_CATEGORIES, query],
{ method: 'get', url: `item-categories`, params: query },
{
select: transformCategories,
defaultData: {
itemsCategories: [],
pagination: {},
},
...props,
},
);
}
/**
* Retrieve the item category details.
* @param {number} id - Item category.
*/
export function useItemCategory(id, props) {
return useRequestQuery(
[t.ITEM_CATEGORY, id],
{ method: 'get', url: `item-categories/${id}` },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
@@ -1,17 +1,19 @@
// @ts-nocheck
import { useQueryClient, useMutation } from 'react-query';
import { useQueryClient, useMutation, useQuery } from '@tanstack/react-query';
import { fetchLandedCostTransactions } from '@bigcapital/sdk-ts';
import useApiRequest from '../useRequest';
import { useApiFetcher } from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import t from './types';
const commonInvalidateQueries = (queryClient) => {
// Invalidate bills.
queryClient.invalidateQueries(t.BILLS);
queryClient.invalidateQueries(t.BILL);
queryClient.invalidateQueries({ queryKey: [t.BILLS] });
queryClient.invalidateQueries({ queryKey: [t.BILL] });
// Invalidate landed cost.
queryClient.invalidateQueries(t.LANDED_COST);
queryClient.invalidateQueries(t.LANDED_COST_TRANSACTION);
queryClient.invalidateQueries({ queryKey: [t.LANDED_COST] });
queryClient.invalidateQueries({ queryKey: [t.LANDED_COST_TRANSACTION] });
};
/**
@@ -21,11 +23,9 @@ export function useCreateLandedCost(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) =>
return useMutation({ mutationFn: ([id, values]) =>
apiRequest.post(`landed-cost/bills/${id}/allocate`, values),
{
onSuccess: (res, id) => {
onSuccess: (res, id) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
@@ -41,11 +41,9 @@ export function useDeleteLandedCost(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(landedCostId) =>
return useMutation({ mutationFn: (landedCostId) =>
apiRequest.delete(`landed-cost/${landedCostId}`),
{
onSuccess: (res, id) => {
onSuccess: (res, id) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
@@ -58,18 +56,13 @@ export function useDeleteLandedCost(props) {
* Retrieve the landed cost transactions.
*/
export function useLandedCostTransaction(query, props) {
return useRequestQuery(
[t.LANDED_COST, query],
{
method: 'get',
url: 'landed-cost/transactions',
params: { transaction_type: query },
},
{
select: (res) => res.data,
...props,
},
);
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.LANDED_COST, query],
queryFn: () =>
fetchLandedCostTransactions(fetcher, { transaction_type: query } as Record<string, unknown>),
...props,
});
}
/**
@@ -0,0 +1,214 @@
// @ts-nocheck
import {
useMutation,
useQuery,
useQueryClient,
} from '@tanstack/react-query';
import type {
CreateManualJournalBody,
EditManualJournalBody,
ManualJournalsListResponse,
} from '@bigcapital/sdk-ts';
import {
fetchManualJournals,
fetchManualJournal,
createManualJournal,
editManualJournal,
deleteManualJournal,
publishManualJournal,
bulkDeleteManualJournals,
validateBulkDeleteManualJournals,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { transformPagination, transformToCamelCase } from '@/utils';
import t from './types';
const commonInvalidateQueries = (client) => {
// Invalidate manual journals.
client.invalidateQueries({ queryKey: [t.MANUAL_JOURNALS] });
// Invalidate customers.
client.invalidateQueries({ queryKey: [t.CUSTOMERS] });
client.invalidateQueries({ queryKey: [t.CUSTOMER] });
// Invalidate vendors.
client.invalidateQueries({ queryKey: [t.VENDORS] });
client.invalidateQueries({ queryKey: [t.VENDOR] });
// Invalidate accounts.
client.invalidateQueries({ queryKey: [t.ACCOUNTS] });
client.invalidateQueries({ queryKey: [t.ACCOUNT] });
// Invalidate settings.
client.invalidateQueries([t.SETTING, t.SETTING_MANUAL_JOURNALS]);
// Invalidate financial reports.
client.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
// Invalidate the cashflow transactions.
client.invalidateQueries({ queryKey: [t.CASH_FLOW_TRANSACTIONS] });
client.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY] });
};
/**
* Creates a new manual journal.
*/
export function useCreateJournal(props) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreateManualJournalBody) =>
createManualJournal(fetcher, values),
onSuccess: () => {
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Edits the given manual journal.
*/
export function useEditJournal(props) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, EditManualJournalBody]) =>
editManualJournal(fetcher, id, values),
onSuccess: (_res, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.MANUAL_JOURNAL, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Deletes the given manual journal.
*/
export function useDeleteJournal(props) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => deleteManualJournal(fetcher, id),
onSuccess: (_res, id) => {
queryClient.invalidateQueries({ queryKey: [t.MANUAL_JOURNAL, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Deletes multiple manual journals in bulk.
*/
export function useBulkDeleteManualJournals(props) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
bulkDeleteManualJournals(fetcher, { ids, skipUndeletable }),
onSuccess: () => {
commonInvalidateQueries(queryClient);
},
...props,
});
}
export function useValidateBulkDeleteManualJournals(props) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeleteManualJournals(fetcher, { ids }).then((res) =>
transformToCamelCase(res)
),
...props,
});
}
/**
* Publishes the given manual journal.
*/
export function usePublishJournal(props) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => publishManualJournal(fetcher, id),
onSuccess: (_res, id) => {
queryClient.invalidateQueries({ queryKey: [t.MANUAL_JOURNAL, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
function transformJournalsList(
data: ManualJournalsListResponse
): {
manualJournals: unknown[];
pagination: ReturnType<typeof transformPagination>;
filterMeta: Record<string, unknown>;
} {
const raw = data as {
manual_journals?: unknown[];
manualJournals?: unknown[];
pagination?: unknown;
filter_meta?: Record<string, unknown>;
filterMeta?: Record<string, unknown>;
};
return {
manualJournals: raw?.manual_journals ?? raw?.manualJournals ?? [],
pagination: transformPagination(raw?.pagination ?? {}),
filterMeta: raw?.filter_meta ?? raw?.filterMeta ?? {},
};
}
/**
* Retrieve the manual journals with pagination meta.
*/
export function useJournals(query, props) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.MANUAL_JOURNALS, query],
queryFn: () => fetchManualJournals(fetcher, query),
select: transformJournalsList,
...props,
});
}
/**
* Retrieve the manual journal details.
*/
export function useJournal(id, props) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.MANUAL_JOURNAL, id],
queryFn: () => fetchManualJournal(fetcher, id),
enabled: id != null,
...props,
});
}
export function useRefreshJournals() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries({ queryKey: [t.MANUAL_JOURNALS] });
},
};
}
@@ -1,200 +0,0 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination, transformToCamelCase } from '@/utils';
import useApiRequest from '../useRequest';
import t from './types';
const commonInvalidateQueries = (client) => {
// Invalidate manual journals.
client.invalidateQueries(t.MANUAL_JOURNALS);
// Invalidate customers.
client.invalidateQueries(t.CUSTOMERS);
client.invalidateQueries(t.CUSTOMER);
// Invalidate vendors.
client.invalidateQueries(t.VENDORS);
client.invalidateQueries(t.VENDOR);
// Invalidate accounts.
client.invalidateQueries(t.ACCOUNTS);
client.invalidateQueries(t.ACCOUNT);
// Invalidate settings.
client.invalidateQueries([t.SETTING, t.SETTING_MANUAL_JOURNALS]);
// Invalidate financial reports.
client.invalidateQueries(t.FINANCIAL_REPORT);
// Invalidate the cashflow transactions.
client.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
client.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
};
/**
* Creates a new manual journal.
*/
export function useCreateJournal(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('manual-journals', values), {
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Edits the given manual journal.
*/
export function useEditJournal(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`manual-journals/${id}`, values),
{
onSuccess: (res, [id]) => {
// Invalidate specific manual journal.
queryClient.invalidateQueries(t.MANUAL_JOURNAL, id);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
/**
* Deletes the given manual jouranl.
*/
export function useDeleteJournal(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`manual-journals/${id}`), {
onSuccess: (res, id) => {
// Invalidate specific manual journal.
queryClient.invalidateQueries(t.MANUAL_JOURNAL, id);
commonInvalidateQueries(queryClient);
},
...props,
});
}
/**
* Deletes multiple manual journals in bulk.
*/
export function useBulkDeleteManualJournals(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('manual-journals/bulk-delete', {
ids,
skip_undeletable: skipUndeletable,
}),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export function useValidateBulkDeleteManualJournals(props) {
const apiRequest = useApiRequest();
return useMutation(
(ids: number[]) =>
apiRequest
.post('manual-journals/validate-bulk-delete', { ids })
.then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
}
/**
* Publishes the given manual journal.
*/
export function usePublishJournal(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.patch(`manual-journals/${id}/publish`), {
onSuccess: (res, id) => {
// Invalidate specific manual journal.
queryClient.invalidateQueries(t.MANUAL_JOURNAL, id);
commonInvalidateQueries(queryClient);
},
...props,
});
}
const transformJournals = (response) => ({
manualJournals: response.data.manual_journals,
pagination: transformPagination(response.data.pagination),
filterMeta: response.data.filter_meta,
});
/**
* Retrieve the manual journals with pagination meta.
*/
export function useJournals(query, props) {
return useRequestQuery(
[t.MANUAL_JOURNALS, query],
{ method: 'get', url: 'manual-journals', params: query },
{
select: transformJournals,
defaultData: {
manualJournals: [],
pagination: {},
filterMeta: {},
},
...props,
},
);
}
/**
* Retrieve the manual journal details.
*/
export function useJournal(id, props) {
return useRequestQuery(
[t.MANUAL_JOURNAL, id],
{ method: 'get', url: `manual-journals/${id}` },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
export function useRefreshJournals() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries(t.MANUAL_JOURNALS);
},
};
}
@@ -4,7 +4,7 @@ import {
UseMutationOptions,
UseMutationResult,
useQueryClient,
} from 'react-query';
} from '@tanstack/react-query';
import useApiRequest from '../useRequest';
import {
useSetAuthToken,
@@ -40,8 +40,7 @@ export function useCreateOneClickDemo(
return useMutation<CreateOneClickDemoRes, Error, CreateOneClickDemoValues>(
() => apiRequest.post(`/demo/one_click`),
{
onSuccess: (res, id) => { },
onSuccess: (res, id) => { },
...props,
},
);
@@ -76,8 +75,7 @@ export function useOneClickDemoSignin(
return useMutation<OneClickSigninDemoRes, Error, OneClickSigninDemoValues>(
({ demoId }) =>
apiRequest.post(`/demo/one_click_signin`, { demo_id: demoId }),
{
onSuccess: (res, id) => {
onSuccess: (res, id) => {
// Set authentication cookies.
setAuthLoginCookies(res.data);
@@ -1,9 +1,11 @@
// @ts-nocheck
import { useMutation, useQueryClient } from 'react-query';
import { useEffect } from 'react';
import { useMutation, useQuery, useQueryClient } from '@tanstack/react-query';
import { batch } from 'react-redux';
import { omit } from 'lodash';
import { fetchOrganizationCurrent } from '@bigcapital/sdk-ts';
import t from './types';
import useApiRequest from '../useRequest';
import useApiRequest, { useApiFetcher } from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import { useSetOrganizations, useSetSubscriptions } from '../state';
@@ -38,27 +40,26 @@ export function useOrganizations(props) {
export function useCurrentOrganization(props) {
const setOrganizations = useSetOrganizations();
const setSubscriptions = useSetSubscriptions();
const fetcher = useApiFetcher();
return useRequestQuery(
[t.ORGANIZATION_CURRENT],
{ method: 'get', url: OrganizationRoute.Current },
{
select: (res) => res.data,
defaultData: {},
onSuccess: (data) => {
const organization = omit(data, ['subscriptions']);
const result = useQuery({
queryKey: [t.ORGANIZATION_CURRENT],
queryFn: () => fetchOrganizationCurrent(fetcher),
...props,
});
batch(() => {
// Sets subscriptions.
setSubscriptions(data.subscriptions);
useEffect(() => {
if (result.isSuccess && result.data) {
const data = result.data as { subscriptions?: unknown; [k: string]: unknown };
const organization = omit(data, ['subscriptions']);
batch(() => {
setSubscriptions(data.subscriptions);
setOrganizations([organization]);
});
}
}, [result.isSuccess, result.data, setSubscriptions, setOrganizations]);
// Sets organizations.
setOrganizations([organization]);
});
},
...props,
},
);
return result;
}
/**
@@ -68,12 +69,10 @@ export function useOrganizationSetup() {
const apiRequest = useApiRequest();
const queryClient = useQueryClient();
return useMutation(
(values) => apiRequest.post(OrganizationRoute.Build, values),
{
onSuccess: (res) => {
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
queryClient.invalidateQueries(t.ORGANIZATIONS);
return useMutation({ mutationFn: (values) => apiRequest.post(OrganizationRoute.Build, values),
onSuccess: (res) => {
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATION_CURRENT] });
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATIONS] });
},
},
);
@@ -86,12 +85,10 @@ export function useUpdateOrganization(props = {}) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(information: any) => apiRequest.put('organization', information),
{
onSuccess: () => {
queryClient.invalidateQueries(t.ORGANIZATION_CURRENT);
queryClient.invalidateQueries(t.ORGANIZATIONS);
return useMutation({ mutationFn: (information: any) => apiRequest.put('organization', information),
onSuccess: () => {
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATION_CURRENT] });
queryClient.invalidateQueries({ queryKey: [t.ORGANIZATIONS] });
},
...props,
},
@@ -6,7 +6,7 @@ import {
UseQueryResult,
useMutation,
useQuery,
} from 'react-query';
} from '@tanstack/react-query';
import useApiRequest from '../useRequest';
import { transformToCamelCase, transfromToSnakeCase } from '@/utils';
@@ -50,8 +50,7 @@ export function useCreatePaymentLink(
transfromToSnakeCase(values),
)
.then((res) => res.data),
{
...options,
...options,
},
);
}
@@ -137,8 +136,7 @@ export function useGetInvoicePaymentLink(
apiRequest
.get(`/payment-links/${linkId}/invoice`)
.then((res) => transformToCamelCase(res.data?.data)),
{
...options,
...options,
},
);
}
@@ -166,8 +164,7 @@ export const useCreateStripeCheckoutSession = (
> => {
const apiRequest = useApiRequest();
return useMutation(
(values: CreateCheckoutSessionValues) => {
return useMutation({ mutationFn: (values: CreateCheckoutSessionValues) => {
return apiRequest
.post(`/payment-links/${values.linkId}/stripe_checkout_session`, values)
.then(
@@ -232,8 +229,7 @@ export const useGetPaymentLinkInvoicePdf = (
headers: { accept: 'application/pdf' },
})
.then((res) => res.data),
{
...options,
...options,
},
);
};
@@ -0,0 +1,176 @@
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
} from '@tanstack/react-query';
import type {
BillPaymentsListResponse,
BillPayment,
CreateBillPaymentBody,
EditBillPaymentBody,
} from '@bigcapital/sdk-ts';
import {
fetchBillPayments,
fetchBillPayment,
createBillPayment,
editBillPayment,
deleteBillPayment,
fetchBillPaymentEditPage,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination } from '@/utils';
import t from './types';
const commonInvalidateQueries = (client: ReturnType<typeof useQueryClient>) => {
client.invalidateQueries({ queryKey: [t.PAYMENT_MADES] });
client.invalidateQueries({ queryKey: [t.PAYMENT_MADE_NEW_ENTRIES] });
client.invalidateQueries({ queryKey: [t.PAYMENT_MADE_EDIT_PAGE] });
client.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
client.invalidateQueries({ queryKey: [t.ACCOUNTS] });
client.invalidateQueries({ queryKey: [t.ACCOUNT] });
client.invalidateQueries({ queryKey: [t.BILLS] });
client.invalidateQueries({ queryKey: [t.BILL] });
client.invalidateQueries({ queryKey: [t.VENDORS] });
client.invalidateQueries({ queryKey: [t.VENDOR] });
client.invalidateQueries({ queryKey: [t.CASH_FLOW_TRANSACTIONS] });
client.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY] });
client.invalidateQueries({ queryKey: [t.BILLS_PAYMENT_TRANSACTIONS] });
};
export type PaymentMadesListResult = {
paymentMades: unknown[];
pagination: ReturnType<typeof transformPagination>;
filterMeta: Record<string, unknown>;
};
function transformPaymentMades(data: BillPaymentsListResponse): PaymentMadesListResult {
const raw = data as {
bill_payments?: unknown[];
pagination?: unknown;
filter_meta?: Record<string, unknown>;
};
return {
paymentMades: raw.bill_payments ?? (data as { data?: unknown[] })?.data ?? [],
pagination: transformPagination(raw.pagination ?? {}),
filterMeta: raw.filter_meta ?? {},
};
}
export function usePaymentMades(
query?: Record<string, unknown>,
props?: Omit<
UseQueryOptions<BillPaymentsListResponse, Error, PaymentMadesListResult>,
'queryKey' | 'queryFn' | 'select'
>
) {
const fetcher = useApiFetcher();
return useQuery<BillPaymentsListResponse, Error, PaymentMadesListResult>({
queryKey: [t.PAYMENT_MADES, query],
queryFn: () => fetchBillPayments(fetcher),
select: transformPaymentMades,
...props,
});
}
export function useCreatePaymentMade(
props?: UseMutationOptions<void, Error, CreateBillPaymentBody>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreateBillPaymentBody) =>
createBillPayment(fetcher, values),
onSuccess: () => commonInvalidateQueries(client),
...props,
});
}
export function useEditPaymentMade(
props?: UseMutationOptions<void, Error, [number, EditBillPaymentBody]>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, EditBillPaymentBody]) =>
editBillPayment(fetcher, id, values),
onSuccess: (_data, [id]) => {
commonInvalidateQueries(client);
client.invalidateQueries({ queryKey: [t.PAYMENT_MADE, id] });
},
...props,
});
}
export function useDeletePaymentMade(
props?: UseMutationOptions<void, Error, number>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => deleteBillPayment(fetcher, id),
onSuccess: (_data, id) => {
commonInvalidateQueries(client);
client.invalidateQueries({ queryKey: [t.PAYMENT_MADE, id] });
},
...props,
});
}
export function usePaymentMadeEditPage(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.PAYMENT_MADE_EDIT_PAGE, id],
queryFn: () => fetchBillPaymentEditPage(fetcher, id!),
enabled: id != null,
...props,
});
}
/** New page entries uses vendor_id param; kept on useRequestQuery (schema path/param mismatch). */
export function usePaymentMadeNewPageEntries(
vendorId: number | null | undefined,
props?: Record<string, unknown>
) {
return useRequestQuery(
[t.PAYMENT_MADE_NEW_ENTRIES, vendorId],
{
method: 'get',
url: 'bill-payments/new-page/entries',
params: { vendor_id: vendorId },
},
{
select: (res: { data: unknown }) => res.data,
defaultData: [],
...props,
},
);
}
export function useRefreshPaymentMades() {
const queryClient = useQueryClient();
return {
refresh: () => queryClient.invalidateQueries({ queryKey: [t.PAYMENT_MADES] }),
};
}
export function usePaymentMade(
id: number | null | undefined,
props?: Omit<UseQueryOptions<BillPayment>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.PAYMENT_MADE, id],
queryFn: () => fetchBillPayment(fetcher, id!),
enabled: id != null,
...props,
});
}
@@ -3,7 +3,7 @@ import {
useMutation,
UseMutationOptions,
UseMutationResult,
} from 'react-query';
} from '@tanstack/react-query';
import useApiRequest from '../useRequest';
@@ -0,0 +1,369 @@
import {
useMutation,
useQueryClient,
useQuery,
UseQueryOptions,
UseQueryResult,
UseMutationOptions,
UseMutationResult,
} from '@tanstack/react-query';
import type {
PaymentsReceivedListResponse,
PaymentReceived,
CreatePaymentReceivedBody,
EditPaymentReceivedBody,
} from '@bigcapital/sdk-ts';
import {
fetchPaymentsReceived,
fetchPaymentReceived,
createPaymentReceived,
editPaymentReceived,
deletePaymentReceived,
bulkDeletePaymentsReceived,
validateBulkDeletePaymentsReceived,
fetchPaymentReceiveEditPage,
fetchPaymentReceiveMail,
sendPaymentReceiveMail,
fetchPaymentReceivedState,
} from '@bigcapital/sdk-ts';
export type BulkDeletePaymentsReceivedBody = { ids: number[]; skipUndeletable?: boolean };
export type ValidateBulkDeletePaymentsReceivedResponse = {
deletableCount: number;
nonDeletableCount: number;
deletableIds: number[];
nonDeletableIds: number[];
};
import useApiRequest, { useApiFetcher } from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination, saveInvoke, transformToCamelCase } from '@/utils';
import { useRequestPdf } from '../useRequestPdf';
import t from './types';
const commonInvalidateQueries = (client: ReturnType<typeof useQueryClient>) => {
client.invalidateQueries({ queryKey: [t.PAYMENT_RECEIVES] });
client.invalidateQueries({ queryKey: [t.PAYMENT_RECEIVE_EDIT_PAGE] });
client.invalidateQueries({ queryKey: [t.SALE_INVOICES] });
client.invalidateQueries({ queryKey: [t.SALE_INVOICE] });
client.invalidateQueries({ queryKey: [t.ACCOUNTS] });
client.invalidateQueries({ queryKey: [t.ACCOUNT] });
client.invalidateQueries({ queryKey: [t.FINANCIAL_REPORT] });
client.invalidateQueries({ queryKey: [t.TRANSACTIONS_BY_REFERENCE] });
client.invalidateQueries({ queryKey: [t.CUSTOMERS] });
client.invalidateQueries({ queryKey: [t.CUSTOMER] });
client.invalidateQueries({ queryKey: [t.CASH_FLOW_TRANSACTIONS] });
client.invalidateQueries({ queryKey: [t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY] });
client.invalidateQueries({ queryKey: [t.CREDIT_NOTE] });
client.invalidateQueries({ queryKey: [t.CREDIT_NOTES] });
client.invalidateQueries({ queryKey: [t.RECONCILE_CREDIT_NOTE] });
client.invalidateQueries({ queryKey: [t.RECONCILE_CREDIT_NOTES] });
client.invalidateQueries({ queryKey: [t.SALE_INVOICE_PAYMENT_TRANSACTIONS] });
};
export type PaymentReceivesListResult = {
paymentReceives: unknown[];
pagination: ReturnType<typeof transformPagination>;
filterMeta: Record<string, unknown>;
};
function transformPaymentReceives(data: PaymentsReceivedListResponse): PaymentReceivesListResult {
const raw = data as {
payment_receives?: unknown[];
pagination?: unknown;
filter_meta?: Record<string, unknown>;
};
return {
paymentReceives: raw.payment_receives ?? (data as { data?: unknown[] })?.data ?? [],
pagination: transformPagination(raw.pagination ?? {}),
filterMeta: raw.filter_meta ?? {},
};
}
export function usePaymentReceives(
query?: Record<string, unknown>,
props?: Omit<
UseQueryOptions<PaymentsReceivedListResponse, Error, PaymentReceivesListResult>,
'queryKey' | 'queryFn' | 'select'
>
) {
const fetcher = useApiFetcher();
return useQuery<PaymentsReceivedListResponse, Error, PaymentReceivesListResult>({
queryKey: [t.PAYMENT_RECEIVES, query],
queryFn: () => fetchPaymentsReceived(fetcher),
select: transformPaymentReceives,
...props,
});
}
export function useCreatePaymentReceive(
props?: UseMutationOptions<void, Error, CreatePaymentReceivedBody>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreatePaymentReceivedBody) =>
createPaymentReceived(fetcher, values),
onSuccess: (data, _values) => {
commonInvalidateQueries(client);
client.invalidateQueries({ queryKey: [t.SETTING, t.SETTING_PAYMENT_RECEIVES] });
saveInvoke(props?.onSuccess, data);
},
...props,
});
}
export function useEditPaymentReceive(
props?: UseMutationOptions<void, Error, [number, EditPaymentReceivedBody]>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, EditPaymentReceivedBody]) =>
editPaymentReceived(fetcher, id, values),
onSuccess: (data, [id]) => {
client.invalidateQueries({ queryKey: [t.PAYMENT_RECEIVE, id] });
commonInvalidateQueries(client);
saveInvoke(props?.onSuccess, data);
},
...props,
});
}
export function useDeletePaymentReceive(
props?: UseMutationOptions<void, Error, number>
) {
const client = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (id: number) => deletePaymentReceived(fetcher, id),
onSuccess: (data, id) => {
client.invalidateQueries({ queryKey: [t.PAYMENT_RECEIVE, id] });
commonInvalidateQueries(client);
saveInvoke(props?.onSuccess, data);
},
...props,
});
}
export function useBulkDeletePaymentReceives(
props?: UseMutationOptions<void, Error, BulkDeletePaymentsReceivedBody>
) {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (body: BulkDeletePaymentsReceivedBody) =>
bulkDeletePaymentsReceived(fetcher, body),
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export function useValidateBulkDeletePaymentReceives(
props?: UseMutationOptions<ValidateBulkDeletePaymentsReceivedResponse, Error, number[]>
) {
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (ids: number[]) =>
validateBulkDeletePaymentsReceived(fetcher, ids).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as ValidateBulkDeletePaymentsReceivedResponse
),
...props,
});
}
export function usePaymentReceive(
id: number | null | undefined,
props?: Omit<UseQueryOptions<PaymentReceived>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.PAYMENT_RECEIVE, id],
queryFn: () => fetchPaymentReceived(fetcher, id!),
enabled: id != null,
...props,
});
}
export function usePaymentReceiveEditPage(
id: number | null | undefined,
props?: Omit<UseQueryOptions<unknown>, 'queryKey' | 'queryFn'>
) {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.PAYMENT_RECEIVE_EDIT_PAGE, id],
queryFn: () => fetchPaymentReceiveEditPage(fetcher, id!),
enabled: id != null,
...props,
});
}
export function useRefreshPaymentReceive() {
const queryClient = useQueryClient();
return {
refresh: () => queryClient.invalidateQueries({ queryKey: [t.PAYMENT_RECEIVES] }),
};
}
/** Notify by SMS no SDK route in schema; kept on apiRequest. */
export function useCreateNotifyPaymentReceiveBySMS(
props?: UseMutationOptions<unknown, Error, [number, Record<string, unknown>]>
) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation({
mutationFn: ([id, values]: [number, Record<string, unknown>]) =>
apiRequest.post(`payments-received/${id}/notify-by-sms`, values, {}),
onSuccess: (_res, [id]) => {
queryClient.invalidateQueries({ queryKey: [t.NOTIFY_PAYMENT_RECEIVE_BY_SMS, id] });
commonInvalidateQueries(queryClient);
},
...props,
});
}
/** SMS detail no SDK route in schema; kept on useRequestQuery. */
export function usePaymentReceiveSMSDetail(
paymentReceiveId: number | null | undefined,
props?: Record<string, unknown>,
requestProps?: Record<string, unknown>
) {
return useRequestQuery(
[t.PAYMENT_RECEIVE_SMS_DETAIL, paymentReceiveId],
{
method: 'get',
url: `payments-received/${paymentReceiveId}/sms-details`,
...requestProps,
},
{
select: (res: { data: unknown }) => res.data,
defaultData: {},
...props,
},
);
}
export function usePdfPaymentReceive(paymentReceiveId: number) {
return useRequestPdf({ url: `payments-received/${paymentReceiveId}` });
}
interface SendPaymentReceiveMailValues {
to: string[] | string;
cc?: string[] | string;
bcc?: string[] | string;
subject: string;
message: string;
from?: string[] | string;
attachPdf?: boolean;
}
interface SendPaymentReceiveMailResponse {
success: boolean;
message?: string;
}
export function useSendPaymentReceiveMail(
props?: UseMutationOptions<
SendPaymentReceiveMailResponse,
Error,
[number, SendPaymentReceiveMailValues]
>
): UseMutationResult<
SendPaymentReceiveMailResponse,
Error,
[number, SendPaymentReceiveMailValues],
unknown
> {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
return useMutation({
mutationFn: ([id, values]: [number, SendPaymentReceiveMailValues]) =>
sendPaymentReceiveMail(fetcher, id, values as unknown as Record<string, unknown>) as Promise<SendPaymentReceiveMailResponse>,
onSuccess: () => commonInvalidateQueries(queryClient),
...props,
});
}
export interface GetPaymentReceivedMailStateResponse {
companyName: string;
companyLogoUri?: string;
primaryColor?: string;
customerName: string;
entries: Array<{ invoiceNumber: string; paidAmount: string }>;
from: Array<string>;
fromOptions: Array<{ mail: string; label: string; primary: boolean }>;
paymentDate: string;
paymentDateFormatted: string;
to: Array<string>;
toOptions: Array<{ mail: string; label: string; primary: boolean }>;
total: number;
totalFormatted: string;
subtotal: number;
subtotalFormatted: string;
paymentNumber: string;
formatArgs: Record<string, unknown>;
}
export function usePaymentReceivedMailState(
paymentReceiveId: number,
props?: UseQueryOptions<GetPaymentReceivedMailStateResponse, Error>
): UseQueryResult<GetPaymentReceivedMailStateResponse, Error> {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [t.PAYMENT_RECEIVE_MAIL_OPTIONS, paymentReceiveId],
queryFn: () =>
fetchPaymentReceiveMail(fetcher, paymentReceiveId).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as GetPaymentReceivedMailStateResponse
),
...props,
});
}
export interface PaymentReceivedStateResponse {
defaultTemplateId: number;
}
export function usePaymentReceivedState(
options?: UseQueryOptions<PaymentReceivedStateResponse, Error>
): UseQueryResult<PaymentReceivedStateResponse, Error> {
const fetcher = useApiFetcher();
return useQuery({
queryKey: ['PAYMENT_RECEIVED_STATE'],
queryFn: () =>
fetchPaymentReceivedState(fetcher).then((data: Record<string, unknown>) =>
transformToCamelCase(data) as PaymentReceivedStateResponse
),
...options,
});
}
interface PaymentReceivedHtmlResponse {
htmlContent: string;
}
/** HTML content uses custom Accept header; kept on apiRequest. */
export function useGetPaymentReceiveHtml(
paymentReceivedId: number,
options?: UseQueryOptions<PaymentReceivedHtmlResponse, Error>
): UseQueryResult<PaymentReceivedHtmlResponse, Error> {
const apiRequest = useApiRequest();
return useQuery({
queryKey: ['PAYMENT_RECEIVED_HTML', paymentReceivedId],
queryFn: (): Promise<PaymentReceivedHtmlResponse> =>
apiRequest
.get(`/payments-received/${paymentReceivedId}`, {
headers: { Accept: 'application/json+html' },
})
.then((res) => transformToCamelCase(res.data) as PaymentReceivedHtmlResponse),
...options,
});
}
@@ -5,7 +5,7 @@ import {
useQueryClient,
UseQueryOptions,
UseQueryResult,
} from 'react-query';
} from '@tanstack/react-query';
import useApiRequest from '../useRequest';
import { transformToCamelCase, transfromToSnakeCase } from '@/utils';
@@ -36,8 +36,7 @@ export const useGetPaymentServices = (
response.data?.payment_services,
) as GetPaymentServicesResponse,
),
{
...options,
...options,
},
);
};
@@ -80,8 +79,7 @@ export const useGetPaymentServicesState = (
response.data?.data,
) as GetPaymentServicesStateResponse,
),
{
...options,
...options,
},
);
};
@@ -126,8 +124,7 @@ export const useUpdatePaymentMethod = (): UseMutationResult<
transfromToSnakeCase(data.values),
)
.then((response) => response.data),
{
onSuccess: () => {
onSuccess: () => {
queryClient.invalidateQueries(PaymentServicesStateQueryKey);
queryClient.invalidateQueries(PaymentServicesQueryKey);
},
@@ -1,177 +0,0 @@
// @ts-nocheck
import { useMutation, useQuery, useQueryClient } from 'react-query';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination } from '@/utils';
import useApiRequest from '../useRequest';
import t from './types';
const commonInvalidateQueries = (client) => {
// Invalidate payment mades.
client.invalidateQueries(t.PAYMENT_MADES);
// Invalidate payment made new entries.
client.invalidateQueries(t.PAYMENT_MADE_NEW_ENTRIES);
client.invalidateQueries(t.PAYMENT_MADE_EDIT_PAGE);
// Invalidate financial reports.
client.invalidateQueries(t.FINANCIAL_REPORT);
// Invalidate accounts.
client.invalidateQueries(t.ACCOUNTS);
client.invalidateQueries(t.ACCOUNT);
// Invalidate bills.
client.invalidateQueries(t.BILLS);
client.invalidateQueries(t.BILL);
// Invalidate vendors.
client.invalidateQueries(t.VENDORS);
client.invalidateQueries(t.VENDOR);
// Invalidate the cashflow transactions.
client.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
client.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
// Invalidate bills payment transactions.
client.invalidateQueries(t.BILLS_PAYMENT_TRANSACTIONS);
};
/**
* Retrieve payment mades list.
*/
export function usePaymentMades(query, props) {
return useRequestQuery(
[t.PAYMENT_MADES, query],
{ url: 'bill-payments', params: query },
{
select: (res) => ({
paymentMades: res.data.bill_payments,
pagination: transformPagination(res.data.pagination),
filterMeta: res.data.filter_meta,
}),
defaultData: {
paymentMades: [],
pagination: {},
filterMeta: {},
},
...props,
},
);
}
/**
* Creates payment made.
*/
export function useCreatePaymentMade(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((values) => apiRequest.post('bill-payments', values), {
onSuccess: (res, values) => {
// Common invalidation queries.
commonInvalidateQueries(client);
},
...props,
});
}
/**
* Edits payment made.
*/
export function useEditPaymentMade(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`bill-payments/${id}`, values),
{
onSuccess: (res, [id, values]) => {
// Common invalidation queries.
commonInvalidateQueries(client);
// Invalidate specific payment made.
client.invalidateQueries([t.PAYMENT_MADE, id]);
},
...props,
},
);
}
/**
* Deletes payment made.
*/
export function useDeletePaymentMade(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation((id) => apiRequest.delete(`bill-payments/${id}`), {
onSuccess: (res, id) => {
// Common invalidation queries.
commonInvalidateQueries(client);
// Invalidate specific payment made.
client.invalidateQueries([t.PAYMENT_MADE, id]);
},
...props,
});
}
/**
* Retrieve specific payment made.
*/
export function usePaymentMadeEditPage(
id: number,
props?: UseQueryOptions<any, Error>,
) {
const apiRequest = useApiRequest();
return useQuery([t.PAYMENT_MADE_EDIT_PAGE, id], () =>
apiRequest.get(`bill-payments/${id}/edit-page`).then((res) => res.data),
props
);
}
/**
* Retreive payment made new page entries.
* @param {number} vendorId -
*/
export function usePaymentMadeNewPageEntries(vendorId, props) {
return useRequestQuery(
[t.PAYMENT_MADE_NEW_ENTRIES, vendorId],
{
method: 'get',
url: `bill-payments/new-page/entries`,
params: { vendor_id: vendorId },
},
{
select: (res) => res.data,
defaultData: [],
...props,
},
);
}
export function useRefreshPaymentMades() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries(t.PAYMENT_MADES);
},
};
}
/**
* Retrieve specific payment made.
* @param {number} id - Payment made.
*/
export function usePaymentMade(id, props) {
return useRequestQuery(
[t.PAYMENT_MADE, id],
{ method: 'get', url: `bill-payments/${id}` },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
@@ -1,434 +0,0 @@
// @ts-nocheck
import {
useMutation,
useQueryClient,
UseQueryOptions,
UseQueryResult,
useQuery,
UseMutationOptions,
UseMutationResult,
} from 'react-query';
import useApiRequest from '../useRequest';
import { useRequestQuery } from '../useQueryRequest';
import { transformPagination, saveInvoke, transformToCamelCase } from '@/utils';
import { useRequestPdf } from '../useRequestPdf';
import t from './types';
// Common invalidate queries.
const commonInvalidateQueries = (client) => {
// Invalidate payment receives.
client.invalidateQueries(t.PAYMENT_RECEIVES);
client.invalidateQueries(t.PAYMENT_RECEIVE_EDIT_PAGE);
// Invalidate invoices.
client.invalidateQueries(t.SALE_INVOICES);
client.invalidateQueries(t.SALE_INVOICE);
// Invalidate accounts.
client.invalidateQueries(t.ACCOUNTS);
client.invalidateQueries(t.ACCOUNT);
// Invalidate financial reports.
client.invalidateQueries(t.FINANCIAL_REPORT);
// Invalidate transactions by reference.
client.invalidateQueries(t.TRANSACTIONS_BY_REFERENCE);
// Invalidate customers.
client.invalidateQueries(t.CUSTOMERS);
client.invalidateQueries(t.CUSTOMER);
// Invalidate the cashflow transactions.
client.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
client.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
client.invalidateQueries(t.CREDIT_NOTE);
client.invalidateQueries(t.CREDIT_NOTES);
// Invalidate reconcile.
client.invalidateQueries(t.RECONCILE_CREDIT_NOTE);
client.invalidateQueries(t.RECONCILE_CREDIT_NOTES);
// Invalidate invoices payment transactions.
client.invalidateQueries(t.SALE_INVOICE_PAYMENT_TRANSACTIONS);
};
// Transform payment receives.
const transformPaymentReceives = (res) => ({
paymentReceives: res.data.payment_receives,
pagination: transformPagination(res.data.pagination),
filterMeta: res.data.filter_meta,
});
/**
* Retrieve accounts list.
*/
export function usePaymentReceives(query, props) {
return useRequestQuery(
[t.PAYMENT_RECEIVES, query],
{ method: 'get', url: 'payments-received', params: query },
{
select: transformPaymentReceives,
defaultData: {
paymentReceives: [],
pagination: { page: 1, pageSize: 20, total: 0 },
filterMeta: {},
},
...props,
},
);
}
/**
* Creates payment receive.
*/
export function useCreatePaymentReceive(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(values) => apiRequest.post('payments-received', values),
{
onSuccess: (data, values) => {
// Invalidate specific payment receive.
commonInvalidateQueries(client);
// Invalidate payment receive settings.
client.invalidateQueries([t.SETTING, t.SETTING_PAYMENT_RECEIVES]);
saveInvoke(props?.onSuccess, data);
},
...props,
},
);
}
/**
* Edits payment receive.
*/
export function useEditPaymentReceive(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) => apiRequest.put(`payments-received/${id}`, values),
{
onSuccess: (data, [id, values]) => {
// Invalidate specific payment receive.
client.invalidateQueries([t.PAYMENT_RECEIVE, id]);
// Common invalidate queries.
commonInvalidateQueries(client);
saveInvoke(props?.onSuccess, data);
},
...props,
},
);
}
/**
* Deletes payment receive.
*/
export function useDeletePaymentReceive(props) {
const client = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
(id) => apiRequest.delete(`payments-received/${id}`),
{
onSuccess: (data, id) => {
// Invalidate specific payment receive.
client.invalidateQueries([t.PAYMENT_RECEIVE, id]);
commonInvalidateQueries(client);
saveInvoke(props?.onSuccess, data);
},
...props,
},
);
}
/**
* Deletes multiple payments received in bulk.
*/
export function useBulkDeletePaymentReceives(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
({
ids,
skipUndeletable = false,
}: {
ids: number[];
skipUndeletable?: boolean;
}) =>
apiRequest.post('payments-received/bulk-delete', {
ids,
skip_undeletable: skipUndeletable,
}),
{
onSuccess: () => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export function useValidateBulkDeletePaymentReceives(props) {
const apiRequest = useApiRequest();
return useMutation(
(ids: number[]) =>
apiRequest
.post('payments-received/validate-bulk-delete', { ids })
.then((res) => transformToCamelCase(res.data)),
{
...props,
},
);
}
/**
* Retrieve specific payment receive.
* @param {number} id - Payment receive.
*/
export function usePaymentReceive(id, props) {
return useRequestQuery(
[t.PAYMENT_RECEIVE, id],
{ method: 'get', url: `payments-received/${id}` },
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
/**
* Retrieve information of payment receive in edit page.
* @param {number} id - Payment receive id.
*/
export function usePaymentReceiveEditPage(id, props) {
const apiRequest = useApiRequest();
return useQuery(
[t.PAYMENT_RECEIVE_EDIT_PAGE, id],
() => apiRequest.get(`payments-received/${id}/edit-page`).then(res => res.data),
props
);
}
export function useRefreshPaymentReceive() {
const queryClient = useQueryClient();
return {
refresh: () => {
queryClient.invalidateQueries(t.PAYMENT_RECEIVES);
},
};
}
export function useCreateNotifyPaymentReceiveBySMS(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation(
([id, values]) =>
apiRequest.post(`payments-received/${id}/notify-by-sms`, values),
{
onSuccess: (res, [id, values]) => {
// Invalidate
queryClient.invalidateQueries([t.NOTIFY_PAYMENT_RECEIVE_BY_SMS, id]);
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export function usePaymentReceiveSMSDetail(
paymentReceiveId,
props,
requestProps,
) {
return useRequestQuery(
[t.PAYMENT_RECEIVE_SMS_DETAIL, paymentReceiveId],
{
method: 'get',
url: `payments-received/${paymentReceiveId}/sms-details`,
...requestProps,
},
{
select: (res) => res.data,
defaultData: {},
...props,
},
);
}
/**
* Retrieve the payment receive pdf document data.
* @param {number} paymentReceiveId - Payment receive id.
*/
export function usePdfPaymentReceive(paymentReceiveId) {
return useRequestPdf({ url: `payments-received/${paymentReceiveId}` });
}
interface SendPaymentReceiveMailValues {
to: string[] | string;
cc?: string[] | string,
bcc?: string[] | string,
subject: string;
message: string;
from?: string[] | string;
attachPdf?: boolean;
}
interface SendPaymentReceiveMailResponse {
success: boolean;
message?: string;
}
type SendPaymentReceiveMailMutation = UseMutationResult<
SendPaymentReceiveMailResponse,
Error,
[number, SendPaymentReceiveMailValues],
unknown
>;
export function useSendPaymentReceiveMail(
props?: Partial<
UseMutationOptions<
SendPaymentReceiveMailResponse,
Error,
[number, SendPaymentReceiveMailValues]
>
>,
): SendPaymentReceiveMailMutation {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation<
SendPaymentReceiveMailResponse,
Error,
[number, SendPaymentReceiveMailValues]
>(
([id, values]) =>
apiRequest.post(`payments-received/${id}/mail`, values),
{
onSuccess: (res, [id, values]) => {
// Common invalidate queries.
commonInvalidateQueries(queryClient);
},
...props,
},
);
}
export interface GetPaymentReceivedMailStateResponse {
companyName: string;
companyLogoUri?: string;
primaryColor?: string;
customerName: string;
entries: Array<{ invoiceNumber: string; paidAmount: string }>;
from: Array<string>;
fromOptions: Array<{ mail: string; label: string; primary: boolean }>;
paymentDate: string;
paymentDateFormatted: string;
to: Array<string>;
toOptions: Array<{ mail: string; label: string; primary: boolean }>;
total: number;
totalFormatted: string;
subtotal: number;
subtotalFormatted: string;
paymentNumber: string;
formatArgs: Record<string, any>;
}
export function usePaymentReceivedMailState(
paymentReceiveId: number,
props?: UseQueryOptions<GetPaymentReceivedMailStateResponse, Error>,
): UseQueryResult<GetPaymentReceivedMailStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<GetPaymentReceivedMailStateResponse, Error>(
[t.PAYMENT_RECEIVE_MAIL_OPTIONS, paymentReceiveId],
() =>
apiRequest
.get(`payments-received/${paymentReceiveId}/mail`)
.then((res) => transformToCamelCase(res.data)),
);
}
export interface PaymentReceivedStateResponse {
defaultTemplateId: number;
}
/**
* Retrieves the payment receive state.
* @param {Record<string, any>} query - Query parameters for the request.
* @param {UseQueryOptions<PaymentReceivedStateResponse, Error>} options - Optional query options.
* @returns {UseQueryResult<PaymentReceivedStateResponse, Error>} The query result.
*/
export function usePaymentReceivedState(
options?: UseQueryOptions<PaymentReceivedStateResponse, Error>,
): UseQueryResult<PaymentReceivedStateResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<PaymentReceivedStateResponse, Error>(
['PAYMENT_RECEIVED_STATE'],
() =>
apiRequest
.get('/payments-received/state')
.then((res) => transformToCamelCase(res.data)),
{
...options,
},
);
}
interface PaymentReceivedHtmlResponse {
htmlContent: string;
}
/**
* Retrieves the html content of the given payment receive.
* @param {number} paymentReceivedId
* @param {UseQueryOptions<PaymentReceivedHtmlResponse, Error>} options
* @returns {UseQueryResult<PaymentReceivedHtmlResponse, Error>}
*/
export function useGetPaymentReceiveHtml(
paymentReceivedId: number,
options?: UseQueryOptions<PaymentReceivedHtmlResponse, Error>,
): UseQueryResult<PaymentReceivedHtmlResponse, Error> {
const apiRequest = useApiRequest();
return useQuery<PaymentReceivedHtmlResponse, Error>(
['PAYMENT_RECEIVED_HTML', paymentReceivedId],
() =>
apiRequest
.get(`/payments-received/${paymentReceivedId}`, {
headers: {
Accept: 'application/json+html',
},
})
.then((res) => transformToCamelCase(res.data)),
{
...options,
},
);
}
+127 -186
View File
@@ -1,236 +1,177 @@
// @ts-nocheck
import {
useMutation,
useQuery,
useQueryClient,
UseMutationOptions,
UseQueryOptions,
UseMutationResult,
UseQueryResult,
useQueryClient,
} from 'react-query';
import useApiRequest from '../useRequest';
import { transformToCamelCase, transfromToSnakeCase } from '@/utils';
} from '@tanstack/react-query';
import {
fetchPdfTemplates,
fetchPdfTemplate,
createPdfTemplate,
editPdfTemplate,
deletePdfTemplate,
assignPdfTemplateAsDefault,
fetchPdfTemplateBrandingState,
} from '@bigcapital/sdk-ts';
import type {
CreatePdfTemplateBody,
EditPdfTemplateBody,
PdfTemplateResponse,
PdfTemplatesListResponse,
PdfTemplateBrandingStateResponse,
GetPdfTemplatesQuery,
} from '@bigcapital/sdk-ts';
import { useApiFetcher } from '../useRequest';
const PdfTemplatesQueryKey = 'PdfTemplate';
export interface CreatePdfTemplateValues {
templateName: string;
resource: string;
attributes: Record<string, any>;
}
// Re-export types for consumers (aliases for SDK types)
export type CreatePdfTemplateValues = CreatePdfTemplateBody;
export type CreatePdfTemplateResponse = void;
export interface CreatePdfTemplateResponse {}
export interface EditPdfTemplateValues {
templateName: string;
attributes: Record<string, any>;
}
export interface EditPdfTemplateResponse {}
export type EditPdfTemplateValues = EditPdfTemplateBody;
export type EditPdfTemplateResponse = void;
export interface DeletePdfTemplateValues {
templateId: number | string;
}
export type DeletePdfTemplateResponse = void;
export interface DeletePdfTemplateResponse {}
export type GetPdfTemplateResponse = PdfTemplateResponse;
export interface GetPdfTemplateValues {}
export type GetPdfTemplatesResponse = PdfTemplatesListResponse;
export interface GetPdfTemplateResponse {
templateName: string;
companyLogoUri?: string | null;
attributes: Record<string, any>;
predefined: boolean;
default: boolean;
createdAt: string;
updatedAt: string | null;
export type AssignPdfTemplateAsDefaultValues = { templateId: number };
export type AssignPdfTemplateAsDefaultResponse = void;
export type GetPdfTemplateBrandingStateResponse = PdfTemplateBrandingStateResponse;
function invalidatePdfTemplateQueries(queryClient: ReturnType<typeof useQueryClient>) {
queryClient.invalidateQueries({ queryKey: [PdfTemplatesQueryKey] });
}
export interface GetPdfTemplatesValues {}
export interface GetPdfTemplatesResponse {}
// Hook for creating a PDF template
export const useCreatePdfTemplate = (
options?: UseMutationOptions<
CreatePdfTemplateResponse,
Error,
CreatePdfTemplateValues
>,
): UseMutationResult<
CreatePdfTemplateResponse,
Error,
CreatePdfTemplateValues
> => {
const apiRequest = useApiRequest();
export function useCreatePdfTemplate(
options?: UseMutationOptions<CreatePdfTemplateResponse, Error, CreatePdfTemplateValues>
): UseMutationResult<CreatePdfTemplateResponse, Error, CreatePdfTemplateValues> {
const queryClient = useQueryClient();
return useMutation<CreatePdfTemplateResponse, Error, CreatePdfTemplateValues>(
(values) =>
apiRequest
.post('/pdf-templates', transfromToSnakeCase(values))
.then((res) => res.data),
{
onSuccess: () => {
queryClient.invalidateQueries([PdfTemplatesQueryKey]);
},
...options,
},
);
};
const fetcher = useApiFetcher();
return useMutation({
mutationFn: (values: CreatePdfTemplateValues) => createPdfTemplate(fetcher, values),
onSuccess: () => invalidatePdfTemplateQueries(queryClient),
...options,
});
}
// Hook for editing a PDF template
export const useEditPdfTemplate = (
export function useEditPdfTemplate(
options?: UseMutationOptions<
EditPdfTemplateResponse,
Error,
{ templateId: number; values: EditPdfTemplateValues }
>,
>
): UseMutationResult<
EditPdfTemplateResponse,
Error,
{ templateId: number; values: EditPdfTemplateValues }
> => {
> {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
return useMutation<
EditPdfTemplateResponse,
Error,
{ templateId: number; values: EditPdfTemplateValues }
>(
({ templateId, values }) =>
apiRequest
.put(`/pdf-templates/${templateId}`, transfromToSnakeCase(values))
.then((res) => res.data),
{
onSuccess: () => {
queryClient.invalidateQueries([PdfTemplatesQueryKey]);
},
...options,
},
);
};
const fetcher = useApiFetcher();
// Hook for deleting a PDF template
export const useDeletePdfTemplate = (
options?: UseMutationOptions<
DeletePdfTemplateResponse,
Error,
{ templateId: number }
>,
): UseMutationResult<
DeletePdfTemplateResponse,
Error,
{ templateId: number }
> => {
const apiRequest = useApiRequest();
const queryClient = useQueryClient();
return useMutation<DeletePdfTemplateResponse, Error, { templateId: number }>(
({ templateId }) =>
apiRequest.delete(`/pdf-templates/${templateId}`).then((res) => res.data),
{
onSuccess: () => {
queryClient.invalidateQueries([PdfTemplatesQueryKey]);
},
...options,
},
);
};
// Hook for getting a single PDF template
export const useGetPdfTemplate = (
templateId: number,
options?: UseQueryOptions<GetPdfTemplateResponse, Error>,
): UseQueryResult<GetPdfTemplateResponse, Error> => {
const apiRequest = useApiRequest();
return useQuery<GetPdfTemplateResponse, Error>(
[PdfTemplatesQueryKey, templateId],
() =>
apiRequest
.get(`/pdf-templates/${templateId}`)
.then((res) => transformToCamelCase(res.data)),
options,
);
};
// Hook for getting multiple PDF templates
export const useGetPdfTemplates = (
query?: { resource: string },
options?: UseQueryOptions<GetPdfTemplatesResponse, Error>,
): UseQueryResult<GetPdfTemplatesResponse, Error> => {
const apiRequest = useApiRequest();
return useQuery<GetPdfTemplatesResponse, Error>(
[PdfTemplatesQueryKey, query],
() =>
apiRequest
.get('/pdf-templates', { params: query })
.then((res) => res.data),
options,
);
};
export interface AssignPdfTemplateAsDefaultValues {
templateId: number;
return useMutation({
mutationFn: ({ templateId, values }: { templateId: number; values: EditPdfTemplateValues }) =>
editPdfTemplate(fetcher, templateId, values),
onSuccess: () => invalidatePdfTemplateQueries(queryClient),
...options,
});
}
export interface AssignPdfTemplateAsDefaultResponse {}
// Hook for deleting a PDF template
export function useDeletePdfTemplate(
options?: UseMutationOptions<DeletePdfTemplateResponse, Error, { templateId: number }>
): UseMutationResult<DeletePdfTemplateResponse, Error, { templateId: number }> {
const queryClient = useQueryClient();
const fetcher = useApiFetcher();
export const useAssignPdfTemplateAsDefault = (
return useMutation({
mutationFn: ({ templateId }: { templateId: number }) =>
deletePdfTemplate(fetcher, templateId),
onSuccess: () => invalidatePdfTemplateQueries(queryClient),
...options,
});
}
// Hook for getting a single PDF template
export function useGetPdfTemplate(
templateId: number,
options?: UseQueryOptions<GetPdfTemplateResponse, Error>
): UseQueryResult<GetPdfTemplateResponse, Error> {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [PdfTemplatesQueryKey, templateId],
queryFn: () => fetchPdfTemplate(fetcher, templateId),
...options,
});
}
// Hook for getting multiple PDF templates
export function useGetPdfTemplates(
query?: GetPdfTemplatesQuery,
options?: UseQueryOptions<GetPdfTemplatesResponse, Error>
): UseQueryResult<GetPdfTemplatesResponse, Error> {
const fetcher = useApiFetcher();
return useQuery({
queryKey: [PdfTemplatesQueryKey, query],
queryFn: () => fetchPdfTemplates(fetcher, query),
...options,
});
}
// Hook for assigning a PDF template as default
export function useAssignPdfTemplateAsDefault(
options?: UseMutationOptions<
AssignPdfTemplateAsDefaultResponse,
Error,
AssignPdfTemplateAsDefaultValues
>,
>
): UseMutationResult<
AssignPdfTemplateAsDefaultResponse,
Error,
AssignPdfTemplateAsDefaultValues
> => {
const apiRequest = useApiRequest();
> {
const queryClient = useQueryClient();
return useMutation<
AssignPdfTemplateAsDefaultResponse,
Error,
AssignPdfTemplateAsDefaultValues
>(
({ templateId }) =>
apiRequest
.post(`/pdf-templates/${templateId}/assign_default`)
.then((res) => res.data),
{
onSuccess: () => {
queryClient.invalidateQueries([PdfTemplatesQueryKey]);
queryClient.invalidateQueries(['SALE_INVOICE_STATE']);
queryClient.invalidateQueries(['SALE_ESTIMATE_STATE']);
queryClient.invalidateQueries(['SALE_RECEIPT_STATE']);
queryClient.invalidateQueries(['CREDIT_NOTE_STATE']);
queryClient.invalidateQueries(['PAYMENT_RECEIVED_STATE']);
},
...options,
},
);
};
const fetcher = useApiFetcher();
// Retrieve organization branding state.
// --------------------------------------------------
export interface GetPdfTemplateBrandingStateResponse {
companyName: string;
companyAddress: string;
companyLogoUri: string;
companyLogoKey: string;
primaryColor: string;
return useMutation({
mutationFn: ({ templateId }: AssignPdfTemplateAsDefaultValues) =>
assignPdfTemplateAsDefault(fetcher, templateId),
onSuccess: () => {
invalidatePdfTemplateQueries(queryClient);
queryClient.invalidateQueries({ queryKey: ['SALE_INVOICE_STATE'] });
queryClient.invalidateQueries({ queryKey: ['SALE_ESTIMATE_STATE'] });
queryClient.invalidateQueries({ queryKey: ['SALE_RECEIPT_STATE'] });
queryClient.invalidateQueries({ queryKey: ['CREDIT_NOTE_STATE'] });
queryClient.invalidateQueries({ queryKey: ['PAYMENT_RECEIVED_STATE'] });
},
...options,
});
}
export const useGetPdfTemplateBrandingState = (
options?: UseQueryOptions<GetPdfTemplateBrandingStateResponse, Error>,
): UseQueryResult<GetPdfTemplateBrandingStateResponse, Error> => {
const apiRequest = useApiRequest();
// Retrieve organization branding state.
export function useGetPdfTemplateBrandingState(
options?: UseQueryOptions<GetPdfTemplateBrandingStateResponse, Error>
): UseQueryResult<GetPdfTemplateBrandingStateResponse, Error> {
const fetcher = useApiFetcher();
return useQuery<GetPdfTemplateBrandingStateResponse, Error>(
[PdfTemplatesQueryKey, 'state'],
() =>
apiRequest
.get('/pdf-templates/state')
.then((res) => transformToCamelCase(res.data)),
options,
);
};
return useQuery({
queryKey: [PdfTemplatesQueryKey, 'state'],
queryFn: () => fetchPdfTemplateBrandingState(fetcher),
...options,
});
}

Some files were not shown because too many files have changed in this diff Show More