143 lines
5.4 KiB
TypeScript
143 lines
5.4 KiB
TypeScript
import { config, collection, fields } from '@keystatic/core';
|
|
|
|
export default config({
|
|
storage: {
|
|
kind: 'local',
|
|
},
|
|
ui: {
|
|
brand: {
|
|
name: 'Admin Renacer',
|
|
},
|
|
},
|
|
collections: {
|
|
programas: collection({
|
|
label: 'Programas',
|
|
slugField: 'nombre',
|
|
path: 'src/content/programas/*',
|
|
format: { data: 'yaml' },
|
|
schema: {
|
|
nombre: fields.slug({
|
|
name: { label: 'Nombre del programa' },
|
|
slug: { label: 'Slug (URL)' },
|
|
}),
|
|
|
|
// ── Tarjeta en el landing ─────────────────────────────────────
|
|
estado: fields.select({
|
|
label: 'Estado',
|
|
options: [
|
|
{ label: 'Activo', value: 'Activo' },
|
|
{ label: 'Vacaciones', value: 'Vacaciones' },
|
|
{ label: 'Anual', value: 'Anual' },
|
|
{ label: 'Temporada', value: 'Temporada' },
|
|
{ label: 'En planificación', value: 'En planificación' },
|
|
],
|
|
defaultValue: 'Activo',
|
|
}),
|
|
bajada: fields.text({
|
|
label: 'Resumen corto (opcional)',
|
|
description: 'Campo editorial secundario. Ya no se muestra en la tarjeta pública.',
|
|
}),
|
|
detalle: fields.text({
|
|
label: 'Descripción breve',
|
|
description: 'Texto que sí aparece en la tarjeta del landing, bajo el título.',
|
|
multiline: true,
|
|
validation: { isRequired: true },
|
|
}),
|
|
icono: fields.select({
|
|
label: 'Icono de la tarjeta',
|
|
description: 'Se muestra dentro del círculo de la tarjeta del programa.',
|
|
options: [
|
|
{ label: 'Manos y apoyo', value: 'HeartHandshake' },
|
|
{ label: 'Alimentación', value: 'UtensilsCrossed' },
|
|
{ label: 'Canasta / apoyo', value: 'Package' },
|
|
{ label: 'Vestimenta', value: 'Shirt' },
|
|
{ label: 'Naturaleza', value: 'Sprout' },
|
|
{ label: 'Regalo / campaña', value: 'Gift' },
|
|
{ label: 'Juego e infancia', value: 'Puzzle' },
|
|
{ label: 'Comunidad', value: 'Users' },
|
|
{ label: 'Inclusión', value: 'HandHelping' },
|
|
],
|
|
defaultValue: 'HeartHandshake',
|
|
}),
|
|
orden: fields.integer({
|
|
label: 'Orden en landing',
|
|
description: 'Número de posición (menor = primero). Ej: 1, 2, 3…',
|
|
defaultValue: 99,
|
|
validation: { isRequired: true },
|
|
}),
|
|
|
|
// ── Configuración de página ───────────────────────────────────
|
|
tienePagina: fields.checkbox({
|
|
label: '¿Tiene página propia?',
|
|
description: 'Desmarcar para programas en planificación sin página',
|
|
defaultValue: true,
|
|
}),
|
|
externalHref: fields.text({
|
|
label: 'URL externa o personalizada (opcional)',
|
|
description: 'Déjalo vacío para usar automáticamente /programas/slug/.',
|
|
}),
|
|
|
|
// ── Contenido de la página ────────────────────────────────────
|
|
kicker: fields.text({
|
|
label: 'Kicker (nombre corto para la página)',
|
|
description: 'Aparece sobre el título principal',
|
|
}),
|
|
titulo: fields.text({
|
|
label: 'Título de la página',
|
|
description: 'Título largo y descriptivo',
|
|
}),
|
|
lead: fields.text({
|
|
label: 'Párrafo introductorio (lead)',
|
|
description: 'Párrafo destacado que aparece bajo el título',
|
|
multiline: true,
|
|
}),
|
|
parrafos: fields.array(
|
|
fields.text({ label: 'Párrafo', multiline: true }),
|
|
{
|
|
label: 'Párrafos del cuerpo',
|
|
description: 'Agrega los párrafos del contenido principal',
|
|
itemLabel: (props) => {
|
|
const val = props.value ?? '';
|
|
return val.length > 60 ? val.slice(0, 60) + '…' : val || 'Párrafo vacío';
|
|
},
|
|
}
|
|
),
|
|
stats: fields.array(
|
|
fields.object({
|
|
valor: fields.text({ label: 'Valor o cifra' }),
|
|
etiqueta: fields.text({ label: 'Descripción' }),
|
|
}),
|
|
{
|
|
label: 'Estadísticas (idealmente 4)',
|
|
description: 'Datos clave del programa en formato cifra + descripción',
|
|
itemLabel: (props) => props.fields.valor.value || 'Estadística',
|
|
}
|
|
),
|
|
textoApoyo: fields.text({
|
|
label: 'Texto de apoyo / cómo colaborar',
|
|
description: 'Texto que aparece en la sección final de la página',
|
|
multiline: true,
|
|
}),
|
|
imagen: fields.image({
|
|
label: 'Imagen principal (opcional)',
|
|
description: 'Portada del hero para la página del programa',
|
|
directory: 'public/uploads/programas',
|
|
publicPath: '/uploads/programas/',
|
|
}),
|
|
galeria: fields.array(
|
|
fields.image({
|
|
label: 'Imagen de galería',
|
|
directory: 'public/uploads/programas',
|
|
publicPath: '/uploads/programas/',
|
|
}),
|
|
{
|
|
label: 'Galería (opcional)',
|
|
description: 'Imágenes secundarias para mostrar debajo del contenido',
|
|
itemLabel: (props) => props.value?.split('/').pop() ?? 'Imagen',
|
|
}
|
|
),
|
|
},
|
|
}),
|
|
},
|
|
});
|