@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.
Files changed (265) hide show
  1. package/dist/module.json +1 -1
  2. package/layer/app/app.config.ts +6 -0
  3. package/layer/app/components/OipPubmedSummary.vue +223 -0
  4. package/layer/app/components/OipResourceDrawer.vue +331 -0
  5. package/layer/app/components/OipResourceDrawerLink.vue +40 -0
  6. package/layer/app/components/OipResourceField.vue +41 -0
  7. package/layer/app/components/OipResourceGenericCard.vue +54 -0
  8. package/layer/app/components/OipResourceSource.vue +50 -0
  9. package/layer/app/components/OipResourceTags.vue +65 -0
  10. package/layer/app/components/OipResourceView.vue +107 -0
  11. package/layer/app/components/oip-drugs/fiches/AssociationFiche.vue +775 -0
  12. package/layer/app/components/oip-drugs/fiches/BrandFiche.vue +1111 -0
  13. package/layer/app/components/oip-drugs/fiches/IndicationFiche.vue +182 -0
  14. package/layer/app/components/oip-drugs/fiches/JoFiche.vue +101 -0
  15. package/layer/app/components/oip-drugs/fiches/PndsFiche.vue +279 -0
  16. package/layer/app/components/oip-drugs/heart/JoCard.vue +314 -0
  17. package/layer/app/components/oip-drugs/heart/TextHighlight.vue +326 -0
  18. package/layer/app/components/oip-drugs/heart/ansm/BrandCard.vue +187 -0
  19. package/layer/app/components/oip-drugs/heart/ansm/CisDetail.vue +363 -0
  20. package/layer/app/components/oip-drugs/heart/ansm/CisTable.vue +167 -0
  21. package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyCard.vue +373 -0
  22. package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyFiche.vue +372 -0
  23. package/layer/app/components/oip-drugs/heart/associations/TranscriptionCard.vue +55 -0
  24. package/layer/app/components/oip-drugs/heart/elastic/SourceContainerElastic.vue +103 -0
  25. package/layer/app/components/oip-drugs/heart/france/BrandGroupCard.vue +450 -0
  26. package/layer/app/components/oip-drugs/heart/mitm/Card.vue +199 -0
  27. package/layer/app/components/oip-drugs/heart/mitm/Source.vue +23 -0
  28. package/layer/app/components/oip-drugs/heart/mitm/details/Overview.vue +381 -0
  29. package/layer/app/components/oip-drugs/heart/put/Card.vue +212 -0
  30. package/layer/app/components/oip-drugs/heart/results/AccesCard.vue +696 -0
  31. package/layer/app/components/oip-drugs/heart/results/AlertCard.vue +342 -0
  32. package/layer/app/components/oip-drugs/heart/results/AsmrCursor.vue +229 -0
  33. package/layer/app/components/oip-drugs/heart/results/EvalCard.vue +370 -0
  34. package/layer/app/components/oip-drugs/heart/results/IndicCard.vue +743 -0
  35. package/layer/app/components/oip-drugs/heart/results/MatchExplain.vue +243 -0
  36. package/layer/app/components/oip-drugs/heart/results/PrefRows.vue +105 -0
  37. package/layer/app/components/oip-drugs/heart/results/details/HasHistory.vue +487 -0
  38. package/layer/app/components/oip-drugs/heart/results/details/InternationalCountryCard.vue +461 -0
  39. package/layer/app/components/oip-drugs/heart/results/details/InternationalOverview.vue +200 -0
  40. package/layer/app/components/oip-drugs/heart/results/details/InternationalPriceDrawer.vue +647 -0
  41. package/layer/app/components/oip-drugs/heart/results/details/Monograph.vue +128 -0
  42. package/layer/app/components/oip-drugs/heart/results/details/OpinionDrawer.vue +535 -0
  43. package/layer/app/components/oip-drugs/heart/results/details/PresentationDrawer.vue +738 -0
  44. package/layer/app/components/oip-drugs/heart/results/details/Price.vue +227 -0
  45. package/layer/app/components/oip-drugs/heart/results/details/PriceOverview.vue +1261 -0
  46. package/layer/app/components/oip-drugs/heart/results/details/RecordDrawer.vue +494 -0
  47. package/layer/app/components/oip-drugs/heart/results/details/RecordList.vue +426 -0
  48. package/layer/app/components/oip-drugs/heart/results/les/Card.vue +340 -0
  49. package/layer/app/components/oip-drugs/heart/results/les/Drawer.vue +67 -0
  50. package/layer/app/components/oip-drugs/heart/results/les/IndicationDetail.vue +149 -0
  51. package/layer/app/components/oip-drugs/heart/results/les/Source.vue +20 -0
  52. package/layer/app/components/oip-drugs/heart/results/les/SourceTag.vue +39 -0
  53. package/layer/app/components/oip-drugs/heart/searchPage/DynamicSource.vue +29 -0
  54. package/layer/app/components/oip-drugs/medicam/market/Chart.vue +121 -0
  55. package/layer/app/components/oip-drugs/outpatient/ProductEvolution.vue +236 -0
  56. package/layer/app/components/oip-drugs/resources/Ansm.vue +75 -0
  57. package/layer/app/components/oip-drugs/resources/Association.vue +30 -0
  58. package/layer/app/components/oip-drugs/resources/Brand.vue +65 -0
  59. package/layer/app/components/oip-drugs/resources/Contribution.vue +216 -0
  60. package/layer/app/components/oip-drugs/resources/Hospital.vue +151 -0
  61. package/layer/app/components/oip-drugs/resources/Indication.vue +54 -0
  62. package/layer/app/components/oip-drugs/resources/Jo.vue +57 -0
  63. package/layer/app/components/oip-drugs/resources/Medicam.vue +140 -0
  64. package/layer/app/components/oip-drugs/resources/Mitm.vue +84 -0
  65. package/layer/app/components/oip-drugs/resources/NationalAssembly.vue +93 -0
  66. package/layer/app/components/oip-drugs/resources/Outpatient.vue +97 -0
  67. package/layer/app/components/oip-drugs/resources/Pnds.vue +24 -0
  68. package/layer/app/components/oip-drugs/resources/Price.vue +106 -0
  69. package/layer/app/components/oip-drugs/resources/Put.vue +143 -0
  70. package/layer/app/components/oip-science/appel-a-projet/Cards.vue +162 -0
  71. package/layer/app/components/oip-science/clinical-trials/Cards.vue +382 -0
  72. package/layer/app/components/oip-science/clinical-trials/CardsGlobal.vue +273 -0
  73. package/layer/app/components/oip-science/clinical-trials/LinkedList.vue +366 -0
  74. package/layer/app/components/oip-science/clinical-trials/PairBadge.vue +25 -0
  75. package/layer/app/components/oip-science/clinical-trials/PairBody.vue +182 -0
  76. package/layer/app/components/oip-science/clinical-trials/SitesDrawer.vue +95 -0
  77. package/layer/app/components/oip-science/common/Form.vue +73 -0
  78. package/layer/app/components/oip-science/common/MatchAvgTag.vue +283 -0
  79. package/layer/app/components/oip-science/common/NoData.vue +16 -0
  80. package/layer/app/components/oip-science/common/ScoreBadge.vue +35 -0
  81. package/layer/app/components/oip-science/common/Source.vue +31 -0
  82. package/layer/app/components/oip-science/common/TableTags.vue +279 -0
  83. package/layer/app/components/oip-science/common/Timeline.vue +104 -0
  84. package/layer/app/components/oip-science/common/ToolTips.vue +89 -0
  85. package/layer/app/components/oip-science/cross/publicationPubmed.vue +484 -0
  86. package/layer/app/components/oip-science/crossData/CrossDataLocations.vue +71 -0
  87. package/layer/app/components/oip-science/ctgov/Investigators.vue +148 -0
  88. package/layer/app/components/oip-science/ctgov/Locations.vue +102 -0
  89. package/layer/app/components/oip-science/ctgov/Publications.vue +52 -0
  90. package/layer/app/components/oip-science/ctgov/Sponsors.vue +66 -0
  91. package/layer/app/components/oip-science/ctgov/StudyDescription.vue +1136 -0
  92. package/layer/app/components/oip-science/ctgov-centers/ClinicalTrials.vue +40 -0
  93. package/layer/app/components/oip-science/ctgov-centers/Publications.vue +50 -0
  94. package/layer/app/components/oip-science/ctgov-investigators/ClinicalTrials.vue +43 -0
  95. package/layer/app/components/oip-science/ctgov-investigators/Informations.vue +171 -0
  96. package/layer/app/components/oip-science/ctgov-investigators/Publications.vue +44 -0
  97. package/layer/app/components/oip-science/elastic/DateRangeFilter.vue +209 -0
  98. package/layer/app/components/oip-science/elastic/Filter.vue +719 -0
  99. package/layer/app/components/oip-science/elastic/MatchExplain.vue +152 -0
  100. package/layer/app/components/oip-science/establishments/Cards.vue +183 -0
  101. package/layer/app/components/oip-science/establishments/ClinicalTrials.vue +62 -0
  102. package/layer/app/components/oip-science/establishments/Hcps.vue +227 -0
  103. package/layer/app/components/oip-science/establishments/Informations.vue +263 -0
  104. package/layer/app/components/oip-science/establishments/LinkedList.vue +153 -0
  105. package/layer/app/components/oip-science/establishments/MatchedLabels.vue +194 -0
  106. package/layer/app/components/oip-science/establishments/PublicFinance.vue +62 -0
  107. package/layer/app/components/oip-science/euct/Investigators.vue +125 -0
  108. package/layer/app/components/oip-science/euct/Locations.vue +102 -0
  109. package/layer/app/components/oip-science/euct/Products.vue +101 -0
  110. package/layer/app/components/oip-science/euct/Publications.vue +89 -0
  111. package/layer/app/components/oip-science/euct/Sponsors.vue +86 -0
  112. package/layer/app/components/oip-science/euct/StudyDescription.vue +1075 -0
  113. package/layer/app/components/oip-science/euct-centers/ClinicalTrials.vue +40 -0
  114. package/layer/app/components/oip-science/euct-centers/Publications.vue +55 -0
  115. package/layer/app/components/oip-science/euct-investigators/ClinicalTrials.vue +41 -0
  116. package/layer/app/components/oip-science/euct-investigators/Informations.vue +171 -0
  117. package/layer/app/components/oip-science/euct-investigators/Publications.vue +51 -0
  118. package/layer/app/components/oip-science/hcps/AppelsAProjet.vue +62 -0
  119. package/layer/app/components/oip-science/hcps/Cards.vue +237 -0
  120. package/layer/app/components/oip-science/hcps/ClinicalTrials.vue +78 -0
  121. package/layer/app/components/oip-science/hcps/Informations.vue +296 -0
  122. package/layer/app/components/oip-science/hcps/LinkedList.vue +153 -0
  123. package/layer/app/components/oip-science/hcps/MatchedLabels.vue +207 -0
  124. package/layer/app/components/oip-science/hcps/Pubmed.vue +128 -0
  125. package/layer/app/components/oip-science/local/SliderTabs.vue +99 -0
  126. package/layer/app/components/oip-science/local/SliderTabsFull.vue +135 -0
  127. package/layer/app/components/oip-science/pubmed/Authors.vue +128 -0
  128. package/layer/app/components/oip-science/pubmed/Cards.vue +417 -0
  129. package/layer/app/components/oip-science/pubmed/ClinicalTrials.vue +71 -0
  130. package/layer/app/components/oip-science/resources/Phrc.vue +39 -0
  131. package/layer/app/composables/useOipChapterScroll.ts +43 -0
  132. package/layer/app/composables/useOipResourceHooks.ts +27 -0
  133. package/layer/app/composables/useOipResourceNav.ts +66 -0
  134. package/layer/app/composables/useOipResourceViews.ts +117 -0
  135. package/layer/app/composables/useOipResources.ts +83 -0
  136. package/layer/app/oip-drugs/PORTING.md +120 -0
  137. package/layer/app/oip-drugs/composables/useAssociationDetail.ts +220 -0
  138. package/layer/app/oip-drugs/composables/useAssociationExport.ts +63 -0
  139. package/layer/app/oip-drugs/composables/useAssociationLookup.ts +105 -0
  140. package/layer/app/oip-drugs/composables/useCardPrefOptions.ts +201 -0
  141. package/layer/app/oip-drugs/composables/useCurrency.ts +121 -0
  142. package/layer/app/oip-drugs/composables/useDirectusSources.ts +224 -0
  143. package/layer/app/oip-drugs/composables/useHeartBrandMatches.ts +112 -0
  144. package/layer/app/oip-drugs/composables/useHeartDetailSearches.ts +479 -0
  145. package/layer/app/oip-drugs/composables/useHeartIntlApprovals.ts +661 -0
  146. package/layer/app/oip-drugs/composables/useHeartLesIndication.ts +168 -0
  147. package/layer/app/oip-drugs/composables/useHeartMatchExplain.ts +231 -0
  148. package/layer/app/oip-drugs/composables/useHeartReports.ts +239 -0
  149. package/layer/app/oip-drugs/composables/useHeartSearchFields.ts +233 -0
  150. package/layer/app/oip-drugs/composables/useMergeByKey.ts +23 -0
  151. package/layer/app/oip-drugs/composables/useOipDrugsElastic.ts +621 -0
  152. package/layer/app/oip-drugs/composables/usePageEmpty.ts +58 -0
  153. package/layer/app/oip-drugs/composables/v-useSalesSource.ts +64 -0
  154. package/layer/app/oip-drugs/drugs.css +500 -0
  155. package/layer/app/oip-drugs/esIndices.ts +322 -0
  156. package/layer/app/oip-drugs/kinds.ts +264 -0
  157. package/layer/app/oip-drugs/locales/en.json +1571 -0
  158. package/layer/app/oip-drugs/locales/fr.json +1571 -0
  159. package/layer/app/oip-drugs/monographs/blincyto-has.vue +289 -0
  160. package/layer/app/oip-drugs/monographs/darzalex-has.vue +276 -0
  161. package/layer/app/oip-drugs/monographs/dupixent-has.vue +216 -0
  162. package/layer/app/oip-drugs/monographs/enhertu-has.vue +280 -0
  163. package/layer/app/oip-drugs/monographs/has-sein-2023.vue +1649 -0
  164. package/layer/app/oip-drugs/monographs/ibrance-has.vue +277 -0
  165. package/layer/app/oip-drugs/monographs/imfinzi-has.vue +293 -0
  166. package/layer/app/oip-drugs/monographs/keytruda-has.vue +334 -0
  167. package/layer/app/oip-drugs/monographs/kisqali-has.vue +201 -0
  168. package/layer/app/oip-drugs/monographs/opdivo-has.vue +231 -0
  169. package/layer/app/oip-drugs/monographs/ozempic-has.vue +186 -0
  170. package/layer/app/oip-drugs/monographs/tecentriq-has.vue +312 -0
  171. package/layer/app/oip-drugs/monographs/yescarta-has.vue +272 -0
  172. package/layer/app/oip-drugs/types/elastic.ts +113 -0
  173. package/layer/app/oip-drugs/types/es/agencies.ts +152 -0
  174. package/layer/app/oip-drugs/types/es/directory.ts +54 -0
  175. package/layer/app/oip-drugs/types/es/docByIndex.ts +151 -0
  176. package/layer/app/oip-drugs/types/es/openmedic.ts +67 -0
  177. package/layer/app/oip-drugs/types/es/outpatient.ts +71 -0
  178. package/layer/app/oip-drugs/types/es/portal.ts +130 -0
  179. package/layer/app/oip-drugs/types/es/retail.ts +107 -0
  180. package/layer/app/oip-drugs/types/es/statistics.ts +29 -0
  181. package/layer/app/oip-drugs/types/heart/CurrencyRate.ts +16 -0
  182. package/layer/app/oip-drugs/types/heart/ansm.ts +106 -0
  183. package/layer/app/oip-drugs/types/heart/tag.ts +29 -0
  184. package/layer/app/oip-drugs/utils/associationFields.ts +118 -0
  185. package/layer/app/oip-drugs/utils/contributions.ts +36 -0
  186. package/layer/app/oip-drugs/utils/countryMapping.ts +387 -0
  187. package/layer/app/oip-drugs/utils/esHighlight.ts +21 -0
  188. package/layer/app/oip-drugs/utils/exportSheets.ts +57 -0
  189. package/layer/app/oip-drugs/utils/heartIntlPrice.ts +228 -0
  190. package/layer/app/oip-drugs/utils/heartStyleAndFormat.ts +262 -0
  191. package/layer/app/oip-drugs/utils/heartStyleAnsm.ts +71 -0
  192. package/layer/app/oip-drugs/utils/latestDate.ts +31 -0
  193. package/layer/app/oip-drugs/utils/p-heartCardTags.ts +53 -0
  194. package/layer/app/oip-drugs/utils/priceExport.ts +269 -0
  195. package/layer/app/oip-drugs/utils/q-hasRatings.ts +43 -0
  196. package/layer/app/oip-drugs/utils/s-openCard.ts +20 -0
  197. package/layer/app/oip-drugs/utils/sourceUuids.ts +155 -0
  198. package/layer/app/oip-drugs/utils/styleAndFormat.ts +40 -0
  199. package/layer/app/oip-drugs/utils/v-salesSeries.ts +156 -0
  200. package/layer/app/oip-drugs/utils/v-scopeTags.ts +23 -0
  201. package/layer/app/oip-science/PORTING.md +93 -0
  202. package/layer/app/oip-science/assets/smartSelection.json +428 -0
  203. package/layer/app/oip-science/composables/useAuthorMatching.ts +342 -0
  204. package/layer/app/oip-science/composables/useCTCenter.ts +107 -0
  205. package/layer/app/oip-science/composables/useCTInvestigators.ts +107 -0
  206. package/layer/app/oip-science/composables/useEstablishmentCrossData.ts +139 -0
  207. package/layer/app/oip-science/composables/useEstablishmentMatching.ts +176 -0
  208. package/layer/app/oip-science/composables/useEuct.ts +418 -0
  209. package/layer/app/oip-science/composables/useEuctCenter.ts +107 -0
  210. package/layer/app/oip-science/composables/useEuctInvestigators.ts +107 -0
  211. package/layer/app/oip-science/composables/useGlobalClinicalTrials.ts +624 -0
  212. package/layer/app/oip-science/composables/useLinkedTrials.ts +83 -0
  213. package/layer/app/oip-science/composables/useOipElastic.ts +658 -0
  214. package/layer/app/oip-science/composables/useOipSearchExplain.ts +166 -0
  215. package/layer/app/oip-science/composables/usePubmed.ts +487 -0
  216. package/layer/app/oip-science/composables/useSearchFields.ts +153 -0
  217. package/layer/app/oip-science/indexConfig.json +794 -0
  218. package/layer/app/oip-science/locales/en.json +483 -0
  219. package/layer/app/oip-science/locales/fr.json +483 -0
  220. package/layer/app/oip-science/science.css +1182 -0
  221. package/layer/app/oip-science/utils/a-openCard.ts +23 -0
  222. package/layer/app/oip-science/utils/b-openCard.ts +35 -0
  223. package/layer/app/oip-science/utils/c-filterContext.ts +81 -0
  224. package/layer/app/oip-science/utils/f-types.ts +241 -0
  225. package/layer/app/oip-science/utils/frDiseaseTerms.ts +269 -0
  226. package/layer/app/oip-science/utils/matchMethod.ts +53 -0
  227. package/layer/app/oip-science/utils/sliderTabs.ts +13 -0
  228. package/layer/app/oip-science/utils/sources.ts +15 -0
  229. package/layer/app/oip-science/utils/styleAndFormat.ts +608 -0
  230. package/layer/app/oip-science/utils/toPresets.ts +7 -0
  231. package/layer/app/oip-science/utils/valueTable.ts +126 -0
  232. package/layer/app/plugins/oip-science-i18n.ts +17 -0
  233. package/layer/app/utils/oipFicheRoutes.ts +118 -0
  234. package/layer/app/utils/oipResources.ts +440 -0
  235. package/layer/nuxt.config.ts +22 -2
  236. package/layer/public/reports/blincyto-has.html +292 -0
  237. package/layer/public/reports/blincyto-has.pdf +0 -0
  238. package/layer/public/reports/darzalex-has.html +279 -0
  239. package/layer/public/reports/darzalex-has.pdf +0 -0
  240. package/layer/public/reports/dupixent-has.html +217 -0
  241. package/layer/public/reports/dupixent-has.pdf +0 -0
  242. package/layer/public/reports/enhertu-has.html +283 -0
  243. package/layer/public/reports/enhertu-has.pdf +0 -0
  244. package/layer/public/reports/has-sein-2023.html +1639 -0
  245. package/layer/public/reports/ibrance-has.html +280 -0
  246. package/layer/public/reports/ibrance-has.pdf +0 -0
  247. package/layer/public/reports/imfinzi-has.html +297 -0
  248. package/layer/public/reports/imfinzi-has.pdf +0 -0
  249. package/layer/public/reports/keytruda-has.html +337 -0
  250. package/layer/public/reports/keytruda-has.pdf +0 -0
  251. package/layer/public/reports/kisqali-has.html +202 -0
  252. package/layer/public/reports/kisqali-has.pdf +0 -0
  253. package/layer/public/reports/opdivo-has.html +232 -0
  254. package/layer/public/reports/opdivo-has.pdf +0 -0
  255. package/layer/public/reports/ozempic-has.html +188 -0
  256. package/layer/public/reports/ozempic-has.pdf +0 -0
  257. package/layer/public/reports/tecentriq-has.html +315 -0
  258. package/layer/public/reports/tecentriq-has.pdf +0 -0
  259. package/layer/public/reports/yescarta-has.html +275 -0
  260. package/layer/public/reports/yescarta-has.pdf +0 -0
  261. package/layer/server/api/oip/es.post.ts +99 -0
  262. package/layer/server/api/oip/pdf.get.ts +70 -0
  263. package/layer/server/api/oip/reports.get.ts +98 -0
  264. package/layer/server/api/oip/resource-types.get.ts +22 -0
  265. package/package.json +1 -1
@@ -0,0 +1,696 @@
1
+ <template>
2
+ <!-- Component for global result card -->
3
+ <!-- I would advise to create a separate card component for France results as there is more info displayed on the card -->
4
+ <RmSectionCard
5
+ class="oip-drugs"
6
+ v-if="getLatestHistory !== undefined"
7
+ position="top"
8
+ :class="inDetails ? '' : 'action'"
9
+ >
10
+ <template #header>
11
+ <div class="oip_row v-center justify-between full_flex" style="width: 100%">
12
+ <div class="oip_row gap-8 wrap v-center">
13
+ <RmTag v-if="inDetails && isFirst" variant="green">{{
14
+ $t("oipDrugs.heart.card.first")
15
+ }}</RmTag>
16
+ <RmTag v-if="opinionMatch" variant="green">
17
+ Match : {{ opinionMatch.fields.map(f => f.label).join(', ') }} - {{ $t('oipDrugs.heart.card.history.opinion') }} <RmDate :lang="locale" :date="opinionMatch.date" />
18
+ </RmTag>
19
+ <RmTag v-if="filterMatches.length > 0" variant="green">
20
+ Match : {{ filterMatches.join(', ') }}
21
+ </RmTag>
22
+ <RmTag variant="teal">{{ opinionCount }} {{ opinionCount > 1 ? (locale === 'fr' ? 'avis' : 'opinions') : (locale === 'fr' ? 'avis' : 'opinion') }}</RmTag>
23
+ <div class="oip_row v-center gap-8" v-if="locale === 'en' || showOriginal">
24
+ <p>{{ $t("oipDrugs.heart.translation") }}</p>
25
+ <div class="link" @click="showOriginal = !showOriginal">
26
+ {{ showOriginal ? $t("oipDrugs.heart.card.lang") : $t("oipDrugs.heart.card.original") }}
27
+ </div>
28
+ </div>
29
+ </div>
30
+ <div v-if="!inDetails" class="oip_row v-center gap-8" style="margin-left: auto">
31
+ <a
32
+ :href="detailsHref"
33
+ @click="onDetails"
34
+ >
35
+ <RmButton prefix-icon="Eye" variant="secondary">{{ $t("oipDrugs.heart.card.details") }}</RmButton>
36
+ </a>
37
+ </div>
38
+ </div>
39
+ </template>
40
+ <div class="card_display">
41
+ <div class="card_top">
42
+ <div class="oip_row gap-32 space-between">
43
+ <div class="card_header">
44
+ <div class="card_title">
45
+ <oip-drugs-heart-text-highlight
46
+ :text="`${product._source.brand_group} - ${getLatestHistory.molecule}`"
47
+ :queries="getMolHighlight.concat(getHighlight(['brand']))"
48
+ class="has_product_title"
49
+ />
50
+ </div>
51
+ </div>
52
+ </div>
53
+
54
+ <div class="oip_row v-center gap-8 card_head_text wrap">
55
+ <RmDate :lang="locale" :date="getLatestHistory.decision_date" />
56
+ <div class="sep">&nbsp;</div>
57
+ <span v-if="getLatestHistory.has_code"><strong class="has_code_prefix">{{ getLatestHistory.has_code.slice(0, 2) }}</strong>{{ getLatestHistory.has_code.slice(2) }}</span>
58
+ <span
59
+ v-if="
60
+ (getLatestHistory.has_code &&
61
+ getLatestHistory.has_code !== null &&
62
+ (locale === 'fr' || showOriginal) &&
63
+ (getLatestHistory.nature_of_request_regroup !== null ||
64
+ getLatestHistory.nature_of_request !== null)) ||
65
+ (locale === 'en' &&
66
+ !showOriginal &&
67
+ ((getLatestHistory.nature_of_request_regroup_en &&
68
+ getLatestHistory.nature_of_request_regroup_en !== null) ||
69
+ (getLatestHistory.nature_of_request_en &&
70
+ getLatestHistory.nature_of_request_en !== null)))
71
+ "
72
+ >-</span
73
+ >
74
+ <oip-drugs-heart-text-highlight
75
+ :text="
76
+ !showOriginal && locale === 'en'
77
+ ? getLatestHistory.nature_of_request_regroup_en !== null
78
+ ? getLatestHistory.nature_of_request_regroup_en
79
+ : getLatestHistory.nature_of_request_en
80
+ : getLatestHistory.nature_of_request_regroup !== null
81
+ ? getLatestHistory.nature_of_request_regroup
82
+ : getLatestHistory.nature_of_request
83
+ "
84
+ :queries="getStore('motif')"
85
+ v-if="
86
+ ((locale === 'fr' || showOriginal) &&
87
+ (getLatestHistory.nature_of_request_regroup !== null ||
88
+ getLatestHistory.nature_of_request !== null)) ||
89
+ (locale === 'en' &&
90
+ !showOriginal &&
91
+ ((getLatestHistory.nature_of_request_regroup_en &&
92
+ getLatestHistory.nature_of_request_regroup_en !== null) ||
93
+ (getLatestHistory.nature_of_request_en &&
94
+ getLatestHistory.nature_of_request_en !== null)))
95
+ "
96
+ />
97
+ </div>
98
+ </div>
99
+ <div class="oip_row v-center gap-8">
100
+ <div class="oip_list v-start gap-4">
101
+ <p class="oip_filter_label">ATC5</p>
102
+ <RmTag variant="transparent">
103
+ <oip-drugs-heart-text-highlight
104
+ v-if="getLatestHistory.atc5_code !== null"
105
+ :text="getLatestHistory.atc5_code?.join(', ')"
106
+ :queries="getMolHighlight"
107
+ />
108
+ <span v-else>{{ $t("oipDrugs.heart.card.not_provided") }}</span></RmTag>
109
+ </div>
110
+ <div
111
+ v-if="allCompanies.length > 0"
112
+ class="oip_list v-start gap-4"
113
+ style="flex: 1; min-width: 0;"
114
+ >
115
+ <p class="oip_filter_label">{{ $t("oipDrugs.heart.card.labels.comps") }}</p>
116
+ <RmTagRow :tags="allCompanies" />
117
+ </div>
118
+ </div>
119
+ <oip-drugs-heart-text-highlight
120
+ :key="textKey"
121
+ crop
122
+ have-read-more
123
+ :queries="getHighlightQueries"
124
+ :text="
125
+ locale === 'en' && !showOriginal ? accessOpinionEn : accessOpinion
126
+ "
127
+ v-if="getLatestHistory.essential || getLatestHistory.essential_en"
128
+ :lang="locale"
129
+ class="oip_body"
130
+ :id="`access_${getLatestHistory.brand}_${getLatestHistory.opinion_id}`"
131
+ />
132
+ <div
133
+ v-if="getLatestHistory.theme !== null || rareList.length > 0 || oncologyIcd10.length > 0 || oncologyTerms.length > 0"
134
+ class="oip_list v-start gap-16"
135
+ >
136
+ <div v-if="getLatestHistory.theme !== null" class="indic_category_row">
137
+ <div class="indic_category_label">
138
+ <RmIcon name="Tag" :size="16" color="#4A4A4A" />
139
+ <p class="oip_filter_label">{{ $t("oipDrugs.heart.card.labels.theme") }}</p>
140
+ </div>
141
+ <div class="indic_tags_wrap">
142
+ <RmTag variant="gray"
143
+ v-for="(theme, index) in locale === 'en' && !showOriginal
144
+ ? getLatestHistory.theme_en?.split(',')
145
+ : getLatestHistory.theme?.split(',')"
146
+ :key="index"
147
+ ><oip-drugs-heart-text-highlight :text="theme" :queries="getHighlightQueries"
148
+ /></RmTag>
149
+ </div>
150
+ </div>
151
+ <div v-if="rareList.length > 0" class="indic_category_row">
152
+ <div class="indic_category_label">
153
+ <RmIcon name="Virus" :size="16" color="#4A4A4A" />
154
+ <p class="oip_filter_label">
155
+ {{ locale === "fr" ? "Maladies Rares" : "Rare Diseases" }}
156
+ </p>
157
+ </div>
158
+ <div class="indic_tags_wrap">
159
+ <div v-for="(rare, index) in rareList.slice(0, maxTags)" :key="index">
160
+ <RmTag variant="gray">
161
+ <oip-drugs-heart-text-highlight
162
+ :text="rare"
163
+ :queries="getHighlight(['rare'])"
164
+ /></RmTag>
165
+ </div>
166
+ <div v-if="rareList.length > maxTags" class="indic_more_tag" @mouseenter="rareTooltip = true" @mouseleave="rareTooltip = false">
167
+ <RmTag variant="gray">+{{ rareList.length - maxTags }}</RmTag>
168
+ <div v-if="rareTooltip" class="indic_tooltip">
169
+ <RmTag variant="gray" v-for="(rare, i) in rareList.slice(maxTags)" :key="'rare-tip-' + i">
170
+ {{ rare }}
171
+ </RmTag>
172
+ </div>
173
+ </div>
174
+ </div>
175
+ </div>
176
+ <div v-if="oncologyIcd10.length > 0" class="indic_category_row">
177
+ <div class="indic_category_label">
178
+ <RmIcon name="Dna" :size="16" color="#4A4A4A" />
179
+ <p class="oip_filter_label">Oncology ICD-10</p>
180
+ </div>
181
+ <div class="indic_tags_wrap">
182
+ <RmTag v-for="(item, i) in oncologyIcd10.slice(0, maxTags)" :key="'icd-' + i" variant="gray">
183
+ {{ item }}
184
+ </RmTag>
185
+ <div v-if="oncologyIcd10.length > maxTags" class="indic_more_tag" @mouseenter="icdTooltip = true" @mouseleave="icdTooltip = false">
186
+ <RmTag variant="gray">+{{ oncologyIcd10.length - maxTags }}</RmTag>
187
+ <div v-if="icdTooltip" class="indic_tooltip">
188
+ <RmTag v-for="(item, i) in oncologyIcd10.slice(maxTags)" :key="'icd-tip-' + i" variant="gray">
189
+ {{ item }}
190
+ </RmTag>
191
+ </div>
192
+ </div>
193
+ </div>
194
+ </div>
195
+ <div v-if="oncologyTerms.length > 0" class="indic_category_row">
196
+ <div class="indic_category_label">
197
+ <RmIcon name="Stethoscope" :size="16" color="#4A4A4A" />
198
+ <p class="oip_filter_label">Oncology Terms</p>
199
+ </div>
200
+ <div class="indic_tags_wrap">
201
+ <RmTag v-for="(term, i) in oncologyTerms.slice(0, maxTags)" :key="'onco-' + i" variant="gray">
202
+ {{ term }}
203
+ </RmTag>
204
+ <div v-if="oncologyTerms.length > maxTags" class="indic_more_tag" @mouseenter="termsTooltip = true" @mouseleave="termsTooltip = false">
205
+ <RmTag variant="gray">+{{ oncologyTerms.length - maxTags }}</RmTag>
206
+ <div v-if="termsTooltip" class="indic_tooltip">
207
+ <RmTag v-for="(term, i) in oncologyTerms.slice(maxTags)" :key="'onco-tip-' + i" variant="gray">
208
+ {{ term }}
209
+ </RmTag>
210
+ </div>
211
+ </div>
212
+ </div>
213
+ </div>
214
+ </div>
215
+ <!-- Pied de carte : la source voyage avec le resultat plutot
216
+ qu'en tete de page. Elle est posee ici, dernier enfant de
217
+ .card_display, et non dans le slot #footer : celui-ci ne
218
+ s'affiche qu'avec `position="bottom"`, ce qui supprimerait
219
+ le slot #header dont la carte a besoin. Et pas en frere de
220
+ .card_display non plus : `.card_content` d'Auriga est un
221
+ flex row, le pied y deviendrait une colonne de droite. -->
222
+ <div class="card_source_footer">
223
+ <oip-drugs-heart-search-page-dynamic-source
224
+ :last-label="$t('oipDrugs.heart.sources.lastDecision')"
225
+ :last-date="getLatestHistory?.decision_date"
226
+ />
227
+ </div>
228
+ </div>
229
+ </RmSectionCard>
230
+ </template>
231
+
232
+ <script setup lang="ts">
233
+ import {
234
+ heartGetBestOpinionMatch,
235
+ heartGetMatchedFields,
236
+ heartGetRareHighlightTerms,
237
+ heartGetTaggingHighlightWords,
238
+ heartSplitSearchTerms,
239
+ } from "../../../../oip-drugs/composables/useHeartDetailSearches";
240
+ import { drugsBrandPath } from "../../../../oip-drugs/kinds";
241
+ import { useOipResourceNav } from "../../../../composables/useOipResourceNav";
242
+
243
+
244
+ // product = one result from ES query
245
+ const props = defineProps({
246
+ product: {
247
+ type: Object as PropType<Record<string, any>>,
248
+ required: true,
249
+ },
250
+ inDetails: {
251
+ type: Boolean,
252
+ default: false,
253
+ },
254
+ history: {
255
+ type: Array as PropType<any[]>,
256
+ default: () => [],
257
+ },
258
+ pathName: {
259
+ type: String,
260
+ require: true,
261
+ },
262
+ isFirst: {
263
+ type: Boolean,
264
+ default: false,
265
+ },
266
+ /** Termes cherches a surligner (ex-filterStore de la page de recherche). */
267
+ highlight: {
268
+ type: Array as PropType<string[]>,
269
+ default: () => [],
270
+ },
271
+ });
272
+
273
+ const showModal = ref(false);
274
+ const { locale } = useI18n();
275
+ const nav = useOipResourceNav();
276
+ const isFavOpinion = ref(0);
277
+ const showOriginal = ref(false);
278
+
279
+ const maxTags = 4;
280
+ const icdTooltip = ref(false);
281
+ const termsTooltip = ref(false);
282
+ const rareTooltip = ref(false);
283
+
284
+ const rareList = computed(() => {
285
+ const src = locale.value === 'fr' || showOriginal.value
286
+ ? props.product._source?.rare_diseases
287
+ : props.product._source?.rare_diseases_en;
288
+ return src?.map((a: any) => a.concat_disease_name_orpha_code) ?? [];
289
+ });
290
+
291
+ const oncologyIcd10 = computed(() => {
292
+ const tagging = locale.value === 'fr'
293
+ ? props.product._source?.oncology_tagging_fr
294
+ : props.product._source?.oncology_tagging_en;
295
+ if (!tagging || !Array.isArray(tagging)) return [];
296
+ const labels = new Set<string>();
297
+ tagging.forEach((t: any) => {
298
+ if (t.icd10 && Array.isArray(t.icd10)) {
299
+ t.icd10.forEach((icd: any) => {
300
+ if (icd.combined_label) labels.add(icd.combined_label);
301
+ });
302
+ }
303
+ });
304
+ return [...labels];
305
+ });
306
+
307
+ const oncologyTerms = computed(() => {
308
+ const tagging = locale.value === 'fr'
309
+ ? props.product._source?.oncology_tagging_fr
310
+ : props.product._source?.oncology_tagging_en;
311
+ if (!tagging || !Array.isArray(tagging)) return [];
312
+ const terms = new Set<string>();
313
+ tagging.forEach((t: any) => {
314
+ if (t.preferred_label) terms.add(t.preferred_label);
315
+ });
316
+ return [...terms];
317
+ });
318
+
319
+ const textKey = ref(0);
320
+
321
+ watch(
322
+ () => showOriginal.value,
323
+ () => {
324
+ textKey.value += 1;
325
+ }
326
+ );
327
+
328
+ function getHistoryLabel(hist: any) {
329
+ if (hist.opinion_type === "early_access_decision") {
330
+ return `AP`;
331
+ } else {
332
+ return `CT`;
333
+ }
334
+ }
335
+
336
+ const opinionCount = computed(() => {
337
+ return props.product._source.brand_history.filter((a: any) => a.document_type !== 'alert').length;
338
+ });
339
+
340
+ const getLatestHistory = computed(() => {
341
+ // If opinion filter has inner_hits, show the most recent matching opinion
342
+ if (props.product.inner_hits?.opinion?.hits?.hits?.length > 0) {
343
+ const matchingOpinions = props.product.inner_hits.opinion.hits.hits
344
+ .map((h: any) => h._source)
345
+ .filter((o: any) => o.opinion_type === "early_access_decision")
346
+ .sort(
347
+ (a: any, b: any) =>
348
+ new Date(b.decision_date).getTime() -
349
+ new Date(a.decision_date).getTime()
350
+ );
351
+ if (matchingOpinions.length > 0) {
352
+ return matchingOpinions[0];
353
+ }
354
+ }
355
+
356
+ // Default: latest early_access_decision
357
+ return props.product._source.brand_history?.[0]?.opinion_type ===
358
+ "early_access_decision"
359
+ ? props.product._source.brand_history[0]
360
+ : props.product._source.brand_history?.find(
361
+ (a: any) => a.opinion_type === "early_access_decision"
362
+ );
363
+ });
364
+
365
+ const allCompanies = computed(() => {
366
+ return [...new Set<string>(
367
+ props.product._source.brand_history
368
+ .map((h: any) => h.company)
369
+ .filter((c: any) => c !== null && c !== undefined && c.length > 0)
370
+ )];
371
+ });
372
+
373
+ // fr_drugs_app relisait les filtres de sa page de recherche (filterStore) ;
374
+ // le layer ne recoit que les termes cherches (`highlight`).
375
+ const getStore = (filter: string): any[] => {
376
+ return filter === "Search Filter" ? props.highlight ?? [] : [];
377
+ };
378
+
379
+ const isHistoryMatch = computed(() => {
380
+ const innerHits = props.product.inner_hits
381
+ ? Object.keys(props.product.inner_hits)
382
+ : [];
383
+
384
+ let match = ref(true);
385
+ innerHits.forEach((hit) => {
386
+ if (
387
+ props.product.inner_hits[hit].hits.total.value > 0 &&
388
+ props.product.inner_hits[hit].hits.hits.filter(
389
+ (f: any) => f._source.opinion_id === getLatestHistory.value.opinion_id
390
+ ).length === 0
391
+ ) {
392
+ match.value = false;
393
+ }
394
+ });
395
+
396
+ return match.value;
397
+ });
398
+
399
+ const taggingData = computed(() => {
400
+ return locale.value === 'fr'
401
+ ? props.product._source?.oncology_tagging_fr
402
+ : props.product._source?.oncology_tagging_en;
403
+ });
404
+
405
+ const filterMatches = computed(() => {
406
+ const opinion = getLatestHistory.value;
407
+ if (!opinion) return [];
408
+ const parts: string[] = [];
409
+
410
+ const oncoTermsValues = getStore('oncologyTerms');
411
+ if (oncoTermsValues?.length > 0 && oncologyTerms.value.length > 0) {
412
+ const highlightWords = heartGetTaggingHighlightWords(taggingData.value, oncoTermsValues);
413
+ const fields = highlightWords.length > 0 ? heartGetMatchedFields(opinion, highlightWords, locale.value) : [];
414
+ parts.push(fields.length > 0 ? `Oncology Terms (${fields.map(f => f.label).join(', ')})` : 'Oncology Terms');
415
+ }
416
+
417
+ const oncoIcdValues = getStore('oncologyIcd10');
418
+ if (oncoIcdValues?.length > 0 && oncologyIcd10.value.length > 0) {
419
+ const highlightWords = heartGetTaggingHighlightWords(taggingData.value, oncoIcdValues);
420
+ const fields = highlightWords.length > 0 ? heartGetMatchedFields(opinion, highlightWords, locale.value) : [];
421
+ parts.push(fields.length > 0 ? `Oncology ICD-10 (${fields.map(f => f.label).join(', ')})` : 'Oncology ICD-10');
422
+ }
423
+
424
+ return parts;
425
+ });
426
+
427
+ const hasHeaderContent = computed(() => {
428
+ return (props.inDetails && props.isFirst) || !!opinionMatch.value || filterMatches.value.length > 0 || locale.value === 'en' || showOriginal.value;
429
+ });
430
+
431
+ const opinionMatch = computed(() => {
432
+ return heartGetBestOpinionMatch(
433
+ props.product._source.brand_history,
434
+ getSearches.value,
435
+ locale.value
436
+ );
437
+ });
438
+
439
+ /** La fiche marque dans fr_drugs_app, sur l'avis matche. */
440
+ const detailsPath = computed(() => {
441
+ const base = drugsBrandPath(props.product._source.brand_group);
442
+ const code = opinionMatch.value?.hasCode ?? getLatestHistory.value?.has_code;
443
+ return code ? `${base}?code=${encodeURIComponent(code)}` : base;
444
+ });
445
+ const detailsHref = computed(() => nav.appHref("fr_drugs_app", detailsPath.value));
446
+
447
+ /** Le clic garde le Ctrl/Cmd-clic du navigateur (nouvel onglet). */
448
+ function onDetails(event: MouseEvent) {
449
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.button === 1) return;
450
+ event.preventDefault();
451
+ nav.openApp("fr_drugs_app", detailsPath.value);
452
+ }
453
+
454
+
455
+ function getHighlight(filters: string[]) {
456
+ const filterValues = ref<any[]>([]);
457
+ filters.forEach((filter) => {
458
+ filterValues.value.push(getStore(filter));
459
+ });
460
+ return filterValues.value
461
+ .concat(getSearches.value)
462
+ .flat()
463
+ .filter((f) => f && f.length > 0);
464
+ }
465
+ const getSearches = computed(() => {
466
+ const searches = getStore("Search Filter");
467
+ if (searches && searches.length > 0) {
468
+ return heartSplitSearchTerms(searches);
469
+ } else return [];
470
+ });
471
+
472
+ const getHighlightQueries = computed(() => {
473
+ const terms = [...getSearches.value];
474
+ const oncoTermsValues = getStore('oncologyTerms');
475
+ if (oncoTermsValues?.length > 0) {
476
+ terms.push(...heartGetTaggingHighlightWords(taggingData.value, oncoTermsValues));
477
+ }
478
+ const oncoIcdValues = getStore('oncologyIcd10');
479
+ if (oncoIcdValues?.length > 0) {
480
+ terms.push(...heartGetTaggingHighlightWords(taggingData.value, oncoIcdValues));
481
+ }
482
+ const rareValues = getStore('rare');
483
+ if (rareValues?.length > 0) {
484
+ terms.push(...heartGetRareHighlightTerms(rareValues));
485
+ }
486
+ return [...new Set(terms)];
487
+ });
488
+
489
+ const accessOpinionEn = computed(() => {
490
+ let accessEssential;
491
+ // `essential` peut etre null : la HAS ne remplit pas toujours l'essentiel.
492
+ const essential = getLatestHistory.value.essential ?? "";
493
+ if (getLatestHistory.value.opinion_status === "avis favorable") {
494
+ isFavOpinion.value = 2;
495
+ accessEssential = getLatestHistory.value.essential_en?.replace(
496
+ "Opinion against",
497
+ ""
498
+ );
499
+ } else if (
500
+ getLatestHistory.value.opinion_status === "autorisation renouvelée" ||
501
+ essential.includes("Autorisation d’accès précoce renouvelée") ||
502
+ essential.includes("L'autorisation d’accès précoce est renouvelée")
503
+ ) {
504
+ isFavOpinion.value = 3;
505
+ accessEssential = getLatestHistory.value.essential_en;
506
+ } else if (getLatestHistory.value.opinion_status === "avis défavorable") {
507
+ isFavOpinion.value = 1;
508
+ accessEssential = getLatestHistory.value.essential_en?.replace(
509
+ "Opinion unfavorable",
510
+ ""
511
+ );
512
+ } else {
513
+ isFavOpinion.value = 0;
514
+ accessEssential = getLatestHistory.value.essential_en;
515
+ }
516
+
517
+ return `${
518
+ isFavOpinion.value === 2
519
+ ? '<span class="has_fav_access">Favorable opinion </span>'
520
+ : isFavOpinion.value === 3
521
+ ? '<span class="has_fav_access">Authorisation renewal </span>'
522
+ : '<span class="has_defav_access">Unfavorable opinion </span>'
523
+ }${accessEssential}`;
524
+ });
525
+ const accessOpinion = computed(() => {
526
+ let accessEssential;
527
+ // `essential` peut etre null : la HAS ne remplit pas toujours l'essentiel.
528
+ const essential = getLatestHistory.value.essential ?? "";
529
+ if (getLatestHistory.value.opinion_status === "avis favorable") {
530
+ isFavOpinion.value = 2;
531
+ accessEssential = essential.replace("Avis favorable", "");
532
+ } else if (
533
+ getLatestHistory.value.opinion_status === "autorisation renouvelée" ||
534
+ essential.includes("Autorisation d’accès précoce renouvelée") ||
535
+ essential.includes("L'autorisation d’accès précoce est renouvelée")
536
+ ) {
537
+ isFavOpinion.value = 3;
538
+ accessEssential = essential;
539
+ } else if (getLatestHistory.value.opinion_status === "avis défavorable") {
540
+ isFavOpinion.value = 1;
541
+ accessEssential = essential.replace("Avis défavorable", "");
542
+ } else {
543
+ isFavOpinion.value = 0;
544
+ accessEssential = essential;
545
+ }
546
+
547
+ return `${
548
+ isFavOpinion.value === 2
549
+ ? '<span class="has_fav_access">Avis favorable </span>'
550
+ : isFavOpinion.value === 3
551
+ ? '<span class="has_fav_access">Autorisation renouvelée </span>'
552
+ : '<span class="has_defav_access">Avis défavorable </span>'
553
+ }${accessEssential}`;
554
+ });
555
+ const getMolHighlight = computed(() => {
556
+ const mols = getStore("molecule");
557
+ const finalMolArray: any = [];
558
+ if (mols.length > 0) {
559
+ mols.forEach((mol: any) => {
560
+ finalMolArray.push(
561
+ mol.split(" (ATC5: ")[0],
562
+ mol.split(" (ATC5: ")[1]?.replace(")", "")
563
+ );
564
+ });
565
+ }
566
+ return finalMolArray.filter(Boolean);
567
+ });
568
+ const nestedResults = computed(() => {
569
+ const nestedCommonHits = ref<any[]>([]);
570
+
571
+ if (props.product.inner_hits !== undefined) {
572
+ const tempHits = Object.values(props.product.inner_hits).map(
573
+ (innerHit: any) => innerHit.hits.hits
574
+ );
575
+
576
+ const common =
577
+ tempHits.length > 0
578
+ ? tempHits.reduce((acc, currentArray) => {
579
+ return acc.filter((item: any) =>
580
+ currentArray.some(
581
+ (currentItem: any) =>
582
+ item._source.opinion_id === currentItem._source.opinion_id
583
+ )
584
+ );
585
+ })
586
+ : [];
587
+ if (common.length > 0) {
588
+ common.forEach((item: any) => {
589
+ nestedCommonHits.value.push(item);
590
+ });
591
+ }
592
+ return nestedCommonHits.value
593
+ .map((a) => a._source)
594
+ .sort(
595
+ (a, b) =>
596
+ new Date(b.decision_date).getTime() -
597
+ new Date(a.decision_date).getTime()
598
+ );
599
+ } else {
600
+ return props.product._source.brand_history;
601
+ }
602
+ });
603
+
604
+ const getMatchDate = computed(() => {
605
+ return nestedResults.value[0]?.decision_date;
606
+ });
607
+
608
+ </script>
609
+
610
+ <style scoped>
611
+ /* Pied de source, cale sur `.drug-card-foot` du design system : libelle
612
+ atenue, 11px, filet clair. Le bleu primaire d'arg-source-container y
613
+ attirait l'oeil autant que le titre du resultat, alors que la provenance
614
+ se lit apres. */
615
+ .card_source_footer {
616
+ display: flex;
617
+ align-items: center;
618
+ /* Pas de marge haute : `.card_display` porte deja `gap: 20px`, qui separe
619
+ le pied du dernier bloc de contenu. S'y ajouter faisait 28px au-dessus
620
+ du filet contre 25 en dessous, d'ou le desequilibre. */
621
+ padding-top: 6px;
622
+ border-top: 1px solid var(--light);
623
+ font-size: 11px;
624
+ }
625
+
626
+ /* Auriga pose 24px de padding sous le contenu de la carte, pensés pour un
627
+ bloc de texte, pas pour un pied de provenance : ça laissait 25px de vide
628
+ sous le filet. La charte en met 8 sous ce texte (`.drug-card-foot`).
629
+ Cible la carte courante via son style scope, pas toutes les
630
+ `arg_section_card` de l'app. */
631
+ :deep(.card_content) {
632
+ padding-bottom: 8px;
633
+ }
634
+
635
+ .card_source_footer :deep(a),
636
+ .card_source_footer :deep(span) {
637
+ color: var(--medium) !important;
638
+ font-size: 11px;
639
+ }
640
+
641
+
642
+ /* Le pied reste cliquable — il ouvre le tiroir Sources. En gris il n'a plus
643
+ de couleur pour le dire, donc le survol assombrit au lieu de repasser au
644
+ primaire : l'affordance survit sans reintroduire le bleu. */
645
+ .card_source_footer:hover :deep(a),
646
+ .card_source_footer:hover :deep(span) {
647
+ color: var(--darkest) !important;
648
+ }
649
+
650
+
651
+ .has_code_prefix {
652
+ font-weight: 700;
653
+ }
654
+ .indic_category_row {
655
+ display: flex;
656
+ flex-direction: row;
657
+ align-items: flex-start;
658
+ gap: 12px;
659
+ }
660
+ .indic_category_label {
661
+ display: flex;
662
+ align-items: center;
663
+ gap: 6px;
664
+ min-width: 160px;
665
+ white-space: nowrap;
666
+ padding-top: 4px;
667
+ }
668
+ .indic_tags_wrap {
669
+ display: flex;
670
+ flex-wrap: wrap;
671
+ gap: 4px;
672
+ flex: 1;
673
+ min-width: 0;
674
+ }
675
+ .indic_more_tag {
676
+ position: relative;
677
+ cursor: pointer;
678
+ }
679
+ .indic_tooltip {
680
+ position: absolute;
681
+ bottom: calc(100% + 8px);
682
+ right: 0;
683
+ z-index: 100;
684
+ background: var(--bg-surface);
685
+ border: 1px solid #e0e0e0;
686
+ border-radius: 8px;
687
+ padding: 8px;
688
+ box-shadow: 0 4px 12px rgba(0, 0, 0, 0.12);
689
+ display: flex;
690
+ flex-wrap: wrap;
691
+ gap: 4px;
692
+ max-width: 400px;
693
+ max-height: 300px;
694
+ overflow-y: auto;
695
+ }
696
+ </style>