Files
inq-roi-simulador-web/sprints/sprint-4/ETAPA_7B_PROMPT.md
Marcos Benítez c738bc5489
Some checks failed
/ Deploy to Cloudflare Pages (push) Has been cancelled
Sprint 4 — Etapa 7B completada.
2026-06-19 00:20:27 -03:00

6.3 KiB

Sprint 4 — Etapa 7B: Tres fixes post-validación visual

Contexto

InQ ROI — React 18 + Vite + TypeScript + TanStack Router + Zustand + shadcn/ui + Tailwind. Etapa 7 completada con OK formal. Durante la validación visual del director se detectaron tres issues que entran en esta etapa.


Fix 1 — Catálogo con contexto de proceso (Opción A aprobada)

Problema

Cuando el usuario navega desde el ResourcesPanel del workspace al catálogo (/recursos), no hay forma de volver al proceso de origen ni de indicar que un recurso está disponible para usar en ese proceso.

Solución

Paso 1: ResourcesPanel — pasar contexto en la URL

En src/features/workspace/ResourcesPanel.tsx, el link "Ver catálogo completo" debe incluir el processId del proceso actual como query param:

// Antes:
navigate({ to: '/recursos' })

// Después:
navigate({ to: '/recursos', search: { fromProcess: currentProcess.id } })

Paso 2: ResourceCatalogPage — detectar contexto y mostrar UI de retorno

En src/features/resources/ResourceCatalogPage.tsx:

Leer el query param fromProcess (puede ser undefined si el usuario navegó directamente).

Si fromProcess está presente:

  1. Banner contextual en la parte superior de la página (antes de la barra de herramientas), con fondo suave naranja InQ:

    [←] Estás viendo el catálogo desde el proceso "[nombre del proceso]"
        Seleccioná un recurso y usalo en una actividad al volver al workspace.
        [← Volver al proceso]
    
    • El nombre del proceso se resuelve buscando fromProcess en el store o con una query puntual a Supabase
    • El botón "← Volver al proceso" navega de vuelta a /workspace/:processId
  2. Botón "← Usar en proceso" en cada fila de la tabla (columna Acciones, junto a editar/eliminar):

    • Solo visible cuando fromProcess está presente
    • Al hacer click: navega a /workspace/:processId
    • No hace ninguna asignación automática — la asignación sigue siendo en ActivityPanel
    • Tooltip: "Volver al workspace para asignar este recurso a una actividad"

Colores del banner:

  • Fondo: #FEF3E7 (naranja InQ muy suave)
  • Borde izquierdo: #F59845 (naranja InQ)
  • Texto secundario: var(--color-text-secondary)
  • Botón "Volver": estilo secundario (borde, sin relleno)

Si fromProcess no está presente (usuario llegó al catálogo directamente): sin banner, sin botón extra. La página funciona exactamente igual que en Etapa 7.


Fix 2 — Redondeo del costo por hora para valores pequeños

Problema

Un recurso con costo $0.037/h se muestra como $0.04 — pérdida de información para recursos de bajo costo unitario (licencias de software, servicios cloud por hora, etc.).

Solución

Crear o actualizar la función de formateo de costo por hora para que use precisión dinámica. Ubicar en src/lib/format.ts (o donde esté la función formatCurrency / formatCostPerHour):

export function formatCostPerHour(value: number, currency = 'USD'): string {
  if (value === 0) return '$0'
  
  // Determinar decimales según magnitud
  let decimals: number
  if (value >= 100)       decimals = 0   // $150/h → $150
  else if (value >= 10)   decimals = 1   // $12.5/h → $12.5
  else if (value >= 1)    decimals = 2   // $1.23/h → $1.23
  else if (value >= 0.1)  decimals = 3   // $0.123/h → $0.123
  else                    decimals = 4   // $0.0123/h → $0.0123

  return `$${value.toFixed(decimals)}`
}

Aplicar esta función en todos los lugares donde se muestra el costo por hora de un recurso:

  • Tabla del catálogo /recursos
  • ResourcesPanel (lista de recursos usados en el proceso)
  • ActivityPanel (selector de recursos y fila de recurso asignado)
  • Cualquier otro lugar donde aparezca costPerHour

Verificación: ingresar un recurso con costo 0.037 y confirmar que se muestra $0.037 (no $0.04).


Fix 3 — Google OAuth: forzar selector de cuenta

Problema

Al hacer click en "Iniciar sesión con Google", el navegador usa directamente la sesión anterior sin mostrar el selector de cuentas de Google. Impide cambiar de cuenta o seleccionar entre múltiples cuentas del navegador.

Solución

En src/auth/SupabaseAuthService.ts, en el método signInWithGoogle(), agregar prompt: 'select_account' en los queryParams:

async signInWithGoogle(): Promise<void> {
  const { error } = await supabase.auth.signInWithOAuth({
    provider: 'google',
    options: {
      redirectTo: `${window.location.origin}/auth/callback`,
      queryParams: {
        prompt: 'select_account',  // 🆕 fuerza el selector de cuentas de Google
      },
    },
  })
  if (error) throw error
}

prompt: 'select_account' es un parámetro estándar de OAuth 2.0 / OpenID Connect que instruye a Google a siempre mostrar el selector de cuentas, incluso si hay una sesión activa.


Qué NO entra en esta etapa

  • Asignación automática de recursos desde el catálogo (eso sería Opción B — diferida)
  • Cambios en PDF, simulación o workspace salvo los indicados
  • Ningún cambio de schema en Supabase

Orden de ejecución

  1. Fix 3 — SupabaseAuthService.signInWithGoogle() (1 línea, más fácil de verificar primero)
  2. Fix 2 — función formatCostPerHour con precisión dinámica + aplicar en todos los contextos
  3. Fix 1 — query param en ResourcesPanel + banner + botón en ResourceCatalogPage
  4. npm run build — debe pasar sin errores TypeScript
  5. npm run test — debe mantener 521+ tests verdes
  6. Commit: fix(sprint-4/etapa-7b): selector cuenta Google + redondeo costo/hora + contexto catálogo

Criterios de validación

  • Login muestra el selector de cuentas de Google (no auto-login)
  • Recurso con costo 0.037 se muestra como $0.037, no $0.04
  • Recurso con costo 45 se muestra como $45, no $45.00 (sin decimales innecesarios)
  • Navegar desde ResourcesPanel → catálogo muestra el banner con nombre del proceso
  • Botón "← Usar en proceso" aparece en cada fila cuando hay contexto de proceso
  • Click en "← Usar en proceso" navega a /workspace/:processId
  • Navegar a /recursos directamente (sin fromProcess) no muestra banner ni botón extra
  • Build limpio sin errores TypeScript
  • 521+ tests verdes
  • Validación visual del director antes del OK formal