diff --git a/bodyshop_translations.babel b/bodyshop_translations.babel index e3f709fc7..17d6e7b03 100644 --- a/bodyshop_translations.babel +++ b/bodyshop_translations.babel @@ -18,6 +18,63 @@ translation + + allocations + + + actions + + + assign + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + fields + + + employee + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + + + + + appointments @@ -1456,6 +1513,27 @@ + + mod_lb_hrs + false + + + + + + en-US + false + + + es-MX + false + + + fr-CA + false + + + oem_partno false diff --git a/client/src/components/allocations-assignment/allocations-assignment.component.jsx b/client/src/components/allocations-assignment/allocations-assignment.component.jsx new file mode 100644 index 000000000..f3f3a0a8a --- /dev/null +++ b/client/src/components/allocations-assignment/allocations-assignment.component.jsx @@ -0,0 +1,76 @@ +import { Select, Button, Popover, InputNumber } from "antd"; +import React from "react"; +import { useTranslation } from "react-i18next"; +import { connect } from "react-redux"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; + +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop +}); + +export default connect( + mapStateToProps, + null +)(function AllocationsAssignmentComponent({ + bodyshop, + handleAssignment, + assignment, + setAssignment, + visibilityState, + maxHours +}) { + const { t } = useTranslation(); + + const onChange = e => { + console.log("e", e); + setAssignment({ ...assignment, employeeid: e }); + }; + + const [visibility, setVisibility] = visibilityState; + + const popContent = ( +
+ + setAssignment({ ...assignment, hours: e })} + /> + + + +
+ ); + + return ( + + + + ); +}); diff --git a/client/src/components/allocations-assignment/allocations-assignment.container.jsx b/client/src/components/allocations-assignment/allocations-assignment.container.jsx new file mode 100644 index 000000000..3369d6904 --- /dev/null +++ b/client/src/components/allocations-assignment/allocations-assignment.container.jsx @@ -0,0 +1,38 @@ +import React, { useState } from "react"; +import AllocationsAssignmentComponent from "./allocations-assignment.component"; +import { useMutation } from "react-apollo"; +import { INSERT_ALLOCATION } from "../../graphql/allocations.queries"; +import { useTranslation } from "react-i18next"; +import { notification } from "antd"; + +export default function AllocationsAssignmentContainer({ jobLineId, hours }) { + const visibilityState = useState(false); + const { t } = useTranslation(); + const [assignment, setAssignment] = useState({ + joblineid: jobLineId, + hours: parseFloat(hours), + employeeid: null + }); + const [insertAllocation] = useMutation(INSERT_ALLOCATION); + + const handleAssignment = () => { + insertAllocation({ variables: { alloc: { ...assignment } } }).then(r => { + notification["success"]({ + message: t("employees.successes.save") + }); + //TODO: Better way to reset the field decorators? + visibilityState[1](false); + //refetch().then(r => form.resetFields()); + }); + }; + + return ( + + ); +} diff --git a/client/src/components/job-detail-lines/job-lines.component.jsx b/client/src/components/job-detail-lines/job-lines.component.jsx index a02f0bed8..97ba507a5 100644 --- a/client/src/components/job-detail-lines/job-lines.component.jsx +++ b/client/src/components/job-detail-lines/job-lines.component.jsx @@ -4,6 +4,7 @@ import { useTranslation } from "react-i18next"; import CurrencyFormatter from "../../utils/CurrencyFormatter"; import { alphaSort } from "../../utils/sorters"; //import EditableCell from "./job-lines-cell.component"; +import AllocationsAssignmentContainer from "../allocations-assignment/allocations-assignment.container"; export default function JobLinesComponent({ jobLines, @@ -97,6 +98,38 @@ export default function JobLinesComponent({ render: (text, record) => ( {record.act_price} ) + }, + { + title: t("joblines.fields.mod_lb_hrs"), + dataIndex: "mod_lb_hrs", + key: "mod_lb_hrs", + sorter: (a, b) => a.mod_lb_hrs - b.mod_lb_hrs, + sortOrder: + state.sortedInfo.columnKey === "mod_lb_hrs" && state.sortedInfo.order + }, + { + title: t("allocations.fields.employee"), + dataIndex: "employee", + key: "employee", + sorter: (a, b) => a.act_price - b.act_price, //TODO Fix employee sorting. + sortOrder: + state.sortedInfo.columnKey === "employee" && state.sortedInfo.order, + render: (text, record) => ( + + {record.allocations && record.allocations.length > 0 + ? record.allocations.map(item => ( +
{`${item.employee.first_name} ${item.employee.last_name} (${item.hours})`}
+ )) + : null} + +
+ ) } ]; diff --git a/client/src/graphql/allocations.queries.js b/client/src/graphql/allocations.queries.js new file mode 100644 index 000000000..728f5534c --- /dev/null +++ b/client/src/graphql/allocations.queries.js @@ -0,0 +1,11 @@ +import { gql } from "apollo-boost"; + +export const INSERT_ALLOCATION = gql` + mutation INSERT_ALLOCATION($alloc: [allocations_insert_input!]!) { + insert_allocations(objects: $alloc) { + returning { + id + } + } + } +`; diff --git a/client/src/graphql/bodyshop.queries.js b/client/src/graphql/bodyshop.queries.js index 23081b0cb..facc647a6 100644 --- a/client/src/graphql/bodyshop.queries.js +++ b/client/src/graphql/bodyshop.queries.js @@ -20,6 +20,13 @@ export const QUERY_BODYSHOP = gql` updated_at zip_post region_config + employees { + id + first_name + last_name + employee_number + cost_center + } } } `; diff --git a/client/src/graphql/jobs-lines.queries.js b/client/src/graphql/jobs-lines.queries.js index 334097e37..5efd5ccd0 100644 --- a/client/src/graphql/jobs-lines.queries.js +++ b/client/src/graphql/jobs-lines.queries.js @@ -18,6 +18,15 @@ export const GET_JOB_LINES_BY_PK = gql` lbr_op lbr_amt op_code_desc + allocations { + id + hours + employee { + id + first_name + last_name + } + } } } `; diff --git a/client/src/translations/en_us/common.json b/client/src/translations/en_us/common.json index b4832f728..1968bd4bb 100644 --- a/client/src/translations/en_us/common.json +++ b/client/src/translations/en_us/common.json @@ -1,5 +1,13 @@ { "translation": { + "allocations": { + "actions": { + "assign": "Assign" + }, + "fields": { + "employee": "Allocated To" + } + }, "appointments": { "actions": { "cancel": "Cancel", @@ -116,6 +124,7 @@ "act_price": "Actual Price", "db_price": "Database Price", "line_desc": "Line Description", + "mod_lb_hrs": "Labor Hours", "oem_partno": "OEM Part #", "part_type": "Part Type", "unq_seq": "Seq #" diff --git a/client/src/translations/es/common.json b/client/src/translations/es/common.json index 7bc56c0c8..c33605a43 100644 --- a/client/src/translations/es/common.json +++ b/client/src/translations/es/common.json @@ -1,5 +1,13 @@ { "translation": { + "allocations": { + "actions": { + "assign": "Asignar" + }, + "fields": { + "employee": "Asignado a" + } + }, "appointments": { "actions": { "cancel": "Cancelar", @@ -116,6 +124,7 @@ "act_price": "Precio actual", "db_price": "Precio de base de datos", "line_desc": "Descripción de línea", + "mod_lb_hrs": "Horas laborales", "oem_partno": "OEM parte #", "part_type": "Tipo de parte", "unq_seq": "Seq #" diff --git a/client/src/translations/fr/common.json b/client/src/translations/fr/common.json index 8dfe552f3..b0ef0b149 100644 --- a/client/src/translations/fr/common.json +++ b/client/src/translations/fr/common.json @@ -1,5 +1,13 @@ { "translation": { + "allocations": { + "actions": { + "assign": "Attribuer" + }, + "fields": { + "employee": "Alloué à" + } + }, "appointments": { "actions": { "cancel": "annuler", @@ -116,6 +124,7 @@ "act_price": "Prix actuel", "db_price": "Prix de la base de données", "line_desc": "Description de la ligne", + "mod_lb_hrs": "Heures de travail", "oem_partno": "Pièce OEM #", "part_type": "Type de pièce", "unq_seq": "Seq #"