import { AlertFilled } from "@ant-design/icons";
import { useLazyQuery, useMutation } from "@apollo/client";
import { Button, Divider, Dropdown, Form, Input, Popover, Select, Space } from "antd";
import parsePhoneNumber from "libphonenumber-js";
import queryString from "query-string";
import { useState } from "react";
import { useTranslation } from "react-i18next";
import { connect } from "react-redux";
import { Link, useLocation, useNavigate } from "react-router-dom";
import { createStructuredSelector } from "reselect";
import { useNotification } from "../../contexts/Notifications/notificationContext.jsx";
import { useSocket } from "../../contexts/SocketIO/useSocket.js";
import { UPDATE_APPOINTMENT } from "../../graphql/appointments.queries";
import { GET_JOB_BY_PK_QUICK_INTAKE, JOB_PRODUCTION_TOGGLE } from "../../graphql/jobs.queries";
import { insertAuditTrail } from "../../redux/application/application.actions";
import { openChatByPhone, setMessage } from "../../redux/messaging/messaging.actions";
import { setModalContext } from "../../redux/modals/modals.actions";
import { selectBodyshop } from "../../redux/user/user.selectors";
import AuditTrailMapping from "../../utils/AuditTrailMappings";
import CurrencyFormatter from "../../utils/CurrencyFormatter";
import { DateTimeFormatterFunction } from "../../utils/DateFormatter";
import dayjs from "../../utils/day";
import { GenerateDocument } from "../../utils/RenderTemplate";
import { TemplateList } from "../../utils/TemplateConstants";
import ChatOpenButton from "../chat-open-button/chat-open-button.component";
import DataLabel from "../data-label/data-label.component";
import FormDateTimePickerComponent from "../form-date-time-picker/form-date-time-picker.component";
import OwnerNameDisplay from "../owner-name-display/owner-name-display.component";
import ProductionListColumnComment from "../production-list-columns/production-list-columns.comment.component";
import ScheduleManualEvent from "../schedule-manual-event/schedule-manual-event.component";
import { HasFeatureAccess } from "./../feature-wrapper/feature-wrapper.component";
import ScheduleAtChange from "./job-at-change.component";
import ScheduleEventColor from "./schedule-event.color.component";
import ScheduleEventNote from "./schedule-event.note.component";
const mapStateToProps = createStructuredSelector({
bodyshop: selectBodyshop
});
const mapDispatchToProps = (dispatch) => ({
setScheduleContext: (context) => dispatch(setModalContext({ context: context, modal: "schedule" })),
openChatByPhone: (phone) => dispatch(openChatByPhone(phone)),
setMessage: (text) => dispatch(setMessage(text)),
insertAuditTrail: ({ jobid, operation }) => dispatch(insertAuditTrail({ jobid, operation }))
});
export function ScheduleEventComponent({
bodyshop,
setMessage,
openChatByPhone,
event,
refetch,
handleCancel,
setScheduleContext,
insertAuditTrail
}) {
const { t } = useTranslation();
const [open, setOpen] = useState(false);
const history = useNavigate();
const searchParams = queryString.parse(useLocation().search);
const [updateAppointment] = useMutation(UPDATE_APPOINTMENT);
const [mutationUpdateJob] = useMutation(JOB_PRODUCTION_TOGGLE);
const [title, setTitle] = useState(event.title);
const { socket } = useSocket();
const notification = useNotification();
const [form] = Form.useForm();
const [popOverVisible, setPopOverVisible] = useState(false);
const [getJobDetails] = useLazyQuery(GET_JOB_BY_PK_QUICK_INTAKE, {
variables: { id: event.job?.id },
onCompleted: (data) => {
if (data?.jobs_by_pk) {
const totalHours =
(data.jobs_by_pk.labhrs?.aggregate?.sum?.mod_lb_hrs || 0) +
(data.jobs_by_pk.larhrs?.aggregate?.sum?.mod_lb_hrs || 0);
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
? data.jobs_by_pk.scheduled_completion
: totalHours && bodyshop.ss_configuration.nobusinessdays
? dayjs().businessDaysAdd(totalHours / (bodyshop.target_touchtime || 1), "day")
: dayjs().add(totalHours / (bodyshop.target_touchtime || 1), "day"),
scheduled_delivery: data.jobs_by_pk.scheduled_delivery
});
}
},
fetchPolicy: "network-only"
});
const blockContent = (
setTitle(e.currentTarget.value)}
onBlur={async () => {
await updateAppointment({
variables: {
appid: event.id,
app: {
title: title
}
},
optimisticResponse: {
update_appointments: {
__typename: "appointments_mutation_response",
returning: [
{
...event,
title: title,
__typename: "appointments"
}
]
}
}
});
}}
/>
);
const handleConvert = async (values) => {
const res = await mutationUpdateJob({
variables: {
jobId: event.job.id,
job: {
...values,
status: bodyshop.md_ro_statuses.default_arrived,
inproduction: true
}
}
});
if (!res.errors) {
notification["success"]({
message: t("jobs.successes.converted")
});
insertAuditTrail({
jobid: event.job.id,
operation: AuditTrailMapping.jobintake(
res.data.update_jobs.returning[0].status,
DateTimeFormatterFunction(values.scheduled_completion)
)
});
setPopOverVisible(false);
refetch();
}
};
const popMenu = (
e.stopPropagation()}>
);
const popoverContent = (
{!event.isintake ? (
{event.title}
) : (
{`${(event.job && event.job.v_model_yr) || ""} ${
(event.job && event.job.v_make_desc) || ""
} ${(event.job && event.job.v_model_desc) || ""}`}
)}
{event.job ? (
{(event.job && event.job.ro_number) || ""}
{(event.job && event.job.clm_total) || ""}
{(event.job && event.job.ins_co_nm) || ""}
{(event.job && event.job.clm_no) || ""}
{(event.job && event.job.ownr_ea) || ""}
{(event.job && event.job.loss_of_use) || ""}
{(event.job && event.job.alt_transport) || ""}
) : (
{event.note || ""}
)}
{event.job ? (
) : null}
{event.job ? (
) : null}
{event.job ? (
{
const Template = TemplateList("job").appointment_reminder;
GenerateDocument(
{
name: Template.key,
variables: { id: event.job.id }
},
{
to: event.job && event.job.ownr_ea,
subject: Template.subject
},
"e",
event.job && event.job.id,
notification
);
}
},
{
key: "sms",
label: t("general.labels.sms"),
disabled: event.arrived || !bodyshop.messagingservicesid,
onClick: () => {
const p = parsePhoneNumber(event.job.ownr_ph1, "CA");
if (p && p.isValid()) {
openChatByPhone({
phone_num: p.formatInternational(),
jobid: event.job.id,
socket
});
setMessage(
t("appointments.labels.reminder", {
shopname: bodyshop.shopname,
date: dayjs(event.start).format("MM/DD/YYYY"),
time: dayjs(event.start).format("HH:mm a")
})
);
setOpen(false);
} else {
notification["error"]({
message: t("messaging.error.invalidphone")
});
}
}
}
]
}}
>
) : null}
{event.arrived ? (
) : (
{
handleCancel({ id: event.id, lost_sale_reason });
}}
>
}
>
)}
{event.isintake ? (
) : (
)}
{event.job &&
(HasFeatureAccess({ featureName: "checklist", bodyshop }) ? (
) : (
{
if (event.job?.id) {
e.stopPropagation();
getJobDetails();
}
}}
getPopupContainer={(trigger) => trigger.parentNode}
trigger="click"
>
))}
);
// Adjust event color for dark mode if needed
const getEventBackground = () => {
if (event?.block) {
return "var(--event-block-bg)"; // Use a specific color for dark mode
}
const baseColor = event.color && event.color.hex ? event.color.hex : event.color || "var(--event-bg-fallback)";
// Optionally adjust color for dark mode (e.g., lighten if too dark)
return baseColor;
};
const RegularEvent = event.isintake ? (
{event.note && }
{`${event.job.ro_number || t("general.labels.na")}`}
{`${(event.job && event.job.v_model_yr) || ""} ${
(event.job && event.job.v_make_desc) || ""
} ${(event.job && event.job.v_model_desc) || ""}`}
{`(${(event.job && event.job.labhrs.aggregate.sum.mod_lb_hrs) || "0"} / ${
(event.job && event.job.larhrs.aggregate.sum.mod_lb_hrs) || "0"
})`}
{event.job && event.job.alt_transport && {event.job.alt_transport}
}
{event?.job?.comment && `C: ${event.job.comment}`}
) : (
{`${event.title || ""}`}
);
return (
!event.vacation && setOpen(vis)}
trigger="click"
content={event.block ? blockContent : popoverContent}
style={{
height: "100%",
width: "100%",
backgroundColor: getEventBackground()
}}
>
{RegularEvent}
);
}
export default connect(mapStateToProps, mapDispatchToProps)(ScheduleEventComponent);