export type HomeTeamBuilding = { id: string; tag: string; title: string; description: string; image: string; demandKeyword: string; detailSubtitle: string; detailParagraphs: string[]; }; export type HomeTeamBuildingApiItem = { id?: string | null; tag?: string | null; title?: string | null; description?: string | null; image?: string | null; demandKeyword?: string | null; detailSubtitle?: string | null; detailParagraphs?: string[] | null; isActive?: boolean | null; sortOrder?: number | null; }; export type HomeTeamBuildings = HomeTeamBuildingApiItem[]; export const homeTeamBuildingMocks: HomeTeamBuilding[] = [ { id: "wild-challenge", tag: "户外挑战", title: "山野挑战,共创极境", description: "洞穴、瀑降与协作,适合 10-30 人。", image: "https://dimg04.c-ctrip.com/images/1mh0412000njfr1ot9453_W_640_10000.jpg?proc=autoorient", demandKeyword: "户外团建", detailSubtitle: "越过山丘,向来处去", detailParagraphs: [ "真正的贵州,从未被写进流水线的攻略里。洞穴、瀑降、峡谷和村寨,都是团队一起重新认识彼此的方式。", "当所有人都在熟悉的点里寻找同一个机位,我们换一条路,去看真正的贵州。", "我们是一群生于斯、长于斯的地坪探索者,也是对体验和美学有高偏好的本地旅行人。", "十年的时间,我们用影像和脚步寻找贵州的小众特色目的地,把贵州在社交媒体分享给全世界。", "我们深知这片土地的魅力,绝不仅是走马观花的打卡。它藏在高山峡谷的边缘感中,也藏在溶洞和地心暗河的回音里。", "去喀斯特洞河里释放野性,去无名山野间寻找宁静,把未知的风险与沿途的惊艳交给最强悍的团队兜底。", "越过山丘,向来处去,有深度,有记录,有趣。如果想解锁贵州这段独特的旅行,欢迎与野呀团队一起,解锁贵州。", ], }, { id: "canyon-teamwork", tag: "团队协作", title: "峡谷溯溪,默契同行", description: "溯溪与分组协作,兼顾参与感与安全。", image: "https://dimg04.c-ctrip.com/images/0EQ5712000ca7t504EC0E_W_640_10000.jpg?proc=autoorient", demandKeyword: "峡谷团建", detailSubtitle: "在峡谷里重新认识彼此", detailParagraphs: [ "把会议室换成溪流和峡谷,让团队在共同完成一段路的过程中自然建立默契。", "从分组协作到沿途探索,每个人都能找到自己的节奏,也能看见同伴身上不一样的力量。", "这是一场有挑战、有风景,也留得下故事的团队共创。", ], }, { id: "village-gathering", tag: "人文聚会", title: "苗寨共聚,认识彼此", description: "夜游、长桌宴与文化体验,适合团建收尾。", image: "https://p6.itc.cn/q_70/images03/20200918/df728d2b79d943da869333e2ea2c92c8.jpeg", demandKeyword: "贵州团建", detailSubtitle: "在山野与人文之间共创一席", detailParagraphs: [ "走进村寨,和当地的人打个照面,再围坐在长桌旁分享一天的见闻。团队关系,往往在这些没有安排的时刻里变得更近。", "夜游、长桌宴与文化体验,为一次团建留下温度,也为下一次共同出发埋下期待。", ], }, ]; export const homeTeamBuildingFallback = homeTeamBuildingMocks; export function normalizeHomeTeamBuildings( items: HomeTeamBuildings | null | undefined, ): HomeTeamBuilding[] { const fallback = homeTeamBuildingFallback.map((item) => ({ ...item })); const activeItems = (items ?? []) .map((item, index) => ({ item, index })) .filter(({ item }) => item.isActive !== false && Boolean(normalizeText(item.title))) .sort( (left, right) => (left.item.sortOrder ?? left.index) - (right.item.sortOrder ?? right.index), ); if (!activeItems.length) return fallback; return activeItems.map(({ item }, index) => { const fallbackItem = homeTeamBuildingFallback.find((candidate) => candidate.id === item.id) ?? homeTeamBuildingFallback[index] ?? homeTeamBuildingFallback[0]; const title = normalizeText(item.title) || fallbackItem.title; return { id: normalizeText(item.id) || fallbackItem.id, tag: normalizeText(item.tag) || fallbackItem.tag, title, description: normalizeText(item.description) || fallbackItem.description, image: normalizeText(item.image) || fallbackItem.image, demandKeyword: normalizeText(item.demandKeyword) || title, detailSubtitle: normalizeText(item.detailSubtitle) || fallbackItem.detailSubtitle || fallbackItem.description, detailParagraphs: normalizeDetailParagraphs(item.detailParagraphs, fallbackItem.detailParagraphs, fallbackItem.description), }; }); } function normalizeDetailParagraphs( paragraphs: string[] | null | undefined, fallbackParagraphs: string[], description: string, ) { const normalized = (paragraphs ?? []).map((paragraph) => normalizeText(paragraph)).filter(Boolean); return normalized.length ? normalized : fallbackParagraphs.length ? [...fallbackParagraphs] : [description]; } function normalizeText(value: unknown) { return typeof value === "string" ? value.trim() : ""; } export function normalizeHomeTeamBuildingDetail( item: HomeTeamBuildingApiItem | null | undefined, ): HomeTeamBuilding { const fallback = homeTeamBuildingFallback.find((candidate) => candidate.id === item?.id) ?? homeTeamBuildingFallback[0]; const normalized = normalizeHomeTeamBuildings(item ? [item] : [fallback])[0]; return normalized; }