// Libraries import moment from 'moment'; import {getObjectPropSafely} from 'Utils/index'; const FORMAT_DATE = 'DD/MM/YYYY'; function getAllDatesOfMonth(date, numberDate, format = FORMAT_DATE) { const mDate = moment(date, format); const daysCount = numberDate || mDate.daysInMonth(); return Array(daysCount).fill(null).map((_,index)=>{ const addDays = index === 0 ? 0 : 1; return mDate.add(addDays, 'days').format(format); }); } const initialCalendar = (date: string, format = FORMAT_DATE) : Record => { const currentDate = getObjectPropSafely(() => moment(date, format).startOf('month').format(format)) || moment(); if (currentDate) { // Get all day in calendar const MAX_COLUMN = 7; // Step 1: get index Day of week of day start of month const mDateOfWeek = moment(currentDate, format).startOf('month').days(); // Step 2: get Day begin of calendar const startDayOfCalendar = moment(currentDate, format).subtract(mDateOfWeek,'days').format(format); // Step 3: calculator number Date const numberDateOfCurrentMonth = moment(currentDate, format).daysInMonth(); const numRowCalendar = Math.ceil((numberDateOfCurrentMonth + mDateOfWeek) / MAX_COLUMN); const numberCellOfCalendar = numRowCalendar * MAX_COLUMN; // Step 4: get all days in calendar const allDaysOfCalendar = getAllDatesOfMonth(startDayOfCalendar, numberCellOfCalendar, format); // Step 5: calculator coordinate day of calendar const coordinateMatrix = allDaysOfCalendar.reduce((acc: Record[] = [], currentDate, index) => { const rowCurrentDate = Math.floor(index / MAX_COLUMN); const columnCurrentDate = index % MAX_COLUMN; acc.push({ value: currentDate, coordinate: { row: rowCurrentDate, column: columnCurrentDate } }); return acc; },[]); // Extra: get position of startMonth and endMonth const startMonth = { row: 0, column: mDateOfWeek }; const endMonth = { row: numRowCalendar - 1, column: moment(currentDate, format).endOf('month').days() }; return { calendarData: coordinateMatrix, totalRow: numRowCalendar, totalColumn: MAX_COLUMN, startMonth, endMonth }; } return {}; }; // const findCoordinateEventInCalendar = (calendarData, date, format = FORMAT_DATE) => { // if (Array.isArray(calendarData)) { // for (let row = 0; row < calendarData.length; row++) { // if (Array.isArray(calendarData[row])) { // for (let col = 0; col < calendarData[row].length; col++) { // const formatSrc = moment(date, format); // const formatDes = moment(calendarData[row][col].value, format); // if (formatSrc.isSame(formatDes)) { // return { // row, // col // }; // } // } // } // } // } // return null; // }; const processDataEvents = (events, calendarData, maxRow, maxCol, format = FORMAT_DATE, sortEventFunc, mapCalendarData) => { // maxRow and maxCol are start from 0 to n const endOfCalendar = getObjectPropSafely(() => calendarData[maxRow][maxCol]); const startOfCalendar = getObjectPropSafely(() => calendarData[0][0]); // sort by start date let sortEventsByStartDate = [...events]; // sort by priority type if (sortEventFunc && typeof sortEventFunc === 'function') { sortEventsByStartDate = sortEventFunc([...events]); } else { sortEventsByStartDate = sortEventsByStartDate.sort((a , b) => { if (a.startDate && b.startDate) { const dateA = moment(a.startDate, format); const dateB = moment(b.startDate, format); return dateA.diff(dateB); } return 0; }); } // handle event has no endDate sortEventsByStartDate = sortEventsByStartDate.map((event, index) => { let updatedEvent = { ...event, originalStartDate: event.startDate || '', originalEndDate: event.endDate || '', levelPosition: index + 1 }; if (!event.endDate || getObjectPropSafely(() => moment(event.endDate, format).isAfter(moment(endOfCalendar.value, format)) )) { updatedEvent = { ...updatedEvent, endDate: endOfCalendar.value }; } if (getObjectPropSafely(() => moment(event.startDate, format).isBefore(moment(startOfCalendar.value, format)) )) { updatedEvent = { ...updatedEvent, startDate: startOfCalendar.value }; } return updatedEvent; }); const processedEvents: Record[] = []; sortEventsByStartDate.forEach(event => { // process each event const {startDate, endDate} = event; const coordinateStart = mapCalendarData[startDate] || null; const coordinateEnd = mapCalendarData[endDate] || null; if (coordinateStart && coordinateEnd) { // const numberLineOfEvent = coordinateEnd.row - coordinateStart.row + 1; // const levelPosition = getLevelPositionEvent(coordinateStart, processedEvents) || 1; const levelPosition = event.levelPosition; for (let i = coordinateStart.row; i <= coordinateEnd.row; i++) { if (i === coordinateStart.row && i === coordinateEnd.row) { const formattedEvent = { event, pointStart: { row: coordinateStart.row, col: coordinateStart.col }, pointEnd: { row: coordinateEnd.row, col: coordinateEnd.col }, levelPosition, label: getObjectPropSafely(() => (event.prefixLabel ? `${event.prefixLabel} ${event.label}` : event.label)), extraLeft: false, extraRight: false }; // case one line processedEvents.push(formattedEvent); } else { // case multi line if (i === coordinateStart.row && i < coordinateEnd.row) { // first line processedEvents.push({ event, pointStart: { row: coordinateStart.row, col: coordinateStart.col }, pointEnd: { row: coordinateStart.row, col: maxCol }, levelPosition, label: getObjectPropSafely(() => (event.prefixLabel ? `${event.prefixLabel} ${event.label}` : event.label)), extraLeft: false, extraRight: true }); } if (i > coordinateStart.row && i < coordinateEnd.row) { const formattedEvent = { event, pointStart: { row: i, col: 0 }, pointEnd: { row: i, col: maxCol }, levelPosition, label: event.label, extraLeft: true, extraRight: true }; // formattedEvent.levelPosition = getLevelPositionEvent(formattedEvent.pointStart, processedEvents) || levelPosition; formattedEvent.levelPosition = event.levelPosition // between line => full line on one row processedEvents.push(formattedEvent); } if (i > coordinateStart.row && i === coordinateEnd.row) { const formattedEvent = { event, pointStart: { row: coordinateEnd.row, col: 0 }, pointEnd: { row: coordinateEnd.row, col: coordinateEnd.col }, levelPosition, label: event.label, extraLeft: true, extraRight: false }; // formattedEvent.levelPosition = getLevelPositionEvent(formattedEvent.pointStart, processedEvents) || levelPosition; formattedEvent.levelPosition = event.levelPosition // end line processedEvents.push(formattedEvent); } } } } }); return processedEvents; }; // const getLevelPositionEvent = (startPoint, processedEvents) => { // const filterEvent = processedEvents.filter(event => { // const {pointStart: pStartEvent, pointEnd: pEndEvent} = event; // // filter event same row and startPoint between event timeline // return pStartEvent.row === startPoint.row && ( // pStartEvent.col <= startPoint.col && // pEndEvent.col >= startPoint.col // ); // }); // let newLevel = 1; // // eslint-disable-next-line no-constant-condition // while (1) { // if (filterEvent.some(event => event.levelPosition === newLevel)) { // newLevel++; // } else { // break; // } // } // return newLevel; // }; export { initialCalendar, processDataEvents };