Files
bodyshop/client/src/components/note-upsert-modal/note-upsert-modal.container.jsx
2025-08-08 12:14:11 -04:00

172 lines
5.4 KiB
JavaScript

import { useMutation } from "@apollo/client";
import { Form, Modal } from "antd";
import { useEffect } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { createStructuredSelector } from "reselect";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { logImEXEvent } from "../../firebase/firebase.utils";
import { GET_JOB_BY_PK } from "../../graphql/jobs.queries.js";
import { INSERT_NEW_NOTE, UPDATE_NOTE } from "../../graphql/notes.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { toggleModalVisible } from "../../redux/modals/modals.actions";
import { selectNoteUpsert } from "../../redux/modals/modals.selectors";
import { selectCurrentUser } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import NoteUpsertModalComponent from "./note-upsert-modal.component";
const mapStateToProps = createStructuredSelector({
currentUser: selectCurrentUser,
noteUpsertModal: selectNoteUpsert
});
const mapDispatchToProps = (dispatch) => ({
toggleModalVisible: () => dispatch(toggleModalVisible("noteUpsert")),
insertAuditTrail: ({ jobid, operation, type }) =>
dispatch(
insertAuditTrail({
jobid,
operation,
type
})
)
});
export function NoteUpsertModalContainer({ currentUser, noteUpsertModal, toggleModalVisible, insertAuditTrail }) {
const { t } = useTranslation();
const [insertNote] = useMutation(INSERT_NEW_NOTE);
const [updateNote] = useMutation(UPDATE_NOTE);
const notification = useNotification();
const { open, context, actions } = noteUpsertModal;
const { jobId, existingNote, text } = context;
const { refetch } = actions;
const [form] = Form.useForm();
useEffect(() => {
//Required to prevent infinite looping.
if (existingNote && open) {
form.setFieldsValue(existingNote);
} else if (!existingNote && open) {
form.resetFields();
if (text) {
form.setFieldValue("text", text);
}
}
}, [existingNote, form, open, text]);
const handleFinish = async (formValues) => {
const { relatedros, ...values } = formValues;
if (existingNote) {
logImEXEvent("job_note_update");
updateNote({
variables: {
noteId: existingNote.id,
note: values
},
refetchQueries: ["GET_JOB_BY_PK", "QUERY_JOB_CARD_DETAILS", "QUERY_PARTS_QUEUE_CARD_DETAILS"]
}).then(() => {
notification["success"]({
message: t("notes.successes.updated")
});
insertAuditTrail({
jobid: context.jobId,
operation: AuditTrailMapping.jobnoteupdated(),
type: "jobnoteupdated"
});
});
if (refetch) refetch();
toggleModalVisible();
} else {
logImEXEvent("job_note_insert");
const AdditionalNoteInserts = relatedros ? Object.keys(relatedros).filter((key) => relatedros[key]) : [];
await insertNote({
variables: {
noteInput: [{ ...values, jobid: jobId, created_by: currentUser.email }]
},
update(cache, { data: { updateNote: updatedNote } }) {
try {
const existingJob = cache.readQuery({
query: GET_JOB_BY_PK,
variables: { id: jobId }
});
if (existingJob) {
cache.writeQuery({
query: GET_JOB_BY_PK,
variables: { id: jobId },
data: {
...existingJob,
job: {
...existingJob.job,
notes: updatedNote.pinned
? [updatedNote, ...existingJob.job.notes]
: existingJob.job.notes.filter((n) => n.id !== updatedNote.id)
}
}
});
}
} catch (error) {
// Cache miss is okay, query hasn't been executed yet
console.log("Cache miss for GET_JOB_BY_PK");
}
},
refetchQueries: ["QUERY_NOTES_BY_JOB_PK"]
});
if (AdditionalNoteInserts.length > 0) {
//Insert the others.
AdditionalNoteInserts.forEach(async (newJobId) => {
await insertNote({
variables: {
noteInput: [{ ...values, jobid: newJobId, created_by: currentUser.email }]
}
});
insertAuditTrail({
jobid: newJobId,
operation: AuditTrailMapping.jobnoteadded(),
type: "jobnoteadded"
});
});
}
if (refetch) refetch();
form.resetFields();
toggleModalVisible();
notification["success"]({
message: t("notes.successes.create")
});
insertAuditTrail({
jobid: context.jobId,
operation: AuditTrailMapping.jobnoteadded(),
type: "jobnoteadded"
});
}
};
return (
<Modal
title={existingNote ? t("notes.actions.edit") : t("notes.actions.new")}
open={open}
okText={t("general.actions.save")}
onOk={() => {
form.submit();
}}
onCancel={() => {
toggleModalVisible();
}}
destroyOnHidden
>
<Form form={form} onFinish={handleFinish} layout="vertical">
<NoteUpsertModalComponent form={form} />
</Form>
</Modal>
);
}
export default connect(mapStateToProps, mapDispatchToProps)(NoteUpsertModalContainer);