import { CircularProgress, List } from "@mui/material"; import { Box } from "@mui/system"; import { memo, useEffect, useState } from "react"; import { v4 as uuidv4 } from "uuid"; import { IODataStructure, WeeklyPlannerDataType } from "../../../../interface/WeeklyPlannerTypes"; import { makeStylesEdt } from "../../../theme"; import { addArrayToSession, formateDateToFrenchFormat, generateDateFromStringInput, generateDayOverviewTimelineRawData, generateStringInputFromDate, getArrayFromSession, getFrenchDayFromDate, setDateTimeToZero, } from "../../../utils"; import { createCustomizableLunaticField } from "../../../utils/create-customizable-lunatic-field"; import CheckboxGroupEdt from "../../CheckboxGroupEdt"; import TooltipInfo from "../../TooltipInfo"; import DayOverview from "../DayOverview/DayOverview"; import DayPlanner from "../DayPlanner/DayPlanner"; import { getProgressBarValue, transformToIODataStructure, transformToWeeklyPlannerDataType, } from "./utils"; import { responsesType, WeeklyPlannerSpecificProps } from "../../../../interface"; export type WeeklyPlannerProps = { handleChange( response: { [name: string]: string }, value: IODataStructure[] | string[] | boolean[], ): void; value: { [key: string]: string[] | IODataStructure[] | boolean[] }; componentSpecificProps: WeeklyPlannerSpecificProps; bindingDependencies: string[]; responses: [ responsesType, responsesType, responsesType, responsesType, responsesType, responsesType, ]; variables: Map; placeWork: { bindingDependencies: string[]; responses: [ responsesType, responsesType, responsesType, responsesType, responsesType, responsesType, ]; label: string; }; }; /** * Generates a week of date starting from the startDate * @param startDate * @returns */ const generateDayList = (startDate: Date): Date[] => { const dayList: Date[] = [startDate]; for (let i = 1; i < 7; i++) { const newDate = new Date(startDate); newDate.setDate(startDate.getDate() + i); dayList.push(newDate); } return dayList; }; /** * Returns total sum of work for the day formatted as h:mm * @returns */ const getFormatedWorkedSum = (workedHoursSum: number): string => { const tempDate = new Date(); tempDate.setHours(0); tempDate.setMinutes(workedHoursSum); return ( tempDate.getHours() + ":" + (tempDate.getMinutes() === 0 ? "00" : tempDate.getMinutes().toString()) ); }; const setDataWeeklyPlannerArray = ( variables: Map, responses: [ responsesType, responsesType, responsesType, responsesType, responsesType, responsesType, ], ) => { return variables.get(responses[0].response.name) as IODataStructure[]; }; const setDataArray = ( variables: Map, responses: [ responsesType, responsesType, responsesType, responsesType, responsesType, responsesType, ], language: string, ) => { const dataWeeklyPlanner = setDataWeeklyPlannerArray(variables, responses); const data: WeeklyPlannerDataType[] | undefined = dataWeeklyPlanner?.length > 1 ? transformToWeeklyPlannerDataType(dataWeeklyPlanner, language) : undefined; return data; }; const WeeklyPlanner = memo((props: WeeklyPlannerProps) => { let { value, handleChange, componentSpecificProps, responses, variables, placeWork } = props; const { surveyDate, isSubChildDisplayed, setIsSubChildDisplayed, isPlaceWorkDisplayed, setIsPlaceWorkDisplayed, labels, saveAll, setDisplayedDayHeader, language, helpStep, moreIcon, expandLessIcon, expandMoreIcon, expandLessWhiteIcon, expandMoreWhiteIcon, workIcon, saveHours, idSurvey, } = { ...componentSpecificProps, }; const { classes } = useStyles(); const startDate: string = surveyDate ?? ""; const startDateFormated: Date = setDateTimeToZero(generateDateFromStringInput(startDate)); const dayList: Date[] = generateDayList(startDateFormated); const [store, setStore] = useState<[IODataStructure[], string[], string[], any[]]>([[], [], [], []]); const [dayOverviewSelectedDate, setDayOverviewSelectedDate] = useState(startDateFormated); const [activityData, setActivityData] = useState([]); const [needSpinner, setNeedSpinner] = useState(true); const [dataCopy, setDataCopy] = useState([]); const setInit = () => { const dataUpdated = setDataArray(variables, responses, language); const temp: WeeklyPlannerDataType[] = dataUpdated ? [...dataUpdated] : []; dayList.forEach(date => { let dayBloc: WeeklyPlannerDataType | undefined = temp.find( d => setDateTimeToZero(generateDateFromStringInput(d.date)).getTime() === date.getTime(), ); if (!dayBloc) { dayBloc = { hasBeenStarted: false, date: generateStringInputFromDate(date), day: getFrenchDayFromDate(date), detail: [], }; temp.push(dayBloc); } }); // loop through saved data to check if some are out of the week range after survey date update const dayListAsString: string[] = dayList.map(d => generateStringInputFromDate(d)); const clearedTemp = temp .filter(dayBloc => dayListAsString.includes(dayBloc.date)) .map(dayBlock => { return { hasBeenStarted: dayBlock.hasBeenStarted, date: getDateWithZeros(dayBlock.date), day: dayBlock.day, detail: dayBlock.detail, }; }) .sort((a, b) => a.date.localeCompare(b.date)); setActivityData(clearedTemp); const toStore = transformToIODataStructure(clearedTemp); setStore(toStore); return toStore; }; useEffect(() => { initializeStore(); }, [idSurvey]); const initializeStore = () => { const storeAct = setInit(); handleChange(responses[1].response, storeAct[1]); handleChange(responses[2].response, storeAct[2]); handleChange(responses[0].response, storeAct[0]); setStore(storeAct); return storeAct; }; const getDateWithZeros = (date: string) => { const yearMonthDay = date.split("-"); let day = yearMonthDay[2]; day = Number(day) < 10 && !day.includes("0", 0) ? "0" + day : day; return yearMonthDay[0] + "-" + yearMonthDay[1] + "-" + day; }; const formateDateLabel = (date: Date): string => { const formatedDate = formateDateToFrenchFormat(date, language); return formatedDate.toUpperCase(); }; useEffect(() => { setNeedSpinner(false); }, [isSubChildDisplayed]); useEffect(() => { setDisplayedDayHeader(formateDateLabel(dayOverviewSelectedDate)); }, [dayOverviewSelectedDate]); // Complete activity data with default values for all days of the week if it was not the case in data input useEffect(() => { setInit(); const init = initializeStore(); addArrayToSession(labels.dates, init[1]); addArrayToSession(labels.datesStarted, init[2]); saveAll(idSurvey, init, true); }, []); useEffect(() => { setNeedSpinner(true); saveAll(idSurvey, store, true); }, [activityData]); const getMainDisplay = () => { return isSubChildDisplayed ? "none" : "inline"; }; const titleLabels = { normalTitle: labels.title, }; const getWorkedHoursSum = () => { const dayBloc: WeeklyPlannerDataType = activityData.filter( d => setDateTimeToZero(generateDateFromStringInput(d.date)).getTime() === dayOverviewSelectedDate.getTime(), )[0]; const sum: number = dayBloc?.detail.reduce((acc, val) => acc + val.duration, 0); return sum; }; useEffect(() => { if (dataCopy.length > 0) { handleChange(responses[0].response, dataCopy); saveAll(idSurvey, [dataCopy, store[1], store[2], store[3]], false); } if (store[1].length > 0) { handleChange(responses[1].response, store[1]); handleChange(responses[2].response, store[2]); } }, [dataCopy, idSurvey]); const renderHelp = () => { return ( ); }; const handle = (data: [IODataStructure[], string[], string[], any[]]) => { if (data[0].length > 0) { setDataCopy(data[0]); handleChange(responses[0].response, dataCopy); } if (data[1].length > 0) { handleChange(responses[1].response, data[1]); handleChange(responses[2].response, data[2]); } let storeAct: [IODataStructure[], string[], string[], any[]] = [ data[0], data[1].length > 0 ? data[1] : store[1], data[2].length > 0 ? data[2] : store[2], data[3].length > 0 ? data[3] : store[3], ]; setStore(storeAct); }; const getIndexOfDayPlanner = () => { let dates = variables.get(labels.dates) as string[]; if (dates == null || dates.length < 7) { dates = getArrayFromSession(labels.dates); } const currentDate = generateStringInputFromDate(dayOverviewSelectedDate); const index = dates.findIndex(date => date == currentDate); const valuesForCheckbox: { [key: string]: boolean | boolean[] } = {}; placeWork.responses.forEach(response => { const valueOfResponse = variables.get(response.response.name) as boolean[]; valuesForCheckbox[response.response.name] = valueOfResponse; }); return [valuesForCheckbox, index]; }; const handleChangeOptions = ( response: { [name: string]: string }, value: IODataStructure[] | string[] | boolean[], ) => { handleChange(response, value); }; const renderOptions = () => { const values = getIndexOfDayPlanner(); return ( ); }; const propsDayOverview = { isDisplayed: isSubChildDisplayed, date: dayOverviewSelectedDate, rawTimeLineData: generateDayOverviewTimelineRawData(), activityData: activityData, setActivityData: setActivityData, handleChangeData: handle, infoLabels: labels.infoLabels, datesLabel: labels.dates, workSumLabel: labels.workSumLabel, workedHoursSum: getWorkedHoursSum(), getFormatedWorkedSum: getFormatedWorkedSum, expandLessIcon: expandLessIcon, expandMoreIcon: expandMoreIcon, expandLessWhiteIcon: expandLessWhiteIcon, expandMoreWhiteIcon: expandMoreWhiteIcon, workIcon: workIcon, handleChange: handleChangeOptions, saveHours: saveHours, values: value, idSurvey: idSurvey, variables: variables, }; const renderWeeklyPlanner = () => { return ( {activityData.length !== 0 && needSpinner ? ( <> {dayList.map(d => ( ))} ) : ( !isSubChildDisplayed && )} ); }; const renderWeek = () => { return isPlaceWorkDisplayed && isSubChildDisplayed ? renderOptions() : renderWeeklyPlanner(); }; return helpStep == null ? renderWeek() : renderHelp(); }); const useStyles = makeStylesEdt({ "name": { WeeklyPlanner } })(theme => ({ containerRoot: { marginTop: "1rem", }, listContainer: { display: "flex", flexDirection: "column", paddingBottom: "6rem", alignItems: "center", }, progressBar: { padding: "1rem", backgroundColor: theme.variables.white, position: "relative", width: "100vw !important", overflowX: "hidden", //Orchestrator content width is limited to 350px, 175px correspond to half if it transform: "translateX(calc(175px - 50vw))", marginBottom: "1rem", }, })); export default createCustomizableLunaticField(WeeklyPlanner, "WeeklyPlanner");