From f3d892cdd2e5cb6bea5d9b4cd0d03c5ecda81b56 Mon Sep 17 00:00:00 2001 From: elforjani3 Date: Wed, 22 Apr 2020 19:31:58 +0200 Subject: [PATCH] WIP feature/Currencies --- client/src/components/DialogsContainer.js | 2 + client/src/config/preferencesMenu.js | 8 +- .../connectors/CurrencyFromDialog.connect.js | 35 ++++ .../Dashboard/Dialogs/CurrencyDialog.js | 182 ++++++++++++++++++ .../Dashboard/Preferences/Currencies.js | 22 +++ .../Dashboard/Preferences/CurrenciesList.js | 146 ++++++++++++++ client/src/routes/preferences.js | 8 +- .../store/currencies/currencies.actions.js | 69 ++++--- .../store/currencies/currencies.reducer.js | 20 +- .../store/currencies/currencies.selector.js | 3 + .../src/store/currencies/currencies.types.js | 5 +- client/src/style/App.scss | 2 +- client/src/style/pages/currency.scss | 12 ++ 13 files changed, 477 insertions(+), 37 deletions(-) create mode 100644 client/src/connectors/CurrencyFromDialog.connect.js create mode 100644 client/src/containers/Dashboard/Dialogs/CurrencyDialog.js create mode 100644 client/src/containers/Dashboard/Preferences/Currencies.js create mode 100644 client/src/containers/Dashboard/Preferences/CurrenciesList.js create mode 100644 client/src/store/currencies/currencies.selector.js create mode 100644 client/src/style/pages/currency.scss diff --git a/client/src/components/DialogsContainer.js b/client/src/components/DialogsContainer.js index b48065b2f..a19833c32 100644 --- a/client/src/components/DialogsContainer.js +++ b/client/src/components/DialogsContainer.js @@ -2,10 +2,12 @@ import React from 'react'; import AccountFormDialog from 'containers/Dashboard/Dialogs/AccountFormDialog'; import UserFormDialog from 'containers/Dashboard/Dialogs/UserFormDialog'; import ItemCategoryDialog from 'containers/Dashboard/Dialogs/ItemCategoryDialog'; +import CurrencyDialog from 'containers/Dashboard/Dialogs/CurrencyDialog'; export default function DialogsContainer() { return ( + diff --git a/client/src/config/preferencesMenu.js b/client/src/config/preferencesMenu.js index 415aba43d..34190463b 100644 --- a/client/src/config/preferencesMenu.js +++ b/client/src/config/preferencesMenu.js @@ -1,4 +1,3 @@ - export default [ { text: 'General', @@ -9,6 +8,11 @@ export default [ text: 'Users', href: '/dashboard/preferences/users', }, + { + text: 'Currencies', + + href: '/dashboard/preferences/currencies', + }, { text: 'Accountant', disabled: false, @@ -49,4 +53,4 @@ export default [ disabled: false, href: '/dashboard/preferences/debit_note', }, -] \ No newline at end of file +]; diff --git a/client/src/connectors/CurrencyFromDialog.connect.js b/client/src/connectors/CurrencyFromDialog.connect.js new file mode 100644 index 000000000..9d6c5632f --- /dev/null +++ b/client/src/connectors/CurrencyFromDialog.connect.js @@ -0,0 +1,35 @@ +import { connect } from 'react-redux'; +import { + fetchCurrencies, + submitCurrencies, + deleteCurrency, + editCurrency, +} from 'store/currencies/currencies.actions'; +import { getDialogPayload } from 'store/dashboard/dashboard.reducer'; +import { getCurrencyById } from 'store/currencies/currencies.selector'; + +export const mapStateToProps = (state, props) => { + const dialogPayload = getDialogPayload(state, 'currency-form'); + + return { + currencies: state.currencies.preferences.currencies, + name: 'currency-form', + payload: { action: 'new', id: null, ...dialogPayload }, + editCurrency: + dialogPayload && dialogPayload.action === 'edit' + ? state.currencies.preferences.currencies[dialogPayload.currency_code] + : {}, + getCurrencyId: (id) => + getCurrencyById(state.currencies.preferences.currencies, id), + }; +}; + +export const mapDispatchToProps = (dispatch) => ({ + requestFetchCurrencies: () => dispatch(fetchCurrencies({})), + requestSubmitCurrencies: (form) => dispatch(submitCurrencies({ form })), + requestEditCurrency: (id, form) => dispatch(editCurrency({ id, form })), + requestDeleteCurrency: (currency_code) => + dispatch(deleteCurrency({ currency_code })), +}); + +export default connect(mapStateToProps, mapDispatchToProps); diff --git a/client/src/containers/Dashboard/Dialogs/CurrencyDialog.js b/client/src/containers/Dashboard/Dialogs/CurrencyDialog.js new file mode 100644 index 000000000..e5d6e4b93 --- /dev/null +++ b/client/src/containers/Dashboard/Dialogs/CurrencyDialog.js @@ -0,0 +1,182 @@ +import React, { useState, useMemo, useCallback } from 'react'; +import { + Button, + Classes, + FormGroup, + InputGroup, + Intent, +} 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 CurrencyFromDialogConnect from 'connectors/CurrencyFromDialog.connect'; +import ErrorMessage from 'components/ErrorMessage'; +import classNames from 'classnames'; +import { pick } from 'lodash'; + +function CurrencyDialog({ + name, + payload, + isOpen, + closeDialog, + requestFetchCurrencies, + requestSubmitCurrencies, + requestEditCurrency, + editCurrency, +}) { + const intl = useIntl(); + + const ValidationSchema = Yup.object().shape({ + currency_name: Yup.string().required( + intl.formatMessage({ id: 'required' }) + ), + currency_code: Yup.string() + .max(4) + .required(intl.formatMessage({ id: 'required' })), + }); + const initialValues = useMemo( + () => ({ + currency_name: '', + currency_code: '', + }), + [] + ); + + const formik = useFormik({ + enableReinitialize: true, + + initialValues: { + ...(payload.action === 'edit' && + pick(editCurrency, Object.keys(initialValues))), + }, + + validationSchema: ValidationSchema, + onSubmit: (values, { setSubmitting }) => { + if (payload.action === 'edit') { + requestEditCurrency(editCurrency.id, values) + .then((response) => { + closeDialog(name); + AppToaster.show({ + message: 'the_currency_has_been_edited', + }); + setSubmitting(false); + }) + .catch((error) => { + setSubmitting(false); + }); + } else { + requestSubmitCurrencies(values) + .then((response) => { + closeDialog(name); + AppToaster.show({ + message: 'the_currency_has_been_submit', + }); + setSubmitting(false); + }) + .catch((error) => { + setSubmitting(false); + }); + } + }, + }); + + const { values, errors, touched } = useMemo(() => formik, [formik]); + + const handleClose = useCallback(() => { + closeDialog(name); + }, [name, closeDialog]); + + const fetchHook = useAsync(async () => { + await Promise.all([requestFetchCurrencies()]); + }); + + const onDialogOpening = useCallback(() => { + fetchHook.execute(); + }, [fetchHook]); + + const onDialogClosed = useCallback(() => { + formik.resetForm(); + closeDialog(name); + }, [formik, closeDialog, name]); + + const requiredSpan = useMemo(() => *, []); + + return ( + +
+
+ } + inline={true} + > + + + } + inline={true} + > + + +
+
+
+ + +
+
+
+
+ ); +} + +export default compose( + CurrencyFromDialogConnect, + DialogConnect, + DialogReduxConnect +)(CurrencyDialog); diff --git a/client/src/containers/Dashboard/Preferences/Currencies.js b/client/src/containers/Dashboard/Preferences/Currencies.js new file mode 100644 index 000000000..8110bad58 --- /dev/null +++ b/client/src/containers/Dashboard/Preferences/Currencies.js @@ -0,0 +1,22 @@ +import React from 'react'; +import { Button, Intent } from '@blueprintjs/core'; +import { compose } from 'utils'; +import DialogConnect from 'connectors/Dialog.connector'; +import CurrencyFromDialogConnect from 'connectors/CurrencyFromDialog.connect'; +function Currencies({ openDialog }) { + const onClickNewCurrency = () => { + openDialog('currency-form',{}); + }; + + return ( +
+
+ +
+
+ ); +} + +export default compose(DialogConnect, CurrencyFromDialogConnect)(Currencies); diff --git a/client/src/containers/Dashboard/Preferences/CurrenciesList.js b/client/src/containers/Dashboard/Preferences/CurrenciesList.js new file mode 100644 index 000000000..7f4f01bbc --- /dev/null +++ b/client/src/containers/Dashboard/Preferences/CurrenciesList.js @@ -0,0 +1,146 @@ +import React, { useEffect, useCallback, useState, useMemo } from 'react'; +import { + Button, + Popover, + Menu, + MenuItem, + MenuDivider, + Position, + Classes, + Tooltip, + Alert, + Intent, +} from '@blueprintjs/core'; +import Icon from 'components/Icon'; +import { snakeCase } from 'lodash'; +import { compose } from 'utils'; +import CurrencyFromDialogConnect from 'connectors/CurrencyFromDialog.connect'; +import DialogConnect from 'connectors/Dialog.connector'; +import DashboardConnect from 'connectors/Dashboard.connector'; +import LoadingIndicator from 'components/LoadingIndicator'; +import DataTable from 'components/DataTable'; +import Currencies from './Currencies'; +import useAsync from 'hooks/async'; +import AppToaster from 'components/AppToaster'; + +function CurrenciesList({ + currencies, + openDialog, + onFetchData, + requestDeleteCurrency, +}) { + const [deleteCurrencyState, setDeleteCurrencyState] = useState(false); + + const handleEditCurrency = (currency) => () => { + openDialog('currency-form', { + action: 'edit', + currency_code: currency.currency_code, + }); + }; + + const onDeleteCurrency = (currency) => { + setDeleteCurrencyState(currency); + }; + const handleCancelCurrencyDelete = () => { + setDeleteCurrencyState(false); + }; + + const handleConfirmCurrencyDelete = useCallback(() => { + requestDeleteCurrency(deleteCurrencyState.currency_code).then( + (response) => { + setDeleteCurrencyState(false); + AppToaster.show({ + message: 'the_Currency_has_been_deleted', + }); + } + ); + }, [deleteCurrencyState]); + + const actionMenuList = useCallback( + (currency) => ( + + + + onDeleteCurrency(currency)} + /> + + ), + [] + ); + + const columns = useMemo( + () => [ + { + id: 'currency_name', + Header: 'Currency Name', + accessor: 'currency_name', + width: 100, + }, + { + id: 'currency_code', + Header: 'Currency Code', + accessor: 'currency_code', + className: 'currency_code', + width: 100, + }, + { + Header: 'Currency sign', + width: 50, + }, + { + id: 'actions', + Header: '', + Cell: ({ cell }) => ( + +