PhoenixKitProjects.People (PhoenixKitProjects v0.21.1)

Copy Markdown View Source

The ONE doorway to people/team/department data for this module — the staff-optional seam (Phase B of the hub rework, panel-approved design).

Why shadow schemas, not a bridge

The staff DB tables are created by CORE's migrations (V100), not by the phoenix_kit_staff package — staff ships no migrations; it is the admin UI + context over core-owned tables. So the tables (and projects' SQL FKs to them) exist on every install, and projects can keep its belongs_to graph, preloads, authz relationship grants, and direct assignee queries by mapping its OWN minimal read-only schemas (PhoenixKitProjects.People.{Person,Team,Department,TeamMembership}) over those tables. The staff PACKAGE is optional: it is the people ADMIN surface, not the data's owner.

Rules

  • Read-only: no changesets, no writes — people are managed in staff.
  • Filter semantics COPIED from staff, not imported: soft-deleted rows are status == "trashed" and excluded from listings by default.
  • Label semantics mirrored from staff: display_name/1 resolves name → user's first/last name → user email → "Unnamed"; team/department names localize via the row's translations map.
  • staff_admin_available?/0 gates ONLY admin-UI affordances (manage- people links, the "Me" chip's person resolution when staff adds value) — data reads never require the staff package.

Summary

Functions

name → user's first/last → user email → "Unnamed" (staff parity).

A person by uuid with [:user, :primary_department] preloaded, or nil.

The person linked to a core user, or nil. STAFF-PARITY: resolves trashed people too (soft-delete keeps assignments/memberships live so restore is clean — filtering here blanked My Tasks and the Me chip for the whole trash→restore window; panel round). Only LISTINGS exclude trashed.

All departments, name-ordered.

A person's team memberships with team: [:department] preloaded.

Non-trashed people ordered by display name source, [:user] preloaded (the option loaders read the user email). Mirrors staff's default trashed-exclusion.

All teams with their department preloaded, name-ordered.

A team/department's localized name: translations[lang]["name"] else the primary.

Whether the staff PACKAGE (the people admin surface) is installed and enabled — for UI affordances only; the data paths below never need it.

Functions

display_name(arg1)

@spec display_name(PhoenixKitProjects.People.Person.t() | nil) :: String.t()

name → user's first/last → user email → "Unnamed" (staff parity).

get_person(uuid, opts \\ [])

@spec get_person(
  binary(),
  keyword()
) :: PhoenixKitProjects.People.Person.t() | nil

A person by uuid with [:user, :primary_department] preloaded, or nil.

get_person_by_user_uuid(user_uuid, opts \\ [])

@spec get_person_by_user_uuid(
  binary(),
  keyword()
) :: PhoenixKitProjects.People.Person.t() | nil

The person linked to a core user, or nil. STAFF-PARITY: resolves trashed people too (soft-delete keeps assignments/memberships live so restore is clean — filtering here blanked My Tasks and the Me chip for the whole trash→restore window; panel round). Only LISTINGS exclude trashed.

list_departments()

@spec list_departments() :: [PhoenixKitProjects.People.Department.t()]

All departments, name-ordered.

list_memberships_for_person(person_uuid)

@spec list_memberships_for_person(binary()) :: [
  PhoenixKitProjects.People.TeamMembership.t()
]

A person's team memberships with team: [:department] preloaded.

list_people(opts \\ [])

@spec list_people(keyword()) :: [PhoenixKitProjects.People.Person.t()]

Non-trashed people ordered by display name source, [:user] preloaded (the option loaders read the user email). Mirrors staff's default trashed-exclusion.

list_teams()

@spec list_teams() :: [PhoenixKitProjects.People.Team.t()]

All teams with their department preloaded, name-ordered.

localized_name(arg1, lang)

@spec localized_name(
  PhoenixKitProjects.People.Team.t()
  | PhoenixKitProjects.People.Department.t()
  | nil,
  String.t() | nil
) :: String.t() | nil

A team/department's localized name: translations[lang]["name"] else the primary.

staff_admin_available?()

@spec staff_admin_available?() :: boolean()

Whether the staff PACKAGE (the people admin surface) is installed and enabled — for UI affordances only; the data paths below never need it.