Added length of appointment to config + fixed appointments not showing in scheduling modal + added appointment confirmation template. BOD-141 BOD-149 BOD-148
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
import { Checkbox, Col, Row, Tabs } from "antd";
|
||||
import { Checkbox, Col, Row, Input, Button } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component";
|
||||
@@ -6,6 +6,7 @@ import ScheduleDayViewContainer from "../schedule-day-view/schedule-day-view.con
|
||||
import ScheduleExistingAppointmentsList from "../schedule-existing-appointments-list/schedule-existing-appointments-list.component";
|
||||
import axios from "axios";
|
||||
import { auth } from "../../firebase/firebase.utils";
|
||||
import EmailInput from "../form-items-formatted/email-form-item.component";
|
||||
|
||||
export default function ScheduleJobModalComponent({
|
||||
existingAppointments,
|
||||
@@ -37,31 +38,24 @@ export default function ScheduleJobModalComponent({
|
||||
return (
|
||||
<Row>
|
||||
<Col span={14}>
|
||||
<Tabs defaultActiveKey="1">
|
||||
<Tabs.TabPane tab="SMART Scheduling" key="auto">
|
||||
Automatic Job Selection.
|
||||
<button onClick={handleAuto}>Get dates.</button>
|
||||
</Tabs.TabPane>
|
||||
<Tabs.TabPane tab="Manual Scheduling" key="manual">
|
||||
<Row>
|
||||
Manual Job Selection Scheduled Time
|
||||
<div style={{ height: "300px" }}>
|
||||
<DateTimePicker
|
||||
value={appData.start}
|
||||
onChange={(e) => {
|
||||
setAppData({ ...appData, start: e });
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
</Row>
|
||||
</Tabs.TabPane>
|
||||
</Tabs>
|
||||
<div style={{ display: "flex", alignContent: "middle" }}>
|
||||
<strong>{t("appointments.fields.time")}</strong>
|
||||
<DateTimePicker
|
||||
value={appData.start}
|
||||
onChange={(e) => {
|
||||
setAppData({ ...appData, start: e });
|
||||
}}
|
||||
/>
|
||||
<Button onClick={handleAuto}>
|
||||
{t("appointments.actions.smartscheduling")}
|
||||
</Button>
|
||||
</div>
|
||||
|
||||
{t("appointments.labels.history")}
|
||||
<ScheduleExistingAppointmentsList
|
||||
existingAppointments={existingAppointments}
|
||||
/>
|
||||
{
|
||||
//TODO Build out notifications.
|
||||
}
|
||||
|
||||
<Checkbox
|
||||
defaultChecked={formData.notifyCustomer}
|
||||
onChange={(e) =>
|
||||
@@ -70,6 +64,11 @@ export default function ScheduleJobModalComponent({
|
||||
>
|
||||
{t("jobs.labels.appointmentconfirmation")}
|
||||
</Checkbox>
|
||||
<EmailInput
|
||||
defaultValue={formData.email}
|
||||
title={t("owner.fields.ownr_ea")}
|
||||
onChange={(e) => setFormData({ ...formData, email: e.target.value })}
|
||||
/>
|
||||
</Col>
|
||||
<Col span={10}>
|
||||
<ScheduleDayViewContainer day={appData.start} />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React, { useState } from "react";
|
||||
import React, { useState, useEffect } from "react";
|
||||
import ScheduleJobModalComponent from "./schedule-job-modal.component";
|
||||
import { useMutation, useQuery } from "@apollo/react-hooks";
|
||||
import {
|
||||
@@ -9,12 +9,13 @@ import moment from "moment";
|
||||
import { notification, Modal } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { UPDATE_JOBS } from "../../graphql/jobs.queries";
|
||||
|
||||
import { setEmailOptions } from "../../redux/email/email.actions";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import { selectSchedule } from "../../redux/modals/modals.selectors";
|
||||
import { toggleModalVisible } from "../../redux/modals/modals.actions";
|
||||
import { TemplateList } from "../../utils/TemplateConstants";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop,
|
||||
@@ -22,22 +23,37 @@ const mapStateToProps = createStructuredSelector({
|
||||
});
|
||||
const mapDispatchToProps = (dispatch) => ({
|
||||
toggleModalVisible: () => dispatch(toggleModalVisible("schedule")),
|
||||
setEmailOptions: (e) => dispatch(setEmailOptions(e)),
|
||||
});
|
||||
export function ScheduleJobModalContainer({
|
||||
scheduleModal,
|
||||
bodyshop,
|
||||
toggleModalVisible,
|
||||
setEmailOptions,
|
||||
}) {
|
||||
const { visible, context, actions } = scheduleModal;
|
||||
const { jobId } = context;
|
||||
const { jobId, job } = context;
|
||||
const { refetch } = actions;
|
||||
|
||||
const [appData, setAppData] = useState({
|
||||
start: null,
|
||||
});
|
||||
|
||||
const [insertAppointment] = useMutation(INSERT_APPOINTMENT);
|
||||
const [updateJobStatus] = useMutation(UPDATE_JOBS);
|
||||
const [formData, setFormData] = useState({ notifyCustomer: false });
|
||||
const [formData, setFormData] = useState({
|
||||
notifyCustomer: false,
|
||||
email: (job && job.ownr_ea) || "",
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
setFormData({
|
||||
notifyCustomer: !!(job && job.ownr_ea),
|
||||
email: (job && job.ownr_ea) || "",
|
||||
start: null,
|
||||
});
|
||||
}, [job, setFormData]);
|
||||
|
||||
const { t } = useTranslation();
|
||||
|
||||
const existingAppointments = useQuery(QUERY_APPOINTMENTS_BY_JOBID, {
|
||||
@@ -47,47 +63,67 @@ export function ScheduleJobModalContainer({
|
||||
});
|
||||
|
||||
//TODO Customize the amount of minutes it will add.
|
||||
const handleOk = () => {
|
||||
insertAppointment({
|
||||
const handleOk = async () => {
|
||||
const appt = await insertAppointment({
|
||||
variables: {
|
||||
app: {
|
||||
...appData,
|
||||
jobid: jobId,
|
||||
bodyshopid: bodyshop.id,
|
||||
end: moment(appData.start).add(60, "minutes"),
|
||||
end: moment(appData.start).add(bodyshop.appt_length || 60, "minutes"),
|
||||
},
|
||||
},
|
||||
})
|
||||
.then((r) => {
|
||||
updateJobStatus({
|
||||
variables: {
|
||||
jobIds: [jobId],
|
||||
fields: {
|
||||
status: bodyshop.md_ro_statuses.default_scheduled,
|
||||
date_scheduled: new Date(),
|
||||
scheduled_in: appData.start,
|
||||
},
|
||||
},
|
||||
}).then((r) => {
|
||||
notification["success"]({
|
||||
message: t("appointments.successes.created"),
|
||||
});
|
||||
});
|
||||
|
||||
if (formData.notifyCustomer) {
|
||||
//TODO Implement customer reminder on scheduling.
|
||||
alert("Chosed to notify the customer somehow!");
|
||||
}
|
||||
toggleModalVisible();
|
||||
if (refetch) refetch();
|
||||
});
|
||||
})
|
||||
.catch((error) => {
|
||||
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: appData.start,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
if (!!jobUpdate.errors) {
|
||||
notification["error"]({
|
||||
message: t("appointments.errors.saving", {
|
||||
message: error.message,
|
||||
message: JSON.stringify(jobUpdate.errors),
|
||||
}),
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
toggleModalVisible();
|
||||
if (formData.notifyCustomer) {
|
||||
setEmailOptions({
|
||||
messageOptions: {
|
||||
to: formData.email,
|
||||
replyTo: bodyshop.email,
|
||||
},
|
||||
template: {
|
||||
name: TemplateList.appointment_confirmation.key,
|
||||
variables: {
|
||||
id: appt.data.insert_appointments.returning[0].id,
|
||||
},
|
||||
},
|
||||
});
|
||||
}
|
||||
if (refetch) refetch();
|
||||
};
|
||||
|
||||
return (
|
||||
|
||||
Reference in New Issue
Block a user