import { Reference, useApolloClient } from '@apollo/client'; import { useRecoilCallback, useRecoilValue } from 'recoil'; import { v4 } from 'uuid'; import { Activity, ActivityType } from '@/activities/types/Activity'; import { ActivityTarget } from '@/activities/types/ActivityTarget'; import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; import { makeActivityTargetsToCreateFromTargetableObjects } from '@/activities/utils/getActivityTargetsToCreateFromTargetableObjects'; import { currentWorkspaceMemberState } from '@/auth/states/currentWorkspaceMemberState'; import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem'; import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState'; import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular'; import { useCreateManyRecordsInCache } from '@/object-record/cache/hooks/useCreateManyRecordsInCache'; import { useCreateOneRecordInCache } from '@/object-record/cache/hooks/useCreateOneRecordInCache'; import { getRecordConnectionFromRecords } from '@/object-record/cache/utils/getRecordConnectionFromRecords'; import { modifyRecordFromCache } from '@/object-record/cache/utils/modifyRecordFromCache'; import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord'; import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState'; import { WorkspaceMember } from '@/workspace-member/types/WorkspaceMember'; import { isDefined } from '~/utils/isDefined'; import { isUndefinedOrNull } from '~/utils/isUndefinedOrNull'; export const useCreateActivityInCache = () => { const { createManyRecordsInCache: createManyActivityTargetsInCache } = useCreateManyRecordsInCache({ objectNameSingular: CoreObjectNameSingular.ActivityTarget, }); const cache = useApolloClient().cache; const objectMetadataItems = useRecoilValue(objectMetadataItemsState); const currentWorkspaceMember = useRecoilValue(currentWorkspaceMemberState); const { record: currentWorkspaceMemberRecord } = useFindOneRecord({ objectNameSingular: CoreObjectNameSingular.WorkspaceMember, objectRecordId: currentWorkspaceMember?.id, }); const { objectMetadataItem: objectMetadataItemActivity } = useObjectMetadataItem({ objectNameSingular: CoreObjectNameSingular.Activity, }); const { objectMetadataItem: objectMetadataItemActivityTarget } = useObjectMetadataItem({ objectNameSingular: CoreObjectNameSingular.ActivityTarget, }); const createOneActivityInCache = useCreateOneRecordInCache({ objectMetadataItem: objectMetadataItemActivity, }); const createActivityInCache = useRecoilCallback( ({ snapshot, set }) => ({ type, targetObject, customAssignee, }: { type: ActivityType; targetObject?: ActivityTargetableObject; customAssignee?: WorkspaceMember; }) => { const activityId = v4(); const createdActivityInCache = createOneActivityInCache({ id: activityId, __typename: 'Activity', createdAt: new Date().toISOString(), updatedAt: new Date().toISOString(), author: currentWorkspaceMemberRecord, authorId: currentWorkspaceMemberRecord?.id, assignee: customAssignee ?? currentWorkspaceMemberRecord, assigneeId: customAssignee?.id ?? currentWorkspaceMemberRecord?.id, type, }); if (isUndefinedOrNull(createdActivityInCache)) { throw new Error('Failed to create activity in cache'); } if (isUndefinedOrNull(targetObject)) { set(recordStoreFamilyState(activityId), { ...createdActivityInCache, activityTargets: [], comments: [], }); return { createdActivityInCache: { ...createdActivityInCache, activityTargets: [], }, }; } const targetObjectRecord = snapshot .getLoadable(recordStoreFamilyState(targetObject.id)) .getValue(); if (isUndefinedOrNull(targetObjectRecord)) { throw new Error('Failed to find target object record'); } const activityTargetsToCreate = makeActivityTargetsToCreateFromTargetableObjects({ activity: createdActivityInCache, targetableObjects: [targetObject], targetObjectRecords: [targetObjectRecord], }); const createdActivityTargetsInCache = createManyActivityTargetsInCache( activityTargetsToCreate, ); const activityTargetsConnection = getRecordConnectionFromRecords({ objectMetadataItems: objectMetadataItems, objectMetadataItem: objectMetadataItemActivityTarget, records: createdActivityTargetsInCache, withPageInfo: false, computeReferences: true, isRootLevel: false, }); modifyRecordFromCache({ recordId: createdActivityInCache.id, cache, fieldModifiers: { activityTargets: () => activityTargetsConnection, }, objectMetadataItem: objectMetadataItemActivity, }); const targetObjectMetadataItem = objectMetadataItems.find( (item) => item.nameSingular === targetObject.targetObjectNameSingular, ); if (isDefined(targetObjectMetadataItem)) { modifyRecordFromCache({ cache, objectMetadataItem: targetObjectMetadataItem, recordId: targetObject.id, fieldModifiers: { activityTargets: (activityTargetsRef, { readField }) => { const edges = readField<{ node: Reference }[]>( 'edges', activityTargetsRef, ); if (!edges) return activityTargetsRef; return { ...activityTargetsRef, edges: [...edges, ...activityTargetsConnection.edges], }; }, }, }); } set(recordStoreFamilyState(activityId), { ...createdActivityInCache, activityTargets: createdActivityTargetsInCache, comments: [], }); return { createdActivityInCache: { ...createdActivityInCache, activityTargets: createdActivityTargetsInCache, }, }; }, [ createOneActivityInCache, currentWorkspaceMemberRecord, createManyActivityTargetsInCache, objectMetadataItems, objectMetadataItemActivityTarget, cache, objectMetadataItemActivity, ], ); return { createActivityInCache, }; };