From d26ef01afccaabedfae00e373eb7b12d5e37bc9f Mon Sep 17 00:00:00 2001
From: elforjani13 <39470382+elforjani13@users.noreply.github.com>
Date: Sat, 6 Nov 2021 21:47:17 +0200
Subject: [PATCH] feat: notify by SMS.
---
src/components/MoreMenutItems.js | 36 +++++++++++++
src/components/MoreVertMenutItems.js | 46 ----------------
src/components/index.js | 6 +--
.../NotifyContactViaSMSContent.js | 8 ++-
.../NotifyContactViaSMSForm.js | 39 +++++++++++---
.../NotifyContactViaSMSForm.schema.js | 6 +--
.../NotifyContactViaSMSFormFields.js | 32 +++++++----
.../NotifyContactViaSMSFormProvider.js | 32 +++++++----
.../NotifyContactViaSMSDialog/index.js | 13 +++--
.../InvoiceDetailActionsBar.js | 16 +-----
.../Drawers/InvoiceDetailDrawer/utils.js | 4 +-
src/hooks/query/estimates.js | 35 ++++++++++++
src/hooks/query/invoices.js | 54 ++++++++++++++++---
src/hooks/query/paymentReceives.js | 31 +++++++++++
src/hooks/query/receipts.js | 31 ++++++++++-
src/hooks/query/settings.js | 15 ++++++
src/hooks/query/types.js | 9 ++++
17 files changed, 307 insertions(+), 106 deletions(-)
create mode 100644 src/components/MoreMenutItems.js
delete mode 100644 src/components/MoreVertMenutItems.js
diff --git a/src/components/MoreMenutItems.js b/src/components/MoreMenutItems.js
new file mode 100644
index 000000000..2201a7206
--- /dev/null
+++ b/src/components/MoreMenutItems.js
@@ -0,0 +1,36 @@
+import React from 'react';
+import {
+ Button,
+ Popover,
+ PopoverInteractionKind,
+ Position,
+ MenuItem,
+ Menu,
+} from '@blueprintjs/core';
+
+import { Icon, FormattedMessage as T } from 'components';
+
+function MoreMenuItems({ payload: { onNotifyViaSMS } }) {
+ return (
+
+ }
+ />
+
+ }
+ interactionKind={PopoverInteractionKind.CLICK}
+ position={Position.BOTTOM_LEFT}
+ modifiers={{
+ offset: { offset: '0, 4' },
+ }}
+ >
+ } minimal={true} />
+
+ );
+}
+
+export default MoreMenuItems;
diff --git a/src/components/MoreVertMenutItems.js b/src/components/MoreVertMenutItems.js
deleted file mode 100644
index 9282f33c1..000000000
--- a/src/components/MoreVertMenutItems.js
+++ /dev/null
@@ -1,46 +0,0 @@
-import React from 'react';
-import {
- Button,
- PopoverInteractionKind,
- MenuItem,
- Position,
-} from '@blueprintjs/core';
-
-import { Select } from '@blueprintjs/select';
-import { Icon } from 'components';
-
-function MoreVertMenutItems({ text, items, onItemSelect, buttonProps }) {
- // Menu items renderer.
- const itemsRenderer = (item, { handleClick, modifiers, query }) => (
-
- );
- const handleMenuSelect = (type) => {
- onItemSelect && onItemSelect(type);
- };
-
- return (
-
- );
-}
-
-export default MoreVertMenutItems;
diff --git a/src/components/index.js b/src/components/index.js
index aa156307e..8d38aefcf 100644
--- a/src/components/index.js
+++ b/src/components/index.js
@@ -61,7 +61,7 @@ import Card from './Card';
import AvaterCell from './AvaterCell';
import { ItemsMultiSelect } from './Items';
-import MoreVertMenutItems from './MoreVertMenutItems';
+import MoreMenuItems from './MoreMenutItems';
export * from './Menu';
export * from './AdvancedFilter/AdvancedFilterDropdown';
@@ -83,7 +83,7 @@ export * from './MultiSelectTaggable';
export * from './Utils/FormatNumber';
export * from './Utils/FormatDate';
export * from './BankAccounts';
-export * from './IntersectionObserver'
+export * from './IntersectionObserver';
export * from './Datatable/CellForceWidth';
export * from './Button';
export * from './IntersectionObserver';
@@ -158,5 +158,5 @@ export {
ItemsMultiSelect,
Card,
AvaterCell,
- MoreVertMenutItems,
+ MoreMenuItems
};
diff --git a/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSContent.js b/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSContent.js
index 59f725294..669cb9527 100644
--- a/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSContent.js
+++ b/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSContent.js
@@ -1,6 +1,6 @@
import React from 'react';
-import '../../../style/pages/NotifyConactViaSMS/NotifyConactViaSMSDialog.scss';
+import 'style/pages/NotifyConactViaSMS/NotifyConactViaSMSDialog.scss';
import { NotifyContactViaSMSFormProvider } from './NotifyContactViaSMSFormProvider';
import NotifyContactViaSMSForm from './NotifyContactViaSMSForm';
@@ -10,9 +10,13 @@ import NotifyContactViaSMSForm from './NotifyContactViaSMSForm';
export default function NotifyContactViaSMSContent({
// #ownProps
dialogName,
+ invoice,
}) {
return (
-
+
);
diff --git a/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSForm.js b/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSForm.js
index 56b49508f..c411563c1 100644
--- a/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSForm.js
+++ b/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSForm.js
@@ -13,27 +13,54 @@ import withDialogActions from 'containers/Dialog/withDialogActions';
import { useNotifyContactViaSMSContext } from './NotifyContactViaSMSFormProvider';
-import { compose } from 'utils';
+import { transformToForm, compose } from 'utils';
const defaultInitialValues = {
- name: '',
- phone: '',
- note: '',
+ customer_name: '',
+ customer_personal_phone: '',
+ sms_message: '',
};
function NotifyContactViaSMSForm({
// #withDialogActions
closeDialog,
}) {
- const { dialogName } = useNotifyContactViaSMSContext();
+ const {
+ invoiceId,
+ invoiceSMSDetail,
+ dialogName,
+ createNotifyInvoiceBySMSMutate,
+ } = useNotifyContactViaSMSContext();
// Initial form values
const initialValues = {
...defaultInitialValues,
+ ...transformToForm(invoiceSMSDetail, defaultInitialValues),
};
// Handles the form submit.
- const handleFormSubmit = (values, { setSubmitting, setErrors }) => {};
+ const handleFormSubmit = (values, { setSubmitting, setErrors }) => {
+ // Handle request response success.
+ const onSuccess = (response) => {
+ AppToaster.show({
+ message: intl.get('notify_via_sms.dialog.success_message'),
+ intent: Intent.SUCCESS,
+ });
+ closeDialog(dialogName);
+ };
+
+ // Handle request response errors.
+ const onError = ({
+ response: {
+ data: { errors },
+ },
+ }) => {
+ setSubmitting(false);
+ };
+ createNotifyInvoiceBySMSMutate([invoiceId, values])
+ .then(onSuccess)
+ .catch(onError);
+ };
return (
{/* ----------- Send Notification to ----------- */}
-
+
{({ form, field, meta: { error, touched } }) => (
}
className={classNames('form-group--customer-name', CLASSES.FILL)}
labelInfo={}
intent={inputIntent({ error, touched })}
- helperText={}
+ helperText={}
>
-
+
)}
{/* ----------- Phone number ----------- */}
-
+
{({ form, field, meta: { error, touched } }) => (
}
labelInfo={}
intent={inputIntent({ error, touched })}
- helperText={}
- className={classNames('form-group--phone', CLASSES.FILL)}
+ helperText={}
+ className={classNames(
+ 'form-group--customer_personal_phone',
+ CLASSES.FILL,
+ )}
>
-
+
)}
{/* ----------- Message Text ----------- */}
-
+
{({ field, meta: { error, touched } }) => (
}
labelInfo={}
- className={'form-group--note'}
+ className={'form-group--sms_message'}
intent={inputIntent({ error, touched })}
- helperText={}
+ helperText={}
>
diff --git a/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSFormProvider.js b/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSFormProvider.js
index 4cdfa1d2e..962ac8921 100644
--- a/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSFormProvider.js
+++ b/src/containers/Dialogs/NotifyContactViaSMSDialog/NotifyContactViaSMSFormProvider.js
@@ -1,27 +1,41 @@
import React from 'react';
import { DialogContent } from 'components';
-import { useCustomers } from 'hooks/query';
+import {
+ useInvoice,
+ useCreateNotifyInvoiceBySMS,
+ useInvocieSMSDetails,
+} from 'hooks/query';
const NotifyContactViaSMSContext = React.createContext();
/**
* Notify contact via SMS provider.
*/
-function NotifyContactViaSMSFormProvider({ dialogName, ...props }) {
- // Fetches customers list.
- const {
- data: { customers },
- isLoading: isCustomersLoading,
- } = useCustomers();
+function NotifyContactViaSMSFormProvider({ invoiceId, dialogName, ...props }) {
+ // Handle fetch invoice data.
+ const { data: invoice, isLoading: isInvoiceLoading } = useInvoice(invoiceId, {
+ enabled: !!invoiceId,
+ });
+
+ const { data: invoiceSMSDetail, isLoading: isInvoiceSMSDetailLoading } =
+ useInvocieSMSDetails(invoiceId, {
+ enabled: !!invoiceId,
+ });
+
+ // Create notfiy invoice by sms mutations.
+ const { mutateAsync: createNotifyInvoiceBySMSMutate } =
+ useCreateNotifyInvoiceBySMS();
// State provider.
const provider = {
+ invoiceId,
+ invoiceSMSDetail,
dialogName,
- customers,
+ createNotifyInvoiceBySMSMutate,
};
return (
-
+
);
diff --git a/src/containers/Dialogs/NotifyContactViaSMSDialog/index.js b/src/containers/Dialogs/NotifyContactViaSMSDialog/index.js
index 2c99a0985..64240e927 100644
--- a/src/containers/Dialogs/NotifyContactViaSMSDialog/index.js
+++ b/src/containers/Dialogs/NotifyContactViaSMSDialog/index.js
@@ -12,18 +12,25 @@ const NotifyContactViaSMSDialogContent = React.lazy(() =>
/**
* Notify contact via SMS.
*/
-function NotifyContactViaSMSDialog({ dialogName, payload, isOpen }) {
+function NotifyContactViaSMSDialog({
+ dialogName,
+ payload: { invoiceId },
+ isOpen,
+}) {
return (
}
isOpen={isOpen}
canEscapeJeyClose={true}
autoFocus={true}
className={'dialog--notify-vis-sms'}
>
-
+
);
diff --git a/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailActionsBar.js b/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailActionsBar.js
index 5b5a7dd87..1aeba690e 100644
--- a/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailActionsBar.js
+++ b/src/containers/Drawers/InvoiceDetailDrawer/InvoiceDetailActionsBar.js
@@ -6,28 +6,17 @@ import {
NavbarGroup,
Classes,
NavbarDivider,
- Popover,
- PopoverInteractionKind,
- Position,
Intent,
- MenuItem,
- Menu,
} from '@blueprintjs/core';
import DashboardActionsBar from 'components/Dashboard/DashboardActionsBar';
import { useInvoiceDetailDrawerContext } from './InvoiceDetailDrawerProvider';
-import { moreVertOptions } from '../../../common/moreVertOptions';
import withDialogActions from 'containers/Dialog/withDialogActions';
import withAlertsActions from 'containers/Alert/withAlertActions';
import withDrawerActions from 'containers/Drawer/withDrawerActions';
-import {
- If,
- Icon,
- FormattedMessage as T,
- // MoreVertMenutItems,
-} from 'components';
+import { If, Icon, FormattedMessage as T } from 'components';
import { compose } from 'utils';
@@ -78,7 +67,7 @@ function InvoiceDetailActionsBar({
};
// Handle notify via SMS.
const handleNotifyViaSMS = () => {
- openDialog('notify-via-sms', {});
+ openDialog('notify-via-sms', { invoiceId });
};
// Handle cancele write-off invoice.
@@ -120,7 +109,6 @@ function InvoiceDetailActionsBar({
/>
);
export const BadDebtMenuItem = ({
- invoice,
payload: { onCancelBadDebt, onBadDebt, onNotifyViaSMS },
}) => {
+ const { invoice } = useInvoiceDetailDrawerContext();
+
return (
apiRequest.post(`sales/estimates/${id}/notify-by-sms`),
+ {
+ onSuccess: (res, id) => {
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+
+ // Invalidate sale estimate.
+ queryClient.invalidateQueries([t.NOTIFY_SALE_ESTIMATE_BY_SMS, id]);
+ },
+ ...props,
+ },
+ );
+}
+
+export function useEstimateSMS(estimateId, props, requestProps) {
+ return useRequestQuery(
+ [t.SALE_ESTIMATE_SMS, estimateId],
+ {
+ method: 'get',
+ url: `sales/estimates/${estimateId}/sms-details`,
+ ...requestProps,
+ },
+ {
+ select: (res) => res.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/invoices.js b/src/hooks/query/invoices.js
index 67debc80c..9948d6064 100644
--- a/src/hooks/query/invoices.js
+++ b/src/hooks/query/invoices.js
@@ -219,14 +219,52 @@ export function useCancelBadDebt(props) {
const queryClient = useQueryClient();
const apiRequest = useApiRequest();
- return useMutation((id) => apiRequest.post(`sales/invoices/${id}/writeoff/cancel`), {
- onSuccess: (res, id) => {
- // Invalidate
- queryClient.invalidateQueries([t.CANCEL_BAD_DEBT, id]);
+ return useMutation(
+ (id) => apiRequest.post(`sales/invoices/${id}/writeoff/cancel`),
+ {
+ onSuccess: (res, id) => {
+ // Invalidate
+ queryClient.invalidateQueries([t.CANCEL_BAD_DEBT, id]);
- // Common invalidate queries.
- commonInvalidateQueries(queryClient);
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
},
- ...props,
- });
+ );
+}
+
+export function useCreateNotifyInvoiceBySMS(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (id) => apiRequest.post(`sales/invoices/${id}/notify-by-sms`),
+ {
+ onSuccess: (res, id) => {
+ // Invalidate
+ queryClient.invalidateQueries([t.NOTIFY_SALE_INVOICE_BY_SMS, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+export function useInvocieSMSDetails(invoiceId, props, requestProps) {
+ return useRequestQuery(
+ [t.SALE_INVOICE_SMS, invoiceId],
+ {
+ method: 'get',
+ url: `sales/invoices/${invoiceId}/sms-details`,
+ ...requestProps,
+ },
+ {
+ select: (res) => res.data.data,
+ defaultData: {},
+ ...props,
+ },
+ );
}
diff --git a/src/hooks/query/paymentReceives.js b/src/hooks/query/paymentReceives.js
index 6f8a0f28a..ea6ba6274 100644
--- a/src/hooks/query/paymentReceives.js
+++ b/src/hooks/query/paymentReceives.js
@@ -174,3 +174,34 @@ export function useRefreshPaymentReceive() {
},
};
}
+
+export function useCreateNotifyPaymentReceiveBySMS(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+
+ return useMutation(
+ (id) => apiRequest.post(`sales/payment_receives/${id}/notify-by-sms`),
+ {
+ onSuccess: (res, id) => {
+ // Invalidate
+ queryClient.invalidateQueries([t.NOTIFY_PAYMENT_RECEIVE_BY_SMS, id]);
+
+ // Common invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+export function usePaymentReceiveSMS(id, props, requestProps) {
+ return useRequestQuery(
+ [t.PAYMENT_RECEIVE_SMS, id],
+ { method: 'get', url: `sales/payment_receives/${id}/sms-details`, ...requestProps },
+ {
+ select: (res) => res.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/receipts.js b/src/hooks/query/receipts.js
index ebefb6c26..6db29e4c3 100644
--- a/src/hooks/query/receipts.js
+++ b/src/hooks/query/receipts.js
@@ -23,7 +23,7 @@ const commonInvalidateQueries = (queryClient) => {
// Invalidate the cashflow transactions.
queryClient.invalidateQueries(t.CASH_FLOW_TRANSACTIONS);
queryClient.invalidateQueries(t.CASHFLOW_ACCOUNT_TRANSACTIONS_INFINITY);
-
+
// Invalidate the settings.
queryClient.invalidateQueries([t.SETTING, t.SETTING_RECEIPTS]);
};
@@ -163,3 +163,32 @@ export function useRefreshReceipts() {
},
};
}
+
+export function useCreateNotifyReceiptBySMS(props) {
+ const queryClient = useQueryClient();
+ const apiRequest = useApiRequest();
+ return useMutation(
+ (id) => apiRequest.post(`sales/receipts/${id}/notify-by-sms`),
+ {
+ onSuccess: (res, id) => {
+ queryClient.invalidateQueries([t.NOTIFY_SALE_RECEIPT_BY_SMS, id]);
+
+ // Invalidate queries.
+ commonInvalidateQueries(queryClient);
+ },
+ ...props,
+ },
+ );
+}
+
+export function useReceiptSMS(receiptId, props, requestProps) {
+ return useRequestQuery(
+ [t.SALE_RECEIPT_SMS, receiptId],
+ { method: 'get', url: `sales/receipts/${receiptId}/sms-details`, ...requestProps },
+ {
+ select: (res) => res.data,
+ defaultData: {},
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/settings.js b/src/hooks/query/settings.js
index 22e25c72b..7aebe4bf1 100644
--- a/src/hooks/query/settings.js
+++ b/src/hooks/query/settings.js
@@ -123,3 +123,18 @@ export function useSettingCashFlow(props) {
props,
);
}
+
+/**
+ * Retrieve SMS settings.
+ */
+export function useSettingSMSNotifications(props) {
+ return useRequestQuery(
+ [t.SETTING_SMS_NOTIFICATIONS],
+ { method: 'get', url: `settings/sms-notifications` },
+ {
+ select: (res) => res.data.notifications,
+ defaultData: [],
+ ...props,
+ },
+ );
+}
diff --git a/src/hooks/query/types.js b/src/hooks/query/types.js
index 54952a47c..ff9bbe20a 100644
--- a/src/hooks/query/types.js
+++ b/src/hooks/query/types.js
@@ -51,11 +51,15 @@ const ITEMS = {
const SALE_ESTIMATES = {
SALE_ESTIMATES: 'SALE_ESTIMATES',
SALE_ESTIMATE: 'SALE_ESTIMATE',
+ SALE_ESTIMATE_SMS: 'SALE_ESTIMATE_SMS',
+ NOTIFY_SALE_ESTIMATE_BY_SMS: 'NOTIFY_SALE_ESTIMATE_BY_SMS',
};
const SALE_RECEIPTS = {
SALE_RECEIPTS: 'SALE_RECEIPTS',
SALE_RECEIPT: 'SALE_RECEIPT',
+ SALE_RECEIPT_SMS: 'SALE_RECEIPT_SMS',
+ NOTIFY_SALE_RECEIPT_BY_SMS: 'NOTIFY_SALE_RECEIPT_BY_SMS',
};
const INVENTORY_ADJUSTMENTS = {
@@ -79,12 +83,16 @@ const PAYMENT_RECEIVES = {
PAYMENT_RECEIVE: 'PAYMENT_RECEIVE',
PAYMENT_RECEIVE_NEW_ENTRIES: 'PAYMENT_RECEIVE_NEW_ENTRIES',
PAYMENT_RECEIVE_EDIT_PAGE: 'PAYMENT_RECEIVE_EDIT_PAGE',
+ PAYMENT_RECEIVE_SMS: 'PAYMENT_RECEIVE_SMS',
+ NOTIFY_PAYMENT_RECEIVE_BY_SMS: 'NOTIFY_PAYMENT_RECEIVE_BY_SMS',
};
const SALE_INVOICES = {
SALE_INVOICES: 'SALE_INVOICES',
SALE_INVOICE: 'SALE_INVOICE',
SALE_INVOICES_DUE: 'SALE_INVOICES_DUE',
+ SALE_INVOICE_SMS: 'SALE_INVOICE_SMS',
+ NOTIFY_SALE_INVOICE_BY_SMS: 'NOTIFY_SALE_INVOICE_BY_SMS',
BAD_DEBT: 'BAD_DEBT',
CANCEL_BAD_DEBT: 'CANCEL_BAD_DEBT',
};
@@ -103,6 +111,7 @@ const SETTING = {
SETTING_MANUAL_JOURNALS: 'SETTING_MANUAL_JOURNALS',
SETTING_ITEMS: 'SETTING_ITEMS',
SETTING_CASHFLOW: 'SETTING_CASHFLOW',
+ SETTING_SMS_NOTIFICATIONS: 'SETTING_SMS_NOTIFICATIONS',
};
const ORGANIZATIONS = {