diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index 1b11839b1..da72360dc 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -9117,6 +9117,27 @@ + + enterinvoices + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + home false @@ -10803,6 +10824,368 @@ + + bc + + + availablejobs + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + contracts + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + contracts-create + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + contracts-detail + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + courtesycars + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + courtesycars-detail + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + courtesycars-new + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + jobs + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + jobs-active + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + jobs-detail + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + jobs-new + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + owner-detail + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + owners + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + schedule + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + vehicle-details + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + vehicles + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + contracts + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + contracts-create false @@ -10845,6 +11228,27 @@ + + courtesycars + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + courtesycars-create false @@ -11034,6 +11438,27 @@ + + owners-detail + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + profile false diff --git a/client/src/components/breadcrumbs/breadcrumbs.component.jsx b/client/src/components/breadcrumbs/breadcrumbs.component.jsx new file mode 100644 index 000000000..62ebb2b5a --- /dev/null +++ b/client/src/components/breadcrumbs/breadcrumbs.component.jsx @@ -0,0 +1,28 @@ +import React from "react"; +import { Breadcrumb } from "antd"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBreadcrumbs } from "../../redux/application/application.selectors"; +import { Link } from "react-router-dom"; + +const mapStateToProps = createStructuredSelector({ + breadcrumbs: selectBreadcrumbs, +}); + +export function BreadCrumbs({ breadcrumbs }) { + return ( + + Home + {breadcrumbs.map((item) => + item.link ? ( + + {item.label} + + ) : ( + {item.label} + ) + )} + + ); +} +export default connect(mapStateToProps, null)(BreadCrumbs); diff --git a/client/src/components/header/header.component.jsx b/client/src/components/header/header.component.jsx index bf8bca271..f39ced6a1 100644 --- a/client/src/components/header/header.component.jsx +++ b/client/src/components/header/header.component.jsx @@ -15,14 +15,26 @@ import { Link } from "react-router-dom"; import UserImage from "../../assets/User.svg"; import ManageSignInButton from "../manage-sign-in-button/manage-sign-in-button.component"; -export default ({ +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { setModalContext } from "../../redux/modals/modals.actions"; +const mapStateToProps = createStructuredSelector({ + //currentUser: selectCurrentUser +}); +const mapDispatchToProps = (dispatch) => ({ + setInvoiceEnterContext: (context) => + dispatch(setModalContext({ context: context, modal: "invoiceEnter" })), +}); + +function Header({ landingHeader, selectedNavItem, logo, handleMenuClick, currentUser, signOutStart, -}) => { + setInvoiceEnterContext, +}) { const { t } = useTranslation(); //TODO Add @@ -175,6 +187,17 @@ export default ({ } > + { + setInvoiceEnterContext({ + actions: {}, + context: {}, + }); + }} + > + {t("menus.header.enterinvoices")} + {t("menus.header.invoices")} @@ -238,4 +261,6 @@ export default ({ ); -}; +} + +export default connect(mapStateToProps, mapDispatchToProps)(Header); diff --git a/client/src/components/job-totals-table/job-totals-table.component.jsx b/client/src/components/job-totals-table/job-totals-table.component.jsx index 35a38fd40..17e189d6f 100644 --- a/client/src/components/job-totals-table/job-totals-table.component.jsx +++ b/client/src/components/job-totals-table/job-totals-table.component.jsx @@ -1,8 +1,7 @@ +import { Col, List, Row } from "antd"; import React from "react"; -import { List, Row, Col } from "antd"; -import { useTranslation } from "react-i18next"; export default function JobsTotalsTableComponent({ totals }) { - const { t } = useTranslation(); + //const { t } = useTranslation(); if (!!!totals) return null; 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 6a4163334..20d439f9f 100644 --- a/client/src/pages/contract-create/contract-create.page.container.jsx +++ b/client/src/pages/contract-create/contract-create.page.container.jsx @@ -9,11 +9,16 @@ import { useTranslation } from "react-i18next"; import { INSERT_NEW_CONTRACT } from "../../graphql/cccontracts.queries"; import { useMutation } from "@apollo/react-hooks"; import { useHistory, useLocation } from "react-router-dom"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; + const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop + bodyshop: selectBodyshop, +}); +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), }); -export function ContractCreatePageContainer({ bodyshop }) { +export function ContractCreatePageContainer({ bodyshop, setBreadcrumbs }) { const [form] = Form.useForm(); const { t } = useTranslation(); const history = useHistory(); @@ -24,45 +29,56 @@ export function ContractCreatePageContainer({ bodyshop }) { ); const [insertContract] = useMutation(INSERT_NEW_CONTRACT); - console.log("location", location); + console.log("test"); - const handleFinish = values => { + const handleFinish = (values) => { if (!!selectedCarState[0] && !!selectedJobState[0]) { insertContract({ variables: { contract: { ...values, courtesycarid: selectedCarState[0], - jobid: selectedJobState[0] - } - } + jobid: selectedJobState[0], + }, + }, }) - .then(response => { + .then((response) => { notification["success"]({ - message: t("contracts.successes.saved") + message: t("contracts.successes.saved"), }); history.push( `/manage/courtesycars/contracts/${response.data.insert_cccontracts.returning[0].id}` ); }) - .catch(error => + .catch((error) => notification["error"]({ message: t("contracts.errors.saving", { - error: JSON.stringify(error) - }) + error: JSON.stringify(error), + }), }) ); } else { notification["error"]({ - message: t("contracts.errors.selectjobandcar") + message: t("contracts.errors.selectjobandcar"), }); } }; useEffect(() => { document.title = t("titles.contracts-create"); - }, [t]); + setBreadcrumbs([ + { link: "/manage/courtesycars", label: t("titles.bc.courtesycars") }, + { + link: "/manage/courtesycars/contracts", + label: t("titles.bc.contracts"), + }, + { + link: "/manage/courtesycars/contracts/new", + label: t("titles.bc.contracts-create"), + }, + ]); + }, [t, setBreadcrumbs]); return (
@@ -73,4 +89,7 @@ export function ContractCreatePageContainer({ bodyshop }) {
); } -export default connect(mapStateToProps, null)(ContractCreatePageContainer); +export default connect( + mapStateToProps, + mapDispatchToProps +)(ContractCreatePageContainer); 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 fb8278739..e996a1348 100644 --- a/client/src/pages/contract-detail/contract-detail.page.container.jsx +++ b/client/src/pages/contract-detail/contract-detail.page.container.jsx @@ -3,23 +3,29 @@ import { Form, notification } from "antd"; import moment from "moment"; import React, { useEffect } from "react"; import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; import { useParams } from "react-router-dom"; import AlertComponent from "../../components/alert/alert.component"; +import CourtesyCarReturnModalContainer from "../../components/courtesy-car-return-modal/courtesy-car-return-modal.container"; import { QUERY_CONTRACT_BY_PK, - UPDATE_CONTRACT + UPDATE_CONTRACT, } from "../../graphql/cccontracts.queries"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; import ContractDetailPageComponent from "./contract-detail.page.component"; -import CourtesyCarReturnModalContainer from "../../components/courtesy-car-return-modal/courtesy-car-return-modal.container"; -export default function ContractDetailPageContainer() { +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function ContractDetailPageContainer({ setBreadcrumbs }) { const { t } = useTranslation(); const [updateContract] = useMutation(UPDATE_CONTRACT); const [form] = Form.useForm(); const { contractId } = useParams(); const { loading, error, data, refetch } = useQuery(QUERY_CONTRACT_BY_PK, { - variables: { id: contractId } + variables: { id: contractId }, }); useEffect(() => { @@ -28,20 +34,34 @@ export default function ContractDetailPageContainer() { : error ? t("titles.app") : t("titles.contracts-detail", { - id: (data && data.cccontracts_by_pk.agreementnumber) || "" + id: (data && data.cccontracts_by_pk.agreementnumber) || "", }); - }, [t, data, error, loading]); - const handleFinish = values => { + setBreadcrumbs([ + { link: "/manage/courtesycars", label: t("titles.bc.courtesycars") }, + { + link: "/manage/courtesycars/contracts", + label: t("titles.bc.contracts"), + }, + { + link: "/manage/courtesycars/contracts/new", + label: t("titles.bc.contracts-detail", { + number: data.cccontracts_by_pk.agreementnumber || "", + }), + }, + ]); + }, [t, data, error, loading, setBreadcrumbs]); + + const handleFinish = (values) => { updateContract({ - variables: { cccontract: { ...values }, contractId: contractId } + variables: { cccontract: { ...values }, contractId: contractId }, }) - .then(response => { + .then((response) => { notification["success"]({ message: t("contracts.successes.saved") }); }) - .catch(error => + .catch((error) => notification["error"]({ - message: t("contracts.errors.saving", { error: error }) + message: t("contracts.errors.saving", { error: error }), }) ); }; @@ -76,7 +96,7 @@ export default function ContractDetailPageContainer() { : null, driver_dob: data.cccontracts_by_pk.driver_dob ? moment(data.cccontracts_by_pk.driver_dob) - : null + : null, } : {} } @@ -91,3 +111,4 @@ export default function ContractDetailPageContainer() { ); } +export default connect(null, mapDispatchToProps)(ContractDetailPageContainer); diff --git a/client/src/pages/contracts/contracts.page.container.jsx b/client/src/pages/contracts/contracts.page.container.jsx index 08fc143ff..9de40784d 100644 --- a/client/src/pages/contracts/contracts.page.container.jsx +++ b/client/src/pages/contracts/contracts.page.container.jsx @@ -1,11 +1,29 @@ -import React from "react"; -import ContractsPageComponent from "./contracts.page.component"; import { useQuery } from "@apollo/react-hooks"; -import { QUERY_ACTIVE_CONTRACTS } from "../../graphql/cccontracts.queries"; +import React, { useEffect } from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; import AlertComponent from "../../components/alert/alert.component"; +import { QUERY_ACTIVE_CONTRACTS } from "../../graphql/cccontracts.queries"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; +import ContractsPageComponent from "./contracts.page.component"; +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); -export default function ContractsPageContainer() { +export function ContractsPageContainer({ setBreadcrumbs }) { const { loading, error, data } = useQuery(QUERY_ACTIVE_CONTRACTS); + const { t } = useTranslation(); + useEffect(() => { + document.title = t("titles.contracts"); + + setBreadcrumbs([ + { link: "/manage/courtesycars", label: t("titles.bc.courtesycars") }, + { + link: "/manage/courtesycars/contracts", + label: t("titles.bc.contracts"), + }, + ]); + }, [setBreadcrumbs, t]); if (error) return ; return ( @@ -17,3 +35,4 @@ export default function ContractsPageContainer() { ); } +export default connect(null, mapDispatchToProps)(ContractsPageContainer); 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 cbcd4dd45..a9bd1bdd7 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 @@ -8,33 +8,43 @@ import { INSERT_NEW_COURTESY_CAR } from "../../graphql/courtesy-car.queries"; import { selectBodyshop } from "../../redux/user/user.selectors"; import CourtesyCarCreateComponent from "./courtesy-car-create.page.component"; import { useHistory } from "react-router-dom"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop + bodyshop: selectBodyshop, }); - -export function CourtesyCarCreateContainer({ bodyshop }) { +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); +export function CourtesyCarCreateContainer({ bodyshop, setBreadcrumbs }) { const [form] = Form.useForm(); const [insertCourtesyCar] = useMutation(INSERT_NEW_COURTESY_CAR); const { t } = useTranslation(); const history = useHistory(); - const handleFinish = values => { + const handleFinish = (values) => { insertCourtesyCar({ - variables: { courtesycar: { ...values, bodyshopid: bodyshop.id } } + variables: { courtesycar: { ...values, bodyshopid: bodyshop.id } }, }) - .then(response => { + .then((response) => { notification["success"]({ message: t("courtesycars.successes.saved") }); history.push( `/manage/courtesycars/${response.data.insert_courtesycars.returning[0].id}` ); }) - .catch(error => console.log("error", error)); + .catch((error) => console.log("error", error)); }; useEffect(() => { document.title = t("titles.courtesycars-create"); - }, [t]); + setBreadcrumbs([ + { link: "/manage/courtesycars", label: t("titles.bc.courtesycars") }, + { + link: "/manage/courtesycars/new", + label: t("titles.bc.courtesycars-new"), + }, + ]); + }, [t, setBreadcrumbs]); return (
@@ -42,4 +52,7 @@ export function CourtesyCarCreateContainer({ bodyshop }) {
); } -export default connect(mapStateToProps, null)(CourtesyCarCreateContainer); +export default connect( + mapStateToProps, + mapDispatchToProps +)(CourtesyCarCreateContainer); diff --git a/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx b/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx index 8fd114dde..a595be0a6 100644 --- a/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx +++ b/client/src/pages/courtesy-car-detail/courtesy-car-detail.page.container.jsx @@ -3,19 +3,24 @@ import { Form, notification } from "antd"; import moment from "moment"; import React, { useEffect } from "react"; import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; import { useParams } from "react-router-dom"; import AlertComponent from "../../components/alert/alert.component"; import { QUERY_CC_BY_PK, UPDATE_CC } from "../../graphql/courtesy-car.queries"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; import CourtesyCarDetailPageComponent from "./courtesy-car-detail.page.component"; -export default function CourtesyCarDetailPageContainer() { +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); +export function CourtesyCarDetailPageContainer({ setBreadcrumbs }) { const { t } = useTranslation(); const [insertCourtesyCar] = useMutation(UPDATE_CC); const [form] = Form.useForm(); const { ccId } = useParams(); const { loading, error, data } = useQuery(QUERY_CC_BY_PK, { - variables: { id: ccId } + variables: { id: ccId }, }); useEffect(() => { @@ -24,20 +29,31 @@ export default function CourtesyCarDetailPageContainer() { : error ? t("titles.app") : t("titles.courtesycars-detail", { - id: (data && data.courtesycars_by_pk.vin) || "" + id: (data && data.courtesycars_by_pk.fleet_number) || "", }); - }, [t, data, error, loading]); + setBreadcrumbs([ + { link: "/manage/courtesycars", label: t("titles.bc.courtesycars") }, + { + link: `/manage/courtesycars/${ + (data && data.courtesycars_by_pk.id) || "" + }`, + label: t("titles.bc.courtesycars-detail", { + number: (data && data.courtesycars_by_pk.fleetnumber) || "", + }), + }, + ]); + }, [t, data, error, loading, setBreadcrumbs]); - const handleFinish = values => { + const handleFinish = (values) => { insertCourtesyCar({ - variables: { cc: { ...values }, ccId: ccId } + variables: { cc: { ...values }, ccId: ccId }, }) - .then(response => { + .then((response) => { notification["success"]({ message: t("courtesycars.successes.saved") }); }) - .catch(error => + .catch((error) => notification["error"]({ - message: t("courtesycars.errors.saving", { error: error }) + message: t("courtesycars.errors.saving", { error: error }), }) ); }; @@ -76,7 +92,7 @@ export default function CourtesyCarDetailPageContainer() { : null, insuranceexpires: data.courtesycars_by_pk.insuranceexpires ? moment(data.courtesycars_by_pk.insuranceexpires) - : null + : null, } : {} } @@ -87,3 +103,7 @@ export default function CourtesyCarDetailPageContainer() { ); } +export default connect( + null, + mapDispatchToProps +)(CourtesyCarDetailPageContainer); 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 3aac89538..cc464629a 100644 --- a/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx +++ b/client/src/pages/courtesy-cars/courtesy-cars.page.container.jsx @@ -1,12 +1,26 @@ -import React from "react"; +import React, { useEffect } from "react"; import CourtesyCarsPageComponent from "./courtesy-cars.page.component"; import { useQuery } from "@apollo/react-hooks"; import AlertComponent from "../../components/alert/alert.component"; import { QUERY_ALL_CC } from "../../graphql/courtesy-car.queries"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; +import { connect } from "react-redux"; +import { useTranslation } from "react-i18next"; -export default function CourtesyCarsPageContainer() { +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function CourtesyCarsPageContainer({ setBreadcrumbs }) { const { loading, error, data } = useQuery(QUERY_ALL_CC); + const { t } = useTranslation(); + useEffect(() => { + document.title = t("titles.courtesycars"); + setBreadcrumbs([ + { link: "/manage/courtesycars", label: t("titles.bc.courtesycars") }, + ]); + }, [setBreadcrumbs, t]); if (error) return ; return ( ); } + +export default connect(null, mapDispatchToProps)(CourtesyCarsPageContainer); diff --git a/client/src/pages/jobs-available/jobs-available.page.container.jsx b/client/src/pages/jobs-available/jobs-available.page.container.jsx index 7955d331a..56aafd8ae 100644 --- a/client/src/pages/jobs-available/jobs-available.page.container.jsx +++ b/client/src/pages/jobs-available/jobs-available.page.container.jsx @@ -2,12 +2,18 @@ import React, { useEffect } from "react"; import { useMutation, useLazyQuery } from "@apollo/react-hooks"; import { DELETE_AVAILABLE_JOB, - QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK + QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK, } from "../../graphql/available-jobs.queries"; import JobsAvailablePageComponent from "./jobs-available.page.component"; import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; -export default function JobsAvailablePageContainer() { +import { setBreadcrumbs } from "../../redux/application/application.actions"; +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function JobsAvailablePageContainer({ setBreadcrumbs }) { const [deleteJob] = useMutation(DELETE_AVAILABLE_JOB); const { t } = useTranslation(); @@ -15,7 +21,10 @@ export default function JobsAvailablePageContainer() { useEffect(() => { document.title = t("titles.jobsavailable"); - }, [t]); + setBreadcrumbs([ + { link: "/manage/available", label: t("titles.bc.availablejobs") }, + ]); + }, [t, setBreadcrumbs]); return (
@@ -26,3 +35,4 @@ export default function JobsAvailablePageContainer() {
); } +export default connect(null, mapDispatchToProps)(JobsAvailablePageContainer); diff --git a/client/src/pages/jobs-create/jobs-create.container.jsx b/client/src/pages/jobs-create/jobs-create.container.jsx index 7132fa291..7aa4a87b2 100644 --- a/client/src/pages/jobs-create/jobs-create.container.jsx +++ b/client/src/pages/jobs-create/jobs-create.container.jsx @@ -9,13 +9,15 @@ import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { selectBodyshop } from "../../redux/user/user.selectors"; import { useTranslation } from "react-i18next"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; const mapStateToProps = createStructuredSelector({ - bodyshop: selectBodyshop + bodyshop: selectBodyshop, }); -export default connect(mapStateToProps, null)(JobsCreateContainer); - -function JobsCreateContainer({ bodyshop }) { +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); +function JobsCreateContainer({ bodyshop, setBreadcrumbs }) { const { t } = useTranslation(); const contextState = useState({ vehicle: { new: false, search: "", selectedid: null, vehicleObj: null }, @@ -24,7 +26,7 @@ function JobsCreateContainer({ bodyshop }) { created: false, error: null, newJobId: null, - newJobEstNum: null + newJobEstNum: null, }); const [form] = Form.useForm(); const [state, setState] = contextState; @@ -36,49 +38,56 @@ function JobsCreateContainer({ bodyshop }) { useEffect(() => { if (!!state.owner.selectedid) { loadOwner({ - variables: { id: state.owner.selectedid } + variables: { id: state.owner.selectedid }, }); } }, [state.owner.selectedid, loadOwner]); useEffect(() => { document.title = t("titles.jobs-create"); - }, [t]); + setBreadcrumbs([ + { link: "/manage/available", label: t("titles.bc.availablejobs") }, + { + link: "/manage/jobs/new", + label: t("titles.bc.jobs-new"), + }, + ]); + }, [t, setBreadcrumbs]); - const runInsertJob = job => { + const runInsertJob = (job) => { insertJob({ variables: { job: job } }) - .then(resp => { + .then((resp) => { setState({ ...state, created: true, error: null, newJobId: resp.data.insert_jobs.returning[0].id, - newJobEstNum: resp.data.insert_jobs.returning[0].est_number + newJobEstNum: resp.data.insert_jobs.returning[0].est_number, }); }) - .catch(error => { + .catch((error) => { notification["error"]({ - message: t("jobs.errors.creating", { error: error }) + message: t("jobs.errors.creating", { error: error }), }); setState({ ...state, error: error }); }); }; - const handleFinish = values => { + const handleFinish = (values) => { let job = Object.assign( {}, values, { vehicle: state.vehicle.selectedid ? null : values.vehicle, - vehicleid: state.vehicle.selectedid || null + vehicleid: state.vehicle.selectedid || null, }, { owner: state.owner.selectedid ? null : values.owner, - ownerid: state.owner.selectedid || null + ownerid: state.owner.selectedid || null, }, { status: bodyshop.md_ro_statuses.default_imported || "Open*", //Pull from redux store. - shopid: bodyshop.id + shopid: bodyshop.id, } ); //TODO Logic to ensure the owner is actually fetched. @@ -128,3 +137,7 @@ function JobsCreateContainer({ bodyshop }) { ); } +export default connect( + mapStateToProps, + mapDispatchToProps +)(JobsCreateContainer); diff --git a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx index ef4740c73..aa8ebb72a 100644 --- a/client/src/pages/jobs-detail/jobs-detail.page.component.jsx +++ b/client/src/pages/jobs-detail/jobs-detail.page.component.jsx @@ -3,7 +3,7 @@ import Icon, { CalendarFilled, DollarCircleOutlined, FileImageFilled, - ToolFilled + ToolFilled, } from "@ant-design/icons"; import { Form, notification, Tabs } from "antd"; import moment from "moment"; @@ -14,7 +14,7 @@ import { FaHistory, FaInfo, FaRegStickyNote, - FaShieldAlt + FaShieldAlt, } from "react-icons/fa"; import { useHistory, useLocation } from "react-router-dom"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; @@ -57,9 +57,7 @@ const JobLineUpsertModalContainer = lazy(() => "../../components/job-lines-upsert-modal/job-lines-upsert-modal.container" ) ); -const EnterInvoiceModalContainer = lazy(() => - import("../../components/invoice-enter-modal/invoice-enter-modal.container") -); + const JobsDetailPliContainer = lazy(() => import("../../components/jobs-detail-pli/jobs-detail-pli.container") ); @@ -73,7 +71,7 @@ export default function JobsDetailPage({ mutationConvertJob, handleSubmit, refetch, - updateJobStatus + updateJobStatus, }) { const { t } = useTranslation(); const [form] = Form.useForm(); @@ -83,22 +81,22 @@ export default function JobsDetailPage({ const formItemLayout = { labelCol: { xs: { span: 12 }, - sm: { span: 5 } + sm: { span: 5 }, }, wrapperCol: { xs: { span: 24 }, - sm: { span: 12 } - } + sm: { span: 12 }, + }, }; - const handleFinish = values => { + const handleFinish = (values) => { mutationUpdateJob({ - variables: { jobId: job.id, job: values } - }).then(r => { + variables: { jobId: job.id, job: values }, + }).then((r) => { notification["success"]({ - message: t("jobs.successes.savetitle") + message: t("jobs.successes.savetitle"), }); - refetch().then(r => form.resetFields()); + refetch().then((r) => form.resetFields()); }); }; @@ -108,7 +106,6 @@ export default function JobsDetailPage({ > -
history.push({ search: `?tab=${key}` })} + onChange={(key) => history.push({ search: `?tab=${key}` })} > ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +function JobsDetailPageContainer({ match, setBreadcrumbs }) { const { jobId } = match.params; const { t } = useTranslation(); const { loading, error, data, refetch } = useQuery(GET_JOB_BY_PK, { variables: { id: jobId }, - fetchPolicy: "network-only" + fetchPolicy: "network-only", }); const [mutationUpdateJob] = useMutation(UPDATE_JOB); const [mutationConvertJob] = useMutation(CONVERT_JOB_TO_RO); const [mutationUpdateJobstatus] = useMutation(UPDATE_JOB_STATUS); - const updateJobStatus = status => { + const updateJobStatus = (status) => { mutationUpdateJobstatus({ - variables: { jobId: jobId, status: status } + variables: { jobId: jobId, status: status }, }) - .then(r => { + .then((r) => { notification["success"]({ message: t("jobs.successes.save") }); refetch(); }) - .catch(error => { + .catch((error) => { notification[error]({ message: t("jobs.errors.saving") }); }); }; @@ -40,9 +51,23 @@ function JobsDetailPageContainer({ match }) { : t("titles.jobsdetail", { ro_number: data.jobs_by_pk.converted ? data.jobs_by_pk.ro_number - : `EST ${data.jobs_by_pk.est_number}` + : `EST ${data.jobs_by_pk.est_number}`, }); - }, [loading, data, t, error]); + setBreadcrumbs([ + { link: "/manage/jobs", label: t("titles.bc.jobs") }, + { + link: `/manage/jobs/${jobId}`, + label: t("titles.bc.jobs-detail", { + number: + (data && + (data.jobs_by_pk.converted + ? data && data.jobs_by_pk.ro_number + : `EST ${data.jobs_by_pk.est_number}`)) || + "", + }), + }, + ]); + }, [loading, data, t, error, setBreadcrumbs, jobId]); if (loading) return ; if (error) return ; @@ -59,4 +84,4 @@ function JobsDetailPageContainer({ match }) { ); } -export default JobsDetailPageContainer; +export default connect(null, mapDispatchToProps)(JobsDetailPageContainer); diff --git a/client/src/pages/jobs/jobs.page.jsx b/client/src/pages/jobs/jobs.page.jsx index 1ac088bc2..fdd2988fb 100644 --- a/client/src/pages/jobs/jobs.page.jsx +++ b/client/src/pages/jobs/jobs.page.jsx @@ -11,11 +11,17 @@ import JobsList from "../../components/jobs-list/jobs-list.component"; import { QUERY_ALL_ACTIVE_JOBS } from "../../graphql/jobs.queries"; import { selectBodyshop } from "../../redux/user/user.selectors"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; + const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, }); -export function JobsPage({ location, bodyshop }) { +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function JobsPage({ location, bodyshop, setBreadcrumbs }) { const { loading, error, data, refetch } = useQuery(QUERY_ALL_ACTIVE_JOBS, { variables: { statuses: bodyshop.md_ro_statuses.open_statuses || ["Open"], @@ -25,7 +31,8 @@ export function JobsPage({ location, bodyshop }) { useEffect(() => { document.title = t("titles.jobs"); - }, [t]); + setBreadcrumbs([{ link: "/manage/jobs", label: t("titles.bc.jobs-active") }]); + }, [t, setBreadcrumbs]); const search = queryString.parse(location.search); const searchTextState = useState(""); @@ -78,4 +85,4 @@ export function JobsPage({ location, bodyshop }) { ); } -export default connect(mapStateToProps, null)(JobsPage); +export default connect(mapStateToProps, mapDispatchToProps)(JobsPage); diff --git a/client/src/pages/manage/manage.page.component.jsx b/client/src/pages/manage/manage.page.component.jsx index dc34419a4..169b5d733 100644 --- a/client/src/pages/manage/manage.page.component.jsx +++ b/client/src/pages/manage/manage.page.component.jsx @@ -8,6 +8,7 @@ import FooterComponent from "../../components/footer/footer.component"; import HeaderContainer from "../../components/header/header.container"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import "./manage.page.styles.scss"; +import BreadCrumbs from "../../components/breadcrumbs/breadcrumbs.component"; const ManageRootPage = lazy(() => import("../manage-root/manage-root.page.container") @@ -70,7 +71,9 @@ const InvoicesListPage = lazy(() => const InvoiceDetailPage = lazy(() => import("../invoice-detail/invoice-detail.page.container") ); - +const EnterInvoiceModalContainer = lazy(() => + import("../../components/invoice-enter-modal/invoice-enter-modal.container") +); const { Header, Content, Footer } = Layout; export default function Manage({ match }) { @@ -96,6 +99,8 @@ export default function Manage({ match }) { } > + + diff --git a/client/src/pages/owners-detail/owners-detail.page.container.jsx b/client/src/pages/owners-detail/owners-detail.page.container.jsx index 5ab821033..042b7022f 100644 --- a/client/src/pages/owners-detail/owners-detail.page.container.jsx +++ b/client/src/pages/owners-detail/owners-detail.page.container.jsx @@ -1,19 +1,49 @@ -import React from "react"; +import React, { useEffect } from "react"; import OwnersDetailComponent from "./owners-detail.page.component"; import { useTranslation } from "react-i18next"; import { useQuery } from "@apollo/react-hooks"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import AlertComponent from "../../components/alert/alert.component"; import { QUERY_OWNER_BY_ID } from "../../graphql/owners.queries"; -export default function OwnersDetailContainer({ match }) { +import { connect } from "react-redux"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function OwnersDetailContainer({ match, setBreadcrumbs }) { const { ownerId } = match.params; const { t } = useTranslation(); const { loading, data, error, refetch } = useQuery(QUERY_OWNER_BY_ID, { variables: { id: ownerId }, - fetchPolicy: "network-only" + fetchPolicy: "network-only", }); + useEffect(() => { + document.title = t("titles.owners-detail", { + name: data + ? `${data.owners_by_pk.ownr_fn || ""} ${ + data.owners_by_pk.ownr_ln || "" + } ${data.owners_by_pk.ownr_co_nm || ""}` + : "", + }); + + setBreadcrumbs([ + { link: "/manage/owners", label: t("titles.bc.owners") }, + { + link: `/manage/owners/${ownerId}`, + label: t("titles.bc.owner-detail", { + name: data + ? `${data.owners_by_pk.ownr_fn || ""} ${ + data.owners_by_pk.ownr_ln || "" + } ${data.owners_by_pk.ownr_co_nm || ""}` + : "", + }), + }, + ]); + }, [setBreadcrumbs, t, data, ownerId]); + if (loading) return ; if (error) return ; @@ -26,3 +56,4 @@ export default function OwnersDetailContainer({ match }) { ); } +export default connect(null, mapDispatchToProps)(OwnersDetailContainer); diff --git a/client/src/pages/owners/owners.page.container.jsx b/client/src/pages/owners/owners.page.container.jsx index 172918110..760f8835f 100644 --- a/client/src/pages/owners/owners.page.container.jsx +++ b/client/src/pages/owners/owners.page.container.jsx @@ -1,12 +1,20 @@ import React, { useEffect } from "react"; import OwnersPageComponent from "./owners.page.component"; import { useTranslation } from "react-i18next"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; +import { connect } from "react-redux"; -export default function OwnersPageContainer() { +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function OwnersPageContainer({ setBreadcrumbs }) { const { t } = useTranslation(); useEffect(() => { document.title = t("titles.owners"); - }, [t]); + setBreadcrumbs([{ link: "/manage/owners", label: t("titles.bc.owners") }]); + }, [t, setBreadcrumbs]); return ; } +export default connect(null, mapDispatchToProps)(OwnersPageContainer); diff --git a/client/src/pages/schedule/schedule.page.container.jsx b/client/src/pages/schedule/schedule.page.container.jsx index 8a21042cd..8ab7ee04f 100644 --- a/client/src/pages/schedule/schedule.page.container.jsx +++ b/client/src/pages/schedule/schedule.page.container.jsx @@ -1,12 +1,22 @@ import React, { useEffect } from "react"; import SchedulePageComponent from "./schedule.page.component"; import { useTranslation } from "react-i18next"; -export default function SchedulePageContainer() { +import { connect } from "react-redux"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function SchedulePageContainer({ setBreadcrumbs }) { const { t } = useTranslation(); useEffect(() => { document.title = t("titles.schedule"); - }, [t]); + setBreadcrumbs([ + { link: "/manage/schedule", label: t("titles.bc.schedule") }, + ]); + }, [t, setBreadcrumbs]); return ; } +export default connect(null, mapDispatchToProps)(SchedulePageContainer); diff --git a/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx b/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx index ac634a941..07e2f6126 100644 --- a/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx +++ b/client/src/pages/vehicles-detail/vehicles-detail.page.container.jsx @@ -5,13 +5,19 @@ import { QUERY_VEHICLE_BY_ID } from "../../graphql/vehicles.queries"; import LoadingSpinner from "../../components/loading-spinner/loading-spinner.component"; import AlertComponent from "../../components/alert/alert.component"; import { useTranslation } from "react-i18next"; +import { setBreadcrumbs } from "../../redux/application/application.actions"; +import { connect } from "react-redux"; -export default function VehicleDetailContainer({ match }) { +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function VehicleDetailContainer({ match, setBreadcrumbs }) { const { vehId } = match.params; const { t } = useTranslation(); const { loading, data, error, refetch } = useQuery(QUERY_VEHICLE_BY_ID, { variables: { id: vehId }, - fetchPolicy: "network-only" + fetchPolicy: "network-only", }); useEffect(() => { @@ -19,9 +25,21 @@ export default function VehicleDetailContainer({ match }) { vehicle: data && data.vehicles_by_pk ? `${data.vehicles_by_pk.v_model_yr} ${data.vehicles_by_pk.v_make_desc} ${data.vehicles_by_pk.v_model_desc}` - : "" + : "", }); - }, [t, data]); + setBreadcrumbs([ + { link: "/manage/vehicles", label: t("titles.bc.vehicles") }, + { + link: `/manage/vehicles/${vehId}`, + label: t("titles.bc.vehicle-details", { + vehicle: + data && data.vehicles_by_pk + ? `${data.vehicles_by_pk.v_model_yr} ${data.vehicles_by_pk.v_make_desc} ${data.vehicles_by_pk.v_model_desc}` + : "", + }), + }, + ]); + }, [t, data, setBreadcrumbs, vehId]); if (loading) return ; if (error) return ; @@ -35,3 +53,4 @@ export default function VehicleDetailContainer({ match }) { ); } +export default connect(null, mapDispatchToProps)(VehicleDetailContainer); diff --git a/client/src/pages/vehicles/vehicles.page.container.jsx b/client/src/pages/vehicles/vehicles.page.container.jsx index 086998bde..7bf7cdd60 100644 --- a/client/src/pages/vehicles/vehicles.page.container.jsx +++ b/client/src/pages/vehicles/vehicles.page.container.jsx @@ -1,10 +1,23 @@ import React, { useEffect } from "react"; import VehiclesPageComponent from "./vehicles.page.component"; import { useTranslation } from "react-i18next"; -export default function VehiclesPageContainer() { +import { connect } from "react-redux"; + +import { setBreadcrumbs } from "../../redux/application/application.actions"; +const mapDispatchToProps = (dispatch) => ({ + setBreadcrumbs: (breadcrumbs) => dispatch(setBreadcrumbs(breadcrumbs)), +}); + +export function VehiclesPageContainer({ setBreadcrumbs }) { const { t } = useTranslation(); + useEffect(() => { document.title = t("titles.vehicles"); - }, [t]); + setBreadcrumbs([ + { link: "/manage/vehicles", label: t("titles.bc.vehicles") }, + ]); + }, [t, setBreadcrumbs]); + return ; } +export default connect(null, mapDispatchToProps)(VehiclesPageContainer); diff --git a/client/src/redux/application/application.actions.js b/client/src/redux/application/application.actions.js index 98bc8f6cf..a3649f769 100644 --- a/client/src/redux/application/application.actions.js +++ b/client/src/redux/application/application.actions.js @@ -1,10 +1,15 @@ import ApplicationActionTypes from "./application.types"; export const startLoading = () => ({ - type: ApplicationActionTypes.START_LOADING + type: ApplicationActionTypes.START_LOADING, }); -export const endLoading = options => ({ +export const endLoading = (options) => ({ type: ApplicationActionTypes.END_LOADING, - payload: options + payload: options, +}); + +export const setBreadcrumbs = (breadcrumbs) => ({ + type: ApplicationActionTypes.SET_BREAD_CRUMBS, + payload: breadcrumbs, }); diff --git a/client/src/redux/application/application.reducer.js b/client/src/redux/application/application.reducer.js index 603032589..9bb60326f 100644 --- a/client/src/redux/application/application.reducer.js +++ b/client/src/redux/application/application.reducer.js @@ -1,7 +1,8 @@ import ApplicationActionTypes from "./application.types"; const INITIAL_STATE = { - loading: false + loading: false, + breadcrumbs: [], }; const applicationReducer = (state = INITIAL_STATE, action) => { @@ -9,12 +10,17 @@ const applicationReducer = (state = INITIAL_STATE, action) => { case ApplicationActionTypes.START_LOADING: return { ...state, - loading: true + loading: true, }; case ApplicationActionTypes.END_LOADING: return { ...state, - loading: false + loading: false, + }; + case ApplicationActionTypes.SET_BREAD_CRUMBS: + return { + ...state, + breadcrumbs: action.payload, }; default: return state; diff --git a/client/src/redux/application/application.selectors.js b/client/src/redux/application/application.selectors.js index 8f19ef04c..2b931b789 100644 --- a/client/src/redux/application/application.selectors.js +++ b/client/src/redux/application/application.selectors.js @@ -1,8 +1,13 @@ import { createSelector } from "reselect"; -const selectApplication = state => state.application; +const selectApplication = (state) => state.application; export const selectLoading = createSelector( [selectApplication], - application => application.loading + (application) => application.loading +); + +export const selectBreadcrumbs = createSelector( + [selectApplication], + (application) => application.breadcrumbs ); diff --git a/client/src/redux/application/application.types.js b/client/src/redux/application/application.types.js index 8f58f01cf..520db6749 100644 --- a/client/src/redux/application/application.types.js +++ b/client/src/redux/application/application.types.js @@ -1,5 +1,6 @@ const ApplicationActionTypes = { START_LOADING: "START_LOADING", - END_LOADING: "END_LOADING" + END_LOADING: "END_LOADING", + SET_BREAD_CRUMBS: "SET_BREAD_CRUMBS", }; export default ApplicationActionTypes; diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index 0a21ba593..e71ab6c69 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -583,6 +583,7 @@ "courtesycars-contracts": "Contracts", "courtesycars-newcontract": "New Contract", "customers": "Customers", + "enterinvoices": "Enter Invoices", "home": "Home", "invoices": "Invoices", "jobs": "Jobs", @@ -710,17 +711,38 @@ }, "titles": { "app": "Bodyshop by ImEX Systems", + "bc": { + "availablejobs": "Available Jobs", + "contracts": "Contracts", + "contracts-create": "New Contract", + "contracts-detail": "Contract #{{number}}", + "courtesycars": "Courtesy Cars", + "courtesycars-detail": "Courtesy Car {{number}}", + "courtesycars-new": "New Courtesy Car", + "jobs": "Jobs", + "jobs-active": "Active Jobs", + "jobs-detail": "Job {{number}}", + "jobs-new": "Create a New Job", + "owner-detail": "{{name}}", + "owners": "Owners", + "schedule": "Schedule", + "vehicle-details": "Vehicle: {{vehicle}}", + "vehicles": "Vehicles" + }, + "contracts": "Courtesy Car Contracts | $t(titles.app)", "contracts-create": "New Contract | $t(titles.app)", "contracts-detail": "Contract {{id}} | $t(titles.app)", + "courtesycars": "Courtesy Cars | $t(titles.app)", "courtesycars-create": "New Courtesy Car | $t(titles.app)", "courtesycars-detail": "Courtesy Car {{id}} | $t(titles.app)", - "jobs": "All Jobs | $t(titles.app)", + "jobs": "Active Jobs | $t(titles.app)", "jobs-create": "Create a New Job | $t(titles.app)", "jobsavailable": "Available Jobs | $t(titles.app)", "jobsdetail": "Job {{ro_number}} | $t(titles.app)", "jobsdocuments": "Job Documents {{ro_number}} | $t(titles.app)", "manageroot": "Home | $t(titles.app)", "owners": "All Owners | $t(titles.app)", + "owners-detail": "{{name}} | $t(titles.app)", "profile": "My Profile | $t(titles.app)", "schedule": "Schedule | $t(titles.app)", "shop": "My Shop | $t(titles.app)", diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 647e0623c..540c016e8 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -583,6 +583,7 @@ "courtesycars-contracts": "", "courtesycars-newcontract": "", "customers": "Clientes", + "enterinvoices": "", "home": "Casa", "invoices": "", "jobs": "Trabajos", @@ -710,8 +711,28 @@ }, "titles": { "app": "Carrocería de ImEX Systems", + "bc": { + "availablejobs": "", + "contracts": "", + "contracts-create": "", + "contracts-detail": "", + "courtesycars": "", + "courtesycars-detail": "", + "courtesycars-new": "", + "jobs": "", + "jobs-active": "", + "jobs-detail": "", + "jobs-new": "", + "owner-detail": "", + "owners": "", + "schedule": "", + "vehicle-details": "", + "vehicles": "" + }, + "contracts": "", "contracts-create": "", "contracts-detail": "", + "courtesycars": "", "courtesycars-create": "", "courtesycars-detail": "", "jobs": "Todos los trabajos | $t(titles.app)", @@ -721,6 +742,7 @@ "jobsdocuments": "Documentos de trabajo {{ro_number}} | $ t (títulos.app)", "manageroot": "Casa | $t(titles.app)", "owners": "Todos los propietarios | $t(titles.app)", + "owners-detail": "", "profile": "Mi perfil | $t(titles.app)", "schedule": "Horario | $t(titles.app)", "shop": "Mi tienda | $t(titles.app)", diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 40bf63967..314a92316 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -583,6 +583,7 @@ "courtesycars-contracts": "", "courtesycars-newcontract": "", "customers": "Les clients", + "enterinvoices": "", "home": "Accueil", "invoices": "", "jobs": "Emplois", @@ -710,8 +711,28 @@ }, "titles": { "app": "Carrosserie par ImEX Systems", + "bc": { + "availablejobs": "", + "contracts": "", + "contracts-create": "", + "contracts-detail": "", + "courtesycars": "", + "courtesycars-detail": "", + "courtesycars-new": "", + "jobs": "", + "jobs-active": "", + "jobs-detail": "", + "jobs-new": "", + "owner-detail": "", + "owners": "", + "schedule": "", + "vehicle-details": "", + "vehicles": "" + }, + "contracts": "", "contracts-create": "", "contracts-detail": "", + "courtesycars": "", "courtesycars-create": "", "courtesycars-detail": "", "jobs": "Tous les emplois | $t(titles.app)", @@ -721,6 +742,7 @@ "jobsdocuments": "Documents de travail {{ro_number}} | $ t (titres.app)", "manageroot": "Accueil | $t(titles.app)", "owners": "Tous les propriétaires | $t(titles.app)", + "owners-detail": "", "profile": "Mon profil | $t(titles.app)", "schedule": "Horaire | $t(titles.app)", "shop": "Mon magasin | $t(titles.app)", diff --git a/client/src/utils/private-route.js b/client/src/utils/private-route.js index cbfccd627..0a55f1184 100644 --- a/client/src/utils/private-route.js +++ b/client/src/utils/private-route.js @@ -4,11 +4,11 @@ export default ({ component: Component, isAuthorized, ...rest }) => { return ( + render={(props) => isAuthorized === true ? ( ) : ( - + ) } />