Merge branch 'feature/itemCategore'

This commit is contained in:
Ahmed Bouhuolia
2020-03-31 16:58:56 +02:00
12 changed files with 356 additions and 27 deletions

View File

@@ -1,12 +1,14 @@
import React from 'react'; import React from 'react';
import AccountFormDialog from 'containers/Dashboard/Dialogs/AccountFormDialog'; import AccountFormDialog from 'containers/Dashboard/Dialogs/AccountFormDialog';
import UserFormDialog from 'containers/Dashboard/Dialogs/UserFormDialog'; import UserFormDialog from 'containers/Dashboard/Dialogs/UserFormDialog';
import ItemFromDialog from 'containers/Dashboard/Dialogs/ItemFromDialog';
export default function DialogsContainer() { export default function DialogsContainer() {
return ( return (
<React.Fragment> <React.Fragment>
<AccountFormDialog /> <AccountFormDialog />
{/* <UserFormDialog /> */} <UserFormDialog />
<ItemFromDialog />
</React.Fragment> </React.Fragment>
); );
} }

View File

@@ -0,0 +1,60 @@
import React, { useMemo } from 'react';
import {
Button,
Popover,
Menu,
MenuItem,
MenuDivider,
Position,
Checkbox
} from '@blueprintjs/core';
import {
GridComponent,
ColumnsDirective,
ColumnDirective,
Inject,
Sort
} from '@syncfusion/ej2-react-grids';
import LoadingIndicator from 'components/LoadingIndicator';
import DashboardConnect from 'connectors/Dashboard.connector';
import ItemFormDialogConnect from 'connectors/ItemFormDialog.connect';
import Icon from 'components/Icon';
import { useParams } from 'react-router-dom';
import { handleBooleanChange, compose } from 'utils';
import DataTable from 'components/DataTable';
const categoryList = ({ categories }) => {
const columns = [
{
field: 'name',
headerText: 'Name'
},
{
field: 'description',
headerText: 'Description'
}
];
return (
<LoadingIndicator>
<GridComponent
allowSorting={true}
dataSource={columns}
enableVirtualization={true}
>
<ColumnsDirective>
<ColumnDirective type='checkbox'></ColumnDirective>
{/* {columns.map(column => {
return (
<ColumnDirective
field={column.field}
headerText={column.headerText}
allowSorting={true}
/>
);
})} */}
</ColumnsDirective>
</GridComponent>
</LoadingIndicator>
);
};
export default compose(DashboardConnect, ItemFormDialogConnect)(categoryList);

View File

@@ -19,16 +19,20 @@ export default [
children: [ children: [
{ {
text: 'Items List', text: 'Items List',
href: '/dashboard/items/list', href: '/dashboard/items/list'
}, },
{ {
text: 'New Item', text: 'New Item',
href: '/dashboard/items/new', href: '/dashboard/items/new'
}, },
{
text: 'Category List',
href: '/dashboard/items/category'
}
] ]
}, },
{ {
divider: true, divider: true
}, },
{ {
icon: 'balance-scale', icon: 'balance-scale',
@@ -37,29 +41,25 @@ export default [
children: [ children: [
{ {
text: 'Accounts Chart', text: 'Accounts Chart',
href: '/dashboard/accounts', href: '/dashboard/accounts'
}, },
{ {
text: 'Make Journal', text: 'Make Journal',
href: '/dashboard/accounting/make-journal-entry' href: '/dashboard/accounting/make-journal-entry'
}, }
] ]
}, },
{ {
icon: 'university', icon: 'university',
iconSize: 20, iconSize: 20,
text: 'Banking', text: 'Banking',
children: [ children: []
]
}, },
{ {
icon: 'shopping-cart', icon: 'shopping-cart',
iconSize: 20, iconSize: 20,
text: 'Sales', text: 'Sales',
children: [ children: []
]
}, },
{ {
icon: 'balance-scale', icon: 'balance-scale',
@@ -81,24 +81,24 @@ export default [
children: [ children: [
{ {
text: 'Balance Sheet', text: 'Balance Sheet',
href: '/dashboard/accounting/balance-sheet', href: '/dashboard/accounting/balance-sheet'
}, },
{ {
text: 'Trial Balance Sheet', text: 'Trial Balance Sheet',
href: '/dashboard/accounting/trial-balance-sheet', href: '/dashboard/accounting/trial-balance-sheet'
}, },
{ {
text: 'Journal', text: 'Journal',
href: '/dashboard/accounting/journal-sheet', href: '/dashboard/accounting/journal-sheet'
}, },
{ {
text: 'General Ledger', text: 'General Ledger',
href: '/dashboard/accounting/general-ledger', href: '/dashboard/accounting/general-ledger'
}, },
{ {
text: 'Profit Loss Sheet', text: 'Profit Loss Sheet',
href: '/dashboard/accounting/profit-loss-sheet', href: '/dashboard/accounting/profit-loss-sheet'
}, }
] ]
}, },
{ {
@@ -108,12 +108,12 @@ export default [
children: [ children: [
{ {
text: 'Expenses List', text: 'Expenses List',
href: '/dashboard/expenses', href: '/dashboard/expenses'
}, },
{ {
text: 'New Expenses', text: 'New Expenses',
href: '/dashboard/expenses/new', href: '/dashboard/expenses/new'
}, }
] ]
}, },
{ {

View File

@@ -0,0 +1,24 @@
//FIXME: FIX Later Need More Work
import { connect } from 'react-redux';
import {
submitItemCategory,
submitCategory,
fetchCategory
} from 'store/itemCategories/itemsCategory.actions';
export const mapStateToProps = (state, props) => {
return {
category: state.category,
name: 'item-form',
payload: { action: 'new', id: null }
};
};
export const mapDispatchToProps = dispatch => ({
submitItemCategory: form => dispatch(submitItemCategory({ form })),
submitCategory: form => dispatch(submitCategory({ form })),
fetchCategory: () => dispatch(fetchCategory())
});
export default connect(mapStateToProps, mapDispatchToProps);

View File

@@ -0,0 +1,130 @@
import React, { useState } from 'react';
import {
Button,
Classes,
FormGroup,
InputGroup,
Intent,
TextArea
} from '@blueprintjs/core';
import * as Yup from 'yup';
import { useIntl } from 'react-intl';
import { useFormik } from 'formik';
import { compose } from 'utils';
import Dialog from 'components/Dialog';
import useAsync from 'hooks/async';
import AppToaster from 'components/AppToaster';
import DialogConnect from 'connectors/Dialog.connector';
import DialogReduxConnect from 'components/DialogReduxConnect';
import ItemFormDialogConnect from 'connectors/ItemFormDialog.connect';
function ItemFromDialog({
name,
payload,
isOpen,
submitItemCategory,
fetchCategory,
openDialog,
closeDialog
}) {
const [state, setState] = useState({});
const intl = useIntl();
const ValidationSchema = Yup.object().shape({
name: Yup.string().required(intl.formatMessage({ id: 'required' })),
description: Yup.string().trim()
});
const formik = useFormik({
enableReinitialize: true,
initialValues: {},
validationSchema: ValidationSchema,
onSubmit: values => {
submitItemCategory({ values })
.then(response => {
AppToaster.show({
message: 'the_category_has_been_submit'
});
})
.catch(error => {
alert(error.message);
});
}
});
const fetchHook = useAsync(async () => {
await Promise.all([submitItemCategory]);
});
const handleClose = () => {
closeDialog(name);
};
const onDialogOpening = () => {
fetchHook.execute();
openDialog(name);
};
const onDialogClosed = () => {
// formik.resetForm();
closeDialog(name);
};
return (
<Dialog
name={name}
title={payload.action === 'new' ? 'New' : ' New Category'}
className={{
'dialog--loading': state.isLoading,
'dialog--item-form': true
}}
isOpen={isOpen}
onClosed={onDialogClosed}
onOpening={onDialogOpening}
isLoading={fetchHook.pending}
>
<form onSubmit={formik.handleSubmit}>
<div className={Classes.DIALOG_BODY}>
<FormGroup
label={'Category Name'}
className={'form-group--category-name'}
intent={formik.errors.name && Intent.DANGER}
helperText={formik.errors.name && formik.errors.name}
inline={true}
>
<InputGroup
medium={formik.values.toString()}
intent={formik.errors.name && Intent.DANGER}
{...formik.getFieldProps('name')}
/>
</FormGroup>
<FormGroup
label={'Description'}
className={'form-group--description'}
intent={formik.errors.description && Intent.DANGER}
helperText={formik.errors.description && formik.errors.credential}
inline={true}
>
<TextArea
growVertically={true}
large={true}
{...formik.getFieldProps('description')}
/>
</FormGroup>
</div>
<div className={Classes.DIALOG_FOOTER}>
<div className={Classes.DIALOG_FOOTER_ACTIONS}>
<Button onClick={handleClose}>Close</Button>
<Button intent={Intent.PRIMARY} type='submit'>
{payload.action === 'new' ? 'New' : 'Submit'}
</Button>
</div>
</div>
</form>
</Dialog>
);
}
export default compose(
ItemFormDialogConnect,
DialogConnect,
DialogReduxConnect
)(ItemFromDialog);

View File

@@ -0,0 +1,24 @@
import React, { useEffect } from 'react';
import { useParams } from 'react-router-dom';
import DashboardConnect from 'connectors/Dashboard.connector';
import DashboardInsider from 'components/Dashboard/DashboardInsider';
import CategoryList from 'components/Items/categoryList';
import ItemFormDialog from 'connectors/ItemFormDialog.connect';
import { compose } from 'utils';
const ItemCategoryList = ({ changePageTitle }) => {
const { id } = useParams();
useEffect(() => {
id
? changePageTitle('Edit Category Details')
: changePageTitle('Category List');
}, []);
return (
<DashboardInsider isLoading={null} name={'item-category-list'}>
<CategoryList />
</DashboardInsider>
);
};
export default compose(DashboardConnect, ItemFormDialog)(ItemCategoryList);

View File

@@ -71,13 +71,19 @@ export default [
path: `${BASE_URL}/items/list`, path: `${BASE_URL}/items/list`,
component: LazyLoader({ component: LazyLoader({
loader: () => import('containers/Dashboard/Items/ItemsList') loader: () => import('containers/Dashboard/Items/ItemsList')
}), })
}, },
{ {
path: `${BASE_URL}/items/new`, path: `${BASE_URL}/items/new`,
component: LazyLoader({ component: LazyLoader({
loader: () => import('containers/Dashboard/Items/ItemForm') loader: () => import('containers/Dashboard/Items/ItemForm')
}), })
},
{
path: `${BASE_URL}/items/category`,
component: LazyLoader({
loader: () => import('containers/Dashboard/Items/ItemCategoryList')
})
}, },
// Financial Reports. // Financial Reports.

View File

@@ -0,0 +1,47 @@
import ApiService from 'services/ApiService';
import t from 'store/types';
export const submitCategory = ({ form }) => {
return dispatch =>
new Promise((resolve, reject) => {
ApiService.post('item_categories', form)
.then(response => {
dispatch({ type: t.ITEMS_CATEGORY_LIST_SET });
resolve(response);
})
.catch(error => {
const { response } = error;
const { data } = response;
const { errors } = data;
dispatch({ type: t.ITEMS_CATEGORY_LIST_SET });
if (errors) {
dispatch({ type: t.ITEMS_CATEGORY_LIST_SET, errors });
}
reject(error);
});
});
};
export const submitItemCategory = ({ form }) => {
return dispatch => {
return ApiService.post('item_categories', { ...form });
};
};
export const fetchCategory = () => {
return (dispatch, getState) =>
new Promise((resolve, reject) => {
ApiService.get('item_categories')
.then(response => {
dispatch({
type: t.ITEMS_CATEGORY_DATA_TABLE,
data: response.data
});
resolve(response);
})
.catch(error => {
reject(error);
});
});
};

View File

@@ -0,0 +1,6 @@
export default {
ITEMS_CATEGORY_LIST_SET: 'ITEMS_CATEGORY_LIST_SET',
ITEMS_CATEGORY_DATA_TABLE: 'ITEMS_CATEGORY_DATA_TABLE',
};

View File

@@ -0,0 +1,27 @@
import t from 'store/types';
import { createReducer } from '@reduxjs/toolkit';
const initialState = {
categories: {},
categoriesById: {}
};
export default createReducer(initialState, {
[t.ITEMS_CATEGORY_LIST_SET]: (state, action) => {
const _categories = {};
action.categories.forEach(category => {
_categories[category.id] = category;
});
state.categories = {
...state.categories,
..._categories
};
},
[t.CATEGORY_SET]: (state, action) => {
state.categoriesById[action.category.id] = action.category;
}
});
export const getCategoryId = (state, id) => {
return state.categories.categoriesById[id];
};

View File

@@ -11,6 +11,7 @@ import expenses from './expenses/expenses.reducer';
import currencies from './currencies/currencies.reducer'; import currencies from './currencies/currencies.reducer';
import resources from './resources/resources.reducer'; import resources from './resources/resources.reducer';
import financialStatements from './financialStatement/financialStatements.reducer'; import financialStatements from './financialStatement/financialStatements.reducer';
import itemCategories from './itemCategories/itemsCateory.reducer';
export default combineReducers({ export default combineReducers({
authentication, authentication,
@@ -24,4 +25,5 @@ export default combineReducers({
resources, resources,
financialStatements, financialStatements,
items, items,
}); itemCategories
});

View File

@@ -10,7 +10,7 @@ import preferences from './preferences/preferences.types';
import resources from './resources/resource.types'; import resources from './resources/resource.types';
import users from './users/users.types'; import users from './users/users.types';
import financialStatements from './financialStatement/financialStatements.types'; import financialStatements from './financialStatement/financialStatements.types';
import itemCategories from './itemCategories/itemsCategory.type';
export default { export default {
...authentication, ...authentication,
...accounts, ...accounts,
@@ -24,4 +24,5 @@ export default {
...resources, ...resources,
...users, ...users,
...financialStatements, ...financialStatements,
} ...itemCategories
};