Skip to content

Commit 8b00c4b

Browse files
committed
feat: detector improvements
1 parent e5083ae commit 8b00c4b

30 files changed

Lines changed: 721 additions & 115 deletions
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import TranslationProvider from 'src/providers/TranslationProvider'
2+
import DetecteurPage from 'src/views/DetecteurPage'
3+
import Exemples from 'components/outils/detecteur/Exemples'
4+
5+
const page = () => {
6+
return (
7+
<TranslationProvider>
8+
<Exemples />
9+
<DetecteurPage />
10+
</TranslationProvider>
11+
)
12+
}
13+
14+
export default page

detection/index-async.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import { RandomCategory } from 'components/comparateur/randomEtiquette'
12
import { initMatomo, start } from './start'
23

34
initMatomo()
@@ -6,7 +7,12 @@ const element = document.getElementById('script-detecteur-impact-co2')
67
if (element) {
78
const search = new URLSearchParams(element.dataset.search || '')
89
// @ts-expect-error: adding on purpose
9-
window.impactCO2Detection = () => start(search.get('theme') === 'night', search.get('language') as 'fr' | 'en')
10+
window.impactCO2Detection = () =>
11+
start(
12+
search.get('theme') === 'night',
13+
search.get('language') as 'fr' | 'en',
14+
search.get('category') as RandomCategory
15+
)
1016
} else {
1117
// @ts-expect-error: adding on purpose
1218
window.impactCO2Detection = start

detection/index.ts

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,25 @@
1+
import { RandomCategory } from 'components/comparateur/randomEtiquette'
12
import { initMatomo, start } from './start'
23

34
initMatomo()
45

56
const element = document.getElementById('script-detecteur-impact-co2')
67
if (element) {
78
const search = new URLSearchParams(element.dataset.search || '')
8-
start(search.get('theme') === 'night', search.get('language') as 'fr' | 'en')
9-
setTimeout(() => start(search.get('theme') === 'night', search.get('language') as 'fr' | 'en'), 2000)
9+
start(
10+
search.get('theme') === 'night',
11+
search.get('language') as 'fr' | 'en',
12+
search.get('category') as RandomCategory
13+
)
14+
setTimeout(
15+
() =>
16+
start(
17+
search.get('theme') === 'night',
18+
search.get('language') as 'fr' | 'en',
19+
search.get('category') as RandomCategory
20+
),
21+
2000
22+
)
1023
} else {
1124
start()
1225
setTimeout(start, 2000)

detection/start.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
import React, { render } from 'preact/compat'
22
import 'utils/variables.css'
3+
import { RandomCategory } from 'components/comparateur/randomEtiquette'
34
import Detector, { regexs } from 'components/externalModules/detection/Detector'
45
import './style.css'
56

67
const className = 'impactCO2-container'
78
const forbiddenTag = ['TITLE', 'HEAD', 'STYLE', 'SCRIPT', 'path', 'IMG', 'META', 'BUTTON', 'A']
89

9-
const transform = (element: Element, language: 'fr' | 'en', darkMode?: boolean) => {
10+
const transform = (element: Element, language: 'fr' | 'en', category: RandomCategory, darkMode?: boolean) => {
1011
if (forbiddenTag.includes(element.tagName) || element.getAttribute('impactCO2') === 'managed') {
1112
return
1213
}
@@ -25,14 +26,14 @@ const transform = (element: Element, language: 'fr' | 'en', darkMode?: boolean)
2526
const after = document.createElement('DIV')
2627
after.className = className
2728
after.innerHTML = existingValues[1]
28-
transform(after, language, darkMode)
29-
render(React.createElement(Detector, { impact: hasImpact[0], language }), etiquette)
29+
transform(after, language, category, darkMode)
30+
render(React.createElement(Detector, { impact: hasImpact[0], language, category }), etiquette)
3031
element.setAttribute('impactCO2', 'managed')
3132
element.replaceChildren(before, etiquette, after)
3233
}
3334
}
3435

35-
const transformText = (element: Element, language: 'fr' | 'en', darkMode?: boolean) => {
36+
const transformText = (element: Element, language: 'fr' | 'en', category: RandomCategory, darkMode?: boolean) => {
3637
;[...element.childNodes.values()]
3738
.filter((child) => child.nodeName === '#text')
3839
.forEach((child) => {
@@ -51,8 +52,8 @@ const transformText = (element: Element, language: 'fr' | 'en', darkMode?: boole
5152
const after = document.createElement('DIV')
5253
after.className = className
5354
after.innerHTML = existingValues[1]
54-
transform(after, language, darkMode)
55-
render(React.createElement(Detector, { impact: hasImpact[0], language }), etiquette)
55+
transform(after, language, category, darkMode)
56+
render(React.createElement(Detector, { impact: hasImpact[0], language, category }), etiquette)
5657
child.replaceWith(before, etiquette, after)
5758
}
5859
}
@@ -91,7 +92,7 @@ export const initMatomo = () => {
9192
}
9293
}
9394

94-
export const start = (darkMode?: boolean, language?: 'fr' | 'en') => {
95+
export const start = (darkMode?: boolean, language?: 'fr' | 'en', category?: RandomCategory) => {
9596
const elems = document.querySelectorAll('*')
9697

9798
Array.from(elems)
@@ -128,12 +129,12 @@ export const start = (darkMode?: boolean, language?: 'fr' | 'en') => {
128129
child.nodeName === 'STRONG'
129130
)
130131
) {
131-
transform(elem, language || 'fr', darkMode)
132+
transform(elem, language || 'fr', category || 'all', darkMode)
132133
} else {
133134
;[...elem.children].forEach((child) => {
134-
transform(child, language || 'fr', darkMode)
135+
transform(child, language || 'fr', category || 'all', darkMode)
135136
})
136-
transformText(elem, language || 'fr', darkMode)
137+
transformText(elem, language || 'fr', category || 'all', darkMode)
137138
}
138139
} catch (e) {
139140
console.error('Impossible de générer les équivalents', e)

public/images/detecteur-co2.jpg

-81.6 KB
Binary file not shown.

public/images/detecteur-co2.png

86.5 KB
Loading

src/components/cards/tools.tsx

Lines changed: 2 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import Image from 'next/image'
1+
import DetectorInformation from 'components/outils/DetectorInformation'
22
import DetectorScript from 'components/outils/DetectorScript'
33

44
export const tools = [
@@ -133,29 +133,7 @@ export const smallTools = [
133133
description: 'L’outil pratique pour mettre en lumière vos données carbone.',
134134
meta: 'Valoriser et mieux faire comprendre les données carbones grâce au détecteur CO2 qui communique les bons ordres de grandeur',
135135
linkLabel: 'Découvrir',
136-
content: (
137-
<>
138-
<p>
139-
Impact CO₂ lance le détecteur CO₂, un nouveau format innovant pour détecter et surligner automatiquement les
140-
mentions de données carbones dans vos contenus.
141-
</p>
142-
<p>
143-
Cet <b>outil gratuit</b>, simple d’utilisation et basé sur les données de l’ADEME a vocation à s’intégrer sur
144-
les sites internet de médias, d’entreprises ou d’associations pour{' '}
145-
<b>vulgariser les bons ordres de grandeur et remettre en perspective les données carbones.</b>
146-
</p>
147-
<p>Un exemple vaut mieux que mille mots ! Découvrez par vous-même 👇</p>
148-
<p>
149-
<b>
150-
L’Info Durable est le premier média spécialisé en développement durable à avoir intégré l’outil sur son site
151-
internet (plus de 45 000 articles en ligne !).
152-
</b>
153-
</p>
154-
<div>
155-
<Image src='/images/detecteur-co2.jpg' alt='' width={680} height={208} />
156-
</div>
157-
</>
158-
),
136+
content: <DetectorInformation />,
159137
script: <DetectorScript />,
160138
},
161139
]

src/components/comparateur/randomEtiquette.ts

Lines changed: 46 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,50 @@
1-
const defaultEquivalents = [
2-
{ max: 1000, equivalents: [['tgv'], ['eaudurobinet'], ['pomme']] },
3-
{
4-
max: 50000,
5-
equivalents: [
6-
['friends', 'game-of-thrones'],
7-
['tgv-paris-berlin', 'tgv-paris-marseille'],
8-
['repasvegetarien', 'repasvegetalien'],
9-
['tomate', 'abricot', 'avocat'],
10-
],
11-
},
12-
{
13-
min: 50000,
14-
max: 500000,
15-
equivalents: [
16-
['repasavecduboeuf'],
17-
['voiture-lille-nimes', 'voiturethermique'],
18-
['smartphone', 'tabletteclassique'],
19-
],
20-
},
21-
{ min: 500000, equivalents: [['avion-pny'], ['francais'], ['ordinateurfixeparticulier', 'ordinateurportable']] },
22-
]
1+
const defaultEquivalents = {
2+
all: [
3+
{ max: 1_000, equivalents: [['tgv'], ['eaudurobinet'], ['pomme'], ['email']] },
4+
{
5+
max: 50_000,
6+
equivalents: [
7+
['friends', 'game-of-thrones'],
8+
['tgv-paris-berlin', 'tgv-paris-marseille', 'voiturethermique'],
9+
['repasvegetarien', 'repasvegetalien'],
10+
['tomate', 'abricot', 'avocat'],
11+
],
12+
},
13+
{
14+
min: 50000,
15+
max: 500_000,
16+
equivalents: [
17+
['repasavecduboeuf'],
18+
['voiture-lille-nimes', 'voiturethermique'],
19+
['smartphone', 'tabletteclassique'],
20+
],
21+
},
22+
{
23+
min: 500_000,
24+
max: 10_000_000,
25+
equivalents: [['avion-pny'], ['francais'], ['ordinateurfixeparticulier', 'ordinateurportable']],
26+
},
27+
],
28+
transport: [],
29+
voiture: [
30+
{
31+
min: 1_000,
32+
max: 10_000_000,
33+
equivalents: [['voiturethermique']],
34+
},
35+
{
36+
min: 10_000_000,
37+
max: 10_000_000_000,
38+
equivalents: [['terre-voiture']],
39+
},
40+
],
41+
numerique: [],
42+
}
43+
44+
export type RandomCategory = keyof typeof defaultEquivalents
2345

24-
export const getRandomEquivalentForValue = (value: number) => {
25-
const equivalents = defaultEquivalents.find(
46+
export const getRandomEquivalentForValue = (value: number, category?: RandomCategory) => {
47+
const equivalents = defaultEquivalents[category || 'all'].find(
2648
(equivalent) => (!equivalent.min || equivalent.min < value) && (!equivalent.max || equivalent.max >= value)
2749
)
2850

src/components/externalModules/SimpleValue.tsx

Lines changed: 67 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,58 @@ import formatNumber from 'utils/formatNumber'
99
import EquivalentIcon from 'components/base/EquivalentIcon'
1010
import LocalNumber from 'components/base/LocalNumber'
1111
import InfinityIcon from 'components/base/icons/infinity'
12+
import { RandomCategory } from 'components/comparateur/randomEtiquette'
1213
import styles from './SimpleValue.module.css'
1314

14-
const equivalents = values as Record<string, SimpleEquivalent>
15+
const allEquivalents = values as Record<string, SimpleEquivalent>
16+
const transportEquivalents = [
17+
'tgv-paris-berlin',
18+
'tgv-paris-marseille',
19+
'avion-pny',
20+
'voiture-lille-nimes',
21+
'terre-voiture',
22+
'trainenfrancejour',
23+
'voiturefrancaiseheure',
24+
'voiturefrancaisejour',
25+
'aviationcivileenfrance',
26+
'voiturefrancaisean',
27+
]
28+
const voitureEquivalents = [
29+
'voiturethermique',
30+
'terre-voiture',
31+
'voiturefrancaiseheure',
32+
'voiturefrancaisejour',
33+
'voiturefrancaisean',
34+
]
35+
const numeriqueEquivalents = [
36+
'game-of-thrones',
37+
'friends',
38+
'harry-potter',
39+
'datacenterjour',
40+
'numeriqueenfrance',
41+
'numeriqueenfrancejour',
42+
]
1543

16-
export const getValues = (comparison: string, value: number) => {
44+
const equivalentCategories: Record<RandomCategory, Record<string, SimpleEquivalent>> = {
45+
all: allEquivalents,
46+
transport: Object.fromEntries(
47+
Object.entries(allEquivalents).filter(
48+
([key, equivalent]) => transportEquivalents.includes(key) || equivalent.category === 4
49+
)
50+
),
51+
voiture: Object.fromEntries(Object.entries(allEquivalents).filter(([key]) => voitureEquivalents.includes(key))),
52+
numerique: Object.fromEntries(
53+
Object.entries(allEquivalents).filter(
54+
([key, equivalent]) =>
55+
numeriqueEquivalents.includes(key) || equivalent.category === 1 || equivalent.category === 10
56+
)
57+
),
58+
}
59+
60+
export const getValues = (comparison: string, value: number, category?: RandomCategory) => {
1761
const [slug, carpool] = comparison.split('+')
18-
if (comparison !== 'random' && equivalents[slug]) {
62+
const equivalents = category ? equivalentCategories[category] : allEquivalents
63+
if (comparison !== 'random' && allEquivalents[slug]) {
1964
const equivalent = equivalents[slug]
2065
return {
2166
equivalent: {
@@ -26,7 +71,12 @@ export const getValues = (comparison: string, value: number) => {
2671
slug,
2772
}
2873
}
29-
const meaningfullEquivalents = Object.entries(equivalents).filter(([, ecv]) => value / ecv.value > 1 && ecv.value > 0)
74+
const meaningfullEquivalents = Object.entries(equivalents).filter(
75+
([, ecv]) => value / ecv.value >= 1 && value / ecv.value <= 99_999 && ecv.value > 0
76+
)
77+
if (meaningfullEquivalents.length === 0) {
78+
return null
79+
}
3080
const categories = [...new Set(meaningfullEquivalents.map((equivalent) => equivalent[1].category))]
3181
const randomCategory = categories[Math.floor(Math.random() * categories.length)]
3282
const categoryEquivalents = meaningfullEquivalents.filter((equivalent) => equivalent[1].category === randomCategory)
@@ -39,22 +89,30 @@ const SimpleValue = ({
3989
comparison,
4090
language,
4191
id,
92+
category,
4293
}: {
4394
value: number
4495
comparison: string
4596
language: Language
4697
id?: string
98+
category?: RandomCategory
4799
}) => {
48-
const [values, setValues] = useState<{ equivalent: SimpleEquivalent; slug: string } | undefined>(
49-
comparison === 'random' ? undefined : getValues(comparison, value)
100+
const [values, setValues] = useState<{ equivalent: SimpleEquivalent; slug: string } | null>(
101+
comparison === 'random' ? null : getValues(comparison, value, category)
50102
)
51103

52104
useEffect(() => {
53-
setValues(getValues(comparison, value))
54-
}, [comparison, value])
105+
setValues(getValues(comparison, value, category))
106+
}, [comparison, value, category])
55107

56108
if (!values) {
57-
return null
109+
return (
110+
<p className={classNames(styles.label, 'impactCO2-etiquette-text')}>
111+
{language === 'en'
112+
? 'No equivalent available for this amount'
113+
: 'Aucun équivalent disponible pour cette quantité'}
114+
</p>
115+
)
58116
}
59117

60118
const comparisonValue = ((values.equivalent.percentage ? 100 : 1) * value) / values.equivalent.value

0 commit comments

Comments
 (0)