Removed references to allocations objects. Added new fields to job for employee assignment + created new component. BOD-100

This commit is contained in:
Patrick Fic
2020-07-16 13:59:27 -07:00
parent bbc0359e3a
commit fbb7bbad15
37 changed files with 2127 additions and 55 deletions

View File

@@ -8,9 +8,9 @@ import { setModalContext } from "../../redux/modals/modals.actions";
import { onlyUnique } from "../../utils/arrayHelper";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { alphaSort } from "../../utils/sorters";
import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container";
import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
// import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container";
// import AllocationsBulkAssignmentContainer from "../allocations-bulk-assignment/allocations-bulk-assignment.container";
// import AllocationsEmployeeLabelContainer from "../allocations-employee-label/allocations-employee-label.container";
import PartsOrderModalContainer from "../parts-order-modal/parts-order-modal.container";
const mapDispatchToProps = (dispatch) => ({
@@ -173,35 +173,35 @@ export function JobLinesComponent({
[],
onFilter: (value, record) => value.includes(record.status),
},
{
title: t("allocations.fields.employee"),
dataIndex: "employee",
key: "employee",
sorter: (a, b) =>
alphaSort(
a.allocations[0] &&
a.allocations[0].employee.first_name +
a.allocations[0].employee.last_name,
b.allocations[0] &&
b.allocations[0].employee.first_name +
b.allocations[0].employee.last_name
),
sortOrder:
state.sortedInfo.columnKey === "employee" && state.sortedInfo.order,
render: (text, record) => (
<span>
{record.allocations && record.allocations.length > 0
? record.allocations.map((item) => (
<AllocationsEmployeeLabelContainer
key={item.id}
refetch={refetch}
allocation={item}
/>
))
: null}
</span>
),
},
// {
// title: t("allocations.fields.employee"),
// dataIndex: "employee",
// key: "employee",
// sorter: (a, b) =>
// alphaSort(
// a.allocations[0] &&
// a.allocations[0].employee.first_name +
// a.allocations[0].employee.last_name,
// b.allocations[0] &&
// b.allocations[0].employee.first_name +
// b.allocations[0].employee.last_name
// ),
// sortOrder:
// state.sortedInfo.columnKey === "employee" && state.sortedInfo.order,
// render: (text, record) => (
// <span>
// {record.allocations && record.allocations.length > 0
// ? record.allocations.map((item) => (
// <AllocationsEmployeeLabelContainer
// key={item.id}
// refetch={refetch}
// allocation={item}
// />
// ))
// : null}
// </span>
// ),
// },
{
title: t("general.labels.actions"),
dataIndex: "actions",
@@ -217,12 +217,14 @@ export function JobLinesComponent({
}}>
{t("general.actions.edit")}
</Button>
<AllocationsAssignmentContainer
key={record.id}
refetch={refetch}
jobLineId={record.id}
hours={record.mod_lb_hrs}
/>
{
// <AllocationsAssignmentContainer
// key={record.id}
// refetch={refetch}
// jobLineId={record.id}
// hours={record.mod_lb_hrs}
// />
}
</div>
),
},
@@ -278,10 +280,12 @@ export function JobLinesComponent({
<Dropdown overlay={markMenu} trigger={["click"]}>
<Button>{t("jobs.actions.mark")}</Button>
</Dropdown>
<AllocationsBulkAssignmentContainer
jobLines={selectedLines}
refetch={refetch}
/>
{
// <AllocationsBulkAssignmentContainer
// jobLines={selectedLines}
// refetch={refetch}
// />
}
<Button
onClick={() => {
setJobLineEditContext({

View File

@@ -0,0 +1,112 @@
import React, { useState } from "react";
import DataLabel from "../data-label/data-label.component";
import { useTranslation } from "react-i18next";
import { PlusCircleFilled, MinusOutlined } from "@ant-design/icons";
import { Select, Button, Popover } from "antd";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
});
const mapDispatchToProps = (dispatch) => ({
//setUserLanguage: language => dispatch(setUserLanguage(language))
});
export function JobEmployeeAssignments({
bodyshop,
body,
refinish,
handleAdd,
handleRemove,
}) {
const { t } = useTranslation();
const [assignment, setAssignment] = useState({
operation: null,
employeeid: null,
});
const [visibility, setVisibility] = useState(false);
const onChange = (e) => {
setAssignment({ ...assignment, employeeid: e });
};
const popContent = (
<div>
<Select
id='employeeSelector'
showSearch
style={{ width: 200 }}
optionFilterProp='children'
onChange={onChange}
filterOption={(input, option) =>
option.props.children.toLowerCase().indexOf(input.toLowerCase()) >= 0
}>
{bodyshop.employees.map((emp) => (
<Select.Option value={emp.id} key={emp.id}>
{`${emp.first_name} ${emp.last_name}`}
</Select.Option>
))}
</Select>
<Button
type='primary'
disabled={!assignment.employeeid}
onClick={() => {
handleAdd(assignment);
setVisibility(false);
}}>
Assign
</Button>
<Button onClick={() => setVisibility(false)}>Close</Button>
</div>
);
return (
<div>
<Popover destroyTooltipOnHide content={popContent} visible={visibility}>
<DataLabel label={t("jobs.fields.employee_body")}>
{body ? (
<div>
<span>{`${body.first_name || ""} ${body.last_name || ""}`}</span>
<MinusOutlined
operation='body'
onClick={() => handleRemove("body")}
/>
</div>
) : (
<PlusCircleFilled
onClick={() => {
setAssignment({ operation: "body" });
setVisibility(true);
}}
/>
)}
</DataLabel>
<DataLabel label={t("jobs.fields.employee_refinish")}>
{refinish ? (
<div>
<span>{`${refinish.first_name || ""} ${
refinish.last_name || ""
}`}</span>
<MinusOutlined
operation='refinish'
onClick={() => handleRemove("refinish")}
/>
</div>
) : (
<PlusCircleFilled
onClick={() => {
setAssignment({ operation: "refinish" });
setVisibility(true);
}}
/>
)}
</DataLabel>
</Popover>
</div>
);
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(JobEmployeeAssignments);

View File

@@ -0,0 +1,70 @@
import { useMutation } from "@apollo/react-hooks";
import { notification } from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import JobEmployeeAssignmentsComponent from "./job-employee-assignments.component";
export default function JobEmployeeAssignmentsContainer({ job }) {
const { t } = useTranslation();
const [updateJob] = useMutation(UPDATE_JOB);
const handleAdd = async (assignment) => {
const { operation, employeeid } = assignment;
let empAssignment = determineFieldName(operation);
const result = await updateJob({
variables: { jobId: job.id, job: { [empAssignment]: employeeid } },
refetchQueries: ["GET_JOB_BY_PK"],
awaitRefetchQueries: true,
});
if (!!result.errors) {
notification["error"]({
message: t("jobs.errors.assigning", {
message: JSON.stringify(result.errors),
}),
});
}
};
const handleRemove = async (operation) => {
console.log("handleRemove -> operation", operation);
let empAssignment = determineFieldName(operation);
const result = await updateJob({
variables: { jobId: job.id, job: { [empAssignment]: null } },
refetchQueries: ["GET_JOB_BY_PK"],
awaitRefetchQueries: true,
});
if (!!result.errors) {
notification["error"]({
message: t("jobs.errors.assigning", {
message: JSON.stringify(result.errors),
}),
});
}
};
return (
<div>
<JobEmployeeAssignmentsComponent
body={job.employee_body_rel}
refinish={job.employee_refinish_rel}
handleAdd={handleAdd}
handleRemove={handleRemove}
/>
</div>
);
}
const determineFieldName = (operation) => {
switch (operation) {
case "body":
return "employee_body";
break;
case "refinish":
return "employee_refinish";
break;
}
};

View File

@@ -7,7 +7,7 @@ import {
Menu,
notification,
PageHeader,
Tag
Tag,
} from "antd";
import React from "react";
import { useTranslation } from "react-i18next";
@@ -21,6 +21,7 @@ import CurrencyFormatter from "../../utils/CurrencyFormatter";
import JobsDetailHeaderActions from "../jobs-detail-header-actions/jobs-detail-header-actions.component";
import OwnerTagPopoverComponent from "../owner-tag-popover/owner-tag-popover.component";
import VehicleTagPopoverComponent from "../vehicle-tag-popover/vehicle-tag-popover.component";
import JobEmployeeAssignments from "../job-employee-assignments/job-employee-assignments.container";
import "./jobs-detail-header.styles.scss";
const mapStateToProps = createStructuredSelector({
@@ -130,7 +131,9 @@ export function JobsDetailHeader({
</Tag>,
]}
extra={menuExtra}>
<Descriptions size='small' column={5}>
<Descriptions
size='small'
column={{ xs: 1, sm: 1, md: 2, lg: 3, xl: 3, xxl: 6 }}>
<Descriptions.Item key='total' label={t("jobs.fields.repairtotal")}>
<CurrencyFormatter>{job.clm_total}</CurrencyFormatter>
</Descriptions.Item>
@@ -165,6 +168,11 @@ export function JobsDetailHeader({
</Link>
))}
</Descriptions.Item>
<Descriptions.Item
key='assignments'
label={t("jobs.labels.employeeassignments")}>
<JobEmployeeAssignments job={job} />
</Descriptions.Item>
</Descriptions>
</PageHeader>
);