This commit is contained in:
Your Name committed 2026-07-24 20:08:21 -04:00
1 parent ac08f4490b
commit f8da2cceaf
8 files changed
+427 -2

No files matched your search

+58 -1
View File
@@ -518,6 +518,59 @@ export const ArticleReferencesSectionPayloadSchema = z.object({
}).strict();
export type ArticleReferencesSectionPayload = z.infer<typeof ArticleReferencesSectionPayloadSchema>;
export const ArticleTableSectionPayloadSchema = z.object({
title: LocalizedStringSchema.optional(),
columns: z.array(LocalizedStringSchema).min(2).max(6),
rows: z.array(z.object({
label: LocalizedStringSchema,
cells: z.array(LocalizedStringSchema).min(2).max(6),
}).strict()).min(1).max(20),
note: LocalizedStringSchema.optional(),
}).strict().superRefine((payload, ctx) => {
payload.rows.forEach((row, index) => {
if (row.cells.length !== payload.columns.length) {
ctx.addIssue({
code: 'custom',
path: ['rows', index, 'cells'],
message: `Row must contain exactly ${payload.columns.length} cells`,
});
}
});
});
export type ArticleTableSectionPayload = z.infer<typeof ArticleTableSectionPayloadSchema>;
export const ArticleDownloadSectionPayloadSchema = z.object({
title: LocalizedStringSchema.optional(),
description: LocalizedStringSchema.optional(),
files: z.array(z.object({
title: LocalizedStringSchema,
url: z.string().url().startsWith('https://'),
fileType: z.string().optional(),
fileSize: z.string().optional(),
}).strict()).min(1).max(10),
}).strict();
export type ArticleDownloadSectionPayload = z.infer<typeof ArticleDownloadSectionPayloadSchema>;
const ArticleLinkSchema = z.string().refine(
(value) => value.startsWith('/') || value.startsWith('https://'),
'Link must be a website-relative path or an HTTPS URL',
);
export const ArticleCtaSectionPayloadSchema = z.object({
title: LocalizedStringSchema,
description: LocalizedStringSchema.optional(),
primaryText: LocalizedStringSchema,
primaryLink: ArticleLinkSchema,
secondaryText: LocalizedStringSchema.optional(),
secondaryLink: ArticleLinkSchema.optional(),
alignment: z.enum(['left', 'center']).optional().default('center'),
}).strict().superRefine((payload, ctx) => {
if (payload.secondaryText && !payload.secondaryLink) {
ctx.addIssue({ code: 'custom', path: ['secondaryLink'], message: 'secondaryLink is required when secondaryText is provided' });
}
});
export type ArticleCtaSectionPayload = z.infer<typeof ArticleCtaSectionPayloadSchema>;
export const ScentNotesBreakdownSectionPayloadSchema = z.object({
title: LocalizedStringSchema.optional(),
description: LocalizedStringSchema.optional(),
@@ -697,7 +750,8 @@ export const PAGE_SECTION_TYPES = [
'HERO', 'ANNOUNCEMENT_BAR', 'NEWSLETTER', 'EDITORIAL_TILE',
'EDITORIAL_CAROUSEL', 'PRODUCTS', 'CATEGORIES', 'TEXT', 'BANNER',
'HERO_ARTICLE', 'RICH_TEXT', 'ARTICLE_HEADER', 'ARTICLE_MEDIA', 'ARTICLE_GALLERY',
'ARTICLE_FACTS', 'ARTICLE_VIDEO', 'ARTICLE_REFERENCES', 'SCENT_NOTES_BREAKDOWN', 'QUOTE_CALLOUT',
'ARTICLE_FACTS', 'ARTICLE_VIDEO', 'ARTICLE_REFERENCES', 'ARTICLE_TABLE', 'ARTICLE_DOWNLOAD',
'ARTICLE_CTA', 'SCENT_NOTES_BREAKDOWN', 'QUOTE_CALLOUT',
'PRODUCT_CAROUSEL', 'ACCORDION', 'CONTACT_INFO', 'CONTACT_FORM',
'HERO_V2', 'USP_BAR', 'PRODUCT_MAIN', 'PRODUCT_DETAILS', 'PRODUCT_SPECS',
'PRODUCT_REVIEWS', 'RELATED_PRODUCTS', 'CUSTOM'
@@ -722,6 +776,9 @@ export const PAGE_SECTION_PAYLOAD_SCHEMAS: Record<SectionType, z.ZodType> = {
ARTICLE_FACTS: ArticleFactsSectionPayloadSchema,
ARTICLE_VIDEO: ArticleVideoSectionPayloadSchema,
ARTICLE_REFERENCES: ArticleReferencesSectionPayloadSchema,
ARTICLE_TABLE: ArticleTableSectionPayloadSchema,
ARTICLE_DOWNLOAD: ArticleDownloadSectionPayloadSchema,
ARTICLE_CTA: ArticleCtaSectionPayloadSchema,
SCENT_NOTES_BREAKDOWN: ScentNotesBreakdownSectionPayloadSchema,
QUOTE_CALLOUT: QuoteCalloutSectionPayloadSchema,
PRODUCT_CAROUSEL: ProductCarouselSectionPayloadSchema,