Compare commits

..

4 Commits

Author SHA1 Message Date
Allan Carr
596132b2af Merge branch 'release/2025-01-31' into feature/IO-3114-Quick-Intake
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>

# Conflicts:
#	client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.component.jsx
#	client/src/components/jobs-detail-header-actions/jobs-detail-header-actions.toggle-production.jsx
2025-01-29 15:24:47 -08:00
Allan Carr
a55102b0ae IO-3114 Quick Intake
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2025-01-29 15:16:20 -08:00
Allan Carr
9b75993ac1 IO-3114 Quick Intake
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2025-01-29 15:14:03 -08:00
Allan Carr
d5e750c1f0 IO-3114 Quick Intake Data
Signed-off-by: Allan Carr <allan.carr@thinkimex.com>
2025-01-29 15:12:20 -08:00
4 changed files with 73 additions and 53 deletions

View File

@@ -4,11 +4,12 @@ import { useSplitTreatments } from "@splitsoftware/splitio-react";
import { Button, Card, Dropdown, Form, Input, Modal, Popconfirm, Popover, Select, Space } from "antd";
import axios from "axios";
import parsePhoneNumber from "libphonenumber-js";
import React, { useContext, useMemo, useState } from "react";
import { useContext, useMemo, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
import { auth, logImEXEvent } from "../../firebase/firebase.utils";
import { CANCEL_APPOINTMENTS_BY_JOB_ID, INSERT_MANUAL_APPT } from "../../graphql/appointments.queries";
import { GET_CURRENT_QUESTIONSET_ID, INSERT_CSI } from "../../graphql/csi.queries";
@@ -30,7 +31,6 @@ import RbacWrapper from "../rbac-wrapper/rbac-wrapper.component";
import AddToProduction from "./jobs-detail-header-actions.addtoproduction.util";
import DuplicateJob from "./jobs-detail-header-actions.duplicate.util";
import JobsDetailHeaderActionsToggleProduction from "./jobs-detail-header-actions.toggle-production";
import SocketContext from "../../contexts/SocketIO/socketContext.jsx";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
const mapStateToProps = createStructuredSelector({
@@ -121,6 +121,7 @@ export function JobsDetailHeaderActions({
const history = useNavigate();
const [form] = Form.useForm();
const [loading, setLoading] = useState(false);
const [dropdownOpen, setDropdownOpen] = useState(false);
const [isCancelScheduleModalVisible, setIsCancelScheduleModalVisible] = useState(false);
const [insertAppointment] = useMutation(INSERT_MANUAL_APPT);
const [deleteJob] = useMutation(DELETE_JOB);
@@ -718,7 +719,13 @@ export function JobsDetailHeaderActions({
key: "toggleproduction",
id: "job-actions-toggleproduction",
disabled: !job.converted || jobRO,
label: <JobsDetailHeaderActionsToggleProduction job={job} refetch={refetch} />
label: (
<JobsDetailHeaderActionsToggleProduction
job={job}
refetch={refetch}
closeParentMenu={() => setDropdownOpen(false)}
/>
)
},
{
@@ -1148,7 +1155,7 @@ export function JobsDetailHeaderActions({
</Form.Item>
</Form>
</Modal>
<Dropdown menu={menu} trigger={["click"]} key="changestatus">
<Dropdown menu={menu} trigger={["click"]} key="changestatus" open={dropdownOpen} onOpenChange={setDropdownOpen}>
<Button>
<span>{t("general.labels.actions")}</span>
<DownCircleFilled />

View File

@@ -1,11 +1,11 @@
import { useMutation } from "@apollo/client";
import { useLazyQuery, useMutation } from "@apollo/client";
import { Button, Form, Popover, Space } from "antd";
import dayjs from "dayjs";
import React, { useEffect, useState } from "react";
import { useEffect, useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { JOB_PRODUCTION_TOGGLE } from "../../graphql/jobs.queries";
import { GET_JOB_BY_PK_QUICK_INTAKE, JOB_PRODUCTION_TOGGLE } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { selectBodyshop } from "../../redux/user/user.selectors";
@@ -23,16 +23,40 @@ const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation }))
});
export function JobsDetailHeaderActionsToggleProduction({ bodyshop, job, jobRO, insertAuditTrail }) {
export function JobsDetailHeaderActionsToggleProduction({
bodyshop,
job,
jobRO,
refetch,
closeParentMenu,
insertAuditTrail
}) {
const [scenario, setScenario] = useState(false);
const [loading, setLoading] = useState(false);
const [popOverVisible, setPopOverVisible] = useState(false);
const [mutationUpdateJob] = useMutation(JOB_PRODUCTION_TOGGLE);
const { t } = useTranslation();
const [form] = Form.useForm();
const notification = useNotification();
const [getJobDetails] = useLazyQuery(GET_JOB_BY_PK_QUICK_INTAKE, {
variables: { id: job.id },
onCompleted: (data) => {
if (data?.jobs_by_pk) {
form.setFieldsValue({
actual_in: data.jobs_by_pk.actual_in ? data.jobs_by_pk.actual_in : dayjs(),
scheduled_completion: data.jobs_by_pk.scheduled_completion,
actual_completion: data.jobs_by_pk.actual_completion,
scheduled_delivery: data.jobs_by_pk.scheduled_delivery,
actual_delivery: data.jobs_by_pk.actual_delivery
});
}
},
fetchPolicy: "network-only"
});
useEffect(() => {
//Figure out what scenario were in, populate accodingly
//Figure out what scenario were in, populate accordingly
if (job && bodyshop) {
if (bodyshop.md_ro_statuses.pre_production_statuses.includes(job.status)) {
setScenario("pre");
@@ -76,24 +100,16 @@ export function JobsDetailHeaderActionsToggleProduction({ bodyshop, job, jobRO,
DateTimeFormatterFunction(values.actual_completion)
)
});
setPopOverVisible(false);
closeParentMenu();
refetch();
}
setLoading(false);
};
const popMenu = (
<div onClick={(e) => e.stopPropagation()}>
<Form
layout="vertical"
form={form}
onFinish={handleConvert}
initialValues={{
actual_in: dayjs(),
scheduled_completion: job.scheduled_completion,
actual_completion: job.actual_completion,
scheduled_deliver: job.scheduled_deliver,
actual_delivery: job.actual_delivery
}}
>
<Form layout="vertical" form={form} onFinish={handleConvert}>
{scenario === "pre" && (
<>
<Form.Item
@@ -158,7 +174,12 @@ export function JobsDetailHeaderActionsToggleProduction({ bodyshop, job, jobRO,
return (
<Popover //open={open}
content={popMenu}
onClick={(e) => e.stopPropagation()}
open={popOverVisible}
onOpenChange={setPopOverVisible}
onClick={(e) => {
getJobDetails();
e.stopPropagation();
}}
getPopupContainer={(trigger) => trigger.parentNode}
trigger="click"
>

View File

@@ -2553,3 +2553,16 @@ export const QUERY_JOBS_IN_PRODUCTION = gql`
}
}
`;
export const GET_JOB_BY_PK_QUICK_INTAKE = gql`
query GET_JOB_BY_PK_QUICK_INTAKE($id: uuid!) {
jobs_by_pk(id: $id) {
id
actual_in
scheduled_completion
actual_completion
scheduled_delivery
actual_delivery
}
}
`;

View File

@@ -1,5 +1,4 @@
import { DeleteFilled, PrinterFilled } from "@ant-design/icons";
import { PageHeader } from "@ant-design/pro-layout";
import { DeleteFilled } from "@ant-design/icons";
import { useApolloClient, useMutation } from "@apollo/client";
import {
Alert,
@@ -17,31 +16,32 @@ import {
Switch,
Typography
} from "antd";
import { useState } from "react";
import { PageHeader } from "@ant-design/pro-layout";
import React, { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
// import { useNavigate } from 'react-router-dom';
import { useSplitTreatments } from "@splitsoftware/splitio-react";
import Dinero from "dinero.js";
import dayjs from "../../utils/day";
import { Link } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import DateTimePicker from "../../components/form-date-time-picker/form-date-time-picker.component";
import FormsFieldChanged from "../../components/form-fields-changed-alert/form-fields-changed-alert.component";
import CurrencyInput from "../../components/form-items-formatted/currency-form-item.component";
import JobCloseRoGuardContainer from "../../components/job-close-ro-guard/job-close-ro-guard.container";
import JobsScoreboardAdd from "../../components/job-scoreboard-add-button/job-scoreboard-add-button.component";
import JobsCloseAutoAllocate from "../../components/jobs-close-auto-allocate/jobs-close-auto-allocate.component";
import JobsCloseLines from "../../components/jobs-close-lines/jobs-close-lines.component";
import LayoutFormRow from "../../components/layout-form-row/layout-form-row.component";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { generateJobLinesUpdatesForInvoicing } from "../../graphql/jobs-lines.queries";
import { UPDATE_JOB } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { selectJobReadOnly } from "../../redux/application/application.selectors";
import { setModalContext } from "../../redux/modals/modals.actions.js";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import dayjs from "../../utils/day";
import JobCloseRoGuardContainer from "../../components/job-close-ro-guard/job-close-ro-guard.container";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop,
@@ -49,17 +49,10 @@ const mapStateToProps = createStructuredSelector({
});
const mapDispatchToProps = (dispatch) => ({
insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type })),
setPrintCenterContext: (context) =>
dispatch(
setModalContext({
context: context,
modal: "printCenter"
})
)
insertAuditTrail: ({ jobid, operation, type }) => dispatch(insertAuditTrail({ jobid, operation, type }))
});
export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, setPrintCenterContext }) {
export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail }) {
const { t } = useTranslation();
const [form] = Form.useForm();
const client = useApolloClient();
@@ -178,6 +171,7 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
extra={
<Space>
<JobsCloseAutoAllocate joblines={job.joblines} form={form} disabled={!!job.date_exported || jobRO} />
<Popconfirm
onConfirm={() => form.submit()}
disabled={jobRO}
@@ -194,21 +188,6 @@ export function JobsCloseComponent({ job, bodyshop, jobRO, insertAuditTrail, set
<Button disabled={job.date_exported || !jobRO}>{t("jobs.actions.sendtodms")}</Button>
</Link>
)}
<Button
onClick={() => {
setPrintCenterContext({
context: {
id: job.id,
job: job,
type: "job"
}
});
}}
key="printing"
icon={<PrinterFilled />}
>
{t("jobs.actions.printCenter")}
</Button>
<JobsScoreboardAdd job={job} disabled={false} />
</Space>
}