---
# System prepended metadata

title: Untitled

---

```
// eslint-disable-next-line eslint-comments/disable-enable-pair
/* eslint-disable @typescript-eslint/consistent-type-assertions */
import { Box } from '@material-ui/core';
import assertNever from 'assert-never';
import { flow, mapValues } from 'lodash';
import { FormattedMessage } from 'react-intl';

import {
  candidacyEventVariant,
  candidacySelectionEventVariant,
} from '../../../constants';
import useDialogQueue from '../../../hooks/use-dialog-queue';
import type {
  CandidacySelectionEventVariant,
  CandidateRejectionReason,
} from '../../../interfaces/candidacy';
import type {
  JobOrder,
  JobOrderCandidacy,
} from '../../../interfaces/job-order';
import type { Recruiter } from '../../../interfaces/recruiter';
import type {
  MergedTalentProfile,
  Talent,
  TalentProfile,
  TalentProfileDataSource,
} from '../../../interfaces/talent';
import type { LinkedInTalentDocument } from '../../../interfaces/talent-linkedin';
import TalentProfileDialogContext from '../../organisms/Dialogs/TalentProfile/context';
import PipelineBoard from './Board';
import type { PipelineContextValue } from './Board/context';
import PipelineContext from './Board/context';
import { dataSourceCandidacies, sortCandidacies } from './constants';
import type { Props as DialogsProps } from './Dialogs';
import Dialogs, { DialogsName } from './Dialogs';
import type { Props as PipelineHeaderProps } from './Header';
import PipelineHeader from './Header';
import type { Props as PipelineMenuProps } from './Menu';

type Data = {
  candidacy: Record<string, JobOrderCandidacy>;
  jobOrder: Record<string, JobOrder>;
  talent: Record<string, Talent>;
  talentProfile: Record<string, TalentProfile>;
  linkedInTalent: Record<string, LinkedInTalentDocument>;
  mergedTalentProfile: Record<string, MergedTalentProfile>;
};

type CandidacyEventPayload = {
  candidacyId: string;
  note?: string;
};

type CandidacySourcedEventPayload = {
  mergedTalentProfileId: string;
  note?: string;
};

type CandidacySelectionHappenedEventPayload = {
  candidacySelectionScheduledId: string;
  conductedAt: string;
  note?: string;
};

type CandidacyEventHandlers = {
  [candidacyEventVariant.SOURCED]: (
    payload: CandidacySourcedEventPayload,
  ) => void;
  [candidacyEventVariant.RECOMMENDED]: (payload: CandidacyEventPayload) => void;
  [candidacyEventVariant.SELECTION_SCHEDULED]: (
    payload: CandidacyEventPayload & {
      variant: CandidacySelectionEventVariant;
    },
  ) => void;
  [candidacyEventVariant.SELECTION_HAPPENED]: (
    payload: CandidacySelectionHappenedEventPayload,
  ) => void;
  [candidacyEventVariant.OFFERED]: (payload: CandidacyEventPayload) => void;
  [candidacyEventVariant.HIRED]: (payload: CandidacyEventPayload) => void;
  [candidacyEventVariant.UNSUITABLE]: (
    payload: CandidacyEventPayload & {
      reasons: CandidateRejectionReason[];
    },
  ) => void;
};

type Props = {
  data: Data;
  currentJobOrderId: string;
  headerProps: PipelineHeaderProps;
  candidacyEventHandlers?: CandidacyEventHandlers;
  canEdit?: boolean;
  canEditCandidacy?: PipelineContextValue['canDragItem'];
  onFetchMergedTalentProfile?: (id: string) => void;
  onFetchTalentProfileSource?: (
    id: string,
    source?: TalentProfileDataSource,
  ) => void;
  onAddRecruiterToJobOrder?: (recruiterId: string, jobOrderId: string) => void;
  onRemoveRecruiterFromJobOrder?: (
    recruiterId: string,
    jobOrderId: string,
  ) => void;
};

type TalentProfileDialogData = {
  id: string;
  candidacyId: string;
};

const PipelineTemplate: React.FunctionComponent<Props> = ({
  data,
  currentJobOrderId,
  headerProps,
  candidacyEventHandlers,
  canEdit = false,
  canEditCandidacy,
  onFetchMergedTalentProfile,
  onFetchTalentProfileSource,
  onAddRecruiterToJobOrder,
  onRemoveRecruiterFromJobOrder,
}) => {
  const {
    queue: dialogQueue,
    lastInQueue: activeDialog,
    appendDialog,
    closeDialog,
  } = useDialogQueue();

  const currentJobOrder = data.jobOrder[currentJobOrderId];
  if (!currentJobOrder) {
    return null;
  }

  const { recruiters, candidacies } = currentJobOrder;

  const mergedTalentProfileIds = new Set(
    candidacies.map((candidacy) => candidacy.mergedTalentProfile.id),
  );

  const talentSearchProps: PipelineContextValue['talentSearchProps'] = {
    filterOptions: (options) =>
      options.filter(
        (option) => !mergedTalentProfileIds.has(option.MergedTalentProfileId),
      ),
    onSelect: (option) => {
      appendDialog({
        key: DialogsName.TALENT_PROFILE,
        data: {
          id: option.MergedTalentProfileId,
        } as TalentProfileDialogData,
      });

      // candidacyEventHandlers?.[candidacyEventVariant.SOURCED]?.({
      //   mergedTalentProfileId: option.MergedTalentProfileId,
      // });
    },
  };

  const dialogsData = mapValues(DialogsName, (name) => dialogQueue[name]?.data);

  const talentProfileDialogData = dialogsData.TALENT_PROFILE as TalentProfileDialogData;

  const talentProfileDialogTalentProfile =
    data.talentProfile[talentProfileDialogData.id];
    
  const talentProfileDialogCandidacy =
    data.candidacy[talentProfileDialogData.candidacyId];

  const rejectTalentDialogData =
    data.candidacy[dialogsData.REJECT_TALENT as string];

  const removeAssigneeDialogData = recruiters.find(
    (recruiter) => recruiter.id === dialogsData.REMOVE_ASSIGNEE,
  );

  const selectionEventTypeDialogData =
    data.candidacy[dialogsData.SELECTION_EVENT_TYPE as string];

  const selectionHappenedDialogData =
    data.candidacy[dialogsData.SELECTION_HAPPENED as string];

  const offerConfirmationDialogData =
    data.candidacy[dialogsData.OFFER_CONFIRMATION as string];

  const handleDropItem: PipelineContextValue['onDropItem'] = (
    candidacy,
    event,
  ) => {
    switch (event.stage) {
      case candidacyEventVariant.SOURCED:
        candidacyEventHandlers?.[event.stage]?.({
          mergedTalentProfileId: candidacy.mergedTalentProfile.id,
        });
        break;
      case candidacyEventVariant.RECOMMENDED:
      case candidacyEventVariant.HIRED:
        candidacyEventHandlers?.[event.stage]?.({
          candidacyId: candidacy.id,
        });
        break;
      case candidacyEventVariant.SELECTION_SCHEDULED:
        appendDialog({
          key: DialogsName.SELECTION_EVENT_TYPE,
          data: candidacy.id,
        });
        break;
      case candidacyEventVariant.OFFERED:
        appendDialog({
          key: DialogsName.OFFER_CONFIRMATION,
          data: candidacy.id,
        });
        break;
      case candidacyEventVariant.UNSUITABLE:
        appendDialog({
          key: DialogsName.REJECT_TALENT,
          data: candidacy.id,
        });
        break;
      default:
        assertNever(event);
    }
  };

  const handleAddRecruiterToJobOrder = (recruiter: Recruiter) => {
    onAddRecruiterToJobOrder?.(recruiter.id, currentJobOrderId);
  };

  const handlePipelineMenuOnClick: PipelineMenuProps['onClick'] = (key) => {
    switch (key) {
      case 'viewMembers':
        appendDialog({
          key: DialogsName.EDIT_MEMBERS,
        });
        break;
      default:
        assertNever(key);
    }
  };

  const handleTalentCardMenuItemOnClick: PipelineContextValue['onClickTalentCardMenuItem'] = (
    key,
    candidacy,
  ) => {
    switch (key) {
      case 'unsuitable':
        appendDialog({
          key: DialogsName.REJECT_TALENT,
          data: candidacy.id,
        });
        break;
      case 'nextSelection':
        appendDialog({
          key: DialogsName.SELECTION_EVENT_TYPE,
          data: candidacy.id,
        });
        break;
      case 'view': {
        const talentProfile =
          data.talentProfile[candidacy.mergedTalentProfile.id];

        if (talentProfile) {
          onFetchTalentProfileSource?.(
            talentProfile.id,
            talentProfile.sources[0],
          );
        }

        onFetchMergedTalentProfile?.(candidacy.mergedTalentProfile.id);
        appendDialog({
          key: DialogsName.TALENT_PROFILE,
          data: {
            id: candidacy.mergedTalentProfile.id,
            candidacyId: candidacy.id,
          },
        });
        break;
      }
      default:
        assertNever(key);
    }
  };

  const handleInterviewHappenedOnClick: PipelineContextValue['onClickInterviewHappened'] = (
    candidacy,
  ) => {
    appendDialog({
      key: DialogsName.SELECTION_HAPPENED,
      data: candidacy.id,
    });
  };

  const filterCandidacies = flow(
    dataSourceCandidacies[headerProps.options.dataSource],
    sortCandidacies[headerProps.options.sort],
  );

  const dialogProps: DialogsProps['dialogProps'] = {
    editMembers: dialogQueue[DialogsName.EDIT_MEMBERS] && {
      data: currentJobOrder,
      onAddRecruiter: handleAddRecruiterToJobOrder,
      onRemoveRecruiter: (recruiter) => {
        appendDialog({
          key: DialogsName.REMOVE_ASSIGNEE,
          data: recruiter.id,
        });
      },
    },
    rejectTalent: rejectTalentDialogData?.mergedTalentProfile_ && {
      data: rejectTalentDialogData.mergedTalentProfile_,
      job: currentJobOrder,
      onSubmit: (formData) => {
        candidacyEventHandlers?.[candidacyEventVariant.UNSUITABLE]({
          candidacyId: rejectTalentDialogData.id,
          note: formData.additionalNote,
          reasons: formData.reasons,
        });

        closeDialog(DialogsName.REJECT_TALENT);
      },
    },
    removeAssignee: removeAssigneeDialogData && {
      data: removeAssigneeDialogData,
      onSubmit: () => {
        onRemoveRecruiterFromJobOrder?.(
          removeAssigneeDialogData.id,
          currentJobOrderId,
        );

        closeDialog(DialogsName.REMOVE_ASSIGNEE);
      },
    },
    talentProfile: talentProfileDialogTalentProfile && {
      data: talentProfileDialogTalentProfile,
      additionalInfo: {
        source: {
          glints: data.talent[talentProfileDialogTalentProfile.id],
          linkedIn: data.linkedInTalent[talentProfileDialogTalentProfile.id],
        },
      },
      onSelectAction: (key) => {
        if(!talentProfileDialogCandidacy) {
          return;
        }

        switch (key) {
          case candidacyEventVariant.SOURCED:
            candidacyEventHandlers?.[key]({
              mergedTalentProfileId:
                talentProfileDialogTalentProfile.MergedTalentProfileId,
            });
            break;
          case candidacyEventVariant.RECOMMENDED:
          case candidacyEventVariant.OFFERED:
          case candidacyEventVariant.HIRED:
            candidacyEventHandlers?.[key]({
              candidacyId: talentProfileDialogCandidacy.id,
            });
            break;
          case candidacyEventVariant.SELECTION_SCHEDULED:
            appendDialog({
              key: DialogsName.SELECTION_EVENT_TYPE,
              data: talentProfileDialogCandidacy.id,
            });
            break;
          case candidacyEventVariant.SELECTION_HAPPENED:
            appendDialog({
              key: DialogsName.SELECTION_HAPPENED,
              data: talentProfileDialogCandidacy.id,
            });
            break;
          case candidacyEventVariant.UNSUITABLE:
            appendDialog({
              key: DialogsName.REJECT_TALENT,
              data: talentProfileDialogCandidacy.id,
            });
            break;
          default:
            assertNever(key);
        }
      },
      onSource: ()
    },
    selectionEventType: selectionEventTypeDialogData && {
      defaultValues: {
        value: candidacySelectionEventVariant.ON_SITE_INTERVIEW,
      },
      onSubmit: ({ value }) => {
        candidacyEventHandlers?.[candidacyEventVariant.SELECTION_SCHEDULED]?.({
          candidacyId: selectionEventTypeDialogData.id,
          variant: value,
        });

        closeDialog(DialogsName.SELECTION_EVENT_TYPE);
      },
    },
    selectionHappened: selectionHappenedDialogData && {
      onSubmit: ({ date }) => {
        candidacyEventHandlers?.[candidacyEventVariant.SELECTION_HAPPENED]?.({
          candidacySelectionScheduledId: selectionHappenedDialogData.latest.id,
          conductedAt: date,
        });

        closeDialog(DialogsName.SELECTION_HAPPENED);
      },
    },
    offerConfirmation: offerConfirmationDialogData && {
      name: offerConfirmationDialogData.mergedTalentProfile_?.name ??
        offerConfirmationDialogData.mergedTalentProfile_?.email ?? (
          <FormattedMessage
            id="unnamed.talent"
            defaultMessage="Unnamed Talent"
          />
        ),
      onConfirm: () => {
        candidacyEventHandlers?.[candidacyEventVariant.OFFERED]?.({
          candidacyId: offerConfirmationDialogData.id,
        });

        closeDialog(DialogsName.OFFER_CONFIRMATION);
      },
    },
  };

  return (
    <PipelineContext.Provider
      value={{
        canEdit,
        talentSearchProps,
        canDragItem: canEditCandidacy,
        onDropItem: handleDropItem,
        onClickTalentCardMenuItem: handleTalentCardMenuItemOnClick,
        onClickInterviewHappened: handleInterviewHappenedOnClick,
      }}
    >
      <Box
        py={2}
        display="flex"
        flexDirection="column"
        flex={1}
        overflow="hidden"
      >
        <PipelineHeader
          {...headerProps}
          pipelineMenuProps={{
            onClick: handlePipelineMenuOnClick,
          }}
        />

        <PipelineBoard candidacies={filterCandidacies(candidacies)} />

        <TalentProfileDialogContext.Provider
          value={{
            canEditActiveCandidacy: canEdit,
            activeCandidacy: talentProfileDialogData && {
              ...talentProfileDialogData,
              jobOrder: currentJobOrder,
            },
            candidacies:
              talentProfileDialogData &&
              data.mergedTalentProfile[
                talentProfileDialogData.mergedTalentProfile.id
              ]?.candidacies,
          }}
        >
          <Dialogs
            activeDialog={activeDialog?.key}
            dialogProps={dialogProps}
            onCloseDialog={closeDialog}
          />
        </TalentProfileDialogContext.Provider>
      </Box>
    </PipelineContext.Provider>
  );
};

export type { Props };
export default PipelineTemplate;

```