@tekkare/romulus 0.1.251 → 0.1.252
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/module.json +1 -1
- package/layer/app/app.config.ts +6 -0
- package/layer/app/components/OipPubmedSummary.vue +223 -0
- package/layer/app/components/OipResourceDrawer.vue +331 -0
- package/layer/app/components/OipResourceDrawerLink.vue +40 -0
- package/layer/app/components/OipResourceField.vue +41 -0
- package/layer/app/components/OipResourceGenericCard.vue +54 -0
- package/layer/app/components/OipResourceSource.vue +50 -0
- package/layer/app/components/OipResourceTags.vue +65 -0
- package/layer/app/components/OipResourceView.vue +107 -0
- package/layer/app/components/oip-drugs/fiches/AssociationFiche.vue +775 -0
- package/layer/app/components/oip-drugs/fiches/BrandFiche.vue +1111 -0
- package/layer/app/components/oip-drugs/fiches/IndicationFiche.vue +182 -0
- package/layer/app/components/oip-drugs/fiches/JoFiche.vue +101 -0
- package/layer/app/components/oip-drugs/fiches/PndsFiche.vue +279 -0
- package/layer/app/components/oip-drugs/heart/JoCard.vue +314 -0
- package/layer/app/components/oip-drugs/heart/TextHighlight.vue +326 -0
- package/layer/app/components/oip-drugs/heart/ansm/BrandCard.vue +187 -0
- package/layer/app/components/oip-drugs/heart/ansm/CisDetail.vue +363 -0
- package/layer/app/components/oip-drugs/heart/ansm/CisTable.vue +167 -0
- package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyCard.vue +373 -0
- package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyFiche.vue +372 -0
- package/layer/app/components/oip-drugs/heart/associations/TranscriptionCard.vue +55 -0
- package/layer/app/components/oip-drugs/heart/elastic/SourceContainerElastic.vue +103 -0
- package/layer/app/components/oip-drugs/heart/france/BrandGroupCard.vue +450 -0
- package/layer/app/components/oip-drugs/heart/mitm/Card.vue +199 -0
- package/layer/app/components/oip-drugs/heart/mitm/Source.vue +23 -0
- package/layer/app/components/oip-drugs/heart/mitm/details/Overview.vue +381 -0
- package/layer/app/components/oip-drugs/heart/put/Card.vue +212 -0
- package/layer/app/components/oip-drugs/heart/results/AccesCard.vue +696 -0
- package/layer/app/components/oip-drugs/heart/results/AlertCard.vue +342 -0
- package/layer/app/components/oip-drugs/heart/results/AsmrCursor.vue +229 -0
- package/layer/app/components/oip-drugs/heart/results/EvalCard.vue +370 -0
- package/layer/app/components/oip-drugs/heart/results/IndicCard.vue +743 -0
- package/layer/app/components/oip-drugs/heart/results/MatchExplain.vue +243 -0
- package/layer/app/components/oip-drugs/heart/results/PrefRows.vue +105 -0
- package/layer/app/components/oip-drugs/heart/results/details/HasHistory.vue +487 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalCountryCard.vue +461 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalOverview.vue +200 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalPriceDrawer.vue +647 -0
- package/layer/app/components/oip-drugs/heart/results/details/Monograph.vue +128 -0
- package/layer/app/components/oip-drugs/heart/results/details/OpinionDrawer.vue +535 -0
- package/layer/app/components/oip-drugs/heart/results/details/PresentationDrawer.vue +738 -0
- package/layer/app/components/oip-drugs/heart/results/details/Price.vue +227 -0
- package/layer/app/components/oip-drugs/heart/results/details/PriceOverview.vue +1261 -0
- package/layer/app/components/oip-drugs/heart/results/details/RecordDrawer.vue +494 -0
- package/layer/app/components/oip-drugs/heart/results/details/RecordList.vue +426 -0
- package/layer/app/components/oip-drugs/heart/results/les/Card.vue +340 -0
- package/layer/app/components/oip-drugs/heart/results/les/Drawer.vue +67 -0
- package/layer/app/components/oip-drugs/heart/results/les/IndicationDetail.vue +149 -0
- package/layer/app/components/oip-drugs/heart/results/les/Source.vue +20 -0
- package/layer/app/components/oip-drugs/heart/results/les/SourceTag.vue +39 -0
- package/layer/app/components/oip-drugs/heart/searchPage/DynamicSource.vue +29 -0
- package/layer/app/components/oip-drugs/medicam/market/Chart.vue +121 -0
- package/layer/app/components/oip-drugs/outpatient/ProductEvolution.vue +236 -0
- package/layer/app/components/oip-drugs/resources/Ansm.vue +75 -0
- package/layer/app/components/oip-drugs/resources/Association.vue +30 -0
- package/layer/app/components/oip-drugs/resources/Brand.vue +65 -0
- package/layer/app/components/oip-drugs/resources/Contribution.vue +216 -0
- package/layer/app/components/oip-drugs/resources/Hospital.vue +151 -0
- package/layer/app/components/oip-drugs/resources/Indication.vue +54 -0
- package/layer/app/components/oip-drugs/resources/Jo.vue +57 -0
- package/layer/app/components/oip-drugs/resources/Medicam.vue +140 -0
- package/layer/app/components/oip-drugs/resources/Mitm.vue +84 -0
- package/layer/app/components/oip-drugs/resources/NationalAssembly.vue +93 -0
- package/layer/app/components/oip-drugs/resources/Outpatient.vue +97 -0
- package/layer/app/components/oip-drugs/resources/Pnds.vue +24 -0
- package/layer/app/components/oip-drugs/resources/Price.vue +106 -0
- package/layer/app/components/oip-drugs/resources/Put.vue +143 -0
- package/layer/app/components/oip-science/appel-a-projet/Cards.vue +162 -0
- package/layer/app/components/oip-science/clinical-trials/Cards.vue +382 -0
- package/layer/app/components/oip-science/clinical-trials/CardsGlobal.vue +273 -0
- package/layer/app/components/oip-science/clinical-trials/LinkedList.vue +366 -0
- package/layer/app/components/oip-science/clinical-trials/PairBadge.vue +25 -0
- package/layer/app/components/oip-science/clinical-trials/PairBody.vue +182 -0
- package/layer/app/components/oip-science/clinical-trials/SitesDrawer.vue +95 -0
- package/layer/app/components/oip-science/common/Form.vue +73 -0
- package/layer/app/components/oip-science/common/MatchAvgTag.vue +283 -0
- package/layer/app/components/oip-science/common/NoData.vue +16 -0
- package/layer/app/components/oip-science/common/ScoreBadge.vue +35 -0
- package/layer/app/components/oip-science/common/Source.vue +31 -0
- package/layer/app/components/oip-science/common/TableTags.vue +279 -0
- package/layer/app/components/oip-science/common/Timeline.vue +104 -0
- package/layer/app/components/oip-science/common/ToolTips.vue +89 -0
- package/layer/app/components/oip-science/cross/publicationPubmed.vue +484 -0
- package/layer/app/components/oip-science/crossData/CrossDataLocations.vue +71 -0
- package/layer/app/components/oip-science/ctgov/Investigators.vue +148 -0
- package/layer/app/components/oip-science/ctgov/Locations.vue +102 -0
- package/layer/app/components/oip-science/ctgov/Publications.vue +52 -0
- package/layer/app/components/oip-science/ctgov/Sponsors.vue +66 -0
- package/layer/app/components/oip-science/ctgov/StudyDescription.vue +1136 -0
- package/layer/app/components/oip-science/ctgov-centers/ClinicalTrials.vue +40 -0
- package/layer/app/components/oip-science/ctgov-centers/Publications.vue +50 -0
- package/layer/app/components/oip-science/ctgov-investigators/ClinicalTrials.vue +43 -0
- package/layer/app/components/oip-science/ctgov-investigators/Informations.vue +171 -0
- package/layer/app/components/oip-science/ctgov-investigators/Publications.vue +44 -0
- package/layer/app/components/oip-science/elastic/DateRangeFilter.vue +209 -0
- package/layer/app/components/oip-science/elastic/Filter.vue +719 -0
- package/layer/app/components/oip-science/elastic/MatchExplain.vue +152 -0
- package/layer/app/components/oip-science/establishments/Cards.vue +183 -0
- package/layer/app/components/oip-science/establishments/ClinicalTrials.vue +62 -0
- package/layer/app/components/oip-science/establishments/Hcps.vue +227 -0
- package/layer/app/components/oip-science/establishments/Informations.vue +263 -0
- package/layer/app/components/oip-science/establishments/LinkedList.vue +153 -0
- package/layer/app/components/oip-science/establishments/MatchedLabels.vue +194 -0
- package/layer/app/components/oip-science/establishments/PublicFinance.vue +62 -0
- package/layer/app/components/oip-science/euct/Investigators.vue +125 -0
- package/layer/app/components/oip-science/euct/Locations.vue +102 -0
- package/layer/app/components/oip-science/euct/Products.vue +101 -0
- package/layer/app/components/oip-science/euct/Publications.vue +89 -0
- package/layer/app/components/oip-science/euct/Sponsors.vue +86 -0
- package/layer/app/components/oip-science/euct/StudyDescription.vue +1075 -0
- package/layer/app/components/oip-science/euct-centers/ClinicalTrials.vue +40 -0
- package/layer/app/components/oip-science/euct-centers/Publications.vue +55 -0
- package/layer/app/components/oip-science/euct-investigators/ClinicalTrials.vue +41 -0
- package/layer/app/components/oip-science/euct-investigators/Informations.vue +171 -0
- package/layer/app/components/oip-science/euct-investigators/Publications.vue +51 -0
- package/layer/app/components/oip-science/hcps/AppelsAProjet.vue +62 -0
- package/layer/app/components/oip-science/hcps/Cards.vue +237 -0
- package/layer/app/components/oip-science/hcps/ClinicalTrials.vue +78 -0
- package/layer/app/components/oip-science/hcps/Informations.vue +296 -0
- package/layer/app/components/oip-science/hcps/LinkedList.vue +153 -0
- package/layer/app/components/oip-science/hcps/MatchedLabels.vue +207 -0
- package/layer/app/components/oip-science/hcps/Pubmed.vue +128 -0
- package/layer/app/components/oip-science/local/SliderTabs.vue +99 -0
- package/layer/app/components/oip-science/local/SliderTabsFull.vue +135 -0
- package/layer/app/components/oip-science/pubmed/Authors.vue +128 -0
- package/layer/app/components/oip-science/pubmed/Cards.vue +417 -0
- package/layer/app/components/oip-science/pubmed/ClinicalTrials.vue +71 -0
- package/layer/app/components/oip-science/resources/Phrc.vue +39 -0
- package/layer/app/composables/useOipChapterScroll.ts +43 -0
- package/layer/app/composables/useOipResourceHooks.ts +27 -0
- package/layer/app/composables/useOipResourceNav.ts +66 -0
- package/layer/app/composables/useOipResourceViews.ts +117 -0
- package/layer/app/composables/useOipResources.ts +83 -0
- package/layer/app/oip-drugs/PORTING.md +120 -0
- package/layer/app/oip-drugs/composables/useAssociationDetail.ts +220 -0
- package/layer/app/oip-drugs/composables/useAssociationExport.ts +63 -0
- package/layer/app/oip-drugs/composables/useAssociationLookup.ts +105 -0
- package/layer/app/oip-drugs/composables/useCardPrefOptions.ts +201 -0
- package/layer/app/oip-drugs/composables/useCurrency.ts +121 -0
- package/layer/app/oip-drugs/composables/useDirectusSources.ts +224 -0
- package/layer/app/oip-drugs/composables/useHeartBrandMatches.ts +112 -0
- package/layer/app/oip-drugs/composables/useHeartDetailSearches.ts +479 -0
- package/layer/app/oip-drugs/composables/useHeartIntlApprovals.ts +661 -0
- package/layer/app/oip-drugs/composables/useHeartLesIndication.ts +168 -0
- package/layer/app/oip-drugs/composables/useHeartMatchExplain.ts +231 -0
- package/layer/app/oip-drugs/composables/useHeartReports.ts +239 -0
- package/layer/app/oip-drugs/composables/useHeartSearchFields.ts +233 -0
- package/layer/app/oip-drugs/composables/useMergeByKey.ts +23 -0
- package/layer/app/oip-drugs/composables/useOipDrugsElastic.ts +621 -0
- package/layer/app/oip-drugs/composables/usePageEmpty.ts +58 -0
- package/layer/app/oip-drugs/composables/v-useSalesSource.ts +64 -0
- package/layer/app/oip-drugs/drugs.css +500 -0
- package/layer/app/oip-drugs/esIndices.ts +322 -0
- package/layer/app/oip-drugs/kinds.ts +264 -0
- package/layer/app/oip-drugs/locales/en.json +1571 -0
- package/layer/app/oip-drugs/locales/fr.json +1571 -0
- package/layer/app/oip-drugs/monographs/blincyto-has.vue +289 -0
- package/layer/app/oip-drugs/monographs/darzalex-has.vue +276 -0
- package/layer/app/oip-drugs/monographs/dupixent-has.vue +216 -0
- package/layer/app/oip-drugs/monographs/enhertu-has.vue +280 -0
- package/layer/app/oip-drugs/monographs/has-sein-2023.vue +1649 -0
- package/layer/app/oip-drugs/monographs/ibrance-has.vue +277 -0
- package/layer/app/oip-drugs/monographs/imfinzi-has.vue +293 -0
- package/layer/app/oip-drugs/monographs/keytruda-has.vue +334 -0
- package/layer/app/oip-drugs/monographs/kisqali-has.vue +201 -0
- package/layer/app/oip-drugs/monographs/opdivo-has.vue +231 -0
- package/layer/app/oip-drugs/monographs/ozempic-has.vue +186 -0
- package/layer/app/oip-drugs/monographs/tecentriq-has.vue +312 -0
- package/layer/app/oip-drugs/monographs/yescarta-has.vue +272 -0
- package/layer/app/oip-drugs/types/elastic.ts +113 -0
- package/layer/app/oip-drugs/types/es/agencies.ts +152 -0
- package/layer/app/oip-drugs/types/es/directory.ts +54 -0
- package/layer/app/oip-drugs/types/es/docByIndex.ts +151 -0
- package/layer/app/oip-drugs/types/es/openmedic.ts +67 -0
- package/layer/app/oip-drugs/types/es/outpatient.ts +71 -0
- package/layer/app/oip-drugs/types/es/portal.ts +130 -0
- package/layer/app/oip-drugs/types/es/retail.ts +107 -0
- package/layer/app/oip-drugs/types/es/statistics.ts +29 -0
- package/layer/app/oip-drugs/types/heart/CurrencyRate.ts +16 -0
- package/layer/app/oip-drugs/types/heart/ansm.ts +106 -0
- package/layer/app/oip-drugs/types/heart/tag.ts +29 -0
- package/layer/app/oip-drugs/utils/associationFields.ts +118 -0
- package/layer/app/oip-drugs/utils/contributions.ts +36 -0
- package/layer/app/oip-drugs/utils/countryMapping.ts +387 -0
- package/layer/app/oip-drugs/utils/esHighlight.ts +21 -0
- package/layer/app/oip-drugs/utils/exportSheets.ts +57 -0
- package/layer/app/oip-drugs/utils/heartIntlPrice.ts +228 -0
- package/layer/app/oip-drugs/utils/heartStyleAndFormat.ts +262 -0
- package/layer/app/oip-drugs/utils/heartStyleAnsm.ts +71 -0
- package/layer/app/oip-drugs/utils/latestDate.ts +31 -0
- package/layer/app/oip-drugs/utils/p-heartCardTags.ts +53 -0
- package/layer/app/oip-drugs/utils/priceExport.ts +269 -0
- package/layer/app/oip-drugs/utils/q-hasRatings.ts +43 -0
- package/layer/app/oip-drugs/utils/s-openCard.ts +20 -0
- package/layer/app/oip-drugs/utils/sourceUuids.ts +155 -0
- package/layer/app/oip-drugs/utils/styleAndFormat.ts +40 -0
- package/layer/app/oip-drugs/utils/v-salesSeries.ts +156 -0
- package/layer/app/oip-drugs/utils/v-scopeTags.ts +23 -0
- package/layer/app/oip-science/PORTING.md +93 -0
- package/layer/app/oip-science/assets/smartSelection.json +428 -0
- package/layer/app/oip-science/composables/useAuthorMatching.ts +342 -0
- package/layer/app/oip-science/composables/useCTCenter.ts +107 -0
- package/layer/app/oip-science/composables/useCTInvestigators.ts +107 -0
- package/layer/app/oip-science/composables/useEstablishmentCrossData.ts +139 -0
- package/layer/app/oip-science/composables/useEstablishmentMatching.ts +176 -0
- package/layer/app/oip-science/composables/useEuct.ts +418 -0
- package/layer/app/oip-science/composables/useEuctCenter.ts +107 -0
- package/layer/app/oip-science/composables/useEuctInvestigators.ts +107 -0
- package/layer/app/oip-science/composables/useGlobalClinicalTrials.ts +624 -0
- package/layer/app/oip-science/composables/useLinkedTrials.ts +83 -0
- package/layer/app/oip-science/composables/useOipElastic.ts +658 -0
- package/layer/app/oip-science/composables/useOipSearchExplain.ts +166 -0
- package/layer/app/oip-science/composables/usePubmed.ts +487 -0
- package/layer/app/oip-science/composables/useSearchFields.ts +153 -0
- package/layer/app/oip-science/indexConfig.json +794 -0
- package/layer/app/oip-science/locales/en.json +483 -0
- package/layer/app/oip-science/locales/fr.json +483 -0
- package/layer/app/oip-science/science.css +1182 -0
- package/layer/app/oip-science/utils/a-openCard.ts +23 -0
- package/layer/app/oip-science/utils/b-openCard.ts +35 -0
- package/layer/app/oip-science/utils/c-filterContext.ts +81 -0
- package/layer/app/oip-science/utils/f-types.ts +241 -0
- package/layer/app/oip-science/utils/frDiseaseTerms.ts +269 -0
- package/layer/app/oip-science/utils/matchMethod.ts +53 -0
- package/layer/app/oip-science/utils/sliderTabs.ts +13 -0
- package/layer/app/oip-science/utils/sources.ts +15 -0
- package/layer/app/oip-science/utils/styleAndFormat.ts +608 -0
- package/layer/app/oip-science/utils/toPresets.ts +7 -0
- package/layer/app/oip-science/utils/valueTable.ts +126 -0
- package/layer/app/plugins/oip-science-i18n.ts +17 -0
- package/layer/app/utils/oipFicheRoutes.ts +118 -0
- package/layer/app/utils/oipResources.ts +440 -0
- package/layer/nuxt.config.ts +22 -2
- package/layer/public/reports/blincyto-has.html +292 -0
- package/layer/public/reports/blincyto-has.pdf +0 -0
- package/layer/public/reports/darzalex-has.html +279 -0
- package/layer/public/reports/darzalex-has.pdf +0 -0
- package/layer/public/reports/dupixent-has.html +217 -0
- package/layer/public/reports/dupixent-has.pdf +0 -0
- package/layer/public/reports/enhertu-has.html +283 -0
- package/layer/public/reports/enhertu-has.pdf +0 -0
- package/layer/public/reports/has-sein-2023.html +1639 -0
- package/layer/public/reports/ibrance-has.html +280 -0
- package/layer/public/reports/ibrance-has.pdf +0 -0
- package/layer/public/reports/imfinzi-has.html +297 -0
- package/layer/public/reports/imfinzi-has.pdf +0 -0
- package/layer/public/reports/keytruda-has.html +337 -0
- package/layer/public/reports/keytruda-has.pdf +0 -0
- package/layer/public/reports/kisqali-has.html +202 -0
- package/layer/public/reports/kisqali-has.pdf +0 -0
- package/layer/public/reports/opdivo-has.html +232 -0
- package/layer/public/reports/opdivo-has.pdf +0 -0
- package/layer/public/reports/ozempic-has.html +188 -0
- package/layer/public/reports/ozempic-has.pdf +0 -0
- package/layer/public/reports/tecentriq-has.html +315 -0
- package/layer/public/reports/tecentriq-has.pdf +0 -0
- package/layer/public/reports/yescarta-has.html +275 -0
- package/layer/public/reports/yescarta-has.pdf +0 -0
- package/layer/server/api/oip/es.post.ts +99 -0
- package/layer/server/api/oip/pdf.get.ts +70 -0
- package/layer/server/api/oip/reports.get.ts +98 -0
- package/layer/server/api/oip/resource-types.get.ts +22 -0
- package/package.json +1 -1
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Vue de ressource d'une contribution patient (FrPatientContribution) : la
|
|
3
|
+
contribution elle-meme (decision produit), relue par son `_id` dans l'index
|
|
4
|
+
des contributions HAS. Le contenu reprend le detail de France Augmented
|
|
5
|
+
Science (identite, rubriques, lien vers l'association et vers l'avis), avec
|
|
6
|
+
les composants et le style du tiroir de contribution de la fiche
|
|
7
|
+
association de fr_drugs_app.
|
|
8
|
+
-->
|
|
9
|
+
<template>
|
|
10
|
+
<div class="oip-drugs arg_page_layout">
|
|
11
|
+
<RmPageHeader :eyebrow="t('oipDrugs.heart.details.tabs.contrib')">
|
|
12
|
+
<template #title>
|
|
13
|
+
<span class="oip-drugs-fiche__title">{{ regroup || id }}</span>
|
|
14
|
+
<slot name="title-link" />
|
|
15
|
+
</template>
|
|
16
|
+
<div v-if="contribution" class="contrib_identity oip_list">
|
|
17
|
+
<div class="oip_row v-center gap-8 wrap">
|
|
18
|
+
<span v-if="contribution.contribution_date" class="oip_label">
|
|
19
|
+
<RmDate :date="contribution.contribution_date" :lang="dateLang" />
|
|
20
|
+
</span>
|
|
21
|
+
<RmTag v-if="contribution.has_code" variant="gray">{{ contribution.has_code }}</RmTag>
|
|
22
|
+
<RmTag v-if="contribution.request_nature" variant="violet">{{ contribution.request_nature }}</RmTag>
|
|
23
|
+
<RmTag v-if="contribution.brand_group" variant="blue">{{ contribution.brand_group }}</RmTag>
|
|
24
|
+
</div>
|
|
25
|
+
<p v-if="original" class="contrib_muted">
|
|
26
|
+
{{ t("oipDrugs.heart.details.patientContrib.originalName") }} : {{ original }}
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
</RmPageHeader>
|
|
30
|
+
|
|
31
|
+
<div class="oip_list gap-12 full contrib_detail">
|
|
32
|
+
<OipDrugsHeartElasticSourceContainerElastic
|
|
33
|
+
:uuid="HEART_SOURCE_UUIDS.ASSOCIATIONS"
|
|
34
|
+
:last-label="t('oipDrugs.heart.sources.lastContribution')"
|
|
35
|
+
:last-date="contribution?.contribution_date ?? null"
|
|
36
|
+
/>
|
|
37
|
+
|
|
38
|
+
<RmLoadingState v-if="loading" />
|
|
39
|
+
<RmEmptyState v-else-if="!contribution" :title="t('oipDrugs.heart.errors.results')" icon="Prohibit" />
|
|
40
|
+
|
|
41
|
+
<div v-else class="oip_card oip_list gap-12 oip_body full">
|
|
42
|
+
<div class="oip_row gap-8 wrap">
|
|
43
|
+
<!-- La fiche de l'association : le lien n'apparait qu'une fois
|
|
44
|
+
l'association reconnue par l'annuaire. -->
|
|
45
|
+
<RmButton
|
|
46
|
+
v-if="associationId"
|
|
47
|
+
variant="secondary"
|
|
48
|
+
prefix-icon="UsersThree"
|
|
49
|
+
@click="nav.openApp('fr_drugs_app', drugsAssociationPath(associationId))"
|
|
50
|
+
>
|
|
51
|
+
{{ t("oipDrugs.heart.details.patientContrib.seeAssociation") }}
|
|
52
|
+
</RmButton>
|
|
53
|
+
<RmButton v-if="opinionPath" variant="secondary" prefix-icon="Tag" @click="nav.openApp('fr_drugs_app', opinionPath)">
|
|
54
|
+
{{ t("oipDrugs.heart.associations.detail.seeLinkedOpinion", { brand: contribution.brand_group }) }}
|
|
55
|
+
</RmButton>
|
|
56
|
+
<RmButton
|
|
57
|
+
v-if="contribution.contribution_url"
|
|
58
|
+
variant="tertiary"
|
|
59
|
+
ghost
|
|
60
|
+
prefix-icon="ArrowSquareOut"
|
|
61
|
+
@click="openLink(contribution.contribution_url)"
|
|
62
|
+
>
|
|
63
|
+
{{ t("oipDrugs.heart.associations.detail.seeOnHas") }}
|
|
64
|
+
</RmButton>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<!-- Sections repliables, comme le tiroir de la fiche association : la
|
|
68
|
+
premiere est ouverte, les autres se replient independamment. -->
|
|
69
|
+
<div v-if="sections.length > 0" class="oip_list full">
|
|
70
|
+
<RmCollapse
|
|
71
|
+
v-for="section in sections"
|
|
72
|
+
:key="section.key"
|
|
73
|
+
v-model="sectionOpen[section.key]"
|
|
74
|
+
:title="section.label"
|
|
75
|
+
>
|
|
76
|
+
<p class="contrib_field_text oip_body">{{ section.value }}</p>
|
|
77
|
+
</RmCollapse>
|
|
78
|
+
</div>
|
|
79
|
+
</div>
|
|
80
|
+
</div>
|
|
81
|
+
</div>
|
|
82
|
+
</template>
|
|
83
|
+
|
|
84
|
+
<script setup lang="ts">
|
|
85
|
+
import { ES_INDEX } from "../../../oip-drugs/esIndices";
|
|
86
|
+
import { HEART_SOURCE_UUIDS } from "../../../oip-drugs/utils/sourceUuids";
|
|
87
|
+
import { withContributionBrands } from "../../../oip-drugs/utils/contributions";
|
|
88
|
+
import { useAssociationLookup } from "../../../oip-drugs/composables/useAssociationLookup";
|
|
89
|
+
import { drugsAssociationPath, drugsBrandPath } from "../../../oip-drugs/kinds";
|
|
90
|
+
import { oipEsSearch } from "../../../composables/useOipResources";
|
|
91
|
+
|
|
92
|
+
const props = withDefaults(
|
|
93
|
+
defineProps<{
|
|
94
|
+
id: string;
|
|
95
|
+
type?: string;
|
|
96
|
+
lang?: "fr" | "en";
|
|
97
|
+
highlight?: string[];
|
|
98
|
+
}>(),
|
|
99
|
+
{ type: "FrPatientContribution", lang: undefined, highlight: () => [] },
|
|
100
|
+
);
|
|
101
|
+
|
|
102
|
+
const { t, locale } = useI18n();
|
|
103
|
+
const nav = useOipResourceNav();
|
|
104
|
+
const lookup = useAssociationLookup();
|
|
105
|
+
|
|
106
|
+
const dateLang = computed(() => props.lang ?? (locale.value === "en" ? "en" : "fr"));
|
|
107
|
+
|
|
108
|
+
const contribution = ref<any>(null);
|
|
109
|
+
const loading = ref(true);
|
|
110
|
+
const sectionOpen = ref<Record<string, boolean>>({});
|
|
111
|
+
|
|
112
|
+
watch(
|
|
113
|
+
() => props.id,
|
|
114
|
+
async (id) => {
|
|
115
|
+
loading.value = true;
|
|
116
|
+
contribution.value = null;
|
|
117
|
+
try {
|
|
118
|
+
const res: any = await oipEsSearch("drugs", ES_INDEX.ASSOCIATION_CONTRIBUTION_HAS, {
|
|
119
|
+
size: 1,
|
|
120
|
+
query: { ids: { values: [id] } },
|
|
121
|
+
});
|
|
122
|
+
const doc = res?.hits?.hits?.[0]?._source ?? null;
|
|
123
|
+
// La marque se relit dans l'index HAS, en une requete a part.
|
|
124
|
+
if (doc) await withContributionBrands([doc]);
|
|
125
|
+
contribution.value = doc;
|
|
126
|
+
} catch {
|
|
127
|
+
contribution.value = null;
|
|
128
|
+
}
|
|
129
|
+
sectionOpen.value = sections.value[0] ? { [sections.value[0].key]: true } : {};
|
|
130
|
+
loading.value = false;
|
|
131
|
+
// L'annuaire dit sous quel nom ouvrir la fiche de l'association.
|
|
132
|
+
if (contribution.value) {
|
|
133
|
+
await lookup.load([contribution.value.association_label_regroup, contribution.value.association_label]);
|
|
134
|
+
}
|
|
135
|
+
},
|
|
136
|
+
{ immediate: true },
|
|
137
|
+
);
|
|
138
|
+
|
|
139
|
+
const regroup = computed(
|
|
140
|
+
() => contribution.value?.association_label_regroup || contribution.value?.association_label || "",
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
/** Le nom d'origine, quand le regroupement l'a reecrit. */
|
|
144
|
+
const original = computed(() => {
|
|
145
|
+
const c = contribution.value;
|
|
146
|
+
return c?.association_label && c?.association_label_regroup && c.association_label !== c.association_label_regroup
|
|
147
|
+
? String(c.association_label)
|
|
148
|
+
: "";
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
const associationId = computed(() =>
|
|
152
|
+
contribution.value
|
|
153
|
+
? lookup.idFor(contribution.value.association_label_regroup, contribution.value.association_label)
|
|
154
|
+
: null,
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
/** La fiche marque de l'avis, sur son onglet des contributions et sur ce code. */
|
|
158
|
+
const opinionPath = computed(() => {
|
|
159
|
+
const brand = contribution.value?.brand_group;
|
|
160
|
+
if (!brand) return "";
|
|
161
|
+
const code = contribution.value?.has_code;
|
|
162
|
+
return `${drugsBrandPath(brand)}?tab=contributions${code ? `&code=${encodeURIComponent(code)}` : ""}`;
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
/** Les champs renseignes, dans l'ordre du questionnaire HAS. */
|
|
166
|
+
const sections = computed(() => {
|
|
167
|
+
const c = contribution.value;
|
|
168
|
+
if (!c) return [];
|
|
169
|
+
const field = (key: string, value: unknown) => ({
|
|
170
|
+
key,
|
|
171
|
+
label: t(`oipDrugs.heart.associations.detail.fields.${key}`),
|
|
172
|
+
value,
|
|
173
|
+
});
|
|
174
|
+
return [
|
|
175
|
+
field("synthesis", c.synthesis),
|
|
176
|
+
field("drugIndication", c.drug_indication),
|
|
177
|
+
field("method", c.method),
|
|
178
|
+
field("experienceDrug", c.experience_drug),
|
|
179
|
+
field("experienceCurrentTreatment", c.experience_current_treatment),
|
|
180
|
+
field("impact", c.impact),
|
|
181
|
+
field("additionalInfo", c.additional_info),
|
|
182
|
+
].filter((entry) => typeof entry.value === "string" && entry.value.trim());
|
|
183
|
+
});
|
|
184
|
+
|
|
185
|
+
function openLink(url: string) {
|
|
186
|
+
if (url) window.open(url, "_blank");
|
|
187
|
+
}
|
|
188
|
+
</script>
|
|
189
|
+
|
|
190
|
+
<style scoped>
|
|
191
|
+
.oip-drugs-fiche__title {
|
|
192
|
+
display: block;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
.contrib_detail {
|
|
196
|
+
padding-left: 24px;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
.contrib_identity {
|
|
200
|
+
gap: 4px;
|
|
201
|
+
color: var(--text-primary);
|
|
202
|
+
font-size: 14px;
|
|
203
|
+
line-height: 160%;
|
|
204
|
+
max-width: 900px;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
.contrib_muted {
|
|
208
|
+
color: var(--dark, #6c6c8a);
|
|
209
|
+
font-size: 13px;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
/* Les textes arrivent en un seul bloc, avec leurs retours a la ligne. */
|
|
213
|
+
.contrib_field_text {
|
|
214
|
+
white-space: pre-line;
|
|
215
|
+
}
|
|
216
|
+
</style>
|
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Vue de ressource d'une marque hospitaliere : liste en sus ATIH
|
|
3
|
+
(FrSusBrand) ou retrocession CNAM (FrRetrocessionBrand), selon `type`.
|
|
4
|
+
|
|
5
|
+
Decision produit : un graphe d'evolution annuelle de la marque, au gabarit
|
|
6
|
+
des vues Medic'AM et Outpatient. Donnees et requetes reprises de
|
|
7
|
+
drugs/HospitalEvolution de France Augmented Science (bloc Total des pages
|
|
8
|
+
/hospital/sus et /hospital/retrocession de fr_drugs_app, au niveau marque,
|
|
9
|
+
sur toutes les annees de l'index). La marque vient du `resourceId`
|
|
10
|
+
(cf. titleFromId de kinds.ts).
|
|
11
|
+
-->
|
|
12
|
+
<template>
|
|
13
|
+
<div class="oip-drugs v-sales">
|
|
14
|
+
<RmPageHeader>
|
|
15
|
+
<template #title>
|
|
16
|
+
<span class="v-sales__title">{{ brand }}</span>
|
|
17
|
+
<slot name="title-link" />
|
|
18
|
+
</template>
|
|
19
|
+
</RmPageHeader>
|
|
20
|
+
|
|
21
|
+
<div class="v-sales__body">
|
|
22
|
+
<RmLoadingState v-if="loading" :lines="1" :chart-height="400" />
|
|
23
|
+
<RmEmptyState
|
|
24
|
+
v-else-if="!rows.length"
|
|
25
|
+
icon="MagnifyingGlassMinus"
|
|
26
|
+
:title="en ? 'No data' : 'Aucune donnée'"
|
|
27
|
+
:text="emptyText"
|
|
28
|
+
/>
|
|
29
|
+
<div v-else class="v-sales__stack">
|
|
30
|
+
<RmSegmented
|
|
31
|
+
v-model="measure"
|
|
32
|
+
size="sm"
|
|
33
|
+
:options="options"
|
|
34
|
+
:aria-label="en ? 'Measure' : 'Mesure'"
|
|
35
|
+
/>
|
|
36
|
+
<RmChartCard :title="cardTitle" :source="source" :verified="verified" :lang="lang"
|
|
37
|
+
:state="chartContent.length > 0 ? 'ready' : 'empty'">
|
|
38
|
+
<RmLineChart :key="chartKey" :categories="chartHead" :series="chartContent" :height="400"
|
|
39
|
+
number-format="compact" />
|
|
40
|
+
</RmChartCard>
|
|
41
|
+
</div>
|
|
42
|
+
</div>
|
|
43
|
+
</div>
|
|
44
|
+
</template>
|
|
45
|
+
|
|
46
|
+
<script setup lang="ts">
|
|
47
|
+
import { ES_INDEX } from "../../../oip-drugs/esIndices";
|
|
48
|
+
import { oipEsSearch } from "../../../composables/useOipResources";
|
|
49
|
+
import { HOSPITAL_MEASURES, measureOptions, salesBrandOf, salesPeriods } from "../../../oip-drugs/utils/v-salesSeries";
|
|
50
|
+
import { useSalesSource } from "../../../oip-drugs/composables/v-useSalesSource";
|
|
51
|
+
|
|
52
|
+
const props = withDefaults(
|
|
53
|
+
defineProps<{ id: string; type: string; lang?: "fr" | "en"; highlight?: string[] }>(),
|
|
54
|
+
{ lang: "fr", highlight: () => [] },
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
const en = computed(() => props.lang === "en");
|
|
58
|
+
const sus = computed(() => props.type !== "FrRetrocessionBrand");
|
|
59
|
+
const kindType = computed(() => (sus.value ? "FrSusBrand" : "FrRetrocessionBrand"));
|
|
60
|
+
const brand = computed(() => salesBrandOf(kindType.value, props.id));
|
|
61
|
+
const { source, verified } = useSalesSource(sus.value ? "SUS" : "RETROCESSION", () => props.lang);
|
|
62
|
+
|
|
63
|
+
// Ex-store hospital : la mesure lue, en etat local.
|
|
64
|
+
const measures = computed(() => HOSPITAL_MEASURES[kindType.value]);
|
|
65
|
+
const measure = ref(measures.value.variables[0]!);
|
|
66
|
+
const options = computed(() => measureOptions(measures.value, en.value));
|
|
67
|
+
const measureLabel = computed(() => options.value.find((o) => o.value === measure.value)?.label ?? "");
|
|
68
|
+
const cardTitle = computed(() => (en.value ? "Yearly evolution: " : "Évolution annuelle : ") + measureLabel.value);
|
|
69
|
+
const emptyText = computed(() => {
|
|
70
|
+
if (sus.value) return en.value ? "No inpatient list sales for this brand." : "Aucune vente en liste en sus pour cette marque.";
|
|
71
|
+
return en.value ? "No retrocession sales for this brand." : "Aucune vente en rétrocession pour cette marque.";
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
// Filtres des pages : niveau marque, et pour la liste en sus le total des
|
|
75
|
+
// secteurs et des activites en analyse 1 (cf. useHospitalBrandIds).
|
|
76
|
+
const filters = computed(() =>
|
|
77
|
+
sus.value
|
|
78
|
+
? [
|
|
79
|
+
{ term: { "level.keyword": "brand" } },
|
|
80
|
+
{ term: { "sector.keyword": "TOTAL" } },
|
|
81
|
+
{ term: { "activity.keyword": "TOTAL" } },
|
|
82
|
+
{ term: { analysis_type: 1 } },
|
|
83
|
+
]
|
|
84
|
+
: [{ term: { "level.keyword": "brand" } }],
|
|
85
|
+
);
|
|
86
|
+
|
|
87
|
+
const rows = ref<any[]>([]);
|
|
88
|
+
const loading = ref(true);
|
|
89
|
+
const chartKey = ref(0);
|
|
90
|
+
|
|
91
|
+
async function load() {
|
|
92
|
+
loading.value = true;
|
|
93
|
+
try {
|
|
94
|
+
const response: any = await oipEsSearch(
|
|
95
|
+
"drugs",
|
|
96
|
+
sus.value ? ES_INDEX.HOSPITAL_ANNUAL_SUS : ES_INDEX.HOSPITAL_ANNUAL_RETROCESSION,
|
|
97
|
+
{
|
|
98
|
+
size: 50,
|
|
99
|
+
query: { bool: { filter: [{ term: { "code.keyword": brand.value } }, ...filters.value] } },
|
|
100
|
+
},
|
|
101
|
+
);
|
|
102
|
+
rows.value = (response?.hits?.hits ?? []).map((hit: any) => hit._source);
|
|
103
|
+
} catch {
|
|
104
|
+
rows.value = [];
|
|
105
|
+
} finally {
|
|
106
|
+
loading.value = false;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
onMounted(load);
|
|
111
|
+
watch(() => [brand.value, kindType.value], load);
|
|
112
|
+
|
|
113
|
+
const chartHead = computed(() => salesPeriods(rows.value));
|
|
114
|
+
|
|
115
|
+
/** Une courbe, nommee comme sur les pages : « Libelle (CODE) » quand ils different. */
|
|
116
|
+
const chartContent = computed(() => {
|
|
117
|
+
if (!rows.value.length) return [];
|
|
118
|
+
const first = rows.value[0];
|
|
119
|
+
const name = first.code === first.label || !first.label ? String(first.code) : `${first.label} (${first.code})`;
|
|
120
|
+
const byPeriod = new Map(rows.value.map((i: any) => [i.period, i[measure.value] ?? null]));
|
|
121
|
+
return [{ name, data: chartHead.value.map((p) => byPeriod.get(p) ?? null) }];
|
|
122
|
+
});
|
|
123
|
+
|
|
124
|
+
watch(chartContent, () => {
|
|
125
|
+
chartKey.value = chartKey.value + 1;
|
|
126
|
+
});
|
|
127
|
+
</script>
|
|
128
|
+
|
|
129
|
+
<style scoped>
|
|
130
|
+
.v-sales__title {
|
|
131
|
+
display: block;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/* Les gouttieres de la colonne de contenu, comme les onglets d'OipResourceView. */
|
|
135
|
+
.v-sales__body {
|
|
136
|
+
box-sizing: border-box;
|
|
137
|
+
margin-top: var(--space-24);
|
|
138
|
+
padding: 0 var(--space-24) var(--space-32);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
.v-sales__stack {
|
|
142
|
+
display: flex;
|
|
143
|
+
flex-direction: column;
|
|
144
|
+
gap: var(--space-16);
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/* Le rail de mesures garde sa largeur. */
|
|
148
|
+
.v-sales__stack > :first-child {
|
|
149
|
+
align-self: flex-start;
|
|
150
|
+
}
|
|
151
|
+
</style>
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Vue de ressource FrHasIndication : le document de l'index LES par son `_id`,
|
|
3
|
+
dont on lit le code d'indication comme le chemin de la famille (cf.
|
|
4
|
+
oip-drugs/kinds.ts), puis la fiche de l'indication.
|
|
5
|
+
-->
|
|
6
|
+
<template>
|
|
7
|
+
<div class="oip-drugs">
|
|
8
|
+
<div v-if="loading" class="oip_row v-center centered stretch">
|
|
9
|
+
<RmLoadingState spinner />
|
|
10
|
+
</div>
|
|
11
|
+
<OipDrugsFichesIndicationFiche
|
|
12
|
+
v-else-if="code"
|
|
13
|
+
v-model:tab="tab"
|
|
14
|
+
:code="code"
|
|
15
|
+
:lang="lang"
|
|
16
|
+
:highlight="highlight"
|
|
17
|
+
>
|
|
18
|
+
<template #title-link><slot name="title-link" /></template>
|
|
19
|
+
</OipDrugsFichesIndicationFiche>
|
|
20
|
+
<RmEmptyState v-else :title="t('oipDrugs.heart.errors.results')" icon="Prohibit" />
|
|
21
|
+
</div>
|
|
22
|
+
</template>
|
|
23
|
+
|
|
24
|
+
<script setup lang="ts">
|
|
25
|
+
import { ES_INDEX } from "../../../oip-drugs/esIndices";
|
|
26
|
+
import { oipEsGet } from "../../../composables/useOipResources";
|
|
27
|
+
|
|
28
|
+
const props = withDefaults(
|
|
29
|
+
defineProps<{
|
|
30
|
+
/** Le `resourceId` : `_id` du document LES. */
|
|
31
|
+
id: string;
|
|
32
|
+
type?: string;
|
|
33
|
+
lang?: "fr" | "en";
|
|
34
|
+
highlight?: string[];
|
|
35
|
+
}>(),
|
|
36
|
+
{ type: "FrHasIndication", lang: undefined, highlight: () => [] },
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const { t } = useI18n();
|
|
40
|
+
|
|
41
|
+
const loading = ref(true);
|
|
42
|
+
const code = ref("");
|
|
43
|
+
const tab = ref("1");
|
|
44
|
+
|
|
45
|
+
async function read() {
|
|
46
|
+
loading.value = true;
|
|
47
|
+
const hit = await oipEsGet<any>("drugs", ES_INDEX.INDICATION_SEARCH_HAS, props.id, ["indication"]).catch(() => null);
|
|
48
|
+
const indication = hit?._source?.indication;
|
|
49
|
+
code.value = String((Array.isArray(indication) ? indication.find(Boolean) : indication) ?? "");
|
|
50
|
+
loading.value = false;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
watch(() => props.id, read, { immediate: true });
|
|
54
|
+
</script>
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Vue de ressource FrDrugPriceJo : le document de l'index JO par son `_id`,
|
|
3
|
+
puis la fiche JO de sa presentation (`local_drug_id`). Avec
|
|
4
|
+
`by="local_drug_id"`, l'id est deja ce code.
|
|
5
|
+
-->
|
|
6
|
+
<template>
|
|
7
|
+
<div class="oip-drugs">
|
|
8
|
+
<div v-if="loading" class="oip_row v-center centered stretch">
|
|
9
|
+
<RmLoadingState spinner />
|
|
10
|
+
</div>
|
|
11
|
+
<OipDrugsFichesJoFiche
|
|
12
|
+
v-else-if="localDrugId"
|
|
13
|
+
:id="localDrugId"
|
|
14
|
+
:lang="lang"
|
|
15
|
+
:highlight="highlight"
|
|
16
|
+
>
|
|
17
|
+
<template #title-link><slot name="title-link" /></template>
|
|
18
|
+
</OipDrugsFichesJoFiche>
|
|
19
|
+
<RmEmptyState v-else :title="t('oipDrugs.heart.errors.results')" icon="Prohibit" />
|
|
20
|
+
</div>
|
|
21
|
+
</template>
|
|
22
|
+
|
|
23
|
+
<script setup lang="ts">
|
|
24
|
+
import { ES_INDEX } from "../../../oip-drugs/esIndices";
|
|
25
|
+
import { oipEsGet } from "../../../composables/useOipResources";
|
|
26
|
+
|
|
27
|
+
const props = withDefaults(
|
|
28
|
+
defineProps<{
|
|
29
|
+
/** Le `resourceId` : `_id` du document JO (ou son `local_drug_id`, cf. `by`). */
|
|
30
|
+
id: string;
|
|
31
|
+
type?: string;
|
|
32
|
+
lang?: "fr" | "en";
|
|
33
|
+
highlight?: string[];
|
|
34
|
+
by?: string;
|
|
35
|
+
}>(),
|
|
36
|
+
{ type: "FrDrugPriceJo", lang: undefined, highlight: () => [], by: "" },
|
|
37
|
+
);
|
|
38
|
+
|
|
39
|
+
const { t } = useI18n();
|
|
40
|
+
|
|
41
|
+
const loading = ref(true);
|
|
42
|
+
const localDrugId = ref("");
|
|
43
|
+
|
|
44
|
+
async function read() {
|
|
45
|
+
if (props.by === "local_drug_id") {
|
|
46
|
+
localDrugId.value = props.id;
|
|
47
|
+
loading.value = false;
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
loading.value = true;
|
|
51
|
+
const hit = await oipEsGet<any>("drugs", ES_INDEX.DRUG_CARDS_PRICE_JO, props.id, ["local_drug_id"]).catch(() => null);
|
|
52
|
+
localDrugId.value = String(hit?._source?.local_drug_id ?? "");
|
|
53
|
+
loading.value = false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
watch(() => [props.id, props.by], read, { immediate: true });
|
|
57
|
+
</script>
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
<!--
|
|
2
|
+
Vue de ressource d'une marque Medic'AM (FrMedicamBrand) : son evolution
|
|
3
|
+
mensuelle, portee de hubr/projectMedicamEvolution de fr_drugs_app.
|
|
4
|
+
|
|
5
|
+
La marque vient du `resourceId` (`DOLIPRANE_2026-06_1` : DOLIPRANE, cf.
|
|
6
|
+
medicamBrandOf) : le mois n'est qu'une ancre. On lit tout l'historique
|
|
7
|
+
mensuel de la marque, en une requete, et chaque graphe se filtre sur son
|
|
8
|
+
secteur et la mesure choisie.
|
|
9
|
+
-->
|
|
10
|
+
<template>
|
|
11
|
+
<div class="oip-drugs v-sales">
|
|
12
|
+
<RmPageHeader>
|
|
13
|
+
<template #title>
|
|
14
|
+
<span class="v-sales__title">{{ brand }}</span>
|
|
15
|
+
<slot name="title-link" />
|
|
16
|
+
</template>
|
|
17
|
+
</RmPageHeader>
|
|
18
|
+
|
|
19
|
+
<div class="v-sales__body">
|
|
20
|
+
<RmEmptyState
|
|
21
|
+
v-if="pageEmpty"
|
|
22
|
+
icon="MagnifyingGlassMinus"
|
|
23
|
+
:title="en ? 'No data' : 'Aucune donnée'"
|
|
24
|
+
:text="emptyText"
|
|
25
|
+
/>
|
|
26
|
+
<!-- Les graphes restent montes : ils disent eux-memes s'ils sont vides. -->
|
|
27
|
+
<div v-show="!pageEmpty" class="hubr_me">
|
|
28
|
+
<RmSegmented
|
|
29
|
+
v-model="measure"
|
|
30
|
+
size="sm"
|
|
31
|
+
:options="options"
|
|
32
|
+
:aria-label="en ? 'Measure' : 'Mesure'"
|
|
33
|
+
/>
|
|
34
|
+
<OipDrugsMedicamMarketChart
|
|
35
|
+
v-for="chart in charts"
|
|
36
|
+
:key="`${chart.sector}-${measure}`"
|
|
37
|
+
:rows="rows"
|
|
38
|
+
:loading="loading"
|
|
39
|
+
selected-level="brand"
|
|
40
|
+
:selected-label="labels"
|
|
41
|
+
:selected-measure="measure"
|
|
42
|
+
:selected-switch="true"
|
|
43
|
+
:selected-title="chart.title"
|
|
44
|
+
:selected-sector="chart.sector"
|
|
45
|
+
:lang="lang"
|
|
46
|
+
:source="source"
|
|
47
|
+
:verified="verified"
|
|
48
|
+
/>
|
|
49
|
+
</div>
|
|
50
|
+
</div>
|
|
51
|
+
</div>
|
|
52
|
+
</template>
|
|
53
|
+
|
|
54
|
+
<script setup lang="ts">
|
|
55
|
+
import { ES_INDEX } from "../../../oip-drugs/esIndices";
|
|
56
|
+
import { oipEsSearch } from "../../../composables/useOipResources";
|
|
57
|
+
import { usePageEmpty } from "../../../oip-drugs/composables/usePageEmpty";
|
|
58
|
+
import { MEDICAM_MEASURES, measureOptions, salesBrandOf } from "../../../oip-drugs/utils/v-salesSeries";
|
|
59
|
+
import { useSalesSource } from "../../../oip-drugs/composables/v-useSalesSource";
|
|
60
|
+
|
|
61
|
+
const props = withDefaults(
|
|
62
|
+
defineProps<{ id: string; type?: string; lang?: "fr" | "en"; highlight?: string[] }>(),
|
|
63
|
+
{ type: "FrMedicamBrand", lang: "fr", highlight: () => [] },
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const en = computed(() => props.lang === "en");
|
|
67
|
+
const brand = computed(() => salesBrandOf("FrMedicamBrand", props.id));
|
|
68
|
+
const { source, verified } = useSalesSource("MEDICAM", () => props.lang);
|
|
69
|
+
const pageEmpty = usePageEmpty();
|
|
70
|
+
const emptyText = computed(() =>
|
|
71
|
+
en.value ? "No Medic'AM sales for this brand." : "Aucune vente Medic'AM pour cette marque.",
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Ex-store retail : la mesure lue, en etat local.
|
|
75
|
+
const measure = ref("unit_reimbursed");
|
|
76
|
+
const options = computed(() => measureOptions(MEDICAM_MEASURES, en.value));
|
|
77
|
+
|
|
78
|
+
const charts = computed(() => [
|
|
79
|
+
{ sector: "total", title: en.value ? "Total" : "Totale" },
|
|
80
|
+
{ sector: "office", title: en.value ? "Office based" : "Ville" },
|
|
81
|
+
{ sector: "hospital", title: en.value ? "Hospital (Public + Espic)" : "Hôpitaux (Publique + Espic)" },
|
|
82
|
+
]);
|
|
83
|
+
|
|
84
|
+
/** Une seule courbe, nommee par la marque. */
|
|
85
|
+
const labels = computed(() => [{ code: brand.value, label: brand.value, code_label: brand.value }]);
|
|
86
|
+
|
|
87
|
+
const rows = ref<any[]>([]);
|
|
88
|
+
const loading = ref(true);
|
|
89
|
+
|
|
90
|
+
async function load() {
|
|
91
|
+
loading.value = true;
|
|
92
|
+
try {
|
|
93
|
+
const response: any = await oipEsSearch("drugs", ES_INDEX.RETAIL_MONTHLY_BRAND, {
|
|
94
|
+
// Tous les mois de l'index (8 ans au plus), la granularite mensuelle.
|
|
95
|
+
size: 200,
|
|
96
|
+
query: {
|
|
97
|
+
bool: {
|
|
98
|
+
// Memes clauses que la page Medic'AM (monthlyQuery).
|
|
99
|
+
must: [
|
|
100
|
+
{ match: { "code.keyword": brand.value } },
|
|
101
|
+
{ match: { period_interval: 1 } },
|
|
102
|
+
],
|
|
103
|
+
},
|
|
104
|
+
},
|
|
105
|
+
});
|
|
106
|
+
rows.value = (response?.hits?.hits ?? []).map((hit: any) => hit._source);
|
|
107
|
+
} catch {
|
|
108
|
+
rows.value = [];
|
|
109
|
+
} finally {
|
|
110
|
+
loading.value = false;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
onMounted(load);
|
|
115
|
+
watch(brand, load);
|
|
116
|
+
</script>
|
|
117
|
+
|
|
118
|
+
<style scoped>
|
|
119
|
+
.v-sales__title {
|
|
120
|
+
display: block;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* Les gouttieres de la colonne de contenu, comme les onglets d'OipResourceView. */
|
|
124
|
+
.v-sales__body {
|
|
125
|
+
box-sizing: border-box;
|
|
126
|
+
margin-top: var(--space-24);
|
|
127
|
+
padding: 0 var(--space-24) var(--space-32);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
.hubr_me {
|
|
131
|
+
display: flex;
|
|
132
|
+
flex-direction: column;
|
|
133
|
+
gap: var(--space-16);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/* La colonne etire ses enfants : le rail de mesures garde sa largeur. */
|
|
137
|
+
.hubr_me > :first-child {
|
|
138
|
+
align-self: flex-start;
|
|
139
|
+
}
|
|
140
|
+
</style>
|