@tekkare/romulus 0.1.250 → 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.
Files changed (270) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/components/BarChart.vue +1 -0
  3. package/dist/runtime/components/ChoroplethMap.vue +4 -1
  4. package/dist/runtime/internal/geo/fr-regions.json +1 -1
  5. package/dist/runtime/utils/chart.d.ts +6 -3
  6. package/dist/runtime/utils/chart.js +15 -2
  7. package/layer/app/app.config.ts +6 -0
  8. package/layer/app/components/OipPubmedSummary.vue +223 -0
  9. package/layer/app/components/OipResourceDrawer.vue +331 -0
  10. package/layer/app/components/OipResourceDrawerLink.vue +40 -0
  11. package/layer/app/components/OipResourceField.vue +41 -0
  12. package/layer/app/components/OipResourceGenericCard.vue +54 -0
  13. package/layer/app/components/OipResourceSource.vue +50 -0
  14. package/layer/app/components/OipResourceTags.vue +65 -0
  15. package/layer/app/components/OipResourceView.vue +107 -0
  16. package/layer/app/components/oip-drugs/fiches/AssociationFiche.vue +775 -0
  17. package/layer/app/components/oip-drugs/fiches/BrandFiche.vue +1111 -0
  18. package/layer/app/components/oip-drugs/fiches/IndicationFiche.vue +182 -0
  19. package/layer/app/components/oip-drugs/fiches/JoFiche.vue +101 -0
  20. package/layer/app/components/oip-drugs/fiches/PndsFiche.vue +279 -0
  21. package/layer/app/components/oip-drugs/heart/JoCard.vue +314 -0
  22. package/layer/app/components/oip-drugs/heart/TextHighlight.vue +326 -0
  23. package/layer/app/components/oip-drugs/heart/ansm/BrandCard.vue +187 -0
  24. package/layer/app/components/oip-drugs/heart/ansm/CisDetail.vue +363 -0
  25. package/layer/app/components/oip-drugs/heart/ansm/CisTable.vue +167 -0
  26. package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyCard.vue +373 -0
  27. package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyFiche.vue +372 -0
  28. package/layer/app/components/oip-drugs/heart/associations/TranscriptionCard.vue +55 -0
  29. package/layer/app/components/oip-drugs/heart/elastic/SourceContainerElastic.vue +103 -0
  30. package/layer/app/components/oip-drugs/heart/france/BrandGroupCard.vue +450 -0
  31. package/layer/app/components/oip-drugs/heart/mitm/Card.vue +199 -0
  32. package/layer/app/components/oip-drugs/heart/mitm/Source.vue +23 -0
  33. package/layer/app/components/oip-drugs/heart/mitm/details/Overview.vue +381 -0
  34. package/layer/app/components/oip-drugs/heart/put/Card.vue +212 -0
  35. package/layer/app/components/oip-drugs/heart/results/AccesCard.vue +696 -0
  36. package/layer/app/components/oip-drugs/heart/results/AlertCard.vue +342 -0
  37. package/layer/app/components/oip-drugs/heart/results/AsmrCursor.vue +229 -0
  38. package/layer/app/components/oip-drugs/heart/results/EvalCard.vue +370 -0
  39. package/layer/app/components/oip-drugs/heart/results/IndicCard.vue +743 -0
  40. package/layer/app/components/oip-drugs/heart/results/MatchExplain.vue +243 -0
  41. package/layer/app/components/oip-drugs/heart/results/PrefRows.vue +105 -0
  42. package/layer/app/components/oip-drugs/heart/results/details/HasHistory.vue +487 -0
  43. package/layer/app/components/oip-drugs/heart/results/details/InternationalCountryCard.vue +461 -0
  44. package/layer/app/components/oip-drugs/heart/results/details/InternationalOverview.vue +200 -0
  45. package/layer/app/components/oip-drugs/heart/results/details/InternationalPriceDrawer.vue +647 -0
  46. package/layer/app/components/oip-drugs/heart/results/details/Monograph.vue +128 -0
  47. package/layer/app/components/oip-drugs/heart/results/details/OpinionDrawer.vue +535 -0
  48. package/layer/app/components/oip-drugs/heart/results/details/PresentationDrawer.vue +738 -0
  49. package/layer/app/components/oip-drugs/heart/results/details/Price.vue +227 -0
  50. package/layer/app/components/oip-drugs/heart/results/details/PriceOverview.vue +1261 -0
  51. package/layer/app/components/oip-drugs/heart/results/details/RecordDrawer.vue +494 -0
  52. package/layer/app/components/oip-drugs/heart/results/details/RecordList.vue +426 -0
  53. package/layer/app/components/oip-drugs/heart/results/les/Card.vue +340 -0
  54. package/layer/app/components/oip-drugs/heart/results/les/Drawer.vue +67 -0
  55. package/layer/app/components/oip-drugs/heart/results/les/IndicationDetail.vue +149 -0
  56. package/layer/app/components/oip-drugs/heart/results/les/Source.vue +20 -0
  57. package/layer/app/components/oip-drugs/heart/results/les/SourceTag.vue +39 -0
  58. package/layer/app/components/oip-drugs/heart/searchPage/DynamicSource.vue +29 -0
  59. package/layer/app/components/oip-drugs/medicam/market/Chart.vue +121 -0
  60. package/layer/app/components/oip-drugs/outpatient/ProductEvolution.vue +236 -0
  61. package/layer/app/components/oip-drugs/resources/Ansm.vue +75 -0
  62. package/layer/app/components/oip-drugs/resources/Association.vue +30 -0
  63. package/layer/app/components/oip-drugs/resources/Brand.vue +65 -0
  64. package/layer/app/components/oip-drugs/resources/Contribution.vue +216 -0
  65. package/layer/app/components/oip-drugs/resources/Hospital.vue +151 -0
  66. package/layer/app/components/oip-drugs/resources/Indication.vue +54 -0
  67. package/layer/app/components/oip-drugs/resources/Jo.vue +57 -0
  68. package/layer/app/components/oip-drugs/resources/Medicam.vue +140 -0
  69. package/layer/app/components/oip-drugs/resources/Mitm.vue +84 -0
  70. package/layer/app/components/oip-drugs/resources/NationalAssembly.vue +93 -0
  71. package/layer/app/components/oip-drugs/resources/Outpatient.vue +97 -0
  72. package/layer/app/components/oip-drugs/resources/Pnds.vue +24 -0
  73. package/layer/app/components/oip-drugs/resources/Price.vue +106 -0
  74. package/layer/app/components/oip-drugs/resources/Put.vue +143 -0
  75. package/layer/app/components/oip-science/appel-a-projet/Cards.vue +162 -0
  76. package/layer/app/components/oip-science/clinical-trials/Cards.vue +382 -0
  77. package/layer/app/components/oip-science/clinical-trials/CardsGlobal.vue +273 -0
  78. package/layer/app/components/oip-science/clinical-trials/LinkedList.vue +366 -0
  79. package/layer/app/components/oip-science/clinical-trials/PairBadge.vue +25 -0
  80. package/layer/app/components/oip-science/clinical-trials/PairBody.vue +182 -0
  81. package/layer/app/components/oip-science/clinical-trials/SitesDrawer.vue +95 -0
  82. package/layer/app/components/oip-science/common/Form.vue +73 -0
  83. package/layer/app/components/oip-science/common/MatchAvgTag.vue +283 -0
  84. package/layer/app/components/oip-science/common/NoData.vue +16 -0
  85. package/layer/app/components/oip-science/common/ScoreBadge.vue +35 -0
  86. package/layer/app/components/oip-science/common/Source.vue +31 -0
  87. package/layer/app/components/oip-science/common/TableTags.vue +279 -0
  88. package/layer/app/components/oip-science/common/Timeline.vue +104 -0
  89. package/layer/app/components/oip-science/common/ToolTips.vue +89 -0
  90. package/layer/app/components/oip-science/cross/publicationPubmed.vue +484 -0
  91. package/layer/app/components/oip-science/crossData/CrossDataLocations.vue +71 -0
  92. package/layer/app/components/oip-science/ctgov/Investigators.vue +148 -0
  93. package/layer/app/components/oip-science/ctgov/Locations.vue +102 -0
  94. package/layer/app/components/oip-science/ctgov/Publications.vue +52 -0
  95. package/layer/app/components/oip-science/ctgov/Sponsors.vue +66 -0
  96. package/layer/app/components/oip-science/ctgov/StudyDescription.vue +1136 -0
  97. package/layer/app/components/oip-science/ctgov-centers/ClinicalTrials.vue +40 -0
  98. package/layer/app/components/oip-science/ctgov-centers/Publications.vue +50 -0
  99. package/layer/app/components/oip-science/ctgov-investigators/ClinicalTrials.vue +43 -0
  100. package/layer/app/components/oip-science/ctgov-investigators/Informations.vue +171 -0
  101. package/layer/app/components/oip-science/ctgov-investigators/Publications.vue +44 -0
  102. package/layer/app/components/oip-science/elastic/DateRangeFilter.vue +209 -0
  103. package/layer/app/components/oip-science/elastic/Filter.vue +719 -0
  104. package/layer/app/components/oip-science/elastic/MatchExplain.vue +152 -0
  105. package/layer/app/components/oip-science/establishments/Cards.vue +183 -0
  106. package/layer/app/components/oip-science/establishments/ClinicalTrials.vue +62 -0
  107. package/layer/app/components/oip-science/establishments/Hcps.vue +227 -0
  108. package/layer/app/components/oip-science/establishments/Informations.vue +263 -0
  109. package/layer/app/components/oip-science/establishments/LinkedList.vue +153 -0
  110. package/layer/app/components/oip-science/establishments/MatchedLabels.vue +194 -0
  111. package/layer/app/components/oip-science/establishments/PublicFinance.vue +62 -0
  112. package/layer/app/components/oip-science/euct/Investigators.vue +125 -0
  113. package/layer/app/components/oip-science/euct/Locations.vue +102 -0
  114. package/layer/app/components/oip-science/euct/Products.vue +101 -0
  115. package/layer/app/components/oip-science/euct/Publications.vue +89 -0
  116. package/layer/app/components/oip-science/euct/Sponsors.vue +86 -0
  117. package/layer/app/components/oip-science/euct/StudyDescription.vue +1075 -0
  118. package/layer/app/components/oip-science/euct-centers/ClinicalTrials.vue +40 -0
  119. package/layer/app/components/oip-science/euct-centers/Publications.vue +55 -0
  120. package/layer/app/components/oip-science/euct-investigators/ClinicalTrials.vue +41 -0
  121. package/layer/app/components/oip-science/euct-investigators/Informations.vue +171 -0
  122. package/layer/app/components/oip-science/euct-investigators/Publications.vue +51 -0
  123. package/layer/app/components/oip-science/hcps/AppelsAProjet.vue +62 -0
  124. package/layer/app/components/oip-science/hcps/Cards.vue +237 -0
  125. package/layer/app/components/oip-science/hcps/ClinicalTrials.vue +78 -0
  126. package/layer/app/components/oip-science/hcps/Informations.vue +296 -0
  127. package/layer/app/components/oip-science/hcps/LinkedList.vue +153 -0
  128. package/layer/app/components/oip-science/hcps/MatchedLabels.vue +207 -0
  129. package/layer/app/components/oip-science/hcps/Pubmed.vue +128 -0
  130. package/layer/app/components/oip-science/local/SliderTabs.vue +99 -0
  131. package/layer/app/components/oip-science/local/SliderTabsFull.vue +135 -0
  132. package/layer/app/components/oip-science/pubmed/Authors.vue +128 -0
  133. package/layer/app/components/oip-science/pubmed/Cards.vue +417 -0
  134. package/layer/app/components/oip-science/pubmed/ClinicalTrials.vue +71 -0
  135. package/layer/app/components/oip-science/resources/Phrc.vue +39 -0
  136. package/layer/app/composables/useOipChapterScroll.ts +43 -0
  137. package/layer/app/composables/useOipResourceHooks.ts +27 -0
  138. package/layer/app/composables/useOipResourceNav.ts +66 -0
  139. package/layer/app/composables/useOipResourceViews.ts +117 -0
  140. package/layer/app/composables/useOipResources.ts +83 -0
  141. package/layer/app/oip-drugs/PORTING.md +120 -0
  142. package/layer/app/oip-drugs/composables/useAssociationDetail.ts +220 -0
  143. package/layer/app/oip-drugs/composables/useAssociationExport.ts +63 -0
  144. package/layer/app/oip-drugs/composables/useAssociationLookup.ts +105 -0
  145. package/layer/app/oip-drugs/composables/useCardPrefOptions.ts +201 -0
  146. package/layer/app/oip-drugs/composables/useCurrency.ts +121 -0
  147. package/layer/app/oip-drugs/composables/useDirectusSources.ts +224 -0
  148. package/layer/app/oip-drugs/composables/useHeartBrandMatches.ts +112 -0
  149. package/layer/app/oip-drugs/composables/useHeartDetailSearches.ts +479 -0
  150. package/layer/app/oip-drugs/composables/useHeartIntlApprovals.ts +661 -0
  151. package/layer/app/oip-drugs/composables/useHeartLesIndication.ts +168 -0
  152. package/layer/app/oip-drugs/composables/useHeartMatchExplain.ts +231 -0
  153. package/layer/app/oip-drugs/composables/useHeartReports.ts +239 -0
  154. package/layer/app/oip-drugs/composables/useHeartSearchFields.ts +233 -0
  155. package/layer/app/oip-drugs/composables/useMergeByKey.ts +23 -0
  156. package/layer/app/oip-drugs/composables/useOipDrugsElastic.ts +621 -0
  157. package/layer/app/oip-drugs/composables/usePageEmpty.ts +58 -0
  158. package/layer/app/oip-drugs/composables/v-useSalesSource.ts +64 -0
  159. package/layer/app/oip-drugs/drugs.css +500 -0
  160. package/layer/app/oip-drugs/esIndices.ts +322 -0
  161. package/layer/app/oip-drugs/kinds.ts +264 -0
  162. package/layer/app/oip-drugs/locales/en.json +1571 -0
  163. package/layer/app/oip-drugs/locales/fr.json +1571 -0
  164. package/layer/app/oip-drugs/monographs/blincyto-has.vue +289 -0
  165. package/layer/app/oip-drugs/monographs/darzalex-has.vue +276 -0
  166. package/layer/app/oip-drugs/monographs/dupixent-has.vue +216 -0
  167. package/layer/app/oip-drugs/monographs/enhertu-has.vue +280 -0
  168. package/layer/app/oip-drugs/monographs/has-sein-2023.vue +1649 -0
  169. package/layer/app/oip-drugs/monographs/ibrance-has.vue +277 -0
  170. package/layer/app/oip-drugs/monographs/imfinzi-has.vue +293 -0
  171. package/layer/app/oip-drugs/monographs/keytruda-has.vue +334 -0
  172. package/layer/app/oip-drugs/monographs/kisqali-has.vue +201 -0
  173. package/layer/app/oip-drugs/monographs/opdivo-has.vue +231 -0
  174. package/layer/app/oip-drugs/monographs/ozempic-has.vue +186 -0
  175. package/layer/app/oip-drugs/monographs/tecentriq-has.vue +312 -0
  176. package/layer/app/oip-drugs/monographs/yescarta-has.vue +272 -0
  177. package/layer/app/oip-drugs/types/elastic.ts +113 -0
  178. package/layer/app/oip-drugs/types/es/agencies.ts +152 -0
  179. package/layer/app/oip-drugs/types/es/directory.ts +54 -0
  180. package/layer/app/oip-drugs/types/es/docByIndex.ts +151 -0
  181. package/layer/app/oip-drugs/types/es/openmedic.ts +67 -0
  182. package/layer/app/oip-drugs/types/es/outpatient.ts +71 -0
  183. package/layer/app/oip-drugs/types/es/portal.ts +130 -0
  184. package/layer/app/oip-drugs/types/es/retail.ts +107 -0
  185. package/layer/app/oip-drugs/types/es/statistics.ts +29 -0
  186. package/layer/app/oip-drugs/types/heart/CurrencyRate.ts +16 -0
  187. package/layer/app/oip-drugs/types/heart/ansm.ts +106 -0
  188. package/layer/app/oip-drugs/types/heart/tag.ts +29 -0
  189. package/layer/app/oip-drugs/utils/associationFields.ts +118 -0
  190. package/layer/app/oip-drugs/utils/contributions.ts +36 -0
  191. package/layer/app/oip-drugs/utils/countryMapping.ts +387 -0
  192. package/layer/app/oip-drugs/utils/esHighlight.ts +21 -0
  193. package/layer/app/oip-drugs/utils/exportSheets.ts +57 -0
  194. package/layer/app/oip-drugs/utils/heartIntlPrice.ts +228 -0
  195. package/layer/app/oip-drugs/utils/heartStyleAndFormat.ts +262 -0
  196. package/layer/app/oip-drugs/utils/heartStyleAnsm.ts +71 -0
  197. package/layer/app/oip-drugs/utils/latestDate.ts +31 -0
  198. package/layer/app/oip-drugs/utils/p-heartCardTags.ts +53 -0
  199. package/layer/app/oip-drugs/utils/priceExport.ts +269 -0
  200. package/layer/app/oip-drugs/utils/q-hasRatings.ts +43 -0
  201. package/layer/app/oip-drugs/utils/s-openCard.ts +20 -0
  202. package/layer/app/oip-drugs/utils/sourceUuids.ts +155 -0
  203. package/layer/app/oip-drugs/utils/styleAndFormat.ts +40 -0
  204. package/layer/app/oip-drugs/utils/v-salesSeries.ts +156 -0
  205. package/layer/app/oip-drugs/utils/v-scopeTags.ts +23 -0
  206. package/layer/app/oip-science/PORTING.md +93 -0
  207. package/layer/app/oip-science/assets/smartSelection.json +428 -0
  208. package/layer/app/oip-science/composables/useAuthorMatching.ts +342 -0
  209. package/layer/app/oip-science/composables/useCTCenter.ts +107 -0
  210. package/layer/app/oip-science/composables/useCTInvestigators.ts +107 -0
  211. package/layer/app/oip-science/composables/useEstablishmentCrossData.ts +139 -0
  212. package/layer/app/oip-science/composables/useEstablishmentMatching.ts +176 -0
  213. package/layer/app/oip-science/composables/useEuct.ts +418 -0
  214. package/layer/app/oip-science/composables/useEuctCenter.ts +107 -0
  215. package/layer/app/oip-science/composables/useEuctInvestigators.ts +107 -0
  216. package/layer/app/oip-science/composables/useGlobalClinicalTrials.ts +624 -0
  217. package/layer/app/oip-science/composables/useLinkedTrials.ts +83 -0
  218. package/layer/app/oip-science/composables/useOipElastic.ts +658 -0
  219. package/layer/app/oip-science/composables/useOipSearchExplain.ts +166 -0
  220. package/layer/app/oip-science/composables/usePubmed.ts +487 -0
  221. package/layer/app/oip-science/composables/useSearchFields.ts +153 -0
  222. package/layer/app/oip-science/indexConfig.json +794 -0
  223. package/layer/app/oip-science/locales/en.json +483 -0
  224. package/layer/app/oip-science/locales/fr.json +483 -0
  225. package/layer/app/oip-science/science.css +1182 -0
  226. package/layer/app/oip-science/utils/a-openCard.ts +23 -0
  227. package/layer/app/oip-science/utils/b-openCard.ts +35 -0
  228. package/layer/app/oip-science/utils/c-filterContext.ts +81 -0
  229. package/layer/app/oip-science/utils/f-types.ts +241 -0
  230. package/layer/app/oip-science/utils/frDiseaseTerms.ts +269 -0
  231. package/layer/app/oip-science/utils/matchMethod.ts +53 -0
  232. package/layer/app/oip-science/utils/sliderTabs.ts +13 -0
  233. package/layer/app/oip-science/utils/sources.ts +15 -0
  234. package/layer/app/oip-science/utils/styleAndFormat.ts +608 -0
  235. package/layer/app/oip-science/utils/toPresets.ts +7 -0
  236. package/layer/app/oip-science/utils/valueTable.ts +126 -0
  237. package/layer/app/plugins/oip-science-i18n.ts +17 -0
  238. package/layer/app/utils/oipFicheRoutes.ts +118 -0
  239. package/layer/app/utils/oipResources.ts +440 -0
  240. package/layer/nuxt.config.ts +22 -2
  241. package/layer/public/reports/blincyto-has.html +292 -0
  242. package/layer/public/reports/blincyto-has.pdf +0 -0
  243. package/layer/public/reports/darzalex-has.html +279 -0
  244. package/layer/public/reports/darzalex-has.pdf +0 -0
  245. package/layer/public/reports/dupixent-has.html +217 -0
  246. package/layer/public/reports/dupixent-has.pdf +0 -0
  247. package/layer/public/reports/enhertu-has.html +283 -0
  248. package/layer/public/reports/enhertu-has.pdf +0 -0
  249. package/layer/public/reports/has-sein-2023.html +1639 -0
  250. package/layer/public/reports/ibrance-has.html +280 -0
  251. package/layer/public/reports/ibrance-has.pdf +0 -0
  252. package/layer/public/reports/imfinzi-has.html +297 -0
  253. package/layer/public/reports/imfinzi-has.pdf +0 -0
  254. package/layer/public/reports/keytruda-has.html +337 -0
  255. package/layer/public/reports/keytruda-has.pdf +0 -0
  256. package/layer/public/reports/kisqali-has.html +202 -0
  257. package/layer/public/reports/kisqali-has.pdf +0 -0
  258. package/layer/public/reports/opdivo-has.html +232 -0
  259. package/layer/public/reports/opdivo-has.pdf +0 -0
  260. package/layer/public/reports/ozempic-has.html +188 -0
  261. package/layer/public/reports/ozempic-has.pdf +0 -0
  262. package/layer/public/reports/tecentriq-has.html +315 -0
  263. package/layer/public/reports/tecentriq-has.pdf +0 -0
  264. package/layer/public/reports/yescarta-has.html +275 -0
  265. package/layer/public/reports/yescarta-has.pdf +0 -0
  266. package/layer/server/api/oip/es.post.ts +99 -0
  267. package/layer/server/api/oip/pdf.get.ts +70 -0
  268. package/layer/server/api/oip/reports.get.ts +98 -0
  269. package/layer/server/api/oip/resource-types.get.ts +22 -0
  270. package/package.json +1 -1
@@ -0,0 +1,121 @@
1
+ <!--
2
+ Graphe d'evolution d'un secteur Medic'AM, porte de medicam/market/chart de
3
+ fr_drugs_app. Le parent fait la requete du mensuel, une fois pour tous les
4
+ graphes : le bloc recoit les lignes et se filtre sur son secteur et sa
5
+ mesure. Source et date passent en props (ex-store retail).
6
+ -->
7
+ <template>
8
+ <div class="oip-drugs width_100">
9
+ <RmLoadingState v-if="loading" :lines="1" :chart-height="400" />
10
+ <RmChartCard v-else :title="cardTitle" :source="source"
11
+ :verified="verified" :lang="lang"
12
+ :state="chartContent.length > 0 ? 'ready' : 'empty'">
13
+ <RmLineChart :key="chartKey" :categories="chartHead" :series="chartContent" :height="400"
14
+ number-format="compact" />
15
+ </RmChartCard>
16
+ </div>
17
+ </template>
18
+
19
+ <script setup lang="ts">
20
+ import { reportPageEmpty } from "../../../../oip-drugs/composables/usePageEmpty";
21
+ import { salesCurves, salesPeriods } from "../../../../oip-drugs/utils/v-salesSeries";
22
+ import { SALES_SOURCE_FALLBACKS } from "../../../../oip-drugs/composables/v-useSalesSource";
23
+
24
+ // Data
25
+ const chartKey = ref(0 as number);
26
+
27
+ // Props
28
+ const props = defineProps({
29
+ rows: {
30
+ type: Array as PropType<any[]>,
31
+ required: true,
32
+ },
33
+ loading: {
34
+ type: Boolean,
35
+ required: true,
36
+ },
37
+ selectedLevel: {
38
+ type: String,
39
+ required: true,
40
+ },
41
+ selectedLabel: {
42
+ type: Object,
43
+ required: true,
44
+ },
45
+ selectedMeasure: {
46
+ type: String,
47
+ required: true,
48
+ },
49
+ selectedSwitch: {
50
+ type: Boolean,
51
+ required: true,
52
+ },
53
+ selectedTitle: {
54
+ type: String,
55
+ required: true,
56
+ },
57
+ // Titre complet, quand l'appelant le compose (mesure, secteur, periode) :
58
+ // sans lui, la carte se contente de « Evolution » et du secteur.
59
+ title: {
60
+ type: String,
61
+ default: "",
62
+ },
63
+ selectedSector: {
64
+ type: String,
65
+ required: true,
66
+ },
67
+ lang: {
68
+ type: String as PropType<"fr" | "en">,
69
+ default: "fr",
70
+ },
71
+ // Ex-store retail (medicamSource, medicamUpdateDate).
72
+ source: {
73
+ type: String,
74
+ default: SALES_SOURCE_FALLBACKS.MEDICAM,
75
+ },
76
+ verified: {
77
+ type: String,
78
+ default: "/",
79
+ },
80
+ });
81
+
82
+ // Le titre de la carte porte le secteur lu : c'est ce que faisait le slot
83
+ // #title du graphe Auriga.
84
+ const cardTitle = computed(() =>
85
+ props.title ||
86
+ (props.lang === "fr"
87
+ ? "Évolution " + props.selectedTitle
88
+ : props.selectedTitle + " Evolution")
89
+ );
90
+
91
+ const data = computed(() => props.rows);
92
+
93
+ // Methods
94
+ const chartHead = computed(() => salesPeriods(data.value));
95
+ const chartContent = computed(() => {
96
+ const measure = props.selectedSector + "_" + props.selectedMeasure;
97
+ return salesCurves(
98
+ data.value.map((i: any) => ({ ...i, volume: i[measure] })),
99
+ props.selectedLabel as any[],
100
+ props.selectedSwitch,
101
+ );
102
+ });
103
+
104
+ // Watch
105
+ watch(chartContent, () => {
106
+ chartKey.value = chartKey.value + 1;
107
+ });
108
+
109
+ /**
110
+ * Le bloc dit a la vue s'il est vide : elle montre un seul etat vide a la
111
+ * place d'un par carte quand ils se vident tous ensemble. Pas avant la fin du
112
+ * chargement, sinon l'etat vide passerait devant les squelettes.
113
+ */
114
+ reportPageEmpty(() => !props.loading && chartContent.value.length === 0);
115
+ </script>
116
+
117
+ <style scoped>
118
+ .width_100 {
119
+ width: 100%;
120
+ }
121
+ </style>
@@ -0,0 +1,236 @@
1
+ <!--
2
+ Evolution du marche Outpatient (PHMEV) d'un ou plusieurs codes, portee de
3
+ outpatient/productEvolution de fr_drugs_app. La requete passe par
4
+ oipEsSearch (ex-useElasticGeneral, plus d'await au niveau du setup : le
5
+ composant se monte sans Suspense et charge a l'affichage). La mesure lue
6
+ (ex-store outpatient) passe en prop.
7
+ -->
8
+ <template>
9
+ <div class="oip-drugs width_100">
10
+ <RmLoadingState v-if="loading" :lines="1" :chart-height="450" />
11
+ <RmChartCard v-else :title="cardTitle" :tags="cardTags" :source="source"
12
+ :verified="verified" :lang="lang"
13
+ :state="chartContent.length > 0 ? 'ready' : 'empty'">
14
+ <RmLineChart :key="chartKey" :categories="chartHead" :series="chartContent" :height="450"
15
+ number-format="compact" />
16
+ </RmChartCard>
17
+ <!-- Le graphe donne la forme, le tableau donne les chiffres : meme
18
+ donnee, relevable et copiable ligne a ligne. -->
19
+ <RmTableCard v-if="!loading" class="margin_top">
20
+ <template #header>
21
+ <div>
22
+ <p class="rm-table-card__title">{{ lang === "fr" ? "Données d’évolution" : "Evolution data" }}</p>
23
+ <RmTagRow class="kpi-card-tags" :tags="cardTags" />
24
+ <RmSourceLine :source="source" :verified="verified" :lang="lang" />
25
+ </div>
26
+ <p class="rm-table-card__caption">{{ dataTable.rows.length }}
27
+ {{ dataTable.rows.length > 1
28
+ ? (lang === "fr" ? "lignes affichées" : "rows displayed")
29
+ : (lang === "fr" ? "ligne affichée" : "row displayed") }}</p>
30
+ </template>
31
+ <RmTable :columns="dataTable.columns" :rows="dataTable.rows" max-height="420px"
32
+ :empty-text="lang === 'fr' ? 'Aucune donnée' : 'No data'">
33
+ <!-- Volume ou part de marche : le tableau lit la meme valeur que la
34
+ courbe, donc le meme format. -->
35
+ <template v-for="key in dataTable.valueKeys" :key="key" #[key]="{ value }">
36
+ <span v-if="value === null">-</span>
37
+ <span v-else-if="selectedSwitch">{{ rmNumber(Math.round(Number(value))) }}</span>
38
+ <span v-else>{{ rmDecimal(Number(value), 1) }} %</span>
39
+ </template>
40
+ </RmTable>
41
+ </RmTableCard>
42
+ </div>
43
+ </template>
44
+
45
+ <script setup lang="ts">
46
+ import { oipEsSearch } from "../../../composables/useOipResources";
47
+ import { reportPageEmpty } from "../../../oip-drugs/composables/usePageEmpty";
48
+ import { scopeTags } from "../../../oip-drugs/utils/v-scopeTags";
49
+ import {
50
+ OUTPATIENT_DEFAULT_MEASURE,
51
+ OUTPATIENT_MEASURES,
52
+ salesCurves,
53
+ salesPeriods,
54
+ } from "../../../oip-drugs/utils/v-salesSeries";
55
+ import { SALES_SOURCE_FALLBACKS } from "../../../oip-drugs/composables/v-useSalesSource";
56
+
57
+ // Data
58
+ const chartKey = ref(0 as number);
59
+
60
+ // Props
61
+ const props = defineProps({
62
+ esIndex: {
63
+ type: String,
64
+ required: true,
65
+ },
66
+ selectedLabel: {
67
+ type: Array as PropType<any[]>,
68
+ required: true,
69
+ },
70
+ selectedItem: {
71
+ type: Array as PropType<string[]>,
72
+ required: true,
73
+ },
74
+ selectedSwitch: {
75
+ type: Boolean,
76
+ required: true,
77
+ },
78
+ // Ex-store outpatient (outpatientSelectedMeasureIndex).
79
+ measureIndex: {
80
+ type: Number,
81
+ default: OUTPATIENT_DEFAULT_MEASURE,
82
+ },
83
+ lang: {
84
+ type: String as PropType<"fr" | "en">,
85
+ default: "fr",
86
+ },
87
+ // Ex-store outpatient (outpatientSource, outpatientUpdateDate).
88
+ source: {
89
+ type: String,
90
+ default: SALES_SOURCE_FALLBACKS.OUTPATIENT,
91
+ },
92
+ verified: {
93
+ type: String,
94
+ default: "/",
95
+ },
96
+ });
97
+
98
+ const measureLabel = computed(
99
+ () => (props.lang === "fr" ? OUTPATIENT_MEASURES.fr : OUTPATIENT_MEASURES.en)[props.measureIndex] ?? "",
100
+ );
101
+ const selectedMetric = computed(() => OUTPATIENT_MEASURES.variables[props.measureIndex] ?? "value_public_price");
102
+ // Le titre de la carte porte la mesure lue : c'est ce que faisait le slot
103
+ // #title du graphe Auriga.
104
+ const cardTitle = computed(() => (props.lang === "fr" ? "Évolution Totale Marché Sorties Hospitalières (Hôpitaux + Espic)" : "Total Outpatient Market (Hospital + Espic) Evolution"));
105
+ // Mesure et lieu lus, en etiquettes sous le titre (cf. `scopeTags`).
106
+ const cardTags = computed(() => scopeTags({ measure: measureLabel.value, geo: "France" }));
107
+
108
+ // Query
109
+ const esQuery = computed(() => {
110
+ const { selectedItem } = props;
111
+ const selectedHco = ["TOTAL"];
112
+
113
+ let query = {} as any;
114
+ let obj = {} as any;
115
+
116
+ if (selectedItem.length === 0) {
117
+ query = {
118
+ size: 2000,
119
+ query: {
120
+ bool: {
121
+ must: [{ bool: { should: [] } }],
122
+ },
123
+ },
124
+ };
125
+ obj = {
126
+ match_none: {},
127
+ };
128
+ query.query.bool.must[0].bool.should.push(obj);
129
+ }
130
+ if (selectedItem.length > 0) {
131
+ query = {
132
+ size: 2000,
133
+ query: {
134
+ bool: {
135
+ must: [{ bool: { should: [] } }, { bool: { should: [] } }],
136
+ },
137
+ },
138
+ };
139
+ // Filter code
140
+ for (let i = 0; i < selectedItem.length; i++) {
141
+ obj = {
142
+ match: {
143
+ "code.keyword": selectedItem[i],
144
+ },
145
+ };
146
+ query.query.bool.must[0].bool.should.push(obj);
147
+ }
148
+ // Filter hco_et_code === "TOTAL"
149
+ for (let i = 0; i < selectedHco.length; i++) {
150
+ obj = {
151
+ match: {
152
+ "hco_et_code.keyword": selectedHco[i],
153
+ },
154
+ };
155
+ query.query.bool.must[1].bool.should.push(obj);
156
+ }
157
+ }
158
+
159
+ return query;
160
+ });
161
+
162
+ const hits = ref<any[]>([]);
163
+ const loading = ref(true);
164
+
165
+ async function load() {
166
+ loading.value = true;
167
+ try {
168
+ const response: any = await oipEsSearch("drugs", props.esIndex, esQuery.value);
169
+ hits.value = response?.hits?.hits ?? [];
170
+ } catch {
171
+ hits.value = [];
172
+ } finally {
173
+ loading.value = false;
174
+ }
175
+ }
176
+
177
+ onMounted(load);
178
+ watch(() => [props.esIndex, JSON.stringify(esQuery.value)], load);
179
+
180
+ // Methods
181
+ const filteredResult = computed(() => {
182
+ let result = hits.value.map((i: any) => i["_source"]);
183
+ const metric = selectedMetric.value;
184
+
185
+ // Filter only total hospital rows
186
+ result = result.filter((i: any) => i.hco_et_code === "TOTAL");
187
+ // Filter selected codes
188
+ result = result.filter((i: any) => i.code !== "TOTAL");
189
+
190
+ // All periods in column
191
+ const p0_period = result.map((i: any) => i.max_period)[0];
192
+ const p1_period = (Number(p0_period) - 1).toString();
193
+ const p2_period = (Number(p0_period) - 2).toString();
194
+ const p3_period = (Number(p0_period) - 3).toString();
195
+ const p4_period = (Number(p0_period) - 4).toString();
196
+
197
+ const p0 = result.map((i: any) => ({ ...i, volume: i[metric + "_p0"], period: p0_period }));
198
+ const p1 = result.map((i: any) => ({ ...i, volume: i[metric + "_p1"], period: p1_period }));
199
+ const p2 = result.map((i: any) => ({ ...i, volume: i[metric + "_p2"], period: p2_period }));
200
+ const p3 = result.map((i: any) => ({ ...i, volume: i[metric + "_p3"], period: p3_period }));
201
+ const p4 = result.map((i: any) => ({ ...i, volume: i[metric + "_p4"], period: p4_period }));
202
+ return ([] as any[]).concat(p0, p1, p2, p3, p4);
203
+ });
204
+
205
+ const chartHead = computed(() => salesPeriods(filteredResult.value));
206
+ const chartContent = computed(() => salesCurves(filteredResult.value, props.selectedLabel, props.selectedSwitch));
207
+
208
+ // Watch
209
+ watch(chartContent, () => {
210
+ chartKey.value = chartKey.value + 1;
211
+ });
212
+
213
+ // Le meme jeu de series, mis a plat : une ligne par courbe, une colonne par
214
+ // periode.
215
+ const dataTable = computed(() =>
216
+ rmSeriesTable(chartHead.value, chartContent.value, {
217
+ label: props.lang === "fr" ? "Produit" : "Product",
218
+ })
219
+ );
220
+
221
+ /**
222
+ * Le bloc dit a la vue s'il est vide, une fois la reponse arrivee : elle
223
+ * montre alors un seul etat vide.
224
+ */
225
+ reportPageEmpty(() => !loading.value && chartContent.value.length === 0);
226
+ </script>
227
+
228
+ <style scoped>
229
+ .width_100 {
230
+ width: 100%;
231
+ }
232
+
233
+ .margin_top {
234
+ margin-top: 8px;
235
+ }
236
+ </style>
@@ -0,0 +1,75 @@
1
+ <!--
2
+ Une specialite ANSM (CIS) rangee dans un projet (portage de
3
+ pages/hubr/heart/ansm/details/[id] de fr_drugs_app). La page relit le
4
+ document par son `_id` puis renvoie a la fiche marque, onglet ANSM : on
5
+ monte cette fiche, sur ce CIS. Sans marque, le bandeau de la page et le
6
+ detail du CIS (celui de l'onglet ANSM de la fiche marque).
7
+ -->
8
+ <template>
9
+ <div class="oip-drugs oip-drugs-rv-ansm">
10
+ <RmLoadingState v-if="pending" spinner />
11
+
12
+ <OipDrugsFichesBrandFiche
13
+ v-else-if="brand"
14
+ v-model:tab="tab"
15
+ :brand="brand"
16
+ :cis="docId"
17
+ :lang="lang"
18
+ :highlight="highlight"
19
+ >
20
+ <template #title-link><slot name="title-link" /></template>
21
+ </OipDrugsFichesBrandFiche>
22
+
23
+ <div v-else-if="source" class="arg_page_layout">
24
+ <RmPageHeader :eyebrow="$t('oipDrugs.heart.ansm.tabs.ansm')">
25
+ <template #title>
26
+ {{ source.cis_label || $t('oipDrugs.heart.ansm.details') }}
27
+ <slot name="title-link" />
28
+ </template>
29
+ <p class="oip_filter_label">
30
+ {{ [source.cis_code, source.atc5_french_code_label, source.owner].filter(Boolean).join(', ') }}
31
+ </p>
32
+ </RmPageHeader>
33
+ <div class="oip-drugs-rv-ansm__body">
34
+ <OipDrugsHeartAnsmCisDetail :cis="source" :sku-count="1" />
35
+ </div>
36
+ </div>
37
+
38
+ <RmEmptyState
39
+ v-else
40
+ icon="FileX"
41
+ :title="lang === 'en' ? 'Record unavailable' : 'Fiche indisponible'"
42
+ :text="lang === 'en' ? 'The record is no longer in the data.' : 'La fiche n\'est plus dans la donnée.'"
43
+ />
44
+ </div>
45
+ </template>
46
+
47
+ <script setup lang="ts">
48
+ import { oipEsGet } from "../../../composables/useOipResources";
49
+ import { ES_INDEX } from "../../../oip-drugs/esIndices";
50
+
51
+ const props = withDefaults(
52
+ defineProps<{ id: string; type?: string; highlight?: string[]; lang?: "fr" | "en" }>(),
53
+ { type: "FrAnsmProduct", highlight: () => [], lang: "fr" },
54
+ );
55
+
56
+ /** L'onglet de la fiche marque, tenu ici (la page l'ecrivait dans `?tab=`). */
57
+ const tab = ref("ansm");
58
+
59
+ const { data: hit, pending } = useAsyncData(
60
+ () => `oip-drugs-ansm-${props.id}`,
61
+ () => oipEsGet<any>("drugs", ES_INDEX.CIS_ANSM, props.id),
62
+ { server: false, watch: [() => props.id] },
63
+ );
64
+
65
+ const source = computed(() => hit.value?._source ?? null);
66
+ const docId = computed(() => hit.value?._id ?? props.id);
67
+ const brand = computed(() => (source.value?.brand ? String(source.value.brand) : ""));
68
+ </script>
69
+
70
+ <style scoped>
71
+ .oip-drugs-rv-ansm__body {
72
+ box-sizing: border-box;
73
+ padding: var(--space-24);
74
+ }
75
+ </style>
@@ -0,0 +1,30 @@
1
+ <!--
2
+ Vue de ressource d'une association de patients (FrPatientAssociation) :
3
+ le `resourceId` est le nom regroupe, `_id` de l'annuaire. Rien a relire, la
4
+ fiche charge ses donnees elle-meme.
5
+ -->
6
+ <template>
7
+ <OipDrugsFichesAssociationFiche
8
+ v-model:tab="tab"
9
+ class="oip-drugs"
10
+ :label="id"
11
+ :lang="lang"
12
+ :highlight="highlight"
13
+ >
14
+ <template #title-link><slot name="title-link" /></template>
15
+ </OipDrugsFichesAssociationFiche>
16
+ </template>
17
+
18
+ <script setup lang="ts">
19
+ withDefaults(
20
+ defineProps<{
21
+ id: string;
22
+ type?: string;
23
+ lang?: "fr" | "en";
24
+ highlight?: string[];
25
+ }>(),
26
+ { type: "FrPatientAssociation", lang: "fr", highlight: () => [] },
27
+ );
28
+
29
+ const tab = ref("1");
30
+ </script>
@@ -0,0 +1,65 @@
1
+ <!--
2
+ Vue de ressource `FrHasBrand` : la marque rangee dans un projet, par l'`_id`
3
+ de son document BRAND_HAS. Relit le document pour son `brand_group`, puis
4
+ monte la fiche marque entiere (cf. fiches/BrandFiche).
5
+ -->
6
+ <template>
7
+ <div class="oip-drugs">
8
+ <RmLoadingState v-if="loading" :lines="6" />
9
+ <BrandFiche
10
+ v-else-if="brand"
11
+ :brand="brand"
12
+ :tab="tab"
13
+ :lang="lang"
14
+ :highlight="highlight"
15
+ @update:tab="tab = $event"
16
+ >
17
+ <template #title-link><slot name="title-link" /></template>
18
+ </BrandFiche>
19
+ <RmEmptyState
20
+ v-else
21
+ icon="Pill"
22
+ :title="lang === 'en' ? 'Brand not found' : 'Marque introuvable'"
23
+ :text="lang === 'en' ? 'This record is no longer in the HAS index.' : 'Cette fiche ne figure plus dans l’index HAS.'"
24
+ />
25
+ </div>
26
+ </template>
27
+
28
+ <script setup lang="ts">
29
+ import { ES_INDEX } from "../../../oip-drugs/esIndices";
30
+ import useOipDrugsElastic from "../../../oip-drugs/composables/useOipDrugsElastic";
31
+ import BrandFiche from "../fiches/BrandFiche.vue";
32
+
33
+ const props = withDefaults(
34
+ defineProps<{
35
+ /** `_id` du document BRAND_HAS (le resourceId du projet). */
36
+ id: string;
37
+ type?: string;
38
+ lang?: "fr" | "en";
39
+ highlight?: string[];
40
+ }>(),
41
+ { type: "FrHasBrand", lang: "fr", highlight: () => [] },
42
+ );
43
+
44
+ const { queryCustomElastic } = useOipDrugsElastic();
45
+
46
+ const brand = ref<string>("");
47
+ const loading = ref(true);
48
+ /** Onglet ouvert, garde localement : le tiroir n'a pas d'URL a tenir. */
49
+ const tab = ref("");
50
+
51
+ async function load(id: string) {
52
+ loading.value = true;
53
+ brand.value = "";
54
+ const res: any = await queryCustomElastic({
55
+ index: ES_INDEX.BRAND_HAS,
56
+ customQuery: { query: { ids: { values: [id] } }, _source: ["brand_group"], size: 1 } as any,
57
+ onlyOne: true,
58
+ }).catch(() => null);
59
+ if (id !== props.id) return;
60
+ brand.value = res?.brand_group ?? "";
61
+ loading.value = false;
62
+ }
63
+
64
+ watch(() => props.id, (id) => load(id), { immediate: true });
65
+ </script>