From c7a2c8209a1ed6f277b08249cd2bc66beb6eb862 Mon Sep 17 00:00:00 2001 From: Patrick Fic Date: Mon, 9 Dec 2024 18:47:32 -0800 Subject: [PATCH] IO-3020 IO-3036 Add additional upsell components. --- bodyshop_translations.babel | 564 +++++++++++++++++- .../blur-wrapper.component.jsx | 1 + .../components/upsell/upsell.component.jsx | 110 +++- .../accounting-payables.container.jsx | 11 +- .../accounting-payments.container.jsx | 10 +- .../accounting-receivables.container.jsx | 10 +- .../src/pages/bills/bills.page.container.jsx | 10 +- .../contract-create.page.container.jsx | 11 +- .../contract-detail.page.container.jsx | 13 +- .../contracts/contracts.page.container.jsx | 10 +- .../courtesy-car-create.page.container.jsx | 11 +- .../courtesy-cars.page.container.jsx | 10 +- .../pages/dashboard/dashboard.container.jsx | 10 +- .../export-logs.page.container.jsx | 10 +- .../jobs-delivery.page.container.jsx | 10 +- .../jobs-intake.page.container.jsx | 11 +- .../payments-all.container.page.jsx | 11 +- .../production-board.container.jsx | 14 +- .../scoreboard/scoreboard.page.container.jsx | 11 +- .../pages/shift-clock/shift-clock.page.jsx | 10 +- .../shop-csi/shop-csi.container.page.jsx | 43 +- client/src/pages/tech/tech.page.component.jsx | 13 +- .../temporary-docs.container.jsx | 10 +- .../time-tickets/time-tickets.container.jsx | 11 +- .../tt-approvals.page.container.jsx | 10 +- client/src/translations/en_us/common.json | 64 +- client/src/translations/es/common.json | 64 +- client/src/translations/fr/common.json | 64 +- 28 files changed, 1015 insertions(+), 122 deletions(-) diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 2b5a4c48d..6fadc58a7 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -59704,6 +59704,152 @@ messages + + accounting + + + payables + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + payments + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + receivables + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + audit @@ -59855,6 +60001,214 @@ + + checklist + + + general + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + + + courtesycars + + + general + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + + + csi + + + general + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + + + dashboard + + + general + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + lifecycle @@ -60007,7 +60361,111 @@ - scheduling + payments + + + general + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + + + scoreboard + + + general + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + + + smartscheduling datepicker @@ -60152,6 +60610,58 @@ + + techconsole + + + general + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + timetickets @@ -60251,6 +60761,58 @@ + + visualboard + + + general + + + subtitle + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + title + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + diff --git a/client/src/components/feature-wrapper/blur-wrapper.component.jsx b/client/src/components/feature-wrapper/blur-wrapper.component.jsx index 67c4b8b82..b4e4a2129 100644 --- a/client/src/components/feature-wrapper/blur-wrapper.component.jsx +++ b/client/src/components/feature-wrapper/blur-wrapper.component.jsx @@ -129,6 +129,7 @@ const featureNameList = [ "media", "visualboard", "scoreboard", + "techconsole", "checklist", "smartscheduling", "roguard", diff --git a/client/src/components/upsell/upsell.component.jsx b/client/src/components/upsell/upsell.component.jsx index 8560f9d34..3ad3673d4 100644 --- a/client/src/components/upsell/upsell.component.jsx +++ b/client/src/components/upsell/upsell.component.jsx @@ -1,11 +1,21 @@ -import { AppstoreAddOutlined, CalendarOutlined, CarOutlined, MobileOutlined } from "@ant-design/icons"; -import { Result, Button, Card } from "antd"; +import { + AppstoreAddOutlined, + BuildOutlined, + CalendarOutlined, + CarOutlined, + DashboardOutlined, + DollarOutlined, + LineChartOutlined, + MobileOutlined, + StarOutlined +} from "@ant-design/icons"; +import { Button, Card, Result } from "antd"; +import i18n from "i18next"; import React, { useEffect, useRef } from "react"; import { useTranslation } from "react-i18next"; -import i18n from "i18next"; import "./upsell.styles.scss"; -export default function UpsellComponent({ featureName, subFeatureName, upsell, disableMask = false }) { +export default function UpsellComponent({ featureName, subFeatureName, upsell, disableMask }) { const { t } = useTranslation(); const resultProps = upsell || upsellEnum[featureName][subFeatureName]; const componentRef = useRef(null); @@ -27,7 +37,9 @@ export default function UpsellComponent({ featureName, subFeatureName, upsell, d parentElement.prepend(mask); return () => { - parentElement.removeChild(mask); + if (mask && parentElement.contains(mask)) { + parentElement.removeChild(mask); + } }; } }, [disableMask]); @@ -40,7 +52,7 @@ export default function UpsellComponent({ featureName, subFeatureName, upsell, d ); } //Kept in the same function as the result props line must mirror and doesnt warrant a separate function. -export function UpsellMaskWrapper({ children, upsell, featureName, subFeatureName, disableMask = false }) { +export function UpsellMaskWrapper({ children, upsell, featureName, subFeatureName }) { const resultProps = upsell || upsellEnum[featureName][subFeatureName]; return (
@@ -71,6 +83,24 @@ export const upsellEnum = { //status: null } }, + checklist: { + general: { + //icon: null, + title: i18n.t("upsell.messages.checklist.general.title"), + subTitle: i18n.t("upsell.messages.checklist.general.subtitle"), + extra: + //status: null + } + }, + payments: { + general: { + //icon: null, + title: i18n.t("upsell.messages.payments.general.title"), + subTitle: i18n.t("upsell.messages.payments.general.subtitle"), + extra: + //status: null + } + }, audit: { general: { //icon: null, @@ -136,5 +166,73 @@ export const upsellEnum = { subTitle: i18n.t("upsell.messages.smartscheduling.datepicker.subtitle"), extra: } + }, + accounting: { + payables: { + icon: , + title: i18n.t("upsell.messages.accounting.payables.title"), + subTitle: i18n.t("upsell.messages.accounting.payables.subtitle"), + extra: + }, + receivables: { + icon: , + title: i18n.t("upsell.messages.accounting.receivables.title"), + subTitle: i18n.t("upsell.messages.accounting.receivables.subtitle"), + extra: + }, + payments: { + icon: , + title: i18n.t("upsell.messages.accounting.payments.title"), + subTitle: i18n.t("upsell.messages.accounting.payments.subtitle"), + extra: + } + }, + courtesycars: { + general: { + icon: , + title: i18n.t("upsell.messages.courtesycars.general.title"), + subTitle: i18n.t("upsell.messages.courtesycars.general.subtitle"), + extra: + } + }, + dashboard: { + general: { + icon: , + title: i18n.t("upsell.messages.dashboard.general.title"), + subTitle: i18n.t("upsell.messages.dashboard.general.subtitle"), + extra: + } + }, + visualboard: { + general: { + icon: , + title: i18n.t("upsell.messages.visualboard.general.title"), + subTitle: i18n.t("upsell.messages.visualboard.general.subtitle"), + extra: + } + }, + scoreboard: { + general: { + icon: , + title: i18n.t("upsell.messages.scoreboard.general.title"), + subTitle: i18n.t("upsell.messages.scoreboard.general.subtitle"), + extra: + } + }, + techconsole: { + general: { + icon: , + title: i18n.t("upsell.messages.techconsole.general.title"), + subTitle: i18n.t("upsell.messages.techconsole.general.subtitle"), + extra: + } + }, + csi: { + general: { + icon: , + title: i18n.t("upsell.messages.csi.general.title"), + subTitle: i18n.t("upsell.messages.csi.general.subtitle"), + extra: + } } }; diff --git a/client/src/pages/accounting-payables/accounting-payables.container.jsx b/client/src/pages/accounting-payables/accounting-payables.container.jsx index 498e168b9..8e41bee46 100644 --- a/client/src/pages/accounting-payables/accounting-payables.container.jsx +++ b/client/src/pages/accounting-payables/accounting-payables.container.jsx @@ -13,6 +13,8 @@ import { selectPartnerVersion } from "../../redux/application/application.select import { selectBodyshop } from "../../redux/user/user.selectors"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; +import { Card } from "antd"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -59,11 +61,10 @@ export function AccountingPayablesContainer({ bodyshop, setBreadcrumbs, setSelec
+ + } > diff --git a/client/src/pages/accounting-payments/accounting-payments.container.jsx b/client/src/pages/accounting-payments/accounting-payments.container.jsx index aa422804d..ef57983b1 100644 --- a/client/src/pages/accounting-payments/accounting-payments.container.jsx +++ b/client/src/pages/accounting-payments/accounting-payments.container.jsx @@ -13,6 +13,8 @@ import { checkPartnerStatus } from "../../components/partner-ping/partner-ping.c import { selectPartnerVersion } from "../../redux/application/application.selectors"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; +import { Card } from "antd"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -57,10 +59,10 @@ export function AccountingPaymentsContainer({ bodyshop, setBreadcrumbs, setSelec
+ + } > diff --git a/client/src/pages/accounting-receivables/accounting-receivables.container.jsx b/client/src/pages/accounting-receivables/accounting-receivables.container.jsx index f9bf625fd..cfbb07393 100644 --- a/client/src/pages/accounting-receivables/accounting-receivables.container.jsx +++ b/client/src/pages/accounting-receivables/accounting-receivables.container.jsx @@ -13,6 +13,8 @@ import { checkPartnerStatus } from "../../components/partner-ping/partner-ping.c import { selectPartnerVersion } from "../../redux/application/application.selectors"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, @@ -62,10 +64,10 @@ export function AccountingReceivablesContainer({ bodyshop, setBreadcrumbs, setSe
+ + } > diff --git a/client/src/pages/bills/bills.page.container.jsx b/client/src/pages/bills/bills.page.container.jsx index 1d0e23446..b437bfcb0 100644 --- a/client/src/pages/bills/bills.page.container.jsx +++ b/client/src/pages/bills/bills.page.container.jsx @@ -13,6 +13,8 @@ import BillsPageComponent from "./bills.page.component"; import { pageLimit } from "../../utils/config"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapDispatchToProps = (dispatch) => ({ setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), @@ -55,10 +57,10 @@ export function BillsPageContainer({ setBreadcrumbs, setSelectedHeader }) { return ( + + } > diff --git a/client/src/pages/contract-create/contract-create.page.container.jsx b/client/src/pages/contract-create/contract-create.page.container.jsx index cb55f4d3d..3f974789e 100644 --- a/client/src/pages/contract-create/contract-create.page.container.jsx +++ b/client/src/pages/contract-create/contract-create.page.container.jsx @@ -1,5 +1,5 @@ import { useMutation } from "@apollo/client"; -import { Form, notification } from "antd"; +import { Card, Form, notification } from "antd"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -13,6 +13,7 @@ import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/appli import { selectBodyshop } from "../../redux/user/user.selectors"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import ContractCreatePageComponent from "./contract-create.page.component"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -122,10 +123,10 @@ export function ContractCreatePageContainer({ bodyshop, setBreadcrumbs, setSelec return ( + + } > diff --git a/client/src/pages/contract-detail/contract-detail.page.container.jsx b/client/src/pages/contract-detail/contract-detail.page.container.jsx index 77646a79b..67931a32f 100644 --- a/client/src/pages/contract-detail/contract-detail.page.container.jsx +++ b/client/src/pages/contract-detail/contract-detail.page.container.jsx @@ -1,5 +1,5 @@ import { useMutation, useQuery } from "@apollo/client"; -import { Form, notification } from "antd"; +import { Card, Form, notification } from "antd"; import dayjs from "../../utils/day"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; @@ -16,6 +16,7 @@ import ContractDetailPageComponent from "./contract-detail.page.component"; import NotFound from "../../components/not-found/not-found.component"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapDispatchToProps = (dispatch) => ({ setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), @@ -105,15 +106,15 @@ export function ContractDetailPageContainer({ setBreadcrumbs, addRecentItem, set if (error) return ; if (loading) return ; - if (!!!data.cccontracts_by_pk) return ; + if (!data.cccontracts_by_pk) return ; return ( + + } > diff --git a/client/src/pages/contracts/contracts.page.container.jsx b/client/src/pages/contracts/contracts.page.container.jsx index 71c78eb03..72bc9baf3 100644 --- a/client/src/pages/contracts/contracts.page.container.jsx +++ b/client/src/pages/contracts/contracts.page.container.jsx @@ -12,6 +12,8 @@ import ContractsPageComponent from "./contracts.page.component"; import { pageLimit } from "../../utils/config"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapDispatchToProps = (dispatch) => ({ setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), @@ -58,10 +60,10 @@ export function ContractsPageContainer({ setBreadcrumbs, setSelectedHeader }) { return ( + + } > diff --git a/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx b/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx index 921baf76c..4951d9391 100644 --- a/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx +++ b/client/src/pages/courtesy-car-create/courtesy-car-create.page.container.jsx @@ -1,5 +1,5 @@ import { useMutation } from "@apollo/client"; -import { Form, notification } from "antd"; +import { Card, Form, notification } from "antd"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -12,6 +12,7 @@ import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/appli import { selectBodyshop } from "../../redux/user/user.selectors"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -70,10 +71,10 @@ export function CourtesyCarCreateContainer({ bodyshop, setBreadcrumbs, setSelect return ( + + } > diff --git a/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx b/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx index 32399a994..a69ff2cff 100644 --- a/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx +++ b/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx @@ -9,6 +9,8 @@ import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/appli import CourtesyCarsPageComponent from "./courtesy-cars.page.component"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapDispatchToProps = (dispatch) => ({ setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), @@ -36,10 +38,10 @@ export function CourtesyCarsPageContainer({ setBreadcrumbs, setSelectedHeader }) return ( + + } > diff --git a/client/src/pages/dashboard/dashboard.container.jsx b/client/src/pages/dashboard/dashboard.container.jsx index 445c1798f..be31cb289 100644 --- a/client/src/pages/dashboard/dashboard.container.jsx +++ b/client/src/pages/dashboard/dashboard.container.jsx @@ -6,6 +6,8 @@ import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component"; import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions"; import FeatureWrapper from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapDispatchToProps = (dispatch) => ({ setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), @@ -34,10 +36,10 @@ export function ExportsLogPageContainer({ setBreadcrumbs, setSelectedHeader }) { return ( + + } > diff --git a/client/src/pages/export-logs/export-logs.page.container.jsx b/client/src/pages/export-logs/export-logs.page.container.jsx index 873bfeba2..99babd14b 100644 --- a/client/src/pages/export-logs/export-logs.page.container.jsx +++ b/client/src/pages/export-logs/export-logs.page.container.jsx @@ -6,6 +6,8 @@ import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/appli import ExportLogsPage from "./export-logs.page.component"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapDispatchToProps = (dispatch) => ({ setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), @@ -34,10 +36,10 @@ export function ExportsLogPageContainer({ setBreadcrumbs, setSelectedHeader }) { return ( + + } > diff --git a/client/src/pages/jobs-deliver/jobs-delivery.page.container.jsx b/client/src/pages/jobs-deliver/jobs-delivery.page.container.jsx index f3836831b..0f85dc3b0 100644 --- a/client/src/pages/jobs-deliver/jobs-delivery.page.container.jsx +++ b/client/src/pages/jobs-deliver/jobs-delivery.page.container.jsx @@ -13,6 +13,8 @@ import { selectBodyshop } from "../../redux/user/user.selectors"; import JobchecklistComponent from "../../components/job-checklist/job-checklist.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -62,10 +64,10 @@ export function JobsDeliverContainer({ bodyshop, setBreadcrumbs, setSelectedHead return ( + + } > diff --git a/client/src/pages/jobs-intake/jobs-intake.page.container.jsx b/client/src/pages/jobs-intake/jobs-intake.page.container.jsx index 75e7beef0..5c5ed10b2 100644 --- a/client/src/pages/jobs-intake/jobs-intake.page.container.jsx +++ b/client/src/pages/jobs-intake/jobs-intake.page.container.jsx @@ -11,9 +11,10 @@ import { QUERY_INTAKE_CHECKLIST } from "../../graphql/bodyshop.queries"; import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component"; -import { Result } from "antd"; +import { Card, Result } from "antd"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ //currentUser: selectCurrentUser @@ -66,10 +67,10 @@ export function JobsIntakeContainer({ bodyshop, setBreadcrumbs, setSelectedHeade return ( + + } > diff --git a/client/src/pages/payments-all/payments-all.container.page.jsx b/client/src/pages/payments-all/payments-all.container.page.jsx index 7680f0200..4ae5a8d4c 100644 --- a/client/src/pages/payments-all/payments-all.container.page.jsx +++ b/client/src/pages/payments-all/payments-all.container.page.jsx @@ -14,6 +14,8 @@ import { selectBodyshop } from "../../redux/user/user.selectors"; import { pageLimit } from "../../utils/config"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; +import { Card } from "antd"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -60,11 +62,12 @@ export function AllJobs({ bodyshop, setBreadcrumbs, setSelectedHeader }) { return ( + + } + z > + + } > diff --git a/client/src/pages/scoreboard/scoreboard.page.container.jsx b/client/src/pages/scoreboard/scoreboard.page.container.jsx index 119ee4737..2587bd7fa 100644 --- a/client/src/pages/scoreboard/scoreboard.page.container.jsx +++ b/client/src/pages/scoreboard/scoreboard.page.container.jsx @@ -1,5 +1,5 @@ import Icon, { FieldTimeOutlined } from "@ant-design/icons"; -import { Tabs } from "antd"; +import { Card, Tabs } from "antd"; import queryString from "query-string"; import React, { useEffect } from "react"; import { useTranslation } from "react-i18next"; @@ -15,6 +15,7 @@ import ScoreboardTimeTickets from "../../components/scoreboard-timetickets/score import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; /** * Mapping state to props @@ -68,10 +69,10 @@ export function ScoreboardContainer({ setBreadcrumbs, setSelectedHeader }) { return ( + + } > diff --git a/client/src/pages/shift-clock/shift-clock.page.jsx b/client/src/pages/shift-clock/shift-clock.page.jsx index 38a3dce88..2609f3cdd 100644 --- a/client/src/pages/shift-clock/shift-clock.page.jsx +++ b/client/src/pages/shift-clock/shift-clock.page.jsx @@ -2,15 +2,17 @@ import React from "react"; import RbacWrapper from "../../components/rbac-wrapper/rbac-wrapper.component"; import TimeTicketShift from "../../components/time-ticket-shift/time-ticket-shift.container"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; export default function ShiftClock() { return ( + + } > diff --git a/client/src/pages/shop-csi/shop-csi.container.page.jsx b/client/src/pages/shop-csi/shop-csi.container.page.jsx index 67f9e2ef2..2ab87a11e 100644 --- a/client/src/pages/shop-csi/shop-csi.container.page.jsx +++ b/client/src/pages/shop-csi/shop-csi.container.page.jsx @@ -1,5 +1,5 @@ import { useQuery } from "@apollo/client"; -import { Col, Row } from "antd"; +import { Card, Col, Row } from "antd"; import React, { useEffect } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -12,6 +12,8 @@ import { QUERY_CSI_RESPONSE_PAGINATED } from "../../graphql/csi.queries"; import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/application.actions"; import { selectBodyshop } from "../../redux/user/user.selectors"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -50,21 +52,30 @@ export function ShopCsiContainer({ bodyshop, setBreadcrumbs, setSelectedHeader } if (error) return ; return ( - - - - - - - - - - + + + + } + > + + + + + + + + + + + ); } diff --git a/client/src/pages/tech/tech.page.component.jsx b/client/src/pages/tech/tech.page.component.jsx index 549211c20..f2e12cc1e 100644 --- a/client/src/pages/tech/tech.page.component.jsx +++ b/client/src/pages/tech/tech.page.component.jsx @@ -1,4 +1,4 @@ -import { FloatButton, Layout } from "antd"; +import { Card, FloatButton, Layout } from "antd"; import React, { lazy, Suspense, useEffect } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; @@ -14,6 +14,7 @@ import UpdateAlert from "../../components/update-alert/update-alert.component"; import { selectTechnician } from "../../redux/tech/tech.selectors"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; import "./tech.page.styles.scss"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component.jsx"; const TimeTicketModalContainer = lazy(() => import("../../components/time-ticket-modal/time-ticket-modal.container")); const EmailOverlayContainer = lazy(() => import("../../components/email-overlay/email-overlay.container.jsx")); @@ -83,11 +84,11 @@ export function TechPage({ technician }) { } > + + } > diff --git a/client/src/pages/temporary-docs/temporary-docs.container.jsx b/client/src/pages/temporary-docs/temporary-docs.container.jsx index 906ff3e42..08179c656 100644 --- a/client/src/pages/temporary-docs/temporary-docs.container.jsx +++ b/client/src/pages/temporary-docs/temporary-docs.container.jsx @@ -8,6 +8,8 @@ import { selectBodyshop } from "../../redux/user/user.selectors"; import TemporaryDocsComponent from "./temporary-docs.component"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -40,10 +42,10 @@ export function TempDocumentsContainer({ setBreadcrumbs, setSelectedHeader }) { return ( + + } > diff --git a/client/src/pages/time-tickets/time-tickets.container.jsx b/client/src/pages/time-tickets/time-tickets.container.jsx index 28bda495d..e137509ee 100644 --- a/client/src/pages/time-tickets/time-tickets.container.jsx +++ b/client/src/pages/time-tickets/time-tickets.container.jsx @@ -1,5 +1,5 @@ import { useQuery } from "@apollo/client"; -import { Col, Row, Space } from "antd"; +import { Card, Col, Row, Space } from "antd"; import dayjs from "../../utils/day"; import React, { useEffect } from "react"; import { useTranslation } from "react-i18next"; @@ -20,6 +20,7 @@ import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wr import InstanceRenderManager from "../../utils/instanceRenderMgr"; import { useSplitTreatments } from "@splitsoftware/splitio-react"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -75,10 +76,10 @@ export function TimeTicketsContainer({ bodyshop, setBreadcrumbs, setSelectedHead return ( + + } > diff --git a/client/src/pages/tt-approvals/tt-approvals.page.container.jsx b/client/src/pages/tt-approvals/tt-approvals.page.container.jsx index 53a78b704..feab5457f 100644 --- a/client/src/pages/tt-approvals/tt-approvals.page.container.jsx +++ b/client/src/pages/tt-approvals/tt-approvals.page.container.jsx @@ -8,6 +8,8 @@ import { setBreadcrumbs, setSelectedHeader } from "../../redux/application/appli import { selectBodyshop } from "../../redux/user/user.selectors"; import FeatureWrapperComponent from "../../components/feature-wrapper/feature-wrapper.component"; import InstanceRenderManager from "../../utils/instanceRenderMgr"; +import { Card } from "antd"; +import UpsellComponent, { upsellEnum } from "../../components/upsell/upsell.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop @@ -40,10 +42,10 @@ export function TtApprovalsPage({ setBreadcrumbs, setSelectedHeader }) { return ( + + } > diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 209925304..c9d4610c9 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -3487,6 +3487,20 @@ "learnmore": "Learn More" }, "messages": { + "accounting": { + "payables": { + "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", + "title": "Eliminate double data entry" + }, + "payments": { + "subtitle": "Effortlessly send your bills and payables to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", + "title": "Eliminate double data entry" + }, + "receivables": { + "subtitle": "Effortlessly send your invoices to QuickBooks Online or QuickBooks Desktop eliminating the need for duplicate data entry.", + "title": "Eliminate double data entry" + } + }, "audit": { "general": { "subtitle": "Know exactly what happened and when through the entire repair process.", @@ -3503,6 +3517,30 @@ "title": "Boost your profits by taking control of costs!" } }, + "checklist": { + "general": { + "subtitle": "Standardize your intake and delivery with digitized checklists and SOPs.", + "title": "Done right, the first time." + } + }, + "courtesycars": { + "general": { + "subtitle": "Keep track of vehicles and contracts for your courtesy cars, all seamlessly synchronized with your Jobs.", + "title": "Manage your fleet with ease" + } + }, + "csi": { + "general": { + "subtitle": "With our integrated CSI module, send follow up surveys to your customers to see how well you did.", + "title": "See what your customers have to say" + } + }, + "dashboard": { + "general": { + "subtitle": "Make data based decisions and take control of your business using our real-time dashboard.", + "title": "Realtime Insight & Analytics" + } + }, "lifecycle": { "general": { "subtitle": "Job life cycles tell you exactly how long the job stayed in each stage of the repair process to identify bottle necks and inefficiencies.", @@ -3519,7 +3557,19 @@ "title": "Accelerate repair documentation with Mobile" } }, - "scheduling": { + "payments": { + "general": { + "subtitle": "Manage outstanding balances and collect payments by credit card from your customers.", + "title": "Integrated Accounts Receivable & Payments" + } + }, + "scoreboard": { + "general": { + "subtitle": "Understand hours produced and sold to facilitate employee incentive programs.", + "title": "Give credit where credit is due" + } + }, + "smartscheduling": { "datepicker": { "subtitle": "Smart Scsheduling gives you the best dates for a vehicle to come in based on your current and predicted production load.", "title": "When's the best time for this job to arrive?" @@ -3533,6 +3583,12 @@ "title": "Cars come and cars go." } }, + "techconsole": { + "general": { + "subtitle": "The technician's console allows technicians to see job information, media, documents and keep track of their time.", + "title": "Empower your Technicians" + } + }, "timetickets": { "allocations": { "subtitle": "Ensure your technicians are paid out exactly what they are owed - not a penny less, not a penny more.", @@ -3542,6 +3598,12 @@ "subtitle": "Track your technicians time with precision, giving you insight to repair progress and labor efficiency.", "title": "Who did what and for how long?" } + }, + "visualboard": { + "general": { + "subtitle": "The Visual Production Board makes it easier than ever before to manage your work in progress.", + "title": "A whole new kind of production board" + } } } }, diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 929a9c8a8..e1686f974 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -3487,6 +3487,20 @@ "learnmore": "" }, "messages": { + "accounting": { + "payables": { + "subtitle": "", + "title": "" + }, + "payments": { + "subtitle": "", + "title": "" + }, + "receivables": { + "subtitle": "", + "title": "" + } + }, "audit": { "general": { "subtitle": "", @@ -3503,6 +3517,30 @@ "title": "" } }, + "checklist": { + "general": { + "subtitle": "", + "title": "" + } + }, + "courtesycars": { + "general": { + "subtitle": "", + "title": "" + } + }, + "csi": { + "general": { + "subtitle": "", + "title": "" + } + }, + "dashboard": { + "general": { + "subtitle": "", + "title": "" + } + }, "lifecycle": { "general": { "subtitle": "", @@ -3519,7 +3557,19 @@ "title": "" } }, - "scheduling": { + "payments": { + "general": { + "subtitle": "", + "title": "" + } + }, + "scoreboard": { + "general": { + "subtitle": "", + "title": "" + } + }, + "smartscheduling": { "datepicker": { "subtitle": "", "title": "" @@ -3533,6 +3583,12 @@ "title": "" } }, + "techconsole": { + "general": { + "subtitle": "", + "title": "" + } + }, "timetickets": { "allocations": { "subtitle": "", @@ -3542,6 +3598,12 @@ "subtitle": "", "title": "" } + }, + "visualboard": { + "general": { + "subtitle": "", + "title": "" + } } } }, diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 4a8e1307b..d4114eaa5 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -3487,6 +3487,20 @@ "learnmore": "" }, "messages": { + "accounting": { + "payables": { + "subtitle": "", + "title": "" + }, + "payments": { + "subtitle": "", + "title": "" + }, + "receivables": { + "subtitle": "", + "title": "" + } + }, "audit": { "general": { "subtitle": "", @@ -3503,6 +3517,30 @@ "title": "" } }, + "checklist": { + "general": { + "subtitle": "", + "title": "" + } + }, + "courtesycars": { + "general": { + "subtitle": "", + "title": "" + } + }, + "csi": { + "general": { + "subtitle": "", + "title": "" + } + }, + "dashboard": { + "general": { + "subtitle": "", + "title": "" + } + }, "lifecycle": { "general": { "subtitle": "", @@ -3519,7 +3557,19 @@ "title": "" } }, - "scheduling": { + "payments": { + "general": { + "subtitle": "", + "title": "" + } + }, + "scoreboard": { + "general": { + "subtitle": "", + "title": "" + } + }, + "smartscheduling": { "datepicker": { "subtitle": "", "title": "" @@ -3533,6 +3583,12 @@ "title": "" } }, + "techconsole": { + "general": { + "subtitle": "", + "title": "" + } + }, "timetickets": { "allocations": { "subtitle": "", @@ -3542,6 +3598,12 @@ "subtitle": "", "title": "" } + }, + "visualboard": { + "general": { + "subtitle": "", + "title": "" + } } } },