Saltar a contenido

Cómo agregar un nuevo layout al public-menu

Esta guía describe el flujo vigente para añadir un nuevo layout_style a la carta pública de Gastro.

Hoy los layouts activos son:

  • classic_list
  • premium_grid_modal
  • accordion

Resumen del flujo

Agregar un layout nuevo implica tocar cuatro capas:

  1. contrato backend (ThemeLayoutStyle)
  2. contrato TypeScript generado/consumido
  3. renderizado en public-menu
  4. selector visual en admin-panel

1. Extender el contrato en el backend

La fuente de verdad del layout vive en:

Debes ampliar el literal ThemeLayoutStyle con el nuevo valor.

Ejemplo conceptual:

ThemeLayoutStyle = Literal[
    "classic_list",
    "premium_grid_modal",
    "accordion",
    "minimal_text",
]

Verifica también:

  • ejemplos OpenAPI del theme_config
  • validaciones de ThemeConfig

Si el cambio altera contratos públicos, regenera o actualiza:

  • openapi.json
  • tipos generados que consumen los frontends

2. Confirmar el consumo en el admin-panel

El admin-panel usa el contrato generado y además valida localmente el formulario de apariencia.

Puntos reales a tocar:

Hoy AppearancePage.tsx valida:

z.enum(['classic_list', 'premium_grid_modal', 'accordion'])

Debes añadir el nuevo valor también ahí.


3. Crear el componente del nuevo layout en public-menu

Ubicación real:

  • apps/gastro/frontend/public-menu/src/widgets/menu-layouts/

Ejemplo:

src/widgets/menu-layouts/MinimalTextMenu/
└── MinimalTextMenu.tsx

El componente debe recibir la misma estructura de categorías/productos que ya consumen los layouts actuales.

Recomendaciones:

  • no introducir fetch nuevo
  • no redefinir contratos de API manualmente
  • reutilizar atoms/entities existentes cuando tenga sentido

4. Orquestar el layout en la página dinámica del tenant

La selección real del layout ocurre en:

Hoy el branching real es:

  • accordionAccordionMenu
  • premium_grid_modalModalGalleryMenu
  • fallback → InteractiveMenu

Debes:

  1. importar el nuevo layout
  2. añadir la nueva rama de render

Ejemplo conceptual:

{theme.layout_style === 'minimal_text' ? (
  <MinimalTextMenu categories={tenant.categories} />
) : theme.layout_style === 'accordion' ? (
  <AccordionMenu categories={tenant.categories} enableSmartShortlist={...} />
) : theme.layout_style === 'premium_grid_modal' ? (
  <ModalGalleryMenu categories={tenant.categories} enableSmartShortlist={...} />
) : (
  <InteractiveMenu categories={tenant.categories} enableSmartShortlist={...} />
)}

5. Exponer el layout en el selector del admin-panel

La ubicación real del selector visual es:

Y su consumo vive en:

Debes:

  1. añadir la nueva opción visual en LayoutPicker
  2. garantizar que onChange envíe el nuevo valor exacto
  3. verificar que el formulario lo serializa dentro de theme_config.layout_style

6. Verificar persistencia del tenant

El layout se guarda como parte de theme_config del tenant.

Consulta útil:

curl "$BASE/tenants/me" \
  -H "Authorization: Bearer $TOKEN"

Debes ver algo como:

{
  "theme_config": {
    "layout_style": "minimal_text"
  }
}

7. Checklist de validación

Backend

  • ThemeLayoutStyle acepta el nuevo valor
  • OpenAPI refleja el cambio
  • no se rompe PATCH /tenants/me

Admin Panel

  • el layout aparece en el selector
  • se puede guardar desde apariencia
  • el valor persiste tras recargar

Public Menu

  • /{slug} renderiza el nuevo layout
  • no se rompe el fallback de layouts viejos
  • mobile y desktop siguen cargando correctamente

8. Riesgos comunes

  • Cambiar el frontend sin cambiar el contrato backend: el valor no persiste o falla validación.
  • Cambiar solo el backend y no AppearancePage: el formulario bloquea el nuevo layout.
  • Cambiar solo el selector y no page.tsx: el tenant guarda el valor, pero la carta cae al fallback.
  • Duplicar tipos manuales en vez de usar el contrato generado: aparece drift entre apps.

9. Fuentes canónicas relacionadas