---
id: CMP-CRM-ENT-003
title: Affiliation Section
product_area: crm
module: entities
revision: 1
status: draft
design_intent: proposed
implementation_evidence: observed
source_sha:
  react-console: baf6dae382d6f41dce976c7f848667ccc37e076f
purpose: Groups a contact’s organizational relationships so staff can distinguish current, upcoming and past ties
  and manage the draft.
reuse: Serves Create Contact, Edit Contact and Contact 360. The organization Contacts tab uses a separate API-backed
  section of the same exported name and is outside this component’s contract.
supports:
- CAP-CRM-ENT-009
- CAP-CRM-ENT-010
realises:
- CON-CRM-ENT-003
props:
- name: rows
  type: ordered resolved affiliation rows
  required: true
  default: none
  meaning: Supplies primary-first rows with display strings and status already determined; ordering within each
    group is preserved.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: readOnly
  type: boolean
  required: false
  default: false
  meaning: Suppresses row mutations and switches Add to an optional Manage destination.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: onAdd
  type: event handler
  required: false
  default: none
  meaning: Opens a new affiliation draft.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: onEdit
  type: handler receiving an affiliation identifier
  required: false
  default: none
  meaning: Opens the selected affiliation.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: onMakePrimary
  type: handler receiving an affiliation identifier
  required: false
  default: none
  meaning: Requests that the caller make the identified affiliation primary.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: onRemove
  type: handler receiving an affiliation identifier
  required: false
  default: none
  meaning: Requests removal from the contact draft.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: issues
  type: messages keyed by affiliation identifier
  required: false
  default: none
  meaning: Passes validation text to individual rows.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: noPrimaryNotice
  type: text
  required: false
  default: none
  meaning: Supplies a quiet status notice; the section does not derive it.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: manageHref
  type: navigation destination
  required: false
  default: none
  meaning: Provides Manage in read-only mode.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
events:
- name: add
  when: Add Affiliation is activated.
  payload: No payload.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- name: edit / make primary / remove
  when: A row action is activated.
  payload: The selected affiliation identifier.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
states:
- state: empty
  experience: A dashed invitation says there are no organization affiliations, with Add or Manage when available.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- state: mixed dates
  experience: Counts and filters distinguish current, upcoming and past groups.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- state: one date class
  experience: No redundant filter group appears.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- state: read only
  experience: Rows have no mutation callbacks; an optional Manage link remains.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- state: notice or issue
  experience: The overall notice is a status message and individual issues are alerts.
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
validation:
- BR-CAP-CRM-ENT-009-05
accessibility: The toggle group is named Filter Affiliations, row collections use list elements, and the no-primary
  notice has status semantics. Row action naming comes from Affiliation Row. A complete keyboard and screen-reader
  audit is absent.
design_system:
- button
- toggle group
- navigation link
depends_on:
- CMP-CRM-ENT-002
implementation: CMI-CRM-ENT-003
acceptance:
- id: AC-CMP-CRM-ENT-003-01
  proved_by: []
  statement: Rows classified future appear in Upcoming and are excluded from the Current filter.
  level: unit
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- id: AC-CMP-CRM-ENT-003-02
  proved_by: []
  statement: Read-only mode supplies no edit, primary or remove actions to rows.
  level: unit
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- id: AC-CMP-CRM-ENT-003-03
  proved_by: []
  statement: A future nonprimary open-ended row receives Make Primary when the callback exists; its eligibility
    still requires caller validation.
  level: unit
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
controls: []
evidence:
- react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
narrative_sources:
- section: What It Is For
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- section: Where It Is Used
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- section: How It Behaves
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- section: Its Contract
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- section: States
  provenance: observed
  source: react-console:components/affiliations/organization-affiliations-section.tsx; react-console:lib/affiliations/section.ts
- section: Accessibility
  provenance: unknown
  source: FND-CRM-ENT-161
- section: Open Design Questions
  provenance: unknown
  source: FND-CRM-ENT-161; FND-CRM-ENT-162; FND-CRM-ENT-163
used_by: []
---

# Affiliation Section

## What It Is For

Groups a contact’s organizational relationships so staff can distinguish current, upcoming and past ties and manage the draft. The reusable section renders contact-owned relationship groups and delegates presentation to Affiliation Row. Date-group helpers determine which filters are useful and preserve supplied order. It is separate from the organization-side people-list section.

## Where It Is Used

Serves Create Contact, Edit Contact and Contact 360. The organization Contacts tab uses a separate API-backed section of the same exported name and is outside this component’s contract. The form-engine affiliation adapter renders this section in Create Contact and Edit Contact. The Contact 360 affiliations card supplies read-only rows and an optional Manage destination. Organization 360 uses its own paged people-list implementation.

## How It Behaves

Counts describe all supplied rows, while the selected filter controls the visible groups. Filters appear only when multiple date classes occur, and include only classes present. If changed data makes the selected class unavailable, the effective filter becomes All. Current, upcoming and past rows remain separate. Add is available only in editable mode with a callback; read-only mode can instead offer Manage. The component preserves caller ordering inside each class rather than sorting the records itself.

## Its Contract

The caller supplies resolved rows, optional issues and notices, and all mutation callbacks. Filter choice is the section’s only local application state. Row callbacks receive identifiers so the form can find its own draft entries. The section offers Make Primary for any nonpast, nonprimary row with no end date when the callback exists; this includes future rows. The upstream draft validation and service remain responsible for rejecting an ineligible primary request.

## States

Empty: A dashed invitation says there are no organization affiliations, with Add or Manage when available. Mixed dates: Counts and filters distinguish current, upcoming and past groups. One date class: No redundant filter group appears. Read only: Rows have no mutation callbacks; an optional Manage link remains. Notice or issue: The overall notice is a status message and individual issues are alerts.

## Accessibility

The toggle group is named Filter Affiliations, row collections use list elements, and the no-primary notice has status semantics. Row action naming comes from Affiliation Row. A complete keyboard and screen-reader audit is absent. Accessibility verification is an open obligation recorded in the component accessibility finding.

## Open Design Questions

The recorded interaction is observed implementation, with proposed design intent. Component criteria need complete executable bindings and browser accessibility review. Screen owners must wire the registered components into their designs; this slice records usage without changing those screen contracts.
