mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-16 12:50:38 +00:00
Merge branch 'develop' into filter-uncategorized-bank-transactions
This commit is contained in:
@@ -62,6 +62,7 @@ export function BankAccount({
|
||||
balance,
|
||||
loading = false,
|
||||
updatedBeforeText,
|
||||
uncategorizedTransactionsCount,
|
||||
...restProps
|
||||
}) {
|
||||
return (
|
||||
@@ -77,17 +78,19 @@ export function BankAccount({
|
||||
</BankAccountHeader>
|
||||
|
||||
<BankAccountMeta>
|
||||
{false && (
|
||||
{uncategorizedTransactionsCount > 0 && (
|
||||
<BankAccountMetaLine
|
||||
title={intl.get('cash_flow.transactions_for_review')}
|
||||
value={'0'}
|
||||
value={uncategorizedTransactionsCount}
|
||||
className={clsx({ [Classes.SKELETON]: loading })}
|
||||
/>
|
||||
)}
|
||||
{updatedBeforeText && (
|
||||
<BankAccountMetaLine
|
||||
title={updatedBeforeText}
|
||||
className={clsx({ [Classes.SKELETON]: loading })}
|
||||
/>
|
||||
)}
|
||||
<BankAccountMetaLine
|
||||
title={updatedBeforeText}
|
||||
className={clsx({ [Classes.SKELETON]: loading })}
|
||||
/>
|
||||
</BankAccountMeta>
|
||||
|
||||
<BankAccountBalance amount={balance} loading={loading} />
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { createNewItemFromQuery, createNewItemRenderer } from './utils';
|
||||
import { FSelect } from '../Forms';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import { useCreateAutofillListener } from '@/hooks/state/autofill';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
/**
|
||||
@@ -17,6 +19,7 @@ function CustomerSelectRoot({
|
||||
// #ownProps
|
||||
items,
|
||||
allowCreate,
|
||||
name,
|
||||
...props
|
||||
}) {
|
||||
// Maybe inject create new item props to suggest component.
|
||||
@@ -24,14 +27,21 @@ function CustomerSelectRoot({
|
||||
const maybeCreateNewItemFromQuery = allowCreate
|
||||
? createNewItemFromQuery
|
||||
: null;
|
||||
const { setFieldValue } = useFormikContext();
|
||||
|
||||
// Creates autofill listener once the quick customer drawer submit the form.
|
||||
const autofillRef = useCreateAutofillListener((payload: any) => {
|
||||
setFieldValue(name, payload.customerId);
|
||||
});
|
||||
// Handles the create item click.
|
||||
const handleCreateItemClick = () => {
|
||||
openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER);
|
||||
const handleCreateItemClick = (item) => {
|
||||
const displayName = item.name;
|
||||
openDrawer(DRAWERS.QUICK_CREATE_CUSTOMER, { autofillRef, displayName });
|
||||
};
|
||||
|
||||
return (
|
||||
<FSelect
|
||||
name={name}
|
||||
items={items}
|
||||
textAccessor={'display_name'}
|
||||
labelAccessor={'formatted_balance'}
|
||||
|
||||
@@ -60,7 +60,7 @@ export function DataTable(props) {
|
||||
|
||||
// Pagination props.
|
||||
initialPageIndex = 0,
|
||||
initialPageSize = 10,
|
||||
initialPageSize = 20,
|
||||
|
||||
updateDebounceTime = 200,
|
||||
selectionColumnWidth = 42,
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import classNames from 'classnames';
|
||||
import clsx from 'classnames';
|
||||
|
||||
import '@/style/components/Details.scss';
|
||||
|
||||
@@ -24,7 +24,7 @@ export function DetailsMenu({
|
||||
}) {
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
className={clsx(
|
||||
'details-menu',
|
||||
{
|
||||
'details-menu--vertical': direction === DIRECTION.VERTICAL,
|
||||
@@ -44,16 +44,24 @@ export function DetailsMenu({
|
||||
/**
|
||||
* Detail item.
|
||||
*/
|
||||
export function DetailItem({ label, children, name, align, className }) {
|
||||
export function DetailItem({
|
||||
label,
|
||||
children,
|
||||
name,
|
||||
align,
|
||||
multiline,
|
||||
className,
|
||||
}) {
|
||||
const { minLabelSize } = useDetailsMenuContext();
|
||||
|
||||
return (
|
||||
<div
|
||||
className={classNames(
|
||||
className={clsx(
|
||||
'detail-item',
|
||||
{
|
||||
[`detail-item--${name}`]: name,
|
||||
[`align-${align}`]: align,
|
||||
[`detail-item--multilines`]: multiline,
|
||||
},
|
||||
className,
|
||||
)}
|
||||
@@ -66,7 +74,7 @@ export function DetailItem({ label, children, name, align, className }) {
|
||||
>
|
||||
{label}
|
||||
</div>
|
||||
<div>{children}</div>
|
||||
<div className={clsx('detail-item__content')}>{children}</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ import UserFormDialog from '@/containers/Dialogs/UserFormDialog';
|
||||
import ItemCategoryDialog from '@/containers/Dialogs/ItemCategoryDialog';
|
||||
import CurrencyFormDialog from '@/containers/Dialogs/CurrencyFormDialog';
|
||||
import InventoryAdjustmentDialog from '@/containers/Dialogs/InventoryAdjustmentFormDialog';
|
||||
import PaymentViaVoucherDialog from '@/containers/Dialogs/PaymentViaVoucherDialog';
|
||||
import KeyboardShortcutsDialog from '@/containers/Dialogs/keyboardShortcutsDialog';
|
||||
import ContactDuplicateDialog from '@/containers/Dialogs/ContactDuplicateDialog';
|
||||
import QuickPaymentReceiveFormDialog from '@/containers/Dialogs/QuickPaymentReceiveFormDialog';
|
||||
@@ -49,7 +48,7 @@ import InvoiceExchangeRateChangeDialog from '@/containers/Sales/Invoices/Invoice
|
||||
import InvoiceMailDialog from '@/containers/Sales/Invoices/InvoiceMailDialog/InvoiceMailDialog';
|
||||
import EstimateMailDialog from '@/containers/Sales/Estimates/EstimateMailDialog/EstimateMailDialog';
|
||||
import ReceiptMailDialog from '@/containers/Sales/Receipts/ReceiptMailDialog/ReceiptMailDialog';
|
||||
import PaymentMailDialog from '@/containers/Sales/PaymentReceives/PaymentMailDialog/PaymentMailDialog';
|
||||
import PaymentMailDialog from '@/containers/Sales/PaymentsReceived/PaymentMailDialog/PaymentMailDialog';
|
||||
import { ExportDialog } from '@/containers/Dialogs/ExportDialog';
|
||||
import { RuleFormDialog } from '@/containers/Banking/Rules/RuleFormDialog/RuleFormDialog';
|
||||
import { DisconnectBankAccountDialog } from '@/containers/CashFlow/AccountTransactions/dialogs/DisconnectBankAccountDialog/DisconnectBankAccountDialog';
|
||||
@@ -68,7 +67,6 @@ export default function DialogsContainer() {
|
||||
<InventoryAdjustmentDialog
|
||||
dialogName={DialogsName.InventoryAdjustmentForm}
|
||||
/>
|
||||
<PaymentViaVoucherDialog dialogName={DialogsName.PaymentViaVoucherForm} />
|
||||
<KeyboardShortcutsDialog dialogName={DialogsName.KeyboardShortcutForm} />
|
||||
<ContactDuplicateDialog dialogName={DialogsName.ContactDuplicateForm} />
|
||||
<QuickPaymentReceiveFormDialog
|
||||
|
||||
@@ -39,7 +39,7 @@ export default function DrawersContainer() {
|
||||
<InvoiceDetailDrawer name={DRAWERS.INVOICE_DETAILS} />
|
||||
<EstimateDetailDrawer name={DRAWERS.ESTIMATE_DETAILS} />
|
||||
<ReceiptDetailDrawer name={DRAWERS.RECEIPT_DETAILS} />
|
||||
<PaymentReceiveDetailDrawer name={DRAWERS.PAYMENT_RECEIVE_DETAILS} />
|
||||
<PaymentReceiveDetailDrawer name={DRAWERS.PAYMENT_RECEIVED_DETAILS} />
|
||||
<PaymentMadeDetailDrawer name={DRAWERS.PAYMENT_MADE_DETAILS} />
|
||||
<ItemDetailDrawer name={DRAWERS.ITEM_DETAILS} />
|
||||
<CustomerDetailsDrawer name={DRAWERS.CUSTOMER_DETAILS} />
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
|
||||
|
||||
.root {
|
||||
padding: 20px;
|
||||
border: 2px dotted #c5cbd3;
|
||||
@@ -9,4 +7,14 @@
|
||||
flex-direction: column;
|
||||
background: #fff;
|
||||
position: relative;
|
||||
transition: background-color 0.3s ease, border-color 0.3s ease;
|
||||
|
||||
&.dropzoneAccept {
|
||||
border-color: rgb(0, 82, 204);
|
||||
background: rgba(0, 82, 204, 0.05);
|
||||
}
|
||||
&.dropzoneReject {
|
||||
border-color: #AC2F33;
|
||||
background: rgba(172, 47, 51, 0.05)
|
||||
}
|
||||
}
|
||||
@@ -235,7 +235,14 @@ export const Dropzone = (_props: DropzoneProps) => {
|
||||
>
|
||||
<Box
|
||||
{...getRootProps({
|
||||
className: clsx(styles.root, classNames?.root),
|
||||
className: clsx(
|
||||
styles.root,
|
||||
{
|
||||
[styles.dropzoneAccept]: isDragAccept,
|
||||
[styles.dropzoneReject]: isDragReject
|
||||
},
|
||||
classNames?.root
|
||||
),
|
||||
})}
|
||||
// {...getStyles('root', { focusable: true })}
|
||||
{...others}
|
||||
@@ -253,7 +260,7 @@ export const Dropzone = (_props: DropzoneProps) => {
|
||||
<input {...getInputProps(inputProps)} name={name} />
|
||||
<div
|
||||
data-enable-pointer-events={enablePointerEvents || undefined}
|
||||
className={classNames?.content}
|
||||
className={clsx(styles.content, classNames?.content)}
|
||||
>
|
||||
{children}
|
||||
</div>
|
||||
@@ -268,8 +275,6 @@ Dropzone.Idle = DropzoneIdle;
|
||||
Dropzone.Reject = DropzoneReject;
|
||||
|
||||
|
||||
|
||||
|
||||
type PossibleRef<T> = Ref<T> | undefined;
|
||||
|
||||
export function assignRef<T>(ref: PossibleRef<T>, value: T) {
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import * as R from 'ramda';
|
||||
import { useFormikContext } from 'formik';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import { createNewItemFromQuery, createNewItemRenderer } from './utils';
|
||||
import { FSelect } from '../Forms';
|
||||
import { useCreateAutofillListener } from '@/hooks/state/autofill';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
/**
|
||||
@@ -15,6 +17,7 @@ function VendorsSelectRoot({
|
||||
openDrawer,
|
||||
|
||||
// #ownProps
|
||||
name,
|
||||
items,
|
||||
allowCreate,
|
||||
|
||||
@@ -25,14 +28,24 @@ function VendorsSelectRoot({
|
||||
const maybeCreateNewItemFromQuery = allowCreate
|
||||
? createNewItemFromQuery
|
||||
: null;
|
||||
const { setFieldValue } = useFormikContext();
|
||||
|
||||
// Creates a new autofill listener once the quick vendor drawer submits the form.
|
||||
const autofillRef = useCreateAutofillListener((payload: any) => {
|
||||
setFieldValue(name, payload.vendorId);
|
||||
});
|
||||
|
||||
// Handles the create item click.
|
||||
const handleCreateItemClick = () => {
|
||||
openDrawer(DRAWERS.QUICK_WRITE_VENDOR);
|
||||
const handleCreateItemClick = (item) => {
|
||||
openDrawer(DRAWERS.QUICK_WRITE_VENDOR, {
|
||||
autofillRef,
|
||||
displayName: item.name,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<FSelect
|
||||
name={name}
|
||||
items={items}
|
||||
textAccessor={'display_name'}
|
||||
labelAccessor={'formatted_balance'}
|
||||
|
||||
@@ -6,7 +6,7 @@ export enum DRAWERS {
|
||||
BILL_DETAILS = 'bill-drawer',
|
||||
INVOICE_DETAILS = 'invoice-detail-drawer',
|
||||
RECEIPT_DETAILS = 'receipt-detail-drawer',
|
||||
PAYMENT_RECEIVE_DETAILS = 'payment-receive-detail-drawer',
|
||||
PAYMENT_RECEIVED_DETAILS = 'payment-receive-detail-drawer',
|
||||
PAYMENT_MADE_DETAILS = 'payment-made-drawer',
|
||||
ESTIMATE_DETAILS = 'estimate-detail-drawer',
|
||||
ITEM_DETAILS = 'item-detail-drawer',
|
||||
|
||||
@@ -55,7 +55,7 @@ export const accountsReceivable = [
|
||||
description: (
|
||||
<T id={'manage_payment_transactions_from_your_customers'} />
|
||||
),
|
||||
link: '/payment-receives',
|
||||
link: '/payments-received',
|
||||
subject: AbilitySubject.PaymentReceive,
|
||||
ability: PaymentReceiveAction.View,
|
||||
},
|
||||
@@ -88,7 +88,7 @@ export const accountsPayable = [
|
||||
{
|
||||
title: <T id={'vendors_payments'} />,
|
||||
description: <T id={'manage_payments_transactions_to_your_vendors'} />,
|
||||
link: '/payment-mades',
|
||||
link: '/payments-made',
|
||||
subject: AbilitySubject.PaymentMade,
|
||||
ability: PaymentMadeAction.View,
|
||||
},
|
||||
|
||||
@@ -7,4 +7,7 @@ export const BANK_QUERY_KEY = {
|
||||
'RECOGNIZED_BANK_TRANSACTIONS_INFINITY',
|
||||
BANK_ACCOUNT_SUMMARY_META: 'BANK_ACCOUNT_SUMMARY_META',
|
||||
AUTOFILL_CATEGORIZE_BANK_TRANSACTION: 'AUTOFILL_CATEGORIZE_BANK_TRANSACTION',
|
||||
PENDING_BANK_ACCOUNT_TRANSACTIONS: 'PENDING_BANK_ACCOUNT_TRANSACTIONS',
|
||||
PENDING_BANK_ACCOUNT_TRANSACTIONS_INFINITY:
|
||||
'PENDING_BANK_ACCOUNT_TRANSACTIONS_INFINITY',
|
||||
};
|
||||
|
||||
@@ -74,7 +74,7 @@ export const SidebarMenu = [
|
||||
},
|
||||
},
|
||||
{
|
||||
text: <T id={'category_list'} />,
|
||||
text: <T id={'categories_list'} />,
|
||||
href: '/items/categories',
|
||||
type: ISidebarMenuItemType.Link,
|
||||
permission: {
|
||||
@@ -179,8 +179,8 @@ export const SidebarMenu = [
|
||||
type: ISidebarMenuItemType.Link,
|
||||
},
|
||||
{
|
||||
text: <T id={'sidebar.payment_receives'} />,
|
||||
href: '/payment-receives',
|
||||
text: <T id={'sidebar.payments_received'} />,
|
||||
href: '/payments-received',
|
||||
type: ISidebarMenuItemType.Link,
|
||||
permission: {
|
||||
subject: AbilitySubject.PaymentReceive,
|
||||
@@ -226,8 +226,8 @@ export const SidebarMenu = [
|
||||
type: ISidebarMenuItemType.Link,
|
||||
},
|
||||
{
|
||||
text: <T id={'sidebar.new_payment_receive'} />,
|
||||
href: '/payment-receives/new',
|
||||
text: <T id={'sidebar.new_payment_received'} />,
|
||||
href: '/payment-received/new',
|
||||
type: ISidebarMenuItemType.Link,
|
||||
permission: {
|
||||
subject: AbilitySubject.PaymentReceive,
|
||||
@@ -265,8 +265,8 @@ export const SidebarMenu = [
|
||||
type: ISidebarMenuItemType.Link,
|
||||
},
|
||||
{
|
||||
text: <T id={'payment_mades'} />,
|
||||
href: '/payment-mades',
|
||||
text: <T id={'payments_made'} />,
|
||||
href: '/payments-made',
|
||||
type: ISidebarMenuItemType.Link,
|
||||
permission: {
|
||||
subject: AbilitySubject.PaymentMade,
|
||||
@@ -299,7 +299,7 @@ export const SidebarMenu = [
|
||||
},
|
||||
{
|
||||
text: <T id={'sidebar.new_payment_made'} />,
|
||||
href: '/payment-mades/new',
|
||||
href: '/payments-made/new',
|
||||
type: ISidebarMenuItemType.Link,
|
||||
permission: {
|
||||
subject: AbilitySubject.PaymentMade,
|
||||
|
||||
@@ -44,9 +44,9 @@ export const SubscriptionPlans = [
|
||||
},
|
||||
{ text: 'Unlimited User Seats' },
|
||||
],
|
||||
monthlyPrice: '$10',
|
||||
monthlyPrice: '$20',
|
||||
monthlyPriceLabel: 'Per month',
|
||||
annuallyPrice: '$7.5',
|
||||
annuallyPrice: '$15',
|
||||
annuallyPriceLabel: 'Per month',
|
||||
monthlyVariantId: '446152',
|
||||
// monthlyVariantId: '450016',
|
||||
@@ -78,9 +78,9 @@ export const SubscriptionPlans = [
|
||||
{ text: 'Smart Financial Reports' },
|
||||
{ text: 'Advanced Inventory Reports' },
|
||||
],
|
||||
monthlyPrice: '$20',
|
||||
monthlyPrice: '$40',
|
||||
monthlyPriceLabel: 'Per month',
|
||||
annuallyPrice: '$15',
|
||||
annuallyPrice: '$30',
|
||||
annuallyPriceLabel: 'Per month',
|
||||
// monthlyVariantId: '450028',
|
||||
monthlyVariantId: '446155',
|
||||
@@ -101,9 +101,9 @@ export const SubscriptionPlans = [
|
||||
},
|
||||
{ text: 'Analysis Cost Center' },
|
||||
],
|
||||
monthlyPrice: '$25',
|
||||
monthlyPrice: '$55',
|
||||
monthlyPriceLabel: 'Per month',
|
||||
annuallyPrice: '$19',
|
||||
annuallyPrice: '$40',
|
||||
annuallyPriceLabel: 'Per month',
|
||||
featured: true,
|
||||
// monthlyVariantId: '450031',
|
||||
@@ -128,9 +128,9 @@ export const SubscriptionPlans = [
|
||||
hint: 'Track the organization inventory in multiple warehouses and transfer goods between them.',
|
||||
},
|
||||
],
|
||||
monthlyPrice: '$40',
|
||||
monthlyPrice: '$60',
|
||||
monthlyPriceLabel: 'Per month',
|
||||
annuallyPrice: '$30',
|
||||
annuallyPrice: '$45',
|
||||
annuallyPriceLabel: 'Per month',
|
||||
// monthlyVariantId: '450024',
|
||||
monthlyVariantId: '446167',
|
||||
|
||||
@@ -125,8 +125,9 @@ function ManualJournalsDataTable({
|
||||
loading={isManualJournalsLoading}
|
||||
headerLoading={isManualJournalsLoading}
|
||||
progressBarLoading={isManualJournalsFetching}
|
||||
pagesCount={pagination.pagesCount}
|
||||
pagination={true}
|
||||
initialPageSize={manualJournalsTableState.pageSize}
|
||||
pagesCount={pagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
TableLoadingRenderer={TableSkeletonRows}
|
||||
|
||||
@@ -15,6 +15,8 @@ export function MakeJournalFormFooterLeft() {
|
||||
<FEditableText
|
||||
name={'description'}
|
||||
placeholder={intl.get('make_jorunal.decscrption.placeholder')}
|
||||
multiline
|
||||
fastField
|
||||
/>
|
||||
</DescriptionFormGroup>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -27,7 +27,7 @@ export const accountNameAccessor = (account) => {
|
||||
export const handleDeleteErrors = (errors) => {
|
||||
if (errors.find((e) => e.type === 'ACCOUNT.PREDEFINED')) {
|
||||
AppToaster.show({
|
||||
message: intl.get('you_could_not_delete_predefined_accounts'),
|
||||
message: intl.get('cannot_delete_predefined_accounts'),
|
||||
intent: Intent.DANGER,
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,73 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React, { useState } from 'react';
|
||||
import { FormattedMessage as T } from '@/components';
|
||||
import intl from 'react-intl-universal';
|
||||
import { Intent, Alert } from '@blueprintjs/core';
|
||||
import { size } from 'lodash';
|
||||
import { AppToaster } from '@/components';
|
||||
|
||||
import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect';
|
||||
import withAlertActions from '@/containers/Alert/withAlertActions';
|
||||
|
||||
import { compose } from '@/utils';
|
||||
|
||||
/**
|
||||
* Exchange rate bulk delete alert.
|
||||
*/
|
||||
function ExchangeRateBulkDeleteAlert({
|
||||
name,
|
||||
|
||||
// #withAlertStoreConnect
|
||||
isOpen,
|
||||
payload: { exchangeRatesIds },
|
||||
|
||||
// #withAlertActions
|
||||
closeAlert,
|
||||
}) {
|
||||
// handle cancel item bulk delete alert.
|
||||
const handleCancelBulkDelete = () => {
|
||||
closeAlert(name);
|
||||
};
|
||||
|
||||
// handle confirm Exchange Rates bulk delete.
|
||||
// const handleConfirmBulkDelete = () => {
|
||||
// bulkDeleteExchangeRate(exchangeRatesIds)
|
||||
// .then(() => {
|
||||
// AppToaster.show({
|
||||
// message: formatMessage({
|
||||
// id: 'the_exchange_rates_has_been_successfully_deleted',
|
||||
// }),
|
||||
// intent: Intent.SUCCESS,
|
||||
// });
|
||||
// })
|
||||
// .catch(({ errors }) => {
|
||||
// handleDeleteErrors(errors);
|
||||
// });
|
||||
// };
|
||||
|
||||
return (
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={
|
||||
<T id={'delete_count'} values={{ count: size(exchangeRatesIds) }} />
|
||||
}
|
||||
icon="trash"
|
||||
intent={Intent.DANGER}
|
||||
isOpen={isOpen}
|
||||
onCancel={handleCancelBulkDelete}
|
||||
// onConfirm={}
|
||||
// loading={isLoading}
|
||||
>
|
||||
<p>
|
||||
<T
|
||||
id={'once_delete_these_exchange_rates_you_will_not_able_restore_them'}
|
||||
/>
|
||||
</p>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withAlertStoreConnect(),
|
||||
withAlertActions,
|
||||
)(ExchangeRateBulkDeleteAlert);
|
||||
@@ -1,72 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import {
|
||||
AppToaster,
|
||||
FormattedMessage as T,
|
||||
FormattedHTMLMessage,
|
||||
} from '@/components';
|
||||
import { Intent, Alert } from '@blueprintjs/core';
|
||||
|
||||
import { useDeleteExchangeRate } from '@/hooks/query';
|
||||
import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect';
|
||||
import withAlertActions from '@/containers/Alert/withAlertActions';
|
||||
|
||||
import { compose } from '@/utils';
|
||||
|
||||
/**
|
||||
* exchange rate delete alerts.
|
||||
*/
|
||||
function ExchangeRateDeleteAlert({
|
||||
name,
|
||||
|
||||
// #withAlertStoreConnect
|
||||
isOpen,
|
||||
payload: { exchangeRateId },
|
||||
|
||||
// #withAlertActions
|
||||
closeAlert,
|
||||
}) {
|
||||
const { mutateAsync: deleteExchangeRate, isLoading } =
|
||||
useDeleteExchangeRate();
|
||||
|
||||
// Handle cancel delete exchange rate alert.
|
||||
const handleCancelExchangeRateDelete = () => closeAlert(name);
|
||||
|
||||
const handelConfirmExchangeRateDelete = () => {
|
||||
deleteExchangeRate(exchangeRateId)
|
||||
.then((response) => {
|
||||
AppToaster.show({
|
||||
message: intl.get('the_exchange_rates_has_been_deleted_successfully'),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
closeAlert(name);
|
||||
})
|
||||
.catch(() => {
|
||||
closeAlert(name);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={<T id={'delete'} />}
|
||||
intent={Intent.DANGER}
|
||||
isOpen={isOpen}
|
||||
onCancel={handleCancelExchangeRateDelete}
|
||||
onConfirm={handelConfirmExchangeRateDelete}
|
||||
loading={isLoading}
|
||||
>
|
||||
<p>
|
||||
<FormattedHTMLMessage
|
||||
id={'once_delete_this_exchange_rate_you_will_able_to_restore_it'}
|
||||
/>
|
||||
</p>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withAlertStoreConnect(),
|
||||
withAlertActions,
|
||||
)(ExchangeRateDeleteAlert);
|
||||
@@ -21,7 +21,7 @@ import { DRAWERS } from '@/constants/drawers';
|
||||
/**
|
||||
* Payment receive delete alert.
|
||||
*/
|
||||
function PaymentReceiveDeleteAlert({
|
||||
function PaymentReceivedDeleteAlert({
|
||||
name,
|
||||
|
||||
// #withAlertStoreConnect
|
||||
@@ -48,11 +48,11 @@ function PaymentReceiveDeleteAlert({
|
||||
.then(() => {
|
||||
AppToaster.show({
|
||||
message: intl.get(
|
||||
'the_payment_receive_has_been_deleted_successfully',
|
||||
'the_payment_received_has_been_deleted_successfully',
|
||||
),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
closeDrawer(DRAWERS.PAYMENT_RECEIVE_DETAILS);
|
||||
closeDrawer(DRAWERS.PAYMENT_RECEIVED_DETAILS);
|
||||
})
|
||||
.catch(
|
||||
({
|
||||
@@ -81,7 +81,7 @@ function PaymentReceiveDeleteAlert({
|
||||
>
|
||||
<p>
|
||||
<FormattedHTMLMessage
|
||||
id={'once_delete_this_payment_receive_you_will_able_to_restore_it'}
|
||||
id={'once_delete_this_payment_received_you_will_able_to_restore_it'}
|
||||
/>
|
||||
</p>
|
||||
</Alert>
|
||||
@@ -92,4 +92,4 @@ export default compose(
|
||||
withAlertStoreConnect(),
|
||||
withAlertActions,
|
||||
withDrawerActions,
|
||||
)(PaymentReceiveDeleteAlert);
|
||||
)(PaymentReceivedDeleteAlert);
|
||||
@@ -6,9 +6,9 @@ import InventoryAdjustmentsAlerts from '@/containers/InventoryAdjustments/Invent
|
||||
import EstimatesAlerts from '@/containers/Sales/Estimates/EstimatesAlerts';
|
||||
import InvoicesAlerts from '@/containers/Sales/Invoices/InvoicesAlerts';
|
||||
import ReceiptsAlerts from '@/containers/Sales/Receipts/ReceiptsAlerts';
|
||||
import PaymentReceiveAlerts from '@/containers/Sales/PaymentReceives/PaymentReceiveAlerts';
|
||||
import PaymentsReceivedAlerts from '@/containers/Sales/PaymentsReceived/PaymentsReceivedAlerts';
|
||||
import BillsAlerts from '@/containers/Purchases/Bills/BillsLanding/BillsAlerts';
|
||||
import PaymentMadesAlerts from '@/containers/Purchases/PaymentMades/PaymentMadesAlerts';
|
||||
import PaymentsMadeAlerts from '@/containers/Purchases/PaymentsMade/PaymentsMadeAlerts';
|
||||
import CustomersAlerts from '@/containers/Customers/CustomersAlerts';
|
||||
import VendorsAlerts from '@/containers/Vendors/VendorsAlerts';
|
||||
import ManualJournalsAlerts from '@/containers/Accounting/JournalsLanding/ManualJournalsAlerts';
|
||||
@@ -38,9 +38,9 @@ export default [
|
||||
...EstimatesAlerts,
|
||||
...InvoicesAlerts,
|
||||
...ReceiptsAlerts,
|
||||
...PaymentReceiveAlerts,
|
||||
...PaymentsReceivedAlerts,
|
||||
...BillsAlerts,
|
||||
...PaymentMadesAlerts,
|
||||
...PaymentsMadeAlerts,
|
||||
...CustomersAlerts,
|
||||
...VendorsAlerts,
|
||||
...ManualJournalsAlerts,
|
||||
|
||||
@@ -120,6 +120,7 @@ export function UploadAttachmentsPopoverContent({
|
||||
uploadIcon={null}
|
||||
value={null}
|
||||
title={''}
|
||||
subtitle={'Drag and drop file here or choose file'}
|
||||
classNames={{ root: styles.dropzoneRoot }}
|
||||
onChange={handleChangeDropzone}
|
||||
dropzoneProps={{
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// @ts-nocheck
|
||||
import { useCallback, useMemo } from 'react';
|
||||
import { Form, Formik, FormikHelpers, useFormikContext } from 'formik';
|
||||
import { get } from 'lodash';
|
||||
import { Button, Classes, Intent, Radio, Tag } from '@blueprintjs/core';
|
||||
import * as R from 'ramda';
|
||||
import { CreateRuleFormSchema } from './RuleFormContentForm.schema';
|
||||
@@ -17,11 +18,12 @@ import {
|
||||
} from '@/components';
|
||||
import { useCreateBankRule, useEditBankRule } from '@/hooks/query/bank-rules';
|
||||
import {
|
||||
FieldCondition,
|
||||
Fields,
|
||||
RuleFormValues,
|
||||
TransactionTypeOptions,
|
||||
getAccountRootFromMoneyCategory,
|
||||
getDefaultFieldConditionByFieldKey,
|
||||
getFieldConditionsByFieldKey,
|
||||
initialValues,
|
||||
} from './_utils';
|
||||
import { useRuleFormDialogBoot } from './RuleFormBoot';
|
||||
@@ -175,6 +177,13 @@ function RuleFormConditions() {
|
||||
setFieldValue('conditions', _conditions);
|
||||
};
|
||||
|
||||
const handleConditionFieldChange = R.curry((index, item) => {
|
||||
const defaultComparator = getDefaultFieldConditionByFieldKey(item.value);
|
||||
|
||||
setFieldValue(`conditions[${index}].field`, item.value);
|
||||
setFieldValue(`conditions[${index}].comparator`, defaultComparator);
|
||||
});
|
||||
|
||||
return (
|
||||
<Box style={{ marginBottom: 15 }}>
|
||||
<Stack spacing={15}>
|
||||
@@ -190,6 +199,7 @@ function RuleFormConditions() {
|
||||
name={`conditions[${index}].field`}
|
||||
items={Fields}
|
||||
popoverProps={{ minimal: true, inline: false }}
|
||||
onItemChange={handleConditionFieldChange(index)}
|
||||
fastField
|
||||
/>
|
||||
</FFormGroup>
|
||||
@@ -202,8 +212,13 @@ function RuleFormConditions() {
|
||||
>
|
||||
<FSelect
|
||||
name={`conditions[${index}].comparator`}
|
||||
items={FieldCondition}
|
||||
items={getFieldConditionsByFieldKey(
|
||||
get(values, `conditions[${index}].field`),
|
||||
)}
|
||||
popoverProps={{ minimal: true, inline: false }}
|
||||
shouldUpdateDeps={{
|
||||
fieldKey: get(values, `conditions[${index}].field`),
|
||||
}}
|
||||
fastField
|
||||
/>
|
||||
</FFormGroup>
|
||||
|
||||
@@ -42,11 +42,25 @@ export const Fields = [
|
||||
{ value: 'amount', text: 'Amount' },
|
||||
{ value: 'payee', text: 'Payee' },
|
||||
];
|
||||
export const FieldCondition = [
|
||||
|
||||
export const TextFieldConditions = [
|
||||
{ value: 'contains', text: 'Contains' },
|
||||
{ value: 'equals', text: 'Equals' },
|
||||
{ value: 'not_contains', text: 'Not Contains' },
|
||||
];
|
||||
export const NumberFieldConditions = [
|
||||
{ value: 'equal', text: 'Equal' },
|
||||
{ value: 'bigger', text: 'Bigger' },
|
||||
{ value: 'bigger_or_equal', text: 'Bigger or Equal' },
|
||||
{ value: 'smaller', text: 'Smaller' },
|
||||
{ value: 'smaller_or_equal', text: 'Smaller or Equal' },
|
||||
];
|
||||
|
||||
export const FieldCondition = [
|
||||
...TextFieldConditions,
|
||||
...NumberFieldConditions,
|
||||
];
|
||||
|
||||
export const AssignTransactionTypeOptions = [
|
||||
{ value: 'expense', text: 'Expense' },
|
||||
];
|
||||
@@ -56,3 +70,21 @@ export const getAccountRootFromMoneyCategory = (category: string): string[] => {
|
||||
|
||||
return get(MoneyCategoryPerCreditAccountRootType, _category) || [];
|
||||
};
|
||||
|
||||
export const getFieldConditionsByFieldKey = (fieldKey?: string) => {
|
||||
switch (fieldKey) {
|
||||
case 'amount':
|
||||
return NumberFieldConditions;
|
||||
default:
|
||||
return TextFieldConditions;
|
||||
}
|
||||
};
|
||||
|
||||
export const getDefaultFieldConditionByFieldKey = (fieldKey?: string) => {
|
||||
switch (fieldKey) {
|
||||
case 'amount':
|
||||
return 'bigger_or_equal';
|
||||
default:
|
||||
return 'contains';
|
||||
}
|
||||
};
|
||||
|
||||
@@ -32,7 +32,7 @@ import {
|
||||
getAddMoneyOutOptions,
|
||||
getAddMoneyInOptions,
|
||||
} from '@/constants/cashflowOptions';
|
||||
import { useRefreshCashflowTransactionsInfinity } from '@/hooks/query';
|
||||
import { useRefreshCashflowTransactions } from '@/hooks/query';
|
||||
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
@@ -64,6 +64,7 @@ function AccountTransactionsActionsBar({
|
||||
uncategorizedTransationsIdsSelected,
|
||||
excludedTransactionsIdsSelected,
|
||||
openMatchingTransactionAside,
|
||||
categorizedTransactionsSelected,
|
||||
|
||||
// #withBankingActions
|
||||
enableMultipleCategorization,
|
||||
@@ -75,7 +76,7 @@ function AccountTransactionsActionsBar({
|
||||
const { accountId, currentAccount } = useAccountTransactionsContext();
|
||||
|
||||
// Refresh cashflow infinity transactions hook.
|
||||
const { refresh } = useRefreshCashflowTransactionsInfinity();
|
||||
const { refresh } = useRefreshCashflowTransactions();
|
||||
|
||||
const { mutateAsync: updateBankAccount } = useUpdateBankAccount();
|
||||
|
||||
@@ -140,7 +141,7 @@ function AccountTransactionsActionsBar({
|
||||
};
|
||||
// Handle the refresh button click.
|
||||
const handleRefreshBtnClick = () => {
|
||||
refresh();
|
||||
refresh(accountId);
|
||||
};
|
||||
|
||||
const {
|
||||
@@ -194,7 +195,7 @@ function AccountTransactionsActionsBar({
|
||||
// Handle multi select transactions for categorization or matching.
|
||||
const handleMultipleCategorizingSwitch = (event) => {
|
||||
enableMultipleCategorization(event.currentTarget.checked);
|
||||
}
|
||||
};
|
||||
// Handle resume bank feeds syncing.
|
||||
const handleResumeFeedsSyncing = () => {
|
||||
openAlert('resume-feeds-syncing-bank-accounnt', {
|
||||
@@ -207,6 +208,18 @@ function AccountTransactionsActionsBar({
|
||||
bankAccountId: accountId,
|
||||
});
|
||||
};
|
||||
// Handles uncategorize the categorized transactions in bulk.
|
||||
const handleUncategorizeCategorizedBulkBtnClick = () => {
|
||||
openAlert('uncategorize-transactions-bulk', {
|
||||
uncategorizeTransactionsIds: categorizedTransactionsSelected,
|
||||
});
|
||||
};
|
||||
// Handles the delete account button click.
|
||||
const handleDeleteAccountClick = () => {
|
||||
openAlert('account-delete', {
|
||||
accountId,
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
@@ -297,6 +310,14 @@ function AccountTransactionsActionsBar({
|
||||
disabled={isUnexcludingLoading}
|
||||
/>
|
||||
)}
|
||||
{!isEmpty(categorizedTransactionsSelected) && (
|
||||
<Button
|
||||
text={'Uncategorize'}
|
||||
onClick={handleUncategorizeCategorizedBulkBtnClick}
|
||||
intent={Intent.DANGER}
|
||||
minimal
|
||||
/>
|
||||
)}
|
||||
</NavbarGroup>
|
||||
|
||||
<NavbarGroup align={Alignment.RIGHT}>
|
||||
@@ -348,9 +369,19 @@ function AccountTransactionsActionsBar({
|
||||
|
||||
<MenuItem onClick={handleBankRulesClick} text={'Bank rules'} />
|
||||
|
||||
<MenuDivider />
|
||||
<If condition={isSyncingOwner && isFeedsActive}>
|
||||
<MenuItem onClick={handleDisconnectClick} text={'Disconnect'} />
|
||||
<MenuItem
|
||||
intent={Intent.DANGER}
|
||||
onClick={handleDisconnectClick}
|
||||
text={'Disconnect'}
|
||||
/>
|
||||
</If>
|
||||
<MenuItem
|
||||
intent={Intent.DANGER}
|
||||
onClick={handleDeleteAccountClick}
|
||||
text={'Delete'}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
@@ -379,10 +410,12 @@ export default compose(
|
||||
uncategorizedTransationsIdsSelected,
|
||||
excludedTransactionsIdsSelected,
|
||||
openMatchingTransactionAside,
|
||||
categorizedTransactionsSelected,
|
||||
}) => ({
|
||||
uncategorizedTransationsIdsSelected,
|
||||
excludedTransactionsIdsSelected,
|
||||
openMatchingTransactionAside,
|
||||
categorizedTransactionsSelected,
|
||||
}),
|
||||
),
|
||||
withBankingActions,
|
||||
|
||||
@@ -17,15 +17,16 @@ import { TABLES } from '@/constants/tables';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withAlertsActions from '@/containers/Alert/withAlertActions';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import { withBankingActions } from '../withBankingActions';
|
||||
|
||||
import { useMemorizedColumnsWidths } from '@/hooks';
|
||||
import { useAccountTransactionsColumns, ActionsMenu } from './components';
|
||||
import { useAccountTransactionsAllContext } from './AccountTransactionsAllBoot';
|
||||
import { useUnmatchMatchedUncategorizedTransaction } from '@/hooks/query/bank-rules';
|
||||
import { useUncategorizeTransaction } from '@/hooks/query';
|
||||
import { handleCashFlowTransactionType } from './utils';
|
||||
|
||||
import { compose } from '@/utils';
|
||||
import { useUncategorizeTransaction } from '@/hooks/query';
|
||||
|
||||
/**
|
||||
* Account transactions data table.
|
||||
@@ -39,13 +40,19 @@ function AccountTransactionsDataTable({
|
||||
|
||||
// #withDrawerActions
|
||||
openDrawer,
|
||||
|
||||
// #withBankingActions
|
||||
setCategorizedTransactionsSelected,
|
||||
}) {
|
||||
// Retrieve table columns.
|
||||
const columns = useAccountTransactionsColumns();
|
||||
|
||||
// Retrieve list context.
|
||||
const { cashflowTransactions, isCashFlowTransactionsLoading } =
|
||||
useAccountTransactionsAllContext();
|
||||
const {
|
||||
cashflowTransactions,
|
||||
isCashFlowTransactionsLoading,
|
||||
isCashFlowTransactionsFetching,
|
||||
} = useAccountTransactionsAllContext();
|
||||
|
||||
const { mutateAsync: uncategorizeTransaction } = useUncategorizeTransaction();
|
||||
const { mutateAsync: unmatchTransaction } =
|
||||
@@ -97,6 +104,15 @@ function AccountTransactionsDataTable({
|
||||
});
|
||||
};
|
||||
|
||||
// Handle selected rows change.
|
||||
const handleSelectedRowsChange = (selected) => {
|
||||
const selectedIds = selected
|
||||
?.filter((row) => row.original.uncategorized_transaction_id)
|
||||
?.map((row) => row.original.uncategorized_transaction_id);
|
||||
|
||||
setCategorizedTransactionsSelected(selectedIds);
|
||||
};
|
||||
|
||||
return (
|
||||
<CashflowTransactionsTable
|
||||
noInitialFetch={true}
|
||||
@@ -105,6 +121,7 @@ function AccountTransactionsDataTable({
|
||||
sticky={true}
|
||||
loading={isCashFlowTransactionsLoading}
|
||||
headerLoading={isCashFlowTransactionsLoading}
|
||||
progressBarLoading={isCashFlowTransactionsFetching}
|
||||
expandColumnSpace={1}
|
||||
expandToggleColumn={2}
|
||||
selectionColumnWidth={45}
|
||||
@@ -119,6 +136,8 @@ function AccountTransactionsDataTable({
|
||||
vListOverscanRowCount={0}
|
||||
initialColumnsWidths={initialColumnsWidths}
|
||||
onColumnResizing={handleColumnResizing}
|
||||
selectionColumn={true}
|
||||
onSelectedRowsChange={handleSelectedRowsChange}
|
||||
noResults={<T id={'cash_flow.account_transactions.no_results'} />}
|
||||
className="table-constrant"
|
||||
payload={{
|
||||
@@ -136,6 +155,7 @@ export default compose(
|
||||
})),
|
||||
withAlertsActions,
|
||||
withDrawerActions,
|
||||
withBankingActions,
|
||||
)(AccountTransactionsDataTable);
|
||||
|
||||
const DashboardConstrantTable = styled(DataTable)`
|
||||
|
||||
@@ -20,7 +20,8 @@ export function AccountTransactionsFilterTabs() {
|
||||
const hasUncategorizedTransx = useMemo(
|
||||
() =>
|
||||
bankAccountMetaSummary?.totalUncategorizedTransactions > 0 ||
|
||||
bankAccountMetaSummary?.totalExcludedTransactions > 0,
|
||||
bankAccountMetaSummary?.totalExcludedTransactions > 0 ||
|
||||
bankAccountMetaSummary?.totalPendingTransactions > 0,
|
||||
[bankAccountMetaSummary],
|
||||
);
|
||||
|
||||
|
||||
@@ -13,10 +13,10 @@ import {
|
||||
useAccountTransactionsContext,
|
||||
} from './AccountTransactionsProvider';
|
||||
import { AccountTransactionsDetailsBar } from './AccountTransactionsDetailsBar';
|
||||
import { AccountTransactionsProgressBar } from './components';
|
||||
import { AccountTransactionsFilterTabs } from './AccountTransactionsFilterTabs';
|
||||
import { AppContentShell } from '@/components/AppShell';
|
||||
import { CategorizeTransactionAside } from '../CategorizeTransactionAside/CategorizeTransactionAside';
|
||||
import { AccountTransactionsLoadingBar } from './components';
|
||||
import { withBanking } from '../withBanking';
|
||||
|
||||
/**
|
||||
@@ -42,8 +42,8 @@ function AccountTransactionsMain() {
|
||||
return (
|
||||
<AppContentShell.Main ref={(e) => setScrollableRef(e)}>
|
||||
<AccountTransactionsActionsBar />
|
||||
<AccountTransactionsLoadingBar />
|
||||
<AccountTransactionsDetailsBar />
|
||||
<AccountTransactionsProgressBar />
|
||||
|
||||
<DashboardPageContent>
|
||||
<AccountTransactionsFilterTabs />
|
||||
|
||||
@@ -39,6 +39,7 @@ function AccountTransactionsProvider({ query, ...props }) {
|
||||
const {
|
||||
data: bankAccountMetaSummary,
|
||||
isLoading: isBankAccountMetaSummaryLoading,
|
||||
isFetching: isBankAccountMetaSummaryFetching,
|
||||
} = useGetBankAccountSummaryMeta(accountId);
|
||||
|
||||
const [scrollableRef, setScrollableRef] = useState();
|
||||
@@ -52,15 +53,18 @@ function AccountTransactionsProvider({ query, ...props }) {
|
||||
|
||||
isCashFlowAccountsFetching,
|
||||
isCashFlowAccountsLoading,
|
||||
|
||||
isCurrentAccountFetching,
|
||||
isCurrentAccountLoading,
|
||||
|
||||
isBankAccountMetaSummaryLoading,
|
||||
isBankAccountMetaSummaryFetching,
|
||||
|
||||
filterTab,
|
||||
setFilterTab,
|
||||
|
||||
scrollableRef,
|
||||
setScrollableRef
|
||||
setScrollableRef,
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,21 +1,13 @@
|
||||
// @ts-nocheck
|
||||
import { useMemo } from 'react';
|
||||
import * as R from 'ramda';
|
||||
import * as Yup from 'yup';
|
||||
import { useMemo } from 'react';
|
||||
import { Form, Formik } from 'formik';
|
||||
import { useAppQueryString } from '@/hooks';
|
||||
import { Box, FDateInput, FFormGroup, Group, Icon, Stack } from '@/components';
|
||||
import { FDateInput, FFormGroup, Group, Icon, Stack } from '@/components';
|
||||
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||
import { TagsControl } from '@/components/TagsControl';
|
||||
import {
|
||||
Button,
|
||||
Classes,
|
||||
FormGroup,
|
||||
Intent,
|
||||
Popover,
|
||||
Position,
|
||||
} from '@blueprintjs/core';
|
||||
import { DateInput } from '@blueprintjs/datetime';
|
||||
import { Form, Formik } from 'formik';
|
||||
import { Button, FormGroup, Intent, Position } from '@blueprintjs/core';
|
||||
|
||||
export function AccountTransactionsUncategorizeFilter() {
|
||||
const { bankAccountMetaSummary } = useAccountTransactionsContext();
|
||||
@@ -25,31 +17,49 @@ export function AccountTransactionsUncategorizeFilter() {
|
||||
bankAccountMetaSummary?.totalUncategorizedTransactions;
|
||||
const totalRecognized = bankAccountMetaSummary?.totalRecognizedTransactions;
|
||||
|
||||
const totalPending = bankAccountMetaSummary?.totalPendingTransactions;
|
||||
|
||||
const handleTabsChange = (value) => {
|
||||
setLocationQuery({ uncategorizedFilter: value });
|
||||
};
|
||||
|
||||
const options = useMemo(
|
||||
() =>
|
||||
R.when(
|
||||
() => totalPending > 0,
|
||||
R.append({
|
||||
value: 'pending',
|
||||
label: (
|
||||
<>
|
||||
Pending <strong>({totalPending})</strong>
|
||||
</>
|
||||
),
|
||||
}),
|
||||
)([
|
||||
{
|
||||
value: 'all',
|
||||
label: (
|
||||
<>
|
||||
All <strong>({totalUncategorized})</strong>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'recognized',
|
||||
label: (
|
||||
<>
|
||||
Recognized <strong>({totalRecognized})</strong>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]),
|
||||
[totalPending, totalRecognized, totalUncategorized],
|
||||
);
|
||||
|
||||
return (
|
||||
<Group position={'apart'}>
|
||||
<TagsControl
|
||||
options={[
|
||||
{
|
||||
value: 'all',
|
||||
label: (
|
||||
<>
|
||||
All <strong>({totalUncategorized})</strong>
|
||||
</>
|
||||
),
|
||||
},
|
||||
{
|
||||
value: 'recognized',
|
||||
label: (
|
||||
<>
|
||||
Recognized <strong>({totalRecognized})</strong>
|
||||
</>
|
||||
),
|
||||
},
|
||||
]}
|
||||
options={options}
|
||||
value={locationQuery?.uncategorizedFilter || 'all'}
|
||||
onValueChange={handleTabsChange}
|
||||
/>
|
||||
|
||||
@@ -54,6 +54,12 @@ const AccountUncategorizedTransactions = lazy(() =>
|
||||
).then((module) => ({ default: module.AccountUncategorizedTransactionsAll })),
|
||||
);
|
||||
|
||||
const PendingTransactions = lazy(() =>
|
||||
import('./PendingTransactions/PendingTransactions').then((module) => ({
|
||||
default: module.PendingTransactions,
|
||||
})),
|
||||
);
|
||||
|
||||
/**
|
||||
* Switches between the account transactions tables.
|
||||
* @returns {React.ReactNode}
|
||||
@@ -70,6 +76,8 @@ function AccountTransactionsSwitcher() {
|
||||
case 'all':
|
||||
default:
|
||||
return <AccountUncategorizedTransactions />;
|
||||
case 'pending':
|
||||
return <PendingTransactions />;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,11 @@ function ExcludedTransactionsTableRoot({
|
||||
// #withBankingActions
|
||||
setExcludedTransactionsSelected,
|
||||
}: ExcludeTransactionsTableProps) {
|
||||
const { excludedBankTransactions } = useExcludedTransactionsBoot();
|
||||
const {
|
||||
excludedBankTransactions,
|
||||
isExcludedTransactionsLoading,
|
||||
isExcludedTransactionsFetching,
|
||||
} = useExcludedTransactionsBoot();
|
||||
const { mutateAsync: unexcludeBankTransaction } =
|
||||
useUnexcludeUncategorizedTransaction();
|
||||
|
||||
@@ -79,8 +83,9 @@ function ExcludedTransactionsTableRoot({
|
||||
columns={columns}
|
||||
data={excludedBankTransactions}
|
||||
sticky={true}
|
||||
loading={false}
|
||||
headerLoading={false}
|
||||
loading={isExcludedTransactionsLoading}
|
||||
headerLoading={isExcludedTransactionsLoading}
|
||||
progressBarLoading={isExcludedTransactionsFetching}
|
||||
expandColumnSpace={1}
|
||||
expandToggleColumn={2}
|
||||
selectionColumnWidth={45}
|
||||
|
||||
@@ -37,12 +37,13 @@ export function useExcludedTransactionsColumns() {
|
||||
() => [
|
||||
{
|
||||
Header: 'Date',
|
||||
accessor: 'formatted_date',
|
||||
accessor: 'formatted_date',
|
||||
width: 110,
|
||||
},
|
||||
{
|
||||
Header: 'Description',
|
||||
accessor: descriptionAccessor,
|
||||
textOverview: true,
|
||||
},
|
||||
{
|
||||
Header: 'Payee',
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
import React from 'react';
|
||||
import { AccountTransactionsCard } from '../UncategorizedTransactions/AccountTransactionsCard';
|
||||
import { PendingTransactionsBoot } from './PendingTransactionsTableBoot';
|
||||
import { PendingTransactionsDataTable } from './PendingTransactionsTable';
|
||||
|
||||
export function PendingTransactions() {
|
||||
return (
|
||||
<PendingTransactionsBoot>
|
||||
<AccountTransactionsCard>
|
||||
<PendingTransactionsDataTable />
|
||||
</AccountTransactionsCard>
|
||||
</PendingTransactionsBoot>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import clsx from 'classnames';
|
||||
import styled from 'styled-components';
|
||||
import {
|
||||
DataTable,
|
||||
TableFastCell,
|
||||
TableSkeletonRows,
|
||||
TableSkeletonHeader,
|
||||
TableVirtualizedListRows,
|
||||
} from '@/components';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import { withBankingActions } from '../../withBankingActions';
|
||||
|
||||
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||
import { usePendingTransactionsContext } from './PendingTransactionsTableBoot';
|
||||
import { usePendingTransactionsTableColumns } from './_hooks';
|
||||
|
||||
import { compose } from '@/utils';
|
||||
|
||||
/**
|
||||
* Account transactions data table.
|
||||
*/
|
||||
function PendingTransactionsDataTableRoot({
|
||||
// #withSettings
|
||||
cashflowTansactionsTableSize,
|
||||
}) {
|
||||
// Retrieve table columns.
|
||||
const columns = usePendingTransactionsTableColumns();
|
||||
const { scrollableRef } = useAccountTransactionsContext();
|
||||
|
||||
// Retrieve list context.
|
||||
const {
|
||||
pendingTransactions,
|
||||
isPendingTransactionsLoading,
|
||||
isPendingTransactionFetching,
|
||||
} = usePendingTransactionsContext();
|
||||
|
||||
return (
|
||||
<CashflowTransactionsTable
|
||||
noInitialFetch={true}
|
||||
columns={columns}
|
||||
data={pendingTransactions || []}
|
||||
sticky={true}
|
||||
loading={isPendingTransactionsLoading}
|
||||
headerLoading={isPendingTransactionsLoading}
|
||||
progressBarLoading={isPendingTransactionFetching}
|
||||
TableCellRenderer={TableFastCell}
|
||||
TableLoadingRenderer={TableSkeletonRows}
|
||||
TableRowsRenderer={TableVirtualizedListRows}
|
||||
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
||||
// #TableVirtualizedListRows props.
|
||||
vListrowHeight={cashflowTansactionsTableSize === 'small' ? 32 : 40}
|
||||
vListOverscanRowCount={0}
|
||||
noResults={'There is no pending transactions in the current account.'}
|
||||
windowScrollerProps={{ scrollElement: scrollableRef }}
|
||||
className={clsx('table-constrant')}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export const PendingTransactionsDataTable = compose(
|
||||
withSettings(({ cashflowTransactionsSettings }) => ({
|
||||
cashflowTansactionsTableSize: cashflowTransactionsSettings?.tableSize,
|
||||
})),
|
||||
withBankingActions,
|
||||
)(PendingTransactionsDataTableRoot);
|
||||
|
||||
const DashboardConstrantTable = styled(DataTable)`
|
||||
.table {
|
||||
.thead {
|
||||
.th {
|
||||
background: #fff;
|
||||
text-transform: uppercase;
|
||||
letter-spacing: 1px;
|
||||
font-size: 13px;i
|
||||
font-weight: 500;
|
||||
}
|
||||
}
|
||||
|
||||
.tbody {
|
||||
.tr:last-child .td {
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
const CashflowTransactionsTable = styled(DashboardConstrantTable)`
|
||||
.table .tbody {
|
||||
.tbody-inner .tr.no-results {
|
||||
.td {
|
||||
padding: 2rem 0;
|
||||
font-size: 14px;
|
||||
color: #888;
|
||||
font-weight: 400;
|
||||
border-bottom: 0;
|
||||
}
|
||||
}
|
||||
|
||||
.tbody-inner {
|
||||
.tr .td:not(:first-child) {
|
||||
border-left: 1px solid #e6e6e6;
|
||||
}
|
||||
|
||||
.td-description {
|
||||
color: #5f6b7c;
|
||||
}
|
||||
}
|
||||
}
|
||||
`;
|
||||
@@ -0,0 +1,72 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { flatten, map } from 'lodash';
|
||||
import { IntersectionObserver } from '@/components';
|
||||
import { useAccountTransactionsContext } from '../AccountTransactionsProvider';
|
||||
import { usePendingBankTransactionsInfinity } from '@/hooks/query/bank-rules';
|
||||
|
||||
const PendingTransactionsContext = React.createContext();
|
||||
|
||||
function flattenInfinityPagesData(data) {
|
||||
return flatten(map(data.pages, (page) => page.data));
|
||||
}
|
||||
|
||||
/**
|
||||
* Account pending transctions provider.
|
||||
*/
|
||||
function PendingTransactionsBoot({ children }) {
|
||||
const { accountId } = useAccountTransactionsContext();
|
||||
|
||||
// Fetches the pending transactions.
|
||||
const {
|
||||
data: pendingTransactionsPage,
|
||||
isFetching: isPendingTransactionFetching,
|
||||
isLoading: isPendingTransactionsLoading,
|
||||
isSuccess: isPendingTransactionsSuccess,
|
||||
isFetchingNextPage: isPendingTransactionFetchNextPage,
|
||||
fetchNextPage: fetchNextPendingTransactionsPage,
|
||||
hasNextPage: hasPendingTransactionsNextPage,
|
||||
} = usePendingBankTransactionsInfinity({
|
||||
account_id: accountId,
|
||||
page_size: 50,
|
||||
});
|
||||
// Memorized the cashflow account transactions.
|
||||
const pendingTransactions = React.useMemo(
|
||||
() =>
|
||||
isPendingTransactionsSuccess
|
||||
? flattenInfinityPagesData(pendingTransactionsPage)
|
||||
: [],
|
||||
[pendingTransactionsPage, isPendingTransactionsSuccess],
|
||||
);
|
||||
// Handle the observer ineraction.
|
||||
const handleObserverInteract = React.useCallback(() => {
|
||||
if (!isPendingTransactionFetching && hasPendingTransactionsNextPage) {
|
||||
fetchNextPendingTransactionsPage();
|
||||
}
|
||||
}, [
|
||||
isPendingTransactionFetching,
|
||||
hasPendingTransactionsNextPage,
|
||||
fetchNextPendingTransactionsPage,
|
||||
]);
|
||||
// Provider payload.
|
||||
const provider = {
|
||||
pendingTransactions,
|
||||
isPendingTransactionFetching,
|
||||
isPendingTransactionsLoading,
|
||||
};
|
||||
|
||||
return (
|
||||
<PendingTransactionsContext.Provider value={provider}>
|
||||
{children}
|
||||
<IntersectionObserver
|
||||
onIntersect={handleObserverInteract}
|
||||
enabled={!isPendingTransactionFetchNextPage}
|
||||
/>
|
||||
</PendingTransactionsContext.Provider>
|
||||
);
|
||||
}
|
||||
|
||||
const usePendingTransactionsContext = () =>
|
||||
React.useContext(PendingTransactionsContext);
|
||||
|
||||
export { PendingTransactionsBoot, usePendingTransactionsContext };
|
||||
@@ -0,0 +1,65 @@
|
||||
import { useMemo } from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
|
||||
/**
|
||||
* Retrieve account pending transctions table columns.
|
||||
*/
|
||||
export function usePendingTransactionsTableColumns() {
|
||||
return useMemo(
|
||||
() => [
|
||||
{
|
||||
id: 'date',
|
||||
Header: intl.get('date'),
|
||||
accessor: 'formatted_date',
|
||||
width: 40,
|
||||
clickable: true,
|
||||
textOverview: true,
|
||||
},
|
||||
{
|
||||
id: 'description',
|
||||
Header: 'Description',
|
||||
accessor: 'description',
|
||||
width: 160,
|
||||
textOverview: true,
|
||||
clickable: true,
|
||||
},
|
||||
{
|
||||
id: 'payee',
|
||||
Header: 'Payee',
|
||||
accessor: 'payee',
|
||||
width: 60,
|
||||
clickable: true,
|
||||
textOverview: true,
|
||||
},
|
||||
{
|
||||
id: 'reference_number',
|
||||
Header: 'Ref.#',
|
||||
accessor: 'reference_no',
|
||||
width: 50,
|
||||
clickable: true,
|
||||
textOverview: true,
|
||||
},
|
||||
{
|
||||
id: 'deposit',
|
||||
Header: intl.get('cash_flow.label.deposit'),
|
||||
accessor: 'formatted_deposit_amount',
|
||||
width: 40,
|
||||
className: 'deposit',
|
||||
textOverview: true,
|
||||
align: 'right',
|
||||
clickable: true,
|
||||
},
|
||||
{
|
||||
id: 'withdrawal',
|
||||
Header: intl.get('cash_flow.label.withdrawal'),
|
||||
accessor: 'formatted_withdrawal_amount',
|
||||
className: 'withdrawal',
|
||||
width: 40,
|
||||
textOverview: true,
|
||||
align: 'right',
|
||||
clickable: true,
|
||||
},
|
||||
],
|
||||
[],
|
||||
);
|
||||
}
|
||||
@@ -52,8 +52,11 @@ function AccountTransactionsDataTable({
|
||||
const { scrollableRef } = useAccountTransactionsContext();
|
||||
|
||||
// Retrieve list context.
|
||||
const { uncategorizedTransactions, isUncategorizedTransactionsLoading } =
|
||||
useAccountUncategorizedTransactionsContext();
|
||||
const {
|
||||
uncategorizedTransactions,
|
||||
isUncategorizedTransactionsLoading,
|
||||
isUncategorizedTransactionFetching,
|
||||
} = useAccountUncategorizedTransactionsContext();
|
||||
|
||||
const { mutateAsync: excludeTransaction } =
|
||||
useExcludeUncategorizedTransaction();
|
||||
@@ -105,6 +108,7 @@ function AccountTransactionsDataTable({
|
||||
selectionColumn={true}
|
||||
loading={isUncategorizedTransactionsLoading}
|
||||
headerLoading={isUncategorizedTransactionsLoading}
|
||||
progressBarLoading={isUncategorizedTransactionFetching}
|
||||
expandColumnSpace={1}
|
||||
expandToggleColumn={2}
|
||||
selectionColumnWidth={45}
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Intent, Alert } from '@blueprintjs/core';
|
||||
|
||||
import { AppToaster, FormattedMessage as T } from '@/components';
|
||||
import withAlertStoreConnect from '@/containers/Alert/withAlertStoreConnect';
|
||||
import withAlertActions from '@/containers/Alert/withAlertActions';
|
||||
|
||||
import { useUncategorizeTransactionsBulkAction } from '@/hooks/query/bank-transactions';
|
||||
import { compose } from '@/utils';
|
||||
|
||||
/**
|
||||
* Uncategorize bank account transactions in build alert.
|
||||
*/
|
||||
function UncategorizeBankTransactionsBulkAlert({
|
||||
name,
|
||||
|
||||
// #withAlertStoreConnect
|
||||
isOpen,
|
||||
payload: { uncategorizeTransactionsIds },
|
||||
|
||||
// #withAlertActions
|
||||
closeAlert,
|
||||
}) {
|
||||
const { mutateAsync: uncategorizeTransactions, isLoading } =
|
||||
useUncategorizeTransactionsBulkAction();
|
||||
|
||||
// Handle activate item alert cancel.
|
||||
const handleCancelActivateItem = () => {
|
||||
closeAlert(name);
|
||||
};
|
||||
|
||||
// Handle confirm item activated.
|
||||
const handleConfirmItemActivate = () => {
|
||||
uncategorizeTransactions({ ids: uncategorizeTransactionsIds })
|
||||
.then(() => {
|
||||
AppToaster.show({
|
||||
message: 'The bank feeds of the bank account has been resumed.',
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
})
|
||||
.catch((error) => {})
|
||||
.finally(() => {
|
||||
closeAlert(name);
|
||||
});
|
||||
};
|
||||
|
||||
return (
|
||||
<Alert
|
||||
cancelButtonText={<T id={'cancel'} />}
|
||||
confirmButtonText={'Uncategorize Transactions'}
|
||||
intent={Intent.DANGER}
|
||||
isOpen={isOpen}
|
||||
onCancel={handleCancelActivateItem}
|
||||
loading={isLoading}
|
||||
onConfirm={handleConfirmItemActivate}
|
||||
>
|
||||
<p>
|
||||
Are you sure want to uncategorize the selected bank transactions, this
|
||||
action is not reversible but you can always categorize them again?
|
||||
</p>
|
||||
</Alert>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(
|
||||
withAlertStoreConnect(),
|
||||
withAlertActions,
|
||||
)(UncategorizeBankTransactionsBulkAlert);
|
||||
@@ -9,6 +9,10 @@ const PauseFeedsBankAccountAlert = React.lazy(
|
||||
() => import('./PauseFeedsBankAccount'),
|
||||
);
|
||||
|
||||
const UncategorizeTransactionsBulkAlert = React.lazy(
|
||||
() => import('./UncategorizeBankTransactionsBulkAlert'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Bank account alerts.
|
||||
*/
|
||||
@@ -21,4 +25,8 @@ export const BankAccountAlerts = [
|
||||
name: 'pause-feeds-syncing-bank-accounnt',
|
||||
component: PauseFeedsBankAccountAlert,
|
||||
},
|
||||
{
|
||||
name: 'uncategorize-transactions-bulk',
|
||||
component: UncategorizeTransactionsBulkAlert,
|
||||
},
|
||||
];
|
||||
|
||||
@@ -1,18 +1,29 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import {
|
||||
Intent,
|
||||
Menu,
|
||||
MenuItem,
|
||||
Tag,
|
||||
PopoverInteractionKind,
|
||||
Position,
|
||||
Tooltip,
|
||||
} from '@blueprintjs/core';
|
||||
import { Box, FormatDateCell, Icon, MaterialProgressBar } from '@/components';
|
||||
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||
import { Intent, Menu, MenuItem, Tag } from '@blueprintjs/core';
|
||||
import { FormatDateCell, Icon } from '@/components';
|
||||
import { safeCallback } from '@/utils';
|
||||
import { useAccountTransactionsContext } from './AccountTransactionsProvider';
|
||||
import FinancialLoadingBar from '@/containers/FinancialStatements/FinancialLoadingBar';
|
||||
|
||||
export function AccountTransactionsLoadingBar() {
|
||||
const {
|
||||
isBankAccountMetaSummaryFetching,
|
||||
isCurrentAccountFetching,
|
||||
isCashFlowAccountsFetching,
|
||||
} = useAccountTransactionsContext();
|
||||
|
||||
const isLoading =
|
||||
isCashFlowAccountsFetching ||
|
||||
isCurrentAccountFetching ||
|
||||
isBankAccountMetaSummaryFetching;
|
||||
|
||||
if (isLoading) {
|
||||
return <FinancialLoadingBar />;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function ActionsMenu({
|
||||
payload: { onUncategorize, onUnmatch },
|
||||
@@ -137,16 +148,3 @@ export function useAccountTransactionsColumns() {
|
||||
[],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Account transactions progress bar.
|
||||
*/
|
||||
export function AccountTransactionsProgressBar() {
|
||||
const { isCashFlowTransactionsFetching, isUncategorizedTransactionFetching } =
|
||||
useAccountTransactionsContext();
|
||||
|
||||
return isCashFlowTransactionsFetching ||
|
||||
isUncategorizedTransactionFetching ? (
|
||||
<MaterialProgressBar />
|
||||
) : null;
|
||||
}
|
||||
|
||||
@@ -66,7 +66,7 @@ export const handleCashFlowTransactionType = (reference, openDrawer) => {
|
||||
expenseId: reference.reference_id,
|
||||
});
|
||||
case 'PaymentReceive':
|
||||
return openDrawer(DRAWERS.PAYMENT_RECEIVE_DETAILS, {
|
||||
return openDrawer(DRAWERS.PAYMENT_RECEIVED_DETAILS, {
|
||||
paymentReceiveId: reference.reference_id,
|
||||
});
|
||||
case 'BillPayment':
|
||||
|
||||
@@ -10,6 +10,7 @@ import { CashFlowAccountsProvider } from './CashFlowAccountsProvider';
|
||||
import CashflowAccountsGrid from './CashflowAccountsGrid';
|
||||
import CashFlowAccountsActionsBar from './CashFlowAccountsActionsBar';
|
||||
import { CashflowAccountsPlaidLink } from './CashflowAccountsPlaidLink';
|
||||
import { CashflowAccountsLoadingBar } from './CashFlowAccountsLoadingBar';
|
||||
|
||||
import withCashflowAccounts from '@/containers/CashFlow/AccountTransactions/withCashflowAccounts';
|
||||
import withCashflowAccountsTableActions from '@/containers/CashFlow/AccountTransactions/withCashflowAccountsTableActions';
|
||||
@@ -35,6 +36,7 @@ function CashFlowAccountsList({
|
||||
return (
|
||||
<CashFlowAccountsProvider tableState={cashflowAccountsTableState}>
|
||||
<CashFlowAccountsActionsBar />
|
||||
<CashflowAccountsLoadingBar />
|
||||
|
||||
<DashboardPageContent>
|
||||
<CashflowAccountsGrid />
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
// @ts-nocheck
|
||||
import FinancialLoadingBar from '@/containers/FinancialStatements/FinancialLoadingBar';
|
||||
import { useCashFlowAccountsContext } from './CashFlowAccountsProvider';
|
||||
|
||||
export function CashflowAccountsLoadingBar() {
|
||||
const { isCashFlowAccountsFetching } = useCashFlowAccountsContext();
|
||||
|
||||
if (isCashFlowAccountsFetching) {
|
||||
return <FinancialLoadingBar />;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -123,7 +123,12 @@ function CashflowBankAccount({
|
||||
code={account.code}
|
||||
balance={!isNull(account.amount) ? account.formatted_amount : '-'}
|
||||
type={account.account_type}
|
||||
updatedBeforeText={getUpdatedBeforeText(account.createdAt)}
|
||||
updatedBeforeText={
|
||||
account.last_feeds_updated_from_now
|
||||
? `Updated ${account.last_feeds_updated_from_now} ago`
|
||||
: ''
|
||||
}
|
||||
uncategorizedTransactionsCount={account.uncategorized_transactions}
|
||||
/>
|
||||
</CashflowAccountAnchor>
|
||||
</ContextMenu2>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import { useAccounts, useBranches } from '@/hooks/query';
|
||||
import { Spinner } from '@blueprintjs/core';
|
||||
import React from 'react';
|
||||
import { Spinner } from '@blueprintjs/core';
|
||||
import { Features } from '@/constants';
|
||||
import { useAccounts, useBranches } from '@/hooks/query';
|
||||
import { useFeatureCan } from '@/hooks/state';
|
||||
|
||||
interface MatchingReconcileTransactionBootProps {
|
||||
children: React.ReactNode;
|
||||
@@ -15,8 +17,17 @@ const MatchingReconcileTransactionBootContext =
|
||||
export function MatchingReconcileTransactionBoot({
|
||||
children,
|
||||
}: MatchingReconcileTransactionBootProps) {
|
||||
// Detarmines whether the feature is enabled.
|
||||
const { featureCan } = useFeatureCan();
|
||||
const isBranchFeatureCan = featureCan(Features.Branches);
|
||||
|
||||
const { data: accounts, isLoading: isAccountsLoading } = useAccounts({}, {});
|
||||
const { data: branches, isLoading: isBranchesLoading } = useBranches({}, {});
|
||||
const { data: branches, isLoading: isBranchesLoading } = useBranches(
|
||||
{},
|
||||
{
|
||||
enabled: isBranchFeatureCan,
|
||||
},
|
||||
);
|
||||
|
||||
const provider = {
|
||||
accounts,
|
||||
|
||||
@@ -10,6 +10,7 @@ import {
|
||||
Box,
|
||||
BranchSelect,
|
||||
FDateInput,
|
||||
FeatureCan,
|
||||
FFormGroup,
|
||||
FInputGroup,
|
||||
FMoneyInputGroup,
|
||||
@@ -30,6 +31,7 @@ import { useAccountTransactionsContext } from '../../AccountTransactions/Account
|
||||
import { MatchingReconcileFormSchema } from './MatchingReconcileTransactionForm.schema';
|
||||
import { initialValues, transformToReq } from './_utils';
|
||||
import { withBanking } from '../../withBanking';
|
||||
import { Features } from '@/constants';
|
||||
|
||||
interface MatchingReconcileTransactionFormProps {
|
||||
onSubmitSuccess?: (values: any) => void;
|
||||
@@ -205,26 +207,28 @@ function CreateReconcileTransactionContent() {
|
||||
<FInputGroup name={'reference_no'} />
|
||||
</FFormGroup>
|
||||
|
||||
<FFormGroup
|
||||
name={'branchId'}
|
||||
label={'Branch'}
|
||||
labelInfo={<Tag minimal>Required</Tag>}
|
||||
fastField
|
||||
>
|
||||
<BranchSelect
|
||||
<FeatureCan feature={Features.Branches}>
|
||||
<FFormGroup
|
||||
name={'branchId'}
|
||||
branches={branches}
|
||||
popoverProps={{
|
||||
minimal: false,
|
||||
position: Position.LEFT,
|
||||
modifiers: {
|
||||
preventOverflow: { enabled: true },
|
||||
},
|
||||
boundary: 'viewport',
|
||||
}}
|
||||
label={'Branch'}
|
||||
labelInfo={<Tag minimal>Required</Tag>}
|
||||
fastField
|
||||
/>
|
||||
</FFormGroup>
|
||||
>
|
||||
<BranchSelect
|
||||
name={'branchId'}
|
||||
branches={branches}
|
||||
popoverProps={{
|
||||
minimal: false,
|
||||
position: Position.LEFT,
|
||||
modifiers: {
|
||||
preventOverflow: { enabled: true },
|
||||
},
|
||||
boundary: 'viewport',
|
||||
}}
|
||||
fastField
|
||||
/>
|
||||
</FFormGroup>
|
||||
</FeatureCan>
|
||||
</Box>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
import { useMemo } from 'react';
|
||||
import { useFormikContext } from 'formik';
|
||||
import { round } from 'lodash';
|
||||
import { MatchingTransactionFormValues } from './types';
|
||||
import { useMatchingTransactionBoot } from './MatchingTransactionBoot';
|
||||
import { useCategorizeTransactionTabsBoot } from './CategorizeTransactionTabsBoot';
|
||||
import { useMemo } from 'react';
|
||||
|
||||
export const transformToReq = (
|
||||
values: MatchingTransactionFormValues,
|
||||
@@ -38,7 +38,7 @@ export const useGetPendingAmountMatched = () => {
|
||||
);
|
||||
const pendingAmount = totalPending - totalMatchedAmount;
|
||||
|
||||
return pendingAmount;
|
||||
return round(pendingAmount, 2);
|
||||
}, [totalPending, perfectMatches, possibleMatches, values]);
|
||||
};
|
||||
|
||||
|
||||
@@ -22,6 +22,9 @@ export const withBanking = (mapState) => {
|
||||
|
||||
transactionsToCategorizeIdsSelected:
|
||||
state.plaid.transactionsToCategorizeSelected,
|
||||
|
||||
categorizedTransactionsSelected:
|
||||
state.plaid.categorizedTransactionsSelected,
|
||||
};
|
||||
return mapState ? mapState(mapped, state, props) : mapped;
|
||||
};
|
||||
|
||||
@@ -13,6 +13,8 @@ import {
|
||||
enableMultipleCategorization,
|
||||
addTransactionsToCategorizeSelected,
|
||||
removeTransactionsToCategorizeSelected,
|
||||
setCategorizedTransactionsSelected,
|
||||
resetCategorizedTransactionsSelected,
|
||||
} from '@/store/banking/banking.reducer';
|
||||
|
||||
export interface WithBankingActionsProps {
|
||||
@@ -35,6 +37,9 @@ export interface WithBankingActionsProps {
|
||||
resetTransactionsToCategorizeSelected: () => void;
|
||||
|
||||
enableMultipleCategorization: (enable: boolean) => void;
|
||||
|
||||
setCategorizedTransactionsSelected: (ids: Array<string | number>) => void;
|
||||
resetCategorizedTransactionsSelected: () => void;
|
||||
}
|
||||
|
||||
const mapDipatchToProps = (dispatch: any): WithBankingActionsProps => ({
|
||||
@@ -120,6 +125,19 @@ const mapDipatchToProps = (dispatch: any): WithBankingActionsProps => ({
|
||||
*/
|
||||
enableMultipleCategorization: (enable: boolean) =>
|
||||
dispatch(enableMultipleCategorization({ enable })),
|
||||
|
||||
/**
|
||||
* Sets the selected ids of the categorized transactions.
|
||||
* @param {Array<string | number>} ids
|
||||
*/
|
||||
setCategorizedTransactionsSelected: (ids: Array<string | number>) =>
|
||||
dispatch(setCategorizedTransactionsSelected({ ids })),
|
||||
|
||||
/**
|
||||
* Resets the selected categorized transcations.
|
||||
*/
|
||||
resetCategorizedTransactionsSelected: () =>
|
||||
dispatch(resetCategorizedTransactionsSelected()),
|
||||
});
|
||||
|
||||
export const withBankingActions = connect<
|
||||
|
||||
@@ -52,7 +52,7 @@ function CustomerFormFormik({
|
||||
...defaultInitialValues,
|
||||
currency_code: base_currency,
|
||||
...transformToForm(contactDuplicate || customer, defaultInitialValues),
|
||||
...initialCustomerValues,
|
||||
...transformToForm(initialCustomerValues, defaultInitialValues),
|
||||
}),
|
||||
[customer, contactDuplicate, base_currency, initialCustomerValues],
|
||||
);
|
||||
@@ -62,7 +62,7 @@ function CustomerFormFormik({
|
||||
const { setSubmitting, resetForm } = formArgs;
|
||||
const formValues = { ...values };
|
||||
|
||||
const onSuccess = () => {
|
||||
const onSuccess = (res) => {
|
||||
AppToaster.show({
|
||||
message: intl.get(
|
||||
isNewMode
|
||||
@@ -73,8 +73,7 @@ function CustomerFormFormik({
|
||||
});
|
||||
setSubmitting(false);
|
||||
resetForm();
|
||||
|
||||
saveInvoke(onSubmitSuccess, values, formArgs, submitPayload);
|
||||
saveInvoke(onSubmitSuccess, values, formArgs, submitPayload, res.data);
|
||||
};
|
||||
|
||||
const onError = () => {
|
||||
|
||||
@@ -136,6 +136,7 @@ function CustomersTable({
|
||||
sticky={true}
|
||||
spinnerProps={{ size: 30 }}
|
||||
pagination={true}
|
||||
initialPageSize={customersTableState.pageSize}
|
||||
manualSortBy={true}
|
||||
manualPagination={true}
|
||||
pagesCount={pagination.pagesCount}
|
||||
|
||||
@@ -14,4 +14,5 @@ export const ExportResources = [
|
||||
{ value: 'bill', text: 'Bills' },
|
||||
{ value: 'bill_payment', text: 'Bill Payments' },
|
||||
{ value: 'vendor_credit', text: 'Vendor Credits' },
|
||||
{ value: 'tax_rate', text: 'Tax Rate' },
|
||||
];
|
||||
|
||||
@@ -25,7 +25,7 @@ function PaymentReceivePdfPreviewDialog({
|
||||
return (
|
||||
<Dialog
|
||||
name={dialogName}
|
||||
title={<T id={'payment_receive_preview.dialog.title'} />}
|
||||
title={<T id={'payment_received_preview.dialog.title'} />}
|
||||
className={classNames(CLASSES.DIALOG_PDF_PREVIEW)}
|
||||
autoFocus={true}
|
||||
canEscapeKeyClose={true}
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import intl from 'react-intl-universal';
|
||||
import * as Yup from 'yup';
|
||||
import { Formik } from 'formik';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { useHistory } from 'react-router-dom';
|
||||
|
||||
import '@/style/pages/Setup/PaymentViaVoucherDialog.scss';
|
||||
|
||||
import { usePaymentByVoucher } from '@/hooks/query';
|
||||
import { AppToaster as Toaster, DialogContent } from '@/components';
|
||||
import PaymentViaLicenseForm from './PaymentViaVoucherForm';
|
||||
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import { compose } from '@/utils';
|
||||
|
||||
/**
|
||||
* Payment via license dialog content.
|
||||
*/
|
||||
function PaymentViaLicenseDialogContent({
|
||||
// #ownProps
|
||||
subscriptionForm,
|
||||
|
||||
// #withDialog
|
||||
closeDialog,
|
||||
}) {
|
||||
const history = useHistory();
|
||||
|
||||
// Payment via voucher
|
||||
const { mutateAsync: paymentViaVoucherMutate } = usePaymentByVoucher();
|
||||
|
||||
// Handle submit.
|
||||
const handleSubmit = (values, { setSubmitting, setErrors }) => {
|
||||
setSubmitting(true);
|
||||
|
||||
const mutateValues = {
|
||||
plan_slug: `essentials-monthly`,
|
||||
license_code: values.license_code,
|
||||
};
|
||||
// Payment via voucher mutate.
|
||||
paymentViaVoucherMutate({ ...mutateValues })
|
||||
.then(() => {
|
||||
Toaster.show({
|
||||
message: intl.get('payment_via_voucher.success_message'),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
return closeDialog('payment-via-voucher');
|
||||
})
|
||||
.then(() => {
|
||||
history.push('initializing');
|
||||
})
|
||||
.catch(
|
||||
({
|
||||
response: {
|
||||
data: { errors },
|
||||
},
|
||||
}) => {
|
||||
if (errors.find((e) => e.type === 'LICENSE.CODE.IS.INVALID')) {
|
||||
setErrors({
|
||||
license_code: 'payment_via_voucher.license_code_not_valid',
|
||||
});
|
||||
}
|
||||
},
|
||||
)
|
||||
.finally((errors) => {
|
||||
setSubmitting(false);
|
||||
});
|
||||
};
|
||||
|
||||
// Initial values.
|
||||
const initialValues = {
|
||||
license_code: '',
|
||||
plan_slug: '',
|
||||
period: '',
|
||||
...subscriptionForm,
|
||||
};
|
||||
// Validation schema.
|
||||
const validationSchema = Yup.object().shape({
|
||||
license_code: Yup.string()
|
||||
.required()
|
||||
.min(10)
|
||||
.max(10)
|
||||
.label(intl.get('license_code')),
|
||||
});
|
||||
|
||||
return (
|
||||
<DialogContent>
|
||||
<Formik
|
||||
initialValues={initialValues}
|
||||
validationSchema={validationSchema}
|
||||
onSubmit={handleSubmit}
|
||||
component={PaymentViaLicenseForm}
|
||||
/>
|
||||
</DialogContent>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDialogActions)(PaymentViaLicenseDialogContent);
|
||||
@@ -1,77 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React from 'react';
|
||||
import { Button, FormGroup, InputGroup, Intent } from '@blueprintjs/core';
|
||||
import { Form, FastField, ErrorMessage, useFormikContext } from 'formik';
|
||||
import { FormattedMessage as T } from '@/components';
|
||||
import { compose } from 'redux';
|
||||
|
||||
import { CLASSES } from '@/constants/classes';
|
||||
import { inputIntent } from '@/utils';
|
||||
import { useAutofocus } from '@/hooks';
|
||||
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
|
||||
/**
|
||||
* Payment via license form.
|
||||
*/
|
||||
function PaymentViaLicenseForm({
|
||||
// #withDialogActions
|
||||
closeDialog,
|
||||
}) {
|
||||
// Formik context.
|
||||
const { isSubmitting } = useFormikContext();
|
||||
|
||||
const licenseNumberRef = useAutofocus();
|
||||
|
||||
// Handle close button click.
|
||||
const handleCloseBtnClick = () => {
|
||||
closeDialog('payment-via-voucher');
|
||||
};
|
||||
|
||||
return (
|
||||
<Form>
|
||||
<div className={CLASSES.DIALOG_BODY}>
|
||||
<p>
|
||||
<T id={'payment_via_voucher.dialog.description'} />
|
||||
</p>
|
||||
|
||||
<FastField name="license_code">
|
||||
{({ field, meta: { error, touched } }) => (
|
||||
<FormGroup
|
||||
label={<T id={'voucher_number'} />}
|
||||
intent={inputIntent({ error, touched })}
|
||||
helperText={<ErrorMessage name="license_code" />}
|
||||
className={'form-group--voucher_number'}
|
||||
>
|
||||
<InputGroup
|
||||
large={true}
|
||||
intent={inputIntent({ error, touched })}
|
||||
{...field}
|
||||
inputRef={(ref) => (licenseNumberRef.current = ref)}
|
||||
/>
|
||||
</FormGroup>
|
||||
)}
|
||||
</FastField>
|
||||
</div>
|
||||
|
||||
<div className={CLASSES.DIALOG_FOOTER}>
|
||||
<div className={CLASSES.DIALOG_FOOTER_ACTIONS}>
|
||||
<Button onClick={handleCloseBtnClick} disabled={isSubmitting}>
|
||||
<T id={'close'} />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
intent={Intent.PRIMARY}
|
||||
disabled={false}
|
||||
type="submit"
|
||||
loading={isSubmitting}
|
||||
>
|
||||
<T id={'submit'} />
|
||||
</Button>
|
||||
</div>
|
||||
</div>
|
||||
</Form>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDialogActions)(PaymentViaLicenseForm);
|
||||
@@ -1,37 +0,0 @@
|
||||
// @ts-nocheck
|
||||
import React, { lazy } from 'react';
|
||||
import { Dialog, DialogSuspense, FormattedMessage as T } from '@/components';
|
||||
|
||||
import withDialogRedux from '@/components/DialogReduxConnect';
|
||||
|
||||
import { compose } from '@/utils';
|
||||
|
||||
// Lazy loading the content.
|
||||
const PaymentViaLicenseDialogContent = lazy(
|
||||
() => import('./PaymentViaVoucherDialogContent'),
|
||||
);
|
||||
|
||||
/**
|
||||
* Payment via license dialog.
|
||||
*/
|
||||
function PaymentViaLicenseDialog({ dialogName, payload, isOpen }) {
|
||||
return (
|
||||
<Dialog
|
||||
name={dialogName}
|
||||
title={<T id={'payment_via_voucher'} />}
|
||||
className={'dialog--payment-via-voucher'}
|
||||
autoFocus={true}
|
||||
canEscapeKeyClose={true}
|
||||
isOpen={isOpen}
|
||||
>
|
||||
<DialogSuspense>
|
||||
<PaymentViaLicenseDialogContent
|
||||
dialogName={dialogName}
|
||||
subscriptionForm={payload}
|
||||
/>
|
||||
</DialogSuspense>
|
||||
</Dialog>
|
||||
);
|
||||
}
|
||||
|
||||
export default compose(withDialogRedux())(PaymentViaLicenseDialog);
|
||||
@@ -7,7 +7,7 @@ import { useFormikContext } from 'formik';
|
||||
import { Intent } from '@blueprintjs/core';
|
||||
import { AppToaster } from '@/components';
|
||||
import { useQuickPaymentMadeContext } from './QuickPaymentMadeFormProvider';
|
||||
import { PAYMENT_MADE_ERRORS } from '@/containers/Purchases/PaymentMades/constants';
|
||||
import { PAYMENT_MADE_ERRORS } from '@/containers/Purchases/PaymentsMade/constants';
|
||||
|
||||
// Default initial values of payment made.
|
||||
export const defaultPaymentMade = {
|
||||
|
||||
@@ -9,7 +9,7 @@ const Schema = Yup.object().shape({
|
||||
.required()
|
||||
.nullable()
|
||||
.max(DATATYPES_LENGTH.STRING)
|
||||
.label(intl.get('payment_receive_no_')),
|
||||
.label(intl.get('payment_received_no_')),
|
||||
payment_date: Yup.date().required().label(intl.get('payment_date_')),
|
||||
deposit_account_id: Yup.number()
|
||||
.required()
|
||||
|
||||
@@ -70,7 +70,7 @@ function QuickPaymentReceiveForm({
|
||||
// Handle request response success.
|
||||
const onSaved = (response) => {
|
||||
AppToaster.show({
|
||||
message: intl.get('the_payment_receive_transaction_has_been_created'),
|
||||
message: intl.get('the_payment_received_transaction_has_been_created'),
|
||||
intent: Intent.SUCCESS,
|
||||
});
|
||||
closeDialog(dialogName);
|
||||
|
||||
@@ -34,7 +34,7 @@ export const transformErrors = (errors, { setFieldError }) => {
|
||||
if (getError('PAYMENT_RECEIVE_NO_REQUIRED')) {
|
||||
setFieldError(
|
||||
'payment_receive_no',
|
||||
intl.get('payment_receive_number_required'),
|
||||
intl.get('payment_received_number_required'),
|
||||
);
|
||||
}
|
||||
if (getError('INVALID_PAYMENT_AMOUNT')) {
|
||||
|
||||
@@ -6,6 +6,11 @@ import {
|
||||
NavbarGroup,
|
||||
Intent,
|
||||
NavbarDivider,
|
||||
Popover,
|
||||
Menu,
|
||||
MenuItem,
|
||||
PopoverInteractionKind,
|
||||
Position,
|
||||
} from '@blueprintjs/core';
|
||||
import {
|
||||
DashboardActionsBar,
|
||||
@@ -23,6 +28,7 @@ import withAlertsActions from '@/containers/Alert/withAlertActions';
|
||||
import { AccountDialogAction } from '@/containers/Dialogs/AccountDialog/utils';
|
||||
import { useAccountDrawerContext } from './AccountDrawerProvider';
|
||||
import { compose, safeCallback } from '@/utils';
|
||||
import { CLASSES } from '@/constants';
|
||||
|
||||
/**
|
||||
* Account drawer action bar.
|
||||
@@ -56,6 +62,14 @@ function AccountDrawerActionBar({
|
||||
const onDeleteAccount = () => {
|
||||
openAlert('account-delete', { accountId: account.id });
|
||||
};
|
||||
// Handle inactivate button click.
|
||||
const handleInactivateBtnClick = () => {
|
||||
openAlert('account-inactivate', { accountId: account.id });
|
||||
};
|
||||
// Handle activate button click.
|
||||
const handleActivateBtnClick = () => {
|
||||
openAlert('account-activate', { accountId: account.id });
|
||||
};
|
||||
|
||||
return (
|
||||
<DashboardActionsBar>
|
||||
@@ -85,6 +99,43 @@ function AccountDrawerActionBar({
|
||||
onClick={safeCallback(onDeleteAccount)}
|
||||
/>
|
||||
</Can>
|
||||
{!account.active && (
|
||||
<>
|
||||
<NavbarDivider />
|
||||
<Button
|
||||
className={CLASSES.MINIMAL}
|
||||
text={'Activate'}
|
||||
intent={Intent.SUCCESS}
|
||||
onClick={handleActivateBtnClick}
|
||||
/>
|
||||
</>
|
||||
)}
|
||||
{!!account.active && (
|
||||
<>
|
||||
<NavbarDivider />
|
||||
<Popover
|
||||
minimal={true}
|
||||
interactionKind={PopoverInteractionKind.CLICK}
|
||||
position={Position.BOTTOM_LEFT}
|
||||
modifiers={{
|
||||
offset: { offset: '0, 4' },
|
||||
}}
|
||||
content={
|
||||
<Menu>
|
||||
<MenuItem
|
||||
onClick={handleInactivateBtnClick}
|
||||
text={'Inactivate'}
|
||||
/>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Button
|
||||
icon={<Icon icon="more-vert" iconSize={16} />}
|
||||
minimal={true}
|
||||
/>
|
||||
</Popover>
|
||||
</>
|
||||
)}
|
||||
</NavbarGroup>
|
||||
</DashboardActionsBar>
|
||||
);
|
||||
|
||||
@@ -20,7 +20,9 @@ export default function BillDetailFooter() {
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<If condition={bill.note}>
|
||||
<DetailItem label={<T id={'note'} />}>{bill.note}</DetailItem>
|
||||
<DetailItem label={<T id={'note'} />} multiline>
|
||||
{bill.note}
|
||||
</DetailItem>
|
||||
</If>
|
||||
</DetailsMenu>
|
||||
</CommercialDocFooter>
|
||||
|
||||
@@ -48,7 +48,7 @@ function BillPaymentTransactionTable({
|
||||
|
||||
// Handles edit bill payment transactions.
|
||||
const handleEditBillPaymentTransactions = ({ bill_payment_id }) => {
|
||||
history.push(`/payment-mades/${bill_payment_id}/edit`);
|
||||
history.push(`/payments-made/${bill_payment_id}/edit`);
|
||||
closeDrawer(DRAWERS.BILL_DETAILS);
|
||||
};
|
||||
|
||||
|
||||
@@ -9,7 +9,10 @@ export function CashflowTransactionDrawerFooter() {
|
||||
return (
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<DetailItem label={<T id={'cash_flow.drawer.label.statement'} />}>
|
||||
<DetailItem
|
||||
label={<T id={'cash_flow.drawer.label.statement'} />}
|
||||
multiline
|
||||
>
|
||||
{cashflowTransaction.description}
|
||||
</DetailItem>
|
||||
</DetailsMenu>
|
||||
|
||||
@@ -21,11 +21,15 @@ export default function CreditNoteDetailFooter() {
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<If condition={creditNote.terms_conditions}>
|
||||
<DetailItem label={<T id={'note'} />} children={creditNote.note} />
|
||||
<DetailItem
|
||||
label={<T id={'note'} />}
|
||||
children={creditNote.note}
|
||||
multiline
|
||||
/>
|
||||
</If>
|
||||
|
||||
<If condition={creditNote.terms_conditions}>
|
||||
<DetailItem label={<T id={'terms_conditions'} />}>
|
||||
<DetailItem label={<T id={'terms_conditions'} />} multiline>
|
||||
{creditNote.terms_conditions}
|
||||
</DetailItem>
|
||||
</If>
|
||||
|
||||
@@ -68,7 +68,7 @@ function CustomerDetailsActionsBar({
|
||||
};
|
||||
// Handle new payment receive button click.
|
||||
const handleNewPaymentClick = () => {
|
||||
history.push('/payment-receives/new');
|
||||
history.push('/payment-received/new');
|
||||
closeDrawer(DRAWERS.CUSTOMER_DETAILS);
|
||||
};
|
||||
// Handle new estimate button click.
|
||||
|
||||
@@ -16,17 +16,20 @@ import { useEstimateDetailDrawerContext } from './EstimateDetailDrawerProvider';
|
||||
*/
|
||||
export default function EstimateDetailFooter() {
|
||||
const { estimate } = useEstimateDetailDrawerContext();
|
||||
|
||||
|
||||
return (
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<If condition={estimate.terms_conditions}>
|
||||
<DetailItem label={<T id={'estimate.details.terms_conditions'} />}>
|
||||
<DetailItem
|
||||
label={<T id={'estimate.details.terms_conditions'} />}
|
||||
multiline
|
||||
>
|
||||
{estimate.terms_conditions}
|
||||
</DetailItem>
|
||||
</If>
|
||||
<If condition={estimate.note}>
|
||||
<DetailItem label={<T id={'estimate.details.note'} />}>
|
||||
<DetailItem label={<T id={'estimate.details.note'} />} multiline>
|
||||
{estimate.note}
|
||||
</DetailItem>
|
||||
</If>
|
||||
|
||||
@@ -10,7 +10,6 @@ import {
|
||||
Col,
|
||||
DetailItem,
|
||||
DetailsMenu,
|
||||
FormatDate,
|
||||
ExchangeRateDetailItem,
|
||||
FormattedMessage as T,
|
||||
} from '@/components';
|
||||
@@ -41,7 +40,7 @@ export default function ExpenseDrawerHeader() {
|
||||
<Col xs={6}>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<DetailItem name={'date'} label={<T id={'date'} />}>
|
||||
{expense.formatted_payment_date}
|
||||
{expense.formatted_date}
|
||||
</DetailItem>
|
||||
|
||||
<DetailItem name={'reference'} label={<T id={'reference_no'} />}>
|
||||
@@ -65,11 +64,11 @@ export default function ExpenseDrawerHeader() {
|
||||
minLabelSize={'180px'}
|
||||
>
|
||||
<DetailItem label={<T id={'published_at'} />}>
|
||||
{expense.formatted_date}
|
||||
{expense.formatted_published_at || '—'}
|
||||
</DetailItem>
|
||||
|
||||
<DetailItem label={<T id={'created_at'} />}>
|
||||
{expense.formatted_created_at}
|
||||
{expense.formatted_created_at}
|
||||
</DetailItem>
|
||||
</DetailsMenu>
|
||||
</Col>
|
||||
|
||||
@@ -23,13 +23,16 @@ export function InvoiceDetailFooter() {
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<If condition={invoice.terms_conditions}>
|
||||
<DetailItem label={<T id={'terms_conditions'} />}>
|
||||
<DetailItem label={<T id={'terms_conditions'} />} multiline>
|
||||
{invoice.terms_conditions}
|
||||
</DetailItem>
|
||||
</If>
|
||||
|
||||
<If condition={invoice.invoice_message}>
|
||||
<DetailItem label={<T id={'invoice.details.invoice_message'} />}>
|
||||
<DetailItem
|
||||
label={<T id={'invoice.details.invoice_message'} />}
|
||||
multiline
|
||||
>
|
||||
{invoice.invoice_message}
|
||||
</DetailItem>
|
||||
</If>
|
||||
|
||||
@@ -47,14 +47,14 @@ function InvoicePaymentTransactionsTable({
|
||||
|
||||
// Handles delete payment transactions.
|
||||
const handleDeletePaymentTransactons = ({ payment_receive_id }) => {
|
||||
openAlert('payment-receive-delete', {
|
||||
openAlert('payment-received-delete', {
|
||||
paymentReceiveId: payment_receive_id,
|
||||
});
|
||||
};
|
||||
|
||||
// Handles edit payment transactions.
|
||||
const handleEditPaymentTransactions = ({ payment_receive_id }) => {
|
||||
history.push(`/payment-receives/${payment_receive_id}/edit`);
|
||||
history.push(`/payments-received/${payment_receive_id}/edit`);
|
||||
closeDrawer(DRAWERS.INVOICE_DETAILS);
|
||||
};
|
||||
return (
|
||||
|
||||
@@ -42,7 +42,7 @@ function PaymentMadeDetailActionsBar({
|
||||
|
||||
// Handle edit payment made.
|
||||
const handleEditPaymentMade = () => {
|
||||
history.push(`/payment-mades/${paymentMadeId}/edit`);
|
||||
history.push(`/payments-made/${paymentMadeId}/edit`);
|
||||
closeDrawer(DRAWERS.PAYMENT_MADE_DETAILS);
|
||||
};
|
||||
|
||||
|
||||
@@ -20,7 +20,10 @@ export function PaymentMadeDetailFooter() {
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<If condition={paymentMade.statement}>
|
||||
<DetailItem label={<T id={'payment_made.details.statement'} />}>
|
||||
<DetailItem
|
||||
label={<T id={'payment_made.details.statement'} />}
|
||||
multiline
|
||||
>
|
||||
{paymentMade.statement}
|
||||
</DetailItem>
|
||||
</If>
|
||||
|
||||
@@ -33,7 +33,7 @@ import { DialogsName } from '@/constants/dialogs';
|
||||
/**
|
||||
* Payment receive actions bar.
|
||||
*/
|
||||
function PaymentReceiveActionsBar({
|
||||
function PaymentsReceivedActionsBar({
|
||||
// #withAlertsActions
|
||||
openAlert,
|
||||
|
||||
@@ -50,13 +50,13 @@ function PaymentReceiveActionsBar({
|
||||
|
||||
// Handle edit payment receive.
|
||||
const handleEditPaymentReceive = () => {
|
||||
history.push(`/payment-receives/${paymentReceiveId}/edit`);
|
||||
closeDrawer(DRAWERS.PAYMENT_RECEIVE_DETAILS);
|
||||
history.push(`/payments-received/${paymentReceiveId}/edit`);
|
||||
closeDrawer(DRAWERS.PAYMENT_RECEIVED_DETAILS);
|
||||
};
|
||||
|
||||
// Handle delete payment receive.
|
||||
const handleDeletePaymentReceive = () => {
|
||||
openAlert('payment-receive-delete', { paymentReceiveId });
|
||||
openAlert('payment-received-delete', { paymentReceiveId });
|
||||
};
|
||||
|
||||
// Handle notify via SMS.
|
||||
@@ -80,7 +80,7 @@ function PaymentReceiveActionsBar({
|
||||
<Button
|
||||
className={Classes.MINIMAL}
|
||||
icon={<Icon icon="pen-18" />}
|
||||
text={<T id={'edit_payment_receive'} />}
|
||||
text={<T id={'edit_payment_received'} />}
|
||||
onClick={handleEditPaymentReceive}
|
||||
/>
|
||||
<NavbarDivider />
|
||||
@@ -129,4 +129,4 @@ export default compose(
|
||||
withDialogActions,
|
||||
withDrawerActions,
|
||||
withAlertsActions,
|
||||
)(PaymentReceiveActionsBar);
|
||||
)(PaymentsReceivedActionsBar);
|
||||
|
||||
@@ -16,12 +16,15 @@ import { usePaymentReceiveDetailContext } from './PaymentReceiveDetailProvider';
|
||||
*/
|
||||
export default function PaymentReceiveDetailFooter() {
|
||||
const { paymentReceive } = usePaymentReceiveDetailContext();
|
||||
|
||||
|
||||
return (
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<If condition={paymentReceive.statement}>
|
||||
<DetailItem label={<T id={'payment_receive.details.statement'} />}>
|
||||
<DetailItem
|
||||
label={<T id={'payment_receive.details.statement'} />}
|
||||
multiline
|
||||
>
|
||||
{paymentReceive.statement}
|
||||
</DetailItem>
|
||||
</If>
|
||||
|
||||
@@ -35,13 +35,13 @@ function PaymentReceiveDetailProvider({ paymentReceiveId, ...props }) {
|
||||
return (
|
||||
<DrawerLoading loading={isPaymentLoading}>
|
||||
<DrawerHeaderContent
|
||||
name={DRAWERS.PAYMENT_RECEIVE_DETAILS}
|
||||
title={intl.get('payment_receive.drawer.title', {
|
||||
name={DRAWERS.PAYMENT_RECEIVED_DETAILS}
|
||||
title={intl.get('payment_received.drawer.title', {
|
||||
number: paymentReceive.payment_receive_no,
|
||||
})}
|
||||
subTitle={
|
||||
featureCan(Features.Branches)
|
||||
? intl.get('payment_receive.drawer.subtitle', {
|
||||
? intl.get('payment_received.drawer.subtitle', {
|
||||
value: paymentReceive.branch?.name,
|
||||
})
|
||||
: null
|
||||
|
||||
@@ -5,14 +5,16 @@ import {
|
||||
DrawerBody,
|
||||
FormattedMessage as T,
|
||||
} from '@/components';
|
||||
|
||||
import QuickCustomerFormDrawer from './QuickCustomerFormDrawer';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
/**
|
||||
* Quick create/edit customer drawer.
|
||||
*/
|
||||
export default function QuickCreateCustomerDrawerContent({ displayName }) {
|
||||
export default function QuickCreateCustomerDrawerContent({
|
||||
displayName,
|
||||
autofillRef,
|
||||
}) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DrawerHeaderContent
|
||||
@@ -20,7 +22,10 @@ export default function QuickCreateCustomerDrawerContent({ displayName }) {
|
||||
title={<T id={'create_a_new_customer'} />}
|
||||
/>
|
||||
<DrawerBody>
|
||||
<QuickCustomerFormDrawer displayName={displayName} />
|
||||
<QuickCustomerFormDrawer
|
||||
displayName={displayName}
|
||||
autofillRef={autofillRef}
|
||||
/>
|
||||
</DrawerBody>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
@@ -14,6 +14,7 @@ import CustomerFormFormik, {
|
||||
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
import { useAddAutofillRef } from '@/hooks/state/autofill';
|
||||
|
||||
/**
|
||||
* Drawer customer form loading wrapper.
|
||||
@@ -28,9 +29,22 @@ function DrawerCustomerFormLoading({ children }) {
|
||||
/**
|
||||
* Quick customer form of the drawer.
|
||||
*/
|
||||
function QuickCustomerFormDrawer({ displayName, closeDrawer, customerId }) {
|
||||
function QuickCustomerFormDrawer({
|
||||
displayName,
|
||||
autofillRef,
|
||||
closeDrawer,
|
||||
customerId,
|
||||
}) {
|
||||
const addAutofillRef = useAddAutofillRef();
|
||||
|
||||
// Handle the form submit request success.
|
||||
const handleSubmitSuccess = () => {
|
||||
const handleSubmitSuccess = (values, formArgs, submitPayload, res) => {
|
||||
if (autofillRef) {
|
||||
addAutofillRef(autofillRef, {
|
||||
displayName: values.display_name,
|
||||
customerId: res.id,
|
||||
});
|
||||
}
|
||||
closeDrawer(DRAWERS.QUICK_CREATE_CUSTOMER);
|
||||
};
|
||||
// Handle the form cancel action.
|
||||
@@ -43,7 +57,7 @@ function QuickCustomerFormDrawer({ displayName, closeDrawer, customerId }) {
|
||||
<DrawerCustomerFormLoading>
|
||||
<CustomerFormCard>
|
||||
<CustomerFormFormik
|
||||
initialValues={{ display_name: displayName }}
|
||||
initialValues={{ first_name: displayName }}
|
||||
onSubmitSuccess={handleSubmitSuccess}
|
||||
onCancel={handleCancelForm}
|
||||
/>
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
import React from 'react';
|
||||
import { Drawer, DrawerSuspense } from '@/components';
|
||||
import withDrawers from '@/containers/Drawer/withDrawers';
|
||||
|
||||
import { compose } from '@/utils';
|
||||
|
||||
const QuickCreateCustomerDrawerContent = React.lazy(() =>
|
||||
import('./QuickCreateCustomerDrawerContent'),
|
||||
const QuickCreateCustomerDrawerContent = React.lazy(
|
||||
() => import('./QuickCreateCustomerDrawerContent'),
|
||||
);
|
||||
|
||||
/**
|
||||
@@ -17,7 +16,7 @@ function QuickCreateCustomerDrawer({
|
||||
|
||||
// #withDrawer
|
||||
isOpen,
|
||||
payload,
|
||||
payload: { autofillRef, displayName },
|
||||
}) {
|
||||
return (
|
||||
<Drawer
|
||||
@@ -27,7 +26,10 @@ function QuickCreateCustomerDrawer({
|
||||
size={'80%'}
|
||||
>
|
||||
<DrawerSuspense>
|
||||
<QuickCreateCustomerDrawerContent displayName={payload.displayName} />
|
||||
<QuickCreateCustomerDrawerContent
|
||||
displayName={displayName}
|
||||
autofillRef={autofillRef}
|
||||
/>
|
||||
</DrawerSuspense>
|
||||
</Drawer>
|
||||
);
|
||||
|
||||
@@ -16,6 +16,7 @@ import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import withDashboardActions from '@/containers/Dashboard/withDashboardActions';
|
||||
|
||||
import { useDrawerContext } from '@/components/Drawer/DrawerProvider';
|
||||
import { useAddAutofillRef } from '@/hooks/state/autofill';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
|
||||
/**
|
||||
@@ -36,17 +37,20 @@ function QuickVendorFormDrawer({
|
||||
closeDrawer,
|
||||
vendorId,
|
||||
addQuickActionEvent,
|
||||
autofillRef,
|
||||
}) {
|
||||
const { payload } = useDrawerContext();
|
||||
const addAutofillRef = useAddAutofillRef();
|
||||
|
||||
// Handle the form submit request success.
|
||||
const handleSubmitSuccess = (values, form, submitPayload, response) => {
|
||||
const handleSubmitSuccess = (values, form, submitPayload, res) => {
|
||||
if (!submitPayload.noRedirect) {
|
||||
closeDrawer(DRAWERS.QUICK_WRITE_VENDOR);
|
||||
}
|
||||
if (payload.quickActionEvent) {
|
||||
addQuickActionEvent(payload.quickActionEvent, {
|
||||
vendorId: response.data.id,
|
||||
if (autofillRef) {
|
||||
addAutofillRef(autofillRef, {
|
||||
displayName: values.display_name,
|
||||
vendorId: res.id,
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -60,7 +64,7 @@ function QuickVendorFormDrawer({
|
||||
<DrawerVendorFormLoading>
|
||||
<VendorFormCard>
|
||||
<VendorFormFormik
|
||||
initialValues={{ display_name: displayName }}
|
||||
initialValues={{ first_name: displayName }}
|
||||
onSubmitSuccess={handleSubmitSuccess}
|
||||
onCancel={handleCancelForm}
|
||||
/>
|
||||
|
||||
@@ -12,7 +12,7 @@ import { DRAWERS } from '@/constants/drawers';
|
||||
/**
|
||||
* Quick create/edit vendor drawer.
|
||||
*/
|
||||
export default function QuickWriteVendorDrawerContent({ displayName }) {
|
||||
export default function QuickWriteVendorDrawerContent({ displayName, autofillRef }) {
|
||||
return (
|
||||
<React.Fragment>
|
||||
<DrawerHeaderContent
|
||||
@@ -21,7 +21,7 @@ export default function QuickWriteVendorDrawerContent({ displayName }) {
|
||||
|
||||
/>
|
||||
<DrawerBody>
|
||||
<QuickVendorFormDrawer displayName={displayName} />
|
||||
<QuickVendorFormDrawer displayName={displayName} autofillRef={autofillRef} />
|
||||
</DrawerBody>
|
||||
</React.Fragment>
|
||||
);
|
||||
|
||||
@@ -17,7 +17,7 @@ function QuickWriteVendorDrawer({
|
||||
|
||||
// #withDrawer
|
||||
isOpen,
|
||||
payload,
|
||||
payload: { displayName, autofillRef },
|
||||
}) {
|
||||
return (
|
||||
<Drawer
|
||||
@@ -25,10 +25,9 @@ function QuickWriteVendorDrawer({
|
||||
name={name}
|
||||
style={{ minWidth: '700px', maxWidth: '900px' }}
|
||||
size={'80%'}
|
||||
payload={payload}
|
||||
>
|
||||
<DrawerSuspense>
|
||||
<QuickWriteVendorDrawerContent displayName={payload.displayName} />
|
||||
<QuickWriteVendorDrawerContent displayName={displayName} autofillRef={autofillRef} />
|
||||
</DrawerSuspense>
|
||||
</Drawer>
|
||||
);
|
||||
|
||||
@@ -21,12 +21,15 @@ export default function ReceiptDetailFooter() {
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'180px'}>
|
||||
<If condition={receipt.statement}>
|
||||
<DetailItem label={<T id={'receipt.details.statement'} />}>
|
||||
<DetailItem label={<T id={'receipt.details.statement'} />} multiline>
|
||||
{receipt.statement}
|
||||
</DetailItem>
|
||||
</If>
|
||||
<If condition={receipt.receipt_message}>
|
||||
<DetailItem label={<T id={'receipt.details.receipt_message'} />}>
|
||||
<DetailItem
|
||||
label={<T id={'receipt.details.receipt_message'} />}
|
||||
multiline
|
||||
>
|
||||
{receipt.receipt_message}
|
||||
</DetailItem>
|
||||
</If>
|
||||
|
||||
@@ -16,7 +16,11 @@ export function VendorCreditDetailFooter() {
|
||||
<CommercialDocFooter>
|
||||
<DetailsMenu direction={'horizantal'} minLabelSize={'150px'}>
|
||||
<If condition={vendorCredit.note}>
|
||||
<DetailItem label={<T id={'note'} />} children={vendorCredit.note} />
|
||||
<DetailItem
|
||||
label={<T id={'note'} />}
|
||||
children={vendorCredit.note}
|
||||
multiline
|
||||
/>
|
||||
</If>
|
||||
</DetailsMenu>
|
||||
</CommercialDocFooter>
|
||||
|
||||
@@ -71,7 +71,7 @@ function VendorDetailsActionsBar({
|
||||
};
|
||||
|
||||
const handleNewPaymentClick = () => {
|
||||
history.push('/payment-mades/new');
|
||||
history.push('/payments-made/new');
|
||||
closeDrawer(DRAWERS.VENDOR_DETAILS);
|
||||
};
|
||||
|
||||
|
||||
@@ -14,6 +14,8 @@ export function ExpenseFormFooterLeft() {
|
||||
<FEditableText
|
||||
name={'description'}
|
||||
placeholder={<T id={'expenses.decscrption.placeholder'} />}
|
||||
multiline
|
||||
fastField
|
||||
/>
|
||||
</DescriptionFormGroup>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -20,6 +20,7 @@ import withExpensesActions from './withExpensesActions';
|
||||
import withAlertsActions from '@/containers/Alert/withAlertActions';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withExpenses from './withExpenses';
|
||||
|
||||
import { ActionsMenu, useExpensesTableColumns } from './components';
|
||||
import { DRAWERS } from '@/constants/drawers';
|
||||
@@ -39,6 +40,9 @@ function ExpensesDataTable({
|
||||
|
||||
// #withSettings
|
||||
expensesTableSize,
|
||||
|
||||
// #withExpenses
|
||||
expensesTableState
|
||||
}) {
|
||||
// Expenses list context.
|
||||
const {
|
||||
@@ -116,6 +120,7 @@ function ExpensesDataTable({
|
||||
sticky={true}
|
||||
onFetchData={handleFetchData}
|
||||
pagination={true}
|
||||
initialPageSize={expensesTableState.pageSize}
|
||||
manualSortBy={true}
|
||||
manualPagination={true}
|
||||
pagesCount={pagination.pagesCount}
|
||||
@@ -147,4 +152,5 @@ export default compose(
|
||||
withSettings(({ expenseSettings }) => ({
|
||||
expensesTableSize: expenseSettings?.tableSize,
|
||||
})),
|
||||
withExpenses(({ expensesTableState }) => ({ expensesTableState }))
|
||||
)(ExpensesDataTable);
|
||||
|
||||
@@ -13,6 +13,8 @@ export function ImportDropzone() {
|
||||
<Field id={'file'} name={'file'} type="file">
|
||||
{({ form }) => (
|
||||
<ImportDropzoneField
|
||||
title={'Drag and drop files here or click to select files'}
|
||||
subtitle={''}
|
||||
value={form.file}
|
||||
onChange={(file) => {
|
||||
hideAlerts();
|
||||
|
||||
@@ -92,6 +92,7 @@ function InventoryAdjustmentDataTable({
|
||||
manualSortBy={true}
|
||||
selectionColumn={true}
|
||||
pagination={true}
|
||||
initialPageSize={inventoryAdjustmentTableState.pageSize}
|
||||
pagesCount={pagination.pagesCount}
|
||||
autoResetSortBy={false}
|
||||
autoResetPage={false}
|
||||
|
||||
@@ -17,6 +17,7 @@ import withAlertsActions from '@/containers/Alert/withAlertActions';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
import withItems from './withItems';
|
||||
|
||||
import { useItemsListContext } from './ItemsListProvider';
|
||||
import { useItemsTableColumns, ItemsActionMenuList } from './components';
|
||||
@@ -43,6 +44,9 @@ function ItemsDataTable({
|
||||
// #withSettings
|
||||
itemsTableSize,
|
||||
|
||||
// #withItems
|
||||
itemsTableState,
|
||||
|
||||
// #ownProps
|
||||
tableProps,
|
||||
}) {
|
||||
@@ -137,6 +141,7 @@ function ItemsDataTable({
|
||||
sticky={true}
|
||||
rowClassNames={rowClassNames}
|
||||
pagination={true}
|
||||
initialPageSize={itemsTableState.pageSize}
|
||||
manualSortBy={true}
|
||||
manualPagination={true}
|
||||
pagesCount={pagination.pagesCount}
|
||||
@@ -174,4 +179,5 @@ export default compose(
|
||||
withSettings(({ itemsSettings }) => ({
|
||||
itemsTableSize: itemsSettings.tableSize,
|
||||
})),
|
||||
withItems(({ itemsTableState }) => ({ itemsTableState }))
|
||||
)(ItemsDataTable);
|
||||
|
||||
@@ -15,6 +15,8 @@ export function BillFormFooterLeft() {
|
||||
<FEditableText
|
||||
name={'note'}
|
||||
placeholder={intl.get('bill_form.label.note.placeholder')}
|
||||
fastField
|
||||
multiline
|
||||
/>
|
||||
</TermsConditsFormGroup>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -130,6 +130,7 @@ function BillsDataTable({
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
pagination={true}
|
||||
initialPageSize={billsTableState.pageSize}
|
||||
pagesCount={pagination.pagesCount}
|
||||
TableLoadingRenderer={TableSkeletonRows}
|
||||
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
||||
|
||||
@@ -15,6 +15,8 @@ export function VendorCreditNoteFormFooterLeft() {
|
||||
<FEditableText
|
||||
name={'note'}
|
||||
placeholder={intl.get('vendor_credit_form.note.placeholder')}
|
||||
multiline
|
||||
fastField
|
||||
/>
|
||||
</TermsConditsFormGroup>
|
||||
</React.Fragment>
|
||||
|
||||
@@ -17,6 +17,7 @@ import withAlertsActions from '@/containers/Alert/withAlertActions';
|
||||
import withDrawerActions from '@/containers/Drawer/withDrawerActions';
|
||||
import withDialogActions from '@/containers/Dialog/withDialogActions';
|
||||
import withVendorsCreditNotesActions from './withVendorsCreditNotesActions';
|
||||
import withVendorsCreditNotes from './withVendorsCreditNotes';
|
||||
import withSettings from '@/containers/Settings/withSettings';
|
||||
|
||||
import { useVendorsCreditNoteTableColumns, ActionsMenu } from './components';
|
||||
@@ -32,6 +33,9 @@ function VendorsCreditNoteDataTable({
|
||||
// #withVendorsCreditNotesActions
|
||||
setVendorsCreditNoteTableState,
|
||||
|
||||
// #withVendorCredits
|
||||
vendorsCreditNoteTableState,
|
||||
|
||||
// #withAlertsActions
|
||||
openAlert,
|
||||
|
||||
@@ -129,6 +133,7 @@ function VendorsCreditNoteDataTable({
|
||||
noInitialFetch={true}
|
||||
sticky={true}
|
||||
pagination={true}
|
||||
initialPageSize={vendorsCreditNoteTableState.pageSize}
|
||||
pagesCount={pagination.pagesCount}
|
||||
TableLoadingRenderer={TableSkeletonRows}
|
||||
TableHeaderSkeletonRenderer={TableSkeletonHeader}
|
||||
@@ -159,4 +164,7 @@ export default compose(
|
||||
withSettings(({ vendorsCreditNoteSetting }) => ({
|
||||
creditNoteTableSize: vendorsCreditNoteSetting?.tableSize,
|
||||
})),
|
||||
withVendorsCreditNotes(({ vendorsCreditNoteTableState }) => ({
|
||||
vendorsCreditNoteTableState,
|
||||
})),
|
||||
)(VendorsCreditNoteDataTable);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user