import { JsonPropertyDto } from "~/modules/jsonProperties/dtos/JsonPropertyTypeDto"; import { TFunction } from "i18next"; import { JsonPropertiesValuesDto } from "~/modules/jsonProperties/dtos/JsonPropertiesValuesDto"; import { Portal } from "@toolctrl/db/prisma-browser"; export type PortalConfiguration = { enabled: boolean; forTenants: boolean; pricing: boolean; analytics: boolean; domains?: { enabled: boolean; provider: "fly"; portalAppId: string; records?: { A: string; AAAA: string }; }; metadata: Array | undefined; pages: Array; }; export type PortalPageConfigDto = { name: string; title: string; slug: string; properties: Array; errors?: (params: { portal: Portal; page: { attributes: JsonPropertiesValuesDto } | null }) => string[]; }; export function getAppPortalConfiguration({ t }: { t: TFunction }): PortalConfiguration { const titleProperty: JsonPropertyDto = { name: "title", title: t("models.portal.title"), type: "string", required: true, }; const descriptionProperty: JsonPropertyDto = { name: "description", title: t("models.portal.description"), type: "string", required: false, }; const htmlProperty: JsonPropertyDto = { name: "html", title: t("shared.content"), type: "wysiwyg", required: true, }; const seoProperties: JsonPropertyDto[] = [ { name: "seoTitle", title: t("shared.title"), type: "string", required: false, group: t("models.portal.seo"), }, { name: "seoDescription", title: t("shared.description"), type: "string", required: false, group: t("models.portal.seo"), }, { name: "seoImage", title: t("shared.image"), type: "image", required: false, group: t("models.portal.seo"), }, ]; const conf: PortalConfiguration = { // Portals ship gated OFF by default so the boilerplate stays lean; a // deployment opts in with PORTALS_ENABLED=true (e.g. the e2e/readiness // target). The route files are always mounted but the loaders fail closed // (400 "disabled") until this flag is set, so flipping the env is the only // switch needed at runtime. enabled: process.env.PORTALS_ENABLED === "true", forTenants: true, pricing: true, analytics: true, domains: { enabled: true, provider: "fly", portalAppId: "app-portal", records: { A: "66.241.125.25", AAAA: "2a09:8280:1::31:5dc2:0", }, }, metadata: [], pages: [ { name: "pricing", title: t("models.portal.pages.pricing"), slug: "/plans", properties: [titleProperty, descriptionProperty, ...seoProperties], errors: (params) => { let errors: string[] = []; if (!params.portal.stripeAccountId) { errors.push(t("models.portal.pages.errors.stripeAccountMissing")); } return errors; }, }, { name: "privacy-policy", title: t("models.portal.pages.privacyPolicy"), slug: "/privacy-policy", properties: [titleProperty, descriptionProperty, htmlProperty, ...seoProperties], errors: (params) => { const errors: string[] = []; if (!params.page?.attributes?.html) { errors.push(t("models.portal.pages.errors.privacyPolicyContentMissing")); } return errors; }, }, { name: "terms-and-conditions", title: t("models.portal.pages.termsAndConditions"), slug: "/terms-and-conditions", properties: [titleProperty, descriptionProperty, htmlProperty, ...seoProperties], errors: (params) => { const errors: string[] = []; if (!params.page?.attributes?.html) { errors.push(t("models.portal.pages.errors.termsContentMissing")); } return errors; }, }, ], }; return conf; }