diff --git a/app/components/projectAssignment/draggableProjectDates.tsx b/app/components/projectAssignment/draggableProjectDates.tsx new file mode 100644 index 0000000..233875c --- /dev/null +++ b/app/components/projectAssignment/draggableProjectDates.tsx @@ -0,0 +1,102 @@ +'use client' + +import React, { DragEvent, FC } from 'react'; +import { useMutation } from "@apollo/client"; +import { UPSERT_PROJECT } from "@/app/gqlQueries"; +import { useProjectsDataContext } from '@/app/contexts/projectsDataContext'; +import { getISODateFromWeek, getWeekNumberAndYear } from '../scrollingCalendar/helpers'; +import { PROJECT_DATES_TYPE } from '../scrollingCalendar/constants'; + +interface DraggableDatesProps { + weekNumberOfTheYear: number; + monthYear: number; + monthLabel: string; +} + +const DraggableDates: FC = ({ + weekNumberOfTheYear, + monthYear, + monthLabel, +}) => { + const { projectList, setProjectList, singleProjectPage } = useProjectsDataContext() + let endDateWeekNumber; + let startDateWeekNumber; + + if (singleProjectPage?.endsOn) { + endDateWeekNumber = getWeekNumberAndYear(singleProjectPage?.endsOn) + } + if (singleProjectPage?.startsOn) { + startDateWeekNumber = getWeekNumberAndYear(singleProjectPage?.startsOn) + } + const isEndDateWeek = endDateWeekNumber?.weekNumber === weekNumberOfTheYear && monthYear === endDateWeekNumber?.year + const isStartDateWeek = startDateWeekNumber?.weekNumber === weekNumberOfTheYear && monthYear === startDateWeekNumber?.year + + const [upsertProject] = useMutation(UPSERT_PROJECT, { + errorPolicy: "all", + onCompleted({ upsertProject }) { + const { id, endsOn, startsOn } = upsertProject + const updatedProjectList = projectList.map(project => + project.id === id + ? { ...project, endsOn, startsOn } + : project + ); + setProjectList(updatedProjectList) + }, + }); + + const handleDragStart = (e: DragEvent) => { + const type = isStartDateWeek ? PROJECT_DATES_TYPE.STARTS_ON : PROJECT_DATES_TYPE.ENDS_ON + e.dataTransfer.setData('text/plain', JSON.stringify(type)); + e.stopPropagation(); + e.currentTarget.style.zIndex = '100'; + e.currentTarget.style.opacity = '0.5'; + }; + + const handleDrop = async (e: DragEvent) => { + const typeDate = JSON.parse(e.dataTransfer.getData('text/plain')); + const newTargetDate = getISODateFromWeek(monthYear, weekNumberOfTheYear, Number(monthLabel)) + const newDateForComparison = new Date(newTargetDate) + e.preventDefault(); + e.currentTarget.style.zIndex = ''; + e.currentTarget.style.opacity = '1'; + if (typeDate === PROJECT_DATES_TYPE.ENDS_ON && singleProjectPage?.startsOn) { + const startDate = new Date(singleProjectPage.startsOn); + if (startDate >= newDateForComparison) return; + + } + if (typeDate === PROJECT_DATES_TYPE.STARTS_ON && singleProjectPage?.endsOn) { + const endDate = new Date(singleProjectPage.endsOn) + if (newDateForComparison >= endDate) return; + } + const variables = { + id: singleProjectPage?.id, + name: singleProjectPage?.name, + [typeDate]: newTargetDate + } + await upsertProject({ + variables + }); + + }; + + const handleDragEnd = (e: DragEvent) => { + e.currentTarget.style.zIndex = ''; + e.currentTarget.style.opacity = '1'; + }; + + return ( +
e.preventDefault()} + onDrop={handleDrop} + className={`absolute top-0 left-0 right-0 inset-0 flex flex-col leading-none h-full w-full ${(isStartDateWeek || isEndDateWeek) ? 'cursor-pointer navbar' : '' + } `} + > + {isStartDateWeek && 'START' || isEndDateWeek && 'END'} +
+ ); +}; + +export default DraggableDates; diff --git a/app/components/scrollingCalendar/calendarHeader.tsx b/app/components/scrollingCalendar/calendarHeader.tsx index 62f1b83..fd96656 100644 --- a/app/components/scrollingCalendar/calendarHeader.tsx +++ b/app/components/scrollingCalendar/calendarHeader.tsx @@ -15,6 +15,7 @@ import { AssignmentType, MonthsDataType, ProjectType } from '@/app/typeInterface import { calculateTotalHoursPerWeek, isBeforeWeek, showMonthAndYear, getNextWeeksPerView, getPrevWeeksPerView, currentWeek, currentYear } from './helpers'; import ViewsMenu from '../viewsMenu/viewsMenu'; import EditFormController from './editFormController'; +import DraggableDates from '../projectAssignment/draggableProjectDates'; interface ColumnHeaderTitle { title: string; @@ -31,6 +32,7 @@ type CalendarHeaderProps = { editable?: boolean, projectInfo?: string, columnHeaderTitles: ColumnHeaderTitle[], + draggableDates?: boolean } const CalendarHeader: React.FC = ({ @@ -41,7 +43,9 @@ const CalendarHeader: React.FC = ({ userName, editable = false, projectInfo, - columnHeaderTitles }) => { + columnHeaderTitles, + draggableDates = false, +}) => { const [isEditing, setIsEditing] = useState(false); const { setDateRange, scrollToTodayFunction } = useGeneralDataContext(); const { totalActualHours, totalEstimatedHours, proposedEstimatedHours, maxTotalHours } = calculateTotalHoursPerWeek(assignments as AssignmentType[], months) @@ -99,8 +103,15 @@ const CalendarHeader: React.FC = ({ {months?.map((month) => { return month.weeks.map((week) => { - return ( + const isCurrentWeek = currentWeek === week.weekNumberOfTheYear && currentYear === month.year + return ( + {draggableDates && } = ({ {months?.map((month) => { return month.weeks.map((week, index) => { + const isCurrentWeek = currentWeek === week.weekNumberOfTheYear && currentYear === month.year return ( - +
{`W${week.weekNumberOfTheMonth}`} diff --git a/app/components/scrollingCalendar/constants.ts b/app/components/scrollingCalendar/constants.ts index f430898..f2d7b2d 100644 --- a/app/components/scrollingCalendar/constants.ts +++ b/app/components/scrollingCalendar/constants.ts @@ -22,3 +22,8 @@ export const MONTHS_COUNT: MonthsCount = { export const ACTUAL_HOURS = "actualHours"; export const ESTIMATED_HOURS = "estimatedHours"; + +export enum PROJECT_DATES_TYPE { + STARTS_ON = "startsOn", + ENDS_ON = "endsOn", +} diff --git a/app/components/scrollingCalendar/scrollingCalendar.tsx b/app/components/scrollingCalendar/scrollingCalendar.tsx index 3b51e4b..433e85d 100644 --- a/app/components/scrollingCalendar/scrollingCalendar.tsx +++ b/app/components/scrollingCalendar/scrollingCalendar.tsx @@ -21,6 +21,7 @@ interface ScrollingCalendarProps { userName?: string; projectInfo?: string; editable?: boolean; + draggableDates?: boolean } export const ScrollingCalendar = ({ @@ -31,7 +32,8 @@ export const ScrollingCalendar = ({ avatarUrl, userName, projectInfo, - editable + editable, + draggableDates }: ScrollingCalendarProps) => { const [months, setMonths] = useState([]); const { dateRange, setDateRange } = useGeneralDataContext(); @@ -72,6 +74,7 @@ export const ScrollingCalendar = ({ title={title} projectInfo={projectInfo} editable={editable} + draggableDates={draggableDates} /> {React.Children.map(children, (child) => diff --git a/app/projects/[projectId]/page.tsx b/app/projects/[projectId]/page.tsx index 83545f2..07bef02 100644 --- a/app/projects/[projectId]/page.tsx +++ b/app/projects/[projectId]/page.tsx @@ -73,18 +73,17 @@ const ProjectPage: React.FC = () => { const startDate = singleProjectPage?.startsOn ? DateTime.fromISO(singleProjectPage.startsOn) : null; const endDate = singleProjectPage?.endsOn ? DateTime.fromISO(singleProjectPage.endsOn) : null; - if (!startDate || !endDate) { + if (!startDate && !endDate) { return 'Start Date - End Date'; } - const formattedStartDate = startDate.toFormat('d.MMM'); - const formattedEndDate = endDate.toFormat('d.MMM'); - const startYear = startDate.year; - const endYear = endDate.year; - if (startYear === endYear) { - return `${formattedStartDate}-${formattedEndDate}.${endYear}`; - } else { - return `${formattedStartDate}.${startYear}-${formattedEndDate} ${endYear}`; + const formattedStartDate = startDate?.toFormat('d.MMM') + const formattedEndDate = endDate?.toFormat('d.MMM') + const startYear = startDate?.year || '' + const endYear = endDate?.year || '' + if (startDate && startYear && startYear !== endYear) { + return `${formattedStartDate}.${startYear}-${formattedEndDate || 'End Date'} ${endYear}`; } + return `${formattedStartDate || 'Start Date'}-${formattedEndDate}.${endYear}`; } const columnHeaderTitles = [{ title: 'People', showIcon: true, onClick: () => addNewAssignmentRow() }] @@ -94,7 +93,14 @@ const ProjectPage: React.FC = () => { <> {singleProjectPage && projectList.length ? ( <> - + {sortedSingleProjectAssignments?.map((assignment: AssignmentType, rowIndex) => { return (