108 lines
3.2 KiB
TypeScript
108 lines
3.2 KiB
TypeScript
import {
|
|
LayoutItem,
|
|
normalizeLayoutPayload,
|
|
parseMetadata,
|
|
resolveIsActive,
|
|
} from '@/lib/layoutConfig';
|
|
import {
|
|
DEFAULT_FAQ_PAGE,
|
|
FaqCategory,
|
|
FaqItem,
|
|
FaqPageData,
|
|
slugifyFaq,
|
|
} from '@/lib/faqDefaults';
|
|
|
|
export const FAQ_REGIONS = ['faq_hero', 'faq_categories'] as const;
|
|
export type FaqRegion = (typeof FAQ_REGIONS)[number];
|
|
|
|
function asFaqItem(raw: unknown): FaqItem | null {
|
|
if (!raw || typeof raw !== 'object') return null;
|
|
const o = raw as Record<string, unknown>;
|
|
const question = String(o.question || o.title || o.q || '').trim();
|
|
const answer = String(o.answer || o.description || o.a || '').trim();
|
|
if (!question) return null;
|
|
return { question, answer };
|
|
}
|
|
|
|
function asFaqCategory(raw: unknown, index: number): FaqCategory | null {
|
|
if (!raw || typeof raw !== 'object') return null;
|
|
const o = raw as Record<string, unknown>;
|
|
const title = String(o.title || o.name || o.label || '').trim();
|
|
const faqs = Array.isArray(o.faqs)
|
|
? o.faqs.map(asFaqItem).filter((x): x is FaqItem => Boolean(x))
|
|
: [];
|
|
if (!title && faqs.length === 0) return null;
|
|
const slug = slugifyFaq(String(o.slug || o.id || title || `category-${index + 1}`));
|
|
return {
|
|
slug: slug || `category-${index + 1}`,
|
|
title: title || 'FAQs',
|
|
description: String(o.description || o.subtitle || '').trim() || undefined,
|
|
faqs,
|
|
};
|
|
}
|
|
|
|
export function normalizeFaqLayout(raw: unknown): LayoutItem[] {
|
|
return normalizeLayoutPayload(raw)
|
|
.map((item) => ({
|
|
...item,
|
|
metadata: parseMetadata(item),
|
|
metadata_json: parseMetadata(item),
|
|
}))
|
|
.sort(
|
|
(a, b) =>
|
|
(Number(a.display_order) || 0) - (Number(b.display_order) || 0)
|
|
);
|
|
}
|
|
|
|
export function findFaqSection(
|
|
layout: LayoutItem[],
|
|
region: FaqRegion
|
|
): LayoutItem | null {
|
|
return (
|
|
layout.find((s) => {
|
|
const key = parseMetadata(s).section_key || s.region || s.type || '';
|
|
return key === region || s.region === region || s.type === region;
|
|
}) || null
|
|
);
|
|
}
|
|
|
|
export function parseFaqPageData(raw: unknown): FaqPageData {
|
|
const layout = normalizeFaqLayout(raw);
|
|
const hero = findFaqSection(layout, 'faq_hero');
|
|
const cats = findFaqSection(layout, 'faq_categories');
|
|
|
|
const heroVisible = !hero || resolveIsActive(hero);
|
|
const catsVisible = !cats || resolveIsActive(cats);
|
|
|
|
const heroMeta = parseMetadata(hero);
|
|
const catsMeta = parseMetadata(cats);
|
|
|
|
const title =
|
|
(heroVisible && (hero?.title || heroMeta.title)) || DEFAULT_FAQ_PAGE.title;
|
|
const subtitle =
|
|
(heroVisible && (hero?.subtitle || heroMeta.subtitle)) ||
|
|
DEFAULT_FAQ_PAGE.subtitle;
|
|
|
|
const fromCms = catsVisible
|
|
? (Array.isArray(catsMeta.categories) ? catsMeta.categories : [])
|
|
.map(asFaqCategory)
|
|
.filter((x): x is FaqCategory => Boolean(x))
|
|
: [];
|
|
|
|
const categories =
|
|
fromCms.length > 0
|
|
? fromCms.map((c) => ({
|
|
...c,
|
|
faqs: c.faqs.length > 0 ? c.faqs : [],
|
|
}))
|
|
: DEFAULT_FAQ_PAGE.categories;
|
|
|
|
return {
|
|
title: String(title).trim() || DEFAULT_FAQ_PAGE.title,
|
|
subtitle: String(subtitle).trim() || DEFAULT_FAQ_PAGE.subtitle,
|
|
categories:
|
|
categories.filter((c) => c.faqs.length > 0 || c.title).length > 0
|
|
? categories
|
|
: DEFAULT_FAQ_PAGE.categories,
|
|
};
|
|
}
|