Adding of generic appointments to calendar.
This commit is contained in:
@@ -0,0 +1,67 @@
|
||||
import { Checkbox, Col, DatePicker, Modal, Row, TimePicker, Input } from "antd";
|
||||
import React from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ScheduleDayViewContainer from "../schedule-day-view/schedule-day-view.container";
|
||||
|
||||
export default function ScheduleJobModalComponent({
|
||||
appData,
|
||||
setAppData,
|
||||
formData,
|
||||
setFormData,
|
||||
...props
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
//TODO: Existing appointments list only refreshes sometimes after modal close. May have to do with the container class.
|
||||
return (
|
||||
<Modal
|
||||
{...props}
|
||||
width={"80%"}
|
||||
maskClosable={false}
|
||||
destroyOnClose={true}
|
||||
okButtonProps={{ disabled: appData.start ? false : true }}
|
||||
>
|
||||
<Row>
|
||||
<Col span={14}>
|
||||
<Row>
|
||||
Manual Job Selection Scheduled Time
|
||||
<Input
|
||||
placeholder={t("appointments.fields.title")}
|
||||
onChange={e => {
|
||||
setAppData({ ...appData, title: e.target.value });
|
||||
}}
|
||||
/>
|
||||
<DatePicker
|
||||
value={appData.start}
|
||||
onChange={e => {
|
||||
setAppData({ ...appData, start: e });
|
||||
}}
|
||||
/>
|
||||
<TimePicker
|
||||
value={appData.start}
|
||||
format={"HH:mm"}
|
||||
minuteStep={15}
|
||||
onChange={e => {
|
||||
setAppData({ ...appData, start: e });
|
||||
}}
|
||||
/>
|
||||
</Row>
|
||||
|
||||
{
|
||||
//TODO: Build out notifications.
|
||||
}
|
||||
<Checkbox
|
||||
defaultChecked={formData.notifyCustomer}
|
||||
onChange={e =>
|
||||
setFormData({ ...formData, notifyCustomer: e.target.checked })
|
||||
}
|
||||
>
|
||||
{t("jobs.labels.appointmentconfirmation")}
|
||||
</Checkbox>
|
||||
</Col>
|
||||
<Col span={10}>
|
||||
<ScheduleDayViewContainer day={appData.start} />
|
||||
</Col>
|
||||
</Row>
|
||||
</Modal>
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
import { notification } from "antd";
|
||||
import moment from "moment";
|
||||
import React, { useState } from "react";
|
||||
import { useMutation } from "react-apollo";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { connect } from "react-redux";
|
||||
import { createStructuredSelector } from "reselect";
|
||||
import { INSERT_APPOINTMENT } from "../../graphql/appointments.queries";
|
||||
import { selectBodyshop } from "../../redux/user/user.selectors";
|
||||
import ScheduleAppointmentModalComponent from "./schedule-appointment-modal.component";
|
||||
|
||||
const mapStateToProps = createStructuredSelector({
|
||||
bodyshop: selectBodyshop
|
||||
});
|
||||
|
||||
export default connect(
|
||||
mapStateToProps,
|
||||
null
|
||||
)(function ScheduleAppointmentModalContainer({
|
||||
scheduleModalState,
|
||||
jobId,
|
||||
bodyshop,
|
||||
refetch
|
||||
}) {
|
||||
const [scheduleModalVisible, setscheduleModalVisible] = scheduleModalState;
|
||||
const [appData, setAppData] = useState({
|
||||
jobid: jobId,
|
||||
bodyshopid: bodyshop.id,
|
||||
isintake: false,
|
||||
start: null
|
||||
});
|
||||
const [insertAppointment] = useMutation(INSERT_APPOINTMENT);
|
||||
const [formData, setFormData] = useState({ notifyCustomer: false });
|
||||
const { t } = useTranslation();
|
||||
|
||||
return (
|
||||
<ScheduleAppointmentModalComponent
|
||||
appData={appData}
|
||||
setAppData={setAppData}
|
||||
formData={formData}
|
||||
setFormData={setFormData}
|
||||
//Spreadable Modal Props
|
||||
visible={scheduleModalVisible}
|
||||
onCancel={() => setscheduleModalVisible(false)}
|
||||
onOk={() => {
|
||||
//TODO: Customize the amount of minutes it will add.
|
||||
insertAppointment({
|
||||
variables: {
|
||||
app: { ...appData, end: moment(appData.start).add(60, "minutes") }
|
||||
}
|
||||
})
|
||||
.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!");
|
||||
}
|
||||
setscheduleModalVisible(false);
|
||||
if (refetch) refetch();
|
||||
})
|
||||
.catch(error => {
|
||||
notification["error"]({
|
||||
message: t("appointments.errors.saving", {
|
||||
message: error.message
|
||||
})
|
||||
});
|
||||
});
|
||||
}}
|
||||
/>
|
||||
);
|
||||
});
|
||||
@@ -1,13 +1,46 @@
|
||||
import React from "react";
|
||||
//import "react-big-calendar/lib/css/react-big-calendar.css";
|
||||
import ScheduleCalendarWrapperComponent from "../schedule-calendar-wrapper/scheduler-calendar-wrapper.component";
|
||||
import { Button, Icon } from "antd";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import ScheduleAppointmentModalContainer from "../schedule-appointment-modal/schedule-appointment-modal.container";
|
||||
|
||||
export default function ScheduleCalendarComponent({
|
||||
data,
|
||||
refetch,
|
||||
scheduleModalState
|
||||
}) {
|
||||
const { t } = useTranslation();
|
||||
|
||||
export default function ScheduleCalendarComponent({ data, refetch }) {
|
||||
return (
|
||||
<ScheduleCalendarWrapperComponent
|
||||
data={data}
|
||||
defaultView="week"
|
||||
refetch={refetch}
|
||||
/>
|
||||
<div>
|
||||
<Button
|
||||
onClick={() => {
|
||||
refetch();
|
||||
}}
|
||||
>
|
||||
<Icon type="sync" />
|
||||
</Button>
|
||||
|
||||
<Button
|
||||
onClick={() => {
|
||||
scheduleModalState[1](true);
|
||||
}}
|
||||
>
|
||||
{t("appointments.actions.new")}
|
||||
</Button>
|
||||
|
||||
<ScheduleAppointmentModalContainer
|
||||
scheduleModalState={scheduleModalState}
|
||||
jobId={null}
|
||||
refetch={refetch}
|
||||
/>
|
||||
|
||||
<ScheduleCalendarWrapperComponent
|
||||
data={data}
|
||||
defaultView="week"
|
||||
refetch={refetch}
|
||||
/>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import React from "react";
|
||||
import React, { useState } from "react";
|
||||
import { useQuery } from "react-apollo";
|
||||
import ScheduleCalendarComponent from "./schedule-calendar.component";
|
||||
import { QUERY_ALL_ACTIVE_APPOINTMENTS } from "../../graphql/appointments.queries";
|
||||
@@ -12,6 +12,7 @@ export default function ScheduleCalendarContainer() {
|
||||
fetchPolicy: "network-only"
|
||||
}
|
||||
);
|
||||
const scheduleModalState = useState(false);
|
||||
|
||||
if (loading) return <LoadingSpinner />;
|
||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
||||
@@ -27,6 +28,7 @@ export default function ScheduleCalendarContainer() {
|
||||
|
||||
return (
|
||||
<ScheduleCalendarComponent
|
||||
scheduleModalState={scheduleModalState}
|
||||
refetch={refetch}
|
||||
data={data ? normalizedData : null}
|
||||
/>
|
||||
|
||||
@@ -9,22 +9,53 @@ export default function ScheduleEventComponent({ event, handleCancel }) {
|
||||
const { t } = useTranslation();
|
||||
const popoverContent = (
|
||||
<div>
|
||||
<div>{`${t("jobs.fields.ro_number")}: ${event.job.ro_number}`}</div>
|
||||
<div>
|
||||
{t("jobs.fields.clm_total")}:
|
||||
<CurrencyFormatter>{event.job.clm_total}</CurrencyFormatter>
|
||||
</div>
|
||||
<div>{`${t("jobs.fields.clm_no")}: ${event.job.clm_no}`}</div>
|
||||
<div>
|
||||
{t("jobs.fields.ownr_ea")}:{event.job.ownr_ea}
|
||||
</div>
|
||||
<div>
|
||||
{t("jobs.fields.ownr_ph1")}:
|
||||
<PhoneFormatter>{event.job.ownr_ph1}</PhoneFormatter>
|
||||
</div>
|
||||
<Link to={`/manage/jobs/${event.job.id}`}>
|
||||
<Button>{t("appointments.actions.viewjob")}</Button>
|
||||
</Link>
|
||||
{!event.isintake ? (
|
||||
<strong>{event.title}</strong>
|
||||
) : (
|
||||
<div>
|
||||
<strong>{`${(event.job && event.job.ownr_fn) || ""} ${(event.job &&
|
||||
event.job.ownr_ln) ||
|
||||
""}`}</strong>
|
||||
<span style={{ margin: 4 }}>
|
||||
{`${(event.job && event.job.vehicle.v_model_yr) ||
|
||||
""} ${(event.job && event.job.vehicle.v_make_desc) ||
|
||||
""} ${(event.job && event.job.vehicle.v_model_desc) || ""}`}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
{event.job ? (
|
||||
<div>
|
||||
<div>{`${t("jobs.fields.ro_number")}: ${(event.job &&
|
||||
event.job.ro_number) ||
|
||||
""}`}</div>
|
||||
<div>
|
||||
{t("jobs.fields.clm_total")}:
|
||||
<CurrencyFormatter>
|
||||
{(event.job && event.job.clm_total) || ""}
|
||||
</CurrencyFormatter>
|
||||
</div>
|
||||
<div>{`${t("jobs.fields.clm_no")}: ${(event.job &&
|
||||
event.job.clm_no) ||
|
||||
""}`}</div>
|
||||
<div>
|
||||
{t("jobs.fields.ownr_ea")}:{(event.job && event.job.ownr_ea) || ""}
|
||||
</div>
|
||||
<div>
|
||||
{t("jobs.fields.ownr_ph1")}:
|
||||
<PhoneFormatter>
|
||||
{(event.job && event.job.ownr_ph1) || ""}
|
||||
</PhoneFormatter>
|
||||
</div>
|
||||
</div>
|
||||
) : null}
|
||||
{
|
||||
//TODO Add phone 1 MessagingActionTypes.
|
||||
}
|
||||
{event.job ? (
|
||||
<Link to={`/manage/jobs/${event.job && event.job.id}`}>
|
||||
<Button>{t("appointments.actions.viewjob")}</Button>
|
||||
</Link>
|
||||
) : null}
|
||||
<Button onClick={() => handleCancel(event.id)}>
|
||||
{t("appointments.actions.cancel")}
|
||||
</Button>
|
||||
@@ -34,24 +65,36 @@ export default function ScheduleEventComponent({ event, handleCancel }) {
|
||||
}
|
||||
{t("appointments.actions.reschedule")}
|
||||
</Button>
|
||||
<Button>
|
||||
{
|
||||
//TODO: Add intake func.
|
||||
}
|
||||
{t("appointments.actions.intake")}
|
||||
</Button>
|
||||
{event.isintake ? (
|
||||
<Button>
|
||||
{
|
||||
//TODO: Add intake func.
|
||||
}
|
||||
{t("appointments.actions.intake")}
|
||||
</Button>
|
||||
) : null}
|
||||
</div>
|
||||
);
|
||||
|
||||
return (
|
||||
<Popover content={popoverContent}>
|
||||
<div>
|
||||
<strong>{`${event.job.ownr_fn || ""} ${event.job.ownr_ln ||
|
||||
""}`}</strong>
|
||||
<span style={{ margin: 4 }}>
|
||||
{`${event.job.vehicle.v_model_yr || ""} ${event.job.vehicle
|
||||
.v_make_desc || ""} ${event.job.vehicle.v_model_desc || ""}`}
|
||||
</span>
|
||||
{event.isintake ? (
|
||||
<div>
|
||||
<strong>{`${(event.job && event.job.ownr_fn) || ""} ${(event.job &&
|
||||
event.job.ownr_ln) ||
|
||||
""}`}</strong>
|
||||
<span style={{ margin: 4 }}>
|
||||
{`${(event.job && event.job.vehicle.v_model_yr) ||
|
||||
""} ${(event.job && event.job.vehicle.v_make_desc) ||
|
||||
""} ${(event.job && event.job.vehicle.v_model_desc) || ""}`}
|
||||
</span>
|
||||
</div>
|
||||
) : (
|
||||
<div>
|
||||
<strong>{`${event.title || ""}`}</strong>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</Popover>
|
||||
);
|
||||
|
||||
@@ -28,12 +28,16 @@ export default connect(
|
||||
refetch
|
||||
}) {
|
||||
const [scheduleModalVisible, setscheduleModalVisible] = scheduleModalState;
|
||||
const [appData, setAppData] = useState({ jobid: jobId, start: null });
|
||||
const [appData, setAppData] = useState({
|
||||
jobid: jobId,
|
||||
start: null,
|
||||
bodyshopid: bodyshop.id
|
||||
});
|
||||
const [insertAppointment] = useMutation(INSERT_APPOINTMENT);
|
||||
const [updateJobStatus] = useMutation(UPDATE_JOB_STATUS, {
|
||||
variables: {
|
||||
jobId: jobId,
|
||||
status: bodyshop.md_ro_statuses.default_scheduled
|
||||
status: bodyshop.md_ro_statuses.default_scheduled
|
||||
}
|
||||
});
|
||||
const [formData, setFormData] = useState({ notifyCustomer: false });
|
||||
|
||||
Reference in New Issue
Block a user