const PartnershipsPage = require("../models/partnerships"); const AUDIT_ACTIONS = require("../constants/auditAction"); const partnershipsConfig = require("../utils/contentEditors/partnershipsConfig"); const createPageContentController = require("./_createPageContentController"); const { ensureUniqueIds } = require("../utils/contentEditorIds"); function getTabConfig(tabKey) { return (partnershipsConfig.tabs || []).find((tab) => tab.key === tabKey) || {}; } function getObjectField(tabKey, fieldKey) { const fields = getTabConfig(tabKey)?.schema?.fields || []; return fields.find((field) => field.key === fieldKey) || {}; } function getArrayItemField(tabKey, arrayKey, fieldKey) { const arrayField = getObjectField(tabKey, arrayKey); const itemFields = arrayField?.itemSchema?.fields || []; return itemFields.find((field) => field.key === fieldKey) || {}; } function getPartnershipsEditorUi() { return { hero: { badge: getObjectField("hero", "badge"), title: getObjectField("hero", "title"), description: getObjectField("hero", "description"), linkLabel: getObjectField("hero", "linkLabel"), image: getObjectField("hero", "image"), imageAlt: getObjectField("hero", "imageAlt"), }, directory: { heading: getObjectField("directory", "heading"), description: getObjectField("directory", "description"), tabs: getObjectField("directory", "tabs"), partnerFields: { name: getArrayItemField("directory", "partners", "name"), category: getArrayItemField("directory", "partners", "category"), summary: getArrayItemField("directory", "partners", "summary"), logo: getArrayItemField("directory", "partners", "logo"), logoAlt: getArrayItemField("directory", "partners", "logoAlt"), about: getArrayItemField("directory", "partners", "about"), collabType: getArrayItemField("directory", "partners", "collabType"), benefits: getArrayItemField("directory", "partners", "benefits"), }, tabsFrontendHint: partnershipsConfig.editorUi?.directory?.tabsFrontendHint || "", partnersHelpText: partnershipsConfig.editorUi?.directory?.partnersHelpText || "", }, cta: { heading: getObjectField("cta", "heading"), description: getObjectField("cta", "description"), buttonLabel: getObjectField("cta", "buttonLabel"), }, inquiryForm: { title: getObjectField("inquiryForm", "title"), fields: getObjectField("inquiryForm", "fields"), fieldFields: { label: getArrayItemField("inquiryForm", "fields", "label"), placeholder: getArrayItemField("inquiryForm", "fields", "placeholder"), type: getArrayItemField("inquiryForm", "fields", "type"), width: getArrayItemField("inquiryForm", "fields", "width"), options: getArrayItemField("inquiryForm", "fields", "options"), required: getArrayItemField("inquiryForm", "fields", "required"), }, fieldsHelpText: partnershipsConfig.editorUi?.inquiryForm?.fieldsHelpText || "", }, }; } function toInquiryField(id, field, type, width) { return { id, label: field?.label || "", placeholder: field?.placeholder || "", type, width, required: true, options: Array.isArray(field?.options) ? field.options : [], }; } function normalizeInquiryForm(data) { if (!data?.inquiryForm) { return data; } if (Array.isArray(data.inquiryForm.fields)) { return data; } const legacyFields = data.inquiryForm.fields || {}; return { ...data, inquiryForm: { ...data.inquiryForm, fields: [ toInquiryField("firstName", legacyFields.firstName, "text", "half"), toInquiryField("lastName", legacyFields.lastName, "text", "half"), toInquiryField("organization", legacyFields.organization, "text", "full"), toInquiryField( "partnershipType", legacyFields.partnershipType, "select", "full", ), toInquiryField("message", legacyFields.message, "textarea", "full"), ].filter((field) => field.label || field.placeholder || field.id), }, }; } function prepareInquiryPayload(payload) { const normalized = normalizeInquiryForm(payload); const fields = Array.isArray(normalized?.inquiryForm?.fields) ? normalized.inquiryForm.fields : []; const tabs = Array.isArray(normalized?.directory?.tabs) ? normalized.directory.tabs : []; const partners = Array.isArray(normalized?.directory?.partners) ? normalized.directory.partners : []; const seenTabs = new Set(); const duplicateTabs = []; tabs.forEach((tab) => { const normalizedTab = String(tab || "").trim().toLowerCase(); if (!normalizedTab) { return; } if (seenTabs.has(normalizedTab)) { duplicateTabs.push(String(tab || "").trim()); return; } seenTabs.add(normalizedTab); }); if (duplicateTabs.length > 0) { throw new Error( `Category tab already exists: ${duplicateTabs[0]}. Please use unique tab names.`, ); } return { ...normalized, directory: { ...normalized.directory, partners: ensureUniqueIds( partners, (partner) => partner.id, (partner, index) => partner.name || partner.category || `partner-${index + 1}`, "partner", ), }, inquiryForm: { ...normalized.inquiryForm, fields: ensureUniqueIds( fields, (field) => field.id, (field, index) => field.label || field.placeholder || `field-${index + 1}`, "field", ).map((field) => ({ id: field.id, label: field.label || "", placeholder: field.placeholder || "", type: field.type || "text", width: field.width || "full", required: Boolean(field.required), options: Array.isArray(field.options) ? field.options.filter(Boolean) : [], })), }, }; } const controller = createPageContentController({ model: PartnershipsPage, modelName: "PartnershipsPage", auditAction: AUDIT_ACTIONS.UPDATE_PARTNERSHIPS, editorConfig: partnershipsConfig, normalizeForEditor: normalizeInquiryForm, normalizeForApi: normalizeInquiryForm, preparePayload: prepareInquiryPayload, }); controller.index = async function index(req, res) { try { const doc = await PartnershipsPage.getSingle(); const rawData = doc.toObject(); const data = normalizeInquiryForm(rawData); const frontendUrl = process.env.FRONTEND_URL || "http://localhost:3000"; const backendUrl = process.env.BACKEND_URL ?? `${req.protocol}://${req.get("host")}`; const defaultTab = partnershipsConfig.tabs[0]?.key; const requestedTab = req.query.tab; const activeTab = partnershipsConfig.tabs.some((tab) => tab.key === requestedTab) ? requestedTab : defaultTab; return res.render("admin/partnerships/index", { layout: "layouts/main", title: partnershipsConfig.title, subtitle: partnershipsConfig.subtitle, data, editorConfig: partnershipsConfig, editorUi: getPartnershipsEditorUi(), activeTab, frontendUrl, backendUrl, previewUrl: `${frontendUrl}${partnershipsConfig.previewPath}`, currentPath: req.path, user: req.session.user, }); } catch (error) { console.error("partnerships index error:", error); req.flash("error_msg", "Error loading Partnerships Management"); return req.session.save(() => res.redirect("/admin/dashboard")); } }; module.exports = controller;