feat: Optimize SMS notification module.

This commit is contained in:
a.bouhuolia
2021-11-09 09:51:38 +02:00
parent 6d67d6163d
commit 48221a7af1
24 changed files with 479 additions and 141 deletions

View File

@@ -1,28 +1,62 @@
import React from 'react';
import { Formik, Form } from 'formik';
import { Formik, Form, useFormikContext } from 'formik';
import styled from 'styled-components';
import { Classes } from '@blueprintjs/core';
import 'style/pages/NotifyConactViaSMS/NotifyConactViaSMSDialog.scss';
import { CreateNotifyViaSMSFormSchema } from './NotifyViaSMSForm.schema';
import NotifyViaSMSFormFields from './NotifyViaSMSFormFields';
import NotifyViaSMSFormFloatingActions from './NotifyViaSMSFormFloatingActions';
import { FormObserver, SMSMessagePreview } from 'components';
import { transformToForm, saveInvoke } from 'utils';
import { transformToForm, safeInvoke } from 'utils';
import { getSMSUnits } from './utils';
const defaultInitialValues = {
notification_key: '',
customer_name: '',
customer_phone_number: '',
sms_message: '',
};
/**
* Notify via sms - SMS message preview section.
*/
function SMSMessagePreviewSection() {
const {
values: { sms_message },
} = useFormikContext();
// Calculates the SMS units of message.
const messagesUnits = getSMSUnits(sms_message);
return (
<SMSPreviewSectionRoot>
<SMSMessagePreview message={sms_message} />
<SMSPreviewSectionNote>
<strong>Note</strong>: Note: One SMS unit can contain a maximum of 160
characters. <strong>{messagesUnits}</strong> SMS units will be used to
send this SMS notification.
</SMSPreviewSectionNote>
</SMSPreviewSectionRoot>
);
}
/**
* Notify Via SMS Form.
*/
function NotifyViaSMSForm({ onSubmit, NotificationDetail, NotificationName }) {
function NotifyViaSMSForm({
initialValues: initialValuesComponent,
onSubmit,
onCancel,
onValuesChange,
}) {
// Initial form values
const initialValues = {
...defaultInitialValues,
...transformToForm(NotificationDetail, defaultInitialValues),
...transformToForm(initialValuesComponent, defaultInitialValues),
};
return (
@@ -32,11 +66,56 @@ function NotifyViaSMSForm({ onSubmit, NotificationDetail, NotificationName }) {
onSubmit={onSubmit}
>
<Form>
<NotifyViaSMSFormFields />
<NotifyViaSMSFormFloatingActions dialogName={NotificationName} />
<div className={Classes.DIALOG_BODY}>
<NotifyContent>
<NotifyFieldsSection>
<NotifyViaSMSFormFields />
</NotifyFieldsSection>
<SMSMessagePreviewSection />
</NotifyContent>
</div>
<NotifyViaSMSFormFloatingActions onCancel={onCancel} />
<NotifyObserveValuesChange onChange={onValuesChange} />
</Form>
</Formik>
);
}
/**
* Observes the values change of notify form.
*/
function NotifyObserveValuesChange({ onChange }) {
const { values } = useFormikContext();
// Handle the form change observe.
const handleChange = () => {
safeInvoke(onChange, values);
};
return <FormObserver values={values} onChange={handleChange} />;
}
export default NotifyViaSMSForm;
const NotifyContent = styled.div`
display: flex;
`;
const NotifyFieldsSection = styled.div`
flex: 1;
width: 65%;
`;
const SMSPreviewSectionRoot = styled.div`
display: flex;
flex-direction: column;
width: 45%;
padding-left: 25px;
margin-left: 25px;
border-left: 1px solid #dcdcdd;
`;
const SMSPreviewSectionNote = styled.div`
font-size: 12px;
opacity: 0.7;
`;

View File

@@ -1,16 +1,47 @@
import React from 'react';
import { FastField, ErrorMessage } from 'formik';
import { FormattedMessage as T } from 'components';
import { Classes, FormGroup, TextArea, InputGroup } from '@blueprintjs/core';
import { FormGroup, InputGroup } from '@blueprintjs/core';
import classNames from 'classnames';
import {
ListSelect,
FieldRequiredHint,
FormattedMessage as T,
} from 'components';
import { CLASSES } from 'common/classes';
import { inputIntent } from 'utils';
import { FieldRequiredHint } from 'components';
function NotifyViaSMSFormFields() {
const notificationTypes = [
{ key: 'details', label: 'Invoice details' },
{ key: 'reminder', label: 'Invoice reminder' },
];
export default function NotifyViaSMSFormFields() {
return (
<div className={Classes.DIALOG_BODY}>
<div>
<FastField name={'notification_key'}>
{({ form, meta: { error, touched } }) => (
<FormGroup
label={'Notification type'}
className={classNames(CLASSES.FILL)}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'customer_name'} />}
>
<ListSelect
items={notificationTypes}
selectedItemProp={'key'}
selectedItem={'details'}
textProp={'label'}
popoverProps={{ minimal: true }}
filterable={false}
onItemSelect={(notification) => {
form.setFieldValue('notification_key', notification.key);
}}
/>
</FormGroup>
)}
</FastField>
{/* ----------- Send Notification to ----------- */}
<FastField name={'customer_name'}>
{({ form, field, meta: { error, touched } }) => (
@@ -51,29 +82,6 @@ function NotifyViaSMSFormFields() {
</FormGroup>
)}
</FastField>
{/* ----------- Message Text ----------- */}
<FastField name={'sms_message'}>
{({ field, meta: { error, touched } }) => (
<FormGroup
label={<T id={'notify_via_sms.dialog.message_text'} />}
labelInfo={<FieldRequiredHint />}
className={'form-group--sms_message'}
intent={inputIntent({ error, touched })}
helperText={<ErrorMessage name={'sms_message'} />}
>
<TextArea
growVertically={true}
large={true}
disabled={true}
intent={inputIntent({ error, touched })}
{...field}
/>
</FormGroup>
)}
</FastField>
</div>
);
}
export default NotifyViaSMSFormFields;

View File

@@ -1,41 +1,47 @@
import React from 'react';
import { useFormikContext } from 'formik';
import { Intent, Button, Classes } from '@blueprintjs/core';
import styled from 'styled-components';
import { FormattedMessage as T } from 'components';
import withDialogActions from 'containers/Dialog/withDialogActions';
import { compose } from 'utils';
import { safeCallback } from 'utils';
function NotifyViaSMSFormFloatingActions({
// #withDialogActions
closeDialog,
dialogName,
}) {
/**
*
*/
export default function NotifyViaSMSFormFloatingActions({ onCancel }) {
// Formik context.
const { isSubmitting } = useFormikContext();
// Handle close button click.
const handleCancelBtnClick = () => {
closeDialog(dialogName);
const handleCancelBtnClick = (event) => {
onCancel && onCancel(event);
};
return (
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button onClick={handleCancelBtnClick} style={{ minWidth: '75px' }}>
<T id={'cancel'} />
</Button>
<FooterActions className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button
intent={Intent.PRIMARY}
loading={isSubmitting}
style={{ minWidth: '75px' }}
style={{ minWidth: '110px' }}
type="submit"
>
{<T id={'send'} />}
Send SMS
</Button>
</div>
<Button
disabled={isSubmitting}
onClick={handleCancelBtnClick}
style={{ minWidth: '75px' }}
>
<T id={'cancel'} />
</Button>
</FooterActions>
</div>
);
}
export default compose(withDialogActions)(NotifyViaSMSFormFloatingActions);
const FooterActions = styled.div`
justify-content: flex-start;
`;

View File

@@ -10,3 +10,8 @@ export const transformErrors = (errors) => {
});
}
};
export const getSMSUnits = (message, threshold = 140) => {
return Math.ceil(message.length / threshold);
};