# 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 + `` (línea con `basePath="/my-metrics"`, `activeFilter="mine"`) — **mismo componente compartido** que usa el Dashboard (`components/dashboard/DateRangeControl.tsx`). 2. Grid de 5 `` (design system): Interactions, Offers Made, Accepted, Rejected, Conversion Rate. 3. `` — 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" → `` (`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` 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` 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` | `` (compartido) | "Filtra tus métricas por rango de fechas." | | 2 | `my-usage-stats` | Grid de 5 `` en `page.tsx` | "Tus estadísticas personales: interacciones, ofertas, aceptadas/rechazadas y tasa de conversión." | | 3 | `adoption-charts` | `` (compartido, sin uso previo por otro tour) | "Tu tendencia de adopción de la herramienta, día a día." | | 4 | `session-history` | `` | "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` (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 `{...}`. - `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`.