@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,187 @@
1
+ <template>
2
+ <RmSectionCard class="oip-drugs rcard" :class="{ 'rcard--dense': dense }" @click="openDrugsCard(nav, $event, brandDetailPath)" :position="'top'">
3
+ <template #header>
4
+ <div class="oip_row v-center justify-between full_flex" style="width: 100%">
5
+ <div class="oip_list gap-4">
6
+ <h3 class="card_title">
7
+ <OipDrugsHeartTextHighlight :text="brand.brand || brand.cis_label" :queries="storeSearchBar" />
8
+ </h3>
9
+ <p class="card_context">
10
+ <OipDrugsHeartTextHighlight :text="cardContext" :queries="storeSearchBar" />
11
+ </p>
12
+ </div>
13
+ <div class="oip_row v-center gap-8" style="margin-left: auto">
14
+ <!-- La carte porte une marque et ses presentations (CIS) : ce sont
15
+ ces documents qui partent dans le projet. -->
16
+ <!-- Emplacement libre pour un appelant (la fiche projet y pose son
17
+ bouton « Commenter ») avant le bouton projet. -->
18
+ <slot name="hubr-actions" />
19
+ <component
20
+ :is="projectButton"
21
+ v-if="projectButton"
22
+ :resource-id="cisIds"
23
+ type="FrAnsmProduct"
24
+ :label="brand.brand || brand.cis_label"
25
+ compact
26
+ />
27
+ <RmCardActions
28
+ :lang="locale === 'fr' ? 'fr' : 'en'"
29
+ :name="`ANSM - ${brand.brand || brand.cis_label}`"
30
+ :link="brandDetailHref"
31
+ :payload="exportPayload"
32
+ :visual="false"
33
+ />
34
+ </div>
35
+ </div>
36
+ </template>
37
+
38
+ <OipDrugsHeartAnsmCisTable
39
+ v-if="!dense"
40
+ class="card_body"
41
+ :brand-name="brand.brand || brand.cis_label"
42
+ :cis-hits="cisHits"
43
+ :store-search-bar="storeSearchBar"
44
+ :prefs="prefs"
45
+ />
46
+ <div v-if="!dense" class="rcard_footer">
47
+ <OipDrugsHeartElasticSourceContainerElastic
48
+ :uuid="HEART_SOURCE_UUIDS.ANSM"
49
+ :last-label="t('oipDrugs.heart.sources.lastAuthorization')"
50
+ :last-date="lastAuthorizationDates"
51
+ />
52
+ </div>
53
+ </RmSectionCard>
54
+ </template>
55
+
56
+ <script lang="ts" setup>
57
+ import { HEART_SOURCE_UUIDS } from '../../../../oip-drugs/utils/sourceUuids';
58
+ import { drugsBrandPath } from "../../../../oip-drugs/kinds";
59
+ import { openDrugsCard } from "../../../../oip-drugs/utils/s-openCard";
60
+ // ========================
61
+ // IMPORTS
62
+ // ========================
63
+ import type { OneAnsmResult } from "../../../../oip-drugs/types/heart/ansm";
64
+
65
+ // ========================
66
+ // COMPOSABLES
67
+ // ========================
68
+ const { t, locale } = useI18n();
69
+ const nav = useOipResourceNav();
70
+ const { projectButton } = useOipResourceHooks();
71
+
72
+ // ========================
73
+ // PROPS
74
+ // ========================
75
+ const props = defineProps<{
76
+ brand: OneAnsmResult;
77
+ cisHits: Array<{ _id: string; _source: OneAnsmResult }>;
78
+ storeSearchBar: string[];
79
+ /** Rendu serre de la fiche projet : l'en-tete seul, sans le tableau. */
80
+ dense?: boolean;
81
+ /** Colonnes facultatives du tableau des CIS (ex-cardPrefs, cle « ansm »). */
82
+ prefs?: Record<string, boolean>;
83
+ }>();
84
+
85
+ // ========================
86
+ // COMPUTED
87
+ // ========================
88
+ /** Les documents de la carte : une presentation (CIS) par hit. */
89
+ const cisIds = computed(() => props.cisHits.map((hit) => hit._id).filter(Boolean));
90
+
91
+ /**
92
+ * L'AMM la plus recente des presentations de la marque : c'est le dernier
93
+ * mouvement que l'index ANSM date. Les dates de commercialisation des
94
+ * presentations comptent aussi, une marque autorisee de longue date pouvant
95
+ * n'etre commercialisee que depuis peu.
96
+ */
97
+ const lastAuthorizationDates = computed(() =>
98
+ props.cisHits.flatMap((hit) => [
99
+ (hit._source as any)?.authorization_date,
100
+ ...(((hit._source as any)?.drug ?? []) as any[]).map((d: any) => d?.commercialization_date),
101
+ ]),
102
+ );
103
+
104
+ const cardContext = computed(() => {
105
+ const b = props.brand;
106
+ return [b.atc5_french_code_label, b.atc4_french_code_label, b.owner]
107
+ .filter(Boolean)
108
+ .join(" · ");
109
+ });
110
+
111
+ // Fiche marque unifiee, ouverte sur l'onglet ANSM.
112
+ const brandDetailPath = computed(() => {
113
+ const path = drugsBrandPath(props.brand.brand);
114
+ return path ? `${path}?tab=ansm` : "";
115
+ });
116
+ const brandDetailHref = computed(() =>
117
+ brandDetailPath.value ? nav.appHref("fr_drugs_app", brandDetailPath.value) : undefined,
118
+ );
119
+
120
+ /**
121
+ * Onglet de la carte pour le menu : en fonction, la liste monte la carte
122
+ * vingt fois et le menu ne l'appelle qu'a l'export.
123
+ */
124
+ const exportPayload = () => ({
125
+ title: `ANSM - ${props.brand.brand || props.brand.cis_label}`,
126
+ subtitle: `🇫🇷 ANSM: ${props.brand.brand || props.brand.cis_label}`,
127
+ limit: 10000,
128
+ sheets: exportSheets(),
129
+ });
130
+
131
+ const exportSheets = () => [
132
+ {
133
+ name: "Spécialités",
134
+ data: props.cisHits.map((h) => h._source),
135
+ schema: [
136
+ { column: "Code CIS", type: String, value: (c: any) => c.cis_code, width: 15 },
137
+ { column: "Dénomination", type: String, value: (c: any) => c.cis_label, width: 60, wrap: true },
138
+ { column: "Date d'autorisation", type: String, value: (c: any) => c.authorization_date || "-", width: 20 },
139
+ { column: "État", type: String, value: (c: any) => c.amm_status, width: 25 },
140
+ { column: "Commercialisation", type: String, value: (c: any) => c.commercialization_status, width: 25 },
141
+ { column: "Laboratoire", type: String, value: (c: any) => c.owner, width: 30, wrap: true },
142
+ { column: "ATC5", type: String, value: (c: any) => c.atc5_french_code_label, width: 40, wrap: true },
143
+ ],
144
+ },
145
+ ];
146
+ </script>
147
+
148
+ <style scoped>
149
+ /* Rendu serre : RmSectionCard dessine son corps meme vide. */
150
+ .rcard--dense :deep(.rm-section-card__body) {
151
+ display: none;
152
+ }
153
+
154
+ .card_title {
155
+ font-weight: 900;
156
+ font-size: 20px;
157
+ color: var(--darkest);
158
+ font-family: Figtree, sans-serif !important;
159
+ }
160
+ .card_context {
161
+ font-size: 13px;
162
+ color: var(--dark);
163
+ }
164
+ /* Plus d'air autour du header de la card. */
165
+ :deep(.card_header) {
166
+ padding: 20px 24px;
167
+ }
168
+ /* Tableau a fleur des bords de la carte. La regle visait `.card_content`,
169
+ le corps des cartes Auriga : depuis le passage a `RmSectionCard` ce corps
170
+ s'appelle `rm-section-card__body` et le tableau se retrouvait a 24px des
171
+ deux bords, seul bloc de la carte a ne pas toucher le filet.
172
+
173
+ Marges negatives plutot que padding a zero sur le corps : le pied de
174
+ provenance sort deja par ce chemin (cf. `.rm-shell .rcard_footer` dans
175
+ assets/css/main.css) et garde ainsi son propre calage. Les 24px verticaux
176
+ restent, c'est l'air entre l'en-tete et la premiere ligne. */
177
+ .card_body {
178
+ /* `flex: none` : le corps de la carte est une rangee flex, elle retrecissait
179
+ le tableau elargi pour le faire rentrer et les 24px de droite revenaient. */
180
+ flex: none;
181
+ margin-inline: -24px;
182
+ width: calc(100% + 48px);
183
+ }
184
+ :deep(.flex-table) {
185
+ gap: 0;
186
+ }
187
+ </style>
@@ -0,0 +1,363 @@
1
+ <template>
2
+ <div class="oip-drugs oip_list gap-16 full">
3
+ <!-- Synthèse : badges + strip de stats -->
4
+ <div class="oip_card oip_list gap-16 oip_body full">
5
+ <div class="oip_list gap-4">
6
+ <h3 class="card_title">{{ cis.cis_label }}</h3>
7
+ <p class="oip_filter_label">{{ synthContext }}</p>
8
+ </div>
9
+ <div class="oip_row gap-8 wrap">
10
+ <RmTag :variant="heartGetStatusColor(cis.amm_status)">{{ cis.amm_status }}</RmTag>
11
+ <RmTag :variant="heartGetStatusColor(cis.commercialization_status)">{{ cis.commercialization_status }}</RmTag>
12
+ <RmTag v-if="cis.procedure_type" variant="default">{{ cis.procedure_type }}</RmTag>
13
+ </div>
14
+ <div class="statbar">
15
+ <div class="stat">
16
+ <span class="stat-num">{{ cis.cis_code }}</span>
17
+ <span class="stat-lbl">{{ t('oipDrugs.heart.ansm.card.codeCIS') }}</span>
18
+ </div>
19
+ <div class="stat">
20
+ <span class="stat-num">{{ skuCount ?? '-' }}</span>
21
+ <span class="stat-lbl">{{ t('oipDrugs.heart.ansm.detailsPage.skuOfBrand') }}</span>
22
+ </div>
23
+ <div class="stat">
24
+ <span class="stat-num">{{ avisCount ?? '-' }}</span>
25
+ <span class="stat-lbl">{{ t('oipDrugs.heart.ansm.detailsPage.avisHas') }}</span>
26
+ </div>
27
+ <div class="stat">
28
+ <span class="stat-num">{{ cis.drug?.length ?? 0 }}</span>
29
+ <span class="stat-lbl">{{ t('oipDrugs.heart.ansm.detailsPage.presentations') }}</span>
30
+ </div>
31
+ </div>
32
+ </div>
33
+
34
+ <!-- Composition en substances actives -->
35
+ <div class="oip_card oip_list gap-16 oip_body full">
36
+ <p class="oip_heading">{{ t('oipDrugs.heart.ansm.detailsPage.composition') }}</p>
37
+ <RmTable
38
+ v-if="compoContents.length"
39
+ class="card-table"
40
+ :columns="compoTable.columns"
41
+ :rows="compoTable.rows"
42
+ max-height="600px"
43
+ />
44
+ <div v-else class="oip_list full centered v-center">
45
+ <RmEmptyState :title="t('oipDrugs.heart.ansm.detailsPage.noData')" icon="Prohibit" />
46
+ </div>
47
+ </div>
48
+
49
+ <!-- Titulaire & données administratives -->
50
+ <div class="oip_card oip_list gap-16 oip_body full">
51
+ <p class="oip_heading">{{ t('oipDrugs.heart.ansm.card.administrativeData') }}</p>
52
+ <dl class="admin-grid">
53
+ <div class="col-span">
54
+ <dt>{{ t('oipDrugs.heart.ansm.card.laboratory') }}</dt>
55
+ <dd>
56
+ {{ cis.owner || '-' }}
57
+ <span v-if="ownerSince" class="admin-since">· {{ t('oipDrugs.heart.ansm.detailsPage.holderSince') }} {{ ownerSince }}</span>
58
+ </dd>
59
+ </div>
60
+ <div>
61
+ <dt>{{ t('oipDrugs.heart.ansm.brandCard.authorizationDate') }}</dt>
62
+ <dd>{{ heartFormatDate(cis.authorization_date) }}</dd>
63
+ </div>
64
+ <div>
65
+ <dt>{{ t('oipDrugs.heart.ansm.brandCard.status') }}</dt>
66
+ <dd><RmTag :variant="heartGetStatusColor(cis.amm_status)">{{ cis.amm_status }}</RmTag></dd>
67
+ </div>
68
+ <div>
69
+ <dt>{{ t('oipDrugs.heart.ansm.card.procedure') }}</dt>
70
+ <dd>{{ cis.procedure_type || '-' }}</dd>
71
+ </div>
72
+ <div>
73
+ <dt>{{ t('oipDrugs.heart.ansm.detailsPage.forme') }}</dt>
74
+ <dd>{{ heartFirstLetterUpperCase(cis.pharmaceutical_form) }}</dd>
75
+ </div>
76
+ <div>
77
+ <dt>{{ t('oipDrugs.heart.ansm.detailsPage.administrationMode') }}</dt>
78
+ <dd>{{ heartFormatAdministrations(cis.administration_mode) }}</dd>
79
+ </div>
80
+ <div>
81
+ <dt>{{ t('oipDrugs.heart.ansm.card.molecule') }}</dt>
82
+ <dd>{{ cis.atc5_french_code_label || '-' }}</dd>
83
+ </div>
84
+ <div class="col-span">
85
+ <dt>{{ t('oipDrugs.heart.ansm.card.genericGroup') }}</dt>
86
+ <dd>{{ cis.generic_group_label || t('oipDrugs.heart.ansm.card.noGenericGroup') }}</dd>
87
+ </div>
88
+ </dl>
89
+ </div>
90
+
91
+ <!-- Conditions de prescription et de délivrance -->
92
+ <div class="oip_card oip_list gap-16 oip_body full">
93
+ <p class="oip_heading">{{ t('oipDrugs.heart.ansm.detailsPage.prescription') }}</p>
94
+ <div v-if="cpdGroups.length" class="cpd-groups">
95
+ <div v-for="g in cpdGroups" :key="g.label" class="cpd-group">
96
+ <p class="cpd-group-title">{{ g.label }}</p>
97
+ <ul class="cpd-glist">
98
+ <li v-for="(c, i) in g.items" :key="i">{{ c }}</li>
99
+ </ul>
100
+ </div>
101
+ </div>
102
+ <div v-else class="oip_list full centered v-center">
103
+ <RmEmptyState :title="t('oipDrugs.heart.ansm.detailsPage.noData')" icon="Prohibit" />
104
+ </div>
105
+ </div>
106
+
107
+ <!-- Présentations -->
108
+ <div class="oip_card oip_list gap-16 oip_body full">
109
+ <p class="oip_heading">{{ t('oipDrugs.heart.ansm.detailsPage.presentations') }}</p>
110
+ <RmTable
111
+ v-if="presContents.length"
112
+ class="card-table"
113
+ :columns="presTable.columns"
114
+ :rows="presTable.rows"
115
+ max-height="600px"
116
+ >
117
+ <template v-for="key in presTable.typeKeys.tag" :key="key" #[key]="{ value }">
118
+ <RmTag :variant="heartGetStatusColor(value)">{{ value }}</RmTag>
119
+ </template>
120
+ </RmTable>
121
+ <div v-else class="oip_list full centered v-center">
122
+ <RmEmptyState :title="t('oipDrugs.heart.ansm.detailsPage.noData')" icon="Prohibit" />
123
+ </div>
124
+ </div>
125
+ </div>
126
+ </template>
127
+
128
+ <script lang="ts" setup>
129
+ import type { OneAnsmResult } from "../../../../oip-drugs/types/heart/ansm";
130
+ import {
131
+ heartFirstLetterUpperCase,
132
+ heartFormatAdministrations,
133
+ heartGetStatusColor,
134
+ } from "../../../../oip-drugs/utils/heartStyleAnsm";
135
+ import { heartFormatDate } from "../../../../oip-drugs/utils/heartStyleAndFormat";
136
+ import { valueTable } from "../../../../utils/valueTable";
137
+
138
+ const { t, locale } = useI18n();
139
+
140
+ const props = defineProps<{
141
+ cis: OneAnsmResult;
142
+ skuCount?: number;
143
+ avisCount?: number;
144
+ }>();
145
+
146
+ const synthContext = computed(() =>
147
+ [props.cis.atc5_french_code_label, props.cis.atc4_french_code_label, props.cis.owner]
148
+ .filter(Boolean)
149
+ .join(" · ")
150
+ );
151
+
152
+ const ownerSince = computed(() => {
153
+ const d = (props.cis as any).owner_authorization_date;
154
+ return d && d !== "-" ? heartFormatDate(d) : null;
155
+ });
156
+
157
+ const compoContents = computed(() =>
158
+ (props.cis.compo ?? []).map((c) => ({
159
+ values: [
160
+ c.substance_label,
161
+ heartFirstLetterUpperCase(c.substance_form || c.pharmaceutical_form),
162
+ c.substance_dosage,
163
+ ],
164
+ }))
165
+ );
166
+
167
+ const presContents = computed(() =>
168
+ (props.cis.drug ?? []).map((d) => ({
169
+ values: [
170
+ d.drug_code,
171
+ heartFirstLetterUpperCase(d.presentation_label),
172
+ d.presentation_status,
173
+ d.commercialization_date && d.commercialization_date !== "-"
174
+ ? heartFormatDate(d.commercialization_date)
175
+ : "-",
176
+ ],
177
+ }))
178
+ );
179
+
180
+ // Conditions de prescription regroupées par catégorie (comme le modèle Synappses).
181
+ function cpdCategory(c: string): string {
182
+ const s = (c || "").toLowerCase();
183
+ if (s.includes("surveillance")) return "surveillance";
184
+ if (s.includes("hospital") || s.includes("usage")) return "delivrance";
185
+ if (s.includes("prescription") || s.includes("spécial") || s.includes("special") || s.includes("services") || s.includes("médecin") || s.includes("medecin")) return "prescripteur";
186
+ if (s.includes("liste")) return "classification";
187
+ return "autre";
188
+ }
189
+ const CPD_CATS = [
190
+ { key: "classification", fr: "Classification", en: "Classification" },
191
+ { key: "surveillance", fr: "Surveillance", en: "Monitoring" },
192
+ { key: "prescripteur", fr: "Prescripteur habilité", en: "Authorized prescriber" },
193
+ { key: "delivrance", fr: "Cadre de délivrance", en: "Dispensing setting" },
194
+ { key: "autre", fr: "Autre", en: "Other" },
195
+ ];
196
+ const cpdGroups = computed(() => {
197
+ const map: Record<string, string[]> = {};
198
+ (props.cis.cpd ?? []).forEach((c: any) => {
199
+ const cat = cpdCategory(c.prescription_delivery_condition);
200
+ (map[cat] ||= []).push(c.prescription_delivery_condition);
201
+ });
202
+ return CPD_CATS.filter((c) => map[c.key]).map((c) => ({
203
+ label: locale.value === "en" ? c.en : c.fr,
204
+ items: map[c.key],
205
+ }));
206
+ });
207
+
208
+ // Les deux tableaux de la fiche etaient ecrits pour `arg-table` : des libelles
209
+ // de tete et des lignes `{ values: [...] }`. La conversion en colonnes de
210
+ // RmTable est mecanique, cf. `valueTable`. Ils ne se trient pas : la fiche
211
+ // garde l'ordre de la source.
212
+ const unsorted = (table: ReturnType<typeof valueTable>) => ({
213
+ ...table,
214
+ columns: table.columns.map((column) => ({ ...column, sortable: false })),
215
+ });
216
+
217
+ const compoTable = computed(() =>
218
+ unsorted(
219
+ valueTable(
220
+ [
221
+ t("oipDrugs.heart.ansm.detailsPage.substanceActive"),
222
+ t("oipDrugs.heart.ansm.detailsPage.forme"),
223
+ t("oipDrugs.heart.ansm.detailsPage.dosage"),
224
+ ],
225
+ compoContents.value,
226
+ ["", "", ""],
227
+ { align: ["left", "left", "left"] },
228
+ ),
229
+ ),
230
+ );
231
+
232
+ const presTable = computed(() =>
233
+ unsorted(
234
+ valueTable(
235
+ [
236
+ locale.value === "en" ? "CIP code" : "Code CIP",
237
+ t("oipDrugs.heart.ansm.detailsPage.conditioning"),
238
+ t("oipDrugs.heart.ansm.detailsPage.declaration"),
239
+ t("oipDrugs.heart.ansm.detailsPage.date"),
240
+ ],
241
+ presContents.value,
242
+ ["", "", "tag", ""],
243
+ { align: ["left", "left", "left", "left"] },
244
+ ),
245
+ ),
246
+ );
247
+ </script>
248
+
249
+ <style scoped>
250
+ .card_title {
251
+ font-weight: 900;
252
+ font-size: 20px;
253
+ color: var(--darkest);
254
+ font-family: Figtree, sans-serif !important;
255
+ }
256
+ .wrap {
257
+ flex-wrap: wrap;
258
+ }
259
+
260
+ /* Tableau à fleur des bords de la card (annule le padding 24px de .oip_card).
261
+ Le padding de cellule interne d'arg-table garde le texte aligné sous le titre. */
262
+ .card-table {
263
+ margin: 0 -24px -24px;
264
+ }
265
+
266
+ /* Strip de stats (synthèse). */
267
+ .statbar {
268
+ display: grid;
269
+ grid-template-columns: repeat(4, 1fr);
270
+ border-top: 1px solid var(--light);
271
+ }
272
+ .stat {
273
+ padding: 16px 24px 0;
274
+ border-right: 1px solid var(--light);
275
+ }
276
+ .stat:last-child {
277
+ border-right: none;
278
+ }
279
+ .stat-num {
280
+ display: block;
281
+ font-size: 20px;
282
+ font-weight: 800;
283
+ color: var(--primary);
284
+ line-height: 1.2;
285
+ }
286
+ .stat-lbl {
287
+ display: block;
288
+ margin-top: 4px;
289
+ font-size: 11px;
290
+ font-weight: 600;
291
+ text-transform: uppercase;
292
+ letter-spacing: 0.06em;
293
+ color: var(--medium);
294
+ }
295
+
296
+ /* Grille données administratives (style dl). */
297
+ .admin-grid {
298
+ display: grid;
299
+ grid-template-columns: repeat(3, 1fr);
300
+ gap: 20px 32px;
301
+ margin: 0;
302
+ }
303
+ .admin-grid > div {
304
+ display: flex;
305
+ flex-direction: column;
306
+ gap: 4px;
307
+ }
308
+ .admin-grid .col-span {
309
+ grid-column: 1 / -1;
310
+ }
311
+ .admin-grid dt {
312
+ font-size: 11px;
313
+ font-weight: 600;
314
+ text-transform: uppercase;
315
+ letter-spacing: 0.06em;
316
+ color: var(--medium);
317
+ }
318
+ .admin-grid dd {
319
+ margin: 0;
320
+ font-size: 14px;
321
+ color: var(--darkest);
322
+ font-weight: 500;
323
+ }
324
+ .admin-since {
325
+ color: var(--medium);
326
+ font-weight: 400;
327
+ }
328
+
329
+ /* Conditions de prescription groupées. */
330
+ .cpd-groups {
331
+ display: flex;
332
+ flex-direction: column;
333
+ gap: 16px;
334
+ }
335
+ .cpd-group-title {
336
+ margin: 0 0 6px;
337
+ font-size: 11px;
338
+ font-weight: 600;
339
+ text-transform: uppercase;
340
+ letter-spacing: 0.06em;
341
+ color: var(--primary);
342
+ }
343
+ .cpd-glist {
344
+ margin: 0;
345
+ padding-left: 16px;
346
+ display: flex;
347
+ flex-direction: column;
348
+ gap: 4px;
349
+ }
350
+ .cpd-glist li {
351
+ font-size: 14px;
352
+ color: var(--dark);
353
+ }
354
+
355
+ @media (max-width: 860px) {
356
+ .statbar {
357
+ grid-template-columns: 1fr 1fr;
358
+ }
359
+ .admin-grid {
360
+ grid-template-columns: 1fr 1fr;
361
+ }
362
+ }
363
+ </style>