Saltar a contenido

Vigencia parcial — verificada el 2026-08-19

Plan preexistente migrado al estándar. Verificación puntual contra el código de la rama develop: el paso 1 (variable NEXT_PUBLIC_ALGOLIA_API_KEY en src/lib/search-client.ts) y el paso 3 (home restringida a py/ar/br) siguen pendientes. El resto de los pasos no fue verificado.

Plan de Resolución de Problemas - Navegación y Algolia

Este documento presenta un plan paso a paso para resolver los problemas identificados en la integración con Algolia y el sistema de navegación.


Resumen de Problemas por Prioridad

# Prioridad Problema Impacto
1 CRÍTICO Variable de entorno incorrecta en search-client.ts App crash en búsqueda
2 CRÍTICO SearchBar no incluye countryCode Pérdida de contexto regional
3 MEDIA Homepage restringida a py/ar/br 404 para otras regiones
4 MEDIA InstantSearch routing deshabilitado URL no sincroniza con filtros
5 BAJA Clientes Algolia duplicados Mantenibilidad
6 BAJA Índice Algolia hardcodeado Mantenibilidad

Paso 1: Corregir Variable de Entorno (CRÍTICO)

Archivo a Modificar

src/lib/search-client.ts

Problema Actual

const searchClient = liteClient(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
  process.env.NEXT_PUBLIC_ALGOLIA_API_KEY!  // ❌ No existe
)

Solución

const searchClient = liteClient(
  process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!,
  process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!  // ✅ Variable correcta
)

Verificación

  • Buscar otros usos de NEXT_PUBLIC_ALGOLIA_API_KEY en el proyecto
  • Confirmar que .env.local tiene NEXT_PUBLIC_ALGOLIA_SEARCH_KEY

Paso 2: Agregar Country Code al SearchBar (CRÍTICO)

Archivo a Modificar

src/modules/search/component/SearchBar.tsx

Cambios Requeridos

2.1 Importar hook useParams

import { useParams, useRouter } from "next/navigation"

2.2 Obtener countryCode en el componente

export default function SearchBar({ className }: SearchBarProps) {
  const { countryCode } = useParams<{ countryCode: string }>()
  const router = useRouter()
  // ...
}

2.3 Actualizar todas las navegaciones

onSubmit (búsqueda con Enter):

// Antes
router.push(`/store?q=${state.query}`)

// Después
router.push(`/${countryCode}/store?q=${encodeURIComponent(state.query)}`)

onSelect en querySuggestionsSource:

// Antes
router.push(`/store?q=${item.query}`)

// Después
router.push(`/${countryCode}/store?q=${encodeURIComponent(item.query)}`)

onSelect en categorySuggestionsSource:

// Antes
router.push(`/store?category=${item.value}`)

// Después
router.push(`/${countryCode}/store?category=${encodeURIComponent(item.value)}`)

onSelect en products:

// Antes
router.push(`/products${item.url}`) o router.push(`/products/${sku}`)

// Después
router.push(`/${countryCode}/products${item.url}`)
// o
router.push(`/${countryCode}/products/${sku}`)

Botón Clear/Limpiar:

// Antes
router.push(`/store`)

// Después
router.push(`/${countryCode}/store`)

Verificación

  • Probar búsqueda desde diferentes regiones (/py/, /ar/, /br/)
  • Verificar que la URL mantiene el countryCode después de buscar
  • Probar click en sugerencias, categorías y productos

Paso 3: Resolver Restricción de Homepage (MEDIA)

Archivo a Modificar

src/app/[countryCode]/(main)/page.tsx

Opciones de Solución

Opción A: Permitir todos los países de Medusa (Recomendada)

import { listRegions } from "@lib/data/regions"

export default async function Home({ params }: Props) {
  const { countryCode } = await params

  // Validar contra regiones de Medusa
  const regions = await listRegions()
  const validCodes = regions.flatMap(r =>
    r.countries?.map(c => c.iso_2.toLowerCase()) || []
  )

  if (!validCodes.includes(countryCode.toLowerCase())) {
    notFound()
  }

  // ... resto del componente
}

Opción B: Redirigir a región default

import { redirect } from "next/navigation"

const ALLOWED = ["py", "ar", "br"] as const
const DEFAULT_REGION = "py"

export default async function Home({ params }: Props) {
  const { countryCode } = await params

  if (!ALLOWED.includes(countryCode as any)) {
    redirect(`/${DEFAULT_REGION}`)
  }

  // ... resto del componente
}

Opción C: Mostrar página de región no disponible

export default async function Home({ params }: Props) {
  const { countryCode } = await params

  if (!ALLOWED.includes(countryCode as any)) {
    return <RegionNotAvailable countryCode={countryCode} />
  }

  // ... resto del componente
}

Decisión Requerida

Confirmar cuál de las tres opciones implementar según la estrategia de negocio.


Paso 4: Habilitar InstantSearch Routing (MEDIA)

Archivo a Modificar

src/modules/store/templates/instantsearch-store-template.tsx

Cambio Requerido

import { history } from "instantsearch.js/es/lib/routers"

export default function InstantSearchStoreTemplate({
  initialFilters,
  countryCode
}: Props) {
  return (
    <InstantSearchNext
      searchClient={searchClient}
      indexName={ALGOLIA_INDEX}
      routing={{
        router: history({
          cleanUrlOnDispose: false,
          getLocation: () =>
            typeof window === "undefined"
              ? new URL(`https://localhost/${countryCode}/store`) as unknown as Location
              : window.location,
        }),
        stateMapping: {
          stateToRoute(uiState) {
            const indexUiState = uiState[ALGOLIA_INDEX] || {}
            return {
              q: indexUiState.query,
              category: indexUiState.refinementList?.category?.join(","),
              brand: indexUiState.refinementList?.brand?.join(","),
              product_tag: indexUiState.refinementList?.product_tags?.join(","),
              price_min: indexUiState.range?.price?.min,
              price_max: indexUiState.range?.price?.max,
            }
          },
          routeToState(routeState) {
            return {
              [ALGOLIA_INDEX]: {
                query: routeState.q,
                refinementList: {
                  category: routeState.category?.split(","),
                  brand: routeState.brand?.split(","),
                  product_tags: routeState.product_tag?.split(","),
                },
                range: {
                  price: {
                    min: routeState.price_min,
                    max: routeState.price_max,
                  },
                },
              },
            }
          },
        },
      }}
    >
      <Configure filters="total_stock > 0" />
      <InstantSearchContent />
    </InstantSearchNext>
  )
}

Archivos Adicionales a Modificar

  • src/modules/store/components/instantsearch-content/index.tsx
  • Remover o simplificar componente ApplyFiltersFromURL
  • El routing nativo de InstantSearch manejará la sincronización

Verificación

  • Verificar que cambiar filtros actualiza la URL
  • Verificar que compartir URL con filtros funciona
  • Verificar que el botón "atrás" del navegador funciona correctamente

Paso 5: Consolidar Clientes Algolia (BAJA)

Archivos a Crear/Modificar

5.1 Crear estructura unificada

src/lib/algolia/
├── index.ts        # Re-exports
├── client.ts       # Cliente client-side (lite)
├── server.ts       # Cliente server-side (full)
└── constants.ts    # Constantes compartidas

5.2 constants.ts

export const ALGOLIA_APP_ID = process.env.NEXT_PUBLIC_ALGOLIA_APP_ID!
export const ALGOLIA_SEARCH_KEY = process.env.NEXT_PUBLIC_ALGOLIA_SEARCH_KEY!
export const ALGOLIA_ADMIN_KEY = process.env.ALGOLIA_ADMIN_API_KEY!

export const ALGOLIA_PRODUCT_INDEX = process.env.NEXT_PUBLIC_ALGOLIA_PRODUCT_INDEX!
export const ALGOLIA_SUGGESTIONS_INDEX = process.env.NEXT_PUBLIC_ALGOLIA_SUGGESTIONS_INDEX!

5.3 client.ts

"use client"

import { liteClient as algoliasearch } from "algoliasearch/lite"
import { ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY } from "./constants"

export const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY)

5.4 server.ts

import "server-only"

import algoliasearch from "algoliasearch"
import { ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY } from "./constants"

export const searchClient = algoliasearch(ALGOLIA_APP_ID, ALGOLIA_SEARCH_KEY)

5.5 index.ts

export * from "./constants"

Archivos a Actualizar

  • src/lib/algolia.ts → Eliminar, usar src/lib/algolia/server.ts
  • src/lib/search-client.ts → Eliminar, usar src/lib/algolia/client.ts
  • src/modules/store/templates/instantsearch-store-template.tsx → Importar de @lib/algolia/client
  • src/modules/search/component/SearchBar.tsx → Importar de @lib/algolia
  • src/lib/algolia-products.ts → Importar de @lib/algolia/server

Paso 6: Usar Constantes para Índices (BAJA)

Archivos a Modificar

Buscar y reemplazar todas las instancias hardcodeadas:

// Antes
indexName="product_items_view_index_dev"

// Después
import { ALGOLIA_PRODUCT_INDEX } from "@lib/algolia"
indexName={ALGOLIA_PRODUCT_INDEX}

Archivos Afectados

  • src/modules/store/templates/instantsearch-store-template.tsx
  • src/lib/parse-search-params.ts
  • src/lib/algolia-products.ts (múltiples lugares)

Orden de Implementación Sugerido

Fase 1: Correcciones Críticas (Inmediato)
├── Paso 1: Variable de entorno (5 min)
└── Paso 2: Country code en SearchBar (30 min)

Fase 2: Mejoras Funcionales (Corto plazo)
├── Paso 3: Homepage restriction (15 min)
└── Paso 4: InstantSearch routing (1-2 horas)

Fase 3: Refactoring (Cuando haya tiempo)
├── Paso 5: Consolidar clientes (1 hora)
└── Paso 6: Constantes para índices (30 min)

Checklist de Verificación Final

Después de Fase 1

  • [ ] Búsqueda funciona sin errores de consola
  • [ ] SearchBar navega correctamente con countryCode
  • [ ] Usuarios mantienen su región al buscar
  • [ ] Click en productos lleva a URL correcta

Después de Fase 2

  • [ ] Homepage funciona para todas las regiones configuradas
  • [ ] Filtros de InstantSearch se reflejan en URL
  • [ ] URL compartidas con filtros funcionan
  • [ ] Botón atrás del navegador funciona correctamente

Después de Fase 3

  • [ ] No hay imports de archivos eliminados
  • [ ] Build pasa sin errores
  • [ ] Tests de búsqueda pasan
  • [ ] No hay warnings de variables de entorno

Notas Adicionales

Dependencias entre pasos

  • Paso 5 debe completarse antes de Paso 6
  • Pasos 1-4 son independientes entre sí

Riesgos

  • Paso 4: Cambiar el routing de InstantSearch puede requerir ajustes adicionales en componentes que dependen del estado actual
  • Paso 5: Refactoring de imports puede causar errores temporales si no se actualiza todo

Testing Recomendado

  • Probar flujo de búsqueda completo en cada región
  • Probar navegación desde diferentes puntos de entrada
  • Verificar que SEO/URLs canónicas siguen correctas