import { useMutation, useQuery } from "@apollo/client"; //import moment from "moment"; import { Form, Modal, notification } from "antd"; import moment from "moment-business-days"; import React, { useEffect, useState } from "react"; import { useTranslation } from "react-i18next"; import { connect } from "react-redux"; import { createStructuredSelector } from "reselect"; import { logImEXEvent } from "../../firebase/firebase.utils"; import { CANCEL_APPOINTMENT_BY_ID, INSERT_APPOINTMENT, QUERY_APPOINTMENTS_BY_JOBID, } from "../../graphql/appointments.queries"; import { QUERY_LBR_HRS_BY_PK, UPDATE_JOBS } from "../../graphql/jobs.queries"; import { insertAuditTrail } from "../../redux/application/application.actions"; import { setEmailOptions } from "../../redux/email/email.actions"; import { toggleModalVisible } from "../../redux/modals/modals.actions"; import { selectSchedule } from "../../redux/modals/modals.selectors"; import { selectBodyshop, selectCurrentUser, } from "../../redux/user/user.selectors"; import AuditTrailMapping from "../../utils/AuditTrailMappings"; import { DateTimeFormat } from "../../utils/DateFormatter"; import { TemplateList } from "../../utils/TemplateConstants"; import ScheduleJobModalComponent from "./schedule-job-modal.component"; const mapStateToProps = createStructuredSelector({ bodyshop: selectBodyshop, scheduleModal: selectSchedule, currentUser: selectCurrentUser, }); const mapDispatchToProps = (dispatch) => ({ toggleModalVisible: () => dispatch(toggleModalVisible("schedule")), setEmailOptions: (e) => dispatch(setEmailOptions(e)), insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation })), }); export function ScheduleJobModalContainer({ scheduleModal, bodyshop, toggleModalVisible, setEmailOptions, currentUser, insertAuditTrail, }) { const { visible, context, actions } = scheduleModal; const { jobId, job, previousEvent } = context; const { refetch } = actions; const [form] = Form.useForm(); const { data: lbrHrsData } = useQuery(QUERY_LBR_HRS_BY_PK, { variables: { id: job && job.id }, skip: !job || !job.id, fetchPolicy: "network-only", nextFetchPolicy: "network-only", }); const [loading, setLoading] = useState(false); const [cancelAppointment] = useMutation(CANCEL_APPOINTMENT_BY_ID); const [insertAppointment] = useMutation(INSERT_APPOINTMENT); const [updateJobStatus] = useMutation(UPDATE_JOBS); useEffect(() => { if (job) form.resetFields(); }, [job, form]); const { t } = useTranslation(); const existingAppointments = useQuery(QUERY_APPOINTMENTS_BY_JOBID, { variables: { jobid: jobId }, fetchPolicy: "network-only", nextFetchPolicy: "network-only", skip: !visible || !!!jobId, }); useEffect(() => { if ( existingAppointments.data && existingAppointments.data.appointments.length > 0 && !existingAppointments.data.appointments[0].canceled ) { form.setFieldsValue({ color: existingAppointments.data.appointments[0].color, note: existingAppointments.data.appointments[0].note, }); } }, [existingAppointments.data, form]); const handleFinish = async (values) => { logImEXEvent("schedule_new_appointment"); setLoading(true); if (!!previousEvent) { const cancelAppt = await cancelAppointment({ variables: { appid: previousEvent }, }); if (!!cancelAppt.errors) { notification["error"]({ message: t("appointments.errors.canceling", { message: JSON.stringify(cancelAppt.errors), }), }); return; } notification["success"]({ message: t("appointments.successes.canceled"), }); } if (existingAppointments.data.appointments.length > 0) { await Promise.all( existingAppointments.data.appointments.map((app) => { return cancelAppointment({ variables: { appid: app.id }, }); }) ); } const appt = await insertAppointment({ variables: { app: { jobid: jobId, bodyshopid: bodyshop.id, start: moment(values.start), end: moment(values.start).add(bodyshop.appt_length || 60, "minutes"), color: values.color, note: values.note, created_by: currentUser.email, }, jobId: jobId, altTransport: values.alt_transport, }, }); if (!appt.errors) { insertAuditTrail({ jobid: job.id, operation: AuditTrailMapping.appointmentinsert( DateTimeFormat(values.start) ), }); } if (!!appt.errors) { notification["error"]({ message: t("appointments.errors.saving", { message: JSON.stringify(appt.errors), }), }); return; } notification["success"]({ message: t("appointments.successes.created"), }); if (jobId) { const jobUpdate = await updateJobStatus({ variables: { jobIds: [jobId], fields: { status: bodyshop.md_ro_statuses.default_scheduled, date_scheduled: new Date(), scheduled_in: values.start, scheduled_completion: values.scheduled_completion, lost_sale_reason: null, date_lost_sale: null, }, }, }); if (!!jobUpdate.errors) { notification["error"]({ message: t("appointments.errors.saving", { message: JSON.stringify(jobUpdate.errors), }), }); return; } } setLoading(false); toggleModalVisible(); if (values.notifyCustomer) { setEmailOptions({ jobid: jobId, messageOptions: { to: [values.email], replyTo: bodyshop.email, subject: TemplateList("appointment").appointment_confirmation.subject, }, template: { name: TemplateList("appointment").appointment_confirmation.key, variables: { id: appt.data.insert_appointments.returning[0].id, }, }, }); } if (refetch) refetch(); }; return ( toggleModalVisible()} onOk={() => form.submit()} width={"90%"} maskClosable={false} destroyOnClose okButtonProps={{ loading: loading, }} >
); } export default connect( mapStateToProps, mapDispatchToProps )(ScheduleJobModalContainer);