feat: add SMS message template.

This commit is contained in:
elforjani13
2021-11-04 16:55:37 +02:00
parent 46f6380fe6
commit 17a4744e58
14 changed files with 378 additions and 16 deletions

View File

@@ -0,0 +1,43 @@
import React from 'react';
import classNames from 'classnames';
import { get } from 'lodash';
import { Classes, Switch, FormGroup, Intent } from '@blueprintjs/core';
const SwitchEditableCell = ({
row: { index, original },
column: { id, switchProps },
cell: { value: initialValue },
payload,
}) => {
const [value, setValue] = React.useState(initialValue);
const onChange = (e) => {
const newValue = e.target.checked;
setValue(newValue);
payload.updateData(index, id, newValue);
};
React.useEffect(() => {
setValue(initialValue);
}, [initialValue]);
const error = payload.errors?.[index]?.[id];
return (
<FormGroup
intent={error ? Intent.DANGER : null}
className={classNames(Classes.FILL)}
>
<Switch
value={value}
onChange={onChange}
checked={initialValue}
minimal={true}
className="ml2"
{...switchProps}
/>
</FormGroup>
);
};
export default SwitchEditableCell;

View File

@@ -0,0 +1,42 @@
import React, { useState, useEffect } from 'react';
import classNames from 'classnames';
import { Classes, TextArea, FormGroup, Intent } from '@blueprintjs/core';
const TextAreaEditableCell = ({
row: { index },
column: { id },
cell: { value: initialValue },
payload,
}) => {
const [value, setValue] = useState(initialValue);
const onChange = (e) => {
setValue(e.target.value);
};
const onBlur = () => {
payload.updateData(index, id, value);
};
useEffect(() => {
setValue(initialValue);
}, [initialValue]);
const error = payload.errors?.[index]?.[id];
return (
<FormGroup
intent={error ? Intent.DANGER : null}
className={classNames(Classes.FILL)}
>
<TextArea
growVertically={true}
large={true}
value={value}
onChange={onChange}
onBlur={onBlur}
fill={true}
/>
</FormGroup>
);
};
export default TextAreaEditableCell;

View File

@@ -6,7 +6,9 @@ import ItemsListCell from './ItemsListCell';
import PercentFieldCell from './PercentFieldCell';
import { DivFieldCell, EmptyDiv } from './DivFieldCell';
import NumericInputCell from './NumericInputCell';
import CheckBoxFieldCell from './CheckBoxFieldCell'
import CheckBoxFieldCell from './CheckBoxFieldCell';
import SwitchFieldCell from './SwitchFieldCell';
import TextAreaCell from './TextAreaCell';
export {
AccountsListFieldCell,
@@ -18,5 +20,7 @@ export {
DivFieldCell,
EmptyDiv,
NumericInputCell,
CheckBoxFieldCell
CheckBoxFieldCell,
SwitchFieldCell,
TextAreaCell,
};

View File

@@ -1,29 +1,34 @@
import React from 'react'
import { FormattedMessage as T } from 'components';
import React from 'react';
import { FormattedMessage as T } from 'components';
export default [
{
text: <T id={'general'}/>,
text: <T id={'general'} />,
disabled: false,
href: '/preferences/general',
},
{
text: <T id={'users'}/>,
text: <T id={'users'} />,
href: '/preferences/users',
},
{
text: <T id={'currencies'}/>,
text: <T id={'currencies'} />,
href: '/preferences/currencies',
},
{
text: <T id={'accountant'}/>,
text: <T id={'accountant'} />,
disabled: false,
href: '/preferences/accountant',
},
{
text: <T id={'items'}/>,
text: <T id={'items'} />,
disabled: false,
href: '/preferences/items',
},
{
text: <T id={'sms_message'} />,
disabled: false,
href: '/preferences/sms-message',
},
];

View File

@@ -0,0 +1,28 @@
import React from 'react';
import { useFormikContext } from 'formik';
import { Intent, Button, Classes } from '@blueprintjs/core';
import { FormattedMessage as T } from 'components';
import { useHistory } from 'react-router-dom';
function SMSMessageTemplateFloatingAction() {
const history = useHistory();
const { isSubmitting } = useFormikContext();
const handleCloseClick = () => {
history.go(-1);
};
return (
<div className={'card__footer'}>
<Button intent={Intent.PRIMARY} loading={isSubmitting} type="submit">
<T id={'save'} />
</Button>
<Button onClick={handleCloseClick} disabled={isSubmitting}>
<T id={'close'} />
</Button>
</div>
);
}
export default SMSMessageTemplateFloatingAction;

View File

@@ -0,0 +1,46 @@
import React from 'react';
import { Formik, Form } from 'formik';
import { Intent } from '@blueprintjs/core';
import intl from 'react-intl-universal';
import classNames from 'classnames';
import { useHistory } from 'react-router-dom';
import { CLASSES } from 'common/classes';
import { CreateSMSMessageTemplateSchema } from './SMSMessageTemplateForm.schema';
import SMSMessageTemplateFormContent from './SMSMessageTemplateFormContent';
export const defaultInitialValues = {
entries: [
{
notification: '',
service: '',
message: '',
auto: true,
switch: true,
},
],
};
export default function SMSMessageTemplateForm({}) {
// Form initial values.
const initialValues = {
...defaultInitialValues,
};
// Handles form submit.
const handleSubmit = (values, { setSubmitting, setErrors, resetForm }) => {};
return (
<div
className={classNames(CLASSES.PAGE_FORM, CLASSES.PAGE_FORM_STRIP_STYLE)}
>
<Formik
validationSchema={CreateSMSMessageTemplateSchema}
initialValues={initialValues}
onSubmit={handleSubmit}
component={SMSMessageTemplateFormContent}
/>
</div>
);
}

View File

@@ -0,0 +1,19 @@
import * as Yup from 'yup';
import intl from 'react-intl-universal';
import { DATATYPES_LENGTH } from 'common/dataTypes';
import { isBlank } from 'utils';
const Schema = Yup.object().shape({
entries: Yup.array().of(
Yup.object().shape({
notification: Yup.string().nullable(),
service: Yup.number().nullable(),
message: Yup.string().max(DATATYPES_LENGTH.TEXT).nullable(),
auto:Yup.boolean(),
switch:Yup.boolean(),
}),
),
})
export const CreateSMSMessageTemplateSchema = Schema;

View File

@@ -0,0 +1,23 @@
import React from 'react';
import { FastField } from 'formik';
import SMSMessageTemplatesEntriesTable from './SMSMessageTemplatesEntriesTable';
export default function SMSMessageTemplateFormBody() {
return (
<FastField name={'entries'}>
{({
form: { values, setFieldValue },
field: { value },
meta: { error, touched },
}) => (
<SMSMessageTemplatesEntriesTable
entries={value}
onUpdateData={(newEntries) => {
setFieldValue('entries', newEntries);
}}
/>
)}
</FastField>
);
}

View File

@@ -0,0 +1,16 @@
import React from 'react';
import { Form } from 'formik';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import SMSMessageTemplateFormBody from './SMSMessageTemplateFormBody';
import SMSMessageTemplateFloatingAction from './SMSMessageTemplateFloatingAction';
export default function SMSMessageTemplateFormContent() {
return (
<Form>
<SMSMessageTemplateFormBody />
<SMSMessageTemplateFloatingAction />
</Form>
);
}

View File

@@ -0,0 +1,42 @@
import React from 'react';
import classNames from 'classnames';
import { CLASSES } from 'common/classes';
import { useSettings, useSaveSettings } from 'hooks/query';
import PreferencesPageLoader from '../PreferencesPageLoader';
const SMSMessageTemplateContext = React.createContext();
/**
* SMS message template provider.
*/
function SMSMessageTemplateProvider({ ...props }) {
//Fetches Organization Settings.
const { isLoading: isSettingsLoading } = useSettings();
// Provider state.
const provider = {};
return (
<div
className={classNames(
CLASSES.PREFERENCES_PAGE_INSIDE_CONTENT,
CLASSES.PREFERENCES_PAGE_INSIDE_CONTENT_ACCOUNTANT,
)}
>
<div className={classNames(CLASSES.CARD)}>
{isSettingsLoading ? (
<PreferencesPageLoader />
) : (
<SMSMessageTemplateContext.Provider value={provider} {...props} />
)}
</div>
</div>
);
}
const useSMSMessageTemplateContext = () =>
React.useContext(SMSMessageTemplateContext);
export { SMSMessageTemplateProvider, useSMSMessageTemplateContext };

View File

@@ -0,0 +1,68 @@
import React from 'react';
import intl from 'react-intl-universal';
import {
InputGroupCell,
TextAreaCell,
SwitchFieldCell,
} from 'components/DataTableCells';
import { DataTableEditable } from 'components';
import { compose, updateTableCell } from 'utils';
export default function SMSMessageTemplatesEntriesTable({
onUpdateData,
entries,
}) {
const columns = React.useMemo(() => [
{
Header: intl.get('sms_message_template.label_Notification'),
accessor: 'notification',
Cell: InputGroupCell,
disableSortBy: true,
width: '150',
},
{
Header: intl.get('service'),
accessor: 'service',
Cell: InputGroupCell,
disableSortBy: true,
width: '150',
},
{
Header: intl.get('sms_message_template.label_mesage'),
accessor: 'message',
// Cell: TextAreaCell,
Cell: InputGroupCell,
disableSortBy: true,
width: '150',
},
{
Header: intl.get('sms_message_template.label_auto'),
accessor: 'auto',
Cell: SwitchFieldCell,
disableSortBy: true,
disableResizing: true,
width: '120',
},
]);
const handleUpdateData = React.useCallback(
(rowIndex, columnId, value) => {
const newRows = compose(updateTableCell(rowIndex, columnId, value))(
entries,
);
onUpdateData(newRows);
},
[onUpdateData, entries],
);
return (
<DataTableEditable
columns={columns}
data={entries}
payload={{
errors: [],
updateData: handleUpdateData,
}}
/>
);
}

View File

@@ -0,0 +1,14 @@
import React from 'react';
import { SMSMessageTemplateProvider } from './SMSMessageTemplateProvider';
import SMSMessageTemplateForm from './SMSMessageTemplateForm';
/**
* SMS message template.
*/
export default function SMSMessageTemplates() {
return (
<SMSMessageTemplateProvider>
<SMSMessageTemplateForm />
</SMSMessageTemplateProvider>
);
}

View File

@@ -1407,7 +1407,6 @@
"cash_flow_money_out": "Money Out",
"cash_flow_transaction.switch_item": "Transactions {value}",
"cash_flow_transaction.balance_in_bigcapital": "Balance in Bigcapital",
"AR_aging_summary.filter_customers.all_customers": "All customers",
"AR_aging_summary.filter_customers.all_customers.hint": "All customers, include that ones have zero-balance.",
"AR_aging_summary.filter_customers.without_zero_balance": "Customers without zero balance",
@@ -1425,8 +1424,15 @@
"bad_debt.dialog.bad_debt": "Bad debt",
"bad_debt.dialog.cancel_bad_debt": "Cancel bad debt",
"bad_debt.dialog.header_note": "The seller can charge the amount of an invoice to the bad debt expense account when it is certain that the invoice will not be paid.",
"bad_debt.dialog.success_message":"The given sale invoice has been writte-off successfully.",
"bad_debt.cancel_alert.success_message":"The given sale invoice has been canceled write-off successfully.",
"bad_debt.cancel_alert.message": "Are you sure you want to write off this invoice?"
}
"bad_debt.dialog.success_message": "The given sale invoice has been writte-off successfully.",
"bad_debt.cancel_alert.success_message": "The given sale invoice has been canceled write-off successfully.",
"bad_debt.cancel_alert.message": "Are you sure you want to write off this invoice?",
"notify_via_sms.dialog.send_notification_to":"Send notification to",
"notify_via_sms.dialog.message_text":"Message Text",
"notify_via_sms.dialog.notify_via_sms":"Notify vis SMS",
"send": "Send",
"sms_message_template.label_mesage":"Message",
"sms_message_template.label_Notification":"Notification",
"sms_message_template.label_auto":"Auto",
"sms_message":"SMS message"
}

View File

@@ -4,6 +4,7 @@ import Accountant from 'containers/Preferences/Accountant/Accountant';
// import Accounts from 'containers/Preferences/Accounts/Accounts';
import Currencies from 'containers/Preferences/Currencies/Currencies';
import Item from 'containers/Preferences/Item';
import SMSMessageTemplates from '../containers/Preferences/SMSMessageTemplates';
import DefaultRoute from '../containers/Preferences/DefaultRoute';
const BASE_URL = '/preferences';
@@ -34,6 +35,11 @@ export default [
component: Item,
exact: true,
},
{
path: `${BASE_URL}/sms-message`,
component: SMSMessageTemplates,
exact: true,
},
{
path: `${BASE_URL}/`,
component: DefaultRoute,