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:
- Header +
<DateRangeControl>(línea conbasePath="/my-metrics",activeFilter="mine") — mismo componente compartido que usa el Dashboard (components/dashboard/DateRangeControl.tsx). - Grid de 5
<AgentStatCard>(design system): Interactions, Offers Made, Accepted, Rejected, Conversion Rate. <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í.- Sección "Sessions" →
<SessionHistoryView showStats={false} detailBasePath="/my-metrics">(app/(protected)/upsell-evaluator/_history/SessionHistoryView.tsx, ya es'use client'). - 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"→ keygfiber:tour-seen:my-usage, independiente de los otros dos tours.utils/upsell/tour-bridge.ts— GFIBER-712 lo está refactorizando de singleton aMap<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 endev. Debe hacer el mismo refactor (Map<string, fn>keyado portourId) 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 aUpsellTourButton.tsx) con un mapapathname → tourId. El agente de My Usage debe crear este mismo componente si todavía no existe en su rama (heredada dedevsin 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: sinflow(no hay máquina de etapas),TourControllerinterno +TourProvider+SkipButton/nextButtoncustom + 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 aMap<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 elreturncon<ProductTour>{...}</ProductTour>.data-touren:components/dashboard/DateRangeControl.tsx(ya debería tenerdate-range-controlsi GFIBER-712 aplicó el rename; si no, renombrarlo), el grid deAgentStatCardenpage.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
localStoragevací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-metricsrelanza el tour de My Usage; en/dashboardy/upsell-evaluatorsigue 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.