# US-NOT-001b: Centro de Notificaciones In-App **Épica:** EXT-003 - Sistema de Notificaciones **Sprint:** Mes 3, Semana 2-3 **Story Points:** 5 SP **Presupuesto:** $6,580 MXN **Prioridad:** Alta (Extensión Fase 3) **Estado:** 📋 Planificada **Relación:** Parte de US-NOT-001 (dividida en a/b/c por PF-001) --- ## Descripción **Como** estudiante de Gamilit **Quiero** acceder a un centro de notificaciones donde pueda ver todas mis notificaciones, filtrarlas, marcarlas como leídas y tomar acciones **Para** estar informado de todas las actividades importantes y gestionar notificaciones de manera eficiente **Contexto:** Esta user story es parte del sistema completo de notificaciones (EXT-003), dividida para cumplir con PF-001. Esta parte implementa la **interfaz de usuario** del centro de notificaciones, consumiendo la infraestructura WebSocket de US-NOT-001a. **Alcance:** - UI del centro de notificaciones (dropdown/modal) - Lista de notificaciones con scroll infinito - Badge contador de notificaciones no leídas - Filtros por tipo (Todas, Amigos, Gremios, Misiones, Logros) - Marcar como leído (individual y batch) - Eliminar notificaciones - Toast notifications in-app - Navegación a destino al hacer click --- ## Valor de Negocio - **Click-Through Rate**: >40% usuarios hacen click en notificaciones - **Interaction Rate**: +45% tasa de respuesta a solicitudes sociales - **Session Initiation**: 38% de sesiones iniciadas por notificación - **User Satisfaction**: >4.3/5 rating en centro de notificaciones - Reduce "notification fatigue" con filtros y priorización --- ## Criterios de Aceptación ### CA-01: Tipos de Notificaciones Soportadas **Dado** que ocurren eventos en la plataforma **Cuando** el sistema detecta actividad relevante **Entonces** debe generar notificaciones para estos tipos: **1. Achievements (Logros)** - Icono: 🏆 - `achievement:unlocked` - Nuevo logro desbloqueado - `achievement:milestone` - Hito de logros alcanzado - Payload: `{ achievementId, name, rarity, rewards, icon }` **2. Friends (Amigos)** - Icono: 👤 - `friend:request` - Nueva solicitud de amistad - `friend:accepted` - Solicitud aceptada - `friend:online` - Amigo se conectó - `friend:activity` - Amigo completó algo importante - Payload: `{ friendId, friendName, avatar, action }` **3. Guilds (Gremios)** - Icono: 🛡️ - `guild:invitation` - Invitación a gremio - `guild:accepted` - Aceptado en gremio - `guild:challenge:new` - Nuevo desafío de gremio - `guild:challenge:complete` - Desafío completado - `guild:leaderboard` - Gremio subió en ranking - `guild:member:joined` - Nuevo miembro se unió - Payload: `{ guildId, guildName, icon, message, data }` **4. Missions (Misiones)** - Icono: 🎯 - `mission:completed` - Misión completada - `mission:renewed` - Nuevas misiones disponibles - `mission:expiring` - Misión expira pronto (24h) - `mission:streak:milestone` - Hito de streak alcanzado - Payload: `{ missionId, type, progress, rewards }` **5. System (Sistema)** - Icono: 📢 - `system:announcement` - Anuncio importante - `system:maintenance` - Mantenimiento programado - `system:event:new` - Nuevo evento especial - Payload: `{ title, message, priority, actionUrl }` **6. Gamification** - Icono: ⭐ - `xp:level_up` - Subió de nivel K'in - `cacao:milestone` - Alcanzó hito de Cacao - Payload: `{ oldLevel, newLevel, rewards }` ### CA-02: Centro de Notificaciones (UI) **Dado** que un usuario accede al centro de notificaciones **Cuando** hace click en el icono de campana (🔔) en navbar **Entonces** debe ver: **UI del Centro (Dropdown)**: - Lista de notificaciones (últimas 50 cargadas inicialmente) - Ordenamiento cronológico (más recientes primero) - Badge con contador de no leídas (número rojo en icono) - Indicador visual de leído/no leído: - **No leído**: Fondo azul claro, punto azul a la izquierda - **Leído**: Fondo blanco, sin punto - Filtros por tipo: Todas, Amigos, Gremios, Misiones, Logros - Botón "Marcar todas como leídas" (header) - Botón "Borrar todas leídas" (footer) - Acción directa al hacer click (navegar a destino) - Scroll infinito para cargar más notificaciones - Timestamps relativos: "hace 2 min", "hace 1h", "ayer", "hace 3 días" **Interacciones**: - Click en notificación → Marcar como leída + navegar a destino - Click en "X" (individual) → Eliminar notificación - Click fuera del dropdown → Cerrar centro - Scroll al final → Cargar 50 notificaciones más **Validación**: - Centro muestra últimas 50 notificaciones al abrir - Badge actualiza número al marcar como leído - Filtro "Amigos" muestra solo notificaciones de amigos - Scroll infinito carga más notificaciones correctamente ### CA-03: Notificaciones Toast (In-app Real-time) **Dado** que un usuario está activo en la plataforma **Cuando** llega una notificación en tiempo real (vía WebSocket) **Entonces** debe mostrarse toast notification: **Características del Toast**: - **Posición**: - Desktop: Esquina superior derecha (fixed position) - Mobile: Superior centro (full width) - **Duración**: 5 segundos (auto-dismiss) - **Tipos visuales** (basados en prioridad): - Info (azul): Notificaciones generales (P3) - Success (verde): Logros, completaciones (P2) - Warning (amarillo): Expiraciones, advertencias (P1) - Error (rojo): Errores críticos, sistema (P0) **Contenido del Toast**: - Icono del tipo de notificación (🏆, 👤, 🛡️, etc.) - Avatar del usuario (si aplica) - Título conciso (max 50 caracteres) - Mensaje breve (max 80 caracteres) - Botón de acción (opcional): "Ver", "Aceptar", "Ir a..." - Botón de cerrar (X) **Comportamiento**: - Sonido opcional (activable en preferencias) - Vibración en móviles (si habilitado) - Máximo 3 toasts simultáneos (stack vertical) - Si llega 4to toast → descartar el más antiguo - Animación de entrada: Slide from right (desktop) o top (mobile) - Animación de salida: Fade out - Hover en toast → Pausar auto-dismiss timer **Validación**: - Toast aparece <1 segundo después de recibir notificación WebSocket - Auto-dismiss funciona después de 5 segundos - Stack de toasts no supera 3 simultáneos - Click en toast navega correctamente ### CA-04: Badge Contador de No Leídas **Dado** que un usuario tiene notificaciones no leídas **Cuando** navega por la plataforma **Entonces** debe ver badge contador: **Características**: - Ubicación: Encima del icono de campana (🔔) en navbar - Forma: Círculo rojo con número blanco - Número: Cantidad de notificaciones no leídas - Max display: "99+" si >99 no leídas - Animación: "Bounce" al incrementar - Oculto si 0 no leídas **Actualización**: - Incrementa al recibir notificación en tiempo real - Decrementa al marcar notificación como leída - Resetea a 0 al "Marcar todas como leídas" - Sincroniza con servidor al reconectar **Validación**: - Badge muestra número correcto de no leídas - Incrementa inmediatamente al recibir notificación - Muestra "99+" si >99 no leídas --- ## Especificaciones Técnicas ### Frontend - React Components **Tecnologías**: React 18, TypeScript, Zustand, Socket.IO Client, date-fns, sonner (toasts), TailwindCSS **NotificationCenter Component**: ```typescript import { useState } from 'react'; import { useNotifications } from '@/hooks/useNotifications'; export function NotificationCenter() { const { notifications, unreadCount, markAsRead, markAllAsRead } = useNotifications(); const [isOpen, setIsOpen] = useState(false); const [filter, setFilter] = useState<'all' | 'friend' | 'guild' | 'mission' | 'achievement'>('all'); const filteredNotifications = filter === 'all' ? notifications : notifications.filter(n => n.type.startsWith(filter)); return (
{notification.message}
{formatDistanceToNow(new Date(notification.createdAt), { addSuffix: true, locale: es })}{notification.title}
{notification.message}