diff --git a/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx b/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx
index 16d23beec..44d4233ab 100644
--- a/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx
+++ b/client/src/components/labor-allocations-table/labor-allocations-table.payroll.component.jsx
@@ -235,7 +235,7 @@ export function PayrollLaborAllocationsTable({
>
`${record.cost_center} ${record.mod_lbr_ty}`}
+ rowKey={(record) => `${record.employeeid} ${record.mod_lbr_ty}`}
pagination={false}
onChange={handleTableChange}
dataSource={totals}
diff --git a/client/src/components/time-ticket-task-modal/time-ticket-task-modal.component.jsx b/client/src/components/time-ticket-task-modal/time-ticket-task-modal.component.jsx
index 3cacf667a..09617993b 100644
--- a/client/src/components/time-ticket-task-modal/time-ticket-task-modal.component.jsx
+++ b/client/src/components/time-ticket-task-modal/time-ticket-task-modal.component.jsx
@@ -1,14 +1,12 @@
import {
Alert,
- Checkbox,
Col,
Form,
Radio,
Row,
- Select,
Skeleton,
Space,
- Table,
+ Spin,
Typography,
} from "antd";
import React from "react";
@@ -16,10 +14,8 @@ import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { selectBodyshop } from "../../redux/user/user.selectors";
-import EmployeeTeamSearchSelectComponent from "../employee-team-search-select/employee-team-search-select.component";
-import JobSearchSelectComponent from "../job-search-select/job-search-select.component";
import ReadOnlyFormItemComponent from "../form-items-formatted/read-only-form-item.component";
-import LayoutFormRow from "../layout-form-row/layout-form-row.component";
+import JobSearchSelectComponent from "../job-search-select/job-search-select.component";
const mapStateToProps = createStructuredSelector({
//currentUser: selectCurrentUser
@@ -33,7 +29,12 @@ export default connect(
mapDispatchToProps
)(TimeTicketTaskModalComponent);
-export function TimeTicketTaskModalComponent({ bodyshop, form, loading }) {
+export function TimeTicketTaskModalComponent({
+ bodyshop,
+ form,
+ loading,
+ completedTasks,
+}) {
const { t } = useTranslation();
return (
@@ -57,13 +58,18 @@ export function TimeTicketTaskModalComponent({ bodyshop, form, loading }) {
- ({
- value: preset.name,
- label: preset.name,
- }))}
- />
+ {loading ? (
+
+ ) : (
+ ({
+ value: preset.name,
+ label: preset.name,
+ disabled: completedTasks.includes(preset.name),
+ }))}
+ />
+ )}
{() => {
@@ -75,20 +81,24 @@ export function TimeTicketTaskModalComponent({ bodyshop, form, loading }) {
if (!task) return null;
return (
-
- | {t("bodyshop.fields.md_tasks_presets.percent")} |
- {`${theTaskPreset.percent || 0}%`} |
-
-
- | {t("bodyshop.fields.md_tasks_presets.hourstype")} |
- {theTaskPreset.hourstype.join(", ")} |
-
-
- |
- {t("bodyshop.fields.md_tasks_presets.nextstatus")}
- |
- {theTaskPreset.nextstatus} |
-
+
+
+ | {t("bodyshop.fields.md_tasks_presets.percent")} |
+ {`${theTaskPreset.percent || 0}%`} |
+
+
+ |
+ {t("bodyshop.fields.md_tasks_presets.hourstype")}
+ |
+ {theTaskPreset.hourstype.join(", ")} |
+
+
+ |
+ {t("bodyshop.fields.md_tasks_presets.nextstatus")}
+ |
+ {theTaskPreset.nextstatus} |
+
+
);
}}
diff --git a/client/src/components/time-ticket-task-modal/time-ticket-task-modal.container.jsx b/client/src/components/time-ticket-task-modal/time-ticket-task-modal.container.jsx
index fa77fa6a1..9bb1fb009 100644
--- a/client/src/components/time-ticket-task-modal/time-ticket-task-modal.container.jsx
+++ b/client/src/components/time-ticket-task-modal/time-ticket-task-modal.container.jsx
@@ -1,4 +1,4 @@
-import React, { useState } from "react";
+import React, { useCallback, useEffect, useState } from "react";
import { Form, Modal, notification } from "antd";
import axios from "axios";
@@ -9,6 +9,8 @@ import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectTimeTicketTasks } from "../../redux/modals/modals.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
import TimeTicketTaskModalComponent from "./time-ticket-task-modal.component";
+import { useApolloClient } from "@apollo/client";
+import { QUERY_COMPLETED_TASKS } from "../../graphql/jobs.queries";
const mapStateToProps = createStructuredSelector({
timeTicketTasksModal: selectTimeTicketTasks,
@@ -29,15 +31,41 @@ export function TimeTickeTaskModalContainer({
}) {
const [form] = Form.useForm();
const { context, visible } = timeTicketTasksModal;
-
+ const [completedTasks, setCompletedTasks] = useState([]);
const { t } = useTranslation();
const [loading, setLoading] = useState(false);
+ const client = useApolloClient();
async function handleFinish(values) {
calculateTickets({ values, handleFinish: true });
}
+ const getCompletedTasks = useCallback(
+ async (jobid) => {
+ setLoading(true);
+
+ const { data } = await client.query({
+ query: QUERY_COMPLETED_TASKS,
+ variables: { jobid },
+ });
+
+ setCompletedTasks(data.jobs_by_pk.completed_tasks || []);
+ setLoading(false);
+ },
+ [client]
+ );
+ useEffect(() => {
+ if (visible) {
+ form.setFieldsValue({ ...context, task: null, timetickets: null });
+ if (context.jobid) {
+ getCompletedTasks(context.jobid);
+ }
+ }
+ }, [context.jobid, visible, getCompletedTasks, form, context]);
async function handleValueChange(changedValues, allValues) {
+ if (changedValues.jobid) {
+ getCompletedTasks(changedValues.jobid);
+ }
if (allValues.jobid && allValues.task) {
calculateTickets({ values: allValues, handleFinish: false });
}
@@ -93,7 +121,11 @@ export function TimeTickeTaskModalContainer({
initialValues={context}
onValuesChange={handleValueChange}
>
-
+
);
diff --git a/client/src/graphql/jobs.queries.js b/client/src/graphql/jobs.queries.js
index 6509b74e6..47f93bfd7 100644
--- a/client/src/graphql/jobs.queries.js
+++ b/client/src/graphql/jobs.queries.js
@@ -2196,3 +2196,12 @@ export const GET_JOB_LINE_ORDERS = gql`
}
}
`;
+
+export const QUERY_COMPLETED_TASKS = gql`
+ query QUERY_COMPLETED_TASKS($jobid: uuid!) {
+ jobs_by_pk(id: $jobid) {
+ id
+ completed_tasks
+ }
+ }
+`;
diff --git a/server/graphql-client/queries.js b/server/graphql-client/queries.js
index 99567fa42..08335694c 100644
--- a/server/graphql-client/queries.js
+++ b/server/graphql-client/queries.js
@@ -1881,6 +1881,7 @@ exports.QUERY_JOB_PAYROLL_DATA = `query QUERY_JOB_PAYROLL_DATA($id: uuid!) {
rate_matd
status
materials
+ completed_tasks
joblines(where: { removed: { _eq: false } }){
id
line_no
diff --git a/server/payroll/claim-task.js b/server/payroll/claim-task.js
index fd3efb2b7..6b5ddf5b8 100644
--- a/server/payroll/claim-task.js
+++ b/server/payroll/claim-task.js
@@ -76,6 +76,13 @@ exports.claimtask = async function (req, res) {
(ticket) => ticket.productivehrs !== 0
),
});
+ const updateResult = await client.request(queries.UPDATE_JOB, {
+ jobId: job.id,
+ job: {
+ completed_tasks: [...job.completed_tasks, task],
+ },
+ });
+ console.log("🚀 ~ file: claim-task.js:85 ~ updateResult:", updateResult)
}
res.json(ticketsToInsert);
} catch (error) {