* wip * wip * wip * format * wip(mobile): lint and format * cleanup * nits * nits * idiomatic react * nit * format all root files
44 lines
1.3 KiB
TypeScript
44 lines
1.3 KiB
TypeScript
import type { Human } from '@/api/types';
|
||
import { getInitials } from '@/lib/utils';
|
||
|
||
export const REMOVED_MEMBER_LABEL = 'Removed member';
|
||
export const REMOVED_MEMBER_INITIALS = '–';
|
||
|
||
export interface HumanDisplay {
|
||
/** True when the human was found in the provided list. */
|
||
exists: boolean;
|
||
/** Short name for inline text (e.g. message sender). */
|
||
displayName: string;
|
||
/** Full email or fallback label for tooltips. */
|
||
email: string;
|
||
/** Initials for avatar fallback. */
|
||
initials: string;
|
||
}
|
||
|
||
/**
|
||
* Resolve a human's display info by id, falling back consistently when the
|
||
* human has been removed from the network. Member content (particles, reactions,
|
||
* etc.) is retained after removal, so every render path needs a graceful fallback
|
||
* instead of leaking raw ids into the UI.
|
||
*/
|
||
export function resolveHumanDisplay(
|
||
humanId: string | null | undefined,
|
||
humans: Human[] | undefined,
|
||
): HumanDisplay {
|
||
const human = humanId ? humans?.find((h) => h.id === humanId) : undefined;
|
||
if (!human) {
|
||
return {
|
||
exists: false,
|
||
displayName: REMOVED_MEMBER_LABEL,
|
||
email: REMOVED_MEMBER_LABEL,
|
||
initials: REMOVED_MEMBER_INITIALS,
|
||
};
|
||
}
|
||
return {
|
||
exists: true,
|
||
displayName: human.email_prefix,
|
||
email: human.email,
|
||
initials: getInitials(human.email),
|
||
};
|
||
}
|