diff --git a/src/components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year-by-year.js b/src/components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year-by-year.js new file mode 100644 index 00000000..5f69560b --- /dev/null +++ b/src/components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year-by-year.js @@ -0,0 +1,84 @@ +import '../../../graph.scss'; + +import Highcharts from 'highcharts'; +import HCExportingData from 'highcharts/modules/export-data'; +import HCExporting from 'highcharts/modules/exporting'; +import HighchartsReact from 'highcharts-react-official'; +import PropTypes from 'prop-types'; +import React, { useEffect, useRef, useState } from 'react'; +import { useIntl } from 'react-intl'; + +import customComments from '../../../../../utils/chartComments'; +import { chartOptions } from '../../../../../utils/chartOptions'; +import { + domains, + graphIds, + studiesTypes, +} from '../../../../../utils/constants'; +import { withDomain, withtStudyType } from '../../../../../utils/helpers'; +import WrapperChart from '../../../../WrapperChart'; +import GraphComments from '../../../graph-comments'; +import useGetData from './get-data'; + +HCExporting(Highcharts); +HCExportingData(Highcharts); + +const Chart = ({ domain, hasComments, hasFooter, id, studyType }) => { + const chartRef = useRef(); + const intl = useIntl(); + const [chartComments, setChartComments] = useState(''); + const { allData, isError, isLoading } = useGetData(studyType); + const { dataGraph6 } = allData; + const idWithDomain = withDomain(id, domain); + const idWithDomainAndStudyType = withtStudyType(idWithDomain, studyType); + const optionsGraph = chartOptions[id].getOptions( + idWithDomain, + intl, + dataGraph6, + studyType, + ); + + useEffect(() => { + setChartComments(customComments(allData, idWithDomainAndStudyType, intl)); + }, [allData, idWithDomainAndStudyType, intl]); + + return ( + + + {hasComments && chartComments && ( + + )} + + ); +}; + +Chart.defaultProps = { + domain: 'health', + hasComments: true, + hasFooter: true, + id: 'general.dynamique.chart-evolution-within-1-year-by-year', + studyType: 'Interventional', +}; +Chart.propTypes = { + domain: PropTypes.oneOf(domains), + hasComments: PropTypes.bool, + hasFooter: PropTypes.bool, + id: PropTypes.oneOf(graphIds), + studyType: PropTypes.oneOf(studiesTypes), +}; + +export default Chart; diff --git a/src/components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year.js b/src/components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year.js index 783906ff..c9dd36b0 100644 --- a/src/components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year.js +++ b/src/components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year.js @@ -45,7 +45,7 @@ const Chart = ({ domain, hasComments, hasFooter, id, studyType }) => { return ( ele.key === 1) - ?.by_completion_year.buckets.find((ele) => ele.key === yearMax2); + ?.by_completion_year.buckets.find((ele) => ele.key === yearMax); const academicWithout4 = academic4?.by_has_results_within_1_year.buckets .find((ele) => ele.key === 0) - ?.by_completion_year.buckets.find((ele) => ele.key === yearMax2); + ?.by_completion_year.buckets.find((ele) => ele.key === yearMax); const academicTotal4 = (academicWith4?.doc_count || 0) + (academicWithout4?.doc_count || 0); const indus = data1.by_sponsor_type.buckets.find( (ele) => ele.key === 'industriel', @@ -99,10 +99,10 @@ function useGetData(studyType, sponsor = '*') { ); const indusWith4 = indus4?.by_has_results_within_1_year.buckets .find((el) => el.key === 1) - ?.by_completion_year.buckets.find((ele) => ele.key === yearMax2); + ?.by_completion_year.buckets.find((ele) => ele.key === yearMax); const indusWithout4 = indus4?.by_has_results_within_1_year.buckets .find((el) => el.key === 0) - ?.by_completion_year.buckets.find((ele) => ele.key === yearMax2); + ?.by_completion_year.buckets.find((ele) => ele.key === yearMax); const indusTotal4 = (indusWith4?.doc_count || 0) + (indusWithout4?.doc_count || 0); const spons = data2; const sponsWith = spons?.by_has_result.buckets.find((el) => el.key === 1); @@ -179,7 +179,7 @@ function useGetData(studyType, sponsor = '*') { y: allLeadSponsorRate4, y_abs: (academicWith4?.doc_count ?? 0) + (indusWith4?.doc_count ?? 0), y_tot: academicTotal4 + indusTotal4, - yearMax: yearMax2, + yearMax, }); const publicLeadSponsorsRate4 = 100 * ((academicWith4?.doc_count ?? 0) / academicTotal4); series4[0].data.push({ @@ -188,7 +188,7 @@ function useGetData(studyType, sponsor = '*') { y: publicLeadSponsorsRate4, y_abs: academicWith4?.doc_count ?? 0, y_tot: academicTotal4, - yearMax: yearMax2, + yearMax, }); const privateLeadSponsorsRate4 = 100 * ((indusWith4?.doc_count ?? 0) / indusTotal4); series4[0].data.push({ @@ -197,7 +197,7 @@ function useGetData(studyType, sponsor = '*') { y: privateLeadSponsorsRate4, y_abs: indusWith4?.doc_count ?? 0, y_tot: indusTotal4, - yearMax: yearMax2, + yearMax, }); if (sponsor !== '*') { series1[0].data.push({ @@ -224,8 +224,7 @@ function useGetData(studyType, sponsor = '*') { y: 100 * ((sponsWith?.doc_count ?? 0) / spons?.doc_count), y_abs: sponsWith?.doc_count ?? 0, y_tot: spons?.doc_count ?? 0, - yearMax: yearMax2, - yearMin: yearMin2, + yearMax, }); categories.push(sponsor); } @@ -334,6 +333,107 @@ function useGetData(studyType, sponsor = '*') { ]; const dataGraph5 = { categories: categories5, series: series5 }; + const categories6 = data4.by_sponsor_type.buckets[0].by_has_results_within_1_year.buckets[0].by_completion_year.buckets + .sort((a, b) => a.key - b.key) + .filter((y) => y.key >= 2010 && y.key <= currentYear) + .map((item) => item.key); + const academic6 = data4.by_sponsor_type.buckets.find( + (item) => item.key === 'academique', + ); + const academicData6 = []; + const industrial6 = data4.by_sponsor_type.buckets.find( + (item) => item.key === 'industriel', + ); + const industrialData6 = []; + const allTypesData6 = []; + + categories6.forEach((year) => { + const academicDataWithResultsForYear = academic6?.by_has_results_within_1_year?.buckets + ?.find((item) => item.key === 1) + ?.by_completion_year.buckets?.find((item) => item.key === year) + ?.doc_count ?? 0; + const academicDataWithoutResultsForYear = academic6?.by_has_results_within_1_year?.buckets + ?.find((item) => item.key === 0) + ?.by_completion_year.buckets?.find((item) => item.key === year) + ?.doc_count ?? 0; + const industrialDataWithResultsForYear = industrial6?.by_has_results_within_1_year?.buckets + ?.find((item) => item.key === 1) + ?.by_completion_year.buckets?.find((item) => item.key === year) + ?.doc_count ?? 0; + const industrialDataWithoutResultsForYear = industrial6?.by_has_results_within_1_year?.buckets + ?.find((item) => item.key === 0) + ?.by_completion_year.buckets?.find((item) => item.key === year) + ?.doc_count ?? 0; + academicData6.push({ + y: + 100 + * (academicDataWithResultsForYear + / (academicDataWithResultsForYear + + academicDataWithoutResultsForYear)), + y_abs: academicDataWithResultsForYear, + y_tot: + academicDataWithResultsForYear + academicDataWithoutResultsForYear, + year, + }); + industrialData6.push({ + year, + y: + 100 + * (industrialDataWithResultsForYear + / (industrialDataWithResultsForYear + + industrialDataWithoutResultsForYear)), + y_abs: industrialDataWithResultsForYear, + y_tot: + industrialDataWithResultsForYear + + industrialDataWithoutResultsForYear, + yearMax, + yearMin, + }); + allTypesData6.push({ + year, + y: + 100 + * ((academicDataWithResultsForYear + industrialDataWithResultsForYear) + / (academicDataWithResultsForYear + + academicDataWithoutResultsForYear + + industrialDataWithResultsForYear + + industrialDataWithoutResultsForYear)), + y_abs: + academicDataWithResultsForYear + industrialDataWithResultsForYear, + y_tot: + academicDataWithResultsForYear + + academicDataWithoutResultsForYear + + industrialDataWithResultsForYear + + industrialDataWithoutResultsForYear, + yearMax, + yearMin, + }); + }); + + const series6 = [ + { + id: 'public', + color: getCSSValue('--lead-sponsor-public'), + data: academicData6, + name: capitalize(intl.formatMessage({ id: 'app.sponsor.academique' })), + pointPlacement: -0.2, + }, + { + id: 'prive', + color: getCSSValue('--lead-sponsor-privee'), + data: industrialData6, + name: capitalize(intl.formatMessage({ id: 'app.sponsor.industriel' })), + }, + { + id: 'main', + color: getCSSValue('--blue-soft-100'), + data: allTypesData6, + name: capitalize(intl.formatMessage({ id: 'app.all-sponsor-types' })), + pointPlacement: 0.2, + }, + ]; + const dataGraph6 = { categories: categories6, series: series6 }; + let allLeadSponsorRate = ''; let privateLeadSponsorsRate = ''; let publicLeadSponsorsRate = ''; @@ -366,6 +466,7 @@ function useGetData(studyType, sponsor = '*') { privateLeadSponsorsRate3: privateLeadSponsorsRate3.toFixed(0), publicLeadSponsorsRate, publicLeadSponsorsRate3: publicLeadSponsorsRate3.toFixed(0), + yearMax, yearMin2, yearMax2, }; @@ -376,6 +477,7 @@ function useGetData(studyType, sponsor = '*') { dataGraph3, dataGraph4, dataGraph5, + dataGraph6, }; } diff --git a/src/pages/BaroSante/EssaisCliniques/index.js b/src/pages/BaroSante/EssaisCliniques/index.js index c7ede75c..c0b4caef 100644 --- a/src/pages/BaroSante/EssaisCliniques/index.js +++ b/src/pages/BaroSante/EssaisCliniques/index.js @@ -124,6 +124,12 @@ function EssaisCliniques() { isDisplayed={!isInProduction()} studyType='Interventional' /> + Essais cliniques terminés en {point.yearMax}
{point.name}
{point.y:.2f} % des essais cliniques enregistrés ont posté un résultat
et/ou déclaré une publication scientifique dans l'année après la fin de l'essai clinique ({point.y_abs} / {point.y_tot}).", "app.health-interventional.general.dynamique.chart-evolution-within-1-year.comments": "L'observation de la part d'essais cliniques terminés qui ont posté ou publié des résultats dans l'année après la fin de l'essai clinique s'élève à {allLeadSponsorRate3} %. Ces valeurs sont faibles. Elles sont plus élevées chez les promoteurs industriels ({privateLeadSponsorsRate3} %), tandis qu'elles sont basses chez les promoteurs publiés qui partagent beaucoup moins leurs résultats ({publicLeadSponsorsRate3} %)", + "app.health-interventional.general.dynamique.chart-evolution-within-1-year-by-year.title": "Part d'essais cliniques enregistrés et terminés ayant posté un résultat et/ou déclaré une publication scientifique dans l'année après la fin de l'essai clinique par année de fin", + "app.health-interventional.general.dynamique.chart-evolution-within-1-year-by-year.tooltip": "Essais cliniques terminés en {point.year}
{point.name}

{point.y:.2f} % des essais cliniques enregistrés ont posté un résultat
et/ou déclaré une publication scientifique dans l'année après la fin de l'essai clinique par année de fin ({point.y_abs} / {point.y_tot}).", "app.health-interventional.general.sankey.Active, not recruiting.label": "Actif, ne recrute plus", "app.health-interventional.general.sankey.Completed.label": "Essais cliniques enregistrés publiquement
et terminés", "app.health-interventional.general.sankey.Enrolling by invitation.label": "Sur invitation", diff --git a/src/utils/chartComponents.js b/src/utils/chartComponents.js index 61874397..96043e53 100644 --- a/src/utils/chartComponents.js +++ b/src/utils/chartComponents.js @@ -153,6 +153,9 @@ const ChartEvolutionWithin3YearsByYearStudies = lazy(() => import( const ChartEvolutionWithin1YearStudies = lazy(() => import( '../components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year' )); +const ChartEvolutionWithin1YearByYearStudies = lazy(() => import( + '../components/Charts/studies/general/dynamique-ouverture/chart-evolution-within-1-year-by-year' +)); const ChartRepartitionStudies = lazy(() => import('../components/Charts/studies/general/trajectoires/chart-repartition')); const ChartDynamiqueNombreStudies = lazy(() => import( '../components/Charts/studies/promoteurs/dynamique-ouverture/chart-evolution-nombre' @@ -384,6 +387,8 @@ const chartComponents = { ChartEvolutionWithin3YearsByYearStudies, 'general.dynamique.chart-evolution-within-1-year': ChartEvolutionWithin1YearStudies, + 'general.dynamique.chart-evolution-within-1-year-by-year': + ChartEvolutionWithin1YearByYearStudies, 'general.trajectoires.chart-repartition': ChartRepartitionStudies, 'caracteristiques.quand.chart-evolution-temporalites': ChartEvolutionTemporalitesStudies, diff --git a/src/utils/chartOptions.js b/src/utils/chartOptions.js index c85e9eb0..99dcd35c 100644 --- a/src/utils/chartOptions.js +++ b/src/utils/chartOptions.js @@ -2403,6 +2403,51 @@ export const chartOptions = { return options; }, }, + 'general.dynamique.chart-evolution-within-1-year-by-year': { + getOptions: (id, intl, data, studyType, dataTitle) => { + const options = getGraphOptions({ id, intl, studyType, dataTitle }); + options.chart = { + type: 'bar', + height: '950px', + }; + options.plotOptions = { + series: { + grouping: false, + dataLabels: { + enabled: false, + }, + pointWidth: 15, + }, + bar: { + dataLabels: { + enabled: true, + format: '{point.y:.0f} %', + }, + }, + }; + options.yAxis = getPercentageYAxis(true); + options.xAxis = { + type: 'category', + categories: data?.categories || [], + title: { + text: intl.formatMessage({ id: 'app.study-completion-year' }), + }, + lineWidth: 0, + tickWidth: 0, + reversed: false, + labels: { + style: { + color: getCSSValue('--g800'), + fontSize: '12px', + fontWeight: 'bold', + }, + }, + }; + options.legend.reversed = true; + options.series = data?.series || []; + return options; + }, + }, 'general.trajectoires.chart-repartition': { getOptions: (id, intl, data, studyType) => { const nodeColor = {