\r\n {params?.isCategory || params?.cashFlowDetail ? (\r\n \r\n \r\n \r\n {data[item].name || '-'}\r\n ({data[item].ref_code || '-'})\r\n \r\n | \r\n
\r\n ) : (\r\n \r\n \r\n {intl.formatMessage({ id: 'report.opening_balance' })}\r\n | \r\n \r\n \r\n {data[item].opening_credit > -1\r\n ? currency(data[item].opening_credit, false, true, true)\r\n : `(${currency(data[item].opening_credit, false, true, true)})`.replace(\r\n '-',\r\n '',\r\n )}\r\n \r\n | \r\n \r\n \r\n {data[item].opening_debit > -1\r\n ? currency(data[item].opening_debit, false, true, true)\r\n : `(${currency(data[item].opening_debit, false, true, true)})`.replace('-', '')}\r\n \r\n | \r\n \r\n \r\n {data[item].opening_balance > -1\r\n ? currency(data[item].opening_balance, false, true, true)\r\n : `(${currency(data[item].opening_balance, false, true, true)})`.replace(\r\n '-',\r\n '',\r\n )}\r\n \r\n | \r\n
\r\n )}\r\n\r\n {(data[item].data || []).map((v) => {\r\n return (\r\n \r\n {formatDate(v.trans_date)} | \r\n {v.source} | \r\n {v.desc} | \r\n {v.reference} | \r\n {v.ref_number} | \r\n \r\n {v.debit > -1\r\n ? currency(v.debit, false, true, true)\r\n : `(${currency(v.debit, false, true, true)})`.replace('-', '')}\r\n | \r\n \r\n {v.credit > -1\r\n ? currency(v.credit, false, true, true)\r\n : `(${currency(v.credit, false, true, true)})`.replace('-', '')}\r\n | \r\n {!params.cashFlowDetail && (\r\n \r\n {v.balance > -1\r\n ? currency(v.balance, false, true, true)\r\n : `(${currency(v.balance, false, true, true)})`.replace('-', '')}\r\n | \r\n )}\r\n
\r\n )\r\n })}\r\n \r\n \r\n {intl.formatMessage({ id: 'report.closing_balance' })}\r\n | \r\n \r\n \r\n {data[item].closing_debit > -1\r\n ? currency(data[item].closing_debit, false, true, true)\r\n : `(${currency(data[item].closing_debit, false, true, true)})`.replace('-', '')}\r\n \r\n | \r\n \r\n \r\n {data[item].closing_credit > -1\r\n ? currency(data[item].closing_credit, false, true, true)\r\n : `(${currency(data[item].closing_credit, false, true, true)})`.replace('-', '')}\r\n \r\n | \r\n {!params.cashFlowDetail && (\r\n \r\n \r\n {data[item].closing_balance > -1\r\n ? currency(data[item].closing_balance, false, true, true)\r\n : `(${currency(data[item].closing_balance, false, true, true)})`.replace(\r\n '-',\r\n '',\r\n )}\r\n \r\n | \r\n )}\r\n
\r\n {(Object.keys(data) || []).length !== index + 1 && (\r\n \r\n | \r\n
\r\n )}\r\n ,\r\n )\r\n })\r\n\r\n body.push(\r\n \r\n \r\n \r\n \r\n {data[item].name || '-'}\r\n ({data[item].ref_code || '-'})\r\n \r\n | \r\n
\r\n {(data[item].data || []).map((v) => {\r\n const { trans_type_id } = v\r\n return (\r\n \r\n {formatDate(v.trans_date)} | \r\n {v.source} | \r\n \r\n \r\n | \r\n {/* {link.length ? { e.preventDefault(); history.push(link) }}>{v.desc} : v.desc} | */}\r\n {v.reference} | \r\n {v.ref_number} | \r\n \r\n {v.debit > -1\r\n ? currency(v.debit, false, true, true)\r\n : `(${currency(v.debit, false, true, true)})`.replace('-', '')}\r\n | \r\n {currency(v.credit, false, true, true)} | \r\n {!params.cashFlowDetail ? (\r\n \r\n {v.balance > -1\r\n ? currency(v.balance, false, true, true)\r\n : `(${currency(v.balance, false, true, true)})`.replace('-', '')}\r\n | \r\n ) : null}\r\n
\r\n )\r\n })}\r\n \r\n \r\n {intl.formatMessage({ id: 'report.closing_balance' })}\r\n | \r\n \r\n \r\n {data[item].closing_debit > -1\r\n ? currency(data[item].closing_debit, false, true, true)\r\n : `(${currency(data[item].closing_debit, false, true, true)})`.replace('-', '')}\r\n \r\n | \r\n \r\n {currency(data[item].closing_credit, false, true, true)}\r\n | \r\n {!params.cashFlowDetail ? (\r\n \r\n \r\n {data[item].closing_balance > -1\r\n ? currency(data[item].closing_balance, false, true, true)\r\n : `(${currency(data[item].closing_balance, false, true, true)})`.replace(\r\n '-',\r\n '',\r\n )}\r\n \r\n | \r\n ) : null}\r\n
\r\n {(Object.keys(data) || []).length !== index + 1 && (\r\n \r\n | \r\n
\r\n )}\r\n ,\r\n )\r\n })\r\n body.push(\r\n \r\n \r\n \r\n {intl.formatMessage({ id: 'report.opening_balance' })}\r\n | \r\n \r\n \r\n {data[item].opening_debit > -1\r\n ? currency(data[item].opening_debit, false, true, true)\r\n : `(${currency(data[item].opening_debit, false, true, true)})`.replace('-', '')}\r\n \r\n | \r\n \r\n {currency(data[item].opening_credit, false, true, true)}\r\n | \r\n \r\n \r\n {data[item].opening_balance > -1\r\n ? currency(data[item].opening_balance, false, true, true)\r\n : `(${currency(data[item].opening_balance, false, true, true)})`.replace('-', '')}\r\n \r\n | \r\n
\r\n {(data[item].data || []).map((v) => {\r\n return (\r\n \r\n {dayjs(v.trans_date, 'YYYY-MM-DD').format(formatDateText())} | \r\n {v.source} | \r\n \r\n \r\n | \r\n {v.reference} | \r\n {v.ref_number} | \r\n \r\n {v.debit > -1\r\n ? currency(v.debit, false, true, true)\r\n : `(${currency(v.debit, false, true, true)})`.replace('-', '')}\r\n | \r\n {currency(v.credit, false, true, true)} | \r\n \r\n {v.valid === false ? (\r\n \r\n \r\n \r\n ) : v.balance > -1 ? (\r\n currency(v.balance, false, true, true)\r\n ) : (\r\n `(${currency(v.balance, false, true, true)})`.replace('-', '')\r\n )}\r\n | \r\n
\r\n )\r\n })}\r\n \r\n \r\n {intl.formatMessage({ id: 'report.closing_balance' })}\r\n | \r\n \r\n \r\n {data[item].closing_debit > -1\r\n ? currency(data[item].closing_debit, false, true, true)\r\n : `(${currency(data[item].closing_debit, false, true, true)})`.replace('-', '')}\r\n \r\n | \r\n \r\n {currency(data[item].closing_credit, false, true, true)}\r\n | \r\n \r\n \r\n {data[item].closing_balance > -1\r\n ? currency(data[item].closing_balance, false, true, true)\r\n : `(${currency(data[item].closing_balance, false, true, true)})`.replace('-', '')}\r\n \r\n | \r\n
\r\n {(Object.keys(data) || []).length !== index + 1 && (\r\n \r\n | \r\n
\r\n )}\r\n ,\r\n )\r\n })\r\n body.push(\r\n }\r\n content={() => this.print}\r\n removeAfterPrint\r\n />,\r\n ]}\r\n />\r\n \r\n {showGraph ? : null}\r\n {this.state.summary ? (\r\n this.renderLoading()\r\n ) : (\r\n \r\n \r\n
\r\n
\r\n {loading && (\r\n
\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n
\r\n )}\r\n
\r\n \r\n
\r\n
\r\n
\r\n \r\n {header}
\r\n \r\n {body}\r\n
\r\n
\r\n {!body.length && (\r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n {intl.formatMessage({ id: 'report.no_data' })}\r\n
\r\n
\r\n
\r\n )}\r\n
\r\n
\r\n \r\n
\r\n
\r\n
\r\n {total > per_page && (\r\n \r\n
\r\n this.setState({ page: _page, per_page: _per_page }, this.loadData)\r\n }\r\n total={total || 0}\r\n showSizeChanger\r\n />\r\n \r\n )}\r\n \r\n )}\r\n {/* not use display: none to prevent this error */}\r\n {/* Uncaught DOMException: Failed to execute 'drawImage' on 'CanvasRenderingContext2D': The image argument is a canvas element with a width or height of 0. */}\r\n \r\n
{\r\n this.print = el\r\n }}\r\n data={data}\r\n columns={columns}\r\n header={pageHeader}\r\n journalTotal={journal_total}\r\n params={this.props.params}\r\n getParams={this.getParams}\r\n showGraph={showGraph}\r\n />\r\n \r\n >\r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = (state) => {\r\n return {\r\n isMobileView: state.settings.isMobileView,\r\n loadedInit: state.inits.loadedInit,\r\n show: state.finance.accountTransactionReport.show,\r\n }\r\n}\r\n\r\nexport default connect(mapStateToProps)(injectIntl(AccountTransactionsReports))\r\n","// antd theme settings\r\n// you should restart dev server after variables changes\r\n// ref: https://github.com/ant-design/ant-design/blob/master/components/style/themes/default.less\r\nmodule.exports = {\r\n '@body-background': '#f2f4f8',\r\n '@font-size-base': '13px',\r\n '@font-size-lg': '15px',\r\n\r\n '@font-family': 'Nunito Sans, sans-serif',\r\n '@code-family': 'Nunito Sans, sans-serif',\r\n\r\n '@border-color-base': '#e4e9f0',\r\n\r\n '@background-color-light': '#f2f4f8',\r\n '@background-color-base': '#f2f4f8',\r\n\r\n '@primary-color': '#0190fe',\r\n '@info-color': '#0887c9',\r\n '@success-color': '#46be8a',\r\n '@error-color': '#fb434a',\r\n '@highlight-color': '#fb434a',\r\n '@warning-color': '#f39834',\r\n '@normal-color': '#e4e9f0',\r\n\r\n '@input-padding-horizontal': '13px',\r\n '@input-padding-vertical-base': '7px',\r\n '@input-padding-vertical-sm': '11px',\r\n '@input-padding-vertical-lg': '11px',\r\n '@input-border-color': '#e4e9f0',\r\n '@input-hover-border-color': '#0190fe',\r\n\r\n '@shadow-color': 'rgba(0,0,0,.15)',\r\n '@box-shadow-base': '0 10px 35px -5px rgba(0,0,0,.15)',\r\n '@shadow-1-up': '0 -10px 35px -5px rgba(0,0,0,.15)',\r\n '@shadow-1-down': '0 10px 35px -5px rgba(0,0,0,.15)',\r\n '@shadow-1-left': '-10px 10px 35px -5px rgba(0,0,0,.15)',\r\n '@shadow-1-right': '10px 0 35px -5px rgba(0,0,0,.15)',\r\n '@shadow-2': '0 0px 35px -5px rgba(0,0,0,.15)',\r\n\r\n '@table-header-bg': '#f2f4f8',\r\n '@table-header-sort-bg': '#f2f4f8',\r\n '@table-row-hover-bg': '#e4e9f0',\r\n '@table-padding-vertical': '12px',\r\n '@table-padding-horizontal': '8px',\r\n\r\n '@modal-mask-bg': 'rgba(15, 12, 41, 0.5)',\r\n}\r\n","import React, { Component } from 'react'\r\nimport { connect } from 'react-redux'\r\nimport store from 'store'\r\nimport Router from 'router'\r\nimport { ClearBrowserCacheBoundary } from 'react-clear-browser-cache'\r\nimport SentryErrorBoundary from 'components/SentryErrorBoundary'\r\nimport { initializeFp } from 'utils/gtm'\r\nimport { changeLayoutSetting } from 'redux/settings/actions'\r\nimport InstallPromptWrapper from './InstallPromptWrapper'\r\nimport UpdateAppWrapper from './UpdateAppWrapper'\r\nimport { ServiceWorkerProvider } from './ServiceWorkerProvider'\r\n\r\nclass App extends Component {\r\n async componentDidMount() {\r\n this.setLayoutView(true)\r\n window.addEventListener('resize', () => {\r\n this.setLayoutView()\r\n })\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n // Reinitialize facebook pixel\r\n if (prevProps.user !== this.props.user) {\r\n if (process.env.NODE_ENV === 'production') {\r\n initializeFp(this.props.user.email)\r\n }\r\n }\r\n }\r\n\r\n componentWillUnmount() {\r\n window.removeEventListener('resize', this.setLayoutView)\r\n }\r\n\r\n setLayoutView = (load = false) => {\r\n const windowWidth = global.window.innerWidth\r\n const currentMobileState = windowWidth < 768\r\n const prevMobileState = store.get('app.settings.isMobileView')\r\n const currentTabState = windowWidth >= 768 && windowWidth <= 992\r\n const prevTabState = store.get('app.settings.isTabView')\r\n\r\n if (currentMobileState !== prevMobileState || currentTabState !== prevTabState || load) {\r\n this.props.onChangeLayoutSetting({\r\n isMobileView: currentMobileState,\r\n isTabView: currentTabState,\r\n })\r\n }\r\n }\r\n\r\n render() {\r\n const { history, user } = this.props\r\n const appComponent = (\r\n <>\r\n \r\n \r\n \r\n >\r\n )\r\n\r\n return (\r\n \r\n \r\n {window.Cypress ? (\r\n appComponent\r\n ) : (\r\n {appComponent}\r\n )}\r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nconst mapStateToProps = ({ user }) => ({\r\n user,\r\n})\r\n\r\nconst mapDispatchToProps = (dispatch) => {\r\n return {\r\n onChangeLayoutSetting: (payload) => dispatch(changeLayoutSetting(payload)),\r\n }\r\n}\r\n\r\nexport default connect(mapStateToProps, mapDispatchToProps)(App)\r\n","// extracted by mini-css-extract-plugin\nmodule.exports = {\"legendText\":\"chart-legend_legendText__1rqCN\"};","// extracted by mini-css-extract-plugin\nmodule.exports = {\"tag\":\"tag-suggestion_tag__1AMf4\",\"dark\":\"tag-suggestion_dark__1lXyV\"};","import React from 'react'\r\nimport * as Sentry from '@sentry/react'\r\nimport { Result, Button, Typography } from 'antd'\r\nimport { CloseCircleOutlined } from '@ant-design/icons'\r\n\r\nconst { Paragraph, Text } = Typography\r\n\r\nfunction SentryErrorBoundary({ children, ...props }) {\r\n return (\r\n (\r\n {\r\n window.location.reload()\r\n }}\r\n >\r\n Reload\r\n ,\r\n ,\r\n ]}\r\n >\r\n \r\n
\r\n \r\n Maaf, ditemukan masalah saat Anda menggunakan aplikasi Kledo:\r\n \r\n \r\n
\r\n {error.toString()}\r\n \r\n
{componentStack}\r\n
\r\n \r\n )}\r\n {...props}\r\n >\r\n {children}\r\n \r\n )\r\n}\r\n\r\nexport default SentryErrorBoundary\r\n","import React, { useEffect } from 'react'\r\nimport { injectIntl } from 'react-intl'\r\nimport { Button, Space } from 'antd'\r\n\r\nimport { getMobileOperatingSystem } from 'utils/helper'\r\nimport { useSelector } from \"react-redux\";\r\nimport { darkModeSelector } from \"redux/selectors\";\r\n\r\nconst InstallPromptWrapper = ({ intl }) => {\r\n const [visible, setVisible] = React.useState(false)\r\n const [platform, setPlatform] = React.useState()\r\n const darkMode = useSelector(darkModeSelector)\r\n\r\n useEffect(() => {\r\n if (getMobileOperatingSystem() === 'android') {\r\n setVisible(true)\r\n setPlatform('android')\r\n }\r\n if (getMobileOperatingSystem() === 'ios') {\r\n setVisible(true)\r\n setPlatform('ios')\r\n }\r\n }, [])\r\n\r\n return (\r\n \r\n
\r\n {intl.formatMessage({\r\n id:\r\n platform === 'ios'\r\n ? 'notification.kledo_is_now_on_app_store'\r\n : 'notification.kledo_is_now_on_google_play',\r\n })}\r\n
\r\n \r\n \r\n \r\n \r\n \r\n )\r\n}\r\n\r\nexport default injectIntl(InstallPromptWrapper)\r\n","import React from 'react'\r\nimport { withRouter } from 'react-router-dom'\r\n\r\n@withRouter\r\nclass PublicLayout extends React.PureComponent {\r\n render() {\r\n const { children } = this.props\r\n return children\r\n }\r\n}\r\n\r\nexport default PublicLayout\r\n","import { Checkbox, Form, Input, Modal, message, Typography } from 'antd'\r\nimport Axios from 'axios'\r\nimport { Cancel, Reset, Save } from 'components/UI'\r\nimport React, { useCallback, useMemo } from 'react'\r\nimport { useQueryClient } from 'react-query'\r\nimport localStore from 'store'\r\nimport { generateBaseUri } from 'utils/helper'\r\n\r\nconst ChangeEnvModal = ({ visible, onCancel }) => {\r\n const queryClient = useQueryClient()\r\n\r\n const initialValues = useMemo(() => {\r\n const isOverwriteBaseUrl = localStore.get('app.isOverwriteBaseUrl')\r\n return {\r\n base_url: localStore.get('app.bypassEndpoint') || process.env.REACT_APP_API_URL,\r\n overwrite_baseurl: typeof isOverwriteBaseUrl !== 'undefined' ? isOverwriteBaseUrl : true,\r\n }\r\n }, [])\r\n\r\n const submitHandler = useCallback(\r\n (values) => {\r\n localStore.set('app.bypassEndpoint', values.base_url)\r\n localStore.set('app.isOverwriteBaseUrl', values.overwrite_baseurl)\r\n queryClient.clear()\r\n Axios.defaults.baseURL = values.base_url\r\n message.success('Base URL berhasil diganti')\r\n onCancel()\r\n },\r\n [onCancel, queryClient],\r\n )\r\n\r\n const resetHandler = useCallback(() => {\r\n localStore.set('app.bypassEndpoint', '')\r\n localStore.set('app.isOverwriteBaseUrl', false)\r\n queryClient.clear()\r\n Axios.defaults.baseURL = generateBaseUri()\r\n message.success('Base URL berhasil direset')\r\n onCancel()\r\n }, [onCancel, queryClient])\r\n\r\n return (\r\n ,\r\n ,\r\n ,\r\n ]}\r\n >\r\n \r\n \r\n \r\n \r\n \r\n \r\n Jika dicentang, hanya berlaku untuk login yang memiliki 1 perusahaan. Overwrite disini\r\n artinyaa baseurl yang diinputkan akan mengganti endpoint di response init.\r\n \r\n \r\n \r\n \r\n \r\n )\r\n}\r\n\r\nexport default ChangeEnvModal\r\n","import React from 'react'\r\nimport { injectIntl } from 'react-intl'\r\nimport { Alert, Layout } from 'antd'\r\nimport { withRouter } from 'react-router-dom'\r\nimport { connect } from 'react-redux'\r\nimport { isEmpty } from 'lodash'\r\nimport store from 'store'\r\nimport NProgress from 'nprogress'\r\nimport dayjs from 'dayjs'\r\n\r\nimport { initsPublic } from 'redux/actions'\r\nimport { changeSetting } from 'redux/settings/actions'\r\nimport { hideLoginForm } from 'redux/user/actions'\r\nimport ChangeEnvModal from 'components/apps/User/ChangeEnvModal'\r\nimport { allowedLocales } from 'utils/static'\r\nimport styles from './style.module.scss'\r\n\r\nconst mapDispatchToProps = (dispatch) => {\r\n return {\r\n onInits: () => dispatch(initsPublic()),\r\n onChangeSetting: (payload) => dispatch(changeSetting(payload)),\r\n hideLoginModal: () => dispatch(hideLoginForm()),\r\n }\r\n}\r\n\r\nconst mapStateToProps = ({ options: { options }, inits: { loading }, settings: { locale } }) => ({\r\n property: options,\r\n loading,\r\n locale,\r\n})\r\n\r\n@withRouter\r\n@connect(mapStateToProps, mapDispatchToProps)\r\nclass LoginLayout extends React.PureComponent {\r\n state = {\r\n backgroundNumber: 7,\r\n backgroundEnabled: false,\r\n networkErr: false,\r\n countClick: 0,\r\n showEnvModal: false,\r\n }\r\n\r\n componentDidMount() {\r\n const { property, locale, onChangeSetting } = this.props\r\n this.props.hideLoginModal()\r\n store.remove('app.endpoint')\r\n this.onInit()\r\n if (!isEmpty(property) && locale !== property.property_language) {\r\n onChangeSetting({\r\n setting: 'locale',\r\n value: locale && allowedLocales.includes(locale) ? locale : property.property_language,\r\n })\r\n }\r\n }\r\n\r\n onInit = async () => {\r\n const { onInits } = this.props\r\n const r = await onInits()\r\n if (r === false) {\r\n this.setState({ networkErr: true })\r\n }\r\n }\r\n\r\n changeBackground = () => {\r\n const { backgroundNumber } = this.state\r\n this.setState({\r\n backgroundEnabled: true,\r\n backgroundNumber: backgroundNumber === 5 ? 1 : backgroundNumber + 1,\r\n })\r\n }\r\n\r\n toggleBackground = () => {\r\n const { backgroundEnabled } = this.state\r\n this.setState({\r\n backgroundEnabled: !backgroundEnabled,\r\n })\r\n }\r\n\r\n renderLogo = () => {\r\n const { backgroundEnabled } = this.state\r\n const { property } = this.props\r\n if (backgroundEnabled) {\r\n if (!isEmpty(property.property_logo)) {\r\n return
\r\n }\r\n\r\n return
\r\n }\r\n\r\n return
\r\n }\r\n\r\n clickLayout = () => {\r\n this.setState((prevState) => {\r\n const countClick = prevState.countClick + 1\r\n return { ...prevState, countClick, showEnvModal: countClick > 10 }\r\n })\r\n }\r\n\r\n closeEnvModal = () => this.setState({ countClick: 0, showEnvModal: false })\r\n\r\n render() {\r\n const { children, loading, intl } = this.props\r\n const { backgroundNumber, backgroundEnabled, networkErr, showEnvModal } = this.state\r\n\r\n if (loading) {\r\n NProgress.start()\r\n } else {\r\n NProgress.done()\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n
\r\n {networkErr ? (\r\n
\r\n ) : (\r\n children\r\n )}\r\n
\r\n
\r\n
\r\n\r\n
©{` ${dayjs().format('YYYY')} Kledo. All rights reserved.`}
\r\n
\r\n
\r\n \r\n {showEnvModal && }\r\n \r\n )\r\n }\r\n}\r\n\r\nexport default injectIntl(LoginLayout)\r\n","import React from 'react'\r\nimport { connect } from 'react-redux'\r\nimport { UserOutlined } from '@ant-design/icons'\r\nimport { Avatar, Dropdown, Menu } from 'antd'\r\nimport { FormattedMessage, injectIntl } from 'react-intl'\r\nimport { Link } from 'react-router-dom'\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\r\nimport { push } from 'connected-react-router'\r\n\r\nimport { logout } from 'redux/user/actions'\r\nimport { checkPermission } from 'redux/user/selectors'\r\nimport { formatDate } from 'utils/formatting'\r\nimport { Upgrade } from 'components/UI/Button'\r\n\r\nimport styles from './style.module.scss'\r\n\r\n@connect(\r\n (state) => {\r\n return {\r\n user: state.user,\r\n billing: state.billing,\r\n hasAccessToBilling: checkPermission(state, 'billing'),\r\n }\r\n },\r\n (dispatch) => {\r\n return {\r\n onLogout: () => dispatch(logout()),\r\n push: (path) => dispatch(push(path)),\r\n }\r\n },\r\n)\r\nclass ProfileMenu extends React.Component {\r\n logout = async (e) => {\r\n e.preventDefault()\r\n await this.props.onLogout()\r\n this.props.push('/user/login')\r\n }\r\n\r\n goToUpgradeHandler = () => {\r\n if (this.props.billing.can_be_renewed) {\r\n this.props.push('/settings/billing/upgrade?isRenew=1')\r\n return\r\n }\r\n this.props.push('/settings/billing/upgrade')\r\n }\r\n\r\n render() {\r\n const { user, billing, intl, hasAccessToBilling } = this.props\r\n const items = [\r\n {\r\n key: 'topBar.profileMenu.hello',\r\n label: (\r\n \r\n \r\n , {user.name || 'Anonymous'}\r\n \r\n \r\n ),\r\n },\r\n {\r\n key: 'divider-1',\r\n type: 'divider',\r\n },\r\n {\r\n key: 'topBar.billing.plan',\r\n label: (\r\n <>\r\n \r\n :{' '}\r\n \r\n {billing.plan}\r\n
\r\n \r\n :{' '}\r\n \r\n {billing.expiry_date ? (\r\n formatDate(new Date(billing.expiry_date).setDate(new Date(billing.expiry_date).getDate() - 1))\r\n ) : (\r\n \r\n )}\r\n
\r\n {(billing.can_be_upgraded || billing.can_be_renewed) && hasAccessToBilling && (\r\n \r\n )}\r\n >\r\n ),\r\n },\r\n {\r\n key: 'divider-2',\r\n type: 'divider',\r\n },\r\n {\r\n key: 'topBar.profileMenu.email',\r\n label: (\r\n \r\n \r\n \r\n :{' '}\r\n \r\n {user.email}\r\n
\r\n \r\n :{' '}\r\n \r\n {user.phone_number || '-'}\r\n
\r\n \r\n ),\r\n },\r\n {\r\n key: 'divider-3',\r\n type: 'divider',\r\n },\r\n {\r\n key: 'referral',\r\n label: (\r\n \r\n \r\n \r\n ),\r\n icon: ,\r\n },\r\n {\r\n key: 'divider-4',\r\n type: 'divider',\r\n },\r\n {\r\n key: 'profile.profile',\r\n label: (\r\n \r\n \r\n \r\n ),\r\n icon: ,\r\n },\r\n {\r\n key: 'divider-5',\r\n type: 'divider',\r\n },\r\n {\r\n key: 'topBar.profileMenu.logout',\r\n label: (\r\n \r\n \r\n \r\n ),\r\n icon: ,\r\n },\r\n ]\r\n const menu = \r\n return (\r\n (menu)} trigger={['click']}>\r\n \r\n
}\r\n src={user.profile_image}\r\n />\r\n
\r\n \r\n )\r\n }\r\n}\r\n\r\nexport default injectIntl(ProfileMenu)\r\n","import React from 'react'\r\nimport { Dropdown, Menu, Tooltip } from 'antd'\r\nimport { connect } from 'react-redux'\r\nimport { injectIntl } from 'react-intl'\r\n\r\nimport { changeLanguage } from 'redux/settings/actions'\r\nimport styles from './style.module.scss'\r\n\r\n@connect(\r\n ({ settings, refs: { lang } }) => ({ settings, lang }),\r\n (dispatch) => {\r\n return {\r\n onChangeLanguage: (payload) => dispatch(changeLanguage(payload)),\r\n }\r\n },\r\n)\r\nclass LanguageSelector extends React.PureComponent {\r\n state = {\r\n visibleDropdown: false,\r\n }\r\n\r\n changeLang = ({ key }) => {\r\n const {\r\n onChangeLanguage,\r\n settings: { locale },\r\n } = this.props\r\n if (locale !== key) {\r\n onChangeLanguage({\r\n setting: 'locale',\r\n value: key,\r\n })\r\n }\r\n }\r\n\r\n render() {\r\n const {\r\n settings: { locale },\r\n intl,\r\n } = this.props\r\n const language = locale.substr(0, 2)\r\n const items = this.props.lang.map((item) => {\r\n return {\r\n key: item.value,\r\n label: (\r\n <>\r\n \r\n {item.value.substr(0, 2)}\r\n \r\n {item.name}\r\n >\r\n ),\r\n }\r\n })\r\n\r\n const langMenu = (\r\n \r\n )\r\n return (\r\n \r\n this.setState({ visibleDropdown: visible })}\r\n dropdownRender={() => (langMenu)}\r\n trigger={['click']}\r\n >\r\n \r\n {language}\r\n
\r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nexport default injectIntl(LanguageSelector)\r\n","import React, { useCallback, useEffect, useMemo } from 'react'\r\nimport { Dropdown, Menu } from 'antd'\r\nimport { injectIntl } from 'react-intl'\r\nimport { useDispatch } from 'react-redux'\r\nimport { push } from 'connected-react-router'\r\nimport { useQueryClient } from 'react-query'\r\n\r\nimport { useResponsive } from 'utils/hooks'\r\nimport styles from './style.module.scss'\r\n\r\nconst CompanySelector = ({ onChangeCompany, companies, intl }) => {\r\n const { isMobileView } = useResponsive()\r\n const dispatch = useDispatch()\r\n const queryClient = useQueryClient()\r\n\r\n useEffect(() => {\r\n const header = document.querySelector('header.ant-layout-header')\r\n\r\n if (!header) return\r\n\r\n if (isMobileView) header.classList.add(styles.lineHeightInherit)\r\n else header.classList.remove(styles.lineHeightInherit)\r\n }, [isMobileView])\r\n\r\n const changeCompany = useCallback(\r\n ({ key }) => {\r\n if (key === 'list') {\r\n dispatch(push('/companies'))\r\n } else if (key === 'add') {\r\n dispatch(push('/companies/add'))\r\n } else if (companies.selectedEndpoint !== key) {\r\n onChangeCompany(key, () => {\r\n // Clear all cache from react-query to prevent sharing cache data between company.\r\n // Sharing cache data will cause current company use last cache data from previous company\r\n // until current fetching success\r\n queryClient.clear()\r\n })\r\n }\r\n },\r\n [companies, dispatch, onChangeCompany, queryClient],\r\n )\r\n\r\n const selectedCompany = useMemo(\r\n () => companies.companies.filter((e) => e.endpoint === companies.selectedEndpoint),\r\n [companies],\r\n )\r\n\r\n const items = useMemo(() => {\r\n const newItems = companies.companies.map((item) => {\r\n return {\r\n key: item.endpoint,\r\n label: item.name,\r\n }\r\n })\r\n newItems.push({\r\n type: 'divider',\r\n key: Math.random(),\r\n })\r\n if (companies.companies.length > 1) {\r\n newItems.push({\r\n key: 'list',\r\n label: intl.formatMessage({ id: 'companies.company_list' }),\r\n })\r\n } else {\r\n newItems.push({\r\n key: 'add',\r\n label: intl.formatMessage({ id: 'companies.add_company' }),\r\n })\r\n }\r\n return newItems\r\n }, [companies, intl])\r\n\r\n const langMenu = (\r\n \r\n )\r\n return (\r\n (langMenu)}\r\n trigger={['click']}\r\n >\r\n \r\n \r\n {selectedCompany[0] ? selectedCompany[0].name : ''}\r\n \r\n
\r\n \r\n )\r\n}\r\n\r\nexport default injectIntl(CompanySelector)\r\n","import React from 'react'\r\nimport { List, Typography, Skeleton } from 'antd'\r\nimport InfiniteScroll from 'react-infinite-scroller'\r\nimport _ from 'lodash'\r\nimport dayjs from 'dayjs'\r\nimport { Spinner } from 'components/UI'\r\nimport Player from 'components/UI/ModalPlayer/Player'\r\nimport style from './style.module.scss'\r\n\r\nconst relativeTime = require('dayjs/plugin/relativeTime')\r\n\r\ndayjs.extend(relativeTime)\r\n\r\nconst Media = ({ videoId, imageUrl, title }) => {\r\n if (!_.isEmpty(videoId)) {\r\n return (\r\n \r\n )\r\n }\r\n\r\n if (!_.isEmpty(imageUrl) && _.isEmpty(videoId)) {\r\n return (\r\n \r\n

\r\n
\r\n )\r\n }\r\n\r\n return null\r\n}\r\n\r\nconst News = ({ loading, data, onLoadMore, hasMore, loadingMore }) => {\r\n return (\r\n \r\n \r\n (\r\n \r\n \r\n
\r\n
\r\n
{item.title}
\r\n
\r\n \r\n {dayjs(item.created_at).fromNow()}\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n )}\r\n />\r\n
\r\n \r\n \r\n
\r\n \r\n )\r\n}\r\n\r\nexport default News\r\n","import React from 'react';\r\nimport { message } from 'antd';\r\n\r\nimport News from 'components/apps/Notification/News';\r\nimport {getNews} from 'utils/apis';\r\n\r\nconst NewsContainer = () => {\r\n const [data, setData] = React.useState({});\r\n const [loading, setLoading] = React.useState(false);\r\n const [loadingMore, setLoadingMore] = React.useState(false);\r\n const [hasMore, setHasMore] = React.useState(true);\r\n\r\n const loadData = React.useCallback((mounted) => {\r\n setLoading(true);\r\n getNews().then(response => {\r\n if (mounted) {\r\n if (response.data.success) {\r\n setData(response.data.data);\r\n setLoading(false);\r\n } else {\r\n message.error(response.data.message);\r\n }\r\n setLoading(false);\r\n }\r\n }).catch(() => {\r\n if (mounted) {\r\n setLoading(false);\r\n }\r\n });\r\n }, []);\r\n\r\n const onLoadMore = React.useCallback((page) => {\r\n if (page >= data.last_page) {\r\n setHasMore(false);\r\n }\r\n else {\r\n setLoadingMore(true);\r\n getNews({page}).then(response => {\r\n if (response.data.success) {\r\n const resData = response.data.data;\r\n setData({\r\n ...resData,\r\n data: [\r\n ...data.data,\r\n ...resData.data\r\n ]\r\n });\r\n } else {\r\n message.error(response.data.message);\r\n }\r\n setLoadingMore(false);\r\n }).catch(() => {\r\n setLoadingMore(false);\r\n });\r\n }\r\n }, [data]);\r\n\r\n React.useEffect(() => {\r\n let mounted = true;\r\n loadData(mounted);\r\n return () => { mounted = false };\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, []);\r\n\r\n return (\r\n \r\n );\r\n};\r\n\r\nexport default NewsContainer;","import React from 'react'\r\nimport { Dropdown, Tooltip } from 'antd'\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\r\nimport { injectIntl } from 'react-intl'\r\n\r\nimport News from 'containers/Notification/News'\r\nimport { useResponsive } from 'utils/hooks'\r\nimport { useSelector } from \"react-redux\";\r\nimport { darkModeSelector } from \"redux/selectors\";\r\nimport styles from './style.module.scss'\r\n\r\nconst Actions = ({ intl }) => {\r\n const [visible, setVisible] = React.useState(false)\r\n const darkMode = useSelector(darkModeSelector)\r\n\r\n const { isMobileView } = useResponsive()\r\n\r\n const visibleChangeHandler = (flag) => setVisible(flag)\r\n\r\n const stylePane = { height: 400, overflow: 'auto' }\r\n if (!isMobileView) {\r\n stylePane.width = 400\r\n }\r\n\r\n const menu = (\r\n \r\n )\r\n return (\r\n \r\n (menu)}\r\n trigger={['click']}\r\n placement=\"bottomLeft\"\r\n open={visible}\r\n onOpenChange={visibleChangeHandler}\r\n >\r\n \r\n \r\n
\r\n \r\n \r\n )\r\n}\r\n\r\nexport default injectIntl(Actions)\r\n","import { LoadingOutlined } from '@ant-design/icons'\r\nimport { Divider, Space, Typography } from 'antd'\r\nimport React, { memo } from 'react'\r\nimport { injectIntl } from 'react-intl'\r\nimport { useSelector } from 'react-redux'\r\nimport { loadedInitSelector } from 'redux/selectors'\r\nimport { qtyToCurrency } from 'utils/formatting'\r\nimport { useQueues } from 'utils/queries/queue'\r\n\r\nconst { Text } = Typography\r\n\r\nconst QueueStats = ({ enabled, intl }) => {\r\n const loadedInit = useSelector(loadedInitSelector)\r\n // direfetch 2 detik\r\n const { data } = useQueues({ enabled: loadedInit && enabled, refetchInterval: 2000 })\r\n // tidak ditampilkan jika <= 1\r\n if (!data || data?.data <= 1) {\r\n return null\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n \r\n {intl.formatMessage(\r\n { id: 'queue.data_is_waiting_to_be_processed' },\r\n { value: qtyToCurrency(data?.data || 0) },\r\n )}\r\n \r\n \r\n \r\n )\r\n}\r\n\r\nexport default memo(injectIntl(QueueStats))\r\n","import { useQuery } from 'react-query'\r\n\r\nimport { getQueues } from 'utils/apis/queue'\r\n\r\nexport function useQueues(options = {}) {\r\n return useQuery(\r\n ['queues'],\r\n async () => {\r\n let response\r\n try {\r\n const { data } = await getQueues()\r\n response = data\r\n } catch (error) {\r\n throw new Error('Failed to load data from server!')\r\n }\r\n return response\r\n },\r\n options,\r\n )\r\n}\r\n","import React from 'react'\r\nimport { message } from 'antd'\r\n\r\nimport Timeline from 'components/apps/Notification/Timeline'\r\nimport HideFeature from \"containers/Billing/HideFeature\"\r\nimport { getFinanceLogs } from 'utils/apis'\r\nimport { isFeaturePro } from \"utils/helper\";\r\nimport { useSelector } from \"react-redux\";\r\nimport { billingSelector } from 'redux/selectors'\r\nimport { injectIntl } from \"react-intl\";\r\n\r\nconst TimelineContainer = ({ isReload, onHideParent, isMobileView, intl }) => {\r\n const [data, setData] = React.useState({})\r\n const [loading, setLoading] = React.useState(false)\r\n const [loadingMore, setLoadingMore] = React.useState(false)\r\n const [hasMore, setHasMore] = React.useState(true)\r\n const billing = useSelector(billingSelector)\r\n const isPaidFeature = isFeaturePro({billing, code: 'settings.audit'})\r\n\r\n const loadData = React.useCallback((mounted) => {\r\n setLoading(true)\r\n getFinanceLogs()\r\n .then((response) => {\r\n if (mounted) {\r\n if (response.data.success) {\r\n setData(response.data.data)\r\n setLoading(false)\r\n } else {\r\n message.error(response.data.message)\r\n }\r\n setLoading(false)\r\n }\r\n })\r\n .catch(() => {\r\n if (mounted) {\r\n setLoading(false)\r\n }\r\n })\r\n }, [])\r\n\r\n const onLoadMore = React.useCallback(\r\n (page) => {\r\n if (page >= data.last_page) {\r\n setHasMore(false)\r\n } else {\r\n setLoadingMore(true)\r\n getFinanceLogs({ page })\r\n .then((response) => {\r\n if (response.data.success) {\r\n const resData = response.data.data\r\n setData({\r\n ...resData,\r\n data: [...data.data, ...resData.data],\r\n })\r\n } else {\r\n message.error(response.data.message)\r\n }\r\n setLoadingMore(false)\r\n })\r\n .catch(() => {\r\n setLoadingMore(false)\r\n })\r\n }\r\n },\r\n [data],\r\n )\r\n\r\n React.useEffect(() => {\r\n let mounted = true\r\n if (isReload) {\r\n loadData(mounted)\r\n }\r\n return () => {\r\n mounted = false\r\n }\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [isReload])\r\n\r\n return (\r\n <>\r\n \r\n \r\n
\r\n {!loading && }\r\n >\r\n )\r\n}\r\n\r\nexport default injectIntl(TimelineContainer)\r\n","import React from 'react'\r\nimport { Dropdown, Tooltip } from 'antd'\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\r\nimport { injectIntl } from 'react-intl'\r\n\r\nimport QueueStats from 'components/apps/Notification/QueueStats'\r\nimport Timeline from 'containers/Notification/Timeline'\r\nimport { useResponsive } from 'utils/hooks'\r\nimport { useSelector } from \"react-redux\";\r\nimport { darkModeSelector } from \"redux/selectors\";\r\nimport styles from './style.module.scss'\r\n\r\nconst Timelines = ({ intl }) => {\r\n const [visible, setVisible] = React.useState(false)\r\n const darkMode = useSelector(darkModeSelector)\r\n\r\n const { isMobileView } = useResponsive()\r\n\r\n const visibleChangeHandler = (flag) => setVisible(flag)\r\n const hideHandler = () => setVisible(false)\r\n\r\n const stylePane = { height: 400, overflow: 'auto' }\r\n if (!isMobileView) {\r\n stylePane.width = 400\r\n }\r\n\r\n const menu = (\r\n \r\n )\r\n return (\r\n \r\n (menu)}\r\n trigger={['click']}\r\n placement=\"bottomLeft\"\r\n open={visible}\r\n onOpenChange={visibleChangeHandler}\r\n >\r\n \r\n \r\n
\r\n \r\n \r\n )\r\n}\r\n\r\nexport default injectIntl(Timelines)\r\n","import React, { useCallback } from 'react'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\nimport { Switch, Tooltip } from 'antd'\r\nimport { MoonFilled, SunFilled } from '@ant-design/icons'\r\nimport store from 'store'\r\nimport { injectIntl } from 'react-intl'\r\n\r\nimport { optionsSelector } from 'redux/selectors'\r\nimport { useEditOptionThemeColors } from 'utils/queries/options'\r\nimport { editOptionsRedux } from 'redux/options/actions'\r\n\r\nconst ThemeColors = ({ intl }) => {\r\n const dispatch = useDispatch()\r\n const options = useSelector(optionsSelector)\r\n const isDarkMode = options?.dark_mode === 1\r\n\r\n const editOptionThemeColors = useEditOptionThemeColors()\r\n\r\n const changeThemeHandler = useCallback(\r\n (value) => {\r\n dispatch(editOptionsRedux({ dark_mode: value ? 1 : 0 }))\r\n editOptionThemeColors.mutate(\r\n { dark_mode: value ? 1 : 0 },\r\n {\r\n onSuccess: (response) => {\r\n if (response.data.success) {\r\n if (value) {\r\n store.set('app.darkMode', value ? 1 : 0)\r\n } else {\r\n store.remove('app.darkMode')\r\n }\r\n } else {\r\n dispatch(editOptionsRedux({ dark_mode: value ? 0 : 1 }))\r\n }\r\n },\r\n },\r\n )\r\n },\r\n [dispatch, editOptionThemeColors],\r\n )\r\n\r\n return (\r\n <>\r\n \r\n \r\n }\r\n unCheckedChildren={}\r\n checked={options?.dark_mode === 1}\r\n onChange={changeThemeHandler}\r\n disabled={editOptionThemeColors.isLoading}\r\n loading={editOptionThemeColors.isLoading}\r\n />\r\n
\r\n \r\n >\r\n )\r\n}\r\n\r\nexport default injectIntl(ThemeColors)\r\n","import React from 'react'\r\nimport { Button, Space } from 'antd'\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\r\nimport { useSelector } from 'react-redux'\r\n\r\nimport { checkPermission } from 'redux/user/selectors'\r\nimport ProfileMenu from './ProfileMenu'\r\nimport LanguageSelector from './LanguageSelector'\r\nimport CompanySelector from './CompanySelector'\r\nimport Actions from './Actions'\r\nimport Timelines from './Timelines'\r\nimport ThemeColors from \"./ThemeColors\";\r\n\r\nimport './style.scss'\r\n\r\nconst CustomTopBar = ({\r\n intl,\r\n translation,\r\n invoicePermissions,\r\n purchaseInvoicePermissions,\r\n expensePermissions,\r\n isMobileView,\r\n companies,\r\n role_id,\r\n onChangeCompany,\r\n push,\r\n darkMode,\r\n}) => {\r\n const isHasAccessAudit = useSelector((state) => checkPermission(state, 'audits'))\r\n\r\n return (\r\n \r\n {!isMobileView && (\r\n
\r\n {invoicePermissions.isCanAdd && (\r\n }\r\n >\r\n {intl.formatMessage({ id: 'button.sell' })}\r\n \r\n )}\r\n {purchaseInvoicePermissions.isCanAdd && (\r\n }\r\n >\r\n {intl.formatMessage({ id: 'button.buy' })}\r\n \r\n )}\r\n {expensePermissions.isCanAdd && (\r\n }\r\n >\r\n {translation.menu\r\n ? translation.menu.expenses\r\n : intl.formatMessage({ id: 'financeExpenses.financeExpenses' })}\r\n \r\n )}\r\n \r\n \r\n )}\r\n
\r\n {(companies.companies.length > 1 || role_id === 1) && (\r\n \r\n \r\n
\r\n )}\r\n \r\n \r\n
\r\n {isHasAccessAudit && (\r\n \r\n \r\n
\r\n )}\r\n \r\n \r\n \r\n
\r\n \r\n \r\n
\r\n )\r\n}\r\n\r\nexport default CustomTopBar\r\n","import React from 'react'\r\nimport { connect } from 'react-redux'\r\nimport { Link, withRouter } from 'react-router-dom'\r\nimport { Layout, Menu, Skeleton, Space } from 'antd'\r\nimport store from 'store'\r\nimport { Scrollbars } from 'react-custom-scrollbars'\r\nimport _ from 'lodash'\r\nimport { stringify } from 'query-string'\r\nimport { FontAwesomeIcon } from '@fortawesome/react-fontawesome'\r\n\r\nimport { changeSetting } from 'redux/settings/actions'\r\nimport { checkAlurFlow } from 'redux/options/selectors'\r\nimport { withAppConsumer } from 'components/AppProvider'\r\nimport { DemoWarning, SubscriptionWarning, TrialWarning } from 'components/UI'\r\nimport { getToken } from 'utils/cookies'\r\nimport styles from './style.module.scss'\r\n\r\nconst { Sider } = Layout\r\n\r\nconst PayrollSvg = ({ darkMode }) => {\r\n return (\r\n \r\n )\r\n}\r\n\r\nconst mapStateToProps = ({\r\n menu,\r\n settings,\r\n options,\r\n translation,\r\n inits,\r\n companies: { selectedEndpoint, website_id: websiteId, endpoint },\r\n}) => ({\r\n menuData: menu.menuLeftData,\r\n // isMenuCollapsed: settings.isMenuCollapsed,\r\n isMobileView: settings.isMobileView,\r\n isSettingsOpen: settings.isSettingsOpen,\r\n isLightTheme: settings.isLightTheme,\r\n // isMobileMenuOpen: settings.isMobileMenuOpen,\r\n property: options.options,\r\n darkMode: options.options?.dark_mode,\r\n translation,\r\n loadedInit: inits?.loadedInit,\r\n selectedEndpoint,\r\n websiteId,\r\n endpoint,\r\n})\r\n\r\nconst mapDispatchToProps = (dispatch) => {\r\n return {\r\n onChangeSetting: (payload) => dispatch(changeSetting(payload)),\r\n }\r\n}\r\n\r\n@withRouter\r\n@connect(mapStateToProps, mapDispatchToProps)\r\n@withAppConsumer\r\nclass MenuLeft extends React.PureComponent {\r\n state = {\r\n selectedKeys: store.get('app.menu.selectedKeys') || [],\r\n openedKeys: store.get('app.menu.openedKeys') || [],\r\n }\r\n\r\n // componentDidMount() {\r\n // this.setSelectedKeys(this.props)\r\n // }\r\n\r\n // componentWillReceiveProps(newProps) {\r\n // if (newProps.isMenuCollapsed && !newProps.isMobileView) {\r\n // this.setState({\r\n // openedKeys: [],\r\n // })\r\n // }\r\n // this.setSelectedKeys(newProps)\r\n // }\r\n\r\n componentDidUpdate(prevProps) {\r\n const prevAppContext = prevProps.appContext\r\n const { appContext } = this.props\r\n if (prevAppContext?.settings?.isMenuCollapsed !== appContext?.settings?.isMenuCollapsed) {\r\n if (appContext?.settings?.isMenuCollapsed && !this.props.isMobileView) {\r\n this.setState({\r\n openedKeys: [],\r\n })\r\n }\r\n }\r\n\r\n if (\r\n !_.isEqual(prevProps.menuData, this.props.menuData) ||\r\n prevProps.location.pathname !== this.props.location.pathname\r\n ) {\r\n this.setSelectedKeys()\r\n }\r\n }\r\n\r\n flattenItems = (items, key) =>\r\n items.reduce((flattenedItems, item) => {\r\n flattenedItems.push(item)\r\n if (Array.isArray(item[key])) {\r\n return flattenedItems.concat(this.flattenItems(item[key], key))\r\n }\r\n return flattenedItems\r\n }, [])\r\n\r\n setSelectedKeys = () => {\r\n const { menuData, location } = this.props\r\n const pathName = location.pathname === '/dashboard' ? '/' : location.pathname\r\n const flattenData = this.flattenItems(menuData, 'children')\r\n let selectedItem = null\r\n if (pathName === '/') {\r\n selectedItem = _.find(flattenData, { url: pathName })\r\n } else if (pathName.startsWith('/settings')) {\r\n selectedItem = _.find(menuData, { name: 'settings' })\r\n } else {\r\n for (let i = 0; i < flattenData.length; i += 1) {\r\n const item = flattenData[i]\r\n\r\n if (pathName === '/pos/settings' && pathName === item.url) {\r\n selectedItem = item\r\n break\r\n }\r\n\r\n if (item.url !== '/' && item.url !== '' && pathName.includes(item.url)) {\r\n selectedItem = item\r\n }\r\n }\r\n }\r\n\r\n store.set('app.menu.selectedKeys', selectedItem ? [selectedItem.key] : [])\r\n\r\n this.setState({\r\n selectedKeys: selectedItem ? [selectedItem.key] : [],\r\n })\r\n }\r\n\r\n onCollapse = (value, type) => {\r\n const {\r\n appContext: {\r\n onChangeSettings,\r\n settings: { isMenuCollapsed },\r\n },\r\n } = this.props\r\n if (type === 'responsive' && isMenuCollapsed) {\r\n return\r\n }\r\n\r\n // onChangeSetting({\r\n // setting: 'isMenuCollapsed',\r\n // value: !isMenuCollapsed,\r\n // });\r\n onChangeSettings({ isMenuCollapsed: value })\r\n // this.setState({\r\n // openedKeys: [],\r\n // })\r\n }\r\n\r\n onOpenChange = (openedKeys) => {\r\n this.setState({\r\n openedKeys,\r\n })\r\n }\r\n\r\n handleClick = (e) => {\r\n // const { isSettingsOpen, onChangeSetting } = this.props\r\n store.set('app.menu.selectedKeys', [e.key])\r\n if (e.keyPath[1]) {\r\n store.set('app.menu.openedKeys', [e.keyPath[1]])\r\n } else {\r\n store.set('app.menu.openedKeys', [])\r\n }\r\n\r\n // custom action on settings menu item\r\n // if (e.key === 'settings') {\r\n // onChangeSetting({\r\n // setting: 'isSettingsOpen',\r\n // value: !isSettingsOpen,\r\n // });\r\n // return\r\n // }\r\n this.setState({\r\n selectedKeys: [e.key],\r\n openedKeys: e.keyPath[1] ? [e.keyPath[1]] : [],\r\n // openKeys: e.keyPath,\r\n })\r\n }\r\n\r\n generateMenuItems = () => {\r\n const menuData = _.cloneDeep(this.props.menuData || []).filter((menu) => !_.isEmpty(menu))\r\n const menu = menuData.map((item) => {\r\n if (item.name === 'settings') item.children = null\r\n\r\n return { ...item }\r\n })\r\n\r\n const generateItem = (item) => {\r\n const { key, title, url, icon, disabled } = item\r\n const id = `kledo-menu-${item.name}`\r\n if (item.divider) {\r\n return {\r\n type: 'divider',\r\n key: Math.random(),\r\n }\r\n }\r\n if (item.url && item.name === 'pos') {\r\n const linkKledoPos = (\r\n \r\n {title}\r\n \r\n \r\n )\r\n return {\r\n key,\r\n disabled,\r\n label: linkKledoPos,\r\n }\r\n }\r\n if (item.url) {\r\n let linkComponent = item.target ? (\r\n \r\n {icon && (\r\n \r\n )}\r\n {title}\r\n \r\n ) : (\r\n \r\n {item.name === 'payroll' ? (\r\n \r\n ) : (\r\n <>\r\n {icon && (\r\n \r\n )}\r\n >\r\n )}\r\n\r\n {title}\r\n \r\n )\r\n if (item.name === 'payroll' && this.props.property?.option?.app_connect_hr) {\r\n const searchs = {\r\n token: getToken(),\r\n website_id: this.props.websiteId,\r\n endpoint: this.props.selectedEndpoint,\r\n }\r\n const urlKledo = `${process.env.REACT_APP_GAJIHUB_URL}/dashboard?${stringify(searchs)}`\r\n linkComponent = (\r\n \r\n \r\n {title}\r\n \r\n )\r\n }\r\n return {\r\n id,\r\n key,\r\n disabled,\r\n label: linkComponent,\r\n }\r\n }\r\n return {\r\n key,\r\n disabled,\r\n label: {title},\r\n icon: icon ? (\r\n \r\n ) : null,\r\n }\r\n }\r\n\r\n const generateSubmenu = (items) => {\r\n return items.map((menuItem) => {\r\n if (!checkAlurFlow(menuItem.name)) {\r\n return null\r\n }\r\n const id = `kledo-menu-${menuItem.name}`\r\n\r\n if (menuItem.children) {\r\n const subMenuTitle = (\r\n \r\n {menuItem.title}\r\n {menuItem.icon && (\r\n \r\n )}\r\n \r\n )\r\n return {\r\n key: menuItem.key,\r\n id,\r\n label: subMenuTitle,\r\n children: generateSubmenu(menuItem.children),\r\n }\r\n }\r\n return generateItem(menuItem)\r\n })\r\n }\r\n\r\n return menu.map((menuItem) => {\r\n const id = `kledo-menu-${menuItem.name}`\r\n if (menuItem.children) {\r\n const subMenuTitle = (\r\n \r\n {!_.isEmpty(menuItem.url) ? (\r\n \r\n {menuItem.icon && (\r\n \r\n )}\r\n {menuItem.title}\r\n \r\n ) : (\r\n <>\r\n \r\n
{menuItem.title}\r\n {menuItem.icon && menuItem.icon !== 'kledo-pos' && (\r\n
\r\n )}\r\n {menuItem.icon === 'kledo-pos' && (\r\n
\r\n )}\r\n
\r\n >\r\n )}\r\n \r\n )\r\n return {\r\n key: menuItem.key,\r\n id,\r\n label: subMenuTitle,\r\n children: generateSubmenu(menuItem.children),\r\n }\r\n }\r\n\r\n return generateItem(menuItem)\r\n })\r\n }\r\n\r\n makeLoader = () => {\r\n const loaders = []\r\n for (let i = 1; i <= 10; i += 1) {\r\n loaders.push(\r\n \r\n \r\n {!this.props.appContext.settings?.isMenuCollapsed && (\r\n \r\n )}\r\n ,\r\n )\r\n }\r\n return loaders\r\n }\r\n\r\n render() {\r\n const { selectedKeys, openedKeys } = this.state\r\n const {\r\n isMobileView,\r\n isLightTheme,\r\n property,\r\n darkMode,\r\n scrollBarRef,\r\n appContext: {\r\n settings: { isMenuCollapsed },\r\n },\r\n } = this.props\r\n const menuSettings = isMobileView\r\n ? {\r\n width: 256,\r\n collapsible: false,\r\n collapsed: false,\r\n collapsedWidth: 0,\r\n onCollapse: this.onCollapse,\r\n }\r\n : {\r\n width: 256,\r\n collapsible: true,\r\n collapsed: isMenuCollapsed,\r\n onCollapse: this.onCollapse,\r\n breakpoint: 'lg',\r\n }\r\n\r\n const menu = this.generateMenuItems()\r\n\r\n return (\r\n \r\n \r\n
\r\n
\r\n {!_.isEmpty(property.property_logo) ? (\r\n

\r\n ) : (\r\n

\r\n )}\r\n \r\n
\r\n
\r\n {\r\n (!isMenuCollapsed || isMobileView) && [\r\n ,\r\n ,\r\n ,\r\n ]\r\n // \r\n // \r\n // \r\n // \r\n // \r\n // ),\r\n // }}\r\n // />\r\n // }\r\n // type=\"warning\"\r\n // showIcon={!isMenuCollapsed || isMobileView}\r\n // />\r\n }\r\n (\r\n \r\n )}\r\n autoHide\r\n >\r\n {!this.props.loadedInit ? (\r\n \r\n {this.makeLoader()}\r\n \r\n ) : (\r\n \r\n )}\r\n \r\n {!isMobileView && }\r\n \r\n )\r\n }\r\n}\r\n\r\nexport default MenuLeft\r\n","import 'rc-drawer/assets/index.css'\r\nimport React from 'react'\r\nimport DrawerMenu from 'rc-drawer'\r\nimport { connect } from 'react-redux'\r\nimport { withRouter } from 'react-router-dom'\r\n// import { changeSetting } from 'redux/settings/actions'\r\nimport { withAppConsumer } from 'components/AppProvider'\r\nimport MenuLeft from './MenuLeft'\r\n\r\nconst mapStateToProps = ({ settings }) => ({\r\n isMenuTop: settings.isMenuTop,\r\n // isMobileMenuOpen: settings.isMobileMenuOpen,\r\n isMobileView: settings.isMobileView,\r\n isLightTheme: settings.isLightTheme,\r\n})\r\n\r\n// const mapDispatchToProps = dispatch => {\r\n// return {\r\n// onChangeSetting: (payload) => dispatch(changeSetting(payload))\r\n// };\r\n// }\r\n\r\n@withRouter\r\n@connect(mapStateToProps)\r\n@withAppConsumer\r\nclass AppMenu extends React.PureComponent {\r\n componentDidUpdate(prevProps) {\r\n if (\r\n prevProps.isMobileView !== this.props.isMobileView &&\r\n !this.props.isMobileView &&\r\n this.props.appContext.settings.isMobileMenuOpen\r\n ) {\r\n this.toggleOpen()\r\n }\r\n }\r\n\r\n toggleOpen = () => {\r\n const {\r\n appContext: {\r\n settings: { isMobileMenuOpen },\r\n onChangeSettings,\r\n },\r\n } = this.props\r\n document\r\n .querySelector('#root')\r\n .setAttribute(\r\n 'style',\r\n !isMobileMenuOpen ? 'overflow: hidden; width: 100%; height: 100%;' : '',\r\n )\r\n onChangeSettings({ isMobileMenuOpen: !isMobileMenuOpen })\r\n }\r\n\r\n render() {\r\n const {\r\n appContext: {\r\n settings: { isMobileMenuOpen },\r\n },\r\n isMobileView,\r\n isLightTheme,\r\n scrollBarRef,\r\n } = this.props\r\n\r\n const BootstrappedMenu = () => {\r\n if (isMobileView) {\r\n return (\r\n \r\n \r\n \r\n )\r\n }\r\n\r\n return \r\n }\r\n\r\n return BootstrappedMenu()\r\n }\r\n}\r\n\r\nexport default AppMenu\r\n","import React from 'react'\r\nimport { useSelector } from 'react-redux'\r\n\r\nimport { billingSelector, darkModeSelector, optionsSelector } from 'redux/selectors'\r\nimport { isFeatureChampion } from 'utils/helper'\r\nimport styles from './style.module.scss'\r\n\r\nconst Footer = () => {\r\n const billing = useSelector(billingSelector)\r\n const options = useSelector(optionsSelector)\r\n const darkMode = useSelector(darkModeSelector)\r\n\r\n const isOnChampionPlan = !isFeatureChampion({\r\n billing,\r\n code: 'finance_system_white_label',\r\n })\r\n\r\n const companyName =\r\n options?.finance_system_white_label && isOnChampionPlan ? options.property_name : 'Kledo'\r\n\r\n return (\r\n \r\n )\r\n}\r\n\r\nexport default Footer\r\n","import { appMessage } from 'utils/formatting';\r\n\r\nconst routes = [\r\n { path: '/banks/detail/:id/transactions', breadcrumb: appMessage('transactions')},\r\n { path: '/banks/detail/:id/bankstatements', breadcrumb: appMessage('bankstatements')},\r\n { path: '/banks/detail/:id/reconcile', breadcrumb: appMessage('reconcile')},\r\n { path: '/banks/detail/:id/waiting_approval', breadcrumb: appMessage('approvals.waiting_for_approval')},\r\n { path: '/banks/detail/:id/rejected', breadcrumb: appMessage('approvals.rejected')},\r\n];\r\n\r\nexport default routes;\r\n","import { lazy } from 'react'\r\nimport { appMessage } from 'utils/formatting'\r\n\r\nconst routes = [\r\n {\r\n path: '/companies',\r\n component: lazy(() => import('pages/companies')),\r\n exact: true,\r\n },\r\n {\r\n path: '/companies/add',\r\n component: lazy(() => import('pages/companies/Add')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/notification',\r\n component: lazy(() => import('pages/notification')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/posConnect',\r\n component: lazy(() => import('pages/posConnect')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/posConnect/add',\r\n component: lazy(() => import('pages/posConnect/Add')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/posConnect/add/:pos',\r\n component: lazy(() => import('pages/posConnect/AddForm')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/posConnect/edit/:id',\r\n component: lazy(() => import('pages/posConnect/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/marketplaceConnect',\r\n component: lazy(() => import('pages/marketplaceConnect')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/marketplaceConnect/add',\r\n component: lazy(() => import('pages/marketplaceConnect/Add')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/marketplaceConnect/add/:marketplace',\r\n component: lazy(() => import('pages/marketplaceConnect/AddForm')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/marketplaceConnect/edit/:id',\r\n component: lazy(() => import('pages/marketplaceConnect/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/apps',\r\n component: lazy(() => import('pages/appsSetting')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/apps/add',\r\n component: lazy(() => import('pages/appsSetting/Add')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/apps/detail/:id',\r\n component: lazy(() => import('pages/appsSetting/Detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/whatsappTemplate',\r\n component: lazy(() => import('pages/whatsappTemplate')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/email-template',\r\n component: lazy(() => import('pages/emailTemplate')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/account-mapping',\r\n component: lazy(() => import('pages/accountMapping')),\r\n exact: true,\r\n },\r\n {\r\n path: '/confirm/email/:token',\r\n component: lazy(() => import('pages/emailTemplate/confirm')),\r\n exact: true,\r\n breadcrumb: appMessage('email.email_confirmation'),\r\n },\r\n\r\n {\r\n path: '/referral',\r\n component: lazy(() => import('pages/referral')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/custom-columns',\r\n component: lazy(() => import('pages/customColumn')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/shipping-company',\r\n component: lazy(() => import('pages/shippingCompany')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/consolidation',\r\n component: lazy(() => import('pages/consolidation')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/unit',\r\n component: lazy(() => import('pages/financeUnits')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/translation',\r\n component: lazy(() => import('pages/translation')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/audit',\r\n component: lazy(() => import('pages/audit')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/multi-currency',\r\n component: lazy(() => import('pages/multiCurrency')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/user/billing/success',\r\n component: lazy(() => import('pages/billing/Success')),\r\n exact: true,\r\n },\r\n {\r\n path: '/user/billing/failed',\r\n component: lazy(() => import('pages/billing/Failed')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/billing',\r\n component: lazy(() => import('pages/billing')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/billing/upgrade',\r\n component: lazy(() => import('pages/billing/UpgradeBilling')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/billing/downgrade',\r\n component: lazy(() => import('pages/billing/DowngradeBilling')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/billing/addon',\r\n component: lazy(() => import('pages/billing/AddAddon')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/billing/pos',\r\n component: lazy(() => import('pages/billing/POS')),\r\n exact: true,\r\n },\r\n {\r\n path: '/payments',\r\n component: lazy(() => import('pages/payments')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/users',\r\n component: lazy(() => import('pages/users')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/roles',\r\n component: lazy(() => import('pages/roles')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/roles/add',\r\n component: lazy(() => import('pages/roles/AddRole')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/roles/edit/:id',\r\n component: lazy(() => import('pages/roles/EditRole')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n\r\n {\r\n path: '/settings/sales-commissions',\r\n component: lazy(() => import('pages/salesCommission')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/sales-commissions/add',\r\n component: lazy(() => import('pages/salesCommission/AddSalesCommission')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/sales-commissions/detail/:id',\r\n component: lazy(() => import('pages/salesCommission/DetailSalesCommission')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/sales-commissions/edit/:id',\r\n component: lazy(() => import('pages/salesCommission/EditSalesCommission')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n\r\n // System Pages\r\n {\r\n path: '/onboarding',\r\n component: lazy(() => import('pages/onBoarding')),\r\n exact: true,\r\n },\r\n {\r\n path: '/user/login',\r\n component: lazy(() => import('pages/user/login')),\r\n exact: true,\r\n breadcrumb: 'Login',\r\n },\r\n {\r\n path: '/user/login/sso',\r\n component: lazy(() => import('pages/user/login/sso')),\r\n exact: true,\r\n breadcrumb: 'Login',\r\n },\r\n {\r\n path: '/user/select-company',\r\n component: lazy(() => import('pages/user/select-company')),\r\n exact: true,\r\n },\r\n {\r\n path: '/user/forgot',\r\n component: lazy(() => import('pages/user/forgot')),\r\n exact: true,\r\n },\r\n {\r\n path: '/user/register',\r\n component: lazy(() => import('pages/user/register')),\r\n exact: true,\r\n },\r\n {\r\n path: '/user/reset-password/:token',\r\n component: lazy(() => import('pages/user/reset-password')),\r\n exact: true,\r\n },\r\n {\r\n path: '/user/invite/:token',\r\n component: lazy(() => import('pages/user/invite')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/profile',\r\n component: lazy(() => import('pages/user/profile')),\r\n exact: true,\r\n },\r\n\r\n {\r\n path: '/settings/company',\r\n component: lazy(() => import('pages/company')),\r\n exact: true,\r\n },\r\n\r\n // Dashboards\r\n {\r\n path: '/dashboard',\r\n component: lazy(() => import('pages/dashboard')),\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/overview',\r\n component: lazy(() => import('pages/purchases')),\r\n },\r\n {\r\n path: '/sales/overview',\r\n component: lazy(() => import('pages/sales')),\r\n },\r\n // Reports\r\n {\r\n path: '/reports/sales-per-product-category',\r\n component: lazy(() => import('pages/reports/salesPerProductCategory')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/product-purchases-per-vendor',\r\n component: lazy(() => import('pages/reports/productPurchasesPerVendor')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/product-sales-per-customer',\r\n component: lazy(() => import('pages/reports/productSalesPerCustomer')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/sales-per-period',\r\n component: lazy(() => import('pages/reports/salesPerPeriod')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/purchases-per-period',\r\n component: lazy(() => import('pages/reports/purchasesPerPeriod')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/inventory-summary',\r\n component: lazy(() => import('pages/reports/inventorySummary')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/inventory-stock-movement',\r\n component: lazy(() => import('pages/reports/inventoryStockMovement')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/warehouse-stock-summary',\r\n component: lazy(() => import('pages/reports/warehouseStockSummary')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/warehouse-stock-movement',\r\n component: lazy(() => import('pages/reports/warehouseStockMovement')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/inventory-stock-adjustment',\r\n component: lazy(() => import('pages/reports/inventoryStockAdjustment')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/warehouse-transfer',\r\n component: lazy(() => import('pages/reports/inventoryWarehouseTransfer')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/production',\r\n component: lazy(() => import('pages/reports/production')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/general-ledger',\r\n component: lazy(() => import('pages/reports/generalLedger')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/general-ledger/category/:id',\r\n component: lazy(() => import('pages/reports/generalLedger/Category')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/reports/journal',\r\n component: lazy(() => import('pages/reports/journalReporting')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/bank-summary',\r\n component: lazy(() => import('pages/reports/bankSummary')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/sales-tax',\r\n component: lazy(() => import('pages/reports/salesTax')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/customer-invoice',\r\n component: lazy(() => import('pages/reports/customerInvoice')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/profitability-per-invoice',\r\n component: lazy(() => import('pages/reports/profitabilityPerInvoice')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/supplier-invoice',\r\n component: lazy(() => import('pages/reports/supplierInvoice')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/sales-detail',\r\n component: lazy(() => import('pages/reports/salesDetail')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/purchase-detail',\r\n component: lazy(() => import('pages/reports/purchaseDetail')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/aged-receivable',\r\n component: lazy(() => import('pages/reports/agedReceivable')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/aged-receivable/detail/:id',\r\n component: lazy(() => import('pages/reports/agedReceivableDetail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/reports/aged-payable',\r\n component: lazy(() => import('pages/reports/agedPayable')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/aged-payable/detail/:id',\r\n component: lazy(() => import('pages/reports/agedPayableDetail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/reports/expense-claim',\r\n component: lazy(() => import('pages/reports/expenseClaim')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/expense-claim/detail/:id',\r\n component: lazy(() => import('pages/reports/expenseClaimDetail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/reports/income-per-customer',\r\n component: lazy(() => import('pages/reports/incomePerCustomer')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/trial-balance',\r\n component: lazy(() => import('pages/reports/trialBalance')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/profit-loss',\r\n component: lazy(() => import('pages/reports/profitLoss')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/expense-per-contact',\r\n component: lazy(() => import('pages/reports/expensePerContact')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/sales-per-product',\r\n component: lazy(() => import('pages/reports/salesPerProduct')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/order-per-product',\r\n component: lazy(() => import('pages/reports/orderPerProduct')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/account-transaction/:id',\r\n component: lazy(() => import('pages/reports/accountTransaction')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/reports/purchases-per-vendor',\r\n component: lazy(() => import('pages/reports/purchasesPerVendor')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/purchases-per-product',\r\n component: lazy(() => import('pages/reports/purchasesPerProduct')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports',\r\n component: lazy(() => import('pages/reports/reportingHome')),\r\n exact: true,\r\n breadcrumb: appMessage('report.reports'),\r\n },\r\n {\r\n path: '/reports/cash-flow',\r\n component: lazy(() => import('pages/reports/cashFlow')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/balance-sheet',\r\n component: lazy(() => import('pages/reports/balanceSheet')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/equity-movement',\r\n component: lazy(() => import('pages/reports/equityMovement')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/executive-summary',\r\n component: lazy(() => import('pages/reports/executiveSummary')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/receivable-payable-per-contact',\r\n component: lazy(() => import('pages/reports/receivablePayable')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/fixed-asset-detail',\r\n component: lazy(() => import('pages/reports/fixedAssetDetail')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/fixed-asset-summary',\r\n component: lazy(() => import('pages/reports/fixedAssetSummary')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/fixed-asset-disposal',\r\n component: lazy(() => import('pages/reports/fixedAssetDisposal')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/consolidation-balance-sheet',\r\n component: lazy(() => import('pages/reports/consolidationBalanceSheet')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/consolidation-cash-flow',\r\n component: lazy(() => import('pages/reports/consolidationCashFlow')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/consolidation-profit-loss',\r\n component: lazy(() => import('pages/reports/consolidationProfitLoss')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/consolidation-worksheet',\r\n component: lazy(() => import('pages/reports/consolidationWorksheet')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/sales-delivery',\r\n component: lazy(() => import('pages/reports/salesDelivery')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/purchase-delivery',\r\n component: lazy(() => import('pages/reports/purchaseDelivery')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/budget-management',\r\n component: lazy(() => import('pages/reports/budgetManagement')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/budget-management/add',\r\n component: lazy(() => import('pages/reports/budgetManagement/Add')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/budget-management/edit/:id',\r\n component: lazy(() => import('pages/reports/budgetManagement/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/reports/budget-profit-loss',\r\n component: lazy(() => import('pages/reports/budgetProfitLoss')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/shipping-cost-per-expedition',\r\n component: lazy(() => import('pages/reports/shippingCostPerExpedition')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/sales-per-sales-person',\r\n component: lazy(() => import('pages/reports/salesPerSalesPerson')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/product-profitability',\r\n component: lazy(() => import('pages/reports/productProfitability')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/invoice-payment',\r\n component: lazy(() => import('pages/reports/invoicePayment')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/purchase-invoice-payment',\r\n component: lazy(() => import('pages/reports/purchaseInvoicePayment')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/attachment',\r\n component: lazy(() => import('pages/reports/attachment')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/export',\r\n component: lazy(() => import('pages/reports/export')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/import',\r\n component: lazy(() => import('pages/reports/import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/import/:id',\r\n component: lazy(() => import('pages/reports/import/Detail')),\r\n exact: true,\r\n breadcrumb: appMessage('detail'),\r\n },\r\n {\r\n path: '/settings/setup',\r\n component: lazy(() => import('pages/setup')),\r\n },\r\n // {\r\n // path: '/pos/outlets',\r\n // component: lazy(() => componentLoader(() => import('pages/posSettings/outlets'))),\r\n // },\r\n // {\r\n // path: '/pos/products/:id',\r\n // component: lazy(() => componentLoader(() => import('pages/posSettings/products'))),\r\n // },\r\n // {\r\n // path: '/pos/toroom/:id',\r\n // component: lazy(() => componentLoader(() => import('pages/pos/transferToRoom'))),\r\n // },\r\n // {\r\n // path: '/pos/activity/:id',\r\n // component: lazy(() => componentLoader(() => import('pages/pos/activity'))),\r\n // },\r\n // {\r\n // path: '/pos/:id',\r\n // component: lazy(() => componentLoader(() => import('pages/pos'))),\r\n // },\r\n // {\r\n // path: '/reports/pos',\r\n // component: lazy(() => componentLoader(() => import('pages/reports/pos'))),\r\n // exact: true,\r\n // },\r\n {\r\n path: '/accounts',\r\n component: lazy(() => import('pages/financeAccounts')),\r\n exact: true,\r\n },\r\n {\r\n path: '/accounts/import',\r\n component: lazy(() => import('pages/financeAccounts/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/contacts/import',\r\n component: lazy(() => import('pages/financeContacts/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/contacts/import-accounts-payable',\r\n component: lazy(() => import('pages/financeContacts/ImportAccountsPayable')),\r\n exact: true,\r\n },\r\n {\r\n path: '/contacts',\r\n component: lazy(() => import('pages/financeContacts')),\r\n exact: true,\r\n },\r\n {\r\n path: '/contacts/detail/:id',\r\n component: lazy(() => import('pages/financeContacts/detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/contacts/edit/:id',\r\n component: lazy(() => import('pages/financeContacts/edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/expenses/terms',\r\n component: lazy(() => import('pages/financeExpenseTerms')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/detail/:id',\r\n component: lazy(() => import('pages/financeProducts/detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/products',\r\n component: lazy(() => import('pages/financeProducts')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/access/:id',\r\n component: lazy(() => import('pages/financeProducts/ProductAccess')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/price-rule',\r\n component: lazy(() => import('pages/financeProducts/PriceRule')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/price-rule/add',\r\n component: lazy(() => import('pages/financeProducts/AddPriceRule')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/price-rule/detail/:id',\r\n component: lazy(() => import('pages/financeProducts/DetailPriceRule')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/products/price-rule/edit/:id',\r\n component: lazy(() => import('pages/financeProducts/EditPriceRule')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/products/import',\r\n component: lazy(() => import('pages/financeProducts/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/import-package',\r\n component: lazy(() => import('pages/financeProducts/ImportPackage')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/import-manufacture',\r\n component: lazy(() => import('pages/financeProducts/ImportManufacture')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/import-conversion',\r\n component: lazy(() => import('pages/financeProducts/ImportConversion')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/bundle-package/add/:id?',\r\n component: lazy(() => import('pages/financeProducts/AddBundlePackage')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/bundle-manufacture/add/:id?',\r\n component: lazy(() => import('pages/financeProducts/AddBundleManufacture')),\r\n exact: true,\r\n },\r\n {\r\n path: '/products/bundle-package/edit/:id',\r\n component: lazy(() => import('pages/financeProducts/EditBundlePackage')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/products/bundle-manufacture/edit/:id',\r\n component: lazy(() => import('pages/financeProducts/EditBundleManufacture')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/products/conversions/:id',\r\n component: lazy(() => import('pages/financeProducts/ConversionProduct')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/products/conversions/detail/:id',\r\n component: lazy(() => import('pages/financeProducts/ConversionProductDetail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/products/conversions/edit/:id',\r\n component: lazy(() => import('pages/financeProducts/EditConversionProduct')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/taxes',\r\n component: lazy(() => import('pages/financeTaxes')),\r\n exact: true,\r\n },\r\n {\r\n path: '/expenses',\r\n component: lazy(() => import('pages/financeExpenses')),\r\n exact: true,\r\n },\r\n {\r\n path: '/expenses/import',\r\n component: lazy(() => import('pages/financeExpenses/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/expenses/add/:id?',\r\n component: lazy(() => import('pages/financeExpenses/AddFinanceExpense')),\r\n exact: true,\r\n breadcrumb: appMessage('add'),\r\n },\r\n {\r\n path: '/expenses/edit/:id',\r\n component: lazy(() => import('pages/financeExpenses/EditFinanceExpense')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/expenses/detail/:id',\r\n component: lazy(() => import('pages/financeExpenses/DetailFinanceExpense')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/purchaseorders',\r\n component: lazy(() => import('pages/financePurchaseOrders')),\r\n exact: true,\r\n breadcrumb: appMessage('purchase_order'),\r\n },\r\n {\r\n path: '/purchases/purchaseorders/add/:idQuote?',\r\n component: lazy(() => import('pages/financePurchaseOrders/AddFinancePurchaseOrder')),\r\n exact: true,\r\n breadcrumb: appMessage('add'),\r\n },\r\n {\r\n path: '/purchases/purchaseorders/edit/:id',\r\n component: lazy(() => import('pages/financePurchaseOrders/EditFinancePurchaseOrder')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/purchaseorders/detail/:id',\r\n component: lazy(() => import('pages/financePurchaseOrders/DetailFinancePurchaseOrder')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/purchaseorders/import',\r\n component: lazy(() => import('pages/financePurchaseOrders/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/purchases/purchaseinvoices',\r\n component: lazy(() => import('pages/financePurchaseInvoices')),\r\n exact: true,\r\n breadcrumb: appMessage('purchase_invoice'),\r\n },\r\n {\r\n path: '/purchases/purchaseinvoices/add/:idRelation?',\r\n component: lazy(() => import('pages/financePurchaseInvoices/AddFinancePurchaseInvoice')),\r\n exact: true,\r\n },\r\n {\r\n path: '/purchases/purchaseinvoices/edit/:id',\r\n component: lazy(() => import('pages/financePurchaseInvoices/EditFinancePurchaseInvoice')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/purchaseinvoices/detail/:id',\r\n component: lazy(() => import('pages/financePurchaseInvoices/DetailFinancePurchaseInvoice')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/purchaseinvoices/import',\r\n component: lazy(() => import('pages/financePurchaseInvoices/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/purchases/purchaseinvoices/importStatus',\r\n component: lazy(() => import('pages/financePurchaseInvoices/ImportStatus')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/quotes',\r\n component: lazy(() => import('pages/financeQuotes')),\r\n exact: true,\r\n breadcrumb: appMessage('quote'),\r\n },\r\n {\r\n path: '/sales/quotes/add/:id?',\r\n component: lazy(() => import('pages/financeQuotes/AddFinanceQuote')),\r\n exact: true,\r\n breadcrumb: appMessage('add'),\r\n },\r\n {\r\n path: '/sales/quotes/edit/:id',\r\n component: lazy(() => import('pages/financeQuotes/EditFinanceQuote')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/quotes/detail/:id',\r\n component: lazy(() => import('pages/financeQuotes/DetailFinanceQuote')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/quotes/import',\r\n component: lazy(() => import('pages/financeQuotes/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/invoices',\r\n component: lazy(() => import('pages/financeInvoices')),\r\n exact: true,\r\n breadcrumb: appMessage('invoice'),\r\n },\r\n {\r\n path: '/sales/invoices/add/:idRelation?',\r\n component: lazy(() => import('pages/financeInvoices/AddFinanceInvoice')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/invoices/edit/:id',\r\n component: lazy(() => import('pages/financeInvoices/EditFinanceInvoice')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/invoices/detail/:id',\r\n component: lazy(() => import('pages/financeInvoices/DetailFinanceInvoice')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/invoices/recurring/add',\r\n component: lazy(() => import('pages/recurring/Add')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/invoices/recurring/edit/:id',\r\n component: lazy(() => import('pages/recurring/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/invoices/import',\r\n component: lazy(() => import('pages/financeInvoices/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/invoices/import-recurring',\r\n component: lazy(() => import('pages/financeInvoices/ImportRecurring')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/invoices/import-return',\r\n component: lazy(() => import('pages/financeInvoices/ImportReturn')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/invoices/importStatus',\r\n component: lazy(() => import('pages/financeInvoices/ImportStatus')),\r\n exact: true,\r\n },\r\n {\r\n path: '/banks',\r\n component: lazy(() => import('pages/financeBanks')),\r\n exact: true,\r\n breadcrumb: 'Bank',\r\n },\r\n {\r\n path: '/banks/detail/:id',\r\n component: lazy(() => import('pages/financeBanks/DetailFinanceBank')),\r\n },\r\n {\r\n path: '/banks/:id/access',\r\n component: lazy(() => import('pages/financeAccounts/AccountAccess')),\r\n },\r\n {\r\n path: '/banks/transactions/import/:id',\r\n component: lazy(() => import('pages/financeBanks/ImportBankTrans')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/transfer/import/:id',\r\n component: lazy(() => import('pages/financeBanks/ImportBankTransfer')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/:bankAccountId/spend/:id?',\r\n component: lazy(() => import('pages/financeBanks/AddSpendFinanceBankTrans')),\r\n exact: true,\r\n },\r\n {\r\n path: '/banks/:bankAccountId/receive/:id?',\r\n component: lazy(() => import('pages/financeBanks/AddReceiveFinanceBankTrans')),\r\n exact: true,\r\n },\r\n {\r\n path: '/banks/:bankAccountId/transaction/edit/:id',\r\n component: lazy(() => import('pages/financeBanks/EditFinanceBankTrans')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/:bankAccountId/transaction/detail/:id',\r\n component: lazy(() => import('pages/financeBanks/DetailFinanceBankTrans')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/bankstatement/import/:id',\r\n component: lazy(() => import('pages/financeBanks/ImportBankStatement')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/connect',\r\n component: lazy(() => import('pages/financeBanks/Connect')),\r\n exact: true,\r\n },\r\n {\r\n path: '/banks/connect/detail/:id',\r\n component: lazy(() => import('pages/financeBanks/DetailConnect')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/connect/add/:id',\r\n component: lazy(() => import('pages/financeBanks/AddConnect')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/connect/edit/:id',\r\n component: lazy(() => import('pages/financeBanks/EditConnect')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/automatic-sequencing',\r\n component: lazy(() => import('pages/financeNumbers')),\r\n exact: true,\r\n breadcrumb: 'Automatic Sequencing',\r\n },\r\n {\r\n path: '/accounts/conversionbalances',\r\n component: lazy(() => import('pages/financeConversion/ConversionBalances')),\r\n exact: true,\r\n },\r\n {\r\n path: '/accounts/conversionbalances/import',\r\n component: lazy(() => import('pages/financeConversion/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/accounts/conversionbalances/conversiondate',\r\n component: lazy(() => import('pages/financeConversion/ConversionDate')),\r\n exact: true,\r\n },\r\n {\r\n path: '/accounts/conversionbalances/reversal_detail/:id',\r\n component: lazy(() => import('pages/financeConversion/ReversalDetail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/accounts/conversionbalances/opening_balance/:id',\r\n component: lazy(() => import('pages/financeConversion/OpeningBalanceDetail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/manual-journal',\r\n component: lazy(() => import('pages/financeManualJournal')),\r\n exact: true,\r\n },\r\n {\r\n path: '/manual-journal/import',\r\n component: lazy(() => import('pages/financeManualJournal/ImportManualJournal')),\r\n exact: true,\r\n },\r\n {\r\n path: '/manual-journal/add/:idRelation?',\r\n component: lazy(() => import('pages/financeManualJournal/AddFinanceManualJournal')),\r\n exact: true,\r\n },\r\n {\r\n path: '/manual-journal/edit/:id',\r\n component: lazy(() => import('pages/financeManualJournal/EditFinanceManualJournal')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/manual-journal/detail/:id',\r\n component: lazy(() => import('pages/financeManualJournal/DetailFinanceManualJournal')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/fixed-assets',\r\n component: lazy(() => import('pages/financeFixedAssets')),\r\n exact: true,\r\n },\r\n {\r\n path: '/fixed-assets/import',\r\n component: lazy(() => import('pages/financeFixedAssets/ImportFixedAsset')),\r\n exact: true,\r\n },\r\n {\r\n path: '/fixed-assets/add/:id?',\r\n component: lazy(() => import('pages/financeFixedAssets/AddFinanceFixedAsset')),\r\n exact: true,\r\n },\r\n {\r\n path: '/fixed-assets/detail/:id',\r\n component: lazy(() => import('pages/financeFixedAssets/DetailFinanceFixedAsset')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/fixed-assets/edit/:id',\r\n component: lazy(() => import('pages/financeFixedAssets/EditFinanceFixedAsset')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/fixed-assets/dispose/:id',\r\n component: lazy(() => import('pages/financeFixedAssets/DisposeFixedAsset')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/fixed-assets/register/:id',\r\n component: lazy(() => import('pages/financeFixedAssets/RegisterFixedAsset')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/fixed-assets/run-depreciation',\r\n component: lazy(() => import('pages/financeFixedAssets/RunDepreciation')),\r\n exact: true,\r\n },\r\n {\r\n path: '/fixed-assets/transaction/:tranId',\r\n component: lazy(() => import('pages/financeFixedAssets/DetailFinanceFixedAssetTransaction')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/lock-date',\r\n component: lazy(() => import('pages/financeLockDate')),\r\n exact: true,\r\n },\r\n {\r\n path: '/reports/witholding-tax',\r\n component: lazy(() => import('pages/reports/witholdingTax')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses',\r\n component: lazy(() => import('pages/financeWareHouses')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/detail/:id',\r\n component: lazy(() => import('pages/financeWareHouses/DetailFinanceWareHouse')),\r\n breadcrumb: null,\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/access/:id',\r\n component: lazy(() => import('pages/financeWareHouses/WarehouseAccess')),\r\n breadcrumb: null,\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/access-per-contact/:id',\r\n component: lazy(() => import('pages/financeWareHouses/WarehouseAccessPerContact')),\r\n breadcrumb: null,\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/:id/transfer-in',\r\n component: lazy(() => import('pages/financeWareHouses/AddTransferIn')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/:id/transfer-out',\r\n component: lazy(() => import('pages/financeWareHouses/AddTransferOut')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/:id/transfer/import',\r\n component: lazy(() => import('pages/financeWareHouses/ImportTransfer')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/:warehouseId/transfer/detail/:id',\r\n component: lazy(() => import('pages/financeWareHouses/DetailFinanceWareHouseTransfer')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/:warehouseId/transfer/edit/:id',\r\n component: lazy(() => import('pages/financeWareHouses/EditTransferInOut')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/warehouses/:warehouseId/stock-adjustment/detail/:id',\r\n component: lazy(() => import('pages/financeWareHouses/DetailStockAdjustment')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/:id/stock-adjustment/add/:relationId?',\r\n component: lazy(() => import('pages/financeWareHouses/AddStockAdjustment')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/:id/stock-adjustment/import',\r\n component: lazy(() => import('pages/financeWareHouses/ImportStockAdjustment')),\r\n exact: true,\r\n },\r\n {\r\n path: '/warehouses/:warehouseId/stock-adjustment/edit/:id',\r\n component: lazy(() => import('pages/financeWareHouses/EditStockAdjustment')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/finance-approval',\r\n component: lazy(() => import('pages/approvals')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/layout-invoice',\r\n component: lazy(() => import('pages/layoutInvoice')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/layout-report',\r\n component: lazy(() => import('pages/layoutReport')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/layout-barcode',\r\n component: lazy(() => import('pages/layoutBarcode')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/tags',\r\n component: lazy(() => import('pages/financeTag')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/tags/detail/:id',\r\n component: lazy(() => import('pages/financeTag/detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/tags/access/:id',\r\n component: lazy(() => import('pages/financeTag/TagAccess')),\r\n breadcrumb: null,\r\n exact: true,\r\n },\r\n {\r\n path: '/settings',\r\n component: lazy(() => import('pages/settings')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/approval-setting',\r\n component: lazy(() => import('pages/approvals/ApprovalSettings')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/orders',\r\n component: lazy(() => import('pages/financeOrder')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/orders/import',\r\n component: lazy(() => import('pages/financeOrder/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/orders/detail/:id',\r\n component: lazy(() => import('pages/financeOrder/DetailFinanceOrder')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/orders/add/:idQuote?',\r\n component: lazy(() => import('pages/financeOrder/AddFinanceOrder')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/orders/edit/:id',\r\n component: lazy(() => import('pages/financeOrder/EditFinanceOrder')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/orders/recurring/add',\r\n component: lazy(() => import('pages/recurring/Add')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/orders/recurring/edit/:id',\r\n component: lazy(() => import('pages/recurring/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/deliveries',\r\n component: lazy(() => import('pages/financeDelivery')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/deliveries/add/:idOrder?',\r\n component: lazy(() => import('pages/financeDelivery/AddFinanceDelivery')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/deliveries/detail/:id',\r\n component: lazy(() => import('pages/financeDelivery/DetailFinanceDelivery')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/deliveries/edit/:id',\r\n component: lazy(() => import('pages/financeDelivery/EditFinanceDelivery')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/credit-memo/add/:idContact',\r\n component: lazy(() => import('pages/creditMemo/AddCreditMemo')),\r\n exact: true,\r\n },\r\n {\r\n path: '/credit-memo/edit/:id',\r\n component: lazy(() => import('pages/creditMemo/EditCreditMemo')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/credit-memo/detail/:id',\r\n component: lazy(() => import('pages/creditMemo/DetailCreditMemo')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/returns/add/:idInvoice?',\r\n component: lazy(() => import('pages/return/AddReturn')),\r\n exact: true,\r\n },\r\n {\r\n path: '/sales/returns/detail/:id',\r\n component: lazy(() => import('pages/return/DetailReturn')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/sales/returns/edit/:id',\r\n component: lazy(() => import('pages/return/EditReturn')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/quotes',\r\n component: lazy(() => import('pages/financePurchaseQuotes')),\r\n exact: true,\r\n breadcrumb: appMessage('quote'),\r\n },\r\n {\r\n path: '/purchases/quotes/add/:id?',\r\n component: lazy(() => import('pages/financePurchaseQuotes/AddFinancePurchaseQuote')),\r\n exact: true,\r\n breadcrumb: appMessage('add'),\r\n },\r\n {\r\n path: '/purchases/quotes/edit/:id',\r\n component: lazy(() => import('pages/financePurchaseQuotes/EditFinancePurchaseQuote')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/debit-memo/edit/:id',\r\n component: lazy(() => import('pages/debitMemo/EditDebitMemo')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/quotes/detail/:id',\r\n component: lazy(() => import('pages/financePurchaseQuotes/DetailFinancePurchaseQuote')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/quotes/import',\r\n component: lazy(() => import('pages/financePurchaseQuotes/Import')),\r\n exact: true,\r\n },\r\n {\r\n path: '/debit-memo/detail/:id',\r\n component: lazy(() => import('pages/debitMemo/DetailDebitMemo')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/debit-memo/add/:idContact',\r\n component: lazy(() => import('pages/debitMemo/AddDebitMemo')),\r\n exact: true,\r\n },\r\n {\r\n path: '/purchases/deliveries',\r\n component: lazy(() => import('pages/financePurchaseDelivery')),\r\n exact: true,\r\n },\r\n {\r\n path: '/purchases/deliveries/add/:idOrder?',\r\n component: lazy(() => import('pages/financePurchaseDelivery/AddFinancePurchaseDelivery')),\r\n exact: true,\r\n },\r\n {\r\n path: '/purchases/deliveries/detail/:id',\r\n component: lazy(() => import('pages/financePurchaseDelivery/DetailFinancePurchaseDelivery')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/deliveries/edit/:id',\r\n component: lazy(() => import('pages/financePurchaseDelivery/EditFinancePurchaseDelivery')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/returns/add/:idInvoice?',\r\n component: lazy(() => import('pages/purchaseReturn/AddReturn')),\r\n exact: true,\r\n },\r\n {\r\n path: '/purchases/returns/detail/:id',\r\n component: lazy(() => import('pages/purchaseReturn/DetailReturn')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/returns/edit/:id',\r\n component: lazy(() => import('pages/purchaseReturn/EditReturn')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/settings/business-flow',\r\n component: lazy(() => import('pages/businessFlow')),\r\n exact: true,\r\n // breadcrumb: 'Automatic Sequencing'\r\n },\r\n {\r\n path: '/purchases/purchaseinvoices/recurring/add',\r\n component: lazy(() => import('pages/recurring/Add')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/purchaseinvoices/recurring/edit/:id',\r\n component: lazy(() => import('pages/recurring/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/purchaseorders/recurring/add',\r\n component: lazy(() => import('pages/recurring/Add')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchases/purchaseorders/recurring/edit/:id',\r\n component: lazy(() => import('pages/recurring/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/expenses/recurring/add',\r\n component: lazy(() => import('pages/recurring/Add')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/expenses/recurring/edit/:id',\r\n component: lazy(() => import('pages/recurring/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/manual-journal/recurring/add',\r\n component: lazy(() => import('pages/recurring/Add')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/manual-journal/recurring/edit/:id',\r\n component: lazy(() => import('pages/recurring/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/:bankAccountId/recurring/add',\r\n component: lazy(() => import('pages/recurring/Add')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/banks/:bankAccountId/recurring/edit/:id',\r\n component: lazy(() => import('pages/recurring/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/closing',\r\n component: lazy(() => import('pages/closing')),\r\n exact: true,\r\n },\r\n {\r\n path: '/closing/add',\r\n component: lazy(() => import('pages/closing/Add')),\r\n // exact: true,\r\n },\r\n {\r\n path: '/closing/detail/:id',\r\n component: lazy(() => import('pages/closing/Detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/invoice-payment-credit-memo/detail/:id',\r\n component: lazy(() => import('pages/invoicePaymentCreditMemo/Detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchaseinvoice-payment-debit-memo/detail/:id',\r\n component: lazy(() => import('pages/purchaseInvoicePaymentDebitMemo/Detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/invoice-payment-credit-memo/edit/:id',\r\n component: lazy(() => import('pages/invoicePaymentCreditMemo/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/purchaseinvoice-payment-debit-memo/edit/:id',\r\n component: lazy(() => import('pages/purchaseInvoicePaymentDebitMemo/Edit')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/unrealized-gain/detail/:id',\r\n component: lazy(() => import('pages/unrealizedGain/Detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/payroll',\r\n component: lazy(() => import('pages/payroll')),\r\n exact: true,\r\n // breadcrumb: null,\r\n },\r\n {\r\n path: '/payroll/success',\r\n component: lazy(() => import('pages/payroll/SuccessIntegration')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/faqs',\r\n component: lazy(() => import('pages/faqs')),\r\n exact: true,\r\n },\r\n {\r\n path: '/faqs/detail/:id',\r\n component: lazy(() => import('pages/faqs/Detail')),\r\n exact: true,\r\n breadcrumb: null,\r\n },\r\n {\r\n path: '/pos',\r\n component: lazy(() => import('pages/kledoPos')),\r\n exact: true,\r\n breadcrumb: 'Kledo Pos',\r\n },\r\n {\r\n path: '/pos/settings',\r\n component: lazy(() => import('pages/kledoPos/Settings')),\r\n exact: true,\r\n },\r\n {\r\n path: '/pos/outlets',\r\n component: lazy(() => import('pages/outlets/Outlets')),\r\n exact: true,\r\n },\r\n {\r\n path: '/pos/product-favorites',\r\n component: lazy(() => import('pages/financeProducts/Favorites')),\r\n exact: true,\r\n },\r\n {\r\n path: '/pos/users',\r\n component: lazy(() => import('pages/pos/users')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/due-reminder',\r\n component: lazy(() => import('pages/dueReminder')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/backup-database',\r\n component: lazy(() => import('pages/backupDatabase')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/customer-birthday',\r\n component: lazy(() => import('pages/customerBirthday')),\r\n exact: true,\r\n },\r\n {\r\n path: '/pos/outlets',\r\n component: lazy(() => import('pages/outlets/Outlets')),\r\n exact: true,\r\n },\r\n {\r\n path: '/pos/product-favorites',\r\n component: lazy(() => import('pages/financeProducts/Favorites')),\r\n exact: true,\r\n },\r\n {\r\n path: '/pos/users',\r\n component: lazy(() => import('pages/pos/users')),\r\n exact: true,\r\n },\r\n {\r\n path: '/kledo-pos',\r\n component: lazy(() => import('pages/kledoPos')),\r\n exact: true,\r\n breadcrumb: 'Kledo POS',\r\n },\r\n {\r\n path: '/settings/fees',\r\n component: lazy(() => import('pages/transactionFees')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/sso',\r\n component: lazy(() => import('pages/sso')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/payment-connect',\r\n component: lazy(() => import('pages/paymentConnect')),\r\n exact: true,\r\n },\r\n {\r\n path: '/settings/payment-connect/:id',\r\n component: lazy(() => import('pages/paymentConnect/detail')),\r\n exact: true,\r\n },\r\n]\r\n\r\nexport default routes\r\n","import React from 'react'\r\nimport { Link } from 'react-router-dom'\r\nimport withBreadcrumbs from 'react-router-breadcrumbs-hoc'\r\nimport { injectIntl } from 'react-intl'\r\nimport { Skeleton } from 'antd'\r\nimport { connect } from 'react-redux'\r\nimport dayjs from 'dayjs'\r\n\r\n// import _ from 'lodash';\r\n// import setupRoutes from 'containers/Setup/routes';\r\nimport financeBankRoutes from 'containers/FinanceBanks/routes'\r\nimport { getTerm } from 'utils/hooks/useTerm'\r\nimport routeConfig from '../../../routes'\r\nimport styles from './style.module.scss'\r\n\r\nconst mapStateToProps = ({\r\n inits: { loadedInit },\r\n billing,\r\n menu,\r\n options: { options },\r\n settings,\r\n finance: {\r\n warehouse: { warehouses },\r\n bankAccounts,\r\n paymentConnectProviders,\r\n },\r\n translation,\r\n}) => ({\r\n billing,\r\n menuLeftData: menu.menuLeftData,\r\n isMobileView: settings.isMobileView,\r\n darkMode: options.dark_mode,\r\n warehouses,\r\n accounts: bankAccounts,\r\n translation,\r\n loadedInit,\r\n paymentConnectProviders,\r\n})\r\n\r\n@connect(mapStateToProps)\r\nclass Breadcrumbs extends React.PureComponent {\r\n getWarehouseName = (id) => {\r\n const { warehouses } = this.props\r\n let name = ''\r\n if (id) {\r\n const findWarehouse = warehouses.find((row) => row.id === id)\r\n name = findWarehouse ? findWarehouse.name : ''\r\n }\r\n\r\n return name\r\n }\r\n\r\n getAccountName = (id) => {\r\n const { accounts } = this.props\r\n let name = ''\r\n if (id) {\r\n const findAccount = accounts.find((row) => row.id === id)\r\n name = findAccount ? findAccount.name : ''\r\n }\r\n\r\n return name\r\n }\r\n\r\n render() {\r\n const {\r\n loadedInit,\r\n breadcrumbs,\r\n menuLeftData,\r\n isMobileView,\r\n intl,\r\n billing,\r\n paymentConnectProviders,\r\n darkMode,\r\n translation: { menu = {}, reportmenu = {}, term = {} },\r\n } = this.props\r\n\r\n if (isMobileView) {\r\n return \r\n }\r\n\r\n const _term = getTerm({ intl, term })\r\n\r\n const countBreadCrumb = breadcrumbs.length\r\n const arrMenuLeft = []\r\n ;(menuLeftData || []).forEach((data) => {\r\n if (data.children) {\r\n ;(data.children || []).forEach((chil) => arrMenuLeft.push(chil))\r\n }\r\n const newData = { ...data }\r\n delete newData.children\r\n arrMenuLeft.push(newData)\r\n })\r\n\r\n return (\r\n \r\n {!loadedInit ? (\r\n
\r\n ) : (\r\n
\r\n {breadcrumbs.map((bread, index) => {\r\n const { match, breadcrumb } = bread\r\n const findRoute = arrMenuLeft.find((v) => v.url === match.url)\r\n let link = null\r\n\r\n if (index === breadcrumbs.length - 1) {\r\n link = {breadcrumb}\r\n }\r\n if (typeof breadcrumb.type === 'object') {\r\n link = breadcrumb\r\n }\r\n\r\n if (findRoute) {\r\n if (countBreadCrumb > 1 && index !== breadcrumbs.length - 1) {\r\n link = (\r\n \r\n {findRoute.title}\r\n \r\n )\r\n } else {\r\n link = {findRoute.title}\r\n }\r\n }\r\n\r\n if (match.url === '/sales') {\r\n link = (\r\n \r\n {menu.sales}\r\n \r\n )\r\n }\r\n if (match.url === '/sales/invoices') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.invoices}\r\n } else {\r\n link = (\r\n \r\n {menu.invoices}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/sales/quotes') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.quotes}\r\n } else {\r\n link = (\r\n \r\n {menu.quotes}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/sales/orders') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.orders}\r\n } else {\r\n link = (\r\n \r\n {menu.orders}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/sales/deliveries') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.deliveries}\r\n } else {\r\n link = (\r\n \r\n {menu.deliveries}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/sales/overview') {\r\n link = {menu.overview}\r\n }\r\n if (match.url === '/sales/returns') {\r\n link = (\r\n \r\n {menu.returns}\r\n \r\n )\r\n }\r\n\r\n if (match.url === '/purchases') {\r\n link = (\r\n \r\n {menu.purchases}\r\n \r\n )\r\n }\r\n if (match.url === '/purchases/purchaseinvoices') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.purchase_invoices}\r\n } else {\r\n link = (\r\n \r\n {menu.purchase_invoices}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/purchases/purchaseorders') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.purchase_orders}\r\n } else {\r\n link = (\r\n \r\n {menu.purchase_orders}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/purchases/quotes') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.purchase_quotes}\r\n } else {\r\n link = (\r\n \r\n {menu.purchase_quotes}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/purchases/deliveries') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.purchase_deliveries}\r\n } else {\r\n link = (\r\n \r\n {menu.purchase_deliveries}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/purchases/overview') {\r\n link = {menu.overview}\r\n }\r\n if (match.url === '/purchases/returns') {\r\n link = (\r\n \r\n {menu.purchase_returns}\r\n \r\n )\r\n }\r\n\r\n if (match.url === '/pos') {\r\n link = (\r\n \r\n {menu.pos}\r\n \r\n )\r\n }\r\n if (match.url === '/pos/product-favorites') {\r\n link = {menu.pos_product_favorites}\r\n }\r\n if (match.url === '/pos/users') link = {menu.pos_cashier_users}\r\n if (match.url === '/pos/outlets') link = {menu.pos_outlets}\r\n\r\n if (match.url === '/accounts/conversionbalances/conversiondate') {\r\n link = {intl.formatMessage({ id: 'breadcrumb.conversiondate' })}\r\n }\r\n if (match.url === '/accounts/conversionbalances') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = (\r\n {intl.formatMessage({ id: 'breadcrumb.conversionbalances' })}\r\n )\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'breadcrumb.conversionbalances' })}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (match.url === '/dashboard') {\r\n link = {menu.home}\r\n }\r\n\r\n if (match.url === '/billing/upgrade') {\r\n link = (\r\n \r\n {billing.expiry_date &&\r\n dayjs().subtract(1, 'days').isAfter(billing.expiry_date) &&\r\n billing.can_be_renewed\r\n ? intl.formatMessage({ id: 'billing.renew' })\r\n : intl.formatMessage({ id: 'billing.upgrade' })}\r\n \r\n )\r\n }\r\n if (match.url === '/billing') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.billing}\r\n } else {\r\n link = (\r\n \r\n {menu.billing}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (match.url === '/reports') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.reports}\r\n } else {\r\n link = (\r\n \r\n {menu.reports}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (match.url === '/companies') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'companies.company_list' })}\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'companies.company_list' })}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (match.url === '/settings') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.settings}\r\n } else {\r\n link = (\r\n \r\n {menu.settings}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/settings/account-mapping') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = (\r\n {intl.formatMessage({ id: 'accountMapping.account_mappinng' })}\r\n )\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'accountMapping.account_mappinng' })}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/settings/apps') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'appSetting.apps' })}\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'appSetting.apps' })}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/settings/multi-currency') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = (\r\n {intl.formatMessage({ id: 'multiCurrency.multi_currency' })}\r\n )\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'multiCurrency.multi_currency' })}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/settings/marketplaceConnect') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = Marketplace Connect\r\n } else {\r\n link = (\r\n \r\n Marketplace Connect\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/settings/sales-commissions') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'salesCommission.sales_commission' })}\r\n \r\n )\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'salesCommission.sales_commission' })}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (match.url === '/reports/sales-per-period') {\r\n link = {reportmenu.sales_per_period}\r\n }\r\n if (match.url === '/reports/purchases-per-period') {\r\n link = {reportmenu.purchases_per_period}\r\n }\r\n if (match.url === '/reports/receivable-payable-per-contact') {\r\n link = {reportmenu.payable_credit_per_contact}\r\n }\r\n if (match.url === '/accounts/conversionbalances/opening_balance') {\r\n link = (\r\n {intl.formatMessage({ id: 'financeConversion.opening_balance' })}\r\n )\r\n }\r\n if (match.url === '/accounts/conversionbalances/reversal_detail') {\r\n link = (\r\n {intl.formatMessage({ id: 'financeConversion.reversal_detail' })}\r\n )\r\n }\r\n if (match.url === '/reports/inventory-summary') {\r\n link = {reportmenu.inventory_summary}\r\n }\r\n if (match.url === '/reports/inventory-stock-movement') {\r\n link = {reportmenu.inventory_stock_movement}\r\n }\r\n if (match.url === '/reports/warehouse-stock-summary') {\r\n link = {reportmenu.warehouse_stock_summary}\r\n }\r\n if (match.url === '/reports/warehouse-stock-movement') {\r\n link = {reportmenu.warehouse_stock_movement}\r\n }\r\n if (match.url === '/reports/inventory-stock-adjustment') {\r\n link = {reportmenu.report_inventory_stock_adjustment}\r\n }\r\n if (match.url === '/reports/warehouse-transfer') {\r\n link = {reportmenu.inventory_warehouse_transfer}\r\n }\r\n if (match.url === '/reports/production') {\r\n link = {reportmenu.production}\r\n }\r\n if (match.url === '/reports/shipping-cost-per-expedition') {\r\n link = {reportmenu.shipping_cost_per_expedition}\r\n }\r\n if (match.url === '/reports/sales-per-sales-person') {\r\n link = {reportmenu.sales_per_sales_person}\r\n }\r\n if (match.url === '/reports/product-profitability') {\r\n link = {reportmenu.profitability_product}\r\n }\r\n if (match.url === '/reports/profitability-per-invoice') {\r\n link = {reportmenu.profitability_per_invoice}\r\n }\r\n if (match.url === '/reports/invoice-payment') {\r\n link = {reportmenu.invoice_payment}\r\n }\r\n if (match.url === '/reports/product-sales-per-customer') {\r\n link = {reportmenu?.product_sales_per_customer}\r\n }\r\n if (match.url === '/reports/sales-per-product-category') {\r\n link = {reportmenu.sales_per_product_category}\r\n }\r\n if (match.url === '/reports/product-purchases-per-vendor') {\r\n link = {reportmenu?.product_purchases_per_supplier}\r\n }\r\n if (match.url === '/reports/purchase-invoice-payment') {\r\n link = {reportmenu.purchases_invoice_payment}\r\n }\r\n if (match.url === '/reports/general-ledger') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {reportmenu.general_ledger}\r\n } else {\r\n link = (\r\n \r\n {reportmenu.general_ledger}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/reports/general-ledger/category') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'report.category' })}\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'report.category' })}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/reports/journal') {\r\n link = {reportmenu.journal}\r\n }\r\n if (match.url === '/reports/bank-summary') {\r\n link = {reportmenu.bank_summary}\r\n }\r\n if (match.url === '/reports/sales-tax') {\r\n link = {reportmenu.sales_tax}\r\n }\r\n if (match.url === '/reports/witholding-tax') {\r\n link = {reportmenu.witholding_tax}\r\n }\r\n if (match.url === '/reports/customer-invoice') {\r\n link = {reportmenu.customer_invoice}\r\n }\r\n if (match.url === '/reports/supplier-invoice') {\r\n link = {reportmenu.supplier_invoice}\r\n }\r\n if (match.url === '/reports/sales-detail') {\r\n link = {reportmenu.sales_detail}\r\n }\r\n if (match.url === '/reports/purchase-detail') {\r\n link = {reportmenu.purchase_detail}\r\n }\r\n if (match.url === '/reports/aged-payable') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {reportmenu.aged_payables}\r\n } else {\r\n link = (\r\n \r\n {reportmenu.aged_payables}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/reports/aged-receivable') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {reportmenu.aged_receivables}\r\n } else {\r\n link = (\r\n \r\n {reportmenu.aged_receivables}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/reports/expense-claim') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {reportmenu.expense_claim_detail}\r\n } else {\r\n link = (\r\n \r\n {reportmenu.expense_claim_detail}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (match.url === '/reports/import') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'button.import' })}\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'button.import' })}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (\r\n match.url === '/sales/invoices/recurring' ||\r\n match.url === '/sales/orders/recurring' ||\r\n match.url === '/purchases/purchaseinvoices/recurring' ||\r\n match.url === '/purchases/purchaseorders/recurring' ||\r\n match.url === '/expenses/recurring' ||\r\n match.url === '/manual-journal/recurring' ||\r\n /banks\\/[0-9]+\\/recurring$/.test(match.url) ||\r\n /banks\\/detail\\/[0-9]+\\/recurring$/.test(match.url)\r\n ) {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'recurring.recurring' })}\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'recurring.recurring' })}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (match.url === '/reports/income-per-customer') {\r\n link = {reportmenu.income_per_customer}\r\n }\r\n if (match.url === '/reports/trial-balance') {\r\n link = {reportmenu.trial_balance}\r\n }\r\n if (match.url === '/reports/profit-loss') {\r\n link = {reportmenu.profit_and_loss}\r\n }\r\n if (match.url === '/reports/expense-per-contact') {\r\n link = {reportmenu.expense_per_contact}\r\n }\r\n if (match.url === '/reports/sales-per-product') {\r\n link = {reportmenu.sales_per_product}\r\n }\r\n if (match.url === '/reports/order-per-product') {\r\n link = {reportmenu.order_per_product}\r\n }\r\n if (match.url === '/reports/purchases-per-vendor') {\r\n link = {reportmenu.purchases_per_supplier}\r\n }\r\n if (match.url === '/reports/purchases-per-product') {\r\n link = {reportmenu.purchases_per_product}\r\n }\r\n if (match.url === '/reports/cash-flow') {\r\n link = {reportmenu.cash_flow}\r\n }\r\n if (match.url === '/reports/balance-sheet') {\r\n link = {reportmenu.balance_sheet}\r\n }\r\n if (match.url === '/reports/equity-movement') {\r\n link = {reportmenu.equity_movement}\r\n }\r\n if (match.url === '/reports/executive-summary') {\r\n link = {reportmenu.executive_summary}\r\n }\r\n if (match.url === '/reports/account-transaction') {\r\n link = (\r\n \r\n {intl.formatMessage(\r\n { id: 'report.account_transactions_title' },\r\n { account: '' },\r\n )}\r\n \r\n )\r\n }\r\n if (match.url === '/reports/fixed-asset-detail') {\r\n link = {reportmenu.fixed_asset_detail}\r\n }\r\n if (match.url === '/reports/fixed-asset-summary') {\r\n link = {reportmenu.fixed_asset_summary}\r\n }\r\n if (match.url === '/reports/fixed-asset-disposal') {\r\n link = {reportmenu.fixed_asset_disposal}\r\n }\r\n if (match.url === '/reports/consolidation-balance-sheet') {\r\n link = {`${reportmenu.balance_sheet} ${menu.consolidation}`}\r\n }\r\n if (match.url === '/reports/consolidation-cash-flow') {\r\n link = {`${reportmenu.cash_flow} ${menu.consolidation}`}\r\n }\r\n if (match.url === '/reports/consolidation-profit-loss') {\r\n link = {`${reportmenu.profit_and_loss} ${menu.consolidation}`}\r\n }\r\n if (match.url === '/reports/consolidation-worksheet') {\r\n link = {`${reportmenu.worksheet} ${menu.consolidation}`}\r\n }\r\n if (match.url === '/reports/sales-delivery') {\r\n link = {reportmenu.sales_delivery}\r\n }\r\n if (match.url === '/reports/purchase-delivery') {\r\n link = {reportmenu.purchase_delivery}\r\n }\r\n if (match.url === '/reports/budget-management') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {reportmenu.budget}\r\n } else {\r\n link = (\r\n \r\n {reportmenu.budget}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/reports/budget-profit-loss') {\r\n link = {reportmenu.budget_profit_loss}\r\n }\r\n if (match.url === '/manual-journal') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'financeManualJournal.financeManualJournal' })}\r\n \r\n )\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'financeManualJournal.financeManualJournal' })}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/closing') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'financeClosing.closing' })}\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'financeClosing.closing' })}\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/fixed-assets/transaction') {\r\n link = (\r\n {intl.formatMessage({ id: 'financeFixedAssets.transactions' })}\r\n )\r\n }\r\n if (match.url === '/fixed-assets/run-depreciation') {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'financeFixedAssets.run_depreciation' })}\r\n \r\n )\r\n }\r\n\r\n if (match.url === '/layout-invoice') {\r\n link = {menu.layout_invoice}\r\n }\r\n\r\n if (match.url === '/settings/layout-report') {\r\n link = {intl.formatMessage({ id: 'layoutReport.layout_report' })}\r\n }\r\n\r\n if (match.url === '/settings/backup-database') {\r\n link = {menu.finance_backup_database}\r\n }\r\n\r\n const splitUrl = match.url.split('/')\r\n const lastUrl = splitUrl[splitUrl.length - 1]\r\n\r\n // Bank custom breadcrumbs\r\n if (/banks\\/[0-9]+$/.test(match.url) || /banks\\/detail\\/[0-9]+$/.test(match.url)) {\r\n const id = parseInt(lastUrl, 10)\r\n link = (\r\n \r\n {this.getAccountName(id)}\r\n \r\n )\r\n }\r\n\r\n if (/banks\\/[0-9]+\\/spend$/.test(match.url)) {\r\n link = {intl.formatMessage({ id: 'financeBanks.spend_money' })}\r\n }\r\n\r\n if (\r\n /banks\\/[0-9]+\\/spend\\/[0-9]+$/.test(match.url) ||\r\n /banks\\/[0-9]+\\/receive\\/[0-9]+$/.test(match.url)\r\n ) {\r\n link = null\r\n }\r\n\r\n if (/banks\\/[0-9]+\\/receive$/.test(match.url)) {\r\n link = {intl.formatMessage({ id: 'financeBanks.receive_money' })}\r\n }\r\n\r\n if (/banks\\/transaction$/.test(match.url)) {\r\n if (this.props.account.id) {\r\n link = {this.props.account.name}\r\n }\r\n }\r\n\r\n if (/banks\\/detail\\/[0-9]+\\/transactions$/.test(match.url)) {\r\n link = {intl.formatMessage({ id: 'financeBanks.transactions' })}\r\n }\r\n\r\n if (match.url === '/banks') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.cash_bank}\r\n } else {\r\n link = (\r\n \r\n {menu.cash_bank}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (match.url === '/banks/connect') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'financeBanks.bank_connect' })}\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'financeBanks.bank_connect' })}\r\n \r\n )\r\n }\r\n }\r\n\r\n // Warehouse Custom Breadcrumbs\r\n if (/warehouses\\/[0-9]+$/.test(match.url)) {\r\n const id = parseInt(lastUrl, 10)\r\n link = (\r\n \r\n {this.getWarehouseName(id)}\r\n \r\n )\r\n }\r\n\r\n if (match.url === '/warehouses/access' || /banks\\/[0-9]+\\/access$/.test(match.url)) {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'financeWareHouses.access' })}\r\n \r\n )\r\n }\r\n\r\n if (/warehouses\\/[0-9]+\\/transfer$/.test(match.url)) {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'financeWareHouses.transfer' })}\r\n \r\n )\r\n }\r\n\r\n if (/warehouses\\/[0-9]+\\/stock-adjustment$/.test(match.url)) {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'financeWareHouses.stock_adjustment' })}\r\n \r\n )\r\n }\r\n\r\n if (\r\n /warehouses\\/[0-9]+\\/transfer\\/detail\\/[0-9]+$/.test(match.url) ||\r\n /warehouses\\/[0-9]+\\/stock-adjustment\\/detail\\/[0-9]+$/.test(match.url)\r\n ) {\r\n link = {intl.formatMessage({ id: 'breadcrumb.detail' })}\r\n }\r\n\r\n if (lastUrl === 'import-recurring') {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'button.import' })}{' '}\r\n {intl.formatMessage({\r\n id: 'recurring.repeat',\r\n })}\r\n \r\n )\r\n }\r\n\r\n if (lastUrl === 'import-return') {\r\n link = (\r\n \r\n {intl.formatMessage({\r\n id: 'financeInvoices.import_invoice_return',\r\n })}\r\n \r\n )\r\n }\r\n\r\n if (lastUrl === 'transfer-in') {\r\n link = (\r\n {intl.formatMessage({ id: 'financeWareHouses.transfer_in' })}\r\n )\r\n }\r\n\r\n if (lastUrl === 'transfer-out') {\r\n link = (\r\n {intl.formatMessage({ id: 'financeWareHouses.transfer_out' })}\r\n )\r\n }\r\n\r\n if (lastUrl === 'add') {\r\n link = {intl.formatMessage({ id: 'breadcrumb.add' })}\r\n }\r\n\r\n if (splitUrl[splitUrl.length - 2] === 'add') {\r\n link = ''\r\n }\r\n\r\n if (lastUrl === 'edit') {\r\n link = {intl.formatMessage({ id: 'breadcrumb.edit' })}\r\n }\r\n\r\n if (lastUrl === 'detail' && index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'breadcrumb.detail' })}\r\n }\r\n\r\n if (lastUrl === 'email-template') {\r\n link = {menu.email_template}\r\n }\r\n\r\n if (lastUrl === 'due-reminder') {\r\n link = {menu.due_reminder}\r\n }\r\n\r\n if (lastUrl === 'taxes') {\r\n link = {menu.taxes}\r\n }\r\n\r\n if (lastUrl === 'unit') {\r\n link = {menu.units}\r\n }\r\n\r\n if (lastUrl === 'shipping-company' && index === breadcrumbs.length - 1) {\r\n link = {menu.shipping_comps}\r\n }\r\n\r\n if (lastUrl === 'expenses' && index === breadcrumbs.length - 1) {\r\n link = {menu.expenses}\r\n }\r\n\r\n if (lastUrl === 'products' && index === breadcrumbs.length - 1) {\r\n link = {menu.products}\r\n }\r\n\r\n if (\r\n index === breadcrumbs.length - 1 &&\r\n breadcrumbs[breadcrumbs.length - 1].match.path === '/products/access/:id'\r\n ) {\r\n link = {intl.formatMessage({ id: 'financeWareHouses.access' })}\r\n }\r\n\r\n if (lastUrl === 'price-rule') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {intl.formatMessage({ id: 'priceRule.price_rule' })}\r\n } else {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'priceRule.price_rule' })}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (lastUrl === 'import-package') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = (\r\n \r\n {`${intl.formatMessage({ id: 'button.import' })} ${intl.formatMessage({\r\n id: 'financeProduct.package',\r\n })}`}\r\n \r\n )\r\n } else {\r\n link = (\r\n \r\n {`${intl.formatMessage({ id: 'button.import' })} ${intl.formatMessage({\r\n id: 'financeProduct.package',\r\n })}`}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (lastUrl === 'import-manufacture') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = (\r\n \r\n {`${intl.formatMessage({ id: 'button.import' })} ${intl.formatMessage({\r\n id: 'financeProduct.manufacture',\r\n })}`}\r\n \r\n )\r\n } else {\r\n link = (\r\n \r\n {`${intl.formatMessage({ id: 'button.import' })} ${intl.formatMessage({\r\n id: 'financeProduct.manufacture',\r\n })}`}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (lastUrl === 'import-conversion') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = (\r\n \r\n {`${intl.formatMessage({ id: 'button.import' })} ${intl.formatMessage({\r\n id: 'financeProduct.conversion',\r\n })}`}\r\n \r\n )\r\n } else {\r\n link = (\r\n \r\n {`${intl.formatMessage({ id: 'button.import' })} ${intl.formatMessage({\r\n id: 'financeProduct.conversion',\r\n })}`}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (lastUrl === 'conversions' && index === breadcrumbs.length - 1) {\r\n link = (\r\n {intl.formatMessage({ id: 'financeProduct.product_conversion' })}\r\n )\r\n }\r\n\r\n if (lastUrl === 'finance-approval') {\r\n link = {menu?.approval}\r\n }\r\n\r\n if (lastUrl === 'approval-setting') {\r\n link = {menu?.finance_approval_setting}\r\n }\r\n\r\n if (lastUrl === 'tags' && index === breadcrumbs.length - 1) {\r\n link = {menu.tags}\r\n }\r\n\r\n if (match.url.includes('/settings/tags/access')) {\r\n link = {intl.formatMessage({ id: 'financeWareHouses.access' })}\r\n }\r\n\r\n if (lastUrl === 'contacts' && index === breadcrumbs.length - 1) {\r\n link = {menu.contacts}\r\n }\r\n\r\n if (lastUrl === 'import-accounts-payable' && index === breadcrumbs.length - 1) {\r\n link = (\r\n \r\n {intl.formatMessage(\r\n { id: 'financeContacts.import_contact_transactions_with_title' },\r\n {\r\n credit: _term.payable,\r\n debit: _term.receivable,\r\n },\r\n )}\r\n \r\n )\r\n }\r\n\r\n if (lastUrl === 'accounts' && index === breadcrumbs.length - 1) {\r\n link = {menu.accounts}\r\n }\r\n\r\n if (lastUrl === 'warehouses' && index === breadcrumbs.length - 1) {\r\n link = {menu.inventory}\r\n }\r\n\r\n if (lastUrl === 'company') {\r\n link = {menu.company}\r\n }\r\n\r\n if (lastUrl === 'payments') {\r\n link = {intl.formatMessage({ id: 'payments.payment_method' })}\r\n }\r\n\r\n if (lastUrl === 'custom-column') {\r\n link = {menu.custom_columns}\r\n }\r\n\r\n if (lastUrl === 'terms') {\r\n link = {menu.terms}\r\n }\r\n\r\n if (lastUrl === 'business-flow') {\r\n link = {menu.businessflow}\r\n }\r\n\r\n if (lastUrl === 'customer-birthday') {\r\n link = {menu.customer_birthday}\r\n }\r\n\r\n if (lastUrl === 'automatic-sequencing') {\r\n link = {menu.automatic_sequencing}\r\n }\r\n\r\n if (lastUrl === 'users' && match.url !== '/pos/users') {\r\n link = {menu.users}\r\n }\r\n\r\n if (lastUrl === 'roles' && index === breadcrumbs.length - 1) {\r\n link = {menu.roles}\r\n }\r\n\r\n if (lastUrl === 'profile') {\r\n link = {menu.my_profile}\r\n }\r\n\r\n if (lastUrl === 'consolidation') {\r\n link = {menu.consolidation}\r\n }\r\n\r\n if (match.url === '/setup') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = {menu.setup}\r\n } else {\r\n link = (\r\n \r\n {menu.setup}\r\n \r\n )\r\n }\r\n }\r\n\r\n if (lastUrl === 'clear-demo-data') {\r\n link = {intl.formatMessage({ id: 'setup.clear_demo_data' })}\r\n }\r\n\r\n if (lastUrl === 'add-room-types') {\r\n link = (\r\n \r\n {intl.formatMessage({ id: 'setup.setup_add_room_type_and_rooms' })}\r\n \r\n )\r\n }\r\n\r\n if (lastUrl === 'finish') {\r\n link = {intl.formatMessage({ id: 'setup.finish' })}\r\n }\r\n\r\n if (lastUrl === 'fixed-assets' && index === breadcrumbs.length - 1) {\r\n link = {menu.fixed_assets}\r\n }\r\n\r\n if (lastUrl === 'lock-date' && index === breadcrumbs.length - 1) {\r\n link = {menu.lock_date}\r\n }\r\n\r\n if (lastUrl === 'warehouses' && index === breadcrumbs.length - 1) {\r\n link = {menu.inventory}\r\n }\r\n\r\n if (lastUrl === 'credit-memo') {\r\n link = {_term.payable}\r\n }\r\n\r\n if (lastUrl === 'debit-memo') {\r\n link = {_term.receivable}\r\n }\r\n\r\n if (lastUrl === 'importStatus') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = Import Status\r\n } else {\r\n link = (\r\n \r\n Import Status\r\n \r\n )\r\n }\r\n }\r\n if (match.url === '/invoice-payment-credit-memo') {\r\n link = (\r\n \r\n {intl.formatMessage({\r\n id: 'invoicePaymentCreditMemo.invoicePaymentCreditMemo',\r\n })}\r\n \r\n )\r\n }\r\n if (match.url === '/purchaseinvoice-payment-debit-memo') {\r\n link = (\r\n \r\n {intl.formatMessage({\r\n id: 'purchaseInvoicePaymentDebitMemo.purchaseInvoicePaymentDebitMemo',\r\n })}\r\n \r\n )\r\n }\r\n if (match.url === '/unrealized-gain') {\r\n link = (\r\n \r\n {intl.formatMessage({\r\n id: 'unrealizedGain.unrealizedGain',\r\n })}\r\n \r\n )\r\n }\r\n\r\n if (match.url === '/faqs') {\r\n if (index === breadcrumbs.length - 1) {\r\n link = FAQ\r\n } else {\r\n link = (\r\n \r\n FAQ\r\n \r\n )\r\n }\r\n }\r\n\r\n if (lastUrl === 'fees') {\r\n link = (\r\n \r\n {menu.fees ||\r\n intl.formatMessage({\r\n id: 'transactionFees.fees',\r\n })}\r\n \r\n )\r\n }\r\n\r\n if (match.url.includes('/settings/payment-connect/')) {\r\n link = (\r\n \r\n {paymentConnectProviders.find((provider) => provider.id === Number(lastUrl))\r\n ?.name ?? 'Provider'}\r\n \r\n )\r\n }\r\n\r\n if (lastUrl === 'access-per-contact') {\r\n link = (\r\n \r\n {intl.formatMessage({\r\n id: 'financeWareHouses.per_contact_warehouse_access',\r\n })}\r\n \r\n )\r\n }\r\n\r\n if (!link) {\r\n return null\r\n }\r\n\r\n return (\r\n \r\n {countBreadCrumb > 1 && index > 0 && (\r\n \r\n )}\r\n {link}\r\n \r\n )\r\n })}\r\n
\r\n )}\r\n
\r\n )\r\n }\r\n}\r\n\r\nexport default withBreadcrumbs([\r\n ...routeConfig,\r\n // ...setupRoutes,\r\n ...financeBankRoutes,\r\n])(injectIntl(Breadcrumbs))\r\n","import React from 'react'\r\nimport { Modal } from 'antd'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\nimport { accountTransReportSelector } from 'redux/selectors'\r\nimport { hideAccountTransactionReport } from 'redux/finance/actions'\r\nimport { Cancel } from 'components/UI'\r\nimport AccountTransactions from './index'\r\n\r\nconst AccountTransactionModal = () => {\r\n const dispatch = useDispatch()\r\n\r\n const accountTrans = useSelector(accountTransReportSelector)\r\n\r\n const hideHandler = () => dispatch(hideAccountTransactionReport())\r\n return (\r\n ]}\r\n maskTransitionName=\"\"\r\n width=\"90%\"\r\n styles={{ body: { paddingTop: 40 }}}\r\n >\r\n \r\n \r\n )\r\n}\r\n\r\nexport default AccountTransactionModal\r\n","import React, { useMemo, useState, useRef } from \"react\";\r\nimport { Button, Col, Popover, Progress, Row, Space, Spin, Typography } from \"antd\";\r\nimport { injectIntl } from \"react-intl\";\r\nimport { useDispatch, useSelector } from \"react-redux\";\r\nimport { darkModeSelector, mobileViewSelector, optionsSelector } from 'redux/selectors';\r\nimport { CheckOutlined, ExclamationCircleFilled } from \"@ant-design/icons\";\r\nimport { useOnboardingStatus } from \"utils/queries\";\r\nimport { Link } from \"react-router-dom\";\r\nimport { Delete } from \"components/UI\";\r\nimport { editOption } from \"redux/options/actions\";\r\nimport { useQueryClient } from \"react-query\";\r\nimport styles from \"./style.module.scss\";\r\n\r\nconst Onboarding = ({ intl }) => {\r\n const [isLoadingOnboarding, setIsLoadingOnboarding] = useState(false)\r\n const [open, setOpen] = useState(false)\r\n const isMobileView = useSelector(mobileViewSelector)\r\n const options = useSelector(optionsSelector)\r\n const darkMode = useSelector(darkModeSelector)\r\n const popoverRef = useRef(null)\r\n const dispatch = useDispatch()\r\n const queryClient = useQueryClient()\r\n\r\n const { data, isLoading } = useOnboardingStatus()\r\n\r\n const visibleChangeHandler = (newOpen) => {\r\n if (newOpen) {\r\n setIsLoadingOnboarding(true); // Set isLoadingOnboarding to true when the popover is opened\r\n queryClient.invalidateQueries(['onboarding-status'])\r\n .then(() => setIsLoadingOnboarding(false)) // Set isLoadingOnboarding to false when the query is completed\r\n .catch(() => setIsLoadingOnboarding(false)); // Handle errors and set isLoadingOnboarding to false\r\n }\r\n setOpen(newOpen);\r\n };\r\n\r\n const formattedData = useMemo(() => {\r\n function isChecklistDone(checklistId) {\r\n const progress = data?.progress_detail.find(item => item.checklist_id === checklistId);\r\n return progress ? progress?.completed_at !== null : false;\r\n }\r\n\r\n const newData = [];\r\n\r\n if (data && data?.checklist && Array.isArray(data?.checklist)) {\r\n (data?.checklist ?? []).forEach((item) => {\r\n newData.push({\r\n id: item.id,\r\n app_id: item.app_id,\r\n title: item.title,\r\n desc: item.desc,\r\n button_text: item.button_text,\r\n button_dest: item.button_dest,\r\n position: item.position,\r\n isDone: isChecklistDone(item.id),\r\n });\r\n });\r\n }\r\n\r\n return newData;\r\n }, [data]);\r\n\r\n const handleNavigationButton = () => {\r\n\r\n };\r\n\r\n const handleDismissButton = () => {\r\n dispatch(\r\n editOption({\r\n dismiss_onboarding_checklist: 1,\r\n }),\r\n )\r\n };\r\n\r\n const renderSubContent = (item) => {\r\n return (\r\n \r\n \r\n \r\n \r\n \r\n \r\n {item.title}\r\n {item.desc}\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n
\r\n \r\n
\r\n );\r\n };\r\n\r\n const renderContent = () => {\r\n return (\r\n <>\r\n \r\n \r\n
\r\n {intl.formatMessage({ id: 'onBoarding.checklist_greeting' })}\r\n \r\n \r\n {data?.progress?.completed_percentage}%\r\n \r\n \r\n \r\n \r\n
\r\n \r\n {formattedData?.map((item) => {\r\n return (\r\n
\r\n \r\n
\r\n \r\n
\r\n
\r\n {item.title}\r\n \r\n
\r\n \r\n );\r\n })}\r\n {\r\n (!isLoading && data?.progress?.completed_percentage === 100) &&\r\n
handleDismissButton()} />\r\n }\r\n \r\n \r\n >\r\n );\r\n };\r\n\r\n return (\r\n {\r\n visibleChangeHandler(visible);\r\n if (!visible) {\r\n setOpen(false);\r\n }\r\n }}\r\n ref={popoverRef}\r\n >\r\n \r\n }\r\n style={{\r\n right: \"1rem\",\r\n bottom: options.chat_support ? \"4rem\" : \"1rem\",\r\n position: \"fixed\",\r\n backgroundColor: \"#4777F3\",\r\n borderColor: \"#6C92F5\",\r\n outline: \"none\",\r\n boxShadow: 'none',\r\n zIndex: 15,\r\n height: isMobileView ? '' : 48,\r\n width: isMobileView ? '' : 48,\r\n }}\r\n />\r\n \r\n );\r\n};\r\n\r\nexport default injectIntl(Onboarding);\r\n","import React from 'react'\r\nimport { Button, Card, Carousel, Modal } from 'antd'\r\nimport { injectIntl } from 'react-intl'\r\nimport { BackwardOutlined, CloseOutlined, ForwardOutlined } from '@ant-design/icons'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\nimport _ from 'lodash'\r\n\r\nimport Player from 'components/UI/ModalPlayer/Player'\r\nimport { broadcastSelector } from 'redux/selectors'\r\nimport { hideBroadcast, markAsRead } from 'redux/broadcast/actions'\r\n\r\nconst Media = ({ videoId, imageUrl, title }) => {\r\n if (!_.isEmpty(videoId)) {\r\n return (\r\n \r\n )\r\n }\r\n\r\n if (!_.isEmpty(imageUrl) && _.isEmpty(videoId)) {\r\n return
\r\n }\r\n\r\n return null\r\n}\r\n\r\nconst BroadcastModal = ({ intl }) => {\r\n const dispatch = useDispatch()\r\n const carouselRef = React.useRef()\r\n const [activeSlide, setActiveSlide] = React.useState(0)\r\n const [viewedSlide, setViewedSlide] = React.useState([0])\r\n\r\n const broadcast = useSelector(broadcastSelector)\r\n const hideHandler = () => dispatch(hideBroadcast())\r\n const afterCloseHandler = () => dispatch(markAsRead({ data: getViewedIds() }))\r\n\r\n const goBackHandler = () => carouselRef.current.prev()\r\n const goNextHandler = () => carouselRef.current.next()\r\n const beforeChangeHandler = (current, next) => {\r\n setActiveSlide(next)\r\n if (!_.includes(viewedSlide, next)) {\r\n setViewedSlide([...viewedSlide, next])\r\n }\r\n }\r\n\r\n const getViewedIds = React.useCallback(() => {\r\n const ids = []\r\n viewedSlide.forEach((i) => {\r\n if (broadcast.data[i] && !_.includes(ids, i)) {\r\n ids.push(broadcast.data[i].id)\r\n }\r\n })\r\n return ids\r\n }, [viewedSlide, broadcast])\r\n\r\n const actions = React.useMemo(() => {\r\n const act = []\r\n if (activeSlide > 0) {\r\n act.push(\r\n }\r\n >\r\n {intl.formatMessage({ id: 'button.prev' })}\r\n ,\r\n )\r\n }\r\n if (activeSlide < broadcast.data.length - 1) {\r\n act.push(\r\n }\r\n >\r\n {intl.formatMessage({ id: 'button.next' })}\r\n ,\r\n )\r\n }\r\n return act\r\n // eslint-disable-next-line react-hooks/exhaustive-deps\r\n }, [broadcast, activeSlide])\r\n\r\n return (\r\n 0 ? actions : null}\r\n closable={false}\r\n width={460}\r\n styles={{ body: { textAlign: 'center', padding: 0 }}}\r\n maskClosable={false}\r\n afterClose={afterCloseHandler}\r\n style={{ paddingBottom: 0 }}\r\n >\r\n }\r\n style={{ top: -6, right: -6 }}\r\n danger\r\n size=\"small\"\r\n onClick={hideHandler}\r\n />\r\n \r\n {broadcast.data.map((row) => {\r\n return (\r\n \r\n \r\n }\r\n >\r\n \r\n \r\n
\r\n )\r\n })}\r\n \r\n \r\n )\r\n}\r\n\r\nexport default injectIntl(BroadcastModal)\r\n","import * as api from 'utils/apis/nps'\r\nimport * as actionTypes from 'redux/actionTypes'\r\n\r\nexport const hideNPSRedux = () => {\r\n return {\r\n type: actionTypes.HIDE_NPS,\r\n }\r\n}\r\n\r\nexport const ignoreNPS = () => {\r\n return (dispatch) => {\r\n return api.ignoreNPS().then((response) => {\r\n dispatch(hideNPSRedux())\r\n return response\r\n })\r\n }\r\n}\r\n\r\nexport const postNPS = (payload) => {\r\n return (dispatch) => {\r\n return api.postNPS(payload).then((response) => {\r\n dispatch(hideNPSRedux())\r\n return response\r\n })\r\n }\r\n}\r\n","import axios from 'axios'\r\n\r\nexport const postNPS = (data) => {\r\n return axios.post('/nps', data)\r\n}\r\n\r\nexport const ignoreNPS = () => {\r\n return axios.put('/nps/ignore')\r\n}\r\n","import React, { useState } from 'react';\r\nimport { useDispatch, useSelector } from 'react-redux';\r\nimport { injectIntl } from 'react-intl';\r\nimport { CloseOutlined, LoadingOutlined } from '@ant-design/icons';\r\nimport { Button, Card, Form, Input, message, Rate } from 'antd';\r\nimport { showNPSSelector } from 'redux/selectors';\r\nimport { ignoreNPS, postNPS } from 'redux/nps/actions';\r\nimport { Send } from 'components/UI';\r\n\r\nimport styles from './style.module.scss'\r\n\r\nconst Character = ({ index, value }) => {\r\n return (\r\n = index + 1 ? styles.focusedChar : ''}`}>\r\n {index}\r\n
\r\n );\r\n}\r\n\r\nconst NPS = ({ intl }) => {\r\n const [rate, setRate] = useState();\r\n const [loading, setLoading] = useState(false);\r\n const [loadingClose, setLoadingClose] = useState(false);\r\n const [sent, setSent] = useState(false);\r\n\r\n const dispatch = useDispatch();\r\n const showNPS = useSelector(showNPSSelector);\r\n\r\n const closeNPS = async () => {\r\n if (sent) {\r\n setSent(false);\r\n return;\r\n }\r\n if (loadingClose) return;\r\n try {\r\n setLoadingClose(true);\r\n const response = await dispatch(ignoreNPS());\r\n setLoadingClose(false);\r\n if (response.data.success) {\r\n message.success(response.data.message);\r\n } else {\r\n message.error(response.data.message);\r\n }\r\n } catch (e) {\r\n console.log(e);\r\n setLoadingClose(false);\r\n message.error(intl.formatMessage({ id: 'nps.cannot_hide_nps' }));\r\n }\r\n }\r\n\r\n const sendNPS = async (values) => {\r\n try {\r\n setLoading(true);\r\n const response = await dispatch(postNPS({\r\n ...values,\r\n score: rate - 1,\r\n }));\r\n setLoading(false);\r\n if (response.data.success) {\r\n setSent(true);\r\n message.success(response.data.message);\r\n } else {\r\n message.error(response.data.message);\r\n }\r\n } catch (e) {\r\n console.log(e);\r\n setLoading(false);\r\n message.error(intl.formatMessage({ id: 'nps.cannot_send_nps' }));\r\n }\r\n }\r\n\r\n if ((showNPS === 0 || showNPS === null) && !sent) {\r\n return <>>;\r\n }\r\n\r\n return (\r\n \r\n : }\r\n onClick={closeNPS}\r\n />\r\n {!sent && (\r\n <>\r\n setRate(val)} value={rate} />\r\n \r\n 0{` - ${intl.formatMessage({ id: 'nps.not_likely' })}`}\r\n 10{` - ${intl.formatMessage({ id: 'nps.very_likely' })}`}\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n >\r\n )}\r\n \r\n );\r\n}\r\n\r\nexport default injectIntl(NPS);\r\n","import React, { useMemo, useState } from 'react'\r\nimport { Alert, message, Modal } from 'antd'\r\nimport { injectIntl } from 'react-intl'\r\nimport localStore from 'store'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\n\r\nimport { locationSelector, loginFormSelector, userSelector } from 'redux/selectors'\r\nimport { afterLoginHandler, hideLoginForm } from 'redux/user/actions'\r\nimport { setSelectedEndpoint } from 'redux/companies/actions'\r\nimport { singleLogin, verifyGoogleToken } from 'utils/apis'\r\nimport { setSavedEmail, setToken } from 'utils/cookies'\r\nimport { setErrorLoginForm } from 'redux/loginForm/actions'\r\nimport LoginForm from 'components/apps/User/Login'\r\nimport Sso from 'containers/Users/Login/Sso'\r\n\r\nconst LoginModal = ({ intl }) => {\r\n const [showSso, setShowSso] = useState(false)\r\n\r\n const dispatch = useDispatch()\r\n const user = useSelector(userSelector)\r\n const loginForm = useSelector(loginFormSelector)\r\n const location = useSelector(locationSelector)\r\n\r\n const [loading, setLoading] = React.useState(false)\r\n\r\n // Untuk pengecekan posisi halaman di form atau tidak\r\n const isSafeToReload = useMemo(() => {\r\n const avoidUrl = [\r\n 'add',\r\n 'edit',\r\n 'import',\r\n 'transfer',\r\n 'spend',\r\n 'receive',\r\n 'register',\r\n 'dispose',\r\n ]\r\n let safeToReload = true\r\n\r\n avoidUrl.forEach((url) => {\r\n if (location.pathname.includes(url)) {\r\n safeToReload = false\r\n }\r\n })\r\n return safeToReload\r\n }, [location.pathname])\r\n\r\n // Diparsing baseurl nya sesuai di base url axios\r\n const parseBaseUrl = (url) => {\r\n let baseURL = url.replace(/^(?:https?:\\/\\/)?(?:www\\.)?/i, '')\r\n baseURL = baseURL.replace(/\\/api\\/v1+$/, '')\r\n return baseURL\r\n }\r\n\r\n React.useEffect(() => {\r\n if (!loginForm.showLoginForm) {\r\n dispatch(setErrorLoginForm(null))\r\n }\r\n }, [dispatch, loginForm.showLoginForm])\r\n\r\n const hideHandler = () => dispatch(hideLoginForm())\r\n const login = async (values) => {\r\n try {\r\n setLoading(true)\r\n setSavedEmail(values.email)\r\n // dispatch(setErrorLoginForm(null));\r\n const response = await singleLogin(values.email, values.password, values.remember_me)\r\n setLoading(false)\r\n if (response.data.success) {\r\n // Jika dari api tidak ada return endpoint, untuk ambil endpoin dari config\r\n if (!response.data?.data?.init?.endpoint && !localStore.get('app.endpoint')) {\r\n response.data.data.endpoint = parseBaseUrl(response.config?.baseURL)\r\n }\r\n // Sebelum reload dicek dulu apakah posisi input data\r\n if (isSafeToReload) {\r\n dispatch(afterLoginHandler(response, {}, true))\r\n window.location.reload(true)\r\n } else {\r\n if (user.email === response.data?.data?.user?.email) {\r\n setToken(response.data.data.data.access_token, values.remember_me)\r\n // Jika dapat endpoint dari login dan di localstoragenya kosong\r\n if (response.data?.data?.init?.endpoint && !localStore.get('app.endpoint')) {\r\n dispatch(setSelectedEndpoint(response.data?.data?.init.endpoint))\r\n }\r\n } else {\r\n dispatch(afterLoginHandler(response, {}, true))\r\n }\r\n hideHandler()\r\n }\r\n } else {\r\n message.error(response.data.message)\r\n }\r\n } catch (e) {\r\n setLoading(false)\r\n if (e && e.data && e.data.message) {\r\n dispatch(setErrorLoginForm(e.data.message))\r\n }\r\n }\r\n }\r\n\r\n const onGoogleLogin = async (payload) => {\r\n if (payload?.code) {\r\n try {\r\n setLoading(true)\r\n const response = await verifyGoogleToken(payload.code)\r\n setLoading(false)\r\n if (response.data.success) {\r\n // if (user.email === response.data.data.user.email) {\r\n // setSavedEmail(response.data.data.user.email);\r\n // setToken(response.data.data.data.access_token);\r\n // } else {\r\n // dispatch(afterLoginHandler(response, { email: response.data.data.user.email }, true));\r\n // }\r\n // hideHandler();\r\n // Jika dari api tidak ada return endpoint, untuk ambil endpoin dari config\r\n if (!response.data?.data?.init?.endpoint && !localStore.get('app.endpoint')) {\r\n response.data.data.endpoint = parseBaseUrl(response.config?.baseURL)\r\n }\r\n // Sebelum reload dicek dulu apakah posisi input data\r\n if (isSafeToReload) {\r\n dispatch(afterLoginHandler(response, { email: response.data.data.user.email }, true))\r\n window.location.reload(true)\r\n } else {\r\n if (user.email === response.data?.data?.user?.email) {\r\n setToken(response.data.data.data.access_token, payload.remember_me)\r\n // Jika dapat endpoint dari login dan di localstoragenya kosong\r\n if (response.data?.data?.init?.endpoint && !localStore.get('app.endpoint')) {\r\n dispatch(setSelectedEndpoint(response.data?.data?.init.endpoint))\r\n }\r\n } else {\r\n dispatch(afterLoginHandler(response, { email: response.data.data.user.email }, true))\r\n }\r\n hideHandler()\r\n }\r\n } else {\r\n message.error(response.data.message)\r\n }\r\n } catch (e) {\r\n setLoading(false)\r\n if (e && e.data && e.data.message) {\r\n dispatch(setErrorLoginForm(e.data.message))\r\n }\r\n }\r\n }\r\n }\r\n\r\n return (\r\n \r\n \r\n \r\n {loginForm.message ||\r\n intl.formatMessage({ id: 'users.you_have_logged_out_automatically' })}\r\n \r\n
\r\n {loginForm.error && (\r\n \r\n )}\r\n
\r\n {showSso ? (\r\n setShowSso(false)} />\r\n ) : (\r\n setShowSso(true)}\r\n />\r\n )}\r\n \r\n )\r\n}\r\n\r\nexport default injectIntl(LoginModal)\r\n","import OneSignal from 'react-onesignal'\r\n\r\nconst init = ({ appId, userId, setInizialized }) => {\r\n OneSignal.init({\r\n appId,\r\n allowLocalhostAsSecureOrigin: true,\r\n notificationClickHandlerMatch: 'exact',\r\n notificationClickHandlerAction: 'navigate',\r\n promptOptions: {\r\n slidedown: {\r\n enabled: true,\r\n autoPrompt: true,\r\n timeDelay: 5,\r\n pageViews: 1,\r\n },\r\n },\r\n }).then(() => {\r\n setInizialized()\r\n // OneSignal.showSlidedownPrompt().then(() => {\r\n\r\n // })\r\n if (userId) {\r\n OneSignal.setExternalUserId(userId.toString())\r\n }\r\n\r\n OneSignal.isPushNotificationsEnabled((isEnabled) => {\r\n if (isEnabled) console.log('Push notifications are enabled!')\r\n else console.log('Push notifications are not enabled yet.')\r\n })\r\n\r\n OneSignal.on('notificationDisplay', (event) => {\r\n console.warn('OneSignal notification displayed:', event)\r\n })\r\n\r\n OneSignal.on('notificationDismiss', (event) => {\r\n console.warn('OneSignal notification dismissed:', event)\r\n })\r\n\r\n // OneSignal.addListenerForNotificationOpened((data) => {\r\n // console.log('Received NotificationOpened:')\r\n // onOpenNotification(data)\r\n // console.log(data)\r\n // })\r\n })\r\n\r\n return OneSignal\r\n}\r\n\r\nexport default { init }\r\n","import React from 'react'\r\nimport { Alert, Button, Layout } from 'antd'\r\nimport { connect } from 'react-redux'\r\nimport { Link, withRouter } from 'react-router-dom'\r\nimport { push } from 'connected-react-router'\r\nimport { FormattedMessage, injectIntl } from 'react-intl'\r\nimport { WhatsAppOutlined } from '@ant-design/icons'\r\nimport _ from 'lodash'\r\nimport dayjs from 'dayjs'\r\nimport classNames from 'classnames'\r\nimport NProgress from 'nprogress'\r\nimport TopBar from 'components/LayoutComponents/TopBar'\r\nimport Menu from 'components/LayoutComponents/Menu'\r\nimport Footer from 'components/LayoutComponents/Footer'\r\nimport Breadcrumbs from 'components/LayoutComponents/Breadcrumbs'\r\nimport AccountTransactionModal from 'containers/Reports/AccountTransactions/AccountTransactionModal'\r\nimport Onboarding from 'containers/OnboardingChecklist'\r\nimport BroadcastModal from 'containers/Broadcast'\r\nimport NPS from 'containers/NPS'\r\nimport { Welcome } from 'containers/ProductTour'\r\nimport LoginModal from 'pages/user/login/LoginModal'\r\nimport { inits } from 'redux/actions'\r\nimport { showBroadcast } from 'redux/broadcast/actions'\r\nimport { setSelectedEndpoint } from 'redux/companies/actions'\r\nimport { resetDashboard } from 'redux/finance/actions'\r\nimport { getModulePermissions } from 'redux/user/selectors'\r\nimport OneSignalApp from 'utils/oneSignal'\r\nimport styles from './style.module.scss'\r\n\r\nconst mapStateToProps = ({\r\n settings,\r\n onboardingChecklist: { onboarding_checklist },\r\n user: { id, name, role_id, permissions, email },\r\n inits: { loading, loadedInit, attemp, announcement },\r\n options: { options },\r\n billing,\r\n broadcast: { data: broadcast },\r\n translation,\r\n maintenance,\r\n}) => ({\r\n onboardingChecklist: onboarding_checklist,\r\n darkMode: options.dark_mode,\r\n isBorderless: settings.isBorderless,\r\n isSquaredBorders: settings.isSquaredBorders,\r\n isFixedWidth: settings.isFixedWidth,\r\n isMenuShadow: settings.isMenuShadow,\r\n isMenuTop: settings.isMenuTop,\r\n isMobileView: settings.isMobileView,\r\n id,\r\n name,\r\n role_id,\r\n loading,\r\n company: options.property_name,\r\n chatSupport: options.chat_support,\r\n chatNumber: options.chat_number,\r\n expiryDate: billing.expiry_date,\r\n dismissOnboardingChecklist: options.dismiss_onboarding_checklist,\r\n isProductTour: !options.onboarding && options.product_tour,\r\n broadcast,\r\n loadedInit,\r\n attemp,\r\n translation,\r\n invoicePermissions: getModulePermissions({ user: { permissions } }, 'invoices'),\r\n purchaseInvoicePermissions: getModulePermissions({ user: { permissions } }, 'purchase_invoices'),\r\n expensePermissions: getModulePermissions({ user: { permissions } }, 'expenses'),\r\n announcement,\r\n maintenance,\r\n email,\r\n})\r\n\r\nconst mapDispatchToProps = (dispatch) => {\r\n return {\r\n onInits: () => dispatch(inits()),\r\n onShowBroadcast: () => dispatch(showBroadcast()),\r\n push: (path) => dispatch(push(path)),\r\n onChangeCompany: (payload, callback) => {\r\n dispatch(resetDashboard())\r\n dispatch(setSelectedEndpoint(payload))\r\n if (typeof callback === 'function') callback()\r\n },\r\n }\r\n}\r\n\r\n@withRouter\r\n@connect(mapStateToProps, mapDispatchToProps)\r\nclass MainLayout extends React.PureComponent {\r\n scrollBarRef = React.createRef()\r\n\r\n state = {\r\n initializeOneSignal: false,\r\n }\r\n\r\n componentDidMount() {\r\n if (\r\n !this.props.id &&\r\n !this.props.loading &&\r\n this.props.attemp <= 4 &&\r\n _.isEmpty(this.props.maintenance)\r\n ) {\r\n this.props.onInits()\r\n }\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n const { loadedInit, broadcast, onShowBroadcast, id } = this.props\r\n if (prevProps.loadedInit !== loadedInit && loadedInit && !_.isEmpty(broadcast)) {\r\n onShowBroadcast()\r\n }\r\n if (prevProps.loadedInit !== loadedInit && loadedInit && id) {\r\n if (process.env.REACT_APP_ONESIGNAL_APP_ID && !this.state.initializeOneSignal) {\r\n OneSignalApp.init({\r\n appId: process.env.REACT_APP_ONESIGNAL_APP_ID,\r\n userId: id,\r\n onOpenNotification: (data) => console.log(data),\r\n initialized: this.state.initializeOneSignal,\r\n setInizialized: () => this.setState({ initializeOneSignal: true }),\r\n })\r\n }\r\n }\r\n }\r\n\r\n isDashboard = () => {\r\n return this.props.location.pathname === '/dashboard'\r\n }\r\n\r\n render() {\r\n const {\r\n children,\r\n isBorderless,\r\n isSquaredBorders,\r\n isFixedWidth,\r\n isMenuShadow,\r\n isMenuTop,\r\n loading,\r\n chatSupport,\r\n chatNumber,\r\n expiryDate,\r\n isMobileView,\r\n intl,\r\n name,\r\n company,\r\n isProductTour,\r\n companies,\r\n onChangeCompany,\r\n role_id,\r\n translation,\r\n expensePermissions,\r\n invoicePermissions,\r\n purchaseInvoicePermissions,\r\n announcement,\r\n dismissOnboardingChecklist,\r\n onboardingChecklist,\r\n darkMode,\r\n } = this.props\r\n\r\n if (loading) {\r\n NProgress.start()\r\n } else {\r\n NProgress.done()\r\n }\r\n\r\n let styleCustom = {}\r\n if (this.isDashboard()) {\r\n styleCustom = {\r\n style: {\r\n paddingLeft: 0,\r\n paddingRight: 0,\r\n paddingTop: 0,\r\n },\r\n }\r\n }\r\n\r\n return (\r\n <>\r\n \r\n \r\n \r\n {!_.isEmpty(announcement) && (\r\n \r\n )}\r\n {expiryDate && dayjs().subtract(1, 'days').isAfter(expiryDate) && (\r\n \r\n \r\n \r\n \r\n \r\n ),\r\n }}\r\n />\r\n }\r\n type=\"warning\"\r\n showIcon\r\n />\r\n )}\r\n\r\n \r\n \r\n \r\n \r\n \r\n \r\n {children}\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n {chatSupport === 1 && (\r\n }\r\n className={styles.waBtn}\r\n >\r\n {isMobileView ? null : intl.formatMessage({ id: 'button.hello_can_i_help' })}\r\n \r\n )}\r\n {onboardingChecklist === 1 && dismissOnboardingChecklist !== 1 && }\r\n \r\n \r\n \r\n {isProductTour && }\r\n \r\n >\r\n )\r\n }\r\n}\r\n\r\nexport default injectIntl(MainLayout)\r\n","import React, { useEffect, useState } from 'react'\r\nimport { injectIntl } from 'react-intl'\r\nimport { Alert, Layout } from 'antd'\r\nimport { push } from 'connected-react-router'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\nimport _ from 'lodash'\r\nimport NProgress from 'nprogress'\r\nimport dayjs from 'dayjs'\r\n\r\nimport { inits } from 'redux/actions'\r\nimport { changeSetting } from 'redux/settings/actions'\r\nimport {\r\n companiesSelector,\r\n initsSelector,\r\n optionsSelector,\r\n settingsSelector,\r\n userSelector,\r\n} from 'redux/selectors'\r\nimport styles from './style.module.scss'\r\n\r\nconst SelectCompanyLayout = ({ intl, children }) => {\r\n const dispatch = useDispatch()\r\n const [backgroundEnabled] = useState(false)\r\n const [networkError, setNetworkError] = useState(false)\r\n const [backgroundNumber] = useState(7)\r\n const options = useSelector(optionsSelector)\r\n const { id } = useSelector(userSelector)\r\n const { locale } = useSelector(settingsSelector)\r\n const { loading, loadedInit } = useSelector(initsSelector)\r\n const companies = useSelector(companiesSelector)\r\n\r\n // Loader init\r\n useEffect(() => {\r\n if (loading) {\r\n NProgress.start()\r\n } else {\r\n NProgress.done()\r\n }\r\n }, [loading])\r\n\r\n useEffect(() => {\r\n // Jika init belum di load, maka di ambil dari api\r\n const loadInits = async () => {\r\n const onInits = () => dispatch(inits())\r\n const response = await onInits()\r\n if (!response) {\r\n setNetworkError(true)\r\n }\r\n }\r\n\r\n if (!id && !loading) {\r\n loadInits()\r\n }\r\n }, [id, dispatch, setNetworkError, loading])\r\n\r\n // Jika tidak mempunya perusahaan di redirect ke tambah perusahaan\r\n useEffect(() => {\r\n if (_.isEmpty(companies) && !!id && loadedInit) {\r\n dispatch(push('/companies/add?from_login=1'))\r\n }\r\n }, [companies, dispatch, id, loadedInit])\r\n\r\n useEffect(() => {\r\n // Jika locale di setting tidak sama dg di init di update\r\n if (locale && options.property_language && locale !== options.property_language) {\r\n dispatch(\r\n changeSetting({\r\n setting: 'locale',\r\n value: options.property_language,\r\n }),\r\n )\r\n }\r\n }, [locale, dispatch, options.property_language])\r\n\r\n return (\r\n \r\n \r\n \r\n
\r\n {networkError === true ? (\r\n
\r\n ) : (\r\n children\r\n )}\r\n
\r\n
\r\n
\r\n\r\n
©{` ${dayjs().format('YYYY')} Kledo. All rights reserved.`}
\r\n
\r\n
\r\n \r\n \r\n )\r\n}\r\n\r\nexport default injectIntl(SelectCompanyLayout)\r\n","import React from 'react'\r\nimport { useSelector } from 'react-redux'\r\n\r\nimport { mobileViewSelector } from 'redux/selectors'\r\n\r\nimport ProfileMenu from './ProfileMenu'\r\n\r\nconst NoCompanyTopBar = () => {\r\n const isMobileView = useSelector(mobileViewSelector)\r\n return (\r\n \r\n
\r\n {isMobileView ? (\r\n

\r\n ) : (\r\n

\r\n )}\r\n
\r\n
\r\n
\r\n )\r\n}\r\n\r\nexport default NoCompanyTopBar\r\n","import React, { useEffect } from 'react'\r\nimport { injectIntl } from 'react-intl'\r\nimport { Layout } from 'antd'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\nimport NProgress from 'nprogress'\r\nimport dayjs from 'dayjs'\r\n\r\nimport { inits } from 'redux/actions'\r\nimport { initsSelector, loadedInitSelector, userSelector } from 'redux/selectors'\r\nimport styles from '../Login/style.module.scss'\r\n\r\nconst InfoLayout = ({ children }) => {\r\n const dispatch = useDispatch()\r\n const { loading } = useSelector(initsSelector)\r\n const loadedInit = useSelector(loadedInitSelector)\r\n const { id } = useSelector(userSelector)\r\n\r\n // Loader init\r\n useEffect(() => {\r\n if (loading) {\r\n NProgress.start()\r\n } else {\r\n NProgress.done()\r\n }\r\n }, [loading])\r\n\r\n useEffect(() => {\r\n // Jika init belum di load, maka di ambil dari api\r\n const loadInits = async () => {\r\n const onInits = () => dispatch(inits())\r\n onInits()\r\n }\r\n\r\n if (!id && !loadedInit) {\r\n loadInits()\r\n }\r\n }, [id, dispatch, loadedInit])\r\n\r\n return (\r\n \r\n \r\n \r\n
{children}
\r\n
\r\n
\r\n\r\n
©{` ${dayjs().format('YYYY')} Kledo. All rights reserved.`}
\r\n
\r\n
\r\n \r\n \r\n )\r\n}\r\n\r\nexport default injectIntl(InfoLayout)\r\n","/* eslint-disable no-restricted-globals */\r\nimport React, { Fragment } from 'react'\r\nimport { Redirect, withRouter } from 'react-router-dom'\r\nimport { connect } from 'react-redux'\r\n// import NProgress from 'nprogress'\r\nimport store from 'store'\r\nimport _ from 'lodash'\r\nimport { parse } from 'query-string'\r\nimport { replace } from 'connected-react-router'\r\n\r\n// import Loader from 'components/LayoutComponents/Loader'\r\nimport { Helmet } from 'components/UI'\r\nimport { isTokenExist, removeToken, setToken } from 'utils/cookies'\r\nimport { setSelectedEndpoint } from 'redux/companies/actions'\r\nimport { resetInits } from 'redux/inits/actions'\r\nimport { inits } from 'redux/actions'\r\nimport { hideAccountTransactionReport } from 'redux/finance/actions'\r\nimport { logoutRedux } from 'redux/user/actions'\r\nimport { setErrorLoginForm } from 'redux/loginForm/actions'\r\nimport dayjs from 'dayjs'\r\nimport PublicLayout from './Public'\r\nimport LoginLayout from './Login'\r\nimport MainLayout from './Main'\r\nimport SelectCompanyLayout from './SelectCompany'\r\nimport NoCompanyLayout from './Main/NoCompany'\r\nimport InfoLayout from './Info'\r\n\r\nconst Layouts = {\r\n public: PublicLayout,\r\n login: LoginLayout,\r\n main: MainLayout,\r\n selectCompany: SelectCompanyLayout,\r\n noCompanyLayout: NoCompanyLayout,\r\n info: InfoLayout,\r\n}\r\n\r\nconst avoidRouteWhenAuthorized = [\r\n '/user/select-company',\r\n '/user/billing/success',\r\n '/user/billing/failed',\r\n '/companies/add',\r\n]\r\nconst infoPages = ['/maintenance']\r\nconst execludePreviousPages = ['/', '/user/select-company']\r\nconst publicPages = ['/user/request-delete-account']\r\n\r\n@withRouter\r\n@connect(\r\n ({ user, options: { options }, companies, billing, finance: { accountTransactionReport } }) => ({\r\n user,\r\n options,\r\n companies,\r\n expiryDate: billing.expiry_date,\r\n accountTransactionReport,\r\n }),\r\n {\r\n setSelectedEndpoint,\r\n inits,\r\n hideAccountTransactionReport,\r\n setErrorLoginForm,\r\n resetInits,\r\n logoutRedux,\r\n replacePath: replace,\r\n },\r\n)\r\nclass IndexLayout extends React.PureComponent {\r\n state = {\r\n containerKey: 0,\r\n }\r\n\r\n componentDidMount() {\r\n const searchs = parse(location.search)\r\n\r\n // if there is error params, show error\r\n if (searchs.error) {\r\n this.props.setErrorLoginForm(searchs.error)\r\n // eslint-disable-next-line no-restricted-globals\r\n history.replaceState(null, null, `${location.pathname}${location.hash}`)\r\n }\r\n this.loginFromOtherApp()\r\n }\r\n\r\n componentDidUpdate(prevProps) {\r\n const { location, user } = this.props\r\n const { location: prevLocation } = prevProps\r\n\r\n if (location.pathname !== prevLocation.pathname && location.pathname !== '/user/login') {\r\n if (location.state) {\r\n if (location.state.resetscroll) {\r\n window.scrollTo(0, 0)\r\n }\r\n }\r\n // Untuk hide modal report accountTransaction\r\n if (this.props.accountTransactionReport.show) {\r\n this.props.hideAccountTransactionReport()\r\n }\r\n }\r\n\r\n if (prevProps.user.email !== user.email) {\r\n // set inspectlet identity\r\n // eslint-disable-next-line no-underscore-dangle\r\n if (window.__insp) {\r\n // eslint-disable-next-line no-underscore-dangle\r\n window.__insp.push(['identify', user.email])\r\n }\r\n }\r\n }\r\n\r\n getSnapshotBeforeUpdate(prevProps) {\r\n if (\r\n prevProps.companies.selectedEndpoint !== this.props.companies.selectedEndpoint &&\r\n prevProps.companies.selectedEndpoint &&\r\n this.props.companies.selectedEndpoint\r\n ) {\r\n this.props.inits().then(() => {\r\n this.setState({ containerKey: this.props.companies.selectedEndpoint })\r\n })\r\n }\r\n return null\r\n }\r\n\r\n getLayout = () => {\r\n const {\r\n location: { pathname, search },\r\n } = this.props\r\n const searchs = parse(search)\r\n if (_.includes(publicPages, pathname)) {\r\n return 'public'\r\n }\r\n\r\n if (_.includes(infoPages, pathname)) {\r\n return 'info'\r\n }\r\n\r\n if (pathname === '/user/select-company') {\r\n return 'selectCompany'\r\n }\r\n if (/^\\/user(?=\\/|$)/i.test(pathname)) {\r\n return 'login'\r\n }\r\n\r\n if (pathname === '/companies/add' && !!searchs.from_login) {\r\n return 'noCompanyLayout'\r\n }\r\n return 'main'\r\n }\r\n\r\n loginFromOtherApp = () => {\r\n const { search } = location\r\n const searchs = parse(search)\r\n\r\n // if there is token params, set token\r\n if (searchs.token) {\r\n store.remove('app.previousPathname')\r\n store.remove('app.endpoint')\r\n removeToken()\r\n this.props.setSelectedEndpoint(null)\r\n this.props.logoutRedux()\r\n this.props.resetInits()\r\n setToken(searchs.token)\r\n // if there is endpoint params, set endpoint\r\n if (searchs.endpoint) {\r\n store.set('app.endpoint', searchs.endpoint)\r\n this.props.setSelectedEndpoint(searchs.endpoint)\r\n }\r\n // Hilangkan search params token\r\n // eslint-disable-next-line no-restricted-globals\r\n history.replaceState(null, null, `${location.pathname}${location.hash}`)\r\n }\r\n }\r\n\r\n bootstrappedLayout = () => {\r\n const {\r\n children,\r\n location: { pathname },\r\n user,\r\n options,\r\n companies,\r\n expiryDate,\r\n } = this.props\r\n const storeEndpoint = store.get('app.endpoint')\r\n // Layout Rendering\r\n const layout = this.getLayout()\r\n const Container = Layouts[layout]\r\n const currentLayout = (\r\n \r\n {children}\r\n \r\n )\r\n\r\n const isUserAuthorized = isTokenExist()\r\n const isLoginLayout = layout === 'login'\r\n const isPublicLayout = layout === 'public'\r\n\r\n if (isPublicLayout) {\r\n return currentLayout\r\n }\r\n\r\n // redirect to login page if current is not login page and user not authorized\r\n if ((!isLoginLayout || pathname === '/user/select-company') && !isUserAuthorized) {\r\n // Jika tidak ada token dan tidak melakukan logout, hapus localstorage endpoint\r\n if (!user.logout) {\r\n store.remove('app.endpoint')\r\n }\r\n if (!_.includes(execludePreviousPages, pathname)) {\r\n store.set('app.previousPathname', pathname)\r\n } else {\r\n return \r\n }\r\n return currentLayout\r\n }\r\n // Jika sudah login dan belum memilih perushaan (kalau perusahaan lebih dari satu) dan posisinya tidak di billing dan select company\r\n if (\r\n isUserAuthorized &&\r\n !companies.selectedEndpoint &&\r\n !storeEndpoint &&\r\n !_.includes(avoidRouteWhenAuthorized, pathname)\r\n ) {\r\n if (!isLoginLayout && !_.includes(execludePreviousPages, pathname)) {\r\n store.set('app.previousPathname', pathname)\r\n }\r\n\r\n return \r\n }\r\n\r\n if (!companies.selectedEndpoint && storeEndpoint) {\r\n this.props.setSelectedEndpoint(storeEndpoint)\r\n }\r\n\r\n const isExpired = expiryDate ? dayjs(expiryDate).isBefore(dayjs()) : false\r\n // dayjs().subtract(1, 'days').isAfter(expiryDate)\r\n // Jika sudah login dan expired serta sudah ada endpoint\r\n if (isUserAuthorized && !isLoginLayout && (companies.selectedEndpoint || storeEndpoint)) {\r\n if (isExpired && !pathname.includes('/billing')) {\r\n return \r\n }\r\n }\r\n\r\n // Redirect ke onboarding jika onboarding 1\r\n if (\r\n isUserAuthorized &&\r\n !isLoginLayout &&\r\n options.onboarding &&\r\n pathname !== '/onboarding' &&\r\n (companies.selectedEndpoint || storeEndpoint)\r\n ) {\r\n if (!isExpired) {\r\n return \r\n }\r\n }\r\n\r\n // redirect to main dashboard when user on login page or select company page and authorized\r\n if (\r\n (isLoginLayout || pathname === '/user/select-company') &&\r\n !/^\\/user\\/invite(?=\\/|$)/i.test(pathname) &&\r\n pathname !== '/user/billing/success' &&\r\n pathname !== '/user/billing/failed' &&\r\n isUserAuthorized &&\r\n (companies.selectedEndpoint || store.get('app.endpoint'))\r\n ) {\r\n if (store.get('app.previousPathname')) {\r\n return \r\n }\r\n\r\n return \r\n }\r\n\r\n // in other case render previously set layout\r\n return currentLayout\r\n }\r\n\r\n render() {\r\n return (\r\n \r\n \r\n {this.bootstrappedLayout()}\r\n \r\n )\r\n }\r\n}\r\n\r\nexport default IndexLayout\r\n","import React, { useState, useEffect } from 'react'\r\nimport { injectIntl, FormattedMessage } from 'react-intl'\r\nimport { Layout, Alert, Button } from 'antd'\r\nimport { useSelector, useDispatch } from 'react-redux'\r\nimport NProgress from 'nprogress'\r\nimport { push } from 'connected-react-router'\r\nimport { WhatsAppOutlined } from '@ant-design/icons'\r\nimport dayjs from 'dayjs'\r\nimport store from 'store'\r\nimport classNames from 'classnames'\r\nimport { Link } from 'react-router-dom'\r\nimport _ from 'lodash'\r\n\r\nimport { inits } from 'redux/actions'\r\nimport {\r\n optionsSelector,\r\n userSelector,\r\n settingsSelector,\r\n initsSelector,\r\n billingSelector,\r\n companiesSelector,\r\n} from 'redux/selectors'\r\nimport TopBar from 'components/LayoutComponents/TopBar/NoCompany'\r\nimport Footer from 'components/LayoutComponents/Footer'\r\nimport styles from './style.module.scss'\r\n\r\nconst NoCompanyLayout = ({ intl, children }) => {\r\n const dispatch = useDispatch()\r\n // const [backgroundEnabled, setBackgroundEnabled] = useState(false)\r\n const [networkError, setNetworkError] = useState(false)\r\n // const [backgroundNumber, setBackgroundNumber] = useState(7)\r\n const {\r\n property_name: company,\r\n chat_support: chatSupport,\r\n chat_number: chatNumber,\r\n } = useSelector(optionsSelector)\r\n const { expiry_date: expiryDate } = useSelector(billingSelector)\r\n const { id, name } = useSelector(userSelector)\r\n\r\n const { isBorderless, isSquaredBorders, isFixedWidth, isMenuShadow, isMenuTop, isMobileView } =\r\n useSelector(settingsSelector)\r\n const { loading } = useSelector(initsSelector)\r\n const companies = useSelector(companiesSelector)\r\n\r\n // Loader init\r\n useEffect(() => {\r\n if (loading) {\r\n NProgress.start()\r\n } else {\r\n NProgress.done()\r\n }\r\n }, [loading])\r\n\r\n useEffect(() => {\r\n if (!_.isEmpty(companies) && !store.get('app.endpoint')) {\r\n dispatch(push('/user/select-company'))\r\n }\r\n }, [dispatch, companies])\r\n\r\n useEffect(() => {\r\n // Jika init belum di load, maka di ambil dari api\r\n const loadInits = async () => {\r\n const onInits = () => dispatch(inits())\r\n const response = await onInits()\r\n if (!response) {\r\n setNetworkError(true)\r\n }\r\n }\r\n\r\n if (!id && !loading) {\r\n loadInits()\r\n }\r\n }, [id, dispatch, setNetworkError, loading])\r\n\r\n return (\r\n <>\r\n \r\n \r\n {expiryDate && dayjs().subtract(1, 'days').isAfter(expiryDate) && (\r\n \r\n \r\n \r\n \r\n \r\n ),\r\n }}\r\n />\r\n }\r\n type=\"warning\"\r\n showIcon\r\n />\r\n )}\r\n \r\n \r\n \r\n \r\n \r\n {networkError === true ? (\r\n
\r\n ) : (\r\n children\r\n )}\r\n
\r\n \r\n \r\n \r\n \r\n \r\n \r\n {chatSupport === 1 && (\r\n }\r\n className={styles.waBtn}\r\n >\r\n {isMobileView ? null : intl.formatMessage({ id: 'button.hello_can_i_help' })}\r\n \r\n )}\r\n >\r\n )\r\n}\r\n\r\nexport default injectIntl(NoCompanyLayout)\r\n","import React, { PureComponent } from 'react'\r\nimport { Link } from 'react-router-dom'\r\n\r\nimport { Helmet } from 'components/UI'\r\n\r\nexport default class Error extends PureComponent {\r\n render() {\r\n return (\r\n \r\n
\r\n
\r\n
\r\n
Error
\r\n
Something went wrong.
\r\n
500 —
\r\n
\r\n ← Go back to the home page\r\n \r\n
\r\n
\r\n
\r\n )\r\n }\r\n}\r\n","import React, { PureComponent } from 'react'\r\nimport { injectIntl } from 'react-intl'\r\n\r\nimport { Helmet } from 'components/UI'\r\n\r\nclass ServerError extends PureComponent {\r\n render() {\r\n const { intl } = this.props\r\n return (\r\n \r\n
\r\n
\r\n
\r\n
\r\n {intl.formatMessage({ id: 'notification.server_error' })}\r\n
\r\n
\r\n {intl.formatMessage({ id: 'notification.something_went_wrong' })}\r\n
\r\n
500 —
\r\n
\r\n
\r\n
\r\n )\r\n }\r\n}\r\n\r\nexport default injectIntl(ServerError)\r\n","import React from 'react'\r\nimport classNames from 'classnames'\r\nimport styles from './style.module.scss'\r\n\r\nconst Loader = (props, { spinning = true, fullScreen }) => (\r\n {props.children}\r\n
\r\n)\r\n\r\nexport default Loader;\r\n","import { Result } from 'antd'\r\nimport { push } from 'connected-react-router'\r\nimport React, { useEffect } from 'react'\r\nimport { Helmet } from 'react-helmet'\r\nimport _ from 'lodash'\r\nimport { useDispatch, useSelector } from 'react-redux'\r\nimport { loadedInitSelector, maintenanceSelector, userSelector } from 'redux/selectors'\r\n\r\nconst Maintenance = () => {\r\n const dispatch = useDispatch()\r\n const maintenanceMessage = useSelector(maintenanceSelector)\r\n const loadedInit = useSelector(loadedInitSelector)\r\n const { id } = useSelector(userSelector)\r\n\r\n useEffect(() => {\r\n if (id && loadedInit && _.isEmpty(maintenanceMessage)) {\r\n dispatch(push('/'))\r\n }\r\n }, [id, dispatch, loadedInit, maintenanceMessage])\r\n return (\r\n \r\n )\r\n}\r\n\r\nexport default Maintenance\r\n","import React from 'react'\r\n\r\nimport { Helmet } from 'components/UI'\r\nimport { Typography } from 'antd'\r\nimport styles from './style.module.scss'\r\n\r\nconst privacyPolicy = [\r\n 'Akun yang sudah ditutup tidak dapat dibuka kembali.',\r\n 'Data email/nomor handphone pada akun yang sudah dinonaktifkan tidak dapat digunakan kembali atau didaftarkan pada akun lainnya.',\r\n 'Penutupan akun hanya dapat diproses apabila sudah tidak ada data keuangan di akun kamu.',\r\n 'Pastikan kamu telah menghapus semua data keuangan, akuntansi dan transaksi pada akun Kledo mu.',\r\n]\r\n\r\nconst stepForCloseAccount = [\r\n 'Pastikan akun yang ingin ditutup sudah sesuai seperti informasi Syarat & Ketentuan di atas.',\r\n 'Kirim ke WA 6285232300100 , sebutkan alamat email akunmu dan alasan mengapa ingin hapus akun.',\r\n 'Klik konfirmasi penghapusan akun pada emailmu.',\r\n 'Kamu sudah berhasil tutup akun.',\r\n]\r\n\r\nconst RequestDeleteAccount = () => {\r\n return (\r\n \r\n
\r\n
\r\n
\r\n Hapus Akun Kledo\r\n
\r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n \r\n \r\n Apabila kamu memiliki akun Kledo dan ingin menutup akun tersebut, silakan ikuti\r\n panduan dan tips berikut ini:\r\n \r\n \r\n \r\n \r\n Syarat & Ketentuan\r\n {privacyPolicy.map((row, index) => {\r\n return (\r\n - \r\n {row}\r\n
\r\n )\r\n })}\r\n
\r\n \r\n\r\n \r\n \r\n Cara Tutup Akun\r\n {stepForCloseAccount.map((row, index) => {\r\n return (\r\n - \r\n {row}\r\n
\r\n )\r\n })}\r\n
\r\n \r\n \r\n
\r\n
\r\n
\r\n
\r\n
\r\n )\r\n}\r\n\r\nexport default RequestDeleteAccount\r\n","import React, { Suspense } from 'react'\r\nimport { Route, Switch, Redirect } from 'react-router-dom'\r\nimport { ConnectedRouter } from 'connected-react-router'\r\nimport IndexLayout from 'layouts'\r\nimport NotFoundPage from 'pages/404'\r\nimport ErrorPage from 'pages/Error'\r\nimport ServerError from 'pages/ServerError'\r\nimport routes from 'routes'\r\nimport { Button } from 'antd'\r\nimport Loader from 'components/LayoutComponents/Loader'\r\nimport Maintenance from 'pages/Maintenance'\r\nimport RequestDeleteAccount from 'pages/user/requestDeleteAccount'\r\n\r\nclass Router extends React.Component {\r\n errorComponent = () => {\r\n return (\r\n \r\n You have encountered an error
\r\n \r\n \r\n )\r\n }\r\n\r\n renderRoutes = () => {\r\n // const { demo } = this.props;\r\n try {\r\n return (\r\n \r\n {\r\n return \r\n }}\r\n />\r\n {\r\n return \r\n }}\r\n />\r\n {routes.map((route) => (\r\n \r\n ))}\r\n \r\n \r\n \r\n \r\n \r\n \r\n )\r\n } catch (e) {\r\n return this.errorComponent()\r\n }\r\n }\r\n\r\n render() {\r\n const { history } = this.props\r\n return (\r\n \r\n \r\n }>{this.renderRoutes()}\r\n \r\n \r\n )\r\n }\r\n}\r\n\r\nexport default Router\r\n","import { useSelector } from 'react-redux'\r\nimport { useEffect, useMemo, useState, useCallback } from 'react'\r\n\r\nimport { useClearBrowserCache } from 'react-clear-browser-cache'\r\nimport { locationSelector } from 'redux/selectors'\r\n\r\nimport { useServiceWorker } from '../../ServiceWorkerProvider'\r\n\r\n// Hook untuk handle jika ada update dari server\r\nconst useAppUpdate = () => {\r\n const [showReload, setShowReload] = useState(false)\r\n const { isLatestVersion, clearCacheAndReload, latestVersion } = useClearBrowserCache()\r\n const worker = useServiceWorker()\r\n\r\n const location = useSelector(locationSelector)\r\n\r\n const isSafeToReload = useMemo(() => {\r\n const avoidUrl = [\r\n 'add',\r\n 'edit',\r\n 'import',\r\n 'transfer',\r\n 'spend',\r\n 'receive',\r\n 'register',\r\n 'dispose',\r\n ]\r\n let safeToReload = true\r\n\r\n avoidUrl.forEach((url) => {\r\n if (location.pathname.includes(url)) {\r\n safeToReload = false\r\n }\r\n })\r\n return safeToReload\r\n }, [location.pathname])\r\n\r\n const reloadPage = useCallback(() => {\r\n worker.updateAssets(false)\r\n setShowReload(false)\r\n clearCacheAndReload()\r\n }, [clearCacheAndReload, worker])\r\n\r\n useEffect(() => {\r\n if (isLatestVersion === false || worker.assetsUpdateReady) {\r\n if (isSafeToReload) {\r\n console.log(`meta ${latestVersion} is ${isLatestVersion}`)\r\n console.log(`worker asset ready ${worker.assetsUpdateReady}`)\r\n setShowReload(true)\r\n worker.updateAssets(false)\r\n clearCacheAndReload()\r\n }\r\n }\r\n\r\n return () => setShowReload(false)\r\n }, [\r\n clearCacheAndReload,\r\n isLatestVersion,\r\n isSafeToReload,\r\n latestVersion,\r\n worker,\r\n worker.assetsUpdateReady,\r\n ])\r\n\r\n return { showReload, setShowReload, onReloadPage: reloadPage }\r\n}\r\n\r\nexport default useAppUpdate\r\n","import React, { memo, useState, useEffect } from 'react'\r\nimport { injectIntl } from 'react-intl'\r\nimport { Modal, Result, Button } from 'antd'\r\nimport useAppUpdate from 'utils/hooks/useAppUpdate'\r\n\r\nconst COUNTDOWN_TIME = 15\r\nlet intervalCountDown\r\nconst UpdateAppWrapper = ({ intl }) => {\r\n const [countDown, setCountDown] = useState(COUNTDOWN_TIME)\r\n const { showReload, onReloadPage } = useAppUpdate()\r\n\r\n useEffect(() => {\r\n intervalCountDown = setInterval(() => {\r\n setCountDown((prev) => prev - 1)\r\n }, 1000)\r\n return () => clearInterval(intervalCountDown)\r\n }, [])\r\n\r\n useEffect(() => {\r\n if (countDown === 0) {\r\n clearInterval(intervalCountDown)\r\n }\r\n }, [countDown])\r\n\r\n return (\r\n \r\n {intl.formatMessage({ id: 'notification.a_new_version_is_available' })}}\r\n subTitle={intl.formatMessage(\r\n { id: 'notification.please_wait_prepare_to_reload_page' },\r\n {\r\n countDown,\r\n errorAutoReloadMessage:\r\n countDown === 0\r\n ? intl.formatMessage({ id: 'notification.autoreload_failed' })\r\n : '',\r\n },\r\n )}\r\n extra={\r\n countDown === 0 ? (\r\n \r\n ) : null\r\n }\r\n />\r\n \r\n )\r\n}\r\n\r\nexport default memo(injectIntl(UpdateAppWrapper))\r\n"],"sourceRoot":""}