import { initialsFromDisplayName } from "./column-filter-range-policy" import type { ColumnCellKind } from "./column-cell-kind" export type PersonFilterOption = { value: string label: string initials?: string email?: string } function personFromStub(raw: unknown): PersonFilterOption | null { if (!raw || typeof raw !== "object" || !("name" in raw)) return null const record = raw as { name?: unknown; initials?: unknown } const name = String(record.name ?? "").trim() if (!name) return null const initials = typeof record.initials === "string" ? record.initials : initialsFromDisplayName(name) return { value: name, label: name, initials } } /** Unique person options for avatar pickers — derived from the hub dataset. */ export function derivePersonFilterOptions>( rows: T[], fieldKey: string, cellKind?: ColumnCellKind, ): PersonFilterOption[] { const seen = new Map() const emailKey = `${fieldKey}Email` for (const row of rows) { const val = row[fieldKey] if (cellKind === "people-rail" && Array.isArray(val)) { for (const entry of val) { const opt = personFromStub(entry) if (opt && !seen.has(opt.value)) seen.set(opt.value, opt) } continue } if (typeof val === "string" && val.trim()) { if (seen.has(val)) continue const email = typeof row[emailKey] === "string" ? (row[emailKey] as string) : undefined seen.set(val, { value: val, label: val, initials: initialsFromDisplayName(val), email, }) } } return [...seen.values()].sort((a, b) => a.label.localeCompare(b.label)) } export function isPersonSelectFilter(cellKind?: ColumnCellKind): boolean { return cellKind === "person" || cellKind === "people-rail" }