diff --git a/public/demo-iframeSimulationHomepage.html b/public/demo-iframeSimulationHomepage.html new file mode 100644 index 000000000..89233e108 --- /dev/null +++ b/public/demo-iframeSimulationHomepage.html @@ -0,0 +1,29 @@ + + + + + + Demo Iframe Simulation with Homepage + + +
+

+ Exemple d'intégration du test avec région fixée par l'intégrateur. +

+

+ Ci-dessous, nosgestesclimat.fr intégré comme un iframe paramétré pour + afficher uniquement le parcours utilisateur du test Nos Gestes Climat, + de la page d'accueil à la page de résultats. +

+

La hauteur de l'iframe est fixée à 500px.

+
+
+ +
+ + diff --git a/public/iframe.js b/public/iframe.js index c2b64da37..1bab82a85 100644 --- a/public/iframe.js +++ b/public/iframe.js @@ -2,6 +2,10 @@ const script = document.getElementById('ecolab-climat') || document.getElementById('nosgestesclimat') +if (!script) { + console.error('Iframe Nos Gestes Climat: No target element found') +} + const integratorUrl = encodeURIComponent(window.location.href.toString()) const srcURL = new URL(script.src) diff --git a/public/iframeSimulation.js b/public/iframeSimulation.js index 382bd3035..ba931d263 100644 --- a/public/iframeSimulation.js +++ b/public/iframeSimulation.js @@ -2,6 +2,10 @@ const script = document.getElementById('ecolab-climat') || document.getElementById('nosgestesclimat') +if (!script) { + console.error('Iframe Nos Gestes Climat: No target element found') +} + const integratorUrl = encodeURIComponent(window.location.href.toString()) const srcURL = new URL(script.src) @@ -13,24 +17,35 @@ const possibleOptions = [ { key: 'lang' }, { key: 'onlySimulation' }, { key: 'pr' }, + { key: 'withHomepage' }, + { key: 'maxHeight' }, ] const lang = script.dataset.lang const url = new URL(hostname) -url.pathname = `/${lang ? lang + '/' : ''}simulateur/bilan` +// Check if withHomepage is true +const withHomepage = script.dataset.withHomepage + +if (withHomepage) { + url.pathname = `/${lang ? lang + '/accueil-iframe' : 'accueil-iframe'}` +} else { + url.pathname = `/${lang ? lang + '/' : ''}simulateur/bilan` +} url.searchParams.append('iframe', 'true') url.searchParams.append('integratorUrl', integratorUrl) -possibleOptions.forEach(({ key, legacy }) => { - const value = script.dataset[key] || script.dataset[legacy] +possibleOptions + .filter(({ key }) => key !== 'maxHeight') + .forEach(({ key, legacy }) => { + const value = script.dataset[key] || script.dataset[legacy] - if (value) { - url.searchParams.append(key === 'pr' ? 'PR' : key, value) - } -}) + if (value) { + url.searchParams.append(key === 'pr' ? 'PR' : key, value) + } + }) const iframe = document.createElement('iframe') @@ -41,7 +56,9 @@ const iframeAttributes = { mozallowfullscreen: true, allow: 'fullscreen', id: 'iframeNGC', - style: 'border: none; width: 100%; display: block; height: 801px;', + style: `border: none; width: 100%; display: block; height: 801px; ${ + script.dataset.maxHeight ? `max-height: ${script.dataset.maxHeight}px;` : '' + }`, } for (var key in iframeAttributes) { @@ -49,12 +66,3 @@ for (var key in iframeAttributes) { } script.parentNode.insertBefore(iframe, script) - -window.addEventListener('message', function (evt) { - if ( - evt.data.kind === 'resize-height' && - iframe.style.height !== `${evt.data.value}px` - ) { - iframe.style.height = `${evt.data.value}px` - } -}) diff --git a/src/app/(simulation)/simulateur/[root]/_components/Simulateur.tsx b/src/app/(simulation)/simulateur/[root]/_components/Simulateur.tsx index 5f2941e40..7b61e820b 100644 --- a/src/app/(simulation)/simulateur/[root]/_components/Simulateur.tsx +++ b/src/app/(simulation)/simulateur/[root]/_components/Simulateur.tsx @@ -22,7 +22,7 @@ export default function Simulateur({ } return ( -
+
{isQuestionListOpen && ( -
+
- <AutresQuestions /> - - {/* Check if body has the "iframe-mode" class name and if so add the static class to the footer */} - <div - className={twMerge( - 'tutorial-footer fixed bottom-0 left-0 right-0 z-50 border-t-2 border-primary-200 bg-gray-100 py-3' - )}> - <div - className={twMerge( - 'relative mx-auto flex w-full max-w-3xl justify-between gap-4 px-4 md:px-0 lg:justify-start' - )}> - <ButtonBack /> + <div className={twMerge('mb-12 flex w-full gap-4 sm:px-4 md:px-0 ')}> + <ButtonBack /> - <OrganisationMessage /> + <OrganisationMessage /> - <ButtonStart /> - </div> + <ButtonStart /> </div> + + <AutresQuestions /> </div> </ContentLarge> ) diff --git a/src/app/accueil-iframe/page.tsx b/src/app/accueil-iframe/page.tsx new file mode 100644 index 000000000..21a5412ed --- /dev/null +++ b/src/app/accueil-iframe/page.tsx @@ -0,0 +1,102 @@ +import DynamicCTAButtons from '@/components/cta/DynamicCTAButtons' +import Partners from '@/components/landing-pages/Partners' +import Trans from '@/components/translation/Trans' +import { noIndexObject } from '@/constants/metadata' +import { trackingActionClickCTA } from '@/constants/tracking/actions' +import LandingPage from '@/design-system/layout/LandingPage' +import { getServerTranslation } from '@/helpers/getServerTranslation' +import { getMetadataObject } from '@/helpers/metadata/getMetadataObject' +import { + getLandingClickCTARestart, + getLandingClickCTAResults, + getLandingClickCTAResume, + getLandingClickCTAStart, +} from '@/helpers/tracking/landings' +import { headers } from 'next/headers' +import InteractiveIllustration from '../_components/InteractiveIllustration' + +export async function generateMetadata() { + const { t } = await getServerTranslation() + return getMetadataObject({ + title: t('Calculez votre empreinte carbone et eau en 10 minutes !'), + description: t( + "2 millions de personnes ont déjà calculé leur empreinte sur le climat avec le calculateur Nos Gestes Climat ! Et vous, qu'attendez-vous pour faire le test ?" + ), + image: '/images/misc/calculer-empreinte-carbone-et-eau.png', + alternates: { + canonical: '', + }, + robots: noIndexObject, + }) +} + +export default async function Homepage() { + const headersList = headers() + const pathname = headersList.get('x-pathname') || '/' + + return ( + <> + <LandingPage + heroIllustration={<InteractiveIllustration />} + heroTitle={<Trans>Connaissez-vous votre empreinte écologique ?</Trans>} + heroDescription={ + <div className="flex flex-col items-center gap-6 md:items-start md:gap-10"> + <p className="mb-0 text-base md:order-1 md:text-2xl"> + <Trans> + Calculez votre{' '} + <strong className="text-primary-700">empreinte carbone</strong>{' '} + et votre{' '} + <strong className="text-primary-700">empreinte eau</strong> en{' '} + <strong className="text-secondary-700"> + seulement 10 minutes + </strong> + . + </Trans> + </p> + + <div className="flex flex-col items-center gap-6 md:order-2 md:mt-0 md:max-w-[300px] md:items-start"> + <DynamicCTAButtons + trackingEvents={{ + start: getLandingClickCTAStart( + pathname, + trackingActionClickCTA + ), + resume: getLandingClickCTAResume( + pathname, + trackingActionClickCTA + ), + results: getLandingClickCTAResults( + pathname, + trackingActionClickCTA + ), + restart: getLandingClickCTARestart( + pathname, + trackingActionClickCTA + ), + }} + className="w-full" + /> + + {/* Displayed on mobile only */} + <div className="mx-auto mt-4 max-w-80 md:mt-0 md:hidden"> + <InteractiveIllustration /> + </div> + + {/* Displayed on desktop only */} + <p> + <Trans> + <strong className="text-primary-700"> + 2 millions de personnes + </strong>{' '} + ont déjà calculé leur empreinte ! + </Trans> + </p> + </div> + </div> + } + heroPartners={<Partners />}> + <></> + </LandingPage> + </> + ) +} diff --git a/src/components/layout/header/HeaderDesktop.tsx b/src/components/layout/header/HeaderDesktop.tsx index dfbc378e7..fe6d910ec 100644 --- a/src/components/layout/header/HeaderDesktop.tsx +++ b/src/components/layout/header/HeaderDesktop.tsx @@ -17,6 +17,7 @@ import { HIDE_CTA_PATHS } from '@/constants/urls' import { linkToClassement } from '@/helpers/navigation/classementPages' import { useSimulateurPage } from '@/hooks/navigation/useSimulateurPage' import { useClientTranslation } from '@/hooks/useClientTranslation' +import { useIframe } from '@/hooks/useIframe' import { useUser } from '@/publicodes-state' import { trackEvent } from '@/utils/matomo/trackEvent' import { usePathname } from 'next/navigation' @@ -26,7 +27,6 @@ import OrganisationLink from './_components/OrganisationLink' import ProfileIcon from './_components/ProfileIcon' import DebugIndicator from './headerDesktop/DebugIndicator' import CTAButton from './headerDesktop/MenuCTAButton' - type Props = { isSticky: boolean } @@ -39,6 +39,8 @@ export default function HeaderDesktop({ isSticky }: Props) { const { getLinkToSimulateurPage } = useSimulateurPage() + const { isIframeOnlySimulation } = useIframe() + return ( <header className={twMerge( @@ -51,67 +53,71 @@ export default function HeaderDesktop({ isSticky }: Props) { <Logo onClick={() => trackEvent(headerClickLogo)} /> </div> - <nav className="h-full"> - <ul className="flex h-full flex-1 justify-start gap-4"> - <li> - <NavLink - href={getLinkToSimulateurPage()} - onClick={() => trackEvent(headerClickTest)} - activeMatches={['/tutoriel', '/simulateur', '/fin']} - icon={BilanIcon} - title={t('Mon empreinte')}> - <Trans>Mon empreinte</Trans> - </NavLink> - </li> + {!isIframeOnlySimulation && ( + <> + <nav className="h-full"> + <ul className="flex h-full flex-1 justify-start gap-4"> + <li> + <NavLink + href={getLinkToSimulateurPage()} + onClick={() => trackEvent(headerClickTest)} + activeMatches={['/tutoriel', '/simulateur', '/fin']} + icon={BilanIcon} + title={t('Mon empreinte')}> + <Trans>Mon empreinte</Trans> + </NavLink> + </li> - <li> - <NavLink - href="/actions" - onClick={() => trackEvent(headerClickActions)} - icon={ActionsIcon} - title={t('Mes gestes')}> - <Trans>Mes gestes</Trans> - </NavLink> - </li> + <li> + <NavLink + href="/actions" + onClick={() => trackEvent(headerClickActions)} + icon={ActionsIcon} + title={t('Mes gestes')}> + <Trans>Mes gestes</Trans> + </NavLink> + </li> - <li> - <NavLink - href={linkToClassement} - onClick={() => trackEvent(headerClickClassements)} - icon={AmisIcon} - activeMatches={['/classement', '/amis']} - title={t('Mes classements')} - data-cypress-id="amis-link"> - <Trans>Mes groupes</Trans> - </NavLink> - </li> - </ul> - </nav> + <li> + <NavLink + href={linkToClassement} + onClick={() => trackEvent(headerClickClassements)} + icon={AmisIcon} + activeMatches={['/classement', '/amis']} + title={t('Mes classements')} + data-cypress-id="amis-link"> + <Trans>Mes groupes</Trans> + </NavLink> + </li> + </ul> + </nav> - <div className="flex h-full items-center gap-3"> - <PRIndicator /> + <div className="flex h-full items-center gap-3"> + <PRIndicator /> - <DebugIndicator /> + <DebugIndicator /> - <NavLink - href="/profil" - icon={ProfileIcon} - title={t('Profil')} - className="px-4" - onClick={() => trackEvent(headerClickProfil)}> - <Trans>Profil</Trans> - </NavLink> + <NavLink + href="/profil" + icon={ProfileIcon} + title={t('Profil')} + className="px-4" + onClick={() => trackEvent(headerClickProfil)}> + <Trans>Profil</Trans> + </NavLink> - {user?.organisation?.administratorEmail ? ( - <> - <div className="my-auto h-8 w-[1px] bg-gray-200" /> + {user?.organisation?.administratorEmail ? ( + <> + <div className="my-auto h-8 w-[1px] bg-gray-200" /> - <OrganisationLink /> - </> - ) : !HIDE_CTA_PATHS.find((path) => pathname.includes(path)) ? ( - <CTAButton /> - ) : null} - </div> + <OrganisationLink /> + </> + ) : !HIDE_CTA_PATHS.find((path) => pathname.includes(path)) ? ( + <CTAButton /> + ) : null} + </div> + </> + )} </div> </div> </header> diff --git a/src/components/translation/LocalisationBanner.tsx b/src/components/translation/LocalisationBanner.tsx index 6a4336cf3..5d3ef36e2 100644 --- a/src/components/translation/LocalisationBanner.tsx +++ b/src/components/translation/LocalisationBanner.tsx @@ -56,11 +56,11 @@ export default function LocalisationBanner({ supportedRegions }: Props) { return ( <Card className={twMerge( - 'fixed bottom-0 right-8 z-50 mx-auto mb-8 max-w-full flex-row bg-primary-50', + 'fixed bottom-0 left-4 right-4 z-50 mx-auto mb-8 flex-row bg-primary-50 sm:left-auto sm:right-8', isTutorialOrTest && 'bottom-12' )}> - <div className="flex gap-4"> - <div className="flex-1"> + <div className="flex w-full gap-4"> + <div className="w-full flex-1"> {regionParams && ( <> <p className="mb-0 inline flex-1 items-baseline gap-1">