fix(web): UserMenu crashes for phone-only signups (null email + name)
All checks were successful
Deploy to Production / deploy (push) Successful in 56s
All checks were successful
Deploy to Production / deploy (push) Successful in 56s
Dashboard layout threw TypeError: Cannot read properties of null (reading 'charAt') the moment a phone-only user reached any dashboard page — user.email and user.name are both null for fresh SMS signups, and the initial-letter computation didn't tolerate it. Fallback chain for the visible identifier: name → email → phone → 'Account'. Avatar colour seed falls back to userId. The secondary line under the name also uses phone when email is null. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
d0f3c202eb
commit
c656bd3189
@ -16,8 +16,12 @@ import { useEffect, useRef, useState } from 'react';
|
||||
|
||||
interface MeUser {
|
||||
userId: string;
|
||||
email: string;
|
||||
// All three can be null on a fresh phone-only signup: name not collected,
|
||||
// email not entered, phone is the only stable identifier. Anything that
|
||||
// dereferences these MUST handle the null case.
|
||||
email: string | null;
|
||||
name: string | null;
|
||||
phone: string | null;
|
||||
plan?: 'hobby' | 'pro' | 'team' | 'enterprise';
|
||||
isAdmin?: boolean;
|
||||
}
|
||||
@ -81,9 +85,19 @@ export function UserMenu() {
|
||||
|
||||
if (!user) return null;
|
||||
|
||||
const label = user.name?.trim() || user.email;
|
||||
const initial = (user.name?.trim() || user.email).charAt(0).toUpperCase();
|
||||
const shade = avatarShade(user.email);
|
||||
// Pick the best identifier we have. Phone-only signups have null email
|
||||
// AND null name — used to crash with .charAt(null) here. Fallback chain:
|
||||
// name → email → phone → "Account".
|
||||
const identifier =
|
||||
user.name?.trim() ||
|
||||
user.email ||
|
||||
user.phone ||
|
||||
'Account';
|
||||
const label = identifier;
|
||||
const initial = identifier.charAt(0).toUpperCase() || '?';
|
||||
// Avatar colour is derived from a stable identifier so it doesn't shift
|
||||
// across sessions. Fall back to userId so we always have something.
|
||||
const shade = avatarShade(user.email || user.phone || user.userId);
|
||||
|
||||
return (
|
||||
<div ref={wrapRef} className="relative">
|
||||
@ -121,7 +135,7 @@ export function UserMenu() {
|
||||
{label}
|
||||
</div>
|
||||
<div className="mono truncate text-[10.5px] text-[--color-fg-subtle]">
|
||||
{user.email}
|
||||
{user.email || user.phone || user.userId.slice(0, 8)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user