Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

✨ Better display the water footprint throughout the test #815

Merged
merged 24 commits into from
Feb 3, 2025
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
♻️ Rework explanation tutoriel position and texts
  • Loading branch information
bjlaa committed Jan 20, 2025
commit 25f7281a955bb96f8c8825c5b67f1fc2998f4fc2
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
import Explanation from '@/components/total/total/Explanation'
import InteractiveResultBlock from './resultsBlocksDesktop/InteractiveResultBlock'

export default function ResultsBlocksDesktop() {
return (
<section className="hidden flex-col gap-4 md:flex">
<section className="relative hidden flex-col gap-4 md:flex">
<InteractiveResultBlock metric="carbone" />
<InteractiveResultBlock metric="eau" />

<Explanation />
</section>
)
}
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import TotalFootprintNumber from '@/components/misc/TotalFootprintNumber'
import ValueChangeDisplay from '@/components/misc/ValueChangeDisplay'
import Explanation from '@/components/total/total/Explanation'
import Card from '@/design-system/layout/Card'

export default function ResultsBlocks() {
return (
<div className="mb-8 grid grid-cols-2 gap-4 md:hidden">
<div className="relative mb-8 grid grid-cols-2 gap-4 md:hidden">
<Card
aria-live="polite"
className="relative col-span-1 rounded-md border-primary-100 bg-primary-50 p-2">
@@ -19,6 +20,8 @@ export default function ResultsBlocks() {

<ValueChangeDisplay metric="eau" />
</Card>

<Explanation />
</div>
)
}
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@
import CloudIcon from '@/components/icons/Cloudicon'
import DropIcon from '@/components/icons/DropIcon'
import PlusIcon from '@/components/icons/PlusIcon'
import TotalFootprintNumber from '@/components/misc/TotalFootprintNumber'
import ValueChangeDisplay from '@/components/misc/ValueChangeDisplay'
import { eauMetric } from '@/constants/metric'
import type { Metrics } from '@incubateur-ademe/nosgestesclimat'
import CategoriesResultList from './interactiveResultBlock/CategoriesResultList'

@@ -17,11 +14,6 @@ export default function InteractiveResultBlock({
<summary className="relative z-10 flex cursor-pointer list-none items-center justify-between gap-2 rounded-lg border-2 border-primary-100 bg-primary-50 p-4 [&::-webkit-details-marker]:hidden [&::marker]:hidden">
<div className="relative w-full">
<div className="flex items-center gap-2">
{metric === eauMetric ? (
<DropIcon className="mr-2 h-8 w-8 fill-blue-600 stroke-blue-500 stroke-1" />
) : (
<CloudIcon className="mr-2 h-8 w-8 fill-gray-600 stroke-gray-500 stroke-1" />
)}
<h3 className="mb-0 text-[13px] font-bold md:text-base">
<TotalFootprintNumber metric={metric} />
</h3>
Original file line number Diff line number Diff line change
@@ -50,7 +50,11 @@ export default function CategoryResult({
'relative mb-0 flex w-full items-center justify-between gap-4 overflow-hidden bg-white px-4 py-2 text-sm transition-colors',
isStarted || isCurrent ? 'text-default' : 'text-slate-600'
)}>
<div className="relative flex items-center text-sm font-normal">
<div
className={twMerge(
'relative flex items-center text-sm font-normal',
getTextDarkColor(category)
)}>
<Emoji
className={twMerge(
isStarted || isCurrent ? 'opacity-100' : 'opacity-50',
@@ -63,7 +67,6 @@ export default function CategoryResult({
<span
className={twMerge(
'relative block font-semibold transition-opacity',
getTextDarkColor(category),
isCompleted || isStarted
? 'visible opacity-100'
: 'invisible opacity-0'
52 changes: 1 addition & 51 deletions src/components/total/Total.tsx
Original file line number Diff line number Diff line change
@@ -1,19 +1,12 @@
'use client'

import {
simulateurCloseScoreInfo,
simulateurOpenScoreInfo,
} from '@/constants/tracking/pages/simulateur'
import { getBgCategoryColor } from '@/helpers/getCategoryColorClass'
import { useIframe } from '@/hooks/useIframe'
import { useCurrentSimulation, useForm, useUser } from '@/publicodes-state'
import { trackEvent } from '@/utils/matomo/trackEvent'
import { useCurrentSimulation, useForm } from '@/publicodes-state'
import { useRouter } from 'next/navigation'
import { useEffect, useState } from 'react'
import { twMerge } from 'tailwind-merge'
import ButtonBack from './total/ButtonBack'
import Category from './total/Category'
import Explanation from './total/Explanation'
import Progress from './total/Progress'
import TotalButtons from './total/TotalButtons'

@@ -28,10 +21,6 @@ export default function Total({
toggleSaveModal?: () => void
simulationMode?: boolean
}) {
const { tutorials, hideTutorial, showTutorial } = useUser()

const { progression } = useCurrentSimulation()

const { isIframe, isIframeOnlySimulation } = useIframe()

const { currentCategory } = useForm()
@@ -40,35 +29,6 @@ export default function Total({

const router = useRouter()

const [hasManuallyOpenedTutorial, setHasManuallyOpenedTutorial] =
useState(false)

function toggleOpen() {
if (tutorials.scoreExplanation) {
trackEvent(simulateurOpenScoreInfo)
setHasManuallyOpenedTutorial(true)
showTutorial('scoreExplanation')
} else {
trackEvent(simulateurCloseScoreInfo)
hideTutorial('scoreExplanation')
}
}

useEffect(() => {
if (
progression > 0.05 &&
!tutorials.scoreExplanation &&
!hasManuallyOpenedTutorial
) {
hideTutorial('scoreExplanation')
}
}, [
hideTutorial,
progression,
tutorials.scoreExplanation,
hasManuallyOpenedTutorial,
])

return (
<header
className={twMerge(
@@ -105,16 +65,6 @@ export default function Total({
) : null}
</div>
</div>
{!tutorials.scoreExplanation && simulationMode ? (
<div className="relative mx-auto max-w-6xl">
<Explanation
toggleOpen={toggleOpen}
isFirstToggle={
!tutorials.scoreExplanation && !hasManuallyOpenedTutorial
}
/>
</div>
) : null}
</header>
)
}
83 changes: 59 additions & 24 deletions src/components/total/total/Explanation.tsx
Original file line number Diff line number Diff line change
@@ -2,25 +2,57 @@

import Link from '@/components/Link'
import Trans from '@/components/translation/Trans'
import {
simulateurCloseScoreInfo,
simulateurOpenScoreInfo,
} from '@/constants/tracking/pages/simulateur'
import Button from '@/design-system/inputs/Button'
import Badge from '@/design-system/layout/Badge'
import Emoji from '@/design-system/utils/Emoji'
import { useClientTranslation } from '@/hooks/useClientTranslation'
import { useCurrentSimulation } from '@/publicodes-state'
import { useCurrentSimulation, useUser } from '@/publicodes-state'
import { trackEvent } from '@/utils/matomo/trackEvent'
import { motion } from 'framer-motion'
import { useEffect, useState } from 'react'

export default function Explanation({
toggleOpen,
isFirstToggle,
}: {
toggleOpen: () => void
isFirstToggle: boolean
}) {
export default function Explanation() {
const [hasManuallyOpenedTutorial, setHasManuallyOpenedTutorial] =
useState(false)

const { progression } = useCurrentSimulation()
const { tutorials, hideTutorial, showTutorial } = useUser()

const { t } = useClientTranslation()

const [shouldRender, setShouldRender] = useState(!isFirstToggle)
const isFirstToggle =
!tutorials.scoreExplanation && !hasManuallyOpenedTutorial

const [shouldRender, setShouldRender] = useState(isFirstToggle)

function toggleOpen() {
if (tutorials.scoreExplanation) {
trackEvent(simulateurOpenScoreInfo)
setHasManuallyOpenedTutorial(true)
showTutorial('scoreExplanation')
} else {
trackEvent(simulateurCloseScoreInfo)
hideTutorial('scoreExplanation')
}
}

useEffect(() => {
if (
progression > 0.05 &&
!tutorials.scoreExplanation &&
!hasManuallyOpenedTutorial
) {
hideTutorial('scoreExplanation')
}
}, [
hideTutorial,
progression,
tutorials.scoreExplanation,
hasManuallyOpenedTutorial,
])

useEffect(() => {
if (isFirstToggle) {
@@ -32,7 +64,7 @@ export default function Explanation({
}
}, [isFirstToggle])

if (!shouldRender) {
if (!shouldRender || tutorials.scoreExplanation) {
return null
}

@@ -41,20 +73,21 @@ export default function Explanation({
initial={{ opacity: 0, translateY: '-10px' }}
animate={{ opacity: 1, translateY: 0 }}
transition={{ duration: 0.3 }}
className="absolute left-2 top-0 z-50 mx-4 mb-2 w-full max-w-[calc(100%-2rem)] rounded-xl border-2 border-primary-200 bg-gray-100 p-3 pt-2 text-sm md:left-8 md:top-4 lg:w-2/3">
className="absolute left-0 right-0 top-20 z-50 mb-2 w-full rounded-xl border-2 border-primary-200 bg-gray-100 p-3 pt-2 text-sm md:left-0 md:top-24 md:mx-0 lg:w-80">
<svg
width="28"
height="24"
viewBox="0 0 28 24"
fill="none"
xmlns="http://www.w3.org/2000/svg"
className="absolute bottom-full left-8">
className="absolute -top-6 left-4 z-10">
<path
d="M14 0L27.8564 24H0.143594L14 0Z"
className=" fill-gray-100 stroke-primary-200 stroke-2"
/>
</svg>
<div className="flex justify-end">

<div className="mb-1 flex justify-end">
<button
onClick={toggleOpen}
className="h-3 w-3 bg-gray-100 text-xl leading-none"
@@ -65,36 +98,38 @@ export default function Explanation({

{progression === 0 ? (
<p className="mb-2">
<Emoji>🧮</Emoji>{' '}
<Trans i18nKey={'components.ScoreExplanation.text.p1'}>
🧮 Voici votre score de départ, calculé à partir de réponses
attribuées à l'avance à chaque question ! Il évoluera à chaque
nouvelle réponse.
Voici vos scores de départ, calculés à partir de réponses attribuées
à l'avance à chaque question ! Ils évolueront à chaque nouvelle
réponse.
</Trans>
</p>
) : (
<p className="mb-2">
<Emoji>🧮</Emoji>{' '}
<Trans i18nKey={'components.ScoreExplanation.text.p2'}>
🧮 Voici votre score provisoire, il évolue à chaque nouvelle réponse
Voici vos scores provisoires, ils évoluent à chaque nouvelle réponse
!
</Trans>
</p>
)}
<p className="mb-2">
<Emoji>🤔</Emoji>{' '}
<Trans i18nKey={'components.ScoreExplanation.text.p3'}>
🤔 Si vous répondez "je ne sais pas" à une question, le score ne
changera pas : une valeur par défaut vous est attribuée.
Si vous répondez "je ne sais pas" à une question, le score ne changera
pas : une valeur par défaut vous est attribuée.
</Trans>
</p>
<p className="mb-2">
<Emoji>💡</Emoji>{' '}
<Trans i18nKey={'components.ScoreExplanation.text.p4'}>
💡 Nous améliorons le calcul et ses valeurs par défaut{' '}
Nous améliorons le calcul et ses valeurs par défaut{' '}
<Link href="/nouveautes">tous les mois</Link>!
</Trans>
</p>
<p className="mb-2 md:mb-4">
<Badge tag="span" color="secondary" size="xs">
BETA
</Badge>{' '}
<Emoji>💧</Emoji>{' '}
<Trans>
Retrouvez aussi le résultat de votre empreinte eau à la fin du test !
</Trans>
18 changes: 10 additions & 8 deletions src/locales/ui/ui-en.yaml
Original file line number Diff line number Diff line change
@@ -71,14 +71,14 @@ entries:
Voir toutes les actions: See all actions
Vous n'avez pas encore fait le test.: You haven't taken the test yet.
actions choisies: selected actions
components.ScoreExplanation.text.p1: 🧮 This is your starting score, calculated from pre-assigned answers to each question! It will change with each new answer.
components.ScoreExplanation.text.p1.lock: 🧮 Voici votre score de départ, calculé à partir de réponses attribuées à l'avance à chaque question ! Il évoluera à chaque nouvelle réponse.
components.ScoreExplanation.text.p2: 🧮 Here is your provisional score, it changes with each new answer!
components.ScoreExplanation.text.p2.lock: 🧮 Voici votre score provisoire, il évolue à chaque nouvelle réponse !
components.ScoreExplanation.text.p3: '🤔 If you answer "I don''t know" to a question, the score will not change: you are assigned a default value.'
components.ScoreExplanation.text.p3.lock: '🤔 Si vous répondez "je ne sais pas" à une question, le score ne changera pas : une valeur par défaut vous est attribuée.'
components.ScoreExplanation.text.p4: 💡 We improve the calculation and its default values <2>every month</2>!
components.ScoreExplanation.text.p4.lock: 💡 Nous améliorons le calcul et ses valeurs par défaut <2>tous les mois</2>!
components.ScoreExplanation.text.p1: Here are your starting scores, calculated from the answers assigned to each question in advance! They will change with each new answer.
components.ScoreExplanation.text.p1.lock: Voici vos scores de départ, calculés à partir de réponses attribuées à l'avance à chaque question ! Ils évolueront à chaque nouvelle réponse.
components.ScoreExplanation.text.p2: Here are your provisional scores - they change with each new answer!
components.ScoreExplanation.text.p2.lock: Voici vos scores provisoires, ils évoluent à chaque nouvelle réponse !
components.ScoreExplanation.text.p3: 'If you answer "I don''t know" to a question, the score will not change: you will be given a default value.'
components.ScoreExplanation.text.p3.lock: 'Si vous répondez "je ne sais pas" à une question, le score ne changera pas : une valeur par défaut vous est attribuée.'
components.ScoreExplanation.text.p4: We improve the calculation and its default values <2>every month</2>!
components.ScoreExplanation.text.p4.lock: Nous améliorons le calcul et ses valeurs par défaut <2>tous les mois</2>!
components.localisation.LocalisationMessage.betaMsg: It is currently in <1>beta</1> version.
components.localisation.LocalisationMessage.betaMsg.lock: Elle est actuellement en version <1>bêta</1>.
components.localisation.LocalisationMessage.warnMessage: Your region is not yet supported, the French model is proposed by default
@@ -1529,3 +1529,5 @@ entries:
La valeur maximum pour ce champ est de: The maximum value for this field is
La valeur pour ce champ est comprise entre: The value for this field is between
En participant vous acceptez que vos résultats soient partagés anonymement avec cette organisation.: By taking part, you agree to your results being shared anonymously with this organisation.
d'eau / jour: of water / day
de CO₂e / an: of CO₂e / year
18 changes: 10 additions & 8 deletions src/locales/ui/ui-es.yaml
Original file line number Diff line number Diff line change
@@ -67,22 +67,22 @@ entries:
Sites Web: Páginas web
components.localisation.LocalisationMessage.warnMessage: Su región aún no es compatible, el modelo francés se propone por defecto
components.localisation.LocalisationMessage.warnMessage.lock: Votre région n'est pas encore supportée, le modèle Français vous est proposé par défaut
components.ScoreExplanation.text.p2: 🧮 ¡Aquí tienes tu puntuación provisional, que cambia con cada nueva respuesta!
components.ScoreExplanation.text.p2.lock: 🧮 Voici votre score provisoire, il évolue à chaque nouvelle réponse !
components.ScoreExplanation.text.p2: 'Aquí tienes tus puntuaciones provisionales: ¡cambian con cada nueva respuesta!'
components.ScoreExplanation.text.p2.lock: Voici vos scores provisoires, ils évoluent à chaque nouvelle réponse !
actions choisies: acciones seleccionadas
Une technologie moderne: Tecnología moderna
Questions fréquentes: Preguntas más frecuentes
derniers: última
Non: No
Nouveautés: Noticias
components.ScoreExplanation.text.p3: '🤔 Si contestas "No lo sé" a una pregunta, la puntuación no cambiará: se te da un valor por defecto.'
components.ScoreExplanation.text.p3.lock: '🤔 Si vous répondez "je ne sais pas" à une question, le score ne changera pas : une valeur par défaut vous est attribuée.'
components.ScoreExplanation.text.p4: 💡 ¡Mejoramos el cálculo y sus valores por defecto <2>cada mes</2>!
components.ScoreExplanation.text.p4.lock: 💡 Nous améliorons le calcul et ses valeurs par défaut <2>tous les mois</2>!
components.ScoreExplanation.text.p3: 'Si responde "No lo sé" a una pregunta, la puntuación no cambiará: se le dará un valor por defecto.'
components.ScoreExplanation.text.p3.lock: 'Si vous répondez "je ne sais pas" à une question, le score ne changera pas : une valeur par défaut vous est attribuée.'
components.ScoreExplanation.text.p4: Mejoramos el cálculo y sus valores por defecto <2>todos los meses</2>
components.ScoreExplanation.text.p4.lock: Nous améliorons le calcul et ses valeurs par défaut <2>tous les mois</2>!
components.localisation.Localisation.warnMessage2: No hemos podido detectar su país de simulación, por lo que se propone por defecto el modelo francés.
components.localisation.Localisation.warnMessage2.lock: Nous n'avons pas pu détecter votre pays de simulation, le modèle Français vous est proposé par défaut.
components.ScoreExplanation.text.p1: 🧮 ¡Aquí tienes tu puntuación inicial, calculada a partir de las respuestas asignadas de antemano a cada pregunta! Cambiará con cada nueva respuesta.
components.ScoreExplanation.text.p1.lock: 🧮 Voici votre score de départ, calculé à partir de réponses attribuées à l'avance à chaque question ! Il évoluera à chaque nouvelle réponse.
components.ScoreExplanation.text.p1: Aquí tienes tus puntuaciones iniciales, calculadas a partir de las respuestas asignadas de antemano a cada pregunta Cambiarán con cada nueva respuesta.
components.ScoreExplanation.text.p1.lock: Voici vos scores de départ, calculés à partir de réponses attribuées à l'avance à chaque question ! Ils évolueront à chaque nouvelle réponse.
publicodes.ActionVignette.questionsRestantesText: '{{nbRemainingQuestions}} pregunta{{pluralSuffix}} restante{{pluralSuffix}}'
publicodes.ActionVignette.questionsRestantesText.lock: '{{nbRemainingQuestions}} question{{pluralSuffix}} restante{{pluralSuffix}}'
minutes: minutos
@@ -1522,3 +1522,5 @@ entries:
La valeur maximum pour ce champ est de: El valor máximo de este campo es
La valeur pour ce champ est comprise entre: El valor de este campo está comprendido entre
En participant vous acceptez que vos résultats soient partagés anonymement avec cette organisation.: Al participar, acepta que sus resultados se compartan de forma anónima con esta organización.
d'eau / jour: de agua / día
de CO₂e / an: de CO₂e / año
Loading