diff --git a/package.json b/package.json index d4129c64..0196c3f6 100644 --- a/package.json +++ b/package.json @@ -45,6 +45,8 @@ "dependencies": { "@libsql/client": "^0.15.4", "@mapbox/search-js-react": "^1.5.0", + "@open-iframe-resizer/core": "^2.1.0", + "@open-iframe-resizer/react": "^2.1.0", "@payloadcms/admin-bar": "3.64.0", "@payloadcms/db-sqlite": "3.64.0", "@payloadcms/email-nodemailer": "3.64.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5f3be766..5c13cd09 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -13,6 +13,12 @@ importers: '@mapbox/search-js-react': specifier: ^1.5.0 version: 1.5.0(mapbox-gl@3.15.0)(react-dom@19.1.0(react@19.1.0))(react@19.1.0) + '@open-iframe-resizer/core': + specifier: ^2.1.0 + version: 2.1.0 + '@open-iframe-resizer/react': + specifier: ^2.1.0 + version: 2.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) '@payloadcms/admin-bar': specifier: 3.64.0 version: 3.64.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0) @@ -3463,6 +3469,21 @@ packages: } engines: { node: '>=12.4.0' } + '@open-iframe-resizer/core@2.1.0': + resolution: + { + integrity: sha512-FKpcXXMgcdM86m+cF2TqU6cG05IQ6PEuTSvJfab5we78A4cXjdpb5MofdcCPz4f4hUr+zZyb3pUzZ834YVxtLg==, + } + + '@open-iframe-resizer/react@2.1.0': + resolution: + { + integrity: sha512-P7+BCqMXOwDF1x3HhGVayU9M7slFIKI+9gsIoahLS71Pq/BF/Sc+36EyMNhSOV1KKtKZn6g8fEYywqQSdjglmw==, + } + peerDependencies: + react: '>=17.0.0' + react-dom: '>=17.0.0' + '@opentelemetry/api-logs@0.53.0': resolution: { @@ -16125,6 +16146,14 @@ snapshots: '@nolyfill/is-core-module@1.0.39': {} + '@open-iframe-resizer/core@2.1.0': {} + + '@open-iframe-resizer/react@2.1.0(react-dom@19.1.0(react@19.1.0))(react@19.1.0)': + dependencies: + '@open-iframe-resizer/core': 2.1.0 + react: 19.1.0 + react-dom: 19.1.0(react@19.1.0) + '@opentelemetry/api-logs@0.53.0': dependencies: '@opentelemetry/api': 1.9.0 diff --git a/src/app/(embeds)/a3-globals.css b/src/app/(embeds)/a3-globals.css new file mode 100644 index 00000000..ee4d19bb --- /dev/null +++ b/src/app/(embeds)/a3-globals.css @@ -0,0 +1,40 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; + +@import '../(frontend)/colors.css'; + +@layer base { + h1, + h2, + h3, + h4, + h5, + h6 { + font-size: auto; + font-weight: auto; + } +} + +@layer base { + * { + @apply border-border; + } + body { + @apply bg-background text-foreground flex flex-col max-w-[100vw] overflow-x-clip; + } +} + +/* A3 Embed Fonts */ +.a3 { + font-family: var(--font-libre-franklin), sans-serif; +} + +.a3 h1, +.a3 h2, +.a3 h3, +.a3 h4, +.a3 h5, +.a3 h6 { + font-family: var(--font-fjalla-one), sans-serif; +} diff --git a/src/app/(frontend)/embeds/courses/CoursesFilters.tsx b/src/app/(embeds)/embeds/courses/CoursesFilters.tsx similarity index 100% rename from src/app/(frontend)/embeds/courses/CoursesFilters.tsx rename to src/app/(embeds)/embeds/courses/CoursesFilters.tsx diff --git a/src/app/(frontend)/embeds/courses/CoursesMobileFilters.tsx b/src/app/(embeds)/embeds/courses/CoursesMobileFilters.tsx similarity index 100% rename from src/app/(frontend)/embeds/courses/CoursesMobileFilters.tsx rename to src/app/(embeds)/embeds/courses/CoursesMobileFilters.tsx diff --git a/src/app/(frontend)/embeds/courses/page.tsx b/src/app/(embeds)/embeds/courses/page.tsx similarity index 56% rename from src/app/(frontend)/embeds/courses/page.tsx rename to src/app/(embeds)/embeds/courses/page.tsx index 46271380..560e252f 100644 --- a/src/app/(frontend)/embeds/courses/page.tsx +++ b/src/app/(embeds)/embeds/courses/page.tsx @@ -3,12 +3,12 @@ import { FiltersTotalProvider } from '@/contexts/FiltersTotalContext' import { getCourses } from '@/utilities/queries/getCourses' import { getCoursesStates } from '@/utilities/queries/getCoursesStates' import { getProviders } from '@/utilities/queries/getProviders' +import Script from 'next/script' import { createLoader, parseAsBoolean, parseAsString, SearchParams } from 'nuqs/server' import { CoursesFilters } from './CoursesFilters' import { CoursesMobileFilters } from './CoursesMobileFilters' const coursesSearchParams = { - backgroundColor: parseAsString, title: parseAsString, showFilters: parseAsBoolean.withDefault(false), types: parseAsString, @@ -27,7 +27,6 @@ export default async function CoursesEmbedPage({ searchParams: Promise }) { const { - backgroundColor, title, showFilters, types, @@ -59,44 +58,50 @@ export default async function CoursesEmbedPage({ ) return ( - -
- {title && ( -
-

{title}

-
- )} - - {showFilters && ( -
- -
- )} + <> + +
+ {title && ( +
+

{title}

+
+ )} -
-
- -
{showFilters && ( - +
+ +
)} + +
+
+ +
+ {showFilters && ( + + )} +
-
-
+ + + ` - setSanitizedHtml(doc.body.innerHTML + resizeScript) - }, [html, id]) - - useEffect(() => { - const handleMessage = (event: MessageEvent) => { - if (event.data?.type === 'embed-resize' && event.data?.id === id) { - const newHeight = event.data.height - if (newHeight && typeof newHeight === 'number') { - setIframeHeight(newHeight) - } - } - } - - window.addEventListener('message', handleMessage) - return () => { - window.removeEventListener('message', handleMessage) - } - }, [id]) + setSanitizedHtml(sanitized + styleOverrides) + }, [html]) if (sanitizedHtml === null) return null @@ -152,34 +79,15 @@ export const GenericEmbedBlock = ({ alignContent === 'right' && 'items-end', className, )} - style={{ - height: shouldBeIframe ? iframeHeight : undefined, - }} > - {shouldBeIframe ? ( - + `, backgroundColor: 'transparent', alignContent: 'left', blockName: null, @@ -101,7 +105,7 @@ export const coursesByExternalProvidersPage: ( blockType: 'headerBlock', }, { - html: ``, backgroundColor: 'transparent', alignContent: 'left', blockName: null, diff --git a/src/providers/PostHogProvider.tsx b/src/providers/PostHogProvider.tsx index bb125556..ad6a5488 100644 --- a/src/providers/PostHogProvider.tsx +++ b/src/providers/PostHogProvider.tsx @@ -6,17 +6,34 @@ import posthog from 'posthog-js' import { PostHogProvider as PHProvider } from 'posthog-js/react' import React, { useEffect } from 'react' -export function PostHogProvider({ children }: { children: React.ReactNode }) { - useEffect(function initPostHog() { - if (process.env.NEXT_PUBLIC_POSTHOG_KEY) { - posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, { - api_host: `${getRootDomainURL()}/ingest`, - ui_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://us.posthog.com', - defaults: '2025-05-24', - debug: process.env.NODE_ENV !== 'production', - }) - } - }, []) +type PersistenceMode = + | 'cookie' + | 'localStorage' + | 'localStorage+cookie' + | 'sessionStorage' + | 'memory' + +export function PostHogProvider({ + children, + persistence = 'localStorage+cookie', +}: { + children: React.ReactNode + persistence?: PersistenceMode +}) { + useEffect( + function initPostHog() { + if (process.env.NEXT_PUBLIC_POSTHOG_KEY) { + posthog.init(process.env.NEXT_PUBLIC_POSTHOG_KEY, { + api_host: `${getRootDomainURL()}/ingest`, + ui_host: process.env.NEXT_PUBLIC_POSTHOG_HOST || 'https://us.posthog.com', + defaults: '2025-05-24', + debug: process.env.NODE_ENV !== 'production', + persistence, // localStorage+cookie is the PostHog default + }) + } + }, + [persistence], + ) useEffect(function addDefaultPostHogProperties() { if (process.env.NEXT_PUBLIC_POSTHOG_KEY) { diff --git a/src/utilities/queries/getCourses.ts b/src/utilities/queries/getCourses.ts index 60d16d7b..e5eb109c 100644 --- a/src/utilities/queries/getCourses.ts +++ b/src/utilities/queries/getCourses.ts @@ -53,7 +53,7 @@ export async function getCourses(params: GetCoursesParams): Promise 0) { conditions.push({ 'provider.slug': {