Files
qwen3-6-lora/data/raw/sanitized/plans/puedes-revisar-los-tickets-cheerful-catmull.md

7.1 KiB

GFIBER-711 — Tutorial interactivo de My Usage

Contexto

GFIBER-711 ("Tutorial: My Usage") es la tercera subtarea de GFIBER-710 ("Implement additional in-app tutorials") que se aborda, después de GFIBER-702 (Upsell Evaluator, mergeado a dev) y GFIBER-712 (Dashboard, actualmente en curso en background vía agente-gfiber-712-dashboard-tour, todavía no mergeado). Quedan además GFIBER-713 (Admin) y GFIBER-714 (Leagues) para más adelante.

A diferencia del Dashboard (solo admin/owner), /my-metrics — la ruta real detrás del link "My Usage" del NavBar — es accesible a todos los roles autenticados (confirmado: no hay layout.tsx propio, solo el gate de autenticación general; el propio código documenta "Accessible to all authenticated roles", con scoping de datos vía RLS por created_by/ agent_id, no por rol).

El usuario decidió lanzar el agente de GFIBER-711 en paralelo con el de GFIBER-712, aceptando el riesgo de un conflicto de merge en los archivos compartidos de infraestructura del tour (ver sección de riesgo más abajo), en vez de esperar a que Dashboard termine primero.

Estructura real de la pantalla

app/(protected)/my-metrics/page.tsx (Server Component, dynamic = "force-dynamic") renderiza, en este orden:

  1. Header + <DateRangeControl> (línea con basePath="/my-metrics", activeFilter="mine") — mismo componente compartido que usa el Dashboard (components/dashboard/DateRangeControl.tsx).
  2. Grid de 5 <AgentStatCard> (design system): Interactions, Offers Made, Accepted, Rejected, Conversion Rate.
  3. <AdoptionCharts variant="individual"> — también compartido con el Dashboard (components/dashboard/AdoptionCharts.tsx), pero el tour de Dashboard (GFIBER-712) no lo ancla en su alcance aprobado, así que hoy no hay colisión de anclaje ahí.
  4. Sección "Sessions" → <SessionHistoryView showStats={false} detailBasePath="/my-metrics"> (app/(protected)/upsell-evaluator/_history/SessionHistoryView.tsx, ya es 'use client').
  5. Estado vacío (sin interacciones aún) — sin anclajes, no bloqueante, igual que el caso análogo en Dashboard.

Grep exhaustivo confirmó: cero data-tour en esta pantalla o sus componentes hoy.

Coordinación de naming con GFIBER-712 (componente compartido)

DateRangeControl es usado por ambos tours. Para evitar que el mismo data-tour fijo en el componente diga "dashboard-*" cuando también aparece en /my-metrics, ya le pedí al agente de GFIBER-712 (vía tmux, en curso) que renombre su anclaje de dashboard-date-range a date-range-control (genérico, por componente, no por página que lo consume). Este plan asume ese nombre ya renombrado y lo usa igual acá. Si por algún motivo el agente de Dashboard no llegó a aplicarlo antes de que el de My Usage lo necesite, el agente de My Usage debe usar date-range-control de todos modos (es el nombre correcto a largo plazo) y, si encuentra dashboard-date-range en su lugar, renombrarlo él mismo.

Reuso de infraestructura

  • utils/upsell/tour-storage.ts — reusar tal cual, tourId = "my-usage" → key gfiber:tour-seen:my-usage, independiente de los otros dos tours.
  • utils/upsell/tour-bridge.ts — GFIBER-712 lo está refactorizando de singleton a Map<tourId, fn> en paralelo, en su propio worktree, todavía sin mergear. Riesgo de conflicto aceptado por el usuario: el agente de My Usage va a encontrar la versión singleton vieja en dev. Debe hacer el mismo refactor (Map<string, fn> keyado por tourId) de forma independiente, en un commit dedicado y aislado (sin mezclarlo con cambios específicos de My Usage), para que sea lo más fácil posible de reconciliar cuando ambos PRs converjan — el usuario resolverá ese conflicto de merge manualmente más adelante.
  • components/NavBar/TourButton.tsx — mismo caso: GFIBER-712 lo está creando (reemplaza a UpsellTourButton.tsx) con un mapa pathname → tourId. El agente de My Usage debe crear este mismo componente si todavía no existe en su rama (heredada de dev sin ese cambio), agregando la entrada "/my-metrics": "my-usage" al mapa, también en un commit aislado.
  • Patrón de ProductTour.tsx — igual que Dashboard: sin flow (no hay máquina de etapas), TourController interno + TourProvider + SkipButton/nextButton custom + estilos --fiber-*.

Anclajes del tour (4 pasos)

| # | data-tour | Elemento real | Contenido del paso | | 1 | date-range-control | <DateRangeControl> (compartido) | "Filtra tus métricas por rango de fechas." | | 2 | my-usage-stats | Grid de 5 <AgentStatCard> en page.tsx | "Tus estadísticas personales: interacciones, ofertas, aceptadas/rechazadas y tasa de conversión." | | 3 | adoption-charts | <AdoptionCharts variant="individual"> (compartido, sin uso previo por otro tour) | "Tu tendencia de adopción de la herramienta, día a día." | | 4 | session-history | <SessionHistoryView> | "Revisa tu historial de sesiones — click en cualquier fila para ver el detalle completo." |

Cambios a implementar

  • utils/upsell/tour-bridge.ts — refactor a Map<tourId, fn> (si no llegó ya mergeado desde GFIBER-712 al momento de implementar).
  • components/NavBar/TourButton.tsx — crear (si no existe ya) o extender su mapa con "/my-metrics": "my-usage".
  • Nuevo app/(protected)/my-metrics/_flow/ProductTour.tsx (o ubicación equivalente, 'use client'): TOUR_ID = "my-usage", 4 steps de la tabla de arriba.
  • app/(protected)/my-metrics/page.tsx: envolver el return con <ProductTour>{...}</ProductTour>.
  • data-tour en: components/dashboard/DateRangeControl.tsx (ya debería tener date-range-control si GFIBER-712 aplicó el rename; si no, renombrarlo), el grid de AgentStatCard en page.tsx, components/dashboard/AdoptionCharts.tsx, app/(protected)/upsell-evaluator/_history/SessionHistoryView.tsx.

Riesgo aceptado

Conflicto de merge probable en tour-bridge.ts y TourButton.tsx cuando los PRs de GFIBER-712 y GFIBER-711 converjan (ambos tocan los mismos archivos de infraestructura compartida en paralelo). El usuario ya decidió aceptar este costo a cambio de arrancar ambos tours en paralelo. Mitigación: instruir a ambos agentes a mantener esos cambios de infraestructura en commits aislados y descriptivos, para facilitar un rebase/resolución manual posterior.

Verificación end-to-end

  • Con localStorage vacío, login con cualquier rol (no solo admin/owner) → el tour se dispara solo en /my-metrics.
  • Recorrer los 4 pasos, incluido el estado con datos reales (no el estado vacío).
  • Completar/Saltar → localStorage["gfiber:tour-seen:my-usage"] === "true"; reload no lo re-dispara.
  • Botón de reinicio en NavBar (TourButton) → en /my-metrics relanza el tour de My Usage; en /dashboard y /upsell-evaluator sigue relanzando el suyo respectivo, sin pisarse.
  • Probar con un agente sin interacciones aún (estado vacío) → confirmar que no rompe nada.
  • Confirmar que el tour de Upsell Evaluator y el de Dashboard (si ya está mergeado) siguen funcionando sin regresión tras el refactor de tour-bridge.ts/TourButton.tsx.