BOD-84 Load calculates for this week. Bug exists going past current week.
This commit is contained in:
@@ -4,5 +4,5 @@ import "./loading-skeleton.styles.scss";
|
|||||||
import { Skeleton } from "antd";
|
import { Skeleton } from "antd";
|
||||||
|
|
||||||
export default function LoadingSkeleton(props) {
|
export default function LoadingSkeleton(props) {
|
||||||
return <Skeleton {...props} className="loading-skeleton" active />;
|
return <Skeleton {...props} className='loading-skeleton' active />;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,62 @@
|
|||||||
|
import React from "react";
|
||||||
|
import { connect } from "react-redux";
|
||||||
|
import { createStructuredSelector } from "reselect";
|
||||||
|
import {
|
||||||
|
selectScheduleLoad,
|
||||||
|
selectScheduleLoadCalculating,
|
||||||
|
} from "../../redux/application/application.selectors";
|
||||||
|
import LoadingSkeleton from "../loading-skeleton/loading-skeleton.component";
|
||||||
|
import { Progress } from "antd";
|
||||||
|
import { MdCallReceived, MdCallMissedOutgoing } from "react-icons/md";
|
||||||
|
import Icon from "@ant-design/icons";
|
||||||
|
const ShopTargetHrs = 100;
|
||||||
|
|
||||||
|
const mapStateToProps = createStructuredSelector({
|
||||||
|
//currentUser: selectCurrentUser
|
||||||
|
load: selectScheduleLoad,
|
||||||
|
calculating: selectScheduleLoadCalculating,
|
||||||
|
});
|
||||||
|
|
||||||
|
const mapDispatchToProps = (dispatch) => ({
|
||||||
|
//setUserLanguage: language => dispatch(setUserLanguage(language))
|
||||||
|
});
|
||||||
|
|
||||||
|
export function ScheduleCalendarHeaderComponent({
|
||||||
|
label,
|
||||||
|
date,
|
||||||
|
load,
|
||||||
|
calculating,
|
||||||
|
...otherProps
|
||||||
|
}) {
|
||||||
|
const loadData = load[date.toISOString().substr(0, 10)];
|
||||||
|
|
||||||
|
const LoadComponent = loadData ? (
|
||||||
|
<div>
|
||||||
|
<Progress
|
||||||
|
percent={((loadData.expectedLoad || 0) / ShopTargetHrs) * 100}
|
||||||
|
/>
|
||||||
|
|
||||||
|
<div>
|
||||||
|
<Icon component={MdCallReceived} />
|
||||||
|
{(loadData.hoursIn || 0) && loadData.hoursIn.toFixed(2)}
|
||||||
|
<Icon component={MdCallMissedOutgoing} />
|
||||||
|
{(loadData.hoursOut || 0) && loadData.hoursOut.toFixed(2)}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
) : null;
|
||||||
|
|
||||||
|
return (
|
||||||
|
<div>
|
||||||
|
{label}
|
||||||
|
{calculating || JSON.stringify(load) === "{}" ? (
|
||||||
|
<LoadingSkeleton />
|
||||||
|
) : (
|
||||||
|
LoadComponent
|
||||||
|
)}
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
export default connect(
|
||||||
|
mapStateToProps,
|
||||||
|
mapDispatchToProps
|
||||||
|
)(ScheduleCalendarHeaderComponent);
|
||||||
@@ -1 +1,6 @@
|
|||||||
@import 'react-big-calendar/lib/sass/styles';
|
@import "react-big-calendar/lib/sass/styles";
|
||||||
|
|
||||||
|
.rbc-time-view .rbc-row {
|
||||||
|
box-sizing: unset !important;
|
||||||
|
min-height: unset !important;
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { Progress } from "antd";
|
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import queryString from "query-string";
|
import queryString from "query-string";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { Calendar, momentLocalizer } from "react-big-calendar";
|
import { Calendar, momentLocalizer } from "react-big-calendar";
|
||||||
import { useHistory, useLocation } from "react-router-dom";
|
import { useHistory, useLocation } from "react-router-dom";
|
||||||
import Event from "../schedule-event/schedule-event.container";
|
import Event from "../schedule-event/schedule-event.container";
|
||||||
|
import HeaderComponent from "./schedule-calendar-header.component";
|
||||||
//import "react-big-calendar/lib/css/react-big-calendar.css";
|
//import "react-big-calendar/lib/css/react-big-calendar.css";
|
||||||
import "./schedule-calendar.styles.scss";
|
import "./schedule-calendar.styles.scss";
|
||||||
|
|
||||||
@@ -37,21 +37,14 @@ export default function ScheduleCalendarWrapperComponent({
|
|||||||
history.push({ search: queryString.stringify(search) });
|
history.push({ search: queryString.stringify(search) });
|
||||||
}}
|
}}
|
||||||
step={30}
|
step={30}
|
||||||
|
timeslots={1}
|
||||||
showMultiDayTimes
|
showMultiDayTimes
|
||||||
localizer={localizer}
|
localizer={localizer}
|
||||||
min={new Date("2020-01-01T06:00:00")} //TODO Read from business settings.
|
min={new Date("2020-01-01T06:00:00")} //TODO Read from business settings.
|
||||||
max={new Date("2020-01-01T20:00:00")}
|
max={new Date("2020-01-01T20:00:00")}
|
||||||
components={{
|
components={{
|
||||||
event: (e) => Event({ event: e.event, refetch: refetch }),
|
event: (e) => Event({ event: e.event, refetch: refetch }),
|
||||||
header: (props) => {
|
header: HeaderComponent,
|
||||||
return (
|
|
||||||
<span>
|
|
||||||
<div>{props.label}</div>
|
|
||||||
<Progress style={{ flex: "1" }} percent={77} showInfo={false} />
|
|
||||||
</span>
|
|
||||||
);
|
|
||||||
},
|
|
||||||
//dateCellWrapper: DateCellWrapper,
|
|
||||||
}}
|
}}
|
||||||
{...otherProps}
|
{...otherProps}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export function ScheduleCalendarContainer({ calculateScheduleLoad }) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
if (loading) return <LoadingSpinner />;
|
if (loading) return <LoadingSpinner />;
|
||||||
if (error) return <AlertComponent message={error.message} type="error" />;
|
if (error) return <AlertComponent message={error.message} type='error' />;
|
||||||
let normalizedData = data.appointments.map((e) => {
|
let normalizedData = data.appointments.map((e) => {
|
||||||
//Required becuase Hasura returns a string instead of a date object.
|
//Required becuase Hasura returns a string instead of a date object.
|
||||||
return Object.assign(
|
return Object.assign(
|
||||||
@@ -42,29 +42,13 @@ export function ScheduleCalendarContainer({ calculateScheduleLoad }) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("ScheduleCalendarContainer -> normalizedData", normalizedData);
|
calculateScheduleLoad(range.end);
|
||||||
normalizedData.push({
|
|
||||||
id: 1,
|
|
||||||
title: "All day event",
|
|
||||||
allDay: true,
|
|
||||||
isintake: false,
|
|
||||||
start: new Date(),
|
|
||||||
end: new Date(),
|
|
||||||
});
|
|
||||||
return (
|
return (
|
||||||
<span>
|
<ScheduleCalendarComponent
|
||||||
<button
|
refetch={refetch}
|
||||||
onClick={() => {
|
data={data ? normalizedData : null}
|
||||||
calculateScheduleLoad(range.end);
|
/>
|
||||||
}}
|
|
||||||
>
|
|
||||||
Calc Load
|
|
||||||
</button>
|
|
||||||
<ScheduleCalendarComponent
|
|
||||||
refetch={refetch}
|
|
||||||
data={data ? normalizedData : null}
|
|
||||||
/>
|
|
||||||
</span>
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
export default connect(
|
export default connect(
|
||||||
|
|||||||
@@ -1,18 +0,0 @@
|
|||||||
import React from "react";
|
|
||||||
|
|
||||||
export default function ScheduleDateCellWrapper(dateCellWrapperProps) {
|
|
||||||
// Show 'click me' text in arbitrary places by using the range prop
|
|
||||||
|
|
||||||
const style = {
|
|
||||||
display: "flex",
|
|
||||||
flex: 1,
|
|
||||||
borderLeft: "1px solid #DDD",
|
|
||||||
backgroundColor: "#fff",
|
|
||||||
};
|
|
||||||
return (
|
|
||||||
<div style={style}>
|
|
||||||
PLACEHOLDER:DATA
|
|
||||||
{dateCellWrapperProps.children}
|
|
||||||
</div>
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@@ -18,3 +18,13 @@ export const calculateScheduleLoad = (rangeEnd) => ({
|
|||||||
type: ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD,
|
type: ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD,
|
||||||
payload: rangeEnd,
|
payload: rangeEnd,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
export const scheduleLoadSuccess = (load) => ({
|
||||||
|
type: ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD_SUCCESS,
|
||||||
|
payload: load,
|
||||||
|
});
|
||||||
|
|
||||||
|
export const scheduleLoadFailure = (error) => ({
|
||||||
|
type: ApplicationActionTypes.CALCULATE_SCHEDULE_LOAD_FAILURE,
|
||||||
|
payload: error,
|
||||||
|
});
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ const INITIAL_STATE = {
|
|||||||
loading: false,
|
loading: false,
|
||||||
breadcrumbs: [],
|
breadcrumbs: [],
|
||||||
scheduleLoad: {
|
scheduleLoad: {
|
||||||
load: [],
|
load: {},
|
||||||
calculating: false,
|
calculating: false,
|
||||||
error: null,
|
error: null,
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
import { all, takeLatest, call } from "redux-saga/effects";
|
import { all, takeLatest, call, put } from "redux-saga/effects";
|
||||||
import ApplicationActionTypes from "./application.types";
|
import ApplicationActionTypes from "./application.types";
|
||||||
import { client } from "../../App/App.container";
|
import { client } from "../../App/App.container";
|
||||||
import { QUERY_SCHEDULE_LOAD_DATA } from "../../graphql/appointments.queries";
|
import { QUERY_SCHEDULE_LOAD_DATA } from "../../graphql/appointments.queries";
|
||||||
|
import {
|
||||||
|
scheduleLoadFailure,
|
||||||
|
scheduleLoadSuccess,
|
||||||
|
} from "./application.actions";
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
|
|
||||||
export function* onCalculateScheduleLoad() {
|
export function* onCalculateScheduleLoad() {
|
||||||
@@ -11,6 +15,7 @@ export function* onCalculateScheduleLoad() {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
export function* calculateScheduleLoad({ payload: end }) {
|
export function* calculateScheduleLoad({ payload: end }) {
|
||||||
|
//REMINDER: Moment.js is not immutable. Today WILL change when adjusted.
|
||||||
const today = moment(new Date()).startOf("day");
|
const today = moment(new Date()).startOf("day");
|
||||||
try {
|
try {
|
||||||
const result = yield client.query({
|
const result = yield client.query({
|
||||||
@@ -21,21 +26,12 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
const productionHoursTotal =
|
let load = {
|
||||||
result.data.productionview_aggregate.aggregate.sum.larhrs +
|
productionHoursTotal:
|
||||||
result.data.productionview_aggregate.aggregate.sum.labhrs;
|
result.data.productionview_aggregate.aggregate.sum.larhrs +
|
||||||
|
result.data.productionview_aggregate.aggregate.sum.labhrs,
|
||||||
|
};
|
||||||
|
|
||||||
const range = Math.round(moment.duration(end.diff(today)).asDays());
|
|
||||||
let load = {};
|
|
||||||
|
|
||||||
//Start from today and go until the range.
|
|
||||||
// for (var day = 0; day < range; day++) {
|
|
||||||
// let workingDate = today.add(day, "days");
|
|
||||||
// console.log(
|
|
||||||
// "function*calculateScheduleLoad -> workingDate",
|
|
||||||
// workingDate.toLocaleString()
|
|
||||||
// );
|
|
||||||
// }
|
|
||||||
const { arrJobs, compJobs } = result.data;
|
const { arrJobs, compJobs } = result.data;
|
||||||
|
|
||||||
arrJobs.forEach((item) => {
|
arrJobs.forEach((item) => {
|
||||||
@@ -45,8 +41,11 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
(load[itemDate].hoursIn || 0) +
|
(load[itemDate].hoursIn || 0) +
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||||
|
load[itemDate].jobsIn.push(item);
|
||||||
} else {
|
} else {
|
||||||
load[itemDate] = {
|
load[itemDate] = {
|
||||||
|
jobsIn: [],
|
||||||
|
jobsOut: [],
|
||||||
hoursIn:
|
hoursIn:
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs,
|
item.larhrs.aggregate.sum.mod_lb_hrs,
|
||||||
@@ -63,6 +62,7 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
(load[itemDate].hoursOut || 0) +
|
(load[itemDate].hoursOut || 0) +
|
||||||
item.labhrs.aggregate.sum.mod_lb_hrs +
|
item.labhrs.aggregate.sum.mod_lb_hrs +
|
||||||
item.larhrs.aggregate.sum.mod_lb_hrs;
|
item.larhrs.aggregate.sum.mod_lb_hrs;
|
||||||
|
load[itemDate].jobsOut.push(item);
|
||||||
} else {
|
} else {
|
||||||
load[itemDate] = {
|
load[itemDate] = {
|
||||||
hoursOut:
|
hoursOut:
|
||||||
@@ -72,10 +72,43 @@ export function* calculateScheduleLoad({ payload: end }) {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log("load", load);
|
//Propagate the expected load to each day.
|
||||||
|
const range = Math.round(moment.duration(end.diff(today)).asDays());
|
||||||
|
for (var day = 0; day < range; day++) {
|
||||||
|
console.log(
|
||||||
|
"function*calculateScheduleLoad -> today",
|
||||||
|
today.toISOString()
|
||||||
|
);
|
||||||
|
const current = moment(today)
|
||||||
|
.add(day, "days")
|
||||||
|
.toISOString()
|
||||||
|
.substr(0, 10);
|
||||||
|
console.log(
|
||||||
|
"function*calculateScheduleLoad -> today",
|
||||||
|
today.toISOString()
|
||||||
|
);
|
||||||
|
console.log("function*calculateScheduleLoad -> current", current);
|
||||||
|
const prev = moment(today)
|
||||||
|
.add(day - 1, "days")
|
||||||
|
.toISOString()
|
||||||
|
.substr(0, 10);
|
||||||
|
console.log("function*calculateScheduleLoad -> prev", prev);
|
||||||
|
if (day === 0) {
|
||||||
|
//Starting on day 1. The load is current.
|
||||||
|
load[current].expectedLoad = load.productionHoursTotal;
|
||||||
|
} else {
|
||||||
|
load[current].expectedLoad =
|
||||||
|
load[prev].expectedLoad +
|
||||||
|
(load[current].hoursIn || 0) -
|
||||||
|
(load[current].hoursOut || 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
yield put(scheduleLoadSuccess(load));
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
//console.log("Error in sendEmailFailure saga.", error.message);
|
//console.log("Error in sendEmailFailure saga.", error.message);
|
||||||
console.log("error", error);
|
console.log("error", error);
|
||||||
|
yield put(scheduleLoadFailure(error));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user