diff --git a/client/src/components/schedule-calendar-wrapper/schedule-calendar.styles.scss b/client/src/components/schedule-calendar-wrapper/schedule-calendar.styles.scss index 699f4fd54..8b390f7c5 100644 --- a/client/src/components/schedule-calendar-wrapper/schedule-calendar.styles.scss +++ b/client/src/components/schedule-calendar-wrapper/schedule-calendar.styles.scss @@ -4,3 +4,7 @@ box-sizing: unset !important; min-height: unset !important; } + +.imex-event-arrived { + background-color: green; +} diff --git a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx index 3a57864f4..6dfa12634 100644 --- a/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx +++ b/client/src/components/schedule-calendar-wrapper/scheduler-calendar-wrapper.component.jsx @@ -2,14 +2,20 @@ import moment from "moment"; import queryString from "query-string"; import React from "react"; import { Calendar, momentLocalizer } from "react-big-calendar"; +import { connect } from "react-redux"; import { useHistory, useLocation } from "react-router-dom"; +import { createStructuredSelector } from "reselect"; +import { selectBodyshop } from "../../redux/user/user.selectors"; import Event from "../schedule-event/schedule-event.container"; import HeaderComponent from "./schedule-calendar-header.component"; import "./schedule-calendar.styles.scss"; +const mapStateToProps = createStructuredSelector({ + bodyshop: selectBodyshop, +}); const localizer = momentLocalizer(moment); - -export default function ScheduleCalendarWrapperComponent({ +export function ScheduleCalendarWrapperComponent({ + bodyshop, data, refetch, defaultView, @@ -19,6 +25,21 @@ export default function ScheduleCalendarWrapperComponent({ }) { const search = queryString.parse(useLocation().search); const history = useHistory(); + + const handleEventPropStyles = (event, start, end, isSelected) => { + // if (!!!bodyshop.ssbuckets) { + // return {}; + // } + // const defaultEventColor = "#3174ad"; + // const jobHrs = result.jobs_by_pk.jobhrs.aggregate.sum.mod_lb_hrs; + // const JobBucket = bodyshop.ssbuckets.filter( + // (bucket) => + // bucket.gte <= jobHrs && (!!bucket.lt ? bucket.lt > jobHrs : true) + // )[0]; + + return { className: event.arrived ? "imex-event-arrived" : "" }; + }; + return ( Event({ event: e.event, refetch: refetch }), header: HeaderComponent, @@ -49,3 +71,5 @@ export default function ScheduleCalendarWrapperComponent({ /> ); } + +export default connect(mapStateToProps, null)(ScheduleCalendarWrapperComponent); diff --git a/client/src/components/schedule-event/schedule-event.component.jsx b/client/src/components/schedule-event/schedule-event.component.jsx index ebe32e66d..ac91bdc1e 100644 --- a/client/src/components/schedule-event/schedule-event.component.jsx +++ b/client/src/components/schedule-event/schedule-event.component.jsx @@ -106,9 +106,9 @@ export function ScheduleEventComponent({ const RegularEvent = event.isintake ? (
- {`${ - (event.job && event.job.ownr_fn) || "" - } ${(event.job && event.job.ownr_ln) || ""}`} + {`${(event.job && event.job.ownr_fn) || ""} ${ + (event.job && event.job.ownr_ln) || "" + }`}
{`${(event.job && event.job.v_model_yr) || ""} ${ (event.job && event.job.v_make_desc) || "" diff --git a/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx b/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx index 336ad1213..0778319a8 100644 --- a/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx +++ b/client/src/components/schedule-job-modal/schedule-job-modal.component.jsx @@ -3,11 +3,12 @@ import axios from "axios"; import React, { useState } from "react"; import { useTranslation } from "react-i18next"; import { auth } from "../../firebase/firebase.utils"; +import { DateFormatter } from "../../utils/DateFormatter"; import DateTimePicker from "../form-date-time-picker/form-date-time-picker.component"; import EmailInput from "../form-items-formatted/email-form-item.component"; import ScheduleDayViewContainer from "../schedule-day-view/schedule-day-view.container"; import ScheduleExistingAppointmentsList from "../schedule-existing-appointments-list/schedule-existing-appointments-list.component"; -import { DateTimeFormatter } from "../../utils/DateFormatter"; +import moment from "moment"; export default function ScheduleJobModalComponent({ existingAppointments, @@ -41,7 +42,7 @@ export default function ScheduleJobModalComponent({ return ( -
+
{t("appointments.fields.time")}
-
+
{appData.smartDates.map((d, idx) => ( ))}
@@ -75,7 +81,8 @@ export default function ScheduleJobModalComponent({ defaultChecked={appData.notifyCustomer} onChange={(e) => setAppData({ ...appData, notifyCustomer: e.target.checked }) - }> + } + > {t("jobs.labels.appointmentconfirmation")} + }} + > { jobId: jobId, }); - const { appointments } = result; + const { appointments, productionview } = result; const { ssbuckets } = result.jobs_by_pk.bodyshop; - const jobhrs = result.jobs_by_pk.jobhrs.aggregate.sum.mod_lb_hrs; + const jobHrs = result.jobs_by_pk.jobhrs.aggregate.sum.mod_lb_hrs; - const JobClassification = ssbuckets.filter( - (b) => b.gte <= jobhrs && b.lt > jobhrs - ); - //Create a matrix of load bucket + const JobBucket = ssbuckets.filter( + (bucket) => + bucket.gte <= jobHrs && (!!bucket.lt ? bucket.lt > jobHrs : true) + )[0]; const bucketMatrix = {}; - //Get latest date + add 5 days. - + //Get latest date + add 5 days to allow for back end adding.. const totalMatrixDays = moment - .max(appointments.map((a) => moment(a.start))) + .max([ + ...appointments.map((a) => moment(a.start)), + ...productionview + .map((p) => moment(p.scheduled_completion)) + .filter((p) => p.isValid()), + ]) .add("5", "days") .diff(moment(), "days"); - for (var i = 0; i++; i < totalMatrixDays) { + //Initialize the bucket matrix + for (i = 0; i < totalMatrixDays; i++) { const theDate = moment().add(i, "days").toISOString().substr(0, 10); - console.log("theDate", theDate); - ssbuckets.forEach((bucket) => { - bucketMatrix[theDate][bucket.id] = { in: 0, out: 0 }; - }); + //Only need to create a matrix for jobs of the same bucket. + bucketMatrix[theDate] = { in: 0, out: 0 }; + + // ssbuckets.forEach((bucket) => { + // bucketMatrix[theDate] = { + // ...bucketMatrix[theDate], + // [bucket.id]: { in: 0, out: 0 }, + // }; + // }); } + //Populate the jobs scheduled to come in. appointments.forEach((appointment) => { - //Get the day of the appointment. - const appDate = moment(appointment.start).toISOString().substr(0, 10); - !!bucketMatrix[appDate] ? {} : {}; + const jobHrs = + appointment.job.joblines_aggregate.aggregate.sum.mod_lb_hrs; + //Is the job in the same bucket? + const appointmentBucket = ssbuckets.filter( + (bucket) => + bucket.gte <= jobHrs && (!!bucket.lt ? bucket.lt > jobHrs : true) + )[0]; + if (appointmentBucket.id === JobBucket.id) { + //Theyre the same classification. Add it to the matrix. + const appDate = moment(appointment.start).toISOString().substr(0, 10); + bucketMatrix[appDate] = { + ...bucketMatrix[appDate], + in: bucketMatrix[appDate].in + 1, + }; + } }); - //Calculate the load for the shop looking forward. + //Populate the jobs that are leaving today. + const todayIsoString = moment().toISOString().substr(0, 10); + productionview.forEach((pjob) => { + const jobHrs = pjob.larhrs + pjob.labhrs; + //Is the job in the same bucket? + const pjobBucket = ssbuckets.filter( + (bucket) => + bucket.gte <= jobHrs && (!!bucket.lt ? bucket.lt > jobHrs : true) + )[0]; + if (pjobBucket.id === JobBucket.id) { + //Theyre the same classification. Add it to the matrix. + const compDate = moment(pjob.scheduled_completion); + //Is the schedule completion behind today? If so, use today as it. + let dateToUse; + dateToUse = compDate.isValid() + ? moment().diff(compDate, "days") <= 0 + ? compDate.toISOString().substr(0, 10) + : todayIsoString + : todayIsoString; + + bucketMatrix[dateToUse] = { + ...bucketMatrix[dateToUse], + out: bucketMatrix[dateToUse].out + 1, + }; + } + }); + + //Propose the first 5 dates where we are below target. const possibleDates = []; + const bucketMatrixKeys = Object.keys(bucketMatrix); + bucketMatrixKeys.forEach((bmkey) => { + if (JobBucket.target > bucketMatrix[bmkey].in - bucketMatrix[bmkey].out) + possibleDates.push(new Date(bmkey).toISOString().substr(0, 10)); + }); //Temp - possibleDates.push(new Date()); - possibleDates.push(new Date()); - possibleDates.push(new Date()); - possibleDates.push(new Date()); - possibleDates.push(new Date()); + // possibleDates.push(new Date()); + // possibleDates.push(new Date()); + // possibleDates.push(new Date()); + // possibleDates.push(new Date()); + // possibleDates.push(new Date()); //Get a list of upcoming appointments //Get the config for each day