Saltar al contenido principal

Visitantes del Perfil — Referencia Técnica

← Volver a Visitantes del Perfil

Actualizado — la conexión faltante del lado de escritura descrita a continuación ha sido corregida: PublicProfilePage.tsx ahora llama a recordProfileVisit al cargar. La funcionalidad está completamente operativa de extremo a extremo a partir de este cambio.

Dónde vive esto

Backend

Frontend

  • apps/frontend-nextjs/src/page-components/settings/ProfileViewersPage.tsx — consulta myProfileViewers(limit: 50, offset: 0) y myProfileViewerCount al montar (network-only), renderiza la lista + el conteo, y un botón Limpiar que llama a clearMyProfileViewers. limit: 50 está fijado de forma estática — no hay interfaz de paginación pese a que el resolver acepta offset.
  • Ruta: apps/frontend-nextjs/src/app/settings/profile-viewers/page.tsx
  • Puntos de entrada: SettingsPage.tsx (el elemento de configuración "Visitantes del perfil") y ProfilePage.tsx (un elemento de menú en tu propio perfil), ambos enlazando a /settings/profile-viewers.
  • recordProfileVisit ahora se llama desde PublicProfilePage.tsx (corregido en este cambio) — un useEffect se dispara una vez por carga de página, reutilizando la verificación existente isOwnProfile de la página para omitir las auto-visitas, y solo se dispara para visitantes autenticados. La mutación absorbe sus propios errores del lado del cliente (.catch(() => {})) para que una llamada fallida nunca rompa la página de perfil. La protección propia del backend de no-op en auto-visitas y el debounce de 60 segundos siguen aplicándose como una segunda capa de protección.

Checklist de implementación técnica

  • myProfileViewers — query real, deduplica a una fila por visitante distinto (visita más reciente) en el código de la aplicación (profile-view.manager.js)
  • myProfileViewerCount — query real
  • clearMyProfileViewers — elimina todas las filas del que llama
  • recordProfileVisit (backend) — completamente implementado: requiere autenticación, no hace nada en auto-visitas, debounce de 60s, verifica el flag hide_profile_visits (ver abajo), que es real y está conectado. Corrección: el argumento se llama targetUserId, no viewedUserId como asumía una versión anterior de este documento — verifica contra el archivo de tipos en lugar de este documento si tienes dudas.
  • recordProfileVisit (punto de llamada del frontend) — corregido en este cambio. PublicProfilePage.tsx ahora lo llama en un useEffect al cargar, protegido para omitir auto-visitas y visitantes no autenticados.
  • flag de privacidad hide_profile_visits — real y conectado de extremo a extremo: por defecto es false en el objeto de configuración predeterminada de privacy-settings.manager.js, incluido en la lista blanca booleana de validatePrivacySettings, expuesto como hideProfileVisits en el tipo GraphQL PrivacySettings y su input, y tiene un interruptor en AccountPrivacyPage.tsx. Se aplica en la verificación de control de profile-view.manager.js — un visitante que lo tenga activado no registra ninguna visita para ningún perfil que navegue.
  • Sin gating premium/monedas — gratis para todos los usuarios autenticados.
  • Sin trabajo de retención/expiración — el historial es ilimitado hasta que el usuario llama a clearMyProfileViewers.
  • No existe implementación en iOS (confirmado mediante grep en apps/ios).

API GraphQL

query MyProfileViewers($limit: Int, $offset: Int) {
myProfileViewers(limit: $limit, offset: $offset) {
viewer { id username profilePicture isVerified }
viewedAt
}
}

query MyProfileViewerCount { myProfileViewerCount }

# Now called from PublicProfilePage.tsx on load (fixed this pass)
mutation RecordProfileVisit($targetUserId: ID!) {
recordProfileVisit(targetUserId: $targetUserId) # returns Boolean!, not an object
}

mutation ClearMyProfileViewers { clearMyProfileViewers } # also returns Boolean!, not an object