fix: auto-increment journal number.

WIP: customer form.
This commit is contained in:
Ahmed Bouhuolia
2020-11-08 16:24:13 +02:00
parent 08f1a8136b
commit 1bc719dea7
16 changed files with 451 additions and 378 deletions

View File

@@ -87,7 +87,7 @@ function Row ({
cols = propValue; cols = propValue;
} }
const infix = brkPoint !== 'xs' ? `-${brkPoint}` : ''; const infix = `-${brkPoint}`;
if (cols != null) classes.push(`${sizePrefix}${infix}-${cols}`); if (cols != null) classes.push(`${sizePrefix}${infix}-${cols}`);
}); });

View File

@@ -29,6 +29,7 @@ import withMediaActions from 'containers/Media/withMediaActions';
import useMedia from 'hooks/useMedia'; import useMedia from 'hooks/useMedia';
import { compose, repeatValue, orderingLinesIndexes } from 'utils'; import { compose, repeatValue, orderingLinesIndexes } from 'utils';
import withManualJournalsActions from './withManualJournalsActions'; import withManualJournalsActions from './withManualJournalsActions';
import withManualJournals from './withManualJournals';
const ERROR = { const ERROR = {
JOURNAL_NUMBER_ALREADY_EXISTS: 'JOURNAL.NUMBER.ALREADY.EXISTS', JOURNAL_NUMBER_ALREADY_EXISTS: 'JOURNAL.NUMBER.ALREADY.EXISTS',
@@ -52,6 +53,9 @@ function MakeJournalEntriesForm({
requestMakeJournalEntries, requestMakeJournalEntries,
requestEditManualJournal, requestEditManualJournal,
// #withManualJournals
journalNumberChanged,
// #withDashboard // #withDashboard
changePageTitle, changePageTitle,
changePageSubtitle, changePageSubtitle,
@@ -87,14 +91,19 @@ function MakeJournalEntriesForm({
savedMediaIds.current = []; savedMediaIds.current = [];
}; };
const journalNumber = journalNumberPrefix
? `${journalNumberPrefix}-${journalNextNumber}`
: journalNextNumber;
useEffect(() => { useEffect(() => {
if (manualJournal && manualJournal.id) { if (manualJournal && manualJournal.id) {
changePageTitle(formatMessage({ id: 'edit_journal' })); changePageTitle(formatMessage({ id: 'edit_journal' }));
changePageSubtitle(`No. ${manualJournal.journal_number}`); changePageSubtitle(`No. ${manualJournal.journal_number}`);
} else { } else {
changePageSubtitle(`No. ${journalNumber}`);
changePageTitle(formatMessage({ id: 'new_journal' })); changePageTitle(formatMessage({ id: 'new_journal' }));
} }
}, [changePageTitle, changePageSubtitle, manualJournal, formatMessage]); }, [changePageTitle, changePageSubtitle, journalNumber, manualJournal, formatMessage]);
const validationSchema = Yup.object().shape({ const validationSchema = Yup.object().shape({
journal_number: Yup.string() journal_number: Yup.string()
@@ -149,11 +158,6 @@ function MakeJournalEntriesForm({
}), }),
[], [],
); );
const journalNumber = journalNumberPrefix
? `${journalNumberPrefix}-${journalNextNumber}`
: journalNextNumber;
const defaultInitialValues = useMemo( const defaultInitialValues = useMemo(
() => ({ () => ({
journal_number: journalNumber, journal_number: journalNumber,
@@ -366,14 +370,13 @@ function MakeJournalEntriesForm({
}, },
}); });
// Observes journal number settings changes.
useEffect(() => { useEffect(() => {
if (journalNumberChanged) {
setFieldValue('journal_number', journalNumber); setFieldValue('journal_number', journalNumber);
}, [journalNumber, setFieldValue]);
// Change page subtitle.
useEffect(() => {
changePageSubtitle(`No. ${journalNumber}`); changePageSubtitle(`No. ${journalNumber}`);
}, [changePageSubtitle, journalNumber]); }
}, [journalNumber, journalNumberChanged, setFieldValue, changePageSubtitle]);
const handleSubmitClick = useCallback( const handleSubmitClick = useCallback(
(payload) => { (payload) => {
@@ -474,4 +477,7 @@ export default compose(
journalNumberPrefix: manualJournalsSettings.numberPrefix, journalNumberPrefix: manualJournalsSettings.numberPrefix,
})), })),
withManualJournalsActions, withManualJournalsActions,
withManualJournals(({ journalNumberChanged }) => ({
journalNumberChanged
}))
)(MakeJournalEntriesForm); )(MakeJournalEntriesForm);

View File

@@ -24,6 +24,10 @@ const mapActionsToProps = (dispatch) => ({
type: t.MANUAL_JOURNALS_TABLE_QUERIES_ADD, type: t.MANUAL_JOURNALS_TABLE_QUERIES_ADD,
queries, queries,
}), }),
setJournalNumberChanged: (isChanged) => dispatch({
type: t.MANUAL_JOURNAL_NUMBER_CHANGED,
payload: { isChanged },
}),
}); });
export default connect(null, mapActionsToProps); export default connect(null, mapActionsToProps);

View File

@@ -1,5 +1,5 @@
import React from 'react'; import React from 'react';
import { FormGroup, Intent, InputGroup } from '@blueprintjs/core'; import { FormGroup, Intent, InputGroup, TextArea } from '@blueprintjs/core';
import { Row, Col } from 'components'; import { Row, Col } from 'components';
import { FormattedMessage as T } from 'react-intl'; import { FormattedMessage as T } from 'react-intl';
@@ -12,7 +12,12 @@ const CustomerBillingAddress = ({
getFieldProps, getFieldProps,
}) => { }) => {
return ( return (
<Row className={'customer-form__tabs-section'}> <div
className={
'customer-form__tabs-section customer-form__tabs-section--address'
}
>
<Row>
<Col xs={6}> <Col xs={6}>
<h4> <h4>
<T id={'billing_address'} /> <T id={'billing_address'} />
@@ -45,8 +50,8 @@ const CustomerBillingAddress = ({
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={<T id={'address'} />} label={<T id={'address_line_1'} />}
className={'form-group--journal-number'} className={'form-group--address_line_1'}
intent={ intent={
errors.billing_address_1 && errors.billing_address_1 &&
touched.billing_address_1 && touched.billing_address_1 &&
@@ -57,7 +62,7 @@ const CustomerBillingAddress = ({
<ErrorMessage name="billing_address_1" {...{ errors, touched }} /> <ErrorMessage name="billing_address_1" {...{ errors, touched }} />
} }
> >
<InputGroup <TextArea
intent={ intent={
errors.billing_address_1 && errors.billing_address_1 &&
touched.billing_address_1 && touched.billing_address_1 &&
@@ -68,7 +73,7 @@ const CustomerBillingAddress = ({
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={<T id={'address'} />} label={<T id={'address_line_2'} />}
className={'form-group--journal-number'} className={'form-group--journal-number'}
intent={ intent={
errors.billing_address_2 && errors.billing_address_2 &&
@@ -80,7 +85,7 @@ const CustomerBillingAddress = ({
<ErrorMessage name="billing_address_2" {...{ errors, touched }} /> <ErrorMessage name="billing_address_2" {...{ errors, touched }} />
} }
> >
<InputGroup <TextArea
intent={ intent={
errors.billing_address_2 && errors.billing_address_2 &&
touched.billing_address_2 && touched.billing_address_2 &&
@@ -218,7 +223,7 @@ const CustomerBillingAddress = ({
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={<T id={'address'} />} label={<T id={'address_line_1'} />}
className={'form-group--journal-number'} className={'form-group--journal-number'}
intent={ intent={
errors.billing_address_1 && errors.billing_address_1 &&
@@ -230,7 +235,7 @@ const CustomerBillingAddress = ({
<ErrorMessage name="billing_address_1" {...{ errors, touched }} /> <ErrorMessage name="billing_address_1" {...{ errors, touched }} />
} }
> >
<InputGroup <TextArea
intent={ intent={
errors.billing_address_1 && errors.billing_address_1 &&
touched.billing_address_1 && touched.billing_address_1 &&
@@ -241,7 +246,7 @@ const CustomerBillingAddress = ({
</FormGroup> </FormGroup>
<FormGroup <FormGroup
label={<T id={'address'} />} label={<T id={'address_line_2'} />}
className={'form-group--journal-number'} className={'form-group--journal-number'}
intent={ intent={
errors.billing_address_2 && errors.billing_address_2 &&
@@ -253,7 +258,7 @@ const CustomerBillingAddress = ({
<ErrorMessage name="billing_address_2" {...{ errors, touched }} /> <ErrorMessage name="billing_address_2" {...{ errors, touched }} />
} }
> >
<InputGroup <TextArea
intent={ intent={
errors.billing_address_2 && errors.billing_address_2 &&
touched.billing_address_2 && touched.billing_address_2 &&
@@ -359,6 +364,7 @@ const CustomerBillingAddress = ({
</FormGroup> </FormGroup>
</Col> </Col>
</Row> </Row>
</div>
); );
}; };

View File

@@ -28,7 +28,7 @@ export default function CustomerFinancialPanel({
); );
return ( return (
<div> <div className={'customer-form__tabs-section customer-form__tabs-section--financial'}>
<Row> <Row>
<Col xs={6}> <Col xs={6}>
<FormGroup <FormGroup

View File

@@ -270,7 +270,6 @@ function CustomerForm({
values={values} values={values}
touched={touched} /> touched={touched} />
</div> </div>
</form>
<CustomerFloatingActions <CustomerFloatingActions
onSubmitClick={handleSubmitClick} onSubmitClick={handleSubmitClick}
@@ -278,6 +277,7 @@ function CustomerForm({
onCancelClick={handleCancelClick} onCancelClick={handleCancelClick}
customerId={null} customerId={null}
/> />
</form>
</div> </div>
); );
} }

View File

@@ -1,6 +1,10 @@
import React from 'react'; import React from 'react';
import { FormGroup, Intent, InputGroup } from '@blueprintjs/core'; import {
import { Row, Col } from 'react-grid-system'; FormGroup,
Intent,
InputGroup,
ControlGroup,
} from '@blueprintjs/core';
import { FormattedMessage as T } from 'react-intl'; import { FormattedMessage as T } from 'react-intl';
import { ErrorMessage } from 'components'; import { ErrorMessage } from 'components';
@@ -16,9 +20,7 @@ export default function CustomerFormAfterPrimarySection({
{/*------------ Customer email -----------*/} {/*------------ Customer email -----------*/}
<FormGroup <FormGroup
intent={errors.email && touched.email && Intent.DANGER} intent={errors.email && touched.email && Intent.DANGER}
helperText={ helperText={<ErrorMessage name={'email'} {...{ errors, touched }} />}
<ErrorMessage name={'email'} {...{ errors, touched }} />
}
className={'form-group--email'} className={'form-group--email'}
label={<T id={'customer_email'} />} label={<T id={'customer_email'} />}
inline={true} inline={true}
@@ -29,7 +31,6 @@ export default function CustomerFormAfterPrimarySection({
/> />
</FormGroup> </FormGroup>
{/*------------ Customer email -----------*/} {/*------------ Customer email -----------*/}
<FormGroup <FormGroup
intent={errors.work_phone && touched.work_phone && Intent.DANGER} intent={errors.work_phone && touched.work_phone && Intent.DANGER}
@@ -40,28 +41,31 @@ export default function CustomerFormAfterPrimarySection({
label={<T id={'phone_number'} />} label={<T id={'phone_number'} />}
inline={true} inline={true}
> >
<ControlGroup>
<InputGroup <InputGroup
intent={ intent={errors.work_phone && touched.work_phone && Intent.DANGER}
errors.work_phone && touched.work_phone && Intent.DANGER
}
{...getFieldProps('work_phone')} {...getFieldProps('work_phone')}
placeholder={'Work'}
/> />
<InputGroup
intent={errors.work_phone && touched.work_phone && Intent.DANGER}
{...getFieldProps('work_phone')}
placeholder={'Mobile'}
/>
</ControlGroup>
</FormGroup> </FormGroup>
{/*------------ Customer website -----------*/} {/*------------ Customer website -----------*/}
<FormGroup <FormGroup
intent={errors.website && touched.website && Intent.DANGER} intent={errors.website && touched.website && Intent.DANGER}
helperText={ helperText={<ErrorMessage name={'website'} {...{ errors, touched }} />}
<ErrorMessage name={'website'} {...{ errors, touched }} />
}
className={'form-group--website'} className={'form-group--website'}
label={<T id={'website'} />} label={<T id={'website'} />}
inline={true} inline={true}
> >
<InputGroup <InputGroup
intent={ intent={errors.website && touched.website && Intent.DANGER}
errors.website && touched.website && Intent.DANGER
}
{...getFieldProps('website')} {...getFieldProps('website')}
/> />
</FormGroup> </FormGroup>

View File

@@ -1,36 +0,0 @@
import React from 'react';
import {
Button,
Classes,
FormGroup,
InputGroup,
Intent,
TextArea,
MenuItem,
} from '@blueprintjs/core';
import { FormattedMessage as T, useIntl } from 'react-intl';
import ErrorMessage from 'components/ErrorMessage';
const CustomerBillingAddress = ({
formik: { errors, touched, setFieldValue, getFieldProps },
}) => {
return (
<div>
<FormGroup
label={<T id={'note'} />}
// className={'form-group--description'}
intent={errors.note && touched.note && Intent.DANGER}
helperText={<ErrorMessage name="note" {...{ errors, touched }} />}
inline={true}
>
<TextArea
growVertically={true}
large={true}
{...getFieldProps('note')}
/>
</FormGroup>
</div>
);
};
export default CustomerBillingAddress;

View File

@@ -0,0 +1,34 @@
import React from 'react';
import classNames from 'classnames';
import { FormGroup, Intent, TextArea, Classes } from '@blueprintjs/core';
import { Row, Col } from 'components';
import { FormattedMessage as T } from 'react-intl';
import ErrorMessage from 'components/ErrorMessage';
export default function CustomerNotePanel({ errors, touched, getFieldProps }) {
return (
<div
className={
'customer-form__tabs-section customer-form__tabs-section--note'
}
>
<Row>
<Col xs={6}>
<FormGroup
label={<T id={'note'} />}
className={classNames('form-group--select-list', Classes.FILL)}
intent={errors.note && touched.note && Intent.DANGER}
helperText={
<ErrorMessage name="payment_date" {...{ errors, touched }} />
}
>
<TextArea
intent={errors.note && touched.note && Intent.DANGER}
{...getFieldProps('note')}
/>
</FormGroup>
</Col>
</Row>
</div>
);
}

View File

@@ -2,58 +2,69 @@ import React, { useState, useCallback } from 'react';
import { Tabs, Tab } from '@blueprintjs/core'; import { Tabs, Tab } from '@blueprintjs/core';
import { FormattedMessage as T, useIntl } from 'react-intl'; import { FormattedMessage as T, useIntl } from 'react-intl';
import CustomerAddressTabs from './CustomerAddressTabs'; import CustomerAddressTabs from './CustomerAddressTabs';
import CustomerNotTabs from './CustomerNotTabs';
import CustomerAttachmentTabs from './CustomerAttachmentTabs'; import CustomerAttachmentTabs from './CustomerAttachmentTabs';
import CustomerFinancialPanel from './CustomerFinancialPanel'; import CustomerFinancialPanel from './CustomerFinancialPanel';
import CustomerNotePanel from './CustomerNotePanel';
function CustomersTabs({ export default function CustomersTabs({
setFieldValue, setFieldValue,
getFieldProps, getFieldProps,
errors, errors,
values, values,
touched, touched,
}) { }) {
const [animate, setAnimate] = useState(true);
const { formatMessage } = useIntl(); const { formatMessage } = useIntl();
const handleChangeTabs = useCallback(() => {}, []);
return ( return (
<div> <div>
<Tabs animate={animate} id={'customer-tabs'} large={true}> <Tabs
animate={true}
id={'customer-tabs'}
large={true}
defaultSelectedTabId="financial"
>
<Tab <Tab
id={'financial'} id={'financial'}
title={formatMessage({ id: 'financial_details' })} title={formatMessage({ id: 'financial_details' })}
panel={<CustomerFinancialPanel panel={
<CustomerFinancialPanel
values={values} values={values}
errors={errors} errors={errors}
setFieldValue={setFieldValue} setFieldValue={setFieldValue}
touched={touched} touched={touched}
/>} />
}
/> />
<Tab <Tab
id={'address'} id={'address'}
title={formatMessage({ id: 'address' })} title={formatMessage({ id: 'address' })}
panel={<CustomerAddressTabs panel={
<CustomerAddressTabs
setFieldValue={setFieldValue} setFieldValue={setFieldValue}
getFieldProps={getFieldProps} getFieldProps={getFieldProps}
errors={errors} errors={errors}
values={values} values={values}
touched={touched} touched={touched}
/>} />
}
/>
<Tab
id="notes"
title={formatMessage({ id: 'notes' })}
panel={
<CustomerNotePanel
errors={errors}
touched={touched}
getFieldProps={getFieldProps}
/>
}
/> />
<Tab <Tab
id={'attachement'} id={'attachement'}
title={formatMessage({ id: 'attachement' })} title={formatMessage({ id: 'attachement' })}
panel={<CustomerAttachmentTabs />} panel={<CustomerAttachmentTabs />}
/> />
{/* <Tab
id={'note'}
title={formatMessage({ id: 'note' })}
panel={<CustomerNotTabs formik={formik} />}
/> */}
</Tabs> </Tabs>
</div> </div>
); );
} }
export default CustomersTabs;

View File

@@ -45,6 +45,7 @@ function JournalNumberDialogContent({
setTimeout(() => { setTimeout(() => {
queryCache.invalidateQueries('settings'); queryCache.invalidateQueries('settings');
setJournalNumberChanged(true);
}, 250); }, 250);
}).catch(() => { }).catch(() => {
setSubmitting(false); setSubmitting(false);

View File

@@ -802,4 +802,6 @@ export default {
'Clearing the table lines will delete all credits and payment were applied, Is this okay?', 'Clearing the table lines will delete all credits and payment were applied, Is this okay?',
changing_full_amount_will_change_all_credits_and_payment: changing_full_amount_will_change_all_credits_and_payment:
' Changing full amount will change all credits and payment were applied, Is this okay?', ' Changing full amount will change all credits and payment were applied, Is this okay?',
address_line_1: 'Address line 1',
address_line_2: 'Address line 2',
}; };

View File

@@ -1,5 +1,5 @@
export const journalNumberReducers = (type) => ({ export const journalNumberChangedReducer = (type) => ({
[type]: (state, action) => { [type]: (state, action) => {
const { isChanged } = action.payload; const { isChanged } = action.payload;
state.journalNumberChanged = isChanged; state.journalNumberChanged = isChanged;

View File

@@ -2,6 +2,7 @@ import t from 'store/types';
import { createReducer } from '@reduxjs/toolkit'; import { createReducer } from '@reduxjs/toolkit';
import { createTableQueryReducers } from 'store/queryReducers'; import { createTableQueryReducers } from 'store/queryReducers';
import { omit } from 'lodash'; import { omit } from 'lodash';
import { journalNumberChangedReducer } from 'store/journalNumber.reducer';
const initialState = { const initialState = {
items: {}, items: {},
@@ -15,6 +16,7 @@ const initialState = {
paginationMeta: { paginationMeta: {
total: 0, total: 0,
}, },
journalNumberChanged: false,
}; };
const defaultJournal = { const defaultJournal = {
@@ -115,6 +117,8 @@ const reducer = createReducer(initialState, {
}, },
}; };
}, },
...journalNumberChangedReducer(t.MANUAL_JOURNAL_NUMBER_CHANGED),
}); });
export default createTableQueryReducers('manual_journals', reducer); export default createTableQueryReducers('manual_journals', reducer);

View File

@@ -3,7 +3,13 @@ import t from 'store/types';
export const submitOptions = ({ form }) => { export const submitOptions = ({ form }) => {
return (dispatch) => { return (dispatch) => {
return ApiService.post('settings', form); return ApiService.post('settings', form).then((response) => {
dispatch({
type: t.SETTING_SET,
options: form.options,
});
return response;
});
}; };
}; };

View File

@@ -16,9 +16,10 @@
#{$self}__header{ #{$self}__header{
.bp3-form-group{ .bp3-form-group{
max-width: 500px;
.bp3-label{ .bp3-label{
width: 200px; min-width: 150px;
} }
.bp3-form-content{ .bp3-form-content{
@@ -27,6 +28,7 @@
} }
.form-group--contact_name{ .form-group--contact_name{
max-width: 100%;
.bp3-control-group > *{ .bp3-control-group > *{
flex-shrink: unset; flex-shrink: unset;
@@ -54,10 +56,28 @@
margin-top: 26px; margin-top: 26px;
} }
.form-group--phone-number{
.bp3-control-group > *{
flex-shrink: unset;
padding-right: 5px;
padding-left: 5px;
&:first-child{
padding-left: 0;
}
&:last-child{
padding-right: 0;
}
}
}
#{$self}__tabs{ #{$self}__tabs{
margin-top: 20px; margin-top: 20px;
max-width: 1000px;
.bp3-form-group{ .bp3-form-group{
max-width: 440px;
.bp3-label{ .bp3-label{
min-width: 145px; min-width: 145px;
@@ -65,6 +85,12 @@
.bp3-form-content{ .bp3-form-content{
width: 100%; width: 100%;
} }
textarea.bp3-input{
max-width: 100%;
width: 100%;
min-height: 50px;
}
} }
h4{ h4{
@@ -103,6 +129,11 @@
} }
} }
} }
#{$self}__floating-actions {
margin-left: -20px;
margin-right: -20px;
}
} }