usePlaybookAop.ts2.3 KBView on GitHub
'use client';

import { useQuery } from '@tanstack/react-query';
import { useTRPC } from '@/providers/query-provider';
import type {
  ConversationFieldDefs,
  CustomFieldDefs,
} from '@/modules/aop/components/TriggerConfigEditor';
import type { CrmFieldEnumOption } from '@/modules/crm/types';

/**
 * A `status` enum option as stored on the AOP — carries the stage colour + icon.
 * Same shape as every other CRM enum option, so the shared `getEnum*` helpers accept it.
 */
export type StageOption = CrmFieldEnumOption;

/**
 * Loads the backing AOP's field definitions for a playbook surface. Both the
 * stage header (icon + colour from `status` options) and the trigger editor
 * (field-change pickers) read from here. Keyed by `aopId`, so multiple stage /
 * trigger nodes in one document share a single cached request. Returns empty
 * definitions until an `aopId` is known (e.g. the legacy slug surface).
 *
 * `ownerUserId` is the AOP's owner, threaded from whoever mounted the document.
 * It is a parameter and not an ambient read of the member picker on purpose:
 * these node views also render inside the `/brain` document editor, which mounts
 * no picker and can be showing anyone's document. An ambient read there would
 * filter an admin's OWN playbook by whichever teammate they had selected, match
 * nothing, and empty the stage pickers and field editors of a document that is
 * working fine.
 */
export function usePlaybookAop(aopId?: string | null, ownerUserId?: string | null) {
  const trpc = useTRPC();
  const { data } = useQuery({
    ...trpc.aop.getAopById.queryOptions({
      id: aopId ?? '',
      targetUserId: ownerUserId ?? undefined,
    }),
    enabled: !!aopId,
    staleTime: 5 * 60 * 1000,
  });

  const aop = data?.aop as
    | {
        name?: string | null;
        conversationFieldDefinitions?: ConversationFieldDefs | null;
        customFieldDefinitions?: CustomFieldDefs | null;
      }
    | undefined;

  const aopName = aop?.name ?? null;
  const conversationFieldDefs = (aop?.conversationFieldDefinitions ?? {}) as ConversationFieldDefs;
  const customFieldDefs = (aop?.customFieldDefinitions ?? {}) as CustomFieldDefs;
  const statusOptions = (conversationFieldDefs.status?.options ?? []) as StageOption[];

  return { aopName, conversationFieldDefs, customFieldDefs, statusOptions };
}