- Merge client update into test-beta
Signed-off-by: Dave Richer <dave@imexsystems.ca>
This commit is contained in:
@@ -183,6 +183,26 @@ jobs:
|
||||
- jira/notify
|
||||
|
||||
|
||||
app-beta-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
resource_class: large
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://imex-online-beta/"
|
||||
- jira/notify
|
||||
|
||||
test-hasura-migrate:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
@@ -233,6 +253,27 @@ jobs:
|
||||
to: "s3://imex-online-test/"
|
||||
- jira/notify
|
||||
|
||||
test-app-beta-build:
|
||||
docker:
|
||||
- image: cimg/node:18.18.2
|
||||
resource_class: large
|
||||
working_directory: ~/repo/client
|
||||
|
||||
steps:
|
||||
- checkout:
|
||||
path: ~/repo
|
||||
|
||||
- run:
|
||||
name: Install Dependencies
|
||||
command: npm i
|
||||
|
||||
- run: npm run build:test
|
||||
|
||||
- aws-s3/sync:
|
||||
from: build
|
||||
to: "s3://imex-online-test-beta/"
|
||||
- jira/notify
|
||||
|
||||
admin-app-build:
|
||||
docker:
|
||||
- image: cimg/node:16.15.0
|
||||
@@ -274,6 +315,10 @@ workflows:
|
||||
filters:
|
||||
branches:
|
||||
only: master
|
||||
- app-beta-build:
|
||||
filters:
|
||||
branches:
|
||||
only: master-beta
|
||||
- hasura-migrate:
|
||||
secret: ${HASURA_PROD_SECRET}
|
||||
filters:
|
||||
@@ -296,6 +341,10 @@ workflows:
|
||||
filters:
|
||||
branches:
|
||||
only: test
|
||||
- test-app-beta-build:
|
||||
filters:
|
||||
branches:
|
||||
only: test-beta
|
||||
- test-hasura-migrate:
|
||||
secret: ${HASURA_TEST_SECRET}
|
||||
filters:
|
||||
|
||||
1
client/.npmrc
Normal file
1
client/.npmrc
Normal file
@@ -0,0 +1 @@
|
||||
legacy-peer-deps=true
|
||||
@@ -2,6 +2,14 @@
|
||||
const TerserPlugin = require("terser-webpack-plugin");
|
||||
const CracoLessPlugin = require("craco-less");
|
||||
const SentryWebpackPlugin = require("@sentry/webpack-plugin");
|
||||
const {convertLegacyToken} = require('@ant-design/compatible/lib');
|
||||
const {theme} = require('antd/lib');
|
||||
|
||||
const {defaultAlgorithm, defaultSeed} = theme;
|
||||
|
||||
const mapToken = defaultAlgorithm(defaultSeed);
|
||||
const v4Token = convertLegacyToken(mapToken);
|
||||
|
||||
|
||||
module.exports = {
|
||||
plugins: [
|
||||
@@ -26,8 +34,10 @@ module.exports = {
|
||||
lessLoaderOptions: {
|
||||
lessOptions: {
|
||||
modifyVars: {
|
||||
...v4Token,
|
||||
// TODO: This will no longer work in AntD 5.0
|
||||
...(process.env.NODE_ENV === "development"
|
||||
? { "@primary-color": "#B22234" }
|
||||
? {"colorPrimary": "#B22234"}
|
||||
: {
|
||||
//"@primary-color": "#1DA57A"
|
||||
}),
|
||||
@@ -53,8 +63,14 @@ module.exports = {
|
||||
},
|
||||
],
|
||||
webpack: {
|
||||
configure: (webpackConfig) => ({
|
||||
configure: (webpackConfig) => {
|
||||
return {
|
||||
...webpackConfig,
|
||||
// Required for Dev Server
|
||||
devServer: {
|
||||
...webpackConfig.devServer,
|
||||
allowedHosts: 'all',
|
||||
},
|
||||
optimization: {
|
||||
...webpackConfig.optimization,
|
||||
// Workaround for CircleCI bug caused by the number of CPUs shown
|
||||
@@ -67,7 +83,8 @@ module.exports = {
|
||||
return item;
|
||||
}),
|
||||
},
|
||||
}),
|
||||
};
|
||||
},
|
||||
},
|
||||
devtool: "source-map",
|
||||
};
|
||||
|
||||
17
client/cypress.config.js
Normal file
17
client/cypress.config.js
Normal file
@@ -0,0 +1,17 @@
|
||||
const { defineConfig } = require('cypress')
|
||||
|
||||
module.exports = defineConfig({
|
||||
experimentalStudio: true,
|
||||
env: {
|
||||
FIREBASE_USERNAME: 'cypress@imex.test',
|
||||
FIREBASE_PASSWORD: 'cypress',
|
||||
},
|
||||
e2e: {
|
||||
// We've imported your old cypress plugins here.
|
||||
// You may want to clean this up later by importing these.
|
||||
setupNodeEvents(on, config) {
|
||||
return require('./cypress/plugins/index.js')(on, config)
|
||||
},
|
||||
baseUrl: 'http://localhost:3000',
|
||||
},
|
||||
})
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"baseUrl": "http://localhost:3000",
|
||||
"experimentalStudio": true,
|
||||
"env": {
|
||||
"FIREBASE_USERNAME": "cypress@imex.test",
|
||||
"FIREBASE_PASSWORD": "cypress"
|
||||
}
|
||||
}
|
||||
@@ -8872,13 +8872,13 @@
|
||||
│ ├─ email: luis@luisrudge.net
|
||||
│ ├─ path: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-flexbugs-fixes
|
||||
│ └─ licenseFile: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-flexbugs-fixes/LICENSE
|
||||
├─ postcss-focus-visible@4.0.0
|
||||
├─ postcss-focus-open@4.0.0
|
||||
│ ├─ licenses: CC0-1.0
|
||||
│ ├─ repository: https://github.com/jonathantneal/postcss-focus-visible
|
||||
│ ├─ repository: https://github.com/jonathantneal/postcss-focus-open
|
||||
│ ├─ publisher: Jonathan Neal
|
||||
│ ├─ email: jonathantneal@hotmail.com
|
||||
│ ├─ path: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-focus-visible
|
||||
│ └─ licenseFile: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-focus-visible/LICENSE.md
|
||||
│ ├─ path: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-focus-open
|
||||
│ └─ licenseFile: /Users/pfic/Documents/Development/bodyshop/client/node_modules/postcss-focus-open/LICENSE.md
|
||||
├─ postcss-focus-within@3.0.0
|
||||
│ ├─ licenses: CC0-1.0
|
||||
│ ├─ repository: https://github.com/jonathantneal/postcss-focus-within
|
||||
|
||||
15965
client/package-lock.json
generated
15965
client/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -4,85 +4,83 @@
|
||||
"private": true,
|
||||
"proxy": "http://localhost:4000",
|
||||
"dependencies": {
|
||||
"@apollo/client": "^3.7.9",
|
||||
"@ant-design/compatible": "^5.1.2",
|
||||
"@ant-design/pro-layout": "^7.17.16",
|
||||
"@apollo/client": "^3.8.10",
|
||||
"@asseinfo/react-kanban": "^2.2.0",
|
||||
"@craco/craco": "^7.0.0",
|
||||
"@fingerprintjs/fingerprintjs": "^3.4.2",
|
||||
"@craco/craco": "^7.1.0",
|
||||
"@fingerprintjs/fingerprintjs": "^4.2.1",
|
||||
"@jsreport/browser-client": "^3.1.0",
|
||||
"@sentry/react": "^7.40.0",
|
||||
"@sentry/tracing": "^7.40.0",
|
||||
"@splitsoftware/splitio-react": "^1.8.1",
|
||||
"@tanem/react-nprogress": "^5.0.8",
|
||||
"antd": "^4.24.8",
|
||||
"@reduxjs/toolkit": "^2.0.1",
|
||||
"@sentry/react": "^7.93.0",
|
||||
"@sentry/tracing": "^7.93.0",
|
||||
"@splitsoftware/splitio-react": "^1.11.0",
|
||||
"@tanem/react-nprogress": "^5.0.51",
|
||||
"antd": "^5.12.8",
|
||||
"apollo-link-logger": "^2.0.1",
|
||||
"axios": "^1.3.4",
|
||||
"craco-less": "^2.0.0",
|
||||
"axios": "^1.6.5",
|
||||
"craco-less": "^3.0.1",
|
||||
"dayjs": "^1.11.10",
|
||||
"dayjs-business-days2": "^1.2.2",
|
||||
"dinero.js": "^1.9.1",
|
||||
"dotenv": "^16.0.1",
|
||||
"dotenv": "^16.3.1",
|
||||
"enquire-js": "^0.2.1",
|
||||
"env-cmd": "^10.1.0",
|
||||
"exifr": "^7.1.3",
|
||||
"firebase": "^9.17.1",
|
||||
"firebase": "^10.7.2",
|
||||
"graphql": "^16.6.0",
|
||||
"i18next": "^22.4.10",
|
||||
"i18next-browser-languagedetector": "^7.0.1",
|
||||
"jsoneditor": "^9.9.0",
|
||||
"i18next": "^23.7.16",
|
||||
"i18next-browser-languagedetector": "^7.0.2",
|
||||
"jsoneditor": "^10.0.0",
|
||||
"jsreport-browser-client-dist": "^1.3.0",
|
||||
"libphonenumber-js": "^1.10.21",
|
||||
"logrocket": "^3.0.1",
|
||||
"markerjs2": "^2.28.1",
|
||||
"moment-business-days": "^1.2.0",
|
||||
"moment-timezone": "^0.5.41",
|
||||
"libphonenumber-js": "^1.10.53",
|
||||
"logrocket": "^7.0.0",
|
||||
"markerjs2": "^2.31.4",
|
||||
"normalize-url": "^8.0.0",
|
||||
"phone": "^3.1.35",
|
||||
"phone": "^3.1.42",
|
||||
"preval.macro": "^5.0.0",
|
||||
"prop-types": "^15.8.1",
|
||||
"query-string": "^7.1.3",
|
||||
"query-string": "^8.1.0",
|
||||
"rc-queue-anim": "^2.0.0",
|
||||
"rc-scroll-anim": "^2.7.6",
|
||||
"react": "^17.0.2",
|
||||
"react-big-calendar": "^1.6.8",
|
||||
"react": "^18.2.0",
|
||||
"react-big-calendar": "^1.8.6",
|
||||
"react-color": "^2.19.3",
|
||||
"react-cookie": "^4.1.1",
|
||||
"react-dom": "^17.0.2",
|
||||
"react-drag-listview": "^0.2.1",
|
||||
"react-cookie": "^7.0.1",
|
||||
"react-dom": "^18.2.0",
|
||||
"react-drag-listview": "^2.0.0",
|
||||
"react-grid-gallery": "^1.0.0",
|
||||
"react-grid-layout": "^1.3.4",
|
||||
"react-i18next": "^12.2.0",
|
||||
"react-icons": "^4.7.1",
|
||||
"react-grid-layout": "1.3.4",
|
||||
"react-i18next": "^14.0.0",
|
||||
"react-icons": "^5.0.1",
|
||||
"react-image-lightbox": "^5.1.4",
|
||||
"react-intersection-observer": "^9.4.3",
|
||||
"react-number-format": "^5.1.3",
|
||||
"react-redux": "^8.0.5",
|
||||
"react-resizable": "^3.0.4",
|
||||
"react-router-dom": "^5.3.0",
|
||||
"react-intersection-observer": "^9.5.3",
|
||||
"react-number-format": "^5.1.4",
|
||||
"react-redux": "^9.1.0",
|
||||
"react-resizable": "^3.0.5",
|
||||
"react-router-dom": "^6.21.3",
|
||||
"react-scripts": "^5.0.1",
|
||||
"react-sticky": "^6.0.3",
|
||||
"react-sublime-video": "^0.2.5",
|
||||
"react-virtualized": "^9.22.3",
|
||||
"recharts": "^2.4.3",
|
||||
"redux": "^4.2.1",
|
||||
"react-virtualized": "^9.22.5",
|
||||
"recharts": "^2.10.4",
|
||||
"redux": "^5.0.1",
|
||||
"redux-persist": "^6.0.0",
|
||||
"redux-saga": "^1.2.2",
|
||||
"redux-saga": "^1.3.0",
|
||||
"redux-state-sync": "^3.1.4",
|
||||
"reselect": "^4.1.7",
|
||||
"sass": "^1.58.3",
|
||||
"socket.io-client": "^4.6.1",
|
||||
"styled-components": "^5.3.6",
|
||||
"reselect": "^5.1.0",
|
||||
"sass": "^1.70.0",
|
||||
"socket.io-client": "^4.7.4",
|
||||
"styled-components": "^6.1.8",
|
||||
"subscriptions-transport-ws": "^0.11.0",
|
||||
"web-vitals": "^2.1.4",
|
||||
"workbox-background-sync": "^6.5.3",
|
||||
"workbox-broadcast-update": "^6.5.3",
|
||||
"workbox-cacheable-response": "^6.5.3",
|
||||
"workbox-core": "^6.5.3",
|
||||
"workbox-expiration": "^6.5.3",
|
||||
"workbox-google-analytics": "^6.5.3",
|
||||
"workbox-navigation-preload": "^6.5.3",
|
||||
"workbox-precaching": "^6.5.3",
|
||||
"workbox-range-requests": "^6.5.3",
|
||||
"workbox-routing": "^6.5.3",
|
||||
"workbox-strategies": "^6.5.3",
|
||||
"workbox-streams": "^6.5.3",
|
||||
"terser-webpack-plugin": "^5.3.10",
|
||||
"web-vitals": "^3.5.1",
|
||||
"workbox-core": "^7.0.0",
|
||||
"workbox-expiration": "^7.0.0",
|
||||
"workbox-navigation-preload": "^7.0.0",
|
||||
"workbox-precaching": "^7.0.0",
|
||||
"workbox-routing": "^7.0.0",
|
||||
"workbox-strategies": "^7.0.0",
|
||||
"yauzl": "^2.10.0"
|
||||
},
|
||||
"scripts": {
|
||||
@@ -119,12 +117,13 @@
|
||||
"react-error-overlay": "6.0.9"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@sentry/webpack-plugin": "^1.20.0",
|
||||
"@testing-library/cypress": "^8.0.3",
|
||||
"cypress": "^10.3.1",
|
||||
"eslint-plugin-cypress": "^2.12.1",
|
||||
"@babel/plugin-proposal-private-property-in-object": "^7.21.11",
|
||||
"@sentry/webpack-plugin": "^2.10.2",
|
||||
"@testing-library/cypress": "^10.0.1",
|
||||
"cypress": "^13.6.3",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
"react-error-overlay": "6.0.11",
|
||||
"redux-logger": "^3.0.6",
|
||||
"source-map-explorer": "^2.5.2"
|
||||
"source-map-explorer": "^2.5.3"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,7 +190,7 @@ This package contains the following license and notice below:
|
||||
# @firebase/logger
|
||||
|
||||
This package serves as the base of all logging in the JS SDK. Any logging that
|
||||
is intended to be visible to Firebase end developers should go through this
|
||||
is intended to be open to Firebase end developers should go through this
|
||||
module.
|
||||
|
||||
## Basic Usage
|
||||
@@ -9375,7 +9375,7 @@ parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
to the extent that it includes a convenient and prominently open
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
|
||||
@@ -1029,7 +1029,7 @@ The following NPM packages may be included in this product:
|
||||
- postcss-dir-pseudo-class@5.0.0
|
||||
- postcss-double-position-gradients@1.0.0
|
||||
- postcss-env-function@2.0.2
|
||||
- postcss-focus-visible@4.0.0
|
||||
- postcss-focus-open@4.0.0
|
||||
- postcss-focus-within@3.0.0
|
||||
- postcss-gap-properties@2.0.0
|
||||
- postcss-image-set-function@3.0.1
|
||||
@@ -1699,7 +1699,7 @@ This package contains the following license and notice below:
|
||||
# @firebase/logger
|
||||
|
||||
This package serves as the base of all logging in the JS SDK. Any logging that
|
||||
is intended to be visible to Firebase end developers should go through this
|
||||
is intended to be open to Firebase end developers should go through this
|
||||
module.
|
||||
|
||||
## Basic Usage
|
||||
@@ -24029,7 +24029,7 @@ parties to make or receive copies. Mere interaction with a user through
|
||||
a computer network, with no transfer of a copy, is not conveying.
|
||||
|
||||
An interactive user interface displays "Appropriate Legal Notices"
|
||||
to the extent that it includes a convenient and prominently visible
|
||||
to the extent that it includes a convenient and prominently open
|
||||
feature that (1) displays an appropriate copyright notice, and (2)
|
||||
tells the user that there is no warranty for the work (except to the
|
||||
extent that warranties are provided), that licensees may convey the
|
||||
|
||||
@@ -2,14 +2,15 @@ import { ApolloProvider } from "@apollo/client";
|
||||
import { SplitFactory, SplitSdk } from "@splitsoftware/splitio-react";
|
||||
import { ConfigProvider } from "antd";
|
||||
import enLocale from "antd/es/locale/en_US";
|
||||
import moment from "moment";
|
||||
import dayjs from "../utils/day";
|
||||
import 'dayjs/locale/en';
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import GlobalLoadingBar from "../components/global-loading-bar/global-loading-bar.component";
|
||||
import client from "../utils/GraphQLClient";
|
||||
import App from "./App";
|
||||
|
||||
moment.locale("en-US");
|
||||
dayjs.locale("en");
|
||||
|
||||
export const factory = SplitSdk({
|
||||
core: {
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
import { useClient } from "@splitsoftware/splitio-react";
|
||||
import {useSplitClient} from "@splitsoftware/splitio-react";
|
||||
import {Button, Result} from "antd";
|
||||
import LogRocket from "logrocket";
|
||||
import React, { lazy, Suspense, useEffect } from "react";
|
||||
import React, {lazy, Suspense, useEffect, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import { Route, Switch } from "react-router-dom";
|
||||
import {Route, Routes} from "react-router-dom";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import DocumentEditorContainer from "../components/document-editor/document-editor.container";
|
||||
import ErrorBoundary from "../components/error-boundary/error-boundary.component";
|
||||
@@ -16,12 +16,10 @@ import TechPageContainer from "../pages/tech/tech.page.container";
|
||||
import {setOnline} from "../redux/application/application.actions";
|
||||
import {selectOnline} from "../redux/application/application.selectors";
|
||||
import {checkUserSession} from "../redux/user/user.actions";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../redux/user/user.selectors";
|
||||
import PrivateRoute from "../utils/private-route";
|
||||
import {selectBodyshop, selectCurrentUser,} from "../redux/user/user.selectors";
|
||||
import PrivateRoute from "../components/PrivateRoute";
|
||||
import "./App.styles.scss";
|
||||
import handleBeta from "../utils/betaHandler";
|
||||
|
||||
const ResetPassword = lazy(() =>
|
||||
import("../pages/reset-password/reset-password.component")
|
||||
@@ -33,7 +31,6 @@ const CsiPage = lazy(() => import("../pages/csi/csi.container.page"));
|
||||
const MobilePaymentContainer = lazy(() =>
|
||||
import("../pages/mobile-payment/mobile-payment.container")
|
||||
);
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
currentUser: selectCurrentUser,
|
||||
online: selectOnline,
|
||||
@@ -44,14 +41,12 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
setOnline: (isOnline) => dispatch(setOnline(isOnline)),
|
||||
});
|
||||
|
||||
export function App({
|
||||
bodyshop,
|
||||
checkUserSession,
|
||||
currentUser,
|
||||
online,
|
||||
setOnline,
|
||||
}) {
|
||||
const client = useClient();
|
||||
export function App({bodyshop, checkUserSession, currentUser, online, setOnline}) {
|
||||
|
||||
const client = useSplitClient().client;
|
||||
const [listenersAdded, setListenersAdded] = useState(false)
|
||||
const {t} = useTranslation();
|
||||
|
||||
|
||||
useEffect(() => {
|
||||
if (!navigator.onLine) {
|
||||
@@ -64,21 +59,38 @@ export function App({
|
||||
//const b = Grid.useBreakpoint();
|
||||
// console.log("Breakpoints:", b);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
window.addEventListener("offline", function (e) {
|
||||
// Associate event listeners, memoize to prevent multiple listeners being added
|
||||
useEffect(() => {
|
||||
const offlineListener = (e) => {
|
||||
setOnline(false);
|
||||
});
|
||||
}
|
||||
|
||||
window.addEventListener("online", function (e) {
|
||||
const onlineListener = (e) => {
|
||||
setOnline(true);
|
||||
});
|
||||
}
|
||||
|
||||
if (!listenersAdded) {
|
||||
console.log('Added events for offline and online');
|
||||
window.addEventListener("offline", offlineListener);
|
||||
window.addEventListener("online", onlineListener);
|
||||
setListenersAdded(true);
|
||||
}
|
||||
|
||||
return () => {
|
||||
window.removeEventListener("offline", offlineListener);
|
||||
window.removeEventListener("online", onlineListener);
|
||||
}
|
||||
}, [setOnline, listenersAdded]);
|
||||
|
||||
useEffect(() => {
|
||||
if (currentUser.authorized && bodyshop) {
|
||||
client.setAttribute("imexshopid", bodyshop.imexshopid);
|
||||
|
||||
LogRocket.init("rome-online/rome-online");
|
||||
if (client.getTreatment("LogRocket_Tracking") === "on") {
|
||||
if (
|
||||
client.getTreatment("LogRocket_Tracking") === "on" ||
|
||||
window.location.hostname === 'beta.romeonline.io'
|
||||
) {
|
||||
console.log("LR Start");
|
||||
LogRocket.init("rome-online/rome-online");
|
||||
}
|
||||
}
|
||||
@@ -88,6 +100,8 @@ export function App({
|
||||
return <LoadingSpinner message={t("general.labels.loggingin")}/>;
|
||||
}
|
||||
|
||||
handleBeta();
|
||||
|
||||
if (!online)
|
||||
return (
|
||||
<Result
|
||||
@@ -107,54 +121,27 @@ export function App({
|
||||
/>
|
||||
);
|
||||
|
||||
// Any route that is not assigned and matched will default to the Landing Page component
|
||||
return (
|
||||
<Switch>
|
||||
<Suspense fallback={<LoadingSpinner />}>
|
||||
<ErrorBoundary>
|
||||
<Route exact path="/" component={LandingPage} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route exact path="/signin" component={SignInPage} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route exact path="/resetpassword" component={ResetPassword} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route exact path="/csi/:surveyId" component={CsiPage} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route exact path="/disclaimer" component={DisclaimerPage} />
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<Route
|
||||
exact
|
||||
path="/mp/:paymentIs"
|
||||
component={MobilePaymentContainer}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute
|
||||
isAuthorized={currentUser.authorized}
|
||||
path="/manage"
|
||||
component={ManagePage}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute
|
||||
isAuthorized={currentUser.authorized}
|
||||
path="/tech"
|
||||
component={TechPageContainer}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
<ErrorBoundary>
|
||||
<PrivateRoute
|
||||
isAuthorized={currentUser.authorized}
|
||||
path="/edit"
|
||||
component={DocumentEditorContainer}
|
||||
/>
|
||||
</ErrorBoundary>
|
||||
<Suspense fallback={<LoadingSpinner message="Rome Online"/>}>
|
||||
<Routes>
|
||||
<Route path="*" element={<ErrorBoundary><LandingPage/></ErrorBoundary>}/>
|
||||
<Route path="/signin" element={<ErrorBoundary><SignInPage/></ErrorBoundary>}/>
|
||||
<Route path="/resetpassword" element={<ErrorBoundary><ResetPassword/></ErrorBoundary>}/>
|
||||
<Route path="/csi/:surveyId" element={<ErrorBoundary><CsiPage/></ErrorBoundary>}/>
|
||||
<Route path="/disclaimer" element={<ErrorBoundary><DisclaimerPage/></ErrorBoundary>}/>
|
||||
<Route path="/mp/:paymentIs" element={<ErrorBoundary><MobilePaymentContainer/></ErrorBoundary>}/>
|
||||
<Route path="/manage/*" element={<ErrorBoundary><PrivateRoute isAuthorized={currentUser.authorized}/></ErrorBoundary>}>
|
||||
<Route path="*" element={<ManagePage/>}/>
|
||||
</Route>
|
||||
<Route path="/tech/*" element={<ErrorBoundary><PrivateRoute isAuthorized={currentUser.authorized}/></ErrorBoundary>}>
|
||||
<Route path="*" element={<TechPageContainer/>}/>
|
||||
</Route>
|
||||
<Route path="/edit/*" element={<PrivateRoute isAuthorized={currentUser.authorized}/>}>
|
||||
<Route path="*" element={<DocumentEditorContainer/>}/>
|
||||
</Route>
|
||||
</Routes>
|
||||
</Suspense>
|
||||
</Switch>
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,14 @@
|
||||
//Global Styles.
|
||||
@import "react-big-calendar/lib/sass/styles";
|
||||
|
||||
.ant-menu-item-divider {
|
||||
border-bottom: 1px solid #74695c !important;
|
||||
}
|
||||
|
||||
.ant-menu-dark .ant-menu-item:hover {
|
||||
background-color: #1890ff !important;
|
||||
}
|
||||
|
||||
.imex-table-header {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
|
||||
17
client/src/components/PrivateRoute.js
Normal file
17
client/src/components/PrivateRoute.js
Normal file
@@ -0,0 +1,17 @@
|
||||
import React, {useEffect} from "react";
|
||||
import {Outlet, useLocation, useNavigate} from "react-router-dom";
|
||||
|
||||
function PrivateRoute({component: Component, isAuthorized, ...rest}) {
|
||||
const location = useLocation();
|
||||
const navigate = useNavigate();
|
||||
|
||||
useEffect(() => {
|
||||
if (!isAuthorized) {
|
||||
navigate(`/signin?redirect=${location.pathname}`);
|
||||
}
|
||||
}, [isAuthorized, navigate, location]);
|
||||
|
||||
return <Outlet/>;
|
||||
}
|
||||
|
||||
export default PrivateRoute;
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Input, Table, Checkbox, Card, Space } from "antd";
|
||||
import {Card, Checkbox, Input, Space, Table} from "antd";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Link} from "react-router-dom";
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Select, Button, Popover, InputNumber } from "antd";
|
||||
import {Button, InputNumber, Popover, Select} from "antd";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
@@ -61,7 +61,7 @@ export function AllocationsAssignmentComponent({
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover content={popContent} visible={visibility}>
|
||||
<Popover content={popContent} open={visibility}>
|
||||
<Button onClick={() => setVisibility(true)}>
|
||||
{t("allocations.actions.assign")}
|
||||
</Button>
|
||||
|
||||
@@ -59,7 +59,7 @@ export default connect(
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover content={popContent} visible={visibility}>
|
||||
<Popover content={popContent} open={visibility}>
|
||||
<Button disabled={disabled} onClick={() => setVisibility(true)}>
|
||||
{t("allocations.actions.assign")}
|
||||
</Button>
|
||||
|
||||
@@ -2,6 +2,7 @@ import React from "react";
|
||||
import {List} from "antd";
|
||||
import Icon from "@ant-design/icons";
|
||||
import {FaArrowRight} from "react-icons/fa";
|
||||
|
||||
export default function AuditTrailValuesComponent({oldV, newV}) {
|
||||
if (!oldV && !newV) return <div></div>;
|
||||
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { Tag, Popover } from "antd";
|
||||
import {Popover, Tag} from "antd";
|
||||
import React from "react";
|
||||
import Barcode from "react-barcode";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
export default function BarcodePopupComponent({value, children}) {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
|
||||
@@ -3,6 +3,7 @@ import React, { useEffect } from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import ReadOnlyFormItemComponent from "../form-items-formatted/read-only-form-item.component";
|
||||
import "./bill-cm-returns-table.styles.scss";
|
||||
|
||||
export default function BillCmdReturnsTableComponent({
|
||||
form,
|
||||
returnLoading,
|
||||
|
||||
@@ -1,17 +1,13 @@
|
||||
import {useMutation, useQuery} from "@apollo/client";
|
||||
import { Button, Form, PageHeader, Popconfirm, Space } from "antd";
|
||||
import moment from "moment";
|
||||
import {Button, Form, Popconfirm, Space} from "antd";
|
||||
import dayjs from "../../utils/day";
|
||||
import queryString from "query-string";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {useLocation} from "react-router-dom";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {
|
||||
DELETE_BILL_LINE,
|
||||
INSERT_NEW_BILL_LINES,
|
||||
UPDATE_BILL_LINE,
|
||||
} from "../../graphql/bill-lines.queries";
|
||||
import {DELETE_BILL_LINE, INSERT_NEW_BILL_LINES, UPDATE_BILL_LINE} from "../../graphql/bill-lines.queries";
|
||||
import {QUERY_BILL_BY_PK, UPDATE_BILL} from "../../graphql/bills.queries";
|
||||
import {insertAuditTrail} from "../../redux/application/application.actions";
|
||||
import {setModalContext} from "../../redux/modals/modals.actions";
|
||||
@@ -26,6 +22,7 @@ import JobDocumentsGallery from "../jobs-documents-gallery/jobs-documents-galler
|
||||
import JobsDocumentsLocalGallery from "../jobs-documents-local-gallery/jobs-documents-local-gallery.container";
|
||||
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||
import BillDetailEditReturn from "./bill-detail-edit-return.component";
|
||||
import {PageHeader} from "@ant-design/pro-layout";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -42,16 +39,12 @@ export default connect(
|
||||
mapDispatchToProps
|
||||
)(BillDetailEditcontainer);
|
||||
|
||||
export function BillDetailEditcontainer({
|
||||
setPartsOrderContext,
|
||||
insertAuditTrail,
|
||||
bodyshop,
|
||||
}) {
|
||||
export function BillDetailEditcontainer({setPartsOrderContext, insertAuditTrail, bodyshop,}) {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
|
||||
const {t} = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [updateLoading, setUpdateLoading] = useState(false);
|
||||
const [update_bill] = useMutation(UPDATE_BILL);
|
||||
const [insertBillLine] = useMutation(INSERT_NEW_BILL_LINES);
|
||||
@@ -65,6 +58,8 @@ export function BillDetailEditcontainer({
|
||||
nextFetchPolicy: "network-only",
|
||||
});
|
||||
|
||||
// ... rest of the code remains the same
|
||||
|
||||
const handleSave = () => {
|
||||
//It's got a previously deducted bill line!
|
||||
if (
|
||||
@@ -72,7 +67,7 @@ export function BillDetailEditcontainer({
|
||||
form.getFieldValue("billlines").filter((b) => b.deductedfromlbr).length >
|
||||
0
|
||||
)
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
else {
|
||||
form.submit();
|
||||
}
|
||||
@@ -155,7 +150,7 @@ export function BillDetailEditcontainer({
|
||||
await refetch();
|
||||
form.setFieldsValue(transformData(data));
|
||||
form.resetFields();
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
setUpdateLoading(false);
|
||||
};
|
||||
|
||||
@@ -179,9 +174,9 @@ export function BillDetailEditcontainer({
|
||||
<BillDetailEditReturn data={data}/>
|
||||
<BillPrintButton billid={search.billid}/>
|
||||
<Popconfirm
|
||||
visible={visible}
|
||||
open={open}
|
||||
onConfirm={() => form.submit()}
|
||||
onCancel={() => setVisible(false)}
|
||||
onCancel={() => setOpen(false)}
|
||||
okButtonProps={{loading: updateLoading}}
|
||||
title={t("bills.labels.editadjwarning")}
|
||||
>
|
||||
@@ -246,7 +241,7 @@ const transformData = (data) => {
|
||||
},
|
||||
};
|
||||
}),
|
||||
date: data.bills_by_pk ? moment(data.bills_by_pk.date) : null,
|
||||
date: data.bills_by_pk ? dayjs(data.bills_by_pk.date) : null,
|
||||
}
|
||||
: {};
|
||||
};
|
||||
|
||||
@@ -3,7 +3,7 @@ import queryString from "query-string";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import {useLocation, useNavigate} from "react-router-dom";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {insertAuditTrail} from "../../redux/application/application.actions";
|
||||
import {setModalContext} from "../../redux/modals/modals.actions";
|
||||
@@ -33,10 +33,10 @@ export function BillDetailEditReturn({
|
||||
disabled,
|
||||
}) {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
const history = useNavigate();
|
||||
const {t} = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const handleFinish = ({billlines}) => {
|
||||
const selectedLines = billlines.filter((l) => l.selected).map((l) => l.id);
|
||||
@@ -67,18 +67,18 @@ export function BillDetailEditReturn({
|
||||
});
|
||||
delete search.billid;
|
||||
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
setVisible(false);
|
||||
history({search: queryString.stringify(search)});
|
||||
setOpen(false);
|
||||
};
|
||||
useEffect(() => {
|
||||
if (visible === false) form.resetFields();
|
||||
}, [visible, form]);
|
||||
if (open === false) form.resetFields();
|
||||
}, [open, form]);
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
visible={visible}
|
||||
onCancel={() => setVisible(false)}
|
||||
open={open}
|
||||
onCancel={() => setOpen(false)}
|
||||
destroyOnClose
|
||||
title={t("bills.actions.return")}
|
||||
onOk={() => form.submit()}
|
||||
@@ -175,7 +175,7 @@ export function BillDetailEditReturn({
|
||||
<Button
|
||||
disabled={data.bills_by_pk.is_credit_memo || disabled}
|
||||
onClick={() => {
|
||||
setVisible(true);
|
||||
setOpen(true);
|
||||
}}
|
||||
>
|
||||
{t("bills.actions.return")}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
import {Drawer, Grid} from "antd";
|
||||
import queryString from "query-string";
|
||||
import React from "react";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import {useLocation, useNavigate} from "react-router-dom";
|
||||
import BillDetailEditComponent from "./bill-detail-edit-component";
|
||||
|
||||
export default function BillDetailEditcontainer() {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
const history = useNavigate();
|
||||
|
||||
const selectedBreakpoint = Object.entries(Grid.useBreakpoint())
|
||||
.filter((screen) => !!screen[1])
|
||||
@@ -29,10 +29,10 @@ export default function BillDetailEditcontainer() {
|
||||
width={drawerPercentage}
|
||||
onClose={() => {
|
||||
delete search.billid;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
history({search: queryString.stringify(search)});
|
||||
}}
|
||||
destroyOnClose
|
||||
visible={search.billid}
|
||||
open={search.billid}
|
||||
>
|
||||
<BillDetailEditComponent/>
|
||||
</Drawer>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {useApolloClient, useMutation} from "@apollo/client";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import { Button, Checkbox, Form, Modal, Space, notification } from "antd";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
import {Button, Checkbox, Form, Modal, notification, Space} from "antd";
|
||||
import _ from "lodash";
|
||||
import React, {useEffect, useMemo, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
@@ -9,18 +9,12 @@ import { createStructuredSelector } from "reselect";
|
||||
import {INSERT_NEW_BILL} from "../../graphql/bills.queries";
|
||||
import {UPDATE_INVENTORY_LINES} from "../../graphql/inventory.queries";
|
||||
import {UPDATE_JOB_LINE} from "../../graphql/jobs-lines.queries";
|
||||
import {
|
||||
QUERY_JOB_LBR_ADJUSTMENTS,
|
||||
UPDATE_JOB,
|
||||
} from "../../graphql/jobs.queries";
|
||||
import {QUERY_JOB_LBR_ADJUSTMENTS, UPDATE_JOB,} from "../../graphql/jobs.queries";
|
||||
import {MUTATION_MARK_RETURN_RECEIVED} from "../../graphql/parts-orders.queries";
|
||||
import {insertAuditTrail} from "../../redux/application/application.actions";
|
||||
import {toggleModalVisible} from "../../redux/modals/modals.actions";
|
||||
import {selectBillEnterModal} from "../../redux/modals/modals.selectors";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import {selectBodyshop, selectCurrentUser,} from "../../redux/user/user.selectors";
|
||||
import AuditTrailMapping from "../../utils/AuditTrailMappings";
|
||||
import {GenerateDocument} from "../../utils/RenderTemplate";
|
||||
import {TemplateList} from "../../utils/TemplateConstants";
|
||||
@@ -64,11 +58,13 @@ function BillEnterModalContainer({
|
||||
"enter_bill_generate_label",
|
||||
false
|
||||
);
|
||||
const { Enhanced_Payroll } = useTreatments(
|
||||
["Enhanced_Payroll"],
|
||||
{},
|
||||
bodyshop.imexshopid
|
||||
);
|
||||
|
||||
const {treatments: {Enhanced_Payroll}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Enhanced_Payroll"],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
const formValues = useMemo(() => {
|
||||
return {
|
||||
...billEnterModal.context.bill,
|
||||
@@ -399,18 +395,18 @@ function BillEnterModalContainer({
|
||||
}, [enterAgain, form]);
|
||||
|
||||
useEffect(() => {
|
||||
if (billEnterModal.visible) {
|
||||
if (billEnterModal.open) {
|
||||
form.setFieldsValue(formValues);
|
||||
} else {
|
||||
form.resetFields();
|
||||
}
|
||||
}, [billEnterModal.visible, form, formValues]);
|
||||
}, [billEnterModal.open, form, formValues]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
title={t("bills.labels.new")}
|
||||
width={"98%"}
|
||||
visible={billEnterModal.visible}
|
||||
open={billEnterModal.open}
|
||||
okText={t("general.actions.save")}
|
||||
keyboard="false"
|
||||
onOk={() => form.submit()}
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
||||
import CurrencyFormatter from "../../utils/CurrencyFormatter";
|
||||
import {alphaSort} from "../../utils/sorters";
|
||||
import BillFormItemsExtendedFormItem from "./bill-form-lines.extended.formitem.component";
|
||||
|
||||
export default function BillFormLinesExtended({
|
||||
lineData,
|
||||
discount,
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
import React from "react";
|
||||
import {
|
||||
PlusCircleFilled,
|
||||
MinusCircleFilled,
|
||||
WarningOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import { Form, Button, InputNumber, Input, Select, Switch, Space } from "antd";
|
||||
import {MinusCircleFilled, PlusCircleFilled, WarningOutlined,} from "@ant-design/icons";
|
||||
import {Button, Form, Input, InputNumber, Select, Space, Switch} from "antd";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
import {connect} from "react-redux";
|
||||
|
||||
@@ -1,18 +1,8 @@
|
||||
import Icon, {UploadOutlined} from "@ant-design/icons";
|
||||
import {useApolloClient} from "@apollo/client";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import {
|
||||
Alert,
|
||||
Divider,
|
||||
Form,
|
||||
Input,
|
||||
Select,
|
||||
Space,
|
||||
Statistic,
|
||||
Switch,
|
||||
Upload,
|
||||
} from "antd";
|
||||
import moment from "moment";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
import {Alert, Divider, Form, Input, Select, Space, Statistic, Switch, Upload,} from "antd";
|
||||
import dayjs from "../../utils/day";
|
||||
import React, {useEffect, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {MdOpenInNew} from "react-icons/md";
|
||||
@@ -50,21 +40,19 @@ export function BillFormComponent({
|
||||
job,
|
||||
loadOutstandingReturns,
|
||||
loadInventory,
|
||||
preferredMake,
|
||||
preferredMake
|
||||
}) {
|
||||
|
||||
const {t} = useTranslation();
|
||||
const client = useApolloClient();
|
||||
const [discount, setDiscount] = useState(0);
|
||||
const { Extended_Bill_Posting } = useTreatments(
|
||||
["Extended_Bill_Posting"],
|
||||
{},
|
||||
bodyshop.imexshopid
|
||||
);
|
||||
const { ClosingPeriod } = useTreatments(
|
||||
["ClosingPeriod"],
|
||||
{},
|
||||
bodyshop.imexshopid
|
||||
);
|
||||
|
||||
const {treatments: {Extended_Bill_Posting, ClosingPeriod}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Extended_Bill_Posting", "ClosingPeriod"],
|
||||
splitKey: bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
|
||||
const handleVendorSelect = (props, opt) => {
|
||||
setDiscount(opt.discount);
|
||||
@@ -288,17 +276,17 @@ export function BillFormComponent({
|
||||
bodyshop.accountingconfig.ClosingPeriod
|
||||
) {
|
||||
if (
|
||||
moment(value)
|
||||
dayjs(value)
|
||||
.startOf("day")
|
||||
.isSameOrAfter(
|
||||
moment(
|
||||
dayjs(
|
||||
bodyshop.accountingconfig.ClosingPeriod[0]
|
||||
).startOf("day")
|
||||
) &&
|
||||
moment(value)
|
||||
dayjs(value)
|
||||
.startOf("day")
|
||||
.isSameOrBefore(
|
||||
moment(
|
||||
dayjs(
|
||||
bodyshop.accountingconfig.ClosingPeriod[1]
|
||||
).endOf("day")
|
||||
)
|
||||
@@ -396,27 +384,22 @@ export function BillFormComponent({
|
||||
>
|
||||
<CurrencyInput min={0} disabled={disabled}/>
|
||||
</Form.Item>
|
||||
{
|
||||
// <Form.Item
|
||||
// span={3}
|
||||
// label={t("bills.fields.local_tax_rate")}
|
||||
// name="local_tax_rate"
|
||||
// >
|
||||
// <CurrencyInput min={0} />
|
||||
// </Form.Item>
|
||||
}
|
||||
{
|
||||
//Removed as a part of the merge to Rome Online. Federal tax not applicable.
|
||||
// bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? (
|
||||
// <Form.Item
|
||||
// span={2}
|
||||
// label={t("bills.labels.federal_tax_exempt")}
|
||||
// name="federal_tax_exempt"
|
||||
// >
|
||||
// <Switch onChange={handleFederalTaxExemptSwitchToggle} />
|
||||
// </Form.Item>
|
||||
// ) : null
|
||||
}
|
||||
{/*<Form.Item*/}
|
||||
{/* span={3}*/}
|
||||
{/* label={t("bills.fields.local_tax_rate")}*/}
|
||||
{/* name="local_tax_rate"*/}
|
||||
{/*>*/}
|
||||
{/* <CurrencyInput min={0} />*/}
|
||||
{/*</Form.Item>*/}
|
||||
{/* {bodyshop.pbs_serialnumber || bodyshop.cdk_dealerid ? (*/}
|
||||
{/* <Form.Item*/}
|
||||
{/* span={2}*/}
|
||||
{/* label={t("bills.labels.federal_tax_exempt")}*/}
|
||||
{/* name="federal_tax_exempt"*/}
|
||||
{/* >*/}
|
||||
{/* <Switch onChange={handleFederalTaxExemptSwitchToggle} />*/}
|
||||
{/* </Form.Item>*/}
|
||||
{/* ) : null}*/}
|
||||
<Form.Item shouldUpdate span={13}>
|
||||
{() => {
|
||||
const values = form.getFieldsValue([
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {useLazyQuery, useQuery} from "@apollo/client";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
import React from "react";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
@@ -23,11 +23,11 @@ export function BillFormContainer({
|
||||
disabled,
|
||||
disableInvNumber,
|
||||
}) {
|
||||
const { Simple_Inventory } = useTreatments(
|
||||
["Simple_Inventory"],
|
||||
{},
|
||||
bodyshop && bodyshop.imexshopid
|
||||
);
|
||||
const {treatments: {Simple_Inventory}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Simple_Inventory"],
|
||||
splitKey: bodyshop && bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
const {data: VendorAutoCompleteData} = useQuery(
|
||||
SEARCH_VENDOR_AUTOCOMPLETE,
|
||||
@@ -79,4 +79,5 @@ export function BillFormContainer({
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null)(BillFormContainer);
|
||||
|
||||
@@ -1,17 +1,6 @@
|
||||
import {DeleteFilled, DollarCircleFilled} from "@ant-design/icons";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import {
|
||||
Button,
|
||||
Checkbox,
|
||||
Form,
|
||||
Input,
|
||||
InputNumber,
|
||||
Select,
|
||||
Space,
|
||||
Switch,
|
||||
Table,
|
||||
Tooltip,
|
||||
} from "antd";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
import {Button, Checkbox, Form, Input, InputNumber, Select, Space, Switch, Table, Tooltip,} from "antd";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
@@ -42,17 +31,13 @@ export function BillEnterModalLinesComponent({
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
const {setFieldsValue, getFieldsValue, getFieldValue} = form;
|
||||
const { Simple_Inventory } = useTreatments(
|
||||
["Simple_Inventory"],
|
||||
{},
|
||||
bodyshop && bodyshop.imexshopid
|
||||
);
|
||||
|
||||
const { Enhanced_Payroll } = useTreatments(
|
||||
["Enhanced_Payroll"],
|
||||
{},
|
||||
bodyshop.imexshopid
|
||||
);
|
||||
const {treatments: {Simple_Inventory, Enhanced_Payroll}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["Simple_Inventory", "Enhanced_Payroll"],
|
||||
splitKey: bodyshop && bodyshop.imexshopid,
|
||||
});
|
||||
|
||||
|
||||
const columns = (remove) => {
|
||||
return [
|
||||
|
||||
@@ -15,7 +15,8 @@ const BillLineSearchSelect = (
|
||||
disabled={disabled}
|
||||
ref={ref}
|
||||
showSearch
|
||||
dropdownMatchSelectWidth={false}
|
||||
popupMatchSelectWidth={false}
|
||||
optionLabelProp={"name"}
|
||||
// optionFilterProp="line_desc"
|
||||
filterOption={(inputValue, option) => {
|
||||
return (
|
||||
@@ -57,6 +58,9 @@ const BillLineSearchSelect = (
|
||||
style={{
|
||||
...(item.removed ? {textDecoration: "line-through"} : {}),
|
||||
}}
|
||||
name={`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
|
||||
item.oem_partno ? ` - ${item.oem_partno}` : ""
|
||||
}${item.alt_partno ? ` (${item.alt_partno})` : ""}`.trim()}
|
||||
>
|
||||
<span>
|
||||
{`${item.removed ? `(REMOVED) ` : ""}${item.line_desc}${
|
||||
|
||||
@@ -1,18 +1,14 @@
|
||||
import { useMutation } from "@apollo/client";
|
||||
import {gql, useMutation} from "@apollo/client";
|
||||
import {Button, notification} from "antd";
|
||||
import { gql } from "@apollo/client";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {
|
||||
selectAuthLevel,
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import {selectAuthLevel, selectBodyshop, selectCurrentUser,} from "../../redux/user/user.selectors";
|
||||
import {HasRbacAccess} from "../rbac-wrapper/rbac-wrapper.component";
|
||||
import {INSERT_EXPORT_LOG} from "../../graphql/accounting.queries";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
authLevel: selectAuthLevel,
|
||||
|
||||
@@ -1,16 +1,13 @@
|
||||
import { useMutation } from "@apollo/client";
|
||||
import {gql, useMutation} from "@apollo/client";
|
||||
import {Button, notification} from "antd";
|
||||
import { gql } from "@apollo/client";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {
|
||||
selectAuthLevel,
|
||||
selectBodyshop,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import {selectAuthLevel, selectBodyshop,} from "../../redux/user/user.selectors";
|
||||
import {HasRbacAccess} from "../rbac-wrapper/rbac-wrapper.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
authLevel: selectAuthLevel,
|
||||
|
||||
@@ -2,15 +2,12 @@ import { FileAddFilled } from "@ant-design/icons";
|
||||
import {useMutation} from "@apollo/client";
|
||||
import {Button, notification, Tooltip} from "antd";
|
||||
import {t} from "i18next";
|
||||
import moment from "moment";
|
||||
import dayjs from "./../../utils/day";
|
||||
import React, {useState} from "react";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {INSERT_INVENTORY_AND_CREDIT} from "../../graphql/inventory.queries";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import {selectBodyshop, selectCurrentUser,} from "../../redux/user/user.selectors";
|
||||
import {CalculateBillTotal} from "../bill-form/bill-form.totals.utility";
|
||||
import queryString from "query-string";
|
||||
import {useLocation} from "react-router-dom";
|
||||
@@ -36,7 +33,6 @@ export function BilllineAddInventory({
|
||||
}) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const {billid} = queryString.parse(useLocation().search);
|
||||
|
||||
const [insertInventoryLine] = useMutation(INSERT_INVENTORY_AND_CREDIT);
|
||||
|
||||
const addToInventory = async () => {
|
||||
@@ -50,7 +46,7 @@ export function BilllineAddInventory({
|
||||
jobid: jobid,
|
||||
isinhouse: true,
|
||||
is_credit_memo: true,
|
||||
date: moment().format("YYYY-MM-DD"),
|
||||
date: dayjs().format("YYYY-MM-DD"),
|
||||
federal_tax_rate: bodyshop.bill_tax_rates.federal_tax_rate,
|
||||
state_tax_rate: bodyshop.bill_tax_rates.state_tax_rate,
|
||||
local_tax_rate: bodyshop.bill_tax_rates.local_tax_rate,
|
||||
@@ -92,7 +88,7 @@ export function BilllineAddInventory({
|
||||
pol: {
|
||||
returnfrombill: billid,
|
||||
vendorid: bodyshop.inhousevendorid,
|
||||
deliver_by: moment().format("YYYY-MM-DD"),
|
||||
deliver_by: dayjs().format("YYYY-MM-DD"),
|
||||
parts_order_lines: {
|
||||
data: [
|
||||
{
|
||||
|
||||
@@ -229,6 +229,7 @@ export function BillsListTableComponent({
|
||||
</Card>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
|
||||
@@ -2,15 +2,15 @@ import React, { useState } from "react";
|
||||
import {QUERY_ALL_VENDORS} from "../../graphql/vendors.queries";
|
||||
import {useQuery} from "@apollo/client";
|
||||
import queryString from "query-string";
|
||||
import { useHistory, useLocation } from "react-router-dom";
|
||||
import { Table, Input } from "antd";
|
||||
import {useLocation, useNavigate} from "react-router-dom";
|
||||
import {Input, Table} from "antd";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {alphaSort} from "../../utils/sorters";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
|
||||
export default function BillsVendorsList() {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const history = useHistory();
|
||||
const history = useNavigate();
|
||||
|
||||
const {loading, error, data} = useQuery(QUERY_ALL_VENDORS, {
|
||||
fetchPolicy: "network-only",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {HomeFilled} from "@ant-design/icons";
|
||||
import { Breadcrumb, Row, Col } from "antd";
|
||||
import {Breadcrumb, Col, Row} from "antd";
|
||||
import React from "react";
|
||||
import {connect} from "react-redux";
|
||||
import {Link} from "react-router-dom";
|
||||
@@ -9,7 +9,7 @@ import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import GlobalSearch from "../global-search/global-search.component";
|
||||
import GlobalSearchOs from "../global-search/global-search-os.component";
|
||||
import "./breadcrumbs.styles.scss";
|
||||
import { useTreatments } from "@splitsoftware/splitio-react";
|
||||
import {useSplitTreatments} from "@splitsoftware/splitio-react";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
breadcrumbs: selectBreadcrumbs,
|
||||
@@ -17,33 +17,42 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
|
||||
export function BreadCrumbs({breadcrumbs, bodyshop}) {
|
||||
const { OpenSearch } = useTreatments(
|
||||
["OpenSearch"],
|
||||
{},
|
||||
bodyshop && bodyshop.imexshopid
|
||||
);
|
||||
|
||||
const {treatments: {OpenSearch}} = useSplitTreatments({
|
||||
attributes: {},
|
||||
names: ["OpenSearch"],
|
||||
splitKey: bodyshop && bodyshop.imexshopid,
|
||||
});
|
||||
// TODO - Client Update - Technically key is not doing anything here
|
||||
return (
|
||||
<Row className="breadcrumb-container">
|
||||
<Col xs={24} sm={24} md={16}>
|
||||
<Breadcrumb separator=">">
|
||||
<Breadcrumb.Item>
|
||||
<Link to={`/manage`}>
|
||||
<Breadcrumb
|
||||
separator=">"
|
||||
items={[
|
||||
{
|
||||
key: "home",
|
||||
title: (
|
||||
<Link to={`/manage/`}>
|
||||
<HomeFilled/>{" "}
|
||||
{(bodyshop && bodyshop.shopname && `(${bodyshop.shopname})`) ||
|
||||
""}
|
||||
</Link>
|
||||
</Breadcrumb.Item>
|
||||
{breadcrumbs.map((item) =>
|
||||
item.link ? (
|
||||
<Breadcrumb.Item key={item.label}>
|
||||
<Link to={item.link}>{item.label} </Link>
|
||||
</Breadcrumb.Item>
|
||||
) : (
|
||||
<Breadcrumb.Item key={item.label}>{item.label}</Breadcrumb.Item>
|
||||
)
|
||||
)}
|
||||
</Breadcrumb>
|
||||
),
|
||||
},
|
||||
...breadcrumbs.map((item) =>
|
||||
item.link
|
||||
? {
|
||||
key: item.label,
|
||||
title: <Link to={item.link}>{item.label}</Link>,
|
||||
}
|
||||
: {
|
||||
key: item.label,
|
||||
title: item.label,
|
||||
}
|
||||
),
|
||||
]}
|
||||
/>
|
||||
</Col>
|
||||
<Col xs={24} sm={24} md={8}>
|
||||
{OpenSearch.treatment === "on" ? <GlobalSearchOs/> : <GlobalSearch/>}
|
||||
@@ -51,4 +60,5 @@ export function BreadCrumbs({ breadcrumbs, bodyshop }) {
|
||||
</Row>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null)(BreadCrumbs);
|
||||
|
||||
@@ -25,7 +25,7 @@ export function ContractsFindModalContainer({
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const { visible } = caBcEtfTableModal;
|
||||
const {open} = caBcEtfTableModal;
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [form] = Form.useForm();
|
||||
const EtfTemplate = TemplateList("special").ca_bc_etf_table;
|
||||
@@ -63,14 +63,14 @@ export function ContractsFindModalContainer({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
if (open) {
|
||||
form.resetFields();
|
||||
}
|
||||
}, [visible, form]);
|
||||
}, [open, form]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
open={open}
|
||||
width="70%"
|
||||
title={t("payments.labels.findermodal")}
|
||||
onCancel={() => toggleModalVisible()}
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Button, Form, InputNumber, Popover } from "antd";
|
||||
import {logImEXEvent} from "../../firebase/firebase.utils";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {CalculatorFilled} from "@ant-design/icons";
|
||||
|
||||
export default function CABCpvrtCalculator({disabled, form}) {
|
||||
const [visibility, setVisibility] = useState(false);
|
||||
|
||||
@@ -38,7 +39,7 @@ export default function CABCpvrtCalculator({ disabled, form }) {
|
||||
<Popover
|
||||
destroyTooltipOnHide
|
||||
content={popContent}
|
||||
visible={visibility}
|
||||
open={visibility}
|
||||
disabled={disabled}
|
||||
>
|
||||
<Button disabled={disabled} onClick={() => setVisibility(true)}>
|
||||
|
||||
@@ -1,27 +1,13 @@
|
||||
import {DeleteFilled} from "@ant-design/icons";
|
||||
import {useLazyQuery, useMutation} from "@apollo/client";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Col,
|
||||
Form,
|
||||
Input,
|
||||
Row,
|
||||
Space,
|
||||
Spin,
|
||||
Statistic,
|
||||
notification,
|
||||
} from "antd";
|
||||
import {Button, Card, Col, Form, Input, notification, Row, Space, Spin, Statistic,} from "antd";
|
||||
import axios from "axios";
|
||||
import moment from "moment";
|
||||
import dayjs from "../../utils/day";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {
|
||||
INSERT_PAYMENT_RESPONSE,
|
||||
QUERY_RO_AND_OWNER_BY_JOB_PKS,
|
||||
} from "../../graphql/payment_response.queries";
|
||||
import {INSERT_PAYMENT_RESPONSE, QUERY_RO_AND_OWNER_BY_JOB_PKS,} from "../../graphql/payment_response.queries";
|
||||
import {INSERT_NEW_PAYMENT} from "../../graphql/payments.queries";
|
||||
import {insertAuditTrail} from "../../redux/application/application.actions";
|
||||
import {toggleModalVisible} from "../../redux/modals/modals.actions";
|
||||
@@ -117,7 +103,7 @@ const CardPaymentModalComponent = ({
|
||||
payer: t("payments.labels.customer"),
|
||||
type: values.paymentResponse.cardbrand,
|
||||
jobid: payment.jobid,
|
||||
date: moment(Date.now()),
|
||||
date: dayjs(Date.now()),
|
||||
payment_responses: {
|
||||
data: [
|
||||
{
|
||||
|
||||
@@ -22,7 +22,7 @@ function CardPaymentModalContainer({
|
||||
toggleModalVisible,
|
||||
bodyshop,
|
||||
}) {
|
||||
const { visible } = cardPaymentModal;
|
||||
const {open} = cardPaymentModal;
|
||||
const {t} = useTranslation();
|
||||
|
||||
const handleCancel = () => {
|
||||
@@ -35,7 +35,7 @@ function CardPaymentModalContainer({
|
||||
|
||||
return (
|
||||
<Modal
|
||||
open={visible}
|
||||
open={open}
|
||||
onOk={handleOK}
|
||||
onCancel={handleCancel}
|
||||
footer={[
|
||||
|
||||
@@ -4,20 +4,11 @@ import { Button, notification, Space } from "antd";
|
||||
import axios from "axios";
|
||||
import React, {useEffect} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import {messaging, requestForToken} from "../../firebase/firebase.utils";
|
||||
import { selectChatVisible } from "../../redux/messaging/messaging.selectors";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import FcmHandler from "../../utils/fcm-handler";
|
||||
import ChatPopupComponent from "../chat-popup/chat-popup.component";
|
||||
import "./chat-affix.styles.scss";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
chatVisible: selectChatVisible,
|
||||
});
|
||||
|
||||
export function ChatAffixContainer({bodyshop, chatVisible}) {
|
||||
const {t} = useTranslation();
|
||||
const client = useApolloClient();
|
||||
@@ -47,7 +38,6 @@ export function ChatAffixContainer({ bodyshop, chatVisible }) {
|
||||
<Button
|
||||
onClick={async () => {
|
||||
await requestForToken();
|
||||
|
||||
SubscribeToTopic();
|
||||
}}
|
||||
>
|
||||
@@ -81,16 +71,17 @@ export function ChatAffixContainer({ bodyshop, chatVisible }) {
|
||||
payload: (payload && payload.data && payload.data.data) || payload.data,
|
||||
});
|
||||
}
|
||||
let stopMessageListenr, channel;
|
||||
|
||||
let stopMessageListener, channel;
|
||||
try {
|
||||
stopMessageListenr = onMessage(messaging, handleMessage);
|
||||
stopMessageListener = onMessage(messaging, handleMessage);
|
||||
channel = new BroadcastChannel("imex-sw-messages");
|
||||
channel.addEventListener("message", handleMessage);
|
||||
} catch (error) {
|
||||
console.log("Unable to set event listeners.");
|
||||
}
|
||||
return () => {
|
||||
stopMessageListenr && stopMessageListenr();
|
||||
stopMessageListener && stopMessageListener();
|
||||
channel && channel.removeEventListener("message", handleMessage);
|
||||
};
|
||||
}, [client]);
|
||||
@@ -103,4 +94,5 @@ export function ChatAffixContainer({ bodyshop, chatVisible }) {
|
||||
</div>
|
||||
);
|
||||
}
|
||||
export default connect(mapStateToProps, null)(ChatAffixContainer);
|
||||
|
||||
export default ChatAffixContainer;
|
||||
@@ -1,19 +1,14 @@
|
||||
import { Badge, List, Tag } from "antd";
|
||||
import {Badge, Card, List, Space, Tag} from "antd";
|
||||
import React from "react";
|
||||
import {connect} from "react-redux";
|
||||
import {
|
||||
AutoSizer,
|
||||
CellMeasurer,
|
||||
CellMeasurerCache,
|
||||
List as VirtualizedList,
|
||||
} from "react-virtualized";
|
||||
import {AutoSizer, CellMeasurer, CellMeasurerCache, List as VirtualizedList,} from "react-virtualized";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {setSelectedConversation} from "../../redux/messaging/messaging.actions";
|
||||
import {selectSelectedConversation} from "../../redux/messaging/messaging.selectors";
|
||||
import {TimeAgoFormatter} from "../../utils/DateFormatter";
|
||||
import PhoneFormatter from "../../utils/PhoneFormatter";
|
||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||
|
||||
import {OwnerNameDisplayFunction} from "../owner-name-display/owner-name-display.component";
|
||||
import _ from "lodash";
|
||||
import "./chat-conversation-list.styles.scss";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@@ -38,6 +33,36 @@ function ChatConversationListComponent({
|
||||
|
||||
const rowRenderer = ({index, key, style, parent}) => {
|
||||
const item = conversationList[index];
|
||||
const cardContentRight =
|
||||
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>;
|
||||
const cardContentLeft = item.job_conversations.length > 0
|
||||
? item.job_conversations.map((j, idx) => (
|
||||
<Tag key={idx}>{j.job.ro_number}</Tag>
|
||||
))
|
||||
: null;
|
||||
|
||||
const names = <>{_.uniq(item.job_conversations.map((j, idx) =>
|
||||
OwnerNameDisplayFunction(j.job)
|
||||
))}</>
|
||||
|
||||
const cardTitle = <>
|
||||
{item.label && <Tag color="blue">{item.label}</Tag>}
|
||||
{item.job_conversations.length > 0 ? (
|
||||
<Space direction="vertical">
|
||||
{names}
|
||||
</Space>
|
||||
) : (
|
||||
<Space>
|
||||
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
||||
</Space>
|
||||
)}
|
||||
</>
|
||||
const cardExtra = <Badge count={item.messages_aggregate.aggregate.count || 0}/>
|
||||
|
||||
const getCardStyle = () =>
|
||||
item.id === selectedConversation
|
||||
? {backgroundColor: 'rgba(128, 128, 128, 0.2)'}
|
||||
: {backgroundColor: index % 2 === 0 ? '#f0f2f5' : '#ffffff'};
|
||||
|
||||
return (
|
||||
<CellMeasurer
|
||||
@@ -49,44 +74,21 @@ function ChatConversationListComponent({
|
||||
>
|
||||
<List.Item
|
||||
onClick={() => setSelectedConversation(item.id)}
|
||||
className={`chat-list-item ${
|
||||
style={style}
|
||||
className={`chat-list-item
|
||||
${
|
||||
item.id === selectedConversation
|
||||
? "chat-list-selected-conversation"
|
||||
: null
|
||||
}`}
|
||||
style={style}
|
||||
>
|
||||
<Card style={getCardStyle()} bordered={false} size="small" extra={cardExtra} title={cardTitle}>
|
||||
<div style={{display: 'inline-block', width: '70%', textAlign: 'left'}}>
|
||||
{cardContentLeft}
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
display: "inline-block",
|
||||
}}
|
||||
>
|
||||
{item.label && <div className="chat-name">{item.label}</div>}
|
||||
{item.job_conversations.length > 0 ? (
|
||||
<div className="chat-name">
|
||||
{item.job_conversations.map((j, idx) => (
|
||||
<div key={idx}>
|
||||
<OwnerNameDisplay ownerObject={j.job} />
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
) : (
|
||||
<PhoneFormatter>{item.phone_num}</PhoneFormatter>
|
||||
)}
|
||||
</div>
|
||||
<div style={{ display: "inline-block" }}>
|
||||
<div>
|
||||
{item.job_conversations.length > 0
|
||||
? item.job_conversations.map((j, idx) => (
|
||||
<Tag key={idx} className="ro-number-tag">
|
||||
{j.job.ro_number}
|
||||
</Tag>
|
||||
))
|
||||
: null}
|
||||
</div>
|
||||
<TimeAgoFormatter>{item.updated_at}</TimeAgoFormatter>
|
||||
</div>
|
||||
<Badge count={item.messages_aggregate.aggregate.count || 0} />
|
||||
style={{display: 'inline-block', width: '30%', textAlign: 'right'}}>{cardContentRight}</div>
|
||||
</Card>
|
||||
</List.Item>
|
||||
</CellMeasurer>
|
||||
);
|
||||
|
||||
@@ -1,27 +1,16 @@
|
||||
.chat-list-selected-conversation {
|
||||
background-color: rgba(128, 128, 128, 0.2);
|
||||
}
|
||||
.chat-list-container {
|
||||
flex: 1;
|
||||
overflow: hidden;
|
||||
height: 100%;
|
||||
border: 1px solid gainsboro;
|
||||
}
|
||||
|
||||
.chat-list-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
.ant-card-head {
|
||||
border: none;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
color: #ff7a00;
|
||||
}
|
||||
.chat-name {
|
||||
flex: 1;
|
||||
display: inline;
|
||||
}
|
||||
.ro-number-tag {
|
||||
align-self: baseline;
|
||||
}
|
||||
padding: 12px 24px;
|
||||
border-bottom: 1px solid gainsboro;
|
||||
}
|
||||
|
||||
@@ -2,15 +2,13 @@ import { useMutation, useQuery, useSubscription } from "@apollo/client";
|
||||
import React, {useState} from "react";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {
|
||||
CONVERSATION_SUBSCRIPTION_BY_PK,
|
||||
GET_CONVERSATION_DETAILS,
|
||||
} from "../../graphql/conversations.queries";
|
||||
import {CONVERSATION_SUBSCRIPTION_BY_PK, GET_CONVERSATION_DETAILS,} from "../../graphql/conversations.queries";
|
||||
import {MARK_MESSAGES_AS_READ_BY_CONVERSATION} from "../../graphql/messages.queries";
|
||||
import {selectSelectedConversation} from "../../redux/messaging/messaging.selectors";
|
||||
import ChatConversationComponent from "./chat-conversation.component";
|
||||
import axios from "axios";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
selectedConversation: selectSelectedConversation,
|
||||
bodyshop: selectBodyshop,
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Input, notification, Spin, Tag, Tooltip } from "antd";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {UPDATE_CONVERSATION_LABEL} from "../../graphql/conversations.queries";
|
||||
|
||||
export default function ChatLabel({conversation}) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [editing, setEditing] = useState(false);
|
||||
|
||||
@@ -9,7 +9,8 @@ import { GET_DOCUMENTS_BY_JOB } from "../../graphql/documents.queries";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
import JobDocumentsGalleryExternal from "../jobs-documents-gallery/jobs-documents-gallery.external.component";
|
||||
import JobDocumentsLocalGalleryExternal from "../jobs-documents-local-gallery/jobs-documents-local-gallery.external.component";
|
||||
import JobDocumentsLocalGalleryExternal
|
||||
from "../jobs-documents-local-gallery/jobs-documents-local-gallery.external.component";
|
||||
import LoadingSpinner from "../loading-spinner/loading-spinner.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
@@ -27,7 +28,7 @@ export function ChatMediaSelector({
|
||||
conversation,
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const {loading, error, data} = useQuery(GET_DOCUMENTS_BY_JOB, {
|
||||
fetchPolicy: "network-only",
|
||||
@@ -39,13 +40,13 @@ export function ChatMediaSelector({
|
||||
},
|
||||
|
||||
skip:
|
||||
!visible ||
|
||||
!open ||
|
||||
!conversation.job_conversations ||
|
||||
conversation.job_conversations.length === 0,
|
||||
});
|
||||
|
||||
const handleVisibleChange = (visible) => {
|
||||
setVisible(visible);
|
||||
const handleVisibleChange = (change) => {
|
||||
setOpen(change);
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
@@ -65,7 +66,7 @@ export function ChatMediaSelector({
|
||||
externalMediaState={[selectedMedia, setSelectedMedia]}
|
||||
/>
|
||||
)}
|
||||
{bodyshop.uselocalmediaserver && visible && (
|
||||
{bodyshop.uselocalmediaserver && open && (
|
||||
<JobDocumentsLocalGalleryExternal
|
||||
externalMediaState={[selectedMedia, setSelectedMedia]}
|
||||
jobId={
|
||||
@@ -88,8 +89,8 @@ export function ChatMediaSelector({
|
||||
}
|
||||
title={t("messaging.labels.selectmedia")}
|
||||
trigger="click"
|
||||
visible={visible}
|
||||
onVisibleChange={handleVisibleChange}
|
||||
open={open}
|
||||
onOpenChange={handleVisibleChange}
|
||||
>
|
||||
<Badge count={selectedMedia.filter((s) => s.isSelected).length}>
|
||||
<PictureFilled style={{margin: "0 .5rem"}}/>
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import Icon from "@ant-design/icons";
|
||||
import {Tooltip} from "antd";
|
||||
import i18n from "i18next";
|
||||
import moment from "moment";
|
||||
import dayjs from "../../utils/day";
|
||||
import React, {useEffect, useRef} from "react";
|
||||
import {MdDone, MdDoneAll} from "react-icons/md";
|
||||
import {
|
||||
AutoSizer,
|
||||
CellMeasurer,
|
||||
CellMeasurerCache,
|
||||
List,
|
||||
} from "react-virtualized";
|
||||
import {AutoSizer, CellMeasurer, CellMeasurerCache, List,} from "react-virtualized";
|
||||
import {DateTimeFormatter} from "../../utils/DateFormatter";
|
||||
import "./chat-message-list.styles.scss";
|
||||
|
||||
@@ -52,7 +47,7 @@ export default function ChatMessageListComponent({ messages }) {
|
||||
<div style={{fontSize: 10}}>
|
||||
{i18n.t("messaging.labels.sentby", {
|
||||
by: messages[index].userid,
|
||||
time: moment(messages[index].created_at).format(
|
||||
time: dayjs(messages[index].created_at).format(
|
||||
"MM/DD/YYYY @ hh:mm a"
|
||||
),
|
||||
})}
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
.yours {
|
||||
align-items: flex-start;
|
||||
}
|
||||
|
||||
.msgmargin {
|
||||
margin-top: 0.1rem;
|
||||
margin-bottom: 0.1rem;
|
||||
@@ -66,6 +67,7 @@
|
||||
background: #eee;
|
||||
border-bottom-right-radius: 15px;
|
||||
}
|
||||
|
||||
.yours .message.last:after {
|
||||
content: "";
|
||||
position: absolute;
|
||||
|
||||
@@ -5,9 +5,7 @@ import { useTranslation } from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {openChatByPhone} from "../../redux/messaging/messaging.actions";
|
||||
import PhoneFormItem, {
|
||||
PhoneItemFormatterValidation,
|
||||
} from "../form-items-formatted/phone-form-item.component";
|
||||
import PhoneFormItem, {PhoneItemFormatterValidation,} from "../form-items-formatted/phone-form-item.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
|
||||
@@ -9,6 +9,7 @@ import PhoneNumberFormatter from "../../utils/PhoneFormatter";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import {searchingForConversation} from "../../redux/messaging/messaging.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
searchingForConversation: searchingForConversation,
|
||||
@@ -49,4 +50,5 @@ export function ChatOpenButton({
|
||||
</a>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChatOpenButton);
|
||||
|
||||
@@ -1,24 +1,13 @@
|
||||
import {
|
||||
InfoCircleOutlined,
|
||||
MessageOutlined,
|
||||
ShrinkOutlined,
|
||||
SyncOutlined,
|
||||
} from "@ant-design/icons";
|
||||
import {InfoCircleOutlined, MessageOutlined, ShrinkOutlined, SyncOutlined,} from "@ant-design/icons";
|
||||
import {useLazyQuery, useQuery} from "@apollo/client";
|
||||
import {Badge, Card, Col, Row, Space, Tag, Tooltip, Typography} from "antd";
|
||||
import React, {useCallback, useEffect, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {
|
||||
CONVERSATION_LIST_QUERY,
|
||||
UNREAD_CONVERSATION_COUNT,
|
||||
} from "../../graphql/conversations.queries";
|
||||
import {CONVERSATION_LIST_QUERY, UNREAD_CONVERSATION_COUNT,} from "../../graphql/conversations.queries";
|
||||
import {toggleChatVisible} from "../../redux/messaging/messaging.actions";
|
||||
import {
|
||||
selectChatVisible,
|
||||
selectSelectedConversation,
|
||||
} from "../../redux/messaging/messaging.selectors";
|
||||
import {selectChatVisible, selectSelectedConversation,} from "../../redux/messaging/messaging.selectors";
|
||||
import ChatConversationListComponent from "../chat-conversation-list/chat-conversation-list.component";
|
||||
import ChatConversationContainer from "../chat-conversation/chat-conversation.container";
|
||||
import ChatNewConversation from "../chat-new-conversation/chat-new-conversation.component";
|
||||
@@ -140,4 +129,5 @@ export function ChatPopupComponent({
|
||||
</Badge>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChatPopupComponent);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
height: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.chat-popup-info-icon {
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {PlusCircleOutlined} from "@ant-design/icons";
|
||||
import { Dropdown, Menu } from "antd";
|
||||
import {Dropdown} from "antd";
|
||||
import React from "react";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
@@ -16,24 +16,22 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
});
|
||||
|
||||
export function ChatPresetsComponent({bodyshop, setMessage, className}) {
|
||||
const menu = (
|
||||
<Menu>
|
||||
{bodyshop.md_messaging_presets.map((i, idx) => (
|
||||
<Menu.Item onClick={() => setMessage(i.text)} key={idx}>
|
||||
{i.label}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
);
|
||||
|
||||
const items = bodyshop.md_messaging_presets.map((i, idx) => ({
|
||||
key: idx,
|
||||
label: (i.label),
|
||||
onClick: () => setMessage(i.text),
|
||||
}));
|
||||
|
||||
return (
|
||||
<div className={className}>
|
||||
<Dropdown trigger={["click"]} overlay={menu}>
|
||||
<Dropdown trigger={["click"]} menu={{items}}>
|
||||
<PlusCircleOutlined/>
|
||||
</Dropdown>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
|
||||
@@ -16,44 +16,31 @@ const mapDispatchToProps = (dispatch) => ({
|
||||
export function ChatPrintButton({conversation}) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
|
||||
const generateDocument = (type) => {
|
||||
setLoading(true);
|
||||
GenerateDocument(
|
||||
{
|
||||
name: TemplateList("messaging").conversation_list.key,
|
||||
variables: {id: conversation.id},
|
||||
},
|
||||
{
|
||||
subject: TemplateList("messaging").conversation_list.subject,
|
||||
},
|
||||
type,
|
||||
conversation.id
|
||||
).catch(e => {
|
||||
console.warn('Something went wrong generating a document.');
|
||||
});
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
return (
|
||||
<Space wrap>
|
||||
<PrinterOutlined
|
||||
onClick={() => {
|
||||
setLoading(true);
|
||||
GenerateDocument(
|
||||
{
|
||||
name: TemplateList("messaging").conversation_list.key,
|
||||
variables: { id: conversation.id },
|
||||
},
|
||||
{
|
||||
subject: TemplateList("messaging").conversation_list.subject,
|
||||
},
|
||||
"p",
|
||||
conversation.id
|
||||
);
|
||||
setLoading(false);
|
||||
}}
|
||||
/>
|
||||
<MailOutlined
|
||||
onClick={() => {
|
||||
setLoading(true);
|
||||
GenerateDocument(
|
||||
{
|
||||
name: TemplateList("messaging").conversation_list.key,
|
||||
variables: { id: conversation.id },
|
||||
},
|
||||
{
|
||||
subject: TemplateList("messaging").conversation_list.subject,
|
||||
},
|
||||
"e",
|
||||
conversation.id
|
||||
);
|
||||
setLoading(false);
|
||||
}}
|
||||
/>
|
||||
<PrinterOutlined onClick={() => generateDocument('p')}/>
|
||||
<MailOutlined onClick={() => generateDocument('e')}/>
|
||||
{loading && <Spin/>}
|
||||
</Space>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, mapDispatchToProps)(ChatPrintButton);
|
||||
|
||||
@@ -5,14 +5,8 @@ import { useTranslation } from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {logImEXEvent} from "../../firebase/firebase.utils";
|
||||
import {
|
||||
sendMessage,
|
||||
setMessage,
|
||||
} from "../../redux/messaging/messaging.actions";
|
||||
import {
|
||||
selectIsSending,
|
||||
selectMessage,
|
||||
} from "../../redux/messaging/messaging.selectors";
|
||||
import {sendMessage, setMessage,} from "../../redux/messaging/messaging.actions";
|
||||
import {selectIsSending, selectMessage,} from "../../redux/messaging/messaging.selectors";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import ChatMediaSelector from "../chat-media-selector/chat-media-selector.component";
|
||||
import ChatPresetsComponent from "../chat-presets/chat-presets.component";
|
||||
@@ -110,6 +104,7 @@ function ChatSendMessageComponent({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
|
||||
@@ -9,17 +9,17 @@ export default function ChatTagRoComponent({
|
||||
loading,
|
||||
handleSearch,
|
||||
handleInsertTag,
|
||||
setVisible,
|
||||
setOpen,
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
|
||||
return (
|
||||
<Space flex>
|
||||
<Space>
|
||||
<div style={{width: "15rem"}}>
|
||||
<Select
|
||||
showSearch
|
||||
autoFocus
|
||||
dropdownMatchSelectWidth
|
||||
popupMatchSelectWidth
|
||||
placeholder={t("general.labels.search")}
|
||||
filterOption={false}
|
||||
onSearch={handleSearch}
|
||||
@@ -38,7 +38,7 @@ export default function ChatTagRoComponent({
|
||||
{loading ? (
|
||||
<LoadingOutlined/>
|
||||
) : (
|
||||
<CloseCircleOutlined onClick={() => setVisible(false)} />
|
||||
<CloseCircleOutlined onClick={() => setOpen(false)}/>
|
||||
)}
|
||||
</Space>
|
||||
);
|
||||
|
||||
@@ -11,7 +11,7 @@ import ChatTagRo from "./chat-tag-ro.component";
|
||||
|
||||
export default function ChatTagRoContainer({conversation}) {
|
||||
const {t} = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
|
||||
const [loadRo, {loading, data}] = useLazyQuery(SEARCH_FOR_JOBS);
|
||||
|
||||
@@ -33,7 +33,7 @@ export default function ChatTagRoContainer({ conversation }) {
|
||||
const handleInsertTag = (value, option) => {
|
||||
logImEXEvent("messaging_add_job_tag");
|
||||
insertTag({variables: {jobId: option.key}});
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
};
|
||||
|
||||
const existingJobTags =
|
||||
@@ -47,16 +47,16 @@ export default function ChatTagRoContainer({ conversation }) {
|
||||
|
||||
return (
|
||||
<div>
|
||||
{visible ? (
|
||||
{open ? (
|
||||
<ChatTagRo
|
||||
loading={loading}
|
||||
roOptions={roOptions}
|
||||
handleSearch={handleSearch}
|
||||
handleInsertTag={handleInsertTag}
|
||||
setVisible={setVisible}
|
||||
setOpen={setOpen}
|
||||
/>
|
||||
) : (
|
||||
<Tag onClick={() => setVisible(true)}>
|
||||
<Tag onClick={() => setOpen(true)}>
|
||||
<PlusOutlined/>
|
||||
{t("messaging.actions.link")}
|
||||
</Tag>
|
||||
|
||||
@@ -3,6 +3,7 @@ import Rate from "./rate/rate.component";
|
||||
import Slider from "./slider/slider.component";
|
||||
import Text from "./text/text.component";
|
||||
import Textarea from "./textarea/textarea.component";
|
||||
|
||||
const e = {
|
||||
checkbox: CheckboxFormItem,
|
||||
slider: Slider,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import React from "react";
|
||||
import { Result, Button } from "antd";
|
||||
import {Button, Result} from "antd";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
export default function ConflictComponent() {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {useQuery} from "@apollo/client";
|
||||
import moment from "moment";
|
||||
import dayjs from "../../utils/day";
|
||||
import React from "react";
|
||||
import {QUERY_AVAILABLE_CC} from "../../graphql/courtesy-car.queries";
|
||||
import AlertComponent from "../alert/alert.component";
|
||||
@@ -7,7 +7,7 @@ import ContractCarsComponent from "./contract-cars.component";
|
||||
|
||||
export default function ContractCarsContainer({selectedCarState, form}) {
|
||||
const {loading, error, data} = useQuery(QUERY_AVAILABLE_CC, {
|
||||
variables: { today: moment().format("YYYY-MM-DD") },
|
||||
variables: {today: dayjs().format("YYYY-MM-DD")},
|
||||
fetchPolicy: "network-only",
|
||||
nextFetchPolicy: "network-only",
|
||||
});
|
||||
|
||||
@@ -1,26 +1,14 @@
|
||||
import {useMutation} from "@apollo/client";
|
||||
import {
|
||||
Button,
|
||||
Form,
|
||||
InputNumber,
|
||||
notification,
|
||||
Popover,
|
||||
Radio,
|
||||
Select,
|
||||
Space,
|
||||
} from "antd";
|
||||
import {Button, Form, InputNumber, notification, Popover, Radio, Select, Space,} from "antd";
|
||||
import axios from "axios";
|
||||
import moment from "moment";
|
||||
import dayjs from "../../utils/day";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
import { useHistory } from "react-router-dom";
|
||||
import {useNavigate} from "react-router-dom";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {INSERT_NEW_JOB} from "../../graphql/jobs.queries";
|
||||
import {
|
||||
selectBodyshop,
|
||||
selectCurrentUser,
|
||||
} from "../../redux/user/user.selectors";
|
||||
import {selectBodyshop, selectCurrentUser,} from "../../redux/user/user.selectors";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
@@ -38,17 +26,17 @@ export function ContractConvertToRo({
|
||||
disabled,
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
const [visible, setVisible] = useState(false);
|
||||
const [open, setOpen] = useState(false);
|
||||
const [loading, setLoading] = useState(false);
|
||||
const [insertJob] = useMutation(INSERT_NEW_JOB);
|
||||
const history = useHistory();
|
||||
const history = useNavigate();
|
||||
|
||||
const handleFinish = async (values) => {
|
||||
setLoading(true);
|
||||
|
||||
const contractLength = moment(contract.actualreturn).diff(
|
||||
moment(contract.start),
|
||||
"days"
|
||||
const contractLength = dayjs(contract.actualreturn).diff(
|
||||
dayjs(contract.start),
|
||||
"day"
|
||||
);
|
||||
const billingLines = [];
|
||||
if (contractLength > 0)
|
||||
@@ -306,7 +294,7 @@ export function ContractConvertToRo({
|
||||
});
|
||||
}
|
||||
|
||||
setVisible(false);
|
||||
setOpen(false);
|
||||
setLoading(false);
|
||||
};
|
||||
|
||||
@@ -380,7 +368,7 @@ export function ContractConvertToRo({
|
||||
<Button type="primary" htmlType="submit" loading={loading}>
|
||||
{t("contracts.actions.convertoro")}
|
||||
</Button>
|
||||
<Button onClick={() => setVisible(false)}>
|
||||
<Button onClick={() => setOpen(false)}>
|
||||
{t("general.actions.close")}
|
||||
</Button>
|
||||
</Space>
|
||||
@@ -390,9 +378,9 @@ export function ContractConvertToRo({
|
||||
|
||||
return (
|
||||
<div>
|
||||
<Popover content={popContent} visible={visible}>
|
||||
<Popover content={popContent} open={open}>
|
||||
<Button
|
||||
onClick={() => setVisible(true)}
|
||||
onClick={() => setOpen(true)}
|
||||
loading={loading}
|
||||
disabled={!contract.dailyrate || !contract.actualreturn || disabled}
|
||||
>
|
||||
@@ -402,6 +390,7 @@ export function ContractConvertToRo({
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
mapDispatchToProps
|
||||
|
||||
@@ -3,6 +3,7 @@ import { Button, notification } from "antd";
|
||||
import React, {useEffect} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {GET_JOB_FOR_CC_CONTRACT} from "../../graphql/jobs.queries";
|
||||
|
||||
export default function ContractCreateJobPrefillComponent({jobId, form}) {
|
||||
const [call, {loading, error, data}] = useLazyQuery(
|
||||
GET_JOB_FOR_CC_CONTRACT
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import {WarningFilled} from "@ant-design/icons";
|
||||
import {Form, Input, InputNumber, Space} from "antd";
|
||||
import moment from "moment";
|
||||
import dayjs from "../../utils/day";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {DateFormatter} from "../../utils/DateFormatter";
|
||||
@@ -11,9 +11,7 @@ import CourtesyCarFuelSlider from "../courtesy-car-fuel-select/courtesy-car-fuel
|
||||
import FormDatePicker from "../form-date-picker/form-date-picker.component";
|
||||
import FormDateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
||||
import FormFieldsChanged from "../form-fields-changed-alert/form-fields-changed-alert.component";
|
||||
import InputPhone, {
|
||||
PhoneItemFormatterValidation,
|
||||
} from "../form-items-formatted/phone-form-item.component";
|
||||
import InputPhone, {PhoneItemFormatterValidation,} from "../form-items-formatted/phone-form-item.component";
|
||||
import LayoutFormRow from "../layout-form-row/layout-form-row.component";
|
||||
import ContractFormJobPrefill from "./contract-form-job-prefill.component";
|
||||
|
||||
@@ -96,8 +94,8 @@ export default function ContractFormComponent({
|
||||
const dueForService =
|
||||
selectedCar &&
|
||||
selectedCar.nextservicedate &&
|
||||
moment(selectedCar.nextservicedate).isBefore(
|
||||
moment(form.getFieldValue("scheduledreturn"))
|
||||
dayjs(selectedCar.nextservicedate).isBefore(
|
||||
dayjs(form.getFieldValue("scheduledreturn"))
|
||||
);
|
||||
|
||||
if (mileageOver || dueForService)
|
||||
@@ -190,9 +188,9 @@ export default function ContractFormComponent({
|
||||
}
|
||||
>
|
||||
{() => {
|
||||
const dlExpiresBeforeReturn = moment(
|
||||
const dlExpiresBeforeReturn = dayjs(
|
||||
form.getFieldValue("driver_dlexpiry")
|
||||
).isBefore(moment(form.getFieldValue("scheduledreturn")));
|
||||
).isBefore(dayjs(form.getFieldValue("scheduledreturn")));
|
||||
|
||||
return (
|
||||
<div>
|
||||
|
||||
@@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next";
|
||||
import {Link} from "react-router-dom";
|
||||
import DataLabel from "../data-label/data-label.component";
|
||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||
|
||||
export default function ContractJobBlock({job}) {
|
||||
const {t} = useTranslation();
|
||||
return (
|
||||
|
||||
@@ -11,6 +11,7 @@ const mapStateToProps = createStructuredSelector({
|
||||
//currentUser: selectCurrentUser
|
||||
bodyshop: selectBodyshop,
|
||||
});
|
||||
|
||||
export function ContractJobsContainer({selectedJobState, bodyshop}) {
|
||||
const {loading, error, data} = useQuery(QUERY_ALL_ACTIVE_JOBS, {
|
||||
variables: {
|
||||
@@ -36,4 +37,5 @@ export function ContractJobsContainer({ selectedJobState, bodyshop }) {
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
||||
export default connect(mapStateToProps, null)(ContractJobsContainer);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {Button, Input, Modal, Typography} from "antd";
|
||||
import moment from "moment";
|
||||
import dayjs from "../../utils/day";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import aamva from "../../utils/aamva";
|
||||
@@ -26,8 +26,8 @@ export default function ContractLicenseDecodeButton({ form }) {
|
||||
|
||||
const values = {
|
||||
driver_dlnumber: decodedBarcode.dl,
|
||||
driver_dlexpiry: moment(
|
||||
`20${decodedBarcode.expiration_date}${moment(
|
||||
driver_dlexpiry: dayjs(
|
||||
`20${decodedBarcode.expiration_date}${dayjs(
|
||||
decodedBarcode.birthday
|
||||
).format("DD")}`
|
||||
),
|
||||
@@ -38,7 +38,7 @@ export default function ContractLicenseDecodeButton({ form }) {
|
||||
driver_city: decodedBarcode.city,
|
||||
driver_state: decodedBarcode.state,
|
||||
driver_zip: decodedBarcode.postal_code,
|
||||
driver_dob: moment(decodedBarcode.birthday),
|
||||
driver_dob: dayjs(decodedBarcode.birthday),
|
||||
};
|
||||
|
||||
form.setFieldsValue(values);
|
||||
@@ -55,7 +55,7 @@ export default function ContractLicenseDecodeButton({ form }) {
|
||||
return (
|
||||
<div>
|
||||
<Modal
|
||||
visible={modalVisible}
|
||||
open={modalVisible}
|
||||
okText={t("contracts.actions.senddltoform")}
|
||||
onOk={handleInsertForm}
|
||||
okButtonProps={{disabled: !!!decodedBarcode}}
|
||||
@@ -94,14 +94,14 @@ export default function ContractLicenseDecodeButton({ form }) {
|
||||
{decodedBarcode.address}
|
||||
</DataLabel>
|
||||
<DataLabel label={t("contracts.fields.driver_dlexpiry")}>
|
||||
{moment(
|
||||
`20${decodedBarcode.expiration_date}${moment(
|
||||
{dayjs(
|
||||
`20${decodedBarcode.expiration_date}${dayjs(
|
||||
decodedBarcode.birthday
|
||||
).format("DD")}`
|
||||
).format("MM/DD/YYYY")}
|
||||
</DataLabel>
|
||||
<DataLabel label={t("contracts.fields.driver_dob")}>
|
||||
{moment(decodedBarcode.birthday).format("MM/DD/YYYY")}
|
||||
{dayjs(decodedBarcode.birthday).format("MM/DD/YYYY")}
|
||||
</DataLabel>
|
||||
<div>
|
||||
<Typography.Title level={4}>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect, forwardRef } from "react";
|
||||
import React, {forwardRef, useEffect, useState} from "react";
|
||||
import {Select} from "antd";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
const ContractStatusComponent = ({value, onChange}, ref) => {
|
||||
|
||||
@@ -31,7 +31,7 @@ export function ContractsFindModalContainer({
|
||||
}) {
|
||||
const {t} = useTranslation();
|
||||
|
||||
const { visible } = contractFinderModal;
|
||||
const {open} = contractFinderModal;
|
||||
|
||||
const [form] = Form.useForm();
|
||||
|
||||
@@ -52,14 +52,14 @@ export function ContractsFindModalContainer({
|
||||
};
|
||||
|
||||
useEffect(() => {
|
||||
if (visible) {
|
||||
if (open) {
|
||||
form.resetFields();
|
||||
}
|
||||
}, [visible, form]);
|
||||
}, [open, form]);
|
||||
|
||||
return (
|
||||
<Modal
|
||||
visible={visible}
|
||||
open={open}
|
||||
width="70%"
|
||||
title={t("contracts.labels.findermodal")}
|
||||
onCancel={() => toggleModalVisible()}
|
||||
|
||||
@@ -3,13 +3,13 @@ import { Button, Card, Input, Space, Table, Typography } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||
import {Link, useLocation, useNavigate} from "react-router-dom";
|
||||
import {setModalContext} from "../../redux/modals/modals.actions";
|
||||
import {DateTimeFormatter} from "../../utils/DateFormatter";
|
||||
import {alphaSort} from "../../utils/sorters";
|
||||
import ContractsFindModalContainer from "../contracts-find-modal/contracts-find-modal.container";
|
||||
|
||||
import moment from "moment";
|
||||
import dayjs from "../../utils/day";
|
||||
import {connect} from "react-redux";
|
||||
import {createStructuredSelector} from "reselect";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
@@ -39,7 +39,7 @@ export function ContractsList({
|
||||
sortedInfo: {},
|
||||
filteredInfo: {text: ""},
|
||||
});
|
||||
const history = useHistory();
|
||||
const history = useNavigate();
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const {page} = search;
|
||||
|
||||
@@ -152,8 +152,8 @@ export function ContractsList({
|
||||
render: (text, record) =>
|
||||
(record.actualreturn &&
|
||||
record.start &&
|
||||
`${moment(record.actualreturn)
|
||||
.diff(moment(record.start), "days", true)
|
||||
`${dayjs(record.actualreturn)
|
||||
.diff(dayjs(record.start), "day", true)
|
||||
.toFixed(1)} days`) ||
|
||||
"",
|
||||
},
|
||||
@@ -164,7 +164,7 @@ export function ContractsList({
|
||||
search.page = pagination.current;
|
||||
search.sortcolumn = sorter.columnKey;
|
||||
search.sortorder = sorter.order;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
history({search: queryString.stringify(search)});
|
||||
};
|
||||
|
||||
return (
|
||||
@@ -179,7 +179,7 @@ export function ContractsList({
|
||||
<Button
|
||||
onClick={() => {
|
||||
delete search.search;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
history({search: queryString.stringify(search)});
|
||||
}}
|
||||
>
|
||||
{t("general.actions.clear")}
|
||||
@@ -196,7 +196,7 @@ export function ContractsList({
|
||||
placeholder={search.searh || t("general.labels.search")}
|
||||
onSearch={(value) => {
|
||||
search.search = value;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
history({search: queryString.stringify(search)});
|
||||
}}
|
||||
/>
|
||||
</Space>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import {DownOutlined} from "@ant-design/icons";
|
||||
import { Dropdown, Menu } from "antd";
|
||||
import {Dropdown} from "antd";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {connect} from "react-redux";
|
||||
@@ -18,20 +18,16 @@ export function ContractsRatesChangeButton({ disabled, form, bodyshop }) {
|
||||
form.setFieldsValue(rate);
|
||||
};
|
||||
|
||||
const menu = (
|
||||
<div>
|
||||
<Menu onClick={handleClick}>
|
||||
{bodyshop.md_ccc_rates.map((rate, idx) => (
|
||||
<Menu.Item value={rate} key={idx}>
|
||||
{rate.label}
|
||||
</Menu.Item>
|
||||
))}
|
||||
</Menu>
|
||||
</div>
|
||||
);
|
||||
const menuItems = bodyshop.md_ccc_rates.map((i, idx) => ({
|
||||
key: idx,
|
||||
label: i.label,
|
||||
value: i,
|
||||
}));
|
||||
|
||||
const menu = {items: menuItems, onClick: handleClick};
|
||||
|
||||
return (
|
||||
<Dropdown overlay={menu} disabled={disabled}>
|
||||
<Dropdown menu={menu} disabled={disabled}>
|
||||
<a
|
||||
className="ant-dropdown-link"
|
||||
href=" #"
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Card, Table } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||
import {Link, useLocation, useNavigate} from "react-router-dom";
|
||||
import {DateFormatter} from "../../utils/DateFormatter";
|
||||
import {alphaSort} from "../../utils/sorters";
|
||||
import {pageLimit} from "../../utils/config";
|
||||
@@ -13,7 +13,7 @@ export default function CourtesyCarContractListComponent({
|
||||
}) {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const {page, sortcolumn, sortorder} = search;
|
||||
const history = useHistory();
|
||||
const history = useNavigate();
|
||||
|
||||
const {t} = useTranslation();
|
||||
|
||||
@@ -81,7 +81,7 @@ export default function CourtesyCarContractListComponent({
|
||||
search.page = pagination.current;
|
||||
search.sortcolumn = sorter.columnKey;
|
||||
search.sortorder = sorter.order;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
history({search: queryString.stringify(search)});
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import {WarningFilled} from "@ant-design/icons";
|
||||
import {useApolloClient} from "@apollo/client";
|
||||
import { Button, Form, Input, InputNumber, PageHeader, Space } from "antd";
|
||||
import moment from "moment";
|
||||
import {Button, Form, Input, InputNumber, Space} from "antd";
|
||||
import {PageHeader} from "@ant-design/pro-layout";
|
||||
import dayjs from "../../utils/day";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {CHECK_CC_FLEET_NUMBER} from "../../graphql/courtesy-car.queries";
|
||||
@@ -263,7 +264,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
|
||||
const nextservicedate = form.getFieldValue("nextservicedate");
|
||||
const dueForService =
|
||||
nextservicedate &&
|
||||
moment(nextservicedate).endOf("day").isSameOrBefore(moment());
|
||||
dayjs(nextservicedate).endOf("day").isSameOrBefore(dayjs());
|
||||
|
||||
if (dueForService)
|
||||
return (
|
||||
@@ -304,7 +305,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
|
||||
const expires = form.getFieldValue("registrationexpires");
|
||||
|
||||
const dateover =
|
||||
expires && moment(expires).endOf("day").isBefore(moment());
|
||||
expires && dayjs(expires).endOf("day").isBefore(dayjs());
|
||||
|
||||
if (dateover)
|
||||
return (
|
||||
@@ -340,7 +341,7 @@ export default function CourtesyCarCreateFormComponent({ form, saveLoading }) {
|
||||
const expires = form.getFieldValue("insuranceexpires");
|
||||
|
||||
const dateover =
|
||||
expires && moment(expires).endOf("day").isBefore(moment());
|
||||
expires && dayjs(expires).endOf("day").isBefore(dayjs());
|
||||
|
||||
if (dateover)
|
||||
return (
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import {Select} from "antd";
|
||||
import React, {forwardRef, useEffect, useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
const CourtesyCarReadinessComponent = ({value, onChange}, ref) => {
|
||||
|
||||
@@ -7,7 +7,7 @@ import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
||||
import {selectCourtesyCarReturn} from "../../redux/modals/modals.selectors";
|
||||
import {selectBodyshop} from "../../redux/user/user.selectors";
|
||||
import CourtesyCarReturnModalComponent from "./courtesy-car-return-modal.component";
|
||||
import moment from "moment";
|
||||
import dayjs from "../../utils/day";
|
||||
import {RETURN_CONTRACT} from "../../graphql/cccontracts.queries";
|
||||
import {useMutation} from "@apollo/client";
|
||||
|
||||
@@ -26,7 +26,7 @@ export function CCReturnModalContainer({
|
||||
bodyshop,
|
||||
}) {
|
||||
const [loading, setLoading] = useState(false);
|
||||
const { visible, context, actions } = courtesyCarReturnModal;
|
||||
const {open, context, actions} = courtesyCarReturnModal;
|
||||
const {t} = useTranslation();
|
||||
const [form] = Form.useForm();
|
||||
const [updateContract] = useMutation(RETURN_CONTRACT);
|
||||
@@ -64,7 +64,7 @@ export function CCReturnModalContainer({
|
||||
return (
|
||||
<Modal
|
||||
title={t("courtesycars.labels.return")}
|
||||
visible={visible}
|
||||
open={open}
|
||||
onCancel={() => toggleModalVisible()}
|
||||
width={"90%"}
|
||||
okText={t("general.actions.save")}
|
||||
@@ -74,7 +74,7 @@ export function CCReturnModalContainer({
|
||||
<Form
|
||||
form={form}
|
||||
onFinish={handleFinish}
|
||||
initialValues={{ fuel: 100, actualreturn: moment(new Date()) }}
|
||||
initialValues={{fuel: 100, actualreturn: dayjs(new Date())}}
|
||||
>
|
||||
<CourtesyCarReturnModalComponent/>
|
||||
</Form>
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import React, { useState, useEffect, forwardRef } from "react";
|
||||
import React, {forwardRef, useEffect, useState} from "react";
|
||||
import {Select} from "antd";
|
||||
import {useTranslation} from "react-i18next";
|
||||
|
||||
const {Option} = Select;
|
||||
|
||||
const CourtesyCarStatusComponent = ({value, onChange}, ref) => {
|
||||
|
||||
@@ -1,15 +1,6 @@
|
||||
import {SyncOutlined, WarningFilled} from "@ant-design/icons";
|
||||
import {
|
||||
Button,
|
||||
Card,
|
||||
Dropdown,
|
||||
Input,
|
||||
Menu,
|
||||
Space,
|
||||
Table,
|
||||
Tooltip,
|
||||
} from "antd";
|
||||
import moment from "moment";
|
||||
import {Button, Card, Dropdown, Input, Space, Table, Tooltip,} from "antd";
|
||||
import dayjs from "../../utils/day";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {Link} from "react-router-dom";
|
||||
@@ -18,6 +9,7 @@ import { GenerateDocument } from "../../utils/RenderTemplate";
|
||||
import {TemplateList} from "../../utils/TemplateConstants";
|
||||
import {alphaSort} from "../../utils/sorters";
|
||||
import {OwnerNameDisplayFunction} from "../owner-name-display/owner-name-display.component";
|
||||
|
||||
export default function CourtesyCarsList({loading, courtesycars, refetch}) {
|
||||
const [state, setState] = useState({
|
||||
sortedInfo: {},
|
||||
@@ -77,8 +69,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
const mileageOver = nextservicekm ? nextservicekm <= mileage : false;
|
||||
|
||||
const dueForService =
|
||||
nextservicedate &&
|
||||
moment(nextservicedate).endOf("day").isSameOrBefore(moment());
|
||||
nextservicedate && dayjs(nextservicedate).endOf('day').isSameOrBefore(dayjs());
|
||||
|
||||
return (
|
||||
<Space>
|
||||
@@ -229,6 +220,27 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
(t(c.status) || "").toLowerCase().includes(searchText.toLowerCase())
|
||||
)
|
||||
: courtesycars;
|
||||
|
||||
const items = [
|
||||
{
|
||||
key: "courtesycar_inventory",
|
||||
label: t("printcenter.courtesycarcontract.courtesy_car_inventory"),
|
||||
onClick: () =>
|
||||
GenerateDocument(
|
||||
{
|
||||
name: TemplateList("courtesycar").courtesy_car_inventory.key,
|
||||
variables: {
|
||||
//id: contract.id
|
||||
},
|
||||
},
|
||||
{},
|
||||
"p"
|
||||
),
|
||||
},
|
||||
];
|
||||
|
||||
const menu = {items};
|
||||
|
||||
return (
|
||||
<Card
|
||||
title={t("menus.header.courtesycars")}
|
||||
@@ -237,30 +249,7 @@ export default function CourtesyCarsList({ loading, courtesycars, refetch }) {
|
||||
<Button onClick={() => refetch()}>
|
||||
<SyncOutlined/>
|
||||
</Button>
|
||||
<Dropdown
|
||||
trigger="click"
|
||||
overlay={
|
||||
<Menu>
|
||||
<Menu.Item
|
||||
onClick={() =>
|
||||
GenerateDocument(
|
||||
{
|
||||
name: TemplateList("courtesycar").courtesy_car_inventory
|
||||
.key,
|
||||
variables: {
|
||||
//id: contract.id
|
||||
},
|
||||
},
|
||||
{},
|
||||
"p"
|
||||
)
|
||||
}
|
||||
>
|
||||
{t("printcenter.courtesycarcontract.courtesy_car_inventory")}
|
||||
</Menu.Item>
|
||||
</Menu>
|
||||
}
|
||||
>
|
||||
<Dropdown trigger="click" menu={menu}>
|
||||
<Button>{t("general.labels.print")}</Button>
|
||||
</Dropdown>
|
||||
<Link to={`/manage/courtesycars/new`}>
|
||||
|
||||
@@ -3,7 +3,7 @@ import { Button, Card, Table } from "antd";
|
||||
import queryString from "query-string";
|
||||
import React, {useState} from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import { Link, useHistory, useLocation } from "react-router-dom";
|
||||
import {Link, useLocation, useNavigate} from "react-router-dom";
|
||||
import {DateFormatter} from "../../utils/DateFormatter";
|
||||
import {alphaSort} from "../../utils/sorters";
|
||||
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
|
||||
@@ -17,7 +17,7 @@ export default function CsiResponseListPaginated({
|
||||
}) {
|
||||
const search = queryString.parse(useLocation().search);
|
||||
const {responseid, page, sortcolumn, sortorder} = search;
|
||||
const history = useHistory();
|
||||
const history = useNavigate();
|
||||
const [state, setState] = useState({
|
||||
sortedInfo: {},
|
||||
filteredInfo: {text: ""},
|
||||
@@ -80,18 +80,18 @@ export default function CsiResponseListPaginated({
|
||||
search.page = pagination.current;
|
||||
search.sortcolumn = sorter.columnKey;
|
||||
search.sortorder = sorter.order;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
history({search: queryString.stringify(search)});
|
||||
};
|
||||
|
||||
const handleOnRowClick = (record) => {
|
||||
if (record) {
|
||||
if (record.id) {
|
||||
search.responseid = record.id;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
history({search: queryString.stringify(search)});
|
||||
}
|
||||
} else {
|
||||
delete search.responseid;
|
||||
history.push({ search: queryString.stringify(search) });
|
||||
history({search: queryString.stringify(search)});
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,19 +1,9 @@
|
||||
import {Card} from "antd";
|
||||
import _ from "lodash";
|
||||
import moment from "moment";
|
||||
import dayjs from "../../../utils/day";
|
||||
import React from "react";
|
||||
import {useTranslation} from "react-i18next";
|
||||
import {
|
||||
Bar,
|
||||
CartesianGrid,
|
||||
ComposedChart,
|
||||
Legend,
|
||||
Line,
|
||||
ResponsiveContainer,
|
||||
Tooltip,
|
||||
XAxis,
|
||||
YAxis,
|
||||
} from "recharts";
|
||||
import {Bar, CartesianGrid, ComposedChart, Legend, Line, ResponsiveContainer, Tooltip, XAxis, YAxis,} from "recharts";
|
||||
import * as Utils from "../../scoreboard-targets-table/scoreboard-targets-table.util";
|
||||
import DashboardRefreshRequired from "../refresh-required.component";
|
||||
|
||||
@@ -27,7 +17,7 @@ export default function DashboardMonthlyEmployeeEfficiency({
|
||||
return <DashboardRefreshRequired {...cardProps} />;
|
||||
|
||||
const ticketsByDate = _.groupBy(data.monthly_employee_efficiency, (item) =>
|
||||
moment(item.date).format("YYYY-MM-DD")
|
||||
dayjs(item.date).format("YYYY-MM-DD")
|
||||
);
|
||||
|
||||
const listOfDays = Utils.ListOfDaysInCurrentMonth();
|
||||
@@ -53,7 +43,7 @@ export default function DashboardMonthlyEmployeeEfficiency({
|
||||
((dailyHrs.productive - dailyHrs.actual) / dailyHrs.actual + 1) * 100;
|
||||
|
||||
const theValue = {
|
||||
date: moment(val).format("DD"),
|
||||
date: dayjs(val).format("DD"),
|
||||
// ...dailyHrs,
|
||||
actual: dailyHrs.actual.toFixed(1),
|
||||
productive: dailyHrs.productive.toFixed(1),
|
||||
@@ -159,9 +149,9 @@ export default function DashboardMonthlyEmployeeEfficiency({
|
||||
}
|
||||
|
||||
export const DashboardMonthlyEmployeeEfficiencyGql = `
|
||||
monthly_employee_efficiency: timetickets(where: {_and: [{date: {_gte: "${moment()
|
||||
monthly_employee_efficiency: timetickets(where: {_and: [{date: {_gte: "${dayjs()
|
||||
.startOf("month")
|
||||
.format("YYYY-MM-DD")}"}},{date: {_lte: "${moment()
|
||||
.format("YYYY-MM-DD")}"}},{date: {_lte: "${dayjs()
|
||||
.endOf("month")
|
||||
.format("YYYY-MM-DD")}"}} ]}) {
|
||||
actualhrs
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user