Ajoute un lien vers le simulateur selectionné

pull/1411/head^2
Johan Girod 2021-03-15 15:19:02 +01:00
parent fe8ebfa739
commit 28e29fb7b9
9 changed files with 340 additions and 3828 deletions

View File

@ -9,7 +9,7 @@
require('dotenv').config()
require('isomorphic-fetch')
const { map, filter, flatten, partition } = require('ramda')
const { map, filter, flatten, partition, pipe } = require('ramda')
const { compose } = require('redux')
const { createDataDir, writeInDataDir } = require('./utils.js')
const matomoSiteVisitsHistory = require('./matomoVisitHistory.json')
@ -157,12 +157,15 @@ const last36Months = {
.slice(0, 8) + '01',
end: yesterday,
}
const uniformiseData = map(
({ d_evo_day, d_evo_month, m_visits, m_events, ...data }) => ({
const uniformiseData = pipe(
// For some reason, an artifact create ghost page with unlogical chapter metrics...
// It seems to only by one per month thought... This hacks resolves it
filter(({ m_visits }) => m_visits === undefined || m_visits > 2),
map(({ d_evo_day, d_evo_month, m_visits, m_events, ...data }) => ({
date: d_evo_day != null ? d_evo_day : d_evo_month,
nombre: m_visits != null ? m_visits : m_events,
...data,
})
}))
)
const flattenPage = compose(
flatten,

File diff suppressed because it is too large Load Diff

View File

@ -49,17 +49,7 @@ export default function Simulation({
<Questions customEndMessages={customEndMessages} />
<br />
<div className="ui__ full-width">
<div
css={`
display: flex;
flex-direction: column;
align-items: center;
@media (min-width: 1200px) {
flex-direction: row;
align-items: baseline;
}
`}
>
<div className="ui__ container-and-side-block">
{explanations && (
<>
<div
@ -78,18 +68,8 @@ export default function Simulation({
</>
)}
<div
css={`
margin-top: 1rem;
@media (min-width: 1200px) {
flex-grow: 0;
flex-shrink: 1;
flex: 1;
display: flex;
${!explanations && 'justify-content: center;'}
position: sticky;
top: 1rem;
}
`}
className="ui__ side-block"
css={!explanations ? 'justify-content: center;' : ''}
>
<div
css={`

View File

@ -0,0 +1,80 @@
section {
padding: 1rem 0;
}
.ui__.container {
width: 100%;
max-width: 850px;
margin-right: auto;
margin-left: auto;
padding-right: 0.6rem;
padding-left: 0.6rem;
}
.ui__.container .ui__.full-width {
--margin: calc((850px - 100vw - 0.6rem) / 2);
margin-right: var(--margin);
margin-left: var(--margin);
}
@media (max-width: 850px) {
.ui__.container .ui__.full-width {
margin: 0 -0.6rem;
}
}
.ui__.container-and-side-block {
display: flex;
flex-direction: column;
align-items: center;
}
.ui__.container-and-side-block > .container {
flex-shrink: 0;
}
@media (min-width: 1200px) {
.ui__.container-and-side-block {
flex-direction: row;
align-items: flex-start;
}
}
.ui__.side-block {
margin-top: 1rem;
display: flex;
flex-direction: column;
}
@media (max-width: 1200px) {
.ui__.side-block {
align-self: center;
}
}
@media (min-width: 1200px) {
.ui__.side-block {
flex-grow: 0;
flex-shrink: 1;
flex: 1;
position: sticky;
top: 1rem;
}
}
.ui__.answer-group {
display: flex;
align-items: center;
justify-content: flex-end;
}
@media (min-width: 500px) {
.ui__.answer-group > :not(:last-child) {
margin-right: 1rem;
}
}
@media (max-width: 500px) {
.ui__.answer-group {
flex-wrap: wrap;
}
.ui__.answer-group > * {
flex: 1;
white-space: nowrap;
margin: 0.5rem !important;
}
}

View File

@ -4,6 +4,7 @@
@import './Toggle.css';
@import './reset.css';
@import './Fonts.css';
@import './Layout.css';
:root {
--color: rgb(41, 117, 209);
@ -47,27 +48,6 @@ blockquote {
color: var(--darkerColor);
}
.ui__.answer-group {
display: flex;
align-items: center;
justify-content: flex-end;
}
@media (min-width: 500px) {
.ui__.answer-group > :not(:last-child) {
margin-right: 1rem;
}
}
@media (max-width: 500px) {
.ui__.answer-group {
flex-wrap: wrap;
}
.ui__.answer-group > * {
flex: 1;
white-space: nowrap;
margin: 0.5rem !important;
}
}
.ui__.light-bg {
background-color: var(--lighterColor) !important;
}
@ -103,29 +83,6 @@ blockquote {
}
}
section {
padding: 1rem 0;
}
.ui__.container {
width: 100%;
max-width: 850px;
margin-right: auto;
margin-left: auto;
padding-right: 0.6rem;
padding-left: 0.6rem;
}
.ui__.container .ui__.full-width {
--margin: calc((850px - 100vw - 0.6rem) / 2);
margin-right: var(--margin);
margin-left: var(--margin);
}
@media (max-width: 850px) {
.ui__.container .ui__.full-width {
margin: 0 -0.6rem;
}
}
ul.ui__.no-bullet {
list-style: none;
}

View File

@ -13,6 +13,7 @@ import { Trans } from 'react-i18next'
import { useDispatch, useSelector } from 'react-redux'
import { SimulationConfig } from 'Reducers/rootReducer'
import { situationSelector } from 'Selectors/simulationSelectors'
import { TrackPage } from '../../ATInternetTracking'
const ISConfig = {
'unité par défaut': '€/an',
@ -90,7 +91,7 @@ function Explanations() {
const situation = useSelector(situationSelector)
const showResult = situation['entreprise . bénéfice']
if (!showResult) {
return null
return <TrackPage name="accueil" />
}
return (
<Animate.fromTop>
@ -107,6 +108,7 @@ function Explanations() {
}
`}
>
<TrackPage name="simulation terminée" />
<strong>
<Value
expression="entreprise . impôt sur les sociétés"

View File

@ -846,7 +846,6 @@ export function getSimulatorsData({
is: {
icône: '🗓',
tracking: 'impot-societe',
path: sitePaths.simulateurs.is,
iframe: 'impot-societe',
meta: {

View File

@ -11,8 +11,6 @@ import {
XAxis,
} from 'recharts'
type Period = 'mois' | 'jours'
type SatisfactionChartProps = {
data: Array<{
date: string

View File

@ -12,25 +12,37 @@ import styled from 'styled-components'
import { TrackPage } from '../../ATInternetTracking'
import stats from '../../data/stats.json'
import { debounce } from '../../utils'
import { SimulateurCard } from '../Simulateurs/Home'
import useSimulatorsData, { SimulatorData } from '../Simulateurs/metadata'
import Chart from './Chart'
import DemandeUtilisateurs from './DemandesUtilisateurs'
import SatisfactionChart from './SatisfactionChart'
type Period = 'mois' | 'jours'
type Chapter2 = typeof stats.visitesJours.pages[number]['page_chapter2']
type Chapter2 = typeof stats.visitesJours.pages[number]['page_chapter2'] | 'PAM'
const chapters2: Chapter2[] = [
...new Set(stats.visitesMois.pages.map((p) => p.page_chapter2)),
'PAM',
]
type Data =
| Array<{ date: string; nombre: number }>
| Array<{ date: string; nombre: Record<string, number> }>
const isPAM = (name: string | undefined) =>
name &&
[
'medecin',
'chirurgien_dentiste',
'auxiliaire_medical',
'sage_femme',
].includes(name)
const filterByChapter2 = (
data: Array<{
date: string
page_chapter2: string
page_chapter3?: string
page?: string
click?: string
}>,
@ -39,7 +51,13 @@ const filterByChapter2 = (
return toPairs(
groupBy(
(p) => p.date,
data.filter((p) => !chapter2 || p.page_chapter2 === chapter2)
data.filter(
(p) =>
!chapter2 ||
(p.page !== 'accueil_pamc' &&
(p.page_chapter2 === chapter2 ||
(chapter2 === 'PAM' && isPAM(p.page_chapter3))))
)
)
).map(([date, values]) => ({
date,
@ -116,8 +134,9 @@ export default function Stats() {
Les données recueillies sont anonymisées.{' '}
<Privacy label="En savoir plus" />
</p>
<p>
<strong>1. Sélectionner le périmètre : </strong>
<strong>1. Sélectionner la fonctionnalité : </strong>
</p>
<p>
<SimulateursChoice
@ -149,73 +168,86 @@ export default function Stats() {
</label>
))}
</p>
<div className="ui__ full-width">
<div className="ui__ container-and-side-block">
<div
className="ui__ side-block"
css={`
align-items: flex-end;
`}
>
<SelectedSimulator chapter2={chapter2} />
</div>
<div className="ui__ container">
<h2>Visites</h2>
<section>
<h2>Visites</h2>
<Chart
period={period}
data={visites}
onDateChange={handleDateChange}
startIndex={startDateIndex}
endIndex={endDateIndex}
/>
{period === 'mois' && !!satisfaction.length && (
<section>
<h2>Satisfaction</h2>
<SatisfactionChart key={chapter2} data={satisfaction} />
</section>
)}
<section>
<h2>
Cumuls pour la période{' '}
{period === 'jours'
? `du ${formatDay(slicedVisits[0].date)} au ${formatDay(
slicedVisits[slicedVisits.length - 1].date
)}`
: `de ${formatMonth(slicedVisits[0].date)}` +
(slicedVisits.length > 1
? ` à ${formatMonth(
slicedVisits[slicedVisits.length - 1].date
)}`
: '')}
</h2>
</section>
<Indicators>
<Indicator
main={formatValue(
typeof totals === 'number' ? totals : totals.accueil
<Chart
period={period}
data={visites}
onDateChange={handleDateChange}
startIndex={startDateIndex}
endIndex={endDateIndex}
/>
{period === 'mois' && !!satisfaction.length && (
<>
<h2>Satisfaction</h2>
<SatisfactionChart key={chapter2} data={satisfaction} />
</>
)}
subTitle="Visites"
/>
{typeof totals !== 'number' && 'simulation_commencee' in totals && (
<>
{' '}
<Indicator
main={formatValue(totals.simulation_commencee)}
subTitle="Simulations "
/>
<h2>
Cumuls pour la période{' '}
{period === 'jours'
? `du ${formatDay(slicedVisits[0].date)} au ${formatDay(
slicedVisits[slicedVisits.length - 1].date
)}`
: `de ${formatMonth(slicedVisits[0].date)}` +
(slicedVisits.length > 1
? ` à ${formatMonth(
slicedVisits[slicedVisits.length - 1].date
)}`
: '')}
</h2>
<Indicators>
<Indicator
main={formatValue(
Math.round(
(100 * totals.simulation_commencee) / totals.accueil
),
{ displayedUnit: '%' }
typeof totals === 'number' ? totals : totals.accueil
)}
subTitle={
<>
Taux de conversion{' '}
<InfoBulle>
Pourcentage de personne qui commencent une simulation
</InfoBulle>
</>
}
subTitle="Visites"
/>
</>
)}
</Indicators>
</section>
{typeof totals !== 'number' && 'simulation_commencee' in totals && (
<>
{' '}
<Indicator
main={formatValue(totals.simulation_commencee)}
subTitle="Simulations "
/>
<Indicator
main={formatValue(
Math.round(
(100 * totals.simulation_commencee) / totals.accueil
),
{ displayedUnit: '%' }
)}
subTitle={
<>
Taux de conversion&nbsp;
<InfoBulle>
Pourcentage de personne qui commencent une simulation
</InfoBulle>
</>
}
/>
</>
)}
</Indicators>
</div>
<div
css={`
flex: 1;
`}
/>
</div>
</div>
<DemandeUtilisateurs />
<MoreInfosOnUs />
</>
@ -268,11 +300,23 @@ function formatMonth(date: string | Date) {
}
function getChapter2(s: SimulatorData[keyof SimulatorData]): Chapter2 | '' {
if (s.iframe === 'pamc') {
return 'PAM'
}
if (!s.tracking) {
return ''
}
return typeof s.tracking === 'string' ? s.tracking : s.tracking.chapter2 ?? ''
}
function SelectedSimulator(props: { chapter2: Chapter2 }) {
const simulateur = Object.values(useSimulatorsData()).find(
(s) => getChapter2(s) === props.chapter2 && !s.tracking.chapter3
)
if (!simulateur) {
return null
}
return <SimulateurCard {...simulateur} />
}
function SimulateursChoice(props: {
onChange: (ch: Chapter2 | '') => void
@ -287,7 +331,6 @@ function SimulateursChoice(props: {
!(s.tracking as any).chapter3
)
})
console.log(props.possibleValues)
return (
<div
@ -297,6 +340,7 @@ function SimulateursChoice(props: {
margin-right: -0.4rem;
> * {
margin-bottom: 0.4rem;
margin-right: 0.4rem;
}
`}