import { useLocation } from 'react-router-dom'; import { useRecoilState, useRecoilValue, useSetRecoilState } from 'recoil'; import { useActivityConnectionUtils } from '@/activities/hooks/useActivityConnectionUtils'; import { useCreateActivityInDB } from '@/activities/hooks/useCreateActivityInDB'; import { useInjectIntoActivitiesQueries } from '@/activities/hooks/useInjectIntoActivitiesQueries'; import { useInjectIntoActivityTargetsQueries } from '@/activities/hooks/useInjectIntoActivityTargetsQueries'; import { currentNotesQueryVariablesState } from '@/activities/notes/states/currentNotesQueryVariablesState'; import { activityIdInDrawerState } from '@/activities/states/activityIdInDrawerState'; import { isActivityInCreateModeState } from '@/activities/states/isActivityInCreateModeState'; import { isUpsertingActivityInDBState } from '@/activities/states/isCreatingActivityInDBState'; import { currentCompletedTaskQueryVariablesState } from '@/activities/tasks/states/currentCompletedTaskQueryVariablesState'; import { currentIncompleteTaskQueryVariablesState } from '@/activities/tasks/states/currentIncompleteTaskQueryVariablesState'; import { useInjectIntoTimelineActivitiesQueries } from '@/activities/timeline/hooks/useInjectIntoTimelineActivitiesQueries'; import { objectShowPageTargetableObjectState } from '@/activities/timeline/states/objectShowPageTargetableObjectIdState'; import { Activity } from '@/activities/types/Activity'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useUpdateOneRecord } from '@/object-record/hooks/useUpdateOneRecord'; import { isDefined } from '~/utils/isDefined'; // TODO: create a generic way to have records only in cache for create mode and delete them afterwards ? export const useUpsertActivity = () => { const [isActivityInCreateMode, setIsActivityInCreateMode] = useRecoilState( isActivityInCreateModeState, ); const { updateOneRecord: updateOneActivity } = useUpdateOneRecord({ objectNameSingular: CoreObjectNameSingular.Activity, }); const { createActivityInDB } = useCreateActivityInDB(); const [, setIsUpsertingActivityInDB] = useRecoilState( isUpsertingActivityInDBState, ); const setActivityIdInDrawer = useSetRecoilState(activityIdInDrawerState); const objectShowPageTargetableObject = useRecoilValue( objectShowPageTargetableObjectState, ); const { injectActivitiesQueries } = useInjectIntoActivitiesQueries(); const { injectActivityTargetsQueries } = useInjectIntoActivityTargetsQueries(); const { pathname } = useLocation(); const weAreOnObjectShowPage = pathname.startsWith('/object'); const weAreOnTaskPage = pathname.startsWith('/tasks'); const { injectIntoTimelineActivitiesQueries } = useInjectIntoTimelineActivitiesQueries(); const { makeActivityWithConnection } = useActivityConnectionUtils(); const currentCompletedTaskQueryVariables = useRecoilValue( currentCompletedTaskQueryVariablesState, ); const currentIncompleteTaskQueryVariables = useRecoilValue( currentIncompleteTaskQueryVariablesState, ); const currentNotesQueryVariables = useRecoilValue( currentNotesQueryVariablesState, ); const upsertActivity = async ({ activity, input, }: { activity: Activity; input: Partial; }) => { setIsUpsertingActivityInDB(true); if (isActivityInCreateMode) { const activityToCreate: Activity = { ...activity, ...input, }; const { activityWithConnection } = makeActivityWithConnection(activityToCreate); if (weAreOnTaskPage) { if (isDefined(activityWithConnection.completedAt)) { injectActivitiesQueries({ activitiesFilters: currentCompletedTaskQueryVariables?.filter, activitiesOrderByVariables: currentCompletedTaskQueryVariables?.orderBy, activityTargetsToInject: activityToCreate.activityTargets, activityToInject: activityWithConnection, targetableObjects: [], }); } else { injectActivitiesQueries({ activitiesFilters: currentIncompleteTaskQueryVariables?.filter, activitiesOrderByVariables: currentIncompleteTaskQueryVariables?.orderBy, activityTargetsToInject: activityToCreate.activityTargets, activityToInject: activityWithConnection, targetableObjects: [], }); } injectActivityTargetsQueries({ activityTargetsToInject: activityToCreate.activityTargets, targetableObjects: [], }); } // Call optimistic effects if (weAreOnObjectShowPage && isDefined(objectShowPageTargetableObject)) { injectIntoTimelineActivitiesQueries({ timelineTargetableObject: objectShowPageTargetableObject, activityToInject: activityWithConnection, activityTargetsToInject: activityToCreate.activityTargets, }); const injectOnlyInIdFilterForTaskQueries = activityWithConnection.type !== 'Task'; const injectOnlyInIdFilterForNotesQueries = activityWithConnection.type !== 'Note'; if (isDefined(currentCompletedTaskQueryVariables)) { injectActivitiesQueries({ activitiesFilters: currentCompletedTaskQueryVariables?.filter, activitiesOrderByVariables: currentCompletedTaskQueryVariables?.orderBy, activityTargetsToInject: activityToCreate.activityTargets, activityToInject: activityWithConnection, targetableObjects: [objectShowPageTargetableObject], injectOnlyInIdFilter: injectOnlyInIdFilterForTaskQueries, }); } if (isDefined(currentIncompleteTaskQueryVariables)) { injectActivitiesQueries({ activitiesFilters: currentIncompleteTaskQueryVariables?.filter ?? {}, activitiesOrderByVariables: currentIncompleteTaskQueryVariables?.orderBy ?? {}, activityTargetsToInject: activityToCreate.activityTargets, activityToInject: activityWithConnection, targetableObjects: [objectShowPageTargetableObject], injectOnlyInIdFilter: injectOnlyInIdFilterForTaskQueries, }); } if (isDefined(currentNotesQueryVariables)) { injectActivitiesQueries({ activitiesFilters: currentNotesQueryVariables?.filter, activitiesOrderByVariables: currentNotesQueryVariables?.orderBy, activityTargetsToInject: activityToCreate.activityTargets, activityToInject: activityWithConnection, targetableObjects: [objectShowPageTargetableObject], injectOnlyInIdFilter: injectOnlyInIdFilterForNotesQueries, }); } injectActivityTargetsQueries({ activityTargetsToInject: activityToCreate.activityTargets, targetableObjects: [objectShowPageTargetableObject], }); } await createActivityInDB(activityToCreate); setActivityIdInDrawer(activityToCreate.id); setIsActivityInCreateMode(false); } else { await updateOneActivity?.({ idToUpdate: activity.id, updateOneRecordInput: input, }); } setIsUpsertingActivityInDB(false); }; return { upsertActivity, }; };