+
+ {t("jobs.labels.availablejobs")}
-
- {
- setSearchText(e.currentTarget.value);
- }}
- />
-
+
+
+ {
+ setSearchText(e.currentTarget.value);
+ }}
+ />
- );
- }}
- size="small"
- pagination={{ position: "top" }}
- columns={columns}
- rowKey="id"
- dataSource={availableJobs}
- onChange={handleTableChange}
- />
-
+
+ );
+ }}
+ size="small"
+ pagination={{ position: "top" }}
+ columns={columns}
+ rowKey="id"
+ dataSource={availableJobs}
+ onChange={handleTableChange}
+ />
);
}
diff --git a/client/src/components/jobs-available-table/jobs-available-table.container.jsx b/client/src/components/jobs-available-table/jobs-available-table.container.jsx
new file mode 100644
index 000000000..dce8d4593
--- /dev/null
+++ b/client/src/components/jobs-available-table/jobs-available-table.container.jsx
@@ -0,0 +1,315 @@
+import {
+ useApolloClient,
+ useLazyQuery,
+ useMutation,
+ useQuery
+} from "@apollo/react-hooks";
+import { notification } from "antd";
+import Axios from "axios";
+import Dinero from "dinero.js";
+import gql from "graphql-tag";
+import _ from "lodash";
+import React, { useState } from "react";
+import { useTranslation } from "react-i18next";
+import { connect } from "react-redux";
+import { useHistory } from "react-router-dom";
+import { createStructuredSelector } from "reselect";
+import { logImEXEvent } from "../../firebase/firebase.utils";
+import {
+ DELETE_AVAILABLE_JOB,
+ QUERY_AVAILABLE_JOBS,
+ QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK
+} from "../../graphql/available-jobs.queries";
+import { INSERT_NEW_JOB, UPDATE_JOB } from "../../graphql/jobs.queries";
+import { SEARCH_VEHICLE_BY_VIN } from "../../graphql/vehicles.queries";
+import { selectBodyshop } from "../../redux/user/user.selectors";
+import AlertComponent from "../alert/alert.component";
+import JobsFindModalContainer from "../jobs-find-modal/jobs-find-modal.container";
+import LoadingSpinner from "../loading-spinner/loading-spinner.component";
+import OwnerFindModalContainer from "../owner-find-modal/owner-find-modal.container";
+import { GetSupplementDelta } from "./jobs-available-supplement.estlines.util";
+import HeaderFields from "./jobs-available-supplement.headerfields";
+import JobsAvailableTableComponent from "./jobs-available-table.component";
+
+const mapStateToProps = createStructuredSelector({
+ bodyshop: selectBodyshop,
+});
+
+export function JobsAvailableContainer({ bodyshop }) {
+ const { loading, error, data, refetch } = useQuery(QUERY_AVAILABLE_JOBS, {
+ fetchPolicy: "network-only",
+ });
+
+ const history = useHistory();
+ const { t } = useTranslation();
+
+ const [ownerModalVisible, setOwnerModalVisible] = useState(false);
+ const [jobModalVisible, setJobModalVisible] = useState(false);
+
+ const [selectedJob, setSelectedJob] = useState(null);
+ const [selectedOwner, setSelectedOwner] = useState(null);
+ const [insertLoading, setInsertLoading] = useState(false);
+ const [deleteJob] = useMutation(DELETE_AVAILABLE_JOB);
+ const [updateJob] = useMutation(UPDATE_JOB);
+
+ const [insertNewJob] = useMutation(INSERT_NEW_JOB);
+ const client = useApolloClient();
+
+ const estDataLazyLoad = useLazyQuery(QUERY_AVAILABLE_NEW_JOBS_EST_DATA_BY_PK);
+ const [loadEstData, estData] = estDataLazyLoad;
+
+ const importOptionsState = useState({ overrideHeaders: false });
+ const importOptions = importOptionsState[0];
+ const modalSearchState = useState("");
+
+ const onOwnerFindModalOk = async () => {
+ logImEXEvent("job_import_new");
+
+ setOwnerModalVisible(false);
+ setInsertLoading(true);
+
+ if (
+ !(
+ estData.data &&
+ estData.data.available_jobs_by_pk &&
+ estData.data.available_jobs_by_pk.est_data
+ )
+ ) {
+ //We don't have the right data. Error!
+ setInsertLoading(false);
+ notification["error"]({
+ message: t("jobs.errors.creating", { error: "No job data present." }),
+ });
+ return;
+ }
+
+ const newTotals = (
+ await Axios.post("/job/totals", {
+ job: {
+ ...estData.data.available_jobs_by_pk.est_data,
+ joblines: estData.data.available_jobs_by_pk.est_data.joblines.data,
+ },
+ })
+ ).data;
+
+ let existingVehicles;
+ if (estData.data.available_jobs_by_pk.est_data.vehicle) {
+ //There's vehicle data, need to double check the VIN.
+ existingVehicles = await client.query({
+ query: SEARCH_VEHICLE_BY_VIN,
+ variables: {
+ vin: estData.data.available_jobs_by_pk.est_data.vehicle.data.v_vin,
+ },
+ });
+ }
+
+ const newJob = {
+ ...estData.data.available_jobs_by_pk.est_data,
+ clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
+ owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat("0.00"),
+ job_totals: newTotals,
+ queued_for_parts: true,
+ ...(existingVehicles && existingVehicles.data.vehicles.length > 0
+ ? { vehicleid: existingVehicles.data.vehicles[0].id, vehicle: null }
+ : {}),
+ };
+
+ insertNewJob({
+ variables: {
+ job: selectedOwner
+ ? Object.assign(
+ {},
+ newJob,
+ { owner: null },
+ { ownerid: selectedOwner }
+ )
+ : newJob,
+ },
+ })
+ .then((r) => {
+ notification["success"]({
+ message: t("jobs.successes.created"),
+ onClick: () => {
+ history.push(`/manage/jobs/${r.data.insert_jobs.returning[0].id}`);
+ },
+ });
+ //Job has been inserted. Clean up the available jobs record.
+
+ deleteJob({
+ variables: { id: estData.data.available_jobs_by_pk.id },
+ }).then((r) => {
+ refetch();
+ setInsertLoading(false);
+ });
+ })
+ .catch((r) => {
+ //error while inserting
+ notification["error"]({
+ message: t("jobs.errors.creating", { error: r.message }),
+ });
+ refetch();
+ setInsertLoading(false);
+ });
+ };
+
+ const onJobFindModalOk = async () => {
+ logImEXEvent("job_import_supplement");
+
+ setJobModalVisible(false);
+ setInsertLoading(true);
+
+ if (
+ !(
+ estData.data &&
+ estData.data.available_jobs_by_pk &&
+ estData.data.available_jobs_by_pk.est_data
+ )
+ ) {
+ //We don't have the right data. Error!
+ setInsertLoading(false);
+ notification["error"]({
+ message: t("jobs.errors.creating", { error: "No job data present." }),
+ });
+ } else {
+ //create upsert job
+ let supp = _.cloneDeep(estData.data.available_jobs_by_pk.est_data);
+
+ delete supp.owner;
+ delete supp.vehicle;
+ if (importOptions.overrideHeaders) {
+ HeaderFields.forEach((item) => delete supp[item]);
+ }
+
+ const newTotals = (
+ await Axios.post("/job/totals", {
+ job: {
+ ...estData.data.available_jobs_by_pk.est_data,
+ joblines: estData.data.available_jobs_by_pk.est_data.joblines.data,
+ },
+ })
+ ).data;
+
+ let suppDelta = await GetSupplementDelta(
+ client,
+ selectedJob,
+ estData.data.available_jobs_by_pk.est_data.joblines.data
+ );
+
+ delete supp.joblines;
+ await client.mutate({
+ mutation: gql`
+ ${suppDelta}
+ `,
+ });
+ updateJob({
+ variables: {
+ jobId: selectedJob,
+ job: {
+ ...supp,
+ clm_total: Dinero(newTotals.totals.total_repairs).toFormat("0.00"),
+ owner_owing: Dinero(newTotals.totals.custPayable.total).toFormat(
+ "0.00"
+ ),
+ job_totals: newTotals,
+ queued_for_parts: true,
+ },
+ },
+ })
+ .then((r) => {
+ notification["success"]({
+ message: t("jobs.successes.supplemented"),
+ onClick: () => {
+ history.push(
+ `/manage/jobs/${r.data.update_jobs.returning[0].id}`
+ );
+ },
+ });
+ //Job has been inserted. Clean up the available jobs record.
+ deleteJob({
+ variables: { id: estData.data.available_jobs_by_pk.id },
+ }).then((r) => {
+ refetch();
+ setInsertLoading(false);
+ });
+ })
+ .catch((r) => {
+ //error while inserting
+ notification["error"]({
+ message: t("jobs.errors.creating", { error: r.message }),
+ });
+ refetch();
+ setInsertLoading(false);
+ });
+ }
+ };
+
+ const owner =
+ estData.data &&
+ estData.data.available_jobs_by_pk &&
+ estData.data.available_jobs_by_pk.est_data &&
+ estData.data.available_jobs_by_pk.est_data.owner &&
+ estData.data.available_jobs_by_pk.est_data.owner.data &&
+ !estData.data.available_jobs_by_pk.issupplement
+ ? estData.data.available_jobs_by_pk.est_data.owner.data
+ : null;
+
+ const onOwnerModalCancel = () => {
+ setOwnerModalVisible(false);
+ setSelectedOwner(null);
+ };
+
+ const onJobModalCancel = () => {
+ setJobModalVisible(false);
+ modalSearchState[1]("");
+ setSelectedJob(null);
+ };
+
+ const addJobAsNew = (record) => {
+ loadEstData({ variables: { id: record.id } });
+ setOwnerModalVisible(true);
+ };
+
+ const addJobAsSupp = (record) => {
+ loadEstData({ variables: { id: record.id } });
+ modalSearchState[1](record.clm_no);
+ setJobModalVisible(true);
+ };
+
+ if (error) return