fix(sprint-5/etapa-4f): || fallback en name vacío — botón Guardar habilitado cuando Google devuelve full_name: ""
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled

El operador ?? solo hace fallback con null/undefined, no con cadena vacía.
Si Google devuelve user_metadata.full_name: "", la cadena de propagación es:
  buildAuthUser → name=""  →  upsertUserOnLogin inserta ""  →  syncProfileFromDB
  devuelve ""  →  AuthContext setUser → "" ?? prev.name = ""  →  ProfileSheet
  setName("") → name.trim() === '' → botón disabled → click no hace nada.

Fix: cambiar ?? por || en todos los puntos donde full_name o name de DB
se propagan al estado: buildAuthUser, syncProfileFromDB, getUserFromStorage,
useEffect IIFE en AuthContext. Agregar fallback a email en ProfileSheet
setName() para usuarios cuya fila en DB ya tiene name="" de sesiones anteriores.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-06-20 19:06:30 -03:00
parent 3ebfd65a90
commit 1c5329915a
3 changed files with 5 additions and 5 deletions

View File

@@ -30,7 +30,7 @@ function getUserFromStorage(): AuthUser | null {
return { return {
id: u.id as string, id: u.id as string,
email, email,
name: (u.user_metadata?.full_name as string) ?? email, name: (u.user_metadata?.full_name as string | undefined) || email,
avatarUrl: u.user_metadata?.avatar_url as string | undefined, avatarUrl: u.user_metadata?.avatar_url as string | undefined,
platformRole: email.endsWith('@inquality.com.py') ? 'platform_admin' : 'guest', platformRole: email.endsWith('@inquality.com.py') ? 'platform_admin' : 'guest',
} }
@@ -95,7 +95,7 @@ export function AuthProvider({ children }: { children: ReactNode }) {
if (profile) { if (profile) {
setUser((prev) => setUser((prev) =>
prev?.id === userId prev?.id === userId
? { ...prev, company: profile.company, name: profile.name ?? prev.name } ? { ...prev, company: profile.company, name: profile.name || prev.name }
: prev : prev
) )
} }

View File

@@ -65,7 +65,7 @@ export class SupabaseAuthService implements AuthService {
const { data } = await (signal ? base.abortSignal(signal) : base).maybeSingle() const { data } = await (signal ? base.abortSignal(signal) : base).maybeSingle()
if (!data) return null if (!data) return null
return { return {
name: (data.name as string | null) ?? undefined as unknown as string, name: ((data.name as string | null | undefined) || undefined) as unknown as string,
company: (data.company as string | null) ?? undefined, company: (data.company as string | null) ?? undefined,
} }
} }
@@ -94,7 +94,7 @@ export class SupabaseAuthService implements AuthService {
return { return {
id: supabaseUser.id, id: supabaseUser.id,
email, email,
name: supabaseUser.user_metadata?.full_name as string ?? email, name: (supabaseUser.user_metadata?.full_name as string | undefined) || email,
avatarUrl: supabaseUser.user_metadata?.avatar_url as string ?? undefined, avatarUrl: supabaseUser.user_metadata?.avatar_url as string ?? undefined,
platformRole: email.endsWith('@inquality.com.py') ? 'platform_admin' : 'guest', platformRole: email.endsWith('@inquality.com.py') ? 'platform_admin' : 'guest',
} }

View File

@@ -37,7 +37,7 @@ export function ProfileSheet({ open, onOpenChange }: ProfileSheetProps) {
useEffect(() => { useEffect(() => {
if (open && user) { if (open && user) {
setName(user.name) setName(user.name || user.email || '')
setCompany(user.company ?? '') setCompany(user.company ?? '')
setError(null) setError(null)
} }