86 lines
4.3 KiB
Markdown
86 lines
4.3 KiB
Markdown
# F-128 — CMS plantillas: contenido por defecto editable
|
|
|
|
## Diagnóstico
|
|
|
|
En `/admin/cms`, el operador reporta que al pulsar "Editar" sobre una plantilla (Home, Productos, Categorías, Marcas), el formulario se abre con el campo **body vacío**, sin contenido para modificar.
|
|
|
|
Reproducción:
|
|
1. `GET /api/cms/pages` → 6 páginas (about, contact, cookies, privacy, shipping, terms). **Ninguna** coincide con los slugs del array `TEMPLATES`.
|
|
2. `TEMPLATES` está hardcoded con `home / products / categories / brands`.
|
|
3. `openTemplate(tpl)` (cms/page.tsx:69):
|
|
```ts
|
|
const existing = items.find(p => p.slug === tpl.slug);
|
|
if (existing) { openEdit(existing); return; }
|
|
setEditing(null);
|
|
setForm({ slug: tpl.slug, title: tpl.defaultTitle, body: '' }); // ← body vacío
|
|
```
|
|
4. Cuando NO existe CMS page para ese slug (caso actual para los 4 templates), `form.body` queda `''` y el botón Guardar está disabled (`!form.body`).
|
|
|
|
Resultado: el operador abre una plantilla → no puede editar nada porque no hay contenido previo. Tendría que crear el contenido desde cero (pero el botón Guardar está disabled por el body vacío, así que tampoco puede).
|
|
|
|
## Diseño
|
|
|
|
Añadir `defaultBody` a cada template (HTML por defecto, listo para Lexical) y pre-rellenar `form.body` cuando se abre una plantilla sin página existente.
|
|
|
|
### Cambios
|
|
|
|
`apps/admin/src/app/(dashboard)/cms/page.tsx`:
|
|
|
|
```diff
|
|
const TEMPLATES = [
|
|
- { slug: 'home', label: 'Home', route: '/', icon: '🏠',
|
|
- defaultTitle: 'Bienvenido a Mercado de Vida',
|
|
- hint: 'Sección de bienvenida destacada en la página de inicio.' },
|
|
+ { slug: 'home', label: 'Home', route: '/', icon: '🏠',
|
|
+ defaultTitle: 'Bienvenido a Mercado de Vida',
|
|
+ hint: 'Sección de bienvenida destacada en la página de inicio.',
|
|
+ defaultBody: '<h2>Bienvenido a Mercado de Vida</h2><p>Productos naturales, ecológicos y de comercio justo. Envío a toda la península en 24-48h.</p>' },
|
|
{ slug: 'products', label: 'Productos', route: '/products', icon: '🛒',
|
|
- defaultTitle: 'Nuestros productos',
|
|
- hint: 'Texto introductorio del listado de productos.' },
|
|
+ defaultTitle: 'Nuestros productos',
|
|
+ hint: 'Texto introductorio del listado de productos.',
|
|
+ defaultBody: '<p>Descubre nuestra selección de productos naturales y ecológicos. Filtra por categoría, marca o atributo (vegano, sin gluten, bio...).</p>' },
|
|
{ slug: 'categories', label: 'Categorías', route: '/categories', icon: '🗂️',
|
|
- defaultTitle: 'Nuestras categorías',
|
|
- hint: 'Texto introductorio del listado de categorías.' },
|
|
+ defaultTitle: 'Nuestras categorías',
|
|
+ hint: 'Texto introductorio del listado de categorías.',
|
|
+ defaultBody: '<p>Explora todas nuestras categorías: alimentación, cosmética, limpieza del hogar y más.</p>' },
|
|
{ slug: 'brands', label: 'Marcas', route: '/brands', icon: '🏷️',
|
|
- defaultTitle: 'Nuestras marcas',
|
|
- hint: 'Texto introductorio del listado de marcas.' },
|
|
+ defaultTitle: 'Nuestras marcas',
|
|
+ hint: 'Texto introductorio del listado de marcas.',
|
|
+ defaultBody: '<p>Trabajamos con marcas comprometidas con la producción ecológica y el comercio justo.</p>' },
|
|
];
|
|
```
|
|
|
|
`openTemplate`:
|
|
```diff
|
|
const openTemplate = (tpl: typeof TEMPLATES[number]) => {
|
|
const existing = items.find(p => p.slug === tpl.slug);
|
|
if (existing) { openEdit(existing); return; }
|
|
setEditing(null);
|
|
- setForm({ slug: tpl.slug, title: tpl.defaultTitle, body: '' });
|
|
+ setForm({ slug: tpl.slug, title: tpl.defaultTitle, body: tpl.defaultBody });
|
|
setShowForm(true);
|
|
};
|
|
```
|
|
|
|
### Por qué `defaultBody` y no crear la página automáticamente
|
|
|
|
- El operador todavía debe poder editar el contenido antes de guardar. Si auto-creamos la página con el contenido por defecto, cualquier apertura accidental del template ensucia la DB.
|
|
- Con el body pre-rellenado, el botón Guardar se habilita (porque `form.body` ya no es vacío) y el operador puede ajustar el contenido y guardarlo cuando quiera.
|
|
|
|
### No tocar el backend
|
|
|
|
El backend ya devuelve el `body` correctamente. No requiere cambios ni migración.
|
|
|
|
## Plan
|
|
|
|
1. Editar `apps/admin/src/app/(dashboard)/cms/page.tsx` — añadir `defaultBody` a cada template + actualizar `openTemplate`.
|
|
2. `cd apps/admin && npx tsc --noEmit`.
|
|
3. `cd apps/admin && npm run build`.
|
|
4. Verificar manualmente (build OK suficiente — la lógica es trivial).
|
|
5. Cerrar gates. |