From dbe03427d6954ac334d01e76911af7cb319518b4 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Wed, 16 Oct 2024 02:36:03 -0400 Subject: [PATCH 01/14] WIP: Need to make recurring rides work as a feature What has been done: - fixed the schedule so that rides from other days show up - unscheduledRides and scheduledRides from useRides of RidesContext now includes recurring rides, however these rides are not in the backend. Then plan is to add them to the backend once you edit/delete them. Edit shouldn't be too hard but delete I need to figure out. - The Edit button on recurring rides now works --- frontend/src/components/Schedule/Schedule.tsx | 2 +- .../src/components/UserTables/RidesTable.tsx | 8 +- frontend/src/context/RidesContext.tsx | 89 +++++++++++++++++-- 3 files changed, 86 insertions(+), 13 deletions(-) diff --git a/frontend/src/components/Schedule/Schedule.tsx b/frontend/src/components/Schedule/Schedule.tsx index 9f2efdc0a..5b5f65a46 100644 --- a/frontend/src/components/Schedule/Schedule.tsx +++ b/frontend/src/components/Schedule/Schedule.tsx @@ -215,7 +215,7 @@ Rider: ${ride.rider.firstName} ${ride.rider.lastName}`, localizer={localizer} toolbar={false} step={5} - defaultDate={scheduleDay} + date={scheduleDay} timeslots={12} showMultiDayTimes={true} events={events} diff --git a/frontend/src/components/UserTables/RidesTable.tsx b/frontend/src/components/UserTables/RidesTable.tsx index e78f95489..29c52fcd2 100644 --- a/frontend/src/components/UserTables/RidesTable.tsx +++ b/frontend/src/components/UserTables/RidesTable.tsx @@ -18,7 +18,6 @@ const RidesTable = ({ rides, hasButtons }: RidesTableProps) => { const { drivers } = useEmployees(); const [openAssignModal, setOpenAssignModal] = useState(-1); const [openEditModal, setOpenEditModal] = useState(-1); - const [openDeleteOrEditModal, setOpenDeleteOrEditModal] = useState(-1); const [editSingle, setEditSingle] = useState(false); const [reassign, setReassign] = useState(false); const [deleteOpen, setDeleteOpen] = useState(-1); @@ -103,11 +102,7 @@ const RidesTable = ({ rides, hasButtons }: RidesTableProps) => { outline small onClick={() => { - if (rides[index].recurring) { - setOpenDeleteOrEditModal(index); - } else { - setOpenEditModal(index); - } + setOpenEditModal(index); }} > Edit @@ -191,7 +186,6 @@ const RidesTable = ({ rides, hasButtons }: RidesTableProps) => { ride={rides[index]} deleting={true} onNext={(single) => { - setOpenDeleteOrEditModal(-1); setOpenEditModal(index); setEditSingle(single); }} diff --git a/frontend/src/context/RidesContext.tsx b/frontend/src/context/RidesContext.tsx index c90569043..59d66001a 100644 --- a/frontend/src/context/RidesContext.tsx +++ b/frontend/src/context/RidesContext.tsx @@ -1,9 +1,10 @@ -import React, { useCallback, useState, useRef, useEffect } from 'react'; +import React, { useCallback, useState, useRef, useEffect, useContext } from 'react'; import { Ride, Type } from '../types'; import { useDate } from './date'; import { format_date } from '../util/index'; import axios from '../util/axios'; + type ridesState = { unscheduledRides: Ride[]; scheduledRides: Ride[]; @@ -23,6 +24,15 @@ type RidesProviderProps = { children: React.ReactNode; }; +function uuidv4() { + return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => + ( + +c ^ + (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4))) + ).toString(16) + ); +} + export const RidesProvider = ({ children }: RidesProviderProps) => { const [unscheduledRides, setUnscheduledRides] = useState([]); const [scheduledRides, setScheduledRides] = useState([]); @@ -30,16 +40,85 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { const date = format_date(curDate); const refreshRides = useCallback(async () => { - const ridesData: Ride[] = await axios + const ridesDataToday: Ride[] = await axios .get(`/api/rides?date=${date}`) .then((res) => res.data) .then((data) => data.data); - if (ridesData) { + + const newRecurringRides: Ride[] = await axios + .get(`/api/rides?recurring=true`) + .then((res) => res.data) + .then((data) => data.data) + // here, I'm assuming that all rides with parentRide as undefined is the "source" rides, meaning that all recurring rides have these rides as parents. + .then((data : Ride[]) => data.filter((ride) => ride.parentRide === undefined)) + .then((data: Ride[]) => + data.filter((ride) => { + let endDate = new Date(ride!.endDate!); + return ( + curDate <= endDate && + ride!.recurringDays?.includes(curDate.getDay()) + ); + }) + ) + .then((recurringParentRides: Ride[]) => + recurringParentRides.filter((parentRide) => { + const startTimeRecurringRide = new Date(parentRide.startTime); + startTimeRecurringRide.setFullYear(curDate.getFullYear()); + startTimeRecurringRide.setMonth(curDate.getMonth()); + startTimeRecurringRide.setDate(curDate.getDate()); + + const endTimeRecurringRide = new Date(parentRide.endTime); + endTimeRecurringRide.setFullYear(curDate.getFullYear()); + endTimeRecurringRide.setMonth(curDate.getMonth()); + endTimeRecurringRide.setDate(curDate.getDate()); + + return !ridesDataToday.some( + (rideToday) => + (new Date(rideToday.startTime)).getTime() === startTimeRecurringRide.getTime() && + (new Date(rideToday.endTime)).getTime() === endTimeRecurringRide.getTime() && + rideToday.startLocation.name === parentRide.startLocation.name && + rideToday.endLocation.name === parentRide.endLocation.name && + rideToday.rider.id === parentRide.rider.id + ); + }) + ) + .then((recurringParentRides: Ride[]) => + recurringParentRides.map((parentRide) => { + + const startTimeRecurringRide = new Date(parentRide.startTime); + startTimeRecurringRide.setFullYear(curDate.getFullYear()); + startTimeRecurringRide.setMonth(curDate.getMonth()); + startTimeRecurringRide.setDate(curDate.getDate()); + + const endTimeRecurringRide = new Date(parentRide.endTime); + endTimeRecurringRide.setFullYear(curDate.getFullYear()); + endTimeRecurringRide.setMonth(curDate.getMonth()); + endTimeRecurringRide.setDate(curDate.getDate()); + + console.log("end time recurring ride is ", endTimeRecurringRide); + console.log("end time iso recurring ride is ", endTimeRecurringRide.toISOString()); + console.log("end time parent", parentRide.endTime); + + // console.log("parent end time", new Date(parentRide.endTime)) + return { + ...parentRide, + startTime: startTimeRecurringRide.toISOString(), + endTime: endTimeRecurringRide.toISOString(), + type : Type.UNSCHEDULED, + parentRide: parentRide, + }; + }) + ); + + console.log("current date is ", curDate.getDate()); + + const combinedRidesData = ridesDataToday.concat(newRecurringRides); + if (combinedRidesData) { setUnscheduledRides( - ridesData.filter(({ type }) => type === Type.UNSCHEDULED) + combinedRidesData.filter(({ type }) => type === Type.UNSCHEDULED) ); setScheduledRides( - ridesData.filter(({ type }) => type !== Type.UNSCHEDULED) + combinedRidesData.filter(({ type }) => type !== Type.UNSCHEDULED) ); } }, [date]); From 5d63f6cdeaeb7435f4836718a138a5664ec224d8 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Wed, 16 Oct 2024 03:26:16 -0400 Subject: [PATCH 02/14] ran prettier --- frontend/src/context/RidesContext.tsx | 39 +++++++++++++++++---------- 1 file changed, 25 insertions(+), 14 deletions(-) diff --git a/frontend/src/context/RidesContext.tsx b/frontend/src/context/RidesContext.tsx index 59d66001a..a2bd8bf00 100644 --- a/frontend/src/context/RidesContext.tsx +++ b/frontend/src/context/RidesContext.tsx @@ -1,10 +1,15 @@ -import React, { useCallback, useState, useRef, useEffect, useContext } from 'react'; +import React, { + useCallback, + useState, + useRef, + useEffect, + useContext, +} from 'react'; import { Ride, Type } from '../types'; import { useDate } from './date'; import { format_date } from '../util/index'; import axios from '../util/axios'; - type ridesState = { unscheduledRides: Ride[]; scheduledRides: Ride[]; @@ -49,8 +54,10 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { .get(`/api/rides?recurring=true`) .then((res) => res.data) .then((data) => data.data) - // here, I'm assuming that all rides with parentRide as undefined is the "source" rides, meaning that all recurring rides have these rides as parents. - .then((data : Ride[]) => data.filter((ride) => ride.parentRide === undefined)) + // here, I'm assuming that all rides with parentRide as undefined is the "source" rides, meaning that all recurring rides have these rides as parents. + .then((data: Ride[]) => + data.filter((ride) => ride.parentRide === undefined) + ) .then((data: Ride[]) => data.filter((ride) => { let endDate = new Date(ride!.endDate!); @@ -74,8 +81,10 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { return !ridesDataToday.some( (rideToday) => - (new Date(rideToday.startTime)).getTime() === startTimeRecurringRide.getTime() && - (new Date(rideToday.endTime)).getTime() === endTimeRecurringRide.getTime() && + new Date(rideToday.startTime).getTime() === + startTimeRecurringRide.getTime() && + new Date(rideToday.endTime).getTime() === + endTimeRecurringRide.getTime() && rideToday.startLocation.name === parentRide.startLocation.name && rideToday.endLocation.name === parentRide.endLocation.name && rideToday.rider.id === parentRide.rider.id @@ -84,7 +93,6 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { ) .then((recurringParentRides: Ride[]) => recurringParentRides.map((parentRide) => { - const startTimeRecurringRide = new Date(parentRide.startTime); startTimeRecurringRide.setFullYear(curDate.getFullYear()); startTimeRecurringRide.setMonth(curDate.getMonth()); @@ -94,23 +102,26 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { endTimeRecurringRide.setFullYear(curDate.getFullYear()); endTimeRecurringRide.setMonth(curDate.getMonth()); endTimeRecurringRide.setDate(curDate.getDate()); - - console.log("end time recurring ride is ", endTimeRecurringRide); - console.log("end time iso recurring ride is ", endTimeRecurringRide.toISOString()); - console.log("end time parent", parentRide.endTime); + + console.log('end time recurring ride is ', endTimeRecurringRide); + console.log( + 'end time iso recurring ride is ', + endTimeRecurringRide.toISOString() + ); + console.log('end time parent', parentRide.endTime); // console.log("parent end time", new Date(parentRide.endTime)) return { ...parentRide, startTime: startTimeRecurringRide.toISOString(), endTime: endTimeRecurringRide.toISOString(), - type : Type.UNSCHEDULED, + type: Type.UNSCHEDULED, parentRide: parentRide, }; }) ); - - console.log("current date is ", curDate.getDate()); + + console.log('current date is ', curDate.getDate()); const combinedRidesData = ridesDataToday.concat(newRecurringRides); if (combinedRidesData) { From 89459785d629d7dc6428bedfd47e4064e9e4b469 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Wed, 23 Oct 2024 07:37:57 -0400 Subject: [PATCH 03/14] recurring rides now work for edit button (options are to edit a single ride which creates a new ride entirely or to edit all recurring rides) and delete (delete that single ride or delete all rides). Lots of bugs: all recurring rides now are unscheduled, also probabaly won't work as a rider --- .../Modal/DeleteOrEditTypeModal.tsx | 23 ++- .../CreateOrEditRideModal.tsx | 4 + .../src/components/RideModal/RideModal.tsx | 142 ++++++++++++++---- .../src/components/UserTables/RidesTable.tsx | 1 - frontend/src/context/RidesContext.tsx | 50 ++---- 5 files changed, 147 insertions(+), 73 deletions(-) diff --git a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx index dc43e3f5e..0d3ca44a1 100644 --- a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx +++ b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx @@ -35,16 +35,25 @@ const DeleteOrEditTypeModal = ({ }; const confirmCancel = () => { - if (ride.recurring && single) { - const startDate = format_date(ride.startTime); - axios - .put(`/api/rides/${ride.id}/edits`, { - deleteOnly: true, - origDate: startDate, - }) + if (ride.recurring) { + if (single) { + let startDate = new Date(ride.startTime); + startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate(), 0, 0, 0); + let parentDeletedDates : string[] = ride?.parentRide?.deleted === undefined ? [] : ride!.parentRide!.deleted; + parentDeletedDates.push(startDate.toISOString()); + axios + .put(`/api/rides/${ride!.parentRide!.id}`, {deleted: parentDeletedDates}) + .then(() => closeModal()) + .then(refreshRides); + } else { + console.log("hellow, del", ride!.parentRide!.id); + axios + .delete(`/api/rides/${ride!.parentRide!.id}`) .then(() => closeModal()) .then(refreshRides); + } } else { + // console.log("hellow, del", ride!.id); axios .delete(`/api/rides/${ride.id}`) .then(() => closeModal()) diff --git a/frontend/src/components/RequestRideModal/CreateOrEditRideModal.tsx b/frontend/src/components/RequestRideModal/CreateOrEditRideModal.tsx index 2a4a868e9..b9d52268a 100644 --- a/frontend/src/components/RequestRideModal/CreateOrEditRideModal.tsx +++ b/frontend/src/components/RequestRideModal/CreateOrEditRideModal.tsx @@ -12,6 +12,9 @@ import { format_date } from '../../util/index'; import { LocationsProvider } from '../../context/LocationsContext'; import axios from '../../util/axios'; +//this is for rider???? + + type CreateOrEditRideModalProps = { isOpen: boolean; modalType: RideModalType; @@ -27,6 +30,7 @@ const CreateOrEditRideModal = ({ onClose = () => {}, ride, }: CreateOrEditRideModalProps) => { + // console.log("FUCKKKK"); const defaultStartDate = () => { if (ride) { if ( diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index 22e97a7d0..cced0670b 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -1,19 +1,20 @@ import React, { useCallback, useEffect, useState } from 'react'; import moment from 'moment'; import Modal from '../Modal/Modal'; -import { Button } from '../FormElements/FormElements'; +import { Input, Label, Button } from '../FormElements/FormElements'; import { DriverPage, RiderInfoPage, RideTimesPage } from './Pages'; import { ObjectType, RepeatValues, Ride } from '../../types/index'; import { format_date } from '../../util/index'; import { useRides } from '../../context/RidesContext'; import { ToastStatus, useToast } from '../../context/toastContext'; import axios from '../../util/axios'; +import DeleteOrEditTypeModal from 'components/Modal/DeleteOrEditTypeModal'; +import { isOutOfBounds } from 'react-datepicker/dist/date_utils'; type RideModalProps = { open?: boolean; close?: () => void; ride?: Ride; - editSingle?: boolean; }; const getRideData = (ride: Ride | undefined) => { @@ -62,14 +63,65 @@ const getRideData = (ride: Ride | undefined) => { return {}; }; -const RideModal = ({ open, close, ride, editSingle }: RideModalProps) => { +type EditRecurringProps = { + onSubmit: (recurring : boolean) => void; +}; + +const EditRecurring = ({ onSubmit }: EditRecurringProps) => { + const [single, setSingle] = useState(true); + const changeSelection = (e: any) => { + setSingle(e.target.value === 'single'); + }; + return ( + <> +
+ changeSelection(e)} + defaultChecked={true} + /> + +
+
+ changeSelection(e)} + /> + +
+
+ +
+ + ); +}; + +//need to add option to this to select whether to editsingle or not, shoulnd't be a prop passed in +const RideModal = ({ open, close, ride }: RideModalProps) => { const originalRideData = getRideData(ride); const [formData, setFormData] = useState(originalRideData); const [isOpen, setIsOpen] = useState(open !== undefined ? open : false); const [currentPage, setCurrentPage] = useState(0); const [isSubmitted, setIsSubmitted] = useState(false); + const [editSingle, setEditSingle] = useState(true); const { showToast } = useToast(); const { refreshRides } = useRides(); + const [showRest, setShowRest] = useState(false); const goNextPage = () => setCurrentPage((p) => p + 1); @@ -80,6 +132,7 @@ const RideModal = ({ open, close, ride, editSingle }: RideModalProps) => { setIsOpen(true); }; + // console.log("HELLO MATEW"); const closeModal = useCallback(() => { if (close) { setFormData(originalRideData); @@ -167,17 +220,22 @@ const RideModal = ({ open, close, ride, editSingle }: RideModalProps) => { rideData.type = 'unscheduled'; } if (editSingle) { - // edit single instance of repeating ride + const daysWithEdits: string[] = + ride!.parentRide!.edits === undefined + ? [] + : ride!.parentRide!.edits; + daysWithEdits.push(new Date(ride.startTime).toISOString()); axios - .put(`/api/rides/${ride.id}/edits`, { - deleteOnly: false, - origDate: format_date(ride.startTime), - ...rideData, + .put(`/api/rides/${ride!.parentRide!.id!}`, { + edits: daysWithEdits, }) .then(refreshRides); + // create new ride with no relation to parent ride + rideData = { ...rideData, parentRide: undefined }; + axios.post('/api/rides', rideData).then(refreshRides); } else { // edit ride or all instances of repeating ride - axios.put(`/api/rides/${ride.id}`, rideData).then(refreshRides); + axios.put(`/api/rides/${ride!.parentRide!.id}`, rideData).then(refreshRides); } } else { // unscheduled ride @@ -199,26 +257,52 @@ const RideModal = ({ open, close, ride, editSingle }: RideModalProps) => { ]); return ride ? ( - <> - - - - - + ride.recurring ? ( + <> + {true && ( + + {setEditSingle(recurring); goNextPage()}}/> + + + + )} + + ) : ( + <> + + + + + + ) ) : ( <> {!open && } diff --git a/frontend/src/components/UserTables/RidesTable.tsx b/frontend/src/components/UserTables/RidesTable.tsx index 22ac28bfb..5c3d70358 100644 --- a/frontend/src/components/UserTables/RidesTable.tsx +++ b/frontend/src/components/UserTables/RidesTable.tsx @@ -210,7 +210,6 @@ const RidesTable = ({ rides, hasButtons }: RidesTableProps) => { open={openEditModal === index} close={() => setOpenEditModal(-1)} ride={rides[index]} - editSingle={editSingle} /> ); diff --git a/frontend/src/context/RidesContext.tsx b/frontend/src/context/RidesContext.tsx index a2bd8bf00..6d014f1cf 100644 --- a/frontend/src/context/RidesContext.tsx +++ b/frontend/src/context/RidesContext.tsx @@ -29,15 +29,6 @@ type RidesProviderProps = { children: React.ReactNode; }; -function uuidv4() { - return '10000000-1000-4000-8000-100000000000'.replace(/[018]/g, (c) => - ( - +c ^ - (crypto.getRandomValues(new Uint8Array(1))[0] & (15 >> (+c / 4))) - ).toString(16) - ); -} - export const RidesProvider = ({ children }: RidesProviderProps) => { const [unscheduledRides, setUnscheduledRides] = useState([]); const [scheduledRides, setScheduledRides] = useState([]); @@ -48,7 +39,8 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { const ridesDataToday: Ride[] = await axios .get(`/api/rides?date=${date}`) .then((res) => res.data) - .then((data) => data.data); + .then((data) => data.data) + .then((data : Ride[]) => data.filter((ride : Ride) => !(ride.recurring && ride.parentRide === undefined))); const newRecurringRides: Ride[] = await axios .get(`/api/rides?recurring=true`) @@ -61,33 +53,18 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { .then((data: Ride[]) => data.filter((ride) => { let endDate = new Date(ride!.endDate!); + console.log(ride); + let startDate = new Date(ride.startTime); + startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate(), 0, 0, 0); + let deletedDateList = ride.deleted === undefined ? [] : ride.deleted.map((d) => new Date(d)); + let editedDateList = ride.edits === undefined ? [] : ride.edits.map((d) => new Date(d)); + console.log(deletedDateList); return ( + curDate >= startDate && curDate <= endDate && - ride!.recurringDays?.includes(curDate.getDay()) - ); - }) - ) - .then((recurringParentRides: Ride[]) => - recurringParentRides.filter((parentRide) => { - const startTimeRecurringRide = new Date(parentRide.startTime); - startTimeRecurringRide.setFullYear(curDate.getFullYear()); - startTimeRecurringRide.setMonth(curDate.getMonth()); - startTimeRecurringRide.setDate(curDate.getDate()); - - const endTimeRecurringRide = new Date(parentRide.endTime); - endTimeRecurringRide.setFullYear(curDate.getFullYear()); - endTimeRecurringRide.setMonth(curDate.getMonth()); - endTimeRecurringRide.setDate(curDate.getDate()); - - return !ridesDataToday.some( - (rideToday) => - new Date(rideToday.startTime).getTime() === - startTimeRecurringRide.getTime() && - new Date(rideToday.endTime).getTime() === - endTimeRecurringRide.getTime() && - rideToday.startLocation.name === parentRide.startLocation.name && - rideToday.endLocation.name === parentRide.endLocation.name && - rideToday.rider.id === parentRide.rider.id + ride!.recurringDays?.includes(curDate.getDay()) && + !deletedDateList.some((d) => d.getDate() === curDate.getDate() && d.getMonth() === curDate.getMonth() && d.getFullYear() === curDate.getFullYear()) && + !editedDateList.some((d) => d.getDate() === curDate.getDate() && d.getMonth() === curDate.getMonth() && d.getFullYear() === curDate.getFullYear()) ); }) ) @@ -117,12 +94,13 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { endTime: endTimeRecurringRide.toISOString(), type: Type.UNSCHEDULED, parentRide: parentRide, + id : "" }; }) ); console.log('current date is ', curDate.getDate()); - + // const ridesDataTodayNoParentRec = ridesDataToday.filter((ride : Ride) => !(ride.recurring && ride.parentRide === undefined)); const combinedRidesData = ridesDataToday.concat(newRecurringRides); if (combinedRidesData) { setUnscheduledRides( From 9dd28d5a2b3ad82e287393008fb9f97b6ed0e628 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Tue, 29 Oct 2024 07:48:18 -0400 Subject: [PATCH 04/14] in the process of implementing --- .../Modal/DeleteOrEditTypeModal.tsx | 105 ++++++++++++--- .../CreateOrEditRideModal.tsx | 9 +- .../src/components/RequestRideModal/types.ts | 3 +- frontend/src/context/EmployeesContext.tsx | 2 +- frontend/src/context/RidesContext.tsx | 125 ++++++++++-------- server/src/models/ride.ts | 22 ++- 6 files changed, 183 insertions(+), 83 deletions(-) diff --git a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx index 0d3ca44a1..4fff20c5d 100644 --- a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx +++ b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx @@ -7,6 +7,8 @@ import { format_date } from '../../util/index'; import { ToastStatus, useToast } from '../../context/toastContext'; import { useRides } from '../../context/RidesContext'; import axios from '../../util/axios'; +import { useDate } from '../../context/date'; + type DeleteOrEditTypeModalProps = { open: boolean; @@ -26,6 +28,7 @@ const DeleteOrEditTypeModal = ({ isRider, }: DeleteOrEditTypeModalProps) => { const [single, setSingle] = useState(true); + const [allOrFollowing, setAllOrFollowing] = useState(true); // true means for all. const { showToast } = useToast(); const { refreshRides } = useRides(); @@ -34,23 +37,78 @@ const DeleteOrEditTypeModal = ({ setSingle(true); }; + //delete logic for normal rides and recurring rides (delete single, all, or from this ride and all following rides) const confirmCancel = () => { if (ride.recurring) { + //Need to fix the logic for this + const {curDate} = useDate(); if (single) { - let startDate = new Date(ride.startTime); - startDate = new Date(startDate.getFullYear(), startDate.getMonth(), startDate.getDate(), 0, 0, 0); - let parentDeletedDates : string[] = ride?.parentRide?.deleted === undefined ? [] : ride!.parentRide!.deleted; - parentDeletedDates.push(startDate.toISOString()); - axios - .put(`/api/rides/${ride!.parentRide!.id}`, {deleted: parentDeletedDates}) - .then(() => closeModal()) - .then(refreshRides); + /** + * trim end date of immediate parent to before this day. + * delete all children rides of the immediate parent. + * create a new ride on the date + 1 with data similar to parent if the parent’s original endTime allow for it. Add the id of the parent ride as the id of this ride’s parentId. + */ + const parentOriginalEndDate = new Date(ride.immediateParentRide!.endDate!); + + let trimmedEndDateImmPar = curDate; + trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); + + axios.put(`/api/rides/${ride.immediateParentRideId}`, {...ride.immediateParentRide, endDate : trimmedEndDateImmPar.toISOString()}); + let currentRide = (ride.immediateParentRide)!.children; + while (currentRide !== undefined) { + axios + .delete(`/api/rides/${currentRide.id}`); + currentRide = currentRide.children; + } + + if (parentOriginalEndDate > curDate) { + let newChildRideStartTime = new Date(ride.startTime) + newChildRideStartTime.setDate(newChildRideStartTime.getDate() + 1); + let {id, ...rideNoId} = ride; + const newChildRide = { + ...rideNoId, + startTime : newChildRideStartTime, + endDate : parentOriginalEndDate.toISOString(), + type : + 'unscheduled' + } + // axios.post('/api/rides', newChildRide).then((response) => response.data).then((data)); + } + + + } else { - console.log("hellow, del", ride!.parentRide!.id); - axios - .delete(`/api/rides/${ride!.parentRide!.id}`) - .then(() => closeModal()) - .then(refreshRides); + if (allOrFollowing) { + /** + * 1. go to source ride, delete itself all children rides + * 2. refreshRides + */ + let currentRide = ride.sourceRide; + while (currentRide !== undefined) { + axios + .delete(`/api/rides/${currentRide.id}`) + currentRide = currentRide.children; + } + closeModal(); + refreshRides(); + } else { + /** + * go to parent ride, trim enddate to before today, delete all children rides (not including itself) + * refreshRides + */ + let trimmedEndDateImmPar = (new Date(ride.immediateParentRide!.endDate!)); + trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); + axios.put(`/api/rides/${ride.immediateParentRideId}`, {...ride.immediateParentRide, endDate : trimmedEndDateImmPar.toISOString()}); + + let currentRide = (ride.immediateParentRide)!.children; + while (currentRide !== undefined) { + axios + .delete(`/api/rides/${currentRide.id}`); + currentRide = currentRide.children; + } + closeModal(); + refreshRides(); + } } } else { // console.log("hellow, del", ride!.id); @@ -69,6 +127,7 @@ const DeleteOrEditTypeModal = ({ setSingle(e.target.value === 'single'); }; + //bruh the fuck is onnext? const onButtonClick = () => { if (deleting) { confirmCancel(); @@ -128,15 +187,27 @@ const DeleteOrEditTypeModal = ({
changeSelection(e)} + value="allRecurring" + onClick={(e) => {changeSelection(e); setAllOrFollowing(true)}} /> -
+
+ {changeSelection(e); setAllOrFollowing(false)}} + /> + +
); }; -//need to add option to this to select whether to editsingle or not, shoulnd't be a prop passed in const RideModal = ({ open, close, ride }: RideModalProps) => { const originalRideData = getRideData(ride); const [formData, setFormData] = useState(originalRideData); const [isOpen, setIsOpen] = useState(open !== undefined ? open : false); const [currentPage, setCurrentPage] = useState(0); const [isSubmitted, setIsSubmitted] = useState(false); - const [editSingle, setEditSingle] = useState(true); + + const [editAddType, setEditAddType] = useState(EditAddRideType.SINGLE); + const {curDate} = useDate(); + + const { showToast } = useToast(); const { refreshRides } = useRides(); const [showRest, setShowRest] = useState(false); @@ -214,28 +236,88 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { }; } + + //shittttt, the new form data is in form data, should use that to get latest data about ride. if (ride) { // scheduled ride if (ride.type === 'active') { rideData.type = 'unscheduled'; } - if (editSingle) { - const daysWithEdits: string[] = - ride!.parentRide!.edits === undefined - ? [] - : ride!.parentRide!.edits; - daysWithEdits.push(new Date(ride.startTime).toISOString()); - axios - .put(`/api/rides/${ride!.parentRide!.id!}`, { - edits: daysWithEdits, - }) - .then(refreshRides); - // create new ride with no relation to parent ride - rideData = { ...rideData, parentRide: undefined }; - axios.post('/api/rides', rideData).then(refreshRides); + if (ride.recurring) { + if (editAddType == EditAddRideType.ALL) { + /** + * Go to the source ride, delete all children ride by recursing down the children’s id. + * apply edit to original + */ + let currentRide = ride.sourceRide?.children; + while (currentRide !== undefined) { + axios.delete(`/api/rides/${currentRide.id}`); + currentRide = currentRide.children; + } + axios + .put(`/api/rides/${ride.sourceRideId}`, rideData) + .then(refreshRides); + } else if (editAddType == EditAddRideType.THIS_AND_FOLLOWING) { + //ill finish this shit later bruh + //fuckkkk in this case we would need to lock the date. + /** + * trim the end date of the immediate parent to before today + * go down the tree of all children rides and delete all of them + * create a new ride with the edited data which has the parent and parentId be the immediate parent. + * refreshRides + */ + let trimmedEndDateImmPar = curDate; + trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); + axios.put(`/api/rides/${ride.immediateParentRideId}`, { + ...ride.immediateParentRide, + endDate: trimmedEndDateImmPar.toISOString(), + }); + + let currentRide = ride.immediateParentRide!.children; + while (currentRide !== undefined) { + axios.delete(`/api/rides/${currentRide.id}`); + currentRide = currentRide.children; + } + //now we create a recurring ride starting from today to the en + + + + + + + } else { + //edit single ride + /** + * Note: should also lock the date for simplicity. + * trim end date of immediate parent to before this day. + * add a new ride with the edited data on that date with immediateParent and immediateParentId being from the immediate parent. + * The children of the immediate parent is this ride. + * create a new recurring ride on the date + 1 with data similar to parent if the parent’s endTime allow for it. Add the id of the parent ride as the id of the newly created ride. + * refreshRides + */ + //dont need to lock the date. + let trimmedEndDateImmPar = curDate; + trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); + axios.put(`/api/rides/${ride.immediateParentRideId}`, { + ...ride.immediateParentRide, + endDate: trimmedEndDateImmPar.toISOString(), + }); + + // here i create a single ride linking back to the trimmed parent ride. it is a one off ride and should not be recurring. Should prob change/remove recurring days. + rideData = { + ...rideData, + immediateParentRideId : ride.immediateParentRideId, + sourceRideId : ride.sourceRideId, + recurring : false, + recurringDays: undefined, + endDate : undefined, + id : undefined + }; + axios.post(`/api/rides/`, rideData); + + } } else { - // edit ride or all instances of repeating ride - axios.put(`/api/rides/${ride!.parentRide!.id}`, rideData).then(refreshRides); + axios.put(`/api/rides/${ride.id}`, rideData).then(refreshRides); } } else { // unscheduled ride @@ -251,7 +333,7 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { formData, isSubmitted, ride, - editSingle, + editAddType, refreshRides, showToast, ]); @@ -267,7 +349,11 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { currentPage={currentPage} onClose={closeModal} > - {setEditSingle(recurring); goNextPage()}}/> + { + setEditAddType(e); + }} + /> Date: Fri, 1 Nov 2024 17:40:48 -0400 Subject: [PATCH 06/14] latest recurring rides impl --- .../Modal/DeleteOrEditTypeModal.tsx | 62 +++++++++++-------- .../src/components/RideModal/RideModal.tsx | 59 +++++++++++++++--- frontend/src/context/RidesContext.tsx | 35 +++++------ server/src/models/ride.ts | 30 ++++----- 4 files changed, 113 insertions(+), 73 deletions(-) diff --git a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx index 195215130..927fb618b 100644 --- a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx +++ b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx @@ -44,44 +44,52 @@ const DeleteOrEditTypeModal = ({ //Need to fix the logic for this if (single) { /** - * trim end date of immediate parent to before this day. - * delete all children rides of the immediate parent. - * create a new ride on the date + 1 with data similar to parent if the parent’s original endTime allow for it. Add the id of the parent ride as the id of this ride’s parentId. - * add childrenId to parent ride. + * trim the end date of the ride to before today, axios.put + * create a new recurring ride with the parent’s original end date (if that endate is > today) starting from today + 1 + * link that ride back to the parent, fill in parent and children fields. */ - const parentOriginalEndDate = new Date(ride.immediateParentRide!.endDate!); + //need to look at sourceride not ride. + const originalEndDate = new Date(ride.sourceRide!.endDate!); - let trimmedEndDateImmPar = curDate; - trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); + let newEndDate = curDate; + newEndDate.setDate(newEndDate.getDate() - 1); - axios.put(`/api/rides/${ride.immediateParentRideId}`, {...ride.immediateParentRide, endDate : trimmedEndDateImmPar.toISOString()}); - let currentRide = (ride.immediateParentRide)!.children; - while (currentRide !== undefined) { - axios - .delete(`/api/rides/${currentRide.id}`); - currentRide = currentRide.children; - } + axios.put(`/api/rides/${ride.id}`, {...ride.sourceRide!, endDate : newEndDate.toISOString()}); - if (parentOriginalEndDate > curDate) { - let newChildRideStartTime = new Date(ride.startTime) - newChildRideStartTime.setDate(newChildRideStartTime.getDate() + 1); - let {id, ...rideNoId} = ride; + if (originalEndDate > curDate) { + //create a new recurring ride with same data as the old one but with start date = curDate + 1. + let newRideStartTime = new Date(ride.sourceRide!.startTime); + newRideStartTime.setDate(curDate.getDate() + 1); + let newRideEndTime = new Date(ride.sourceRide!.endTime); + newRideEndTime.setDate(curDate.getDate() + 1); + + + let {id, ...rideNoId} = ride.sourceRide!; const newChildRide = { ...rideNoId, - startTime : newChildRideStartTime, - endDate : parentOriginalEndDate.toISOString(), - type : - 'unscheduled' + startTime : newRideStartTime.toISOString(), + endTime : newRideEndTime.toISOString(), + endDate : format_date(originalEndDate), + parentRideId : ride.id, + childRideId: ride.sourceRide!.childRideId, + recurring : true, + type : 'unscheduled' } axios .post('/api/rides', newChildRide) .then((response) => response.data) - .then((rideData) => - axios.put(`/api/rides/${ride.immediateParentRideId}`, {...ride.immediateParentRide, children : rideData, childrenId: rideData.id}) - ); - closeModal(); - refreshRides(); + .then((rideData) => { + axios.put(`/api/rides/${ride.id}`, {...ride.sourceRide!, childrenId: rideData.id}); + if (ride.sourceRide!.childRideId !== undefined) { + axios.put(`/api/rides/${ride.sourceRide!.childRideId}`, {...ride.sourceRide!.childRide, parentRideId : rideData.id}); + } + } + ); } + closeModal(); + refreshRides(); + + } else { if (allOrFollowing) { /** diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index aa8fac627..20d8437bc 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -37,6 +37,7 @@ const getRideData = (ride: Ride | undefined) => { dropoffLoc: ride.endLocation.id ? ride.endLocation.name : ride.endLocation.address, + }; if (ride.recurring) { let repeats; @@ -63,6 +64,12 @@ const getRideData = (ride: Ride | undefined) => { repeats, days, endDate: format_date(ride.endDate), + immediateParentRide : ride.immediateParentRide, + immediateParentRideId : ride.immediateParentRideId, + sourceRide : ride.sourceRide, + sourceRideId : ride.sourceRideId, + children: ride.children, + childrenId : ride.childrenId }; } return rideData; @@ -211,6 +218,12 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { rider, startLocation, endLocation, + immediateParentRide, + immediateParentRideId, + sourceRide, + sourceRideId, + children, + childrenId, } = formData; const startTime = moment(`${date} ${pickupTime}`).toISOString(); @@ -225,8 +238,16 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { rider, startLocation, endLocation, + immediateParentRide, + immediateParentRideId, + sourceRide, + sourceRideId, + children, + childrenId, }; + + //if the ride repeats if (repeats !== RepeatValues.DoesNotRepeat) { rideData = { ...rideData, @@ -237,7 +258,7 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { } - //shittttt, the new form data is in form data, should use that to get latest data about ride. + //shittttt, the new form data is in formData, should use that to get latest data about ride. if (ride) { // scheduled ride if (ride.type === 'active') { @@ -260,6 +281,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { } else if (editAddType == EditAddRideType.THIS_AND_FOLLOWING) { //ill finish this shit later bruh //fuckkkk in this case we would need to lock the date. + //here I don't think we need to lock recurring to false/true because if we edit this and following and just + //set it as a non recurring ride then it ends right there. /** * trim the end date of the immediate parent to before today * go down the tree of all children rides and delete all of them @@ -272,21 +295,41 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { ...ride.immediateParentRide, endDate: trimmedEndDateImmPar.toISOString(), }); + + //delete all children ride let currentRide = ride.immediateParentRide!.children; while (currentRide !== undefined) { axios.delete(`/api/rides/${currentRide.id}`); currentRide = currentRide.children; } - //now we create a recurring ride starting from today to the en - - - - - + //now we create a new ride starting from today to with the data in formData, but have it link back to the parent ride and the source ride. + // we also have to update the parentRide to have this ride as its children. + rideData = { + ...rideData, + immediateParentRide : ride.immediateParentRide, + immediateParentRideId : ride.immediateParentRideId, + sourceRide : ride.sourceRide, + sourceRideId : ride.sourceRideId, + children : undefined, + childrenId : undefined + } + //adds the new ride to the database and updates the parent ride to have it as the child. + axios + .post(`/api/rides`, rideData) + .then((response) => response.data) + + .then(data => axios.put(`/api/rides/${ride.immediateParentRideId}`, { + ...ride.immediateParentRide, + children: data, + childrenId : data.id + })) + .then(refreshRides); } else { - //edit single ride + //edit single ride, meaning that we should also lock the recurring to false, can't repeat. + //otherwise, you can do a thing where you add the new recurring ride and then another ride to continoue + //where that ride ended and resume with the parent ride's data. IDK yet, gotta ask desmond /** * Note: should also lock the date for simplicity. * trim end date of immediate parent to before this day. diff --git a/frontend/src/context/RidesContext.tsx b/frontend/src/context/RidesContext.tsx index 967bc4227..547961519 100644 --- a/frontend/src/context/RidesContext.tsx +++ b/frontend/src/context/RidesContext.tsx @@ -71,46 +71,41 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { ); }) //here, i am creating repeating ride objects (that doesn't exist in the database) that link back to some ride in the database. - .map((parentRide) => { - const startTimeRecurringRide = new Date(parentRide.startTime); + .map((filteredSourceRide) => { + const startTimeRecurringRide = new Date(filteredSourceRide.startTime); startTimeRecurringRide.setFullYear(curDate.getFullYear()); startTimeRecurringRide.setMonth(curDate.getMonth()); startTimeRecurringRide.setDate(curDate.getDate()); - const endTimeRecurringRide = new Date(parentRide.endTime); + const endTimeRecurringRide = new Date(filteredSourceRide.endTime); endTimeRecurringRide.setFullYear(curDate.getFullYear()); endTimeRecurringRide.setMonth(curDate.getMonth()); endTimeRecurringRide.setDate(curDate.getDate()); const schedule = - new Date(parentRide.startTime).getDay() == curDate.getDay() && - new Date(parentRide.startTime).getMonth() == curDate.getMonth() && - new Date(parentRide.startTime).getFullYear() == curDate.getFullYear() + new Date(filteredSourceRide.startTime).getDay() == curDate.getDay() && + new Date(filteredSourceRide.startTime).getMonth() == curDate.getMonth() && + new Date(filteredSourceRide.startTime).getFullYear() == curDate.getFullYear() ? Type.ACTIVE : Type.UNSCHEDULED; - - const immediateParentRideId = parentRide.id; - const sourceRideId = parentRide.sourceRideId; - - const immediateParentRide = recurringRides.find((ride) => ride.id === immediateParentRideId); - const sourceRide = recurringRides.find((ride) => ride.id === sourceRideId); + + const parentRide = recurringRides.find((ride) => ride.id === filteredSourceRide.parentRideId); + const childrenRide = recurringRides.find((ride) => ride.id === filteredSourceRide.childRideId); return { - ...parentRide, + ...filteredSourceRide, // id should be the same as the sourceRide startTime: startTimeRecurringRide.toISOString(), endTime: endTimeRecurringRide.toISOString(), type: schedule, - immediateParentRideId: immediateParentRideId, - sourceRideId : sourceRideId, - immediateParentRide, - sourceRide, - id: '', + parentRide: parentRide, + parentRideId: parentRide?.id, + childrenRide : childrenRide, + childrenRideId : childrenRide?.id, + sourceRide : filteredSourceRide }; }); - console.log('current date is ', curDate.getDate()); - // const ridesDataTodayNoParentRec = ridesDataToday.filter((ride : Ride) => !(ride.recurring && ride.parentRide === undefined)); const combinedRidesData = nonRecurringRidesDataToday.concat(recurringRidesToday); if (combinedRidesData) { diff --git a/server/src/models/ride.ts b/server/src/models/ride.ts index dd96d8ea0..5fdbb22c5 100644 --- a/server/src/models/ride.ts +++ b/server/src/models/ride.ts @@ -46,11 +46,10 @@ export type RideType = { deleted?: string[]; edits?: string[]; sourceRide? : RideType; - immediateParentRide?: RideType; - children? : RideType; // id of the children ride. Used for recurring rides. - sourceRideId? : string; - immediateParentRideId? : string; - childrenId? : string; + parentRide? : RideType; + parentRideId? : string; + childrenRide? : RideType; + childrenRideId? : string; }; const locationSchema = { @@ -128,21 +127,16 @@ const schema = new dynamoose.Schema({ required: false, validate: /^(19|20)\d{2}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/, }, - immediateParentRideId : { - type: String, - required: false, - hashKey: true, + parentRideId : { + type : String, + required : false, + hashKey: true }, - sourceRideId : { - type: String, - required: false, - hashKey: true, + childrenRideId : { + type : String, + required : false, + hashKey: true }, - childrenId : { - type: String, - required: false, - hashKey: true, - } }); export const Ride = dynamoose.model('Rides', schema, defaultModelConfig); From a14e6a36813a4e17f89f701f27fdd5b767a4086b Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Fri, 1 Nov 2024 19:06:49 -0400 Subject: [PATCH 07/14] changed type --- server/src/models/ride.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/server/src/models/ride.ts b/server/src/models/ride.ts index 5fdbb22c5..2ea2357b1 100644 --- a/server/src/models/ride.ts +++ b/server/src/models/ride.ts @@ -43,13 +43,13 @@ export type RideType = { recurring: boolean; recurringDays?: number[]; endDate?: string; - deleted?: string[]; - edits?: string[]; + //ride data should be as similar to sourceRide as possible + sourceRide? : RideType; parentRide? : RideType; parentRideId? : string; - childrenRide? : RideType; - childrenRideId? : string; + childRide? : RideType; + childRideId? : string; }; const locationSchema = { From 936da4f1687e77262c7662d412f2151d9195ba20 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Mon, 4 Nov 2024 03:07:20 -0500 Subject: [PATCH 08/14] latest --- .../Modal/DeleteOrEditTypeModal.tsx | 16 +++-- .../src/components/RideModal/RideModal.tsx | 64 ++++++++++++------- 2 files changed, 50 insertions(+), 30 deletions(-) diff --git a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx index 927fb618b..4e06d8ebd 100644 --- a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx +++ b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx @@ -93,31 +93,33 @@ const DeleteOrEditTypeModal = ({ } else { if (allOrFollowing) { /** - * 1. go to source ride, delete itself all children rides + * 1. Go up to find the ancestor ride and delete all descendants, including itself. * 2. refreshRides */ + + //traverse to the ancestor and delete all rides along the way. let currentRide = ride.sourceRide; while (currentRide !== undefined) { axios .delete(`/api/rides/${currentRide.id}`) - currentRide = currentRide.children; + currentRide = currentRide.parentRide; } closeModal(); refreshRides(); } else { /** - * go to parent ride, trim enddate to before today, delete all children rides (not including itself) - * refreshRides + * trim the ride’s parent date to before today, axios put + * delete all descendants of the parent’s ride., axios delete */ let trimmedEndDateImmPar = curDate; trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); - axios.put(`/api/rides/${ride.immediateParentRideId}`, {...ride.immediateParentRide, endDate : trimmedEndDateImmPar.toISOString()}); + axios.put(`/api/rides/${ride.sourceRide}`, {...ride.sourceRide, endDate : trimmedEndDateImmPar.toISOString()}); - let currentRide = (ride.immediateParentRide)!.children; + let currentRide = ride.childRide; while (currentRide !== undefined) { axios .delete(`/api/rides/${currentRide.id}`); - currentRide = currentRide.children; + currentRide = currentRide.childRide; } closeModal(); refreshRides(); diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index 20d8437bc..9d4c36d70 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -64,12 +64,12 @@ const getRideData = (ride: Ride | undefined) => { repeats, days, endDate: format_date(ride.endDate), - immediateParentRide : ride.immediateParentRide, - immediateParentRideId : ride.immediateParentRideId, + parentRide : ride.parentRide, + parentRideId : ride.parentRideId, sourceRide : ride.sourceRide, - sourceRideId : ride.sourceRideId, - children: ride.children, - childrenId : ride.childrenId + sourceRideId : ride.sourceRide, + childRide: ride.childRide, + childRideId : ride.childRideId }; } return rideData; @@ -266,35 +266,53 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { } if (ride.recurring) { if (editAddType == EditAddRideType.ALL) { + //need to show them the data of the sourceRide to edit. /** - * Go to the source ride, delete all children ride by recursing down the children’s id. - * apply edit to original + * go up the chain to the ancestor ride + * delete all children by going down the linked list + * apply edit to the ancestor. */ - let currentRide = ride.sourceRide?.children; - while (currentRide !== undefined) { + let currentRide = ride.sourceRide!; + while (currentRide.parentRide !== undefined) { axios.delete(`/api/rides/${currentRide.id}`); - currentRide = currentRide.children; + currentRide = currentRide.parentRide; } axios - .put(`/api/rides/${ride.sourceRideId}`, rideData) + .put(`/api/rides/${ride.id}`, rideData) .then(refreshRides); } else if (editAddType == EditAddRideType.THIS_AND_FOLLOWING) { - //ill finish this shit later bruh - //fuckkkk in this case we would need to lock the date. - //here I don't think we need to lock recurring to false/true because if we edit this and following and just - //set it as a non recurring ride then it ends right there. + //need to show them the data of the current ride, so don't need to change anything. /** - * trim the end date of the immediate parent to before today - * go down the tree of all children rides and delete all of them - * create a new ride with the edited data which has the parent and parentId be the immediate parent. - * refreshRides + * Note: lock the day and recurring (recurring must be false). + * trim its end date: change its end date then axios put with id and with sourceRide end date changed. + * Create a new ride on that day, have the ride above as its parent and parentId, axios.post. Also axios put the parent ride above to have children as this new ride. + * After this, add another recurring ride with the original ride end date and information (if the end date is larger than today). + * Link this ride to the single non recurring ride you just created: axios put appropriate parent and children field. */ + + //delete ride if enddate is before startdate. also have to axios put children's parent to undefined. let trimmedEndDateImmPar = curDate; trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); - axios.put(`/api/rides/${ride.immediateParentRideId}`, { - ...ride.immediateParentRide, - endDate: trimmedEndDateImmPar.toISOString(), - }); + + let sourceRideStartDate = new Date(ride.sourceRide!.startTime); + sourceRideStartDate.setHours(0, 0, 0); + if (trimmedEndDateImmPar >= sourceRideStartDate) + axios.put(`/api/rides/${ride.id}`, { + ...ride.sourceRide, + endDate: trimmedEndDateImmPar.toISOString(), + }); + else { + axios + .delete(`/api/rides/${ride.id}`) + .then((response) => { + axios.put(`/api/rides/${ride.childRideId}`, { + ...ride.childRide, + parentRideId : undefined + }); + }); + + + } //delete all children ride From 830220feb5b8e023bce0b376a23373c09efff176 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Tue, 5 Nov 2024 16:34:15 -0500 Subject: [PATCH 09/14] implemented add and delete recurring rides on the admin side, now need to fix bug when axios.put --- .../Modal/DeleteOrEditTypeModal.tsx | 55 ++++-- .../src/components/RideModal/RideModal.tsx | 177 ++++++++++-------- .../UserTables/RiderScheduleTable.tsx | 69 +------ frontend/src/context/EmployeesContext.tsx | 2 +- frontend/src/context/RidesContext.tsx | 2 +- server/src/models/ride.ts | 2 - 6 files changed, 146 insertions(+), 161 deletions(-) diff --git a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx index 4e06d8ebd..972fc225a 100644 --- a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx +++ b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx @@ -48,13 +48,25 @@ const DeleteOrEditTypeModal = ({ * create a new recurring ride with the parent’s original end date (if that endate is > today) starting from today + 1 * link that ride back to the parent, fill in parent and children fields. */ - //need to look at sourceride not ride. const originalEndDate = new Date(ride.sourceRide!.endDate!); let newEndDate = curDate; newEndDate.setDate(newEndDate.getDate() - 1); + newEndDate.setHours(0, 0, 0); - axios.put(`/api/rides/${ride.id}`, {...ride.sourceRide!, endDate : newEndDate.toISOString()}); + let sourceRideStartDate = new Date(ride.sourceRide!.startTime); + sourceRideStartDate.setHours(0, 0, 0); + let deletedSourceRide = false; + + if (sourceRideStartDate <= newEndDate) { + const {id, parentRide, childRide, sourceRide, ...sourceRidewithoutRideTypes} = ride.sourceRide!; + axios.put(`/api/rides/${ride.id}`, {...sourceRidewithoutRideTypes, endDate : newEndDate.toISOString()}); + ride.sourceRide! = {...ride.sourceRide!, endDate : newEndDate.toISOString()}; + } else { + // if enddate is a day before the sourceRide start date then delete + deletedSourceRide = true; + axios.delete(`/api/rides/${ride.id}`); + } if (originalEndDate > curDate) { //create a new recurring ride with same data as the old one but with start date = curDate + 1. @@ -79,17 +91,19 @@ const DeleteOrEditTypeModal = ({ .post('/api/rides', newChildRide) .then((response) => response.data) .then((rideData) => { - axios.put(`/api/rides/${ride.id}`, {...ride.sourceRide!, childrenId: rideData.id}); + if (!deletedSourceRide) { + const {id, parentRide, childRide, sourceRide, ...sourceRidewithoutRideTypes} = ride.sourceRide!; + axios.put(`/api/rides/${ride.id}`, {...sourceRidewithoutRideTypes, childRideId: rideData.id}); + } if (ride.sourceRide!.childRideId !== undefined) { - axios.put(`/api/rides/${ride.sourceRide!.childRideId}`, {...ride.sourceRide!.childRide, parentRideId : rideData.id}); + const {id, parentRide, childRide, sourceRide, ...childRidewithoutRideTypes} = ride.sourceRide!.childRide!; + axios.put(`/api/rides/${ride.sourceRide!.childRide!.id}`, {...childRidewithoutRideTypes, parentRideId : rideData.id}); } } ); - } + } closeModal(); refreshRides(); - - } else { if (allOrFollowing) { /** @@ -99,11 +113,15 @@ const DeleteOrEditTypeModal = ({ //traverse to the ancestor and delete all rides along the way. let currentRide = ride.sourceRide; - while (currentRide !== undefined) { - axios - .delete(`/api/rides/${currentRide.id}`) + while (currentRide?.parentRide !== undefined) { currentRide = currentRide.parentRide; } + // now current ride is at the beginning of linked list + while (currentRide !== undefined) { + axios.delete(`/api/rides/${currentRide.id}`); + currentRide = currentRide.childRide; + } + closeModal(); refreshRides(); } else { @@ -111,10 +129,19 @@ const DeleteOrEditTypeModal = ({ * trim the ride’s parent date to before today, axios put * delete all descendants of the parent’s ride., axios delete */ - let trimmedEndDateImmPar = curDate; - trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); - axios.put(`/api/rides/${ride.sourceRide}`, {...ride.sourceRide, endDate : trimmedEndDateImmPar.toISOString()}); - + let newEndDate = curDate; + newEndDate.setDate(newEndDate.getDate() - 1); + newEndDate.setHours(0, 0, 0); + + let sourceRideStartDate = new Date(ride.sourceRide!.startTime); + sourceRideStartDate.setHours(0, 0, 0); + + //if start date of source ride > trimmedEndate then need to delete + if (sourceRideStartDate <= newEndDate) { + axios.put(`/api/rides/${ride.id}`, {...ride.sourceRide, endDate : newEndDate.toISOString()}); + } else { + axios.delete(`/api/rides/${ride.id}`) + } let currentRide = ride.childRide; while (currentRide !== undefined) { axios diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index 9d4c36d70..630b6d797 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -64,11 +64,8 @@ const getRideData = (ride: Ride | undefined) => { repeats, days, endDate: format_date(ride.endDate), - parentRide : ride.parentRide, parentRideId : ride.parentRideId, - sourceRide : ride.sourceRide, sourceRideId : ride.sourceRide, - childRide: ride.childRide, childRideId : ride.childRideId }; } @@ -161,7 +158,6 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { setIsOpen(true); }; - // console.log("HELLO MATEW"); const closeModal = useCallback(() => { if (close) { setFormData(originalRideData); @@ -218,12 +214,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { rider, startLocation, endLocation, - immediateParentRide, - immediateParentRideId, - sourceRide, - sourceRideId, - children, - childrenId, + parentRideId, + childRideId, } = formData; const startTime = moment(`${date} ${pickupTime}`).toISOString(); @@ -238,12 +230,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { rider, startLocation, endLocation, - immediateParentRide, - immediateParentRideId, - sourceRide, - sourceRideId, - children, - childrenId, + parentRideId, + childRideId }; @@ -267,114 +255,148 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { if (ride.recurring) { if (editAddType == EditAddRideType.ALL) { //need to show them the data of the sourceRide to edit. + //have to ask desmond /** * go up the chain to the ancestor ride * delete all children by going down the linked list * apply edit to the ancestor. */ - let currentRide = ride.sourceRide!; - while (currentRide.parentRide !== undefined) { - axios.delete(`/api/rides/${currentRide.id}`); + let currentRide = ride.sourceRide; + while (currentRide?.parentRide !== undefined) { currentRide = currentRide.parentRide; } + //now currentRides is at the beginning of linked list + currentRide = currentRide?.childRide; + while (currentRide !== undefined) { + axios.delete(`/api/rides/${currentRide.id}`); + currentRide = currentRide.childRide; + } + //now all elements except the beginning has been deleted. + axios .put(`/api/rides/${ride.id}`, rideData) .then(refreshRides); } else if (editAddType == EditAddRideType.THIS_AND_FOLLOWING) { //need to show them the data of the current ride, so don't need to change anything. - /** - * Note: lock the day and recurring (recurring must be false). - * trim its end date: change its end date then axios put with id and with sourceRide end date changed. - * Create a new ride on that day, have the ride above as its parent and parentId, axios.post. Also axios put the parent ride above to have children as this new ride. - * After this, add another recurring ride with the original ride end date and information (if the end date is larger than today). - * Link this ride to the single non recurring ride you just created: axios put appropriate parent and children field. - */ + + // lock the start date (date) + // trim the date of this ride, axios.put + // create a new ride, do whatever, can be a single non repeating ride. + // should not link back to parent (gcal does this) + //delete ride if enddate is before startdate. also have to axios put children's parent to undefined. let trimmedEndDateImmPar = curDate; trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); + trimmedEndDateImmPar.setHours(0, 0, 0); let sourceRideStartDate = new Date(ride.sourceRide!.startTime); sourceRideStartDate.setHours(0, 0, 0); - if (trimmedEndDateImmPar >= sourceRideStartDate) + + if (trimmedEndDateImmPar >= sourceRideStartDate) { + const {id, parentRide, childRide, sourceRide, ...sourceRidewithoutRideTypes} = ride.sourceRide!; + axios.put(`/api/rides/${ride.id}`, { - ...ride.sourceRide, + ...sourceRidewithoutRideTypes, endDate: trimmedEndDateImmPar.toISOString(), }); - else { - axios - .delete(`/api/rides/${ride.id}`) - .then((response) => { - axios.put(`/api/rides/${ride.childRideId}`, { - ...ride.childRide, - parentRideId : undefined - }); - }); - - + console.log(sourceRideStartDate); + ride.sourceRide! = {...ride.sourceRide!, endDate: trimmedEndDateImmPar.toISOString()} + } else { + axios.delete(`/api/rides/${ride.id}`) } - //delete all children ride - let currentRide = ride.immediateParentRide!.children; + //delete all descendants ride of sourceRide. + let currentRide = ride.sourceRide?.childRide; while (currentRide !== undefined) { axios.delete(`/api/rides/${currentRide.id}`); - currentRide = currentRide.children; + currentRide = currentRide.childRide; } - //now we create a new ride starting from today to with the data in formData, but have it link back to the parent ride and the source ride. - // we also have to update the parentRide to have this ride as its children. + //now we create a new ride starting from today to with the data in formData, but have it doesn't link back rideData = { ...rideData, - immediateParentRide : ride.immediateParentRide, - immediateParentRideId : ride.immediateParentRideId, - sourceRide : ride.sourceRide, - sourceRideId : ride.sourceRideId, - children : undefined, - childrenId : undefined + parentRideId : undefined, + childRideId : undefined } //adds the new ride to the database and updates the parent ride to have it as the child. axios .post(`/api/rides`, rideData) .then((response) => response.data) - - .then(data => axios.put(`/api/rides/${ride.immediateParentRideId}`, { - ...ride.immediateParentRide, - children: data, - childrenId : data.id - })) .then(refreshRides); } else { - //edit single ride, meaning that we should also lock the recurring to false, can't repeat. - //otherwise, you can do a thing where you add the new recurring ride and then another ride to continoue - //where that ride ended and resume with the parent ride's data. IDK yet, gotta ask desmond - /** - * Note: should also lock the date for simplicity. - * trim end date of immediate parent to before this day. - * add a new ride with the edited data on that date with immediateParent and immediateParentId being from the immediate parent. - * The children of the immediate parent is this ride. - * create a new recurring ride on the date + 1 with data similar to parent if the parent’s endTime allow for it. Add the id of the parent ride as the id of the newly created ride. - * refreshRides - */ - //dont need to lock the date. + + // Note: lock the day and recurring (recurring must be false). + // trim its end date: change its end date then axios put with id and with sourceRide end date changed. + // Create a new ride on that day, have the ride above as its parent and parentId, axios.post. Also axios put the parent ride above to have children as this new ride. + // After this, add another recurring ride with the original ride end date and information (if the end date is larger than today). + // Link this ride to the single non recurring ride you just created: axios put appropriate parent and children field. + let trimmedEndDateImmPar = curDate; - trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); - axios.put(`/api/rides/${ride.immediateParentRideId}`, { - ...ride.immediateParentRide, - endDate: trimmedEndDateImmPar.toISOString(), - }); + trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); + trimmedEndDateImmPar.setHours(0, 0, 0); + + let sourceRideStartDate = new Date(ride.sourceRide!.startTime); + sourceRideStartDate.setHours(0, 0, 0); + let deletedSourceRide = false; + + + if (trimmedEndDateImmPar >= sourceRideStartDate) { + const {id, parentRide, childRide, sourceRide, ...sourceRidewithoutRideTypes} = ride.sourceRide!; + console.log(sourceRidewithoutRideTypes); + + axios.put(`/api/rides/${ride.id}`, { + ...sourceRidewithoutRideTypes, + endDate: trimmedEndDateImmPar.toISOString(), + }); + ride.sourceRide! = {...ride.sourceRide!, endDate: trimmedEndDateImmPar.toISOString()} + deletedSourceRide = true; + } else { + axios.delete(`/api/rides/${ride.id}`) + } - // here i create a single ride linking back to the trimmed parent ride. it is a one off ride and should not be recurring. Should prob change/remove recurring days. rideData = { ...rideData, - immediateParentRideId : ride.immediateParentRideId, - sourceRideId : ride.sourceRideId, + parentRideId : deletedSourceRide ? undefined: ride.id, + sourceRideId : undefined, recurring : false, recurringDays: undefined, endDate : undefined, id : undefined }; - axios.post(`/api/rides/`, rideData); + //here, we add the new ride with the changed data and then add + //another recurring ride after with the same data as sourceRide + + const originalEndDate = new Date(ride.sourceRide!.endDate!); + + axios + .post(`/api/rides/`, rideData) + .then((response) => response.data) + .then((data) => { + console.log(originalEndDate); + if (originalEndDate > curDate) { + //create a new recurring ride with same data as the old one but with start date = curDate + 1. + let newRideStartTime = new Date(ride.sourceRide!.startTime); + newRideStartTime.setDate(curDate.getDate() + 1); + let newRideEndTime = new Date(ride.sourceRide!.endTime); + newRideEndTime.setDate(curDate.getDate() + 1); + + + const {id, parentRide, childRide, sourceRide, ...sourceRidewithoutRideTypes} = ride.sourceRide!; + + axios.post(`/api/rides/`, { + ...sourceRidewithoutRideTypes, + startTime : newRideStartTime.toISOString(), + endTime : newRideEndTime.toISOString(), + endDate : format_date(originalEndDate), + parentRideId : data.id, + childRideId: ride.sourceRide!.childRideId, + recurring : true, + type : 'unscheduled' + }); + } + }); } } else { @@ -413,6 +435,7 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { { setEditAddType(e); + goNextPage(); }} /> { }; // returns a list of dummy recurring rides - const generateRecurringRides = useCallback( - (rides: Ride[]): Ride[] => { - const recurringRides: Ride[] = []; - rides.forEach((originalRide) => { - let origEndDate; - if (originalRide.recurring) { - origEndDate = moment(originalRide.endDate!); - } - // create dummy rides only for active recurring rides - if (origEndDate && origEndDate >= moment(curDate)) { - const origStartTime = moment(originalRide.startTime); - const rideStart = origStartTime; - const days = originalRide.recurringDays!; - let dayIndex = days.indexOf(rideStart.day()); - while (rideStart <= origEndDate) { - // find the next occurrence - dayIndex = dayIndex === days.length - 1 ? 0 : dayIndex + 1; - const daysUntilNextOccurrence = daysUntilWeekday( - rideStart, - days[dayIndex] - ); - rideStart.date(rideStart.date() + daysUntilNextOccurrence); - const now = moment(); - const rideGenerationTime = moment().hour(10).minute(5); - const tomorrow = moment().add(1, 'day').startOf('day'); - const rideHasOccurred = now.isAfter(rideStart); - const rideHasBeenGenerated = - now.isAfter(rideGenerationTime) && - rideStart.isSame(tomorrow, 'day'); - const shouldRideDisplay = !( - rideHasOccurred || rideHasBeenGenerated - ); - - // add to list if ride's start date is not in list of deleted dates - if ( - !originalRide.deleted?.includes(rideStart.format('YYYY-MM-DD')) && - rideStart.isSameOrBefore(origEndDate, 'day') && - shouldRideDisplay - ) { - const rideInstance: Ride = { - id: originalRide.id, - parentRide: originalRide, - type: Type.UNSCHEDULED, - status: Status.NOT_STARTED, - startLocation: originalRide.startLocation, - endLocation: originalRide.endLocation, - startTime: rideStart.toISOString(), - endTime: originalRide.endTime, - rider: originalRide.rider, - driver: originalRide.driver, - recurring: true, - late: false, - recurringDays: originalRide.recurringDays, - endDate: originalRide.endDate, - }; - recurringRides.push(rideInstance); - } - } - } - }); - return recurringRides; - }, - [curDate] - ); + // returns a map with date as keys and a list of rides as values const getRideMap = useCallback((rides: Ride[]): ObjectType => { @@ -135,10 +72,10 @@ const RiderScheduleTable = ({ data, isPast }: RiderScheduleTableProp) => { }, []); useEffect(() => { - let allRides = generateRecurringRides(data).concat(data); + let allRides = (data); allRides = allRides.filter(filterRides).sort(compRides); rideMapToArray(getRideMap(allRides)); - }, [compRides, data, filterRides, generateRecurringRides, getRideMap]); + }, [compRides, data, filterRides, getRideMap]); // returns date in the format "MM/DD/YYYY" const formatDate = (date: string): string => diff --git a/frontend/src/context/EmployeesContext.tsx b/frontend/src/context/EmployeesContext.tsx index eec5c9c5f..3fe2a7150 100644 --- a/frontend/src/context/EmployeesContext.tsx +++ b/frontend/src/context/EmployeesContext.tsx @@ -39,7 +39,7 @@ export const EmployeesProvider = ({ children }: EmployeesProviderProps) => { const refreshDrivers = useCallback(async () => { const driversData: Array = await axios - .get('//drivers') + .get('/api/drivers') .then((res) => res.data) .then((data) => data.data); diff --git a/frontend/src/context/RidesContext.tsx b/frontend/src/context/RidesContext.tsx index 547961519..8ee304b10 100644 --- a/frontend/src/context/RidesContext.tsx +++ b/frontend/src/context/RidesContext.tsx @@ -83,7 +83,7 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { endTimeRecurringRide.setDate(curDate.getDate()); const schedule = - new Date(filteredSourceRide.startTime).getDay() == curDate.getDay() && + new Date(filteredSourceRide.startTime).getDate() == curDate.getDate() && new Date(filteredSourceRide.startTime).getMonth() == curDate.getMonth() && new Date(filteredSourceRide.startTime).getFullYear() == curDate.getFullYear() ? Type.ACTIVE diff --git a/server/src/models/ride.ts b/server/src/models/ride.ts index 2ea2357b1..4887a0ee5 100644 --- a/server/src/models/ride.ts +++ b/server/src/models/ride.ts @@ -130,12 +130,10 @@ const schema = new dynamoose.Schema({ parentRideId : { type : String, required : false, - hashKey: true }, childrenRideId : { type : String, required : false, - hashKey: true }, }); From e174c7c482bb3588f658592745bd0bd23cfd0499 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Wed, 6 Nov 2024 15:33:14 -0500 Subject: [PATCH 10/14] still bug fixing --- .../src/components/RideModal/RideModal.tsx | 34 ++++++------------- server/src/models/ride.ts | 8 ----- 2 files changed, 10 insertions(+), 32 deletions(-) diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index 630b6d797..f4a5e48d2 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -3,14 +3,12 @@ import moment from 'moment'; import Modal from '../Modal/Modal'; import { Input, Label, Button } from '../FormElements/FormElements'; import { DriverPage, RiderInfoPage, RideTimesPage } from './Pages'; -import { ObjectType, RepeatValues, Ride } from '../../types/index'; +import { ObjectType, RepeatValues, Ride, Type } from '../../types/index'; import { format_date } from '../../util/index'; import { useRides } from '../../context/RidesContext'; import { useDate } from '../../context/date'; import { ToastStatus, useToast } from '../../context/toastContext'; import axios from '../../util/axios'; -import DeleteOrEditTypeModal from 'components/Modal/DeleteOrEditTypeModal'; -import { isOutOfBounds } from 'react-datepicker/dist/date_utils'; type RideModalProps = { open?: boolean; @@ -294,14 +292,9 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { sourceRideStartDate.setHours(0, 0, 0); if (trimmedEndDateImmPar >= sourceRideStartDate) { - const {id, parentRide, childRide, sourceRide, ...sourceRidewithoutRideTypes} = ride.sourceRide!; - - axios.put(`/api/rides/${ride.id}`, { - ...sourceRidewithoutRideTypes, - endDate: trimmedEndDateImmPar.toISOString(), - }); - console.log(sourceRideStartDate); ride.sourceRide! = {...ride.sourceRide!, endDate: trimmedEndDateImmPar.toISOString()} + axios.put(`/api/rides/${ride.id}`, getRideData(ride.sourceRide!)); + console.log(sourceRideStartDate); } else { axios.delete(`/api/rides/${ride.id}`) } @@ -343,14 +336,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { if (trimmedEndDateImmPar >= sourceRideStartDate) { - const {id, parentRide, childRide, sourceRide, ...sourceRidewithoutRideTypes} = ride.sourceRide!; - console.log(sourceRidewithoutRideTypes); - - axios.put(`/api/rides/${ride.id}`, { - ...sourceRidewithoutRideTypes, - endDate: trimmedEndDateImmPar.toISOString(), - }); ride.sourceRide! = {...ride.sourceRide!, endDate: trimmedEndDateImmPar.toISOString()} + axios.put(`/api/rides/${ride.id}`, getRideData(ride.sourceRide!)); deletedSourceRide = true; } else { axios.delete(`/api/rides/${ride.id}`) @@ -382,19 +369,18 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { let newRideEndTime = new Date(ride.sourceRide!.endTime); newRideEndTime.setDate(curDate.getDate() + 1); - - const {id, parentRide, childRide, sourceRide, ...sourceRidewithoutRideTypes} = ride.sourceRide!; - - axios.post(`/api/rides/`, { - ...sourceRidewithoutRideTypes, + ride.sourceRide! = { + ...ride.sourceRide!, startTime : newRideStartTime.toISOString(), endTime : newRideEndTime.toISOString(), endDate : format_date(originalEndDate), parentRideId : data.id, childRideId: ride.sourceRide!.childRideId, recurring : true, - type : 'unscheduled' - }); + type : Type.UNSCHEDULED + }; + + axios.post(`/api/rides/`, getRideData(ride.sourceRide!)); } }); diff --git a/server/src/models/ride.ts b/server/src/models/ride.ts index 4887a0ee5..7105ea5a6 100644 --- a/server/src/models/ride.ts +++ b/server/src/models/ride.ts @@ -114,14 +114,6 @@ const schema = new dynamoose.Schema({ type: Array, schema: [Number], }, - deleted: { - type: Array, - schema: [String], - }, - edits: { - type: Array, - schema: [String], - }, endDate: { type: String, required: false, From a344cb32f364de6946a4324abc4f65bef8babd90 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Wed, 6 Nov 2024 15:51:46 -0500 Subject: [PATCH 11/14] minor changes to form data in RideModal --- frontend/src/components/RideModal/RideModal.tsx | 6 ++---- server/src/models/ride.ts | 4 +--- 2 files changed, 3 insertions(+), 7 deletions(-) diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index f4a5e48d2..52b725260 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -212,8 +212,6 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { rider, startLocation, endLocation, - parentRideId, - childRideId, } = formData; const startTime = moment(`${date} ${pickupTime}`).toISOString(); @@ -228,8 +226,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { rider, startLocation, endLocation, - parentRideId, - childRideId + parentRideId : ride!.parentRideId, + childRideId: ride!.childRideId }; diff --git a/server/src/models/ride.ts b/server/src/models/ride.ts index 7105ea5a6..c49fada92 100644 --- a/server/src/models/ride.ts +++ b/server/src/models/ride.ts @@ -42,9 +42,7 @@ export type RideType = { driver?: DriverType; recurring: boolean; recurringDays?: number[]; - endDate?: string; - //ride data should be as similar to sourceRide as possible - + endDate?: string; sourceRide? : RideType; parentRide? : RideType; parentRideId? : string; From c7c44b7d0d04d96147e57dd1f5b718013e8a8490 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Sat, 9 Nov 2024 16:14:13 -0500 Subject: [PATCH 12/14] fixed timezone issue, now can edit a single ride in a chain of repeating rides, but deleting is still an issue because updating childRideId everytime an axios.put or axios.post is called is wrong --- .../Modal/DeleteOrEditTypeModal.tsx | 5 +- .../components/RideModal/Pages/RideTimes.tsx | 2 +- .../src/components/RideModal/RideModal.tsx | 158 ++++++++++++++---- frontend/src/context/RidesContext.tsx | 51 +++--- server/src/models/ride.ts | 5 + server/src/router/ride.ts | 2 +- 6 files changed, 162 insertions(+), 61 deletions(-) diff --git a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx index 972fc225a..85fa7fdc6 100644 --- a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx +++ b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx @@ -113,11 +113,12 @@ const DeleteOrEditTypeModal = ({ //traverse to the ancestor and delete all rides along the way. let currentRide = ride.sourceRide; - while (currentRide?.parentRide !== undefined) { - currentRide = currentRide.parentRide; + while (currentRide!.parentRide !== undefined) { + currentRide = currentRide!.parentRide; } // now current ride is at the beginning of linked list while (currentRide !== undefined) { + console.log("hello, deleting all, current Ride is", currentRide); axios.delete(`/api/rides/${currentRide.id}`); currentRide = currentRide.childRide; } diff --git a/frontend/src/components/RideModal/Pages/RideTimes.tsx b/frontend/src/components/RideModal/Pages/RideTimes.tsx index a797d7ae8..99b0f8e87 100644 --- a/frontend/src/components/RideModal/Pages/RideTimes.tsx +++ b/frontend/src/components/RideModal/Pages/RideTimes.tsx @@ -119,7 +119,7 @@ const RepeatSection: React.FC = ({ repeatValue }) => { {...register('endDate', { required: true, validate: (endDate: string) => { - const fmtEnd = format_date(endDate); + const fmtEnd = (endDate); const fmtStart = format_date(getValues('date')); const notWeekend = moment(fmtEnd).day() !== 0 && moment(fmtEnd).day() !== 6; diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index 52b725260..af846b5f5 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -9,6 +9,7 @@ import { useRides } from '../../context/RidesContext'; import { useDate } from '../../context/date'; import { ToastStatus, useToast } from '../../context/toastContext'; import axios from '../../util/axios'; +import { format } from 'crypto-js'; type RideModalProps = { open?: boolean; @@ -61,7 +62,7 @@ const getRideData = (ride: Ride | undefined) => { ...rideData, repeats, days, - endDate: format_date(ride.endDate), + endDate: (ride.endDate), parentRideId : ride.parentRideId, sourceRideId : ride.sourceRide, childRideId : ride.childRideId @@ -141,7 +142,7 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { const [editAddType, setEditAddType] = useState(EditAddRideType.SINGLE); const {curDate} = useDate(); - + console.log(curDate); const { showToast } = useToast(); const { refreshRides } = useRides(); @@ -218,16 +219,22 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { const endTime = moment(`${date} ${dropoffTime}`).toISOString(); const hasDriver = Boolean(driver) && driver !== 'None'; + //in the case of recurring rides, + //rideData should also have + // 1. recurring = true + // 2. recurringDays + // 3. endDate + + console.log("start end time", startTime, endTime); + let rideData: ObjectType = { type: hasDriver ? 'active' : 'unscheduled', startTime, endTime, driver: hasDriver ? driver : undefined, rider, - startLocation, - endLocation, - parentRideId : ride!.parentRideId, - childRideId: ride!.childRideId + startLocation, // id to location entry in dynamo table + endLocation, // id to location entry in dynamo table }; @@ -237,7 +244,7 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { ...rideData, recurring: true, recurringDays: getRecurringDays(date, repeats, days), - endDate: format_date(endDate), + endDate: (endDate), }; } @@ -282,7 +289,7 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { //delete ride if enddate is before startdate. also have to axios put children's parent to undefined. - let trimmedEndDateImmPar = curDate; + let trimmedEndDateImmPar = new Date(startTime); trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); trimmedEndDateImmPar.setHours(0, 0, 0); @@ -290,9 +297,24 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { sourceRideStartDate.setHours(0, 0, 0); if (trimmedEndDateImmPar >= sourceRideStartDate) { - ride.sourceRide! = {...ride.sourceRide!, endDate: trimmedEndDateImmPar.toISOString()} - axios.put(`/api/rides/${ride.id}`, getRideData(ride.sourceRide!)); - console.log(sourceRideStartDate); + ride.sourceRide! = {...ride.sourceRide!, endDate: format_date(trimmedEndDateImmPar.toISOString())} + + console.log(ride.sourceRide!); + axios.put(`/api/rides/${ride.id}`, { + type : 'unscheduled', + startTime : ride.sourceRide!.startTime, + endTime : ride.sourceRide!.endTime, + driver : undefined, + rider : ride.sourceRide.rider, + startLocation : ride.sourceRide!.startLocation.id, + endLocation : ride.sourceRide!.endLocation.id, + parentRideId : ride!.parentRideId, + childRideId : ride!.childRideId, + recurring : true, + recurringDays : ride!.sourceRide!.recurringDays!, + endDate : format_date(ride!.sourceRide.endDate!) + }); + } else { axios.delete(`/api/rides/${ride.id}`) } @@ -311,20 +333,20 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { childRideId : undefined } - //adds the new ride to the database and updates the parent ride to have it as the child. axios .post(`/api/rides`, rideData) .then((response) => response.data) .then(refreshRides); } else { - // Note: lock the day and recurring (recurring must be false). + // Note: lock the day and recurring (recurring must be true). // trim its end date: change its end date then axios put with id and with sourceRide end date changed. // Create a new ride on that day, have the ride above as its parent and parentId, axios.post. Also axios put the parent ride above to have children as this new ride. // After this, add another recurring ride with the original ride end date and information (if the end date is larger than today). // Link this ride to the single non recurring ride you just created: axios put appropriate parent and children field. - - let trimmedEndDateImmPar = curDate; + const originalEndDate = new Date(ride.sourceRide!.endDate!); + console.log("og end date", originalEndDate); + let trimmedEndDateImmPar = new Date(startTime); trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); trimmedEndDateImmPar.setHours(0, 0, 0); @@ -334,54 +356,116 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { if (trimmedEndDateImmPar >= sourceRideStartDate) { - ride.sourceRide! = {...ride.sourceRide!, endDate: trimmedEndDateImmPar.toISOString()} - axios.put(`/api/rides/${ride.id}`, getRideData(ride.sourceRide!)); - deletedSourceRide = true; + console.log("trimmed end date is", trimmedEndDateImmPar, sourceRideStartDate, trimmedEndDateImmPar.toISOString()); + //updates the source ride. + ride.sourceRide! = {...ride.sourceRide!, endDate: format_date(trimmedEndDateImmPar.toISOString())} + console.log(ride.sourceRide!); + axios.put(`/api/rides/${ride.id}`, { + type : ride.sourceRide!.type, + startTime : ride.sourceRide!.startTime, + endTime : ride.sourceRide!.endTime, + driver : ride.sourceRide!.driver, + rider : ride.sourceRide!.rider, + startLocation : ride.sourceRide!.startLocation.id, + endLocation : ride.sourceRide!.endLocation.id, + parentRideId : ride!.parentRideId, + childRideId : ride!.childRideId, + recurring : true, + recurringDays : ride!.sourceRide!.recurringDays!, + endDate : ride!.sourceRide.endDate! + }); } else { axios.delete(`/api/rides/${ride.id}`) + deletedSourceRide = true; } + let singleRideEndDate = new Date(startTime); + singleRideEndDate.setHours(0, 0, 0); + rideData = { ...rideData, parentRideId : deletedSourceRide ? undefined: ride.id, - sourceRideId : undefined, - recurring : false, - recurringDays: undefined, - endDate : undefined, - id : undefined + childRideId : undefined, + recurring : true, + recurringDays: [1, 2, 3, 4, 5], + endDate : format_date(singleRideEndDate), + driver : ride.sourceRide?.driver }; - //here, we add the new ride with the changed data and then add - //another recurring ride after with the same data as sourceRide - const originalEndDate = new Date(ride.sourceRide!.endDate!); + //here, we need to add new ride (non recurring ride) to database axios.post + //then we need to update its parent ride's children ride field axios.put (if the parent ride still exists) + //then we need to create a new recurring ride with the parent rides's same data axios.post (if the end date of the parent is > than the current date) + + + + //TODO : NEED TO FIX CHILDRIDEID + console.log(originalEndDate, curDate); axios .post(`/api/rides/`, rideData) .then((response) => response.data) - .then((data) => { - console.log(originalEndDate); - if (originalEndDate > curDate) { + .then((newSingleRideData : Ride) => { + if (!deletedSourceRide) { + ride.sourceRide! = { + ...ride.sourceRide!, + childRideId : newSingleRideData.id, + childRide : newSingleRideData + } + axios.put(`/api/rides/${ride.id}`, { + type : ride.sourceRide!.type, + startTime : ride.sourceRide!.startTime, + endTime : ride.sourceRide!.endTime, + driver : ride.sourceRide!.driver, + rider : ride.sourceRide!.rider, + startLocation : ride.sourceRide!.startLocation.id, + endLocation : ride.sourceRide!.endLocation.id, + parentRideId : ride!.parentRideId, + childRideId : ride!.childRideId, + recurring : true, + recurringDays : ride!.sourceRide!.recurringDays!, + endDate : (format_date(ride!.sourceRide.endDate!)) + }); + + } + let today = new Date(startTime); + today.setHours(0, 0, 0); + if (originalEndDate > today) { //create a new recurring ride with same data as the old one but with start date = curDate + 1. let newRideStartTime = new Date(ride.sourceRide!.startTime); - newRideStartTime.setDate(curDate.getDate() + 1); + newRideStartTime.setDate(today.getDate() + 1); let newRideEndTime = new Date(ride.sourceRide!.endTime); - newRideEndTime.setDate(curDate.getDate() + 1); - - ride.sourceRide! = { + newRideEndTime.setDate(today.getDate() + 1); + console.log("current date", today); + console.log("newRideStartTime, newRideEndTime", newRideStartTime, newRideEndTime); + const newRecurringRideData : Ride = { ...ride.sourceRide!, startTime : newRideStartTime.toISOString(), endTime : newRideEndTime.toISOString(), endDate : format_date(originalEndDate), - parentRideId : data.id, + parentRideId : newSingleRideData.id, childRideId: ride.sourceRide!.childRideId, recurring : true, type : Type.UNSCHEDULED }; - axios.post(`/api/rides/`, getRideData(ride.sourceRide!)); - } + axios.post(`/api/rides/`, { + type : newRecurringRideData.type, + startTime : newRecurringRideData.startTime, + endTime : newRecurringRideData.endTime, + driver : newRecurringRideData.driver, + rider : newRecurringRideData.rider, + startLocation : newRecurringRideData.startLocation.id, + endLocation : newRecurringRideData.endLocation.id, + parentRideId : newRecurringRideData.parentRideId, + childRideId : newRecurringRideData.childRideId, + recurring : true, + recurringDays : newRecurringRideData.recurringDays!, + endDate : format_date(newRecurringRideData.endDate) + }); + } else { + + } }); - } } else { axios.put(`/api/rides/${ride.id}`, rideData).then(refreshRides); diff --git a/frontend/src/context/RidesContext.tsx b/frontend/src/context/RidesContext.tsx index 8ee304b10..2a055223b 100644 --- a/frontend/src/context/RidesContext.tsx +++ b/frontend/src/context/RidesContext.tsx @@ -9,6 +9,7 @@ import { Ride, Type } from '../types'; import { useDate } from './date'; import { format_date } from '../util/index'; import axios from '../util/axios'; +import { start } from 'repl'; type ridesState = { unscheduledRides: Ride[]; @@ -45,28 +46,45 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { .then((data: Ride[]) => data.filter((ride: Ride) => !ride.recurring)); let recurringRides: Ride[] = await axios - .get(`/api/rides?recurring=true`) + .get(`/api/rides/recurring`) .then((res) => res.data) .then((data) => data.data); + for (let ride of recurringRides) { + ride.parentRide = recurringRides.find((rideTmp) => rideTmp.id === ride.parentRideId); + ride.childRide = recurringRides.find((rideTmp) => rideTmp.id === ride.childRideId); + ride.sourceRide = ride; + + } + // Here i'm filtering for recurring rides with start and end date including the curDate and includes the day of // week of curDate. + console.log("recurring rides are ", recurringRides); const recurringRidesToday : Ride[] = recurringRides .filter((ride) => { + let endDate = new Date(ride!.endDate!); - // console.log(ride); + let [year, month, date] = (ride!.endDate!).split('-'); + endDate.setFullYear(Number(year), Number(month) - 1, Number(date)); + endDate.setHours(0, 0, 0); + console.log(`The current date is ${curDate}. This repeating ride end date is ${endDate}`); + let startDate = new Date(ride.startTime); - startDate = new Date( - startDate.getFullYear(), - startDate.getMonth(), - startDate.getDate(), - 0, - 0, - 0 + startDate.setHours(0, 0, 0); + + let curDateZeroedHours = (new Date(curDate.getTime())); + curDateZeroedHours.setHours(0, 0, 0); + + console.log(` + The current date is ${curDate}. + This repeating ride end date is ${curDateZeroedHours}. + This repeating ride start date is ${startDate}` ); + + return ( - curDate >= startDate && - curDate <= endDate && + curDateZeroedHours >= startDate && + curDateZeroedHours <= endDate && ride!.recurringDays?.includes(curDate.getDay()) ); }) @@ -76,7 +94,6 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { startTimeRecurringRide.setFullYear(curDate.getFullYear()); startTimeRecurringRide.setMonth(curDate.getMonth()); startTimeRecurringRide.setDate(curDate.getDate()); - const endTimeRecurringRide = new Date(filteredSourceRide.endTime); endTimeRecurringRide.setFullYear(curDate.getFullYear()); endTimeRecurringRide.setMonth(curDate.getMonth()); @@ -88,26 +105,20 @@ export const RidesProvider = ({ children }: RidesProviderProps) => { new Date(filteredSourceRide.startTime).getFullYear() == curDate.getFullYear() ? Type.ACTIVE : Type.UNSCHEDULED; - - const parentRide = recurringRides.find((ride) => ride.id === filteredSourceRide.parentRideId); - const childrenRide = recurringRides.find((ride) => ride.id === filteredSourceRide.childRideId); - return { ...filteredSourceRide, // id should be the same as the sourceRide startTime: startTimeRecurringRide.toISOString(), endTime: endTimeRecurringRide.toISOString(), type: schedule, - parentRide: parentRide, - parentRideId: parentRide?.id, - childrenRide : childrenRide, - childrenRideId : childrenRide?.id, sourceRide : filteredSourceRide }; }); const combinedRidesData = nonRecurringRidesDataToday.concat(recurringRidesToday); + + console.log(combinedRidesData); if (combinedRidesData) { setUnscheduledRides( combinedRidesData.filter(({ type }) => type === Type.UNSCHEDULED) diff --git a/server/src/models/ride.ts b/server/src/models/ride.ts index c49fada92..40058f6b1 100644 --- a/server/src/models/ride.ts +++ b/server/src/models/ride.ts @@ -42,6 +42,11 @@ export type RideType = { driver?: DriverType; recurring: boolean; recurringDays?: number[]; + /** + * endDate means that the recurring rides should end on this date (inclusive) in UTC. + * Ex: 2024-12-31 : recurring rides should end on the 31 of dec + * Note: should change to timestamp in the future. + */ endDate?: string; sourceRide? : RideType; parentRide? : RideType; diff --git a/server/src/router/ride.ts b/server/src/router/ride.ts index 5728a79a9..8aa56903a 100644 --- a/server/src/router/ride.ts +++ b/server/src/router/ride.ts @@ -56,7 +56,7 @@ router.get('/download', (req, res) => { }); // Get and query all master repeating rides in table -router.get('/repeating', validateUser('User'), (req, res) => { +router.get('/recurring', validateUser('User'), (req, res) => { const { query: { rider }, } = req; From 88cd6523bb0fc9183d04bd433f5d259607e75562 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Wed, 13 Nov 2024 10:27:40 -0500 Subject: [PATCH 13/14] fixed schema column naming issue, edit a single ride + delete all rides now work as expected --- .../src/components/Modal/DeleteOrEditTypeModal.tsx | 1 + frontend/src/components/RideModal/RideModal.tsx | 11 ++++++----- server/src/models/ride.ts | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx index 85fa7fdc6..d5a3c493c 100644 --- a/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx +++ b/frontend/src/components/Modal/DeleteOrEditTypeModal.tsx @@ -117,6 +117,7 @@ const DeleteOrEditTypeModal = ({ currentRide = currentRide!.parentRide; } // now current ride is at the beginning of linked list + console.log(currentRide); while (currentRide !== undefined) { console.log("hello, deleting all, current Ride is", currentRide); axios.delete(`/api/rides/${currentRide.id}`); diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index af846b5f5..da4c3a25e 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -368,8 +368,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { rider : ride.sourceRide!.rider, startLocation : ride.sourceRide!.startLocation.id, endLocation : ride.sourceRide!.endLocation.id, - parentRideId : ride!.parentRideId, - childRideId : ride!.childRideId, + parentRideId : ride!.sourceRide.parentRideId, + childRideId : ride!.sourceRide.childRideId, recurring : true, recurringDays : ride!.sourceRide!.recurringDays!, endDate : ride!.sourceRide.endDate! @@ -411,7 +411,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { childRideId : newSingleRideData.id, childRide : newSingleRideData } - axios.put(`/api/rides/${ride.id}`, { + console.log("Child ride id is", ride.sourceRide!.childRideId, "source ride id is ", ride.sourceRide.id) + axios.put(`/api/rides/${ride.sourceRide.id}`, { type : ride.sourceRide!.type, startTime : ride.sourceRide!.startTime, endTime : ride.sourceRide!.endTime, @@ -419,8 +420,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { rider : ride.sourceRide!.rider, startLocation : ride.sourceRide!.startLocation.id, endLocation : ride.sourceRide!.endLocation.id, - parentRideId : ride!.parentRideId, - childRideId : ride!.childRideId, + parentRideId : ride!.sourceRide.parentRideId, + childRideId : ride!.sourceRide.childRideId, recurring : true, recurringDays : ride!.sourceRide!.recurringDays!, endDate : (format_date(ride!.sourceRide.endDate!)) diff --git a/server/src/models/ride.ts b/server/src/models/ride.ts index 40058f6b1..dbd887bdd 100644 --- a/server/src/models/ride.ts +++ b/server/src/models/ride.ts @@ -126,7 +126,7 @@ const schema = new dynamoose.Schema({ type : String, required : false, }, - childrenRideId : { + childRideId : { type : String, required : false, }, From 6986aae02644a739c8d888fc2f2f3afbc5ea67d5 Mon Sep 17 00:00:00 2001 From: Nam Anh Date: Wed, 13 Nov 2024 11:44:58 -0500 Subject: [PATCH 14/14] tried updating the childRideId of the newly created single ride when editing a single ride in a chain of recurring rides, but encountered Invalid UpdateExpression: Two document paths overlap with each other; must remove or rewrite one of these paths; path one: [driver], path two: [parentRideId] --- .../src/components/RideModal/RideModal.tsx | 256 ++++++++++-------- 1 file changed, 138 insertions(+), 118 deletions(-) diff --git a/frontend/src/components/RideModal/RideModal.tsx b/frontend/src/components/RideModal/RideModal.tsx index da4c3a25e..a1464104d 100644 --- a/frontend/src/components/RideModal/RideModal.tsx +++ b/frontend/src/components/RideModal/RideModal.tsx @@ -36,7 +36,6 @@ const getRideData = (ride: Ride | undefined) => { dropoffLoc: ride.endLocation.id ? ride.endLocation.name : ride.endLocation.address, - }; if (ride.recurring) { let repeats; @@ -62,10 +61,10 @@ const getRideData = (ride: Ride | undefined) => { ...rideData, repeats, days, - endDate: (ride.endDate), - parentRideId : ride.parentRideId, - sourceRideId : ride.sourceRide, - childRideId : ride.childRideId + endDate: ride.endDate, + parentRideId: ride.parentRideId, + sourceRideId: ride.sourceRide, + childRideId: ride.childRideId, }; } return rideData; @@ -141,7 +140,7 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { const [isSubmitted, setIsSubmitted] = useState(false); const [editAddType, setEditAddType] = useState(EditAddRideType.SINGLE); - const {curDate} = useDate(); + const { curDate } = useDate(); console.log(curDate); const { showToast } = useToast(); @@ -219,13 +218,13 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { const endTime = moment(`${date} ${dropoffTime}`).toISOString(); const hasDriver = Boolean(driver) && driver !== 'None'; - //in the case of recurring rides, - //rideData should also have + //in the case of recurring rides, + //rideData should also have // 1. recurring = true // 2. recurringDays // 3. endDate - - console.log("start end time", startTime, endTime); + + console.log('start end time', startTime, endTime); let rideData: ObjectType = { type: hasDriver ? 'active' : 'unscheduled', @@ -236,7 +235,6 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { startLocation, // id to location entry in dynamo table endLocation, // id to location entry in dynamo table }; - //if the ride repeats if (repeats !== RepeatValues.DoesNotRepeat) { @@ -244,11 +242,10 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { ...rideData, recurring: true, recurringDays: getRecurringDays(date, repeats, days), - endDate: (endDate), + endDate: endDate, }; } - //shittttt, the new form data is in formData, should use that to get latest data about ride. if (ride) { // scheduled ride @@ -261,8 +258,8 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { //have to ask desmond /** * go up the chain to the ancestor ride - * delete all children by going down the linked list - * apply edit to the ancestor. + * delete all children by going down the linked list + * apply edit to the ancestor. */ let currentRide = ride.sourceRide; while (currentRide?.parentRide !== undefined) { @@ -276,18 +273,15 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { } //now all elements except the beginning has been deleted. - axios - .put(`/api/rides/${ride.id}`, rideData) - .then(refreshRides); + axios.put(`/api/rides/${ride.id}`, rideData).then(refreshRides); } else if (editAddType == EditAddRideType.THIS_AND_FOLLOWING) { //need to show them the data of the current ride, so don't need to change anything. - + // lock the start date (date) // trim the date of this ride, axios.put // create a new ride, do whatever, can be a single non repeating ride. // should not link back to parent (gcal does this) - - + //delete ride if enddate is before startdate. also have to axios put children's parent to undefined. let trimmedEndDateImmPar = new Date(startTime); trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); @@ -297,28 +291,29 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { sourceRideStartDate.setHours(0, 0, 0); if (trimmedEndDateImmPar >= sourceRideStartDate) { - ride.sourceRide! = {...ride.sourceRide!, endDate: format_date(trimmedEndDateImmPar.toISOString())} - + ride.sourceRide! = { + ...ride.sourceRide!, + endDate: format_date(trimmedEndDateImmPar.toISOString()), + }; + console.log(ride.sourceRide!); axios.put(`/api/rides/${ride.id}`, { - type : 'unscheduled', - startTime : ride.sourceRide!.startTime, - endTime : ride.sourceRide!.endTime, - driver : undefined, - rider : ride.sourceRide.rider, - startLocation : ride.sourceRide!.startLocation.id, - endLocation : ride.sourceRide!.endLocation.id, - parentRideId : ride!.parentRideId, - childRideId : ride!.childRideId, - recurring : true, - recurringDays : ride!.sourceRide!.recurringDays!, - endDate : format_date(ride!.sourceRide.endDate!) + type: 'unscheduled', + startTime: ride.sourceRide!.startTime, + endTime: ride.sourceRide!.endTime, + driver: undefined, + rider: ride.sourceRide.rider, + startLocation: ride.sourceRide!.startLocation.id, + endLocation: ride.sourceRide!.endLocation.id, + parentRideId: ride!.parentRideId, + childRideId: ride!.childRideId, + recurring: true, + recurringDays: ride!.sourceRide!.recurringDays!, + endDate: format_date(ride!.sourceRide.endDate!), }); - } else { - axios.delete(`/api/rides/${ride.id}`) + axios.delete(`/api/rides/${ride.id}`); } - //delete all descendants ride of sourceRide. let currentRide = ride.sourceRide?.childRide; @@ -328,24 +323,23 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { } //now we create a new ride starting from today to with the data in formData, but have it doesn't link back rideData = { - ...rideData, - parentRideId : undefined, - childRideId : undefined - } + ...rideData, + parentRideId: undefined, + childRideId: undefined, + }; axios .post(`/api/rides`, rideData) .then((response) => response.data) .then(refreshRides); - } else { - + } else { // Note: lock the day and recurring (recurring must be true). // trim its end date: change its end date then axios put with id and with sourceRide end date changed. // Create a new ride on that day, have the ride above as its parent and parentId, axios.post. Also axios put the parent ride above to have children as this new ride. // After this, add another recurring ride with the original ride end date and information (if the end date is larger than today). // Link this ride to the single non recurring ride you just created: axios put appropriate parent and children field. const originalEndDate = new Date(ride.sourceRide!.endDate!); - console.log("og end date", originalEndDate); + console.log('og end date', originalEndDate); let trimmedEndDateImmPar = new Date(startTime); trimmedEndDateImmPar.setDate(trimmedEndDateImmPar.getDate() - 1); trimmedEndDateImmPar.setHours(0, 0, 0); @@ -354,28 +348,35 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { sourceRideStartDate.setHours(0, 0, 0); let deletedSourceRide = false; - if (trimmedEndDateImmPar >= sourceRideStartDate) { - console.log("trimmed end date is", trimmedEndDateImmPar, sourceRideStartDate, trimmedEndDateImmPar.toISOString()); + console.log( + 'trimmed end date is', + trimmedEndDateImmPar, + sourceRideStartDate, + trimmedEndDateImmPar.toISOString() + ); //updates the source ride. - ride.sourceRide! = {...ride.sourceRide!, endDate: format_date(trimmedEndDateImmPar.toISOString())} + ride.sourceRide! = { + ...ride.sourceRide!, + endDate: format_date(trimmedEndDateImmPar.toISOString()), + }; console.log(ride.sourceRide!); axios.put(`/api/rides/${ride.id}`, { - type : ride.sourceRide!.type, - startTime : ride.sourceRide!.startTime, - endTime : ride.sourceRide!.endTime, - driver : ride.sourceRide!.driver, - rider : ride.sourceRide!.rider, - startLocation : ride.sourceRide!.startLocation.id, - endLocation : ride.sourceRide!.endLocation.id, - parentRideId : ride!.sourceRide.parentRideId, - childRideId : ride!.sourceRide.childRideId, - recurring : true, - recurringDays : ride!.sourceRide!.recurringDays!, - endDate : ride!.sourceRide.endDate! + type: ride.sourceRide!.type, + startTime: ride.sourceRide!.startTime, + endTime: ride.sourceRide!.endTime, + driver: ride.sourceRide!.driver, + rider: ride.sourceRide!.rider, + startLocation: ride.sourceRide!.startLocation.id, + endLocation: ride.sourceRide!.endLocation.id, + parentRideId: ride!.sourceRide.parentRideId, + childRideId: ride!.sourceRide.childRideId, + recurring: true, + recurringDays: ride!.sourceRide!.recurringDays!, + endDate: ride!.sourceRide.endDate!, }); } else { - axios.delete(`/api/rides/${ride.id}`) + axios.delete(`/api/rides/${ride.id}`); deletedSourceRide = true; } @@ -383,50 +384,51 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { singleRideEndDate.setHours(0, 0, 0); rideData = { - ...rideData, - parentRideId : deletedSourceRide ? undefined: ride.id, - childRideId : undefined, - recurring : true, - recurringDays: [1, 2, 3, 4, 5], - endDate : format_date(singleRideEndDate), - driver : ride.sourceRide?.driver + ...rideData, + parentRideId: deletedSourceRide ? undefined : ride.id, + childRideId: undefined, + recurring: true, + recurringDays: [1, 2, 3, 4, 5], + endDate: format_date(singleRideEndDate), + driver: ride.sourceRide?.driver, }; - //here, we need to add new ride (non recurring ride) to database axios.post //then we need to update its parent ride's children ride field axios.put (if the parent ride still exists) //then we need to create a new recurring ride with the parent rides's same data axios.post (if the end date of the parent is > than the current date) - - - //TODO : NEED TO FIX CHILDRIDEID + //TODO : NEED TO FIX CHILDRIDEID console.log(originalEndDate, curDate); axios .post(`/api/rides/`, rideData) .then((response) => response.data) - .then((newSingleRideData : Ride) => { + .then((newSingleRideData: Ride) => { if (!deletedSourceRide) { ride.sourceRide! = { - ...ride.sourceRide!, - childRideId : newSingleRideData.id, - childRide : newSingleRideData - } - console.log("Child ride id is", ride.sourceRide!.childRideId, "source ride id is ", ride.sourceRide.id) + ...ride.sourceRide!, + childRideId: newSingleRideData.id, + childRide: newSingleRideData, + }; + console.log( + 'Child ride id is', + ride.sourceRide!.childRideId, + 'source ride id is ', + ride.sourceRide.id + ); axios.put(`/api/rides/${ride.sourceRide.id}`, { - type : ride.sourceRide!.type, - startTime : ride.sourceRide!.startTime, - endTime : ride.sourceRide!.endTime, - driver : ride.sourceRide!.driver, - rider : ride.sourceRide!.rider, - startLocation : ride.sourceRide!.startLocation.id, - endLocation : ride.sourceRide!.endLocation.id, - parentRideId : ride!.sourceRide.parentRideId, - childRideId : ride!.sourceRide.childRideId, - recurring : true, - recurringDays : ride!.sourceRide!.recurringDays!, - endDate : (format_date(ride!.sourceRide.endDate!)) + type: ride.sourceRide!.type, + startTime: ride.sourceRide!.startTime, + endTime: ride.sourceRide!.endTime, + driver: ride.sourceRide!.driver, + rider: ride.sourceRide!.rider, + startLocation: ride.sourceRide!.startLocation.id, + endLocation: ride.sourceRide!.endLocation.id, + parentRideId: ride!.sourceRide.parentRideId, + childRideId: ride!.sourceRide.childRideId, + recurring: true, + recurringDays: ride!.sourceRide!.recurringDays!, + endDate: format_date(ride!.sourceRide.endDate!), }); - } let today = new Date(startTime); today.setHours(0, 0, 0); @@ -436,35 +438,53 @@ const RideModal = ({ open, close, ride }: RideModalProps) => { newRideStartTime.setDate(today.getDate() + 1); let newRideEndTime = new Date(ride.sourceRide!.endTime); newRideEndTime.setDate(today.getDate() + 1); - console.log("current date", today); - console.log("newRideStartTime, newRideEndTime", newRideStartTime, newRideEndTime); - const newRecurringRideData : Ride = { - ...ride.sourceRide!, - startTime : newRideStartTime.toISOString(), - endTime : newRideEndTime.toISOString(), - endDate : format_date(originalEndDate), - parentRideId : newSingleRideData.id, - childRideId: ride.sourceRide!.childRideId, - recurring : true, - type : Type.UNSCHEDULED + console.log('current date', today); + console.log( + 'newRideStartTime, newRideEndTime', + newRideStartTime, + newRideEndTime + ); + const newRecurringRideData: Ride = { + ...ride.sourceRide!, + startTime: newRideStartTime.toISOString(), + endTime: newRideEndTime.toISOString(), + endDate: format_date(originalEndDate), + parentRideId: newSingleRideData.id, + childRideId: undefined, + recurring: true, + type: Type.UNSCHEDULED, }; - - axios.post(`/api/rides/`, { - type : newRecurringRideData.type, - startTime : newRecurringRideData.startTime, - endTime : newRecurringRideData.endTime, - driver : newRecurringRideData.driver, - rider : newRecurringRideData.rider, - startLocation : newRecurringRideData.startLocation.id, - endLocation : newRecurringRideData.endLocation.id, - parentRideId : newRecurringRideData.parentRideId, - childRideId : newRecurringRideData.childRideId, - recurring : true, - recurringDays : newRecurringRideData.recurringDays!, - endDate : format_date(newRecurringRideData.endDate) - }); - } else { + axios + .post(`/api/rides/`, { + type: newRecurringRideData.type, + startTime: newRecurringRideData.startTime, + endTime: newRecurringRideData.endTime, + driver: newRecurringRideData.driver, + rider: newRecurringRideData.rider, + startLocation: newRecurringRideData.startLocation.id, + endLocation: newRecurringRideData.endLocation.id, + parentRideId: newRecurringRideData.parentRideId, + childRideId: newRecurringRideData.childRideId, + recurring: true, + recurringDays: newRecurringRideData.recurringDays!, + endDate: format_date(newRecurringRideData.endDate), + }) + .then((response) => response.data) + .then((newRecurringRideData: Ride) => { + console.log("new recurring ride data is", newRecurringRideData); + console.log("newSingle ride data ", newSingleRideData); + const {id, ...newSingleRideDataRest} = newSingleRideData; + console.log("rest of data is", newSingleRideDataRest); + return axios.put(`/api/rides/${newSingleRideData.id}`, { + ...newSingleRideDataRest, + startLocation: newSingleRideData.startLocation.id, + endLocation: newSingleRideData.endLocation.id, + childRideId: newRecurringRideData.id, + }); + // axios.put(`a`) + }); + } else { } }); }