@tekkare/romulus 0.1.251 → 0.1.253

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 (267) hide show
  1. package/dist/module.json +1 -1
  2. package/dist/runtime/utils/projects.d.ts +8 -0
  3. package/dist/runtime/utils/projects.js +8 -5
  4. package/layer/app/app.config.ts +6 -0
  5. package/layer/app/components/OipPubmedSummary.vue +223 -0
  6. package/layer/app/components/OipResourceDrawer.vue +331 -0
  7. package/layer/app/components/OipResourceDrawerLink.vue +40 -0
  8. package/layer/app/components/OipResourceField.vue +41 -0
  9. package/layer/app/components/OipResourceGenericCard.vue +54 -0
  10. package/layer/app/components/OipResourceSource.vue +50 -0
  11. package/layer/app/components/OipResourceTags.vue +65 -0
  12. package/layer/app/components/OipResourceView.vue +107 -0
  13. package/layer/app/components/oip-drugs/fiches/AssociationFiche.vue +775 -0
  14. package/layer/app/components/oip-drugs/fiches/BrandFiche.vue +1111 -0
  15. package/layer/app/components/oip-drugs/fiches/IndicationFiche.vue +182 -0
  16. package/layer/app/components/oip-drugs/fiches/JoFiche.vue +101 -0
  17. package/layer/app/components/oip-drugs/fiches/PndsFiche.vue +279 -0
  18. package/layer/app/components/oip-drugs/heart/JoCard.vue +314 -0
  19. package/layer/app/components/oip-drugs/heart/TextHighlight.vue +326 -0
  20. package/layer/app/components/oip-drugs/heart/ansm/BrandCard.vue +187 -0
  21. package/layer/app/components/oip-drugs/heart/ansm/CisDetail.vue +363 -0
  22. package/layer/app/components/oip-drugs/heart/ansm/CisTable.vue +167 -0
  23. package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyCard.vue +373 -0
  24. package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyFiche.vue +372 -0
  25. package/layer/app/components/oip-drugs/heart/associations/TranscriptionCard.vue +55 -0
  26. package/layer/app/components/oip-drugs/heart/elastic/SourceContainerElastic.vue +103 -0
  27. package/layer/app/components/oip-drugs/heart/france/BrandGroupCard.vue +450 -0
  28. package/layer/app/components/oip-drugs/heart/mitm/Card.vue +199 -0
  29. package/layer/app/components/oip-drugs/heart/mitm/Source.vue +23 -0
  30. package/layer/app/components/oip-drugs/heart/mitm/details/Overview.vue +381 -0
  31. package/layer/app/components/oip-drugs/heart/put/Card.vue +212 -0
  32. package/layer/app/components/oip-drugs/heart/results/AccesCard.vue +696 -0
  33. package/layer/app/components/oip-drugs/heart/results/AlertCard.vue +342 -0
  34. package/layer/app/components/oip-drugs/heart/results/AsmrCursor.vue +229 -0
  35. package/layer/app/components/oip-drugs/heart/results/EvalCard.vue +370 -0
  36. package/layer/app/components/oip-drugs/heart/results/IndicCard.vue +743 -0
  37. package/layer/app/components/oip-drugs/heart/results/MatchExplain.vue +243 -0
  38. package/layer/app/components/oip-drugs/heart/results/PrefRows.vue +105 -0
  39. package/layer/app/components/oip-drugs/heart/results/details/HasHistory.vue +487 -0
  40. package/layer/app/components/oip-drugs/heart/results/details/InternationalCountryCard.vue +461 -0
  41. package/layer/app/components/oip-drugs/heart/results/details/InternationalOverview.vue +200 -0
  42. package/layer/app/components/oip-drugs/heart/results/details/InternationalPriceDrawer.vue +647 -0
  43. package/layer/app/components/oip-drugs/heart/results/details/Monograph.vue +128 -0
  44. package/layer/app/components/oip-drugs/heart/results/details/OpinionDrawer.vue +535 -0
  45. package/layer/app/components/oip-drugs/heart/results/details/PresentationDrawer.vue +738 -0
  46. package/layer/app/components/oip-drugs/heart/results/details/Price.vue +227 -0
  47. package/layer/app/components/oip-drugs/heart/results/details/PriceOverview.vue +1261 -0
  48. package/layer/app/components/oip-drugs/heart/results/details/RecordDrawer.vue +494 -0
  49. package/layer/app/components/oip-drugs/heart/results/details/RecordList.vue +426 -0
  50. package/layer/app/components/oip-drugs/heart/results/les/Card.vue +340 -0
  51. package/layer/app/components/oip-drugs/heart/results/les/Drawer.vue +67 -0
  52. package/layer/app/components/oip-drugs/heart/results/les/IndicationDetail.vue +149 -0
  53. package/layer/app/components/oip-drugs/heart/results/les/Source.vue +20 -0
  54. package/layer/app/components/oip-drugs/heart/results/les/SourceTag.vue +39 -0
  55. package/layer/app/components/oip-drugs/heart/searchPage/DynamicSource.vue +29 -0
  56. package/layer/app/components/oip-drugs/medicam/market/Chart.vue +121 -0
  57. package/layer/app/components/oip-drugs/outpatient/ProductEvolution.vue +236 -0
  58. package/layer/app/components/oip-drugs/resources/Ansm.vue +75 -0
  59. package/layer/app/components/oip-drugs/resources/Association.vue +30 -0
  60. package/layer/app/components/oip-drugs/resources/Brand.vue +65 -0
  61. package/layer/app/components/oip-drugs/resources/Contribution.vue +216 -0
  62. package/layer/app/components/oip-drugs/resources/Hospital.vue +151 -0
  63. package/layer/app/components/oip-drugs/resources/Indication.vue +54 -0
  64. package/layer/app/components/oip-drugs/resources/Jo.vue +57 -0
  65. package/layer/app/components/oip-drugs/resources/Medicam.vue +140 -0
  66. package/layer/app/components/oip-drugs/resources/Mitm.vue +84 -0
  67. package/layer/app/components/oip-drugs/resources/NationalAssembly.vue +93 -0
  68. package/layer/app/components/oip-drugs/resources/Outpatient.vue +97 -0
  69. package/layer/app/components/oip-drugs/resources/Pnds.vue +24 -0
  70. package/layer/app/components/oip-drugs/resources/Price.vue +106 -0
  71. package/layer/app/components/oip-drugs/resources/Put.vue +143 -0
  72. package/layer/app/components/oip-science/appel-a-projet/Cards.vue +162 -0
  73. package/layer/app/components/oip-science/clinical-trials/Cards.vue +382 -0
  74. package/layer/app/components/oip-science/clinical-trials/CardsGlobal.vue +273 -0
  75. package/layer/app/components/oip-science/clinical-trials/LinkedList.vue +366 -0
  76. package/layer/app/components/oip-science/clinical-trials/PairBadge.vue +25 -0
  77. package/layer/app/components/oip-science/clinical-trials/PairBody.vue +182 -0
  78. package/layer/app/components/oip-science/clinical-trials/SitesDrawer.vue +95 -0
  79. package/layer/app/components/oip-science/common/Form.vue +73 -0
  80. package/layer/app/components/oip-science/common/MatchAvgTag.vue +283 -0
  81. package/layer/app/components/oip-science/common/NoData.vue +16 -0
  82. package/layer/app/components/oip-science/common/ScoreBadge.vue +35 -0
  83. package/layer/app/components/oip-science/common/Source.vue +31 -0
  84. package/layer/app/components/oip-science/common/TableTags.vue +279 -0
  85. package/layer/app/components/oip-science/common/Timeline.vue +104 -0
  86. package/layer/app/components/oip-science/common/ToolTips.vue +89 -0
  87. package/layer/app/components/oip-science/cross/publicationPubmed.vue +484 -0
  88. package/layer/app/components/oip-science/crossData/CrossDataLocations.vue +71 -0
  89. package/layer/app/components/oip-science/ctgov/Investigators.vue +148 -0
  90. package/layer/app/components/oip-science/ctgov/Locations.vue +102 -0
  91. package/layer/app/components/oip-science/ctgov/Publications.vue +52 -0
  92. package/layer/app/components/oip-science/ctgov/Sponsors.vue +66 -0
  93. package/layer/app/components/oip-science/ctgov/StudyDescription.vue +1136 -0
  94. package/layer/app/components/oip-science/ctgov-centers/ClinicalTrials.vue +40 -0
  95. package/layer/app/components/oip-science/ctgov-centers/Publications.vue +50 -0
  96. package/layer/app/components/oip-science/ctgov-investigators/ClinicalTrials.vue +43 -0
  97. package/layer/app/components/oip-science/ctgov-investigators/Informations.vue +171 -0
  98. package/layer/app/components/oip-science/ctgov-investigators/Publications.vue +44 -0
  99. package/layer/app/components/oip-science/elastic/DateRangeFilter.vue +209 -0
  100. package/layer/app/components/oip-science/elastic/Filter.vue +719 -0
  101. package/layer/app/components/oip-science/elastic/MatchExplain.vue +152 -0
  102. package/layer/app/components/oip-science/establishments/Cards.vue +183 -0
  103. package/layer/app/components/oip-science/establishments/ClinicalTrials.vue +62 -0
  104. package/layer/app/components/oip-science/establishments/Hcps.vue +227 -0
  105. package/layer/app/components/oip-science/establishments/Informations.vue +263 -0
  106. package/layer/app/components/oip-science/establishments/LinkedList.vue +153 -0
  107. package/layer/app/components/oip-science/establishments/MatchedLabels.vue +194 -0
  108. package/layer/app/components/oip-science/establishments/PublicFinance.vue +62 -0
  109. package/layer/app/components/oip-science/euct/Investigators.vue +125 -0
  110. package/layer/app/components/oip-science/euct/Locations.vue +102 -0
  111. package/layer/app/components/oip-science/euct/Products.vue +101 -0
  112. package/layer/app/components/oip-science/euct/Publications.vue +89 -0
  113. package/layer/app/components/oip-science/euct/Sponsors.vue +86 -0
  114. package/layer/app/components/oip-science/euct/StudyDescription.vue +1075 -0
  115. package/layer/app/components/oip-science/euct-centers/ClinicalTrials.vue +40 -0
  116. package/layer/app/components/oip-science/euct-centers/Publications.vue +55 -0
  117. package/layer/app/components/oip-science/euct-investigators/ClinicalTrials.vue +41 -0
  118. package/layer/app/components/oip-science/euct-investigators/Informations.vue +171 -0
  119. package/layer/app/components/oip-science/euct-investigators/Publications.vue +51 -0
  120. package/layer/app/components/oip-science/hcps/AppelsAProjet.vue +62 -0
  121. package/layer/app/components/oip-science/hcps/Cards.vue +237 -0
  122. package/layer/app/components/oip-science/hcps/ClinicalTrials.vue +78 -0
  123. package/layer/app/components/oip-science/hcps/Informations.vue +296 -0
  124. package/layer/app/components/oip-science/hcps/LinkedList.vue +153 -0
  125. package/layer/app/components/oip-science/hcps/MatchedLabels.vue +207 -0
  126. package/layer/app/components/oip-science/hcps/Pubmed.vue +128 -0
  127. package/layer/app/components/oip-science/local/SliderTabs.vue +99 -0
  128. package/layer/app/components/oip-science/local/SliderTabsFull.vue +135 -0
  129. package/layer/app/components/oip-science/pubmed/Authors.vue +128 -0
  130. package/layer/app/components/oip-science/pubmed/Cards.vue +417 -0
  131. package/layer/app/components/oip-science/pubmed/ClinicalTrials.vue +71 -0
  132. package/layer/app/components/oip-science/resources/Phrc.vue +39 -0
  133. package/layer/app/composables/useOipChapterScroll.ts +43 -0
  134. package/layer/app/composables/useOipResourceHooks.ts +27 -0
  135. package/layer/app/composables/useOipResourceNav.ts +66 -0
  136. package/layer/app/composables/useOipResourceViews.ts +117 -0
  137. package/layer/app/composables/useOipResources.ts +83 -0
  138. package/layer/app/oip-drugs/PORTING.md +120 -0
  139. package/layer/app/oip-drugs/composables/useAssociationDetail.ts +220 -0
  140. package/layer/app/oip-drugs/composables/useAssociationExport.ts +63 -0
  141. package/layer/app/oip-drugs/composables/useAssociationLookup.ts +105 -0
  142. package/layer/app/oip-drugs/composables/useCardPrefOptions.ts +201 -0
  143. package/layer/app/oip-drugs/composables/useCurrency.ts +121 -0
  144. package/layer/app/oip-drugs/composables/useDirectusSources.ts +224 -0
  145. package/layer/app/oip-drugs/composables/useHeartBrandMatches.ts +112 -0
  146. package/layer/app/oip-drugs/composables/useHeartDetailSearches.ts +479 -0
  147. package/layer/app/oip-drugs/composables/useHeartIntlApprovals.ts +661 -0
  148. package/layer/app/oip-drugs/composables/useHeartLesIndication.ts +168 -0
  149. package/layer/app/oip-drugs/composables/useHeartMatchExplain.ts +231 -0
  150. package/layer/app/oip-drugs/composables/useHeartReports.ts +239 -0
  151. package/layer/app/oip-drugs/composables/useHeartSearchFields.ts +233 -0
  152. package/layer/app/oip-drugs/composables/useMergeByKey.ts +23 -0
  153. package/layer/app/oip-drugs/composables/useOipDrugsElastic.ts +621 -0
  154. package/layer/app/oip-drugs/composables/usePageEmpty.ts +58 -0
  155. package/layer/app/oip-drugs/composables/v-useSalesSource.ts +64 -0
  156. package/layer/app/oip-drugs/drugs.css +500 -0
  157. package/layer/app/oip-drugs/esIndices.ts +322 -0
  158. package/layer/app/oip-drugs/kinds.ts +264 -0
  159. package/layer/app/oip-drugs/locales/en.json +1571 -0
  160. package/layer/app/oip-drugs/locales/fr.json +1571 -0
  161. package/layer/app/oip-drugs/monographs/blincyto-has.vue +289 -0
  162. package/layer/app/oip-drugs/monographs/darzalex-has.vue +276 -0
  163. package/layer/app/oip-drugs/monographs/dupixent-has.vue +216 -0
  164. package/layer/app/oip-drugs/monographs/enhertu-has.vue +280 -0
  165. package/layer/app/oip-drugs/monographs/has-sein-2023.vue +1649 -0
  166. package/layer/app/oip-drugs/monographs/ibrance-has.vue +277 -0
  167. package/layer/app/oip-drugs/monographs/imfinzi-has.vue +293 -0
  168. package/layer/app/oip-drugs/monographs/keytruda-has.vue +334 -0
  169. package/layer/app/oip-drugs/monographs/kisqali-has.vue +201 -0
  170. package/layer/app/oip-drugs/monographs/opdivo-has.vue +231 -0
  171. package/layer/app/oip-drugs/monographs/ozempic-has.vue +186 -0
  172. package/layer/app/oip-drugs/monographs/tecentriq-has.vue +312 -0
  173. package/layer/app/oip-drugs/monographs/yescarta-has.vue +272 -0
  174. package/layer/app/oip-drugs/types/elastic.ts +113 -0
  175. package/layer/app/oip-drugs/types/es/agencies.ts +152 -0
  176. package/layer/app/oip-drugs/types/es/directory.ts +54 -0
  177. package/layer/app/oip-drugs/types/es/docByIndex.ts +151 -0
  178. package/layer/app/oip-drugs/types/es/openmedic.ts +67 -0
  179. package/layer/app/oip-drugs/types/es/outpatient.ts +71 -0
  180. package/layer/app/oip-drugs/types/es/portal.ts +130 -0
  181. package/layer/app/oip-drugs/types/es/retail.ts +107 -0
  182. package/layer/app/oip-drugs/types/es/statistics.ts +29 -0
  183. package/layer/app/oip-drugs/types/heart/CurrencyRate.ts +16 -0
  184. package/layer/app/oip-drugs/types/heart/ansm.ts +106 -0
  185. package/layer/app/oip-drugs/types/heart/tag.ts +29 -0
  186. package/layer/app/oip-drugs/utils/associationFields.ts +118 -0
  187. package/layer/app/oip-drugs/utils/contributions.ts +36 -0
  188. package/layer/app/oip-drugs/utils/countryMapping.ts +387 -0
  189. package/layer/app/oip-drugs/utils/esHighlight.ts +21 -0
  190. package/layer/app/oip-drugs/utils/exportSheets.ts +57 -0
  191. package/layer/app/oip-drugs/utils/heartIntlPrice.ts +228 -0
  192. package/layer/app/oip-drugs/utils/heartStyleAndFormat.ts +262 -0
  193. package/layer/app/oip-drugs/utils/heartStyleAnsm.ts +71 -0
  194. package/layer/app/oip-drugs/utils/latestDate.ts +31 -0
  195. package/layer/app/oip-drugs/utils/p-heartCardTags.ts +53 -0
  196. package/layer/app/oip-drugs/utils/priceExport.ts +269 -0
  197. package/layer/app/oip-drugs/utils/q-hasRatings.ts +43 -0
  198. package/layer/app/oip-drugs/utils/s-openCard.ts +20 -0
  199. package/layer/app/oip-drugs/utils/sourceUuids.ts +155 -0
  200. package/layer/app/oip-drugs/utils/styleAndFormat.ts +40 -0
  201. package/layer/app/oip-drugs/utils/v-salesSeries.ts +156 -0
  202. package/layer/app/oip-drugs/utils/v-scopeTags.ts +23 -0
  203. package/layer/app/oip-science/PORTING.md +93 -0
  204. package/layer/app/oip-science/assets/smartSelection.json +428 -0
  205. package/layer/app/oip-science/composables/useAuthorMatching.ts +342 -0
  206. package/layer/app/oip-science/composables/useCTCenter.ts +107 -0
  207. package/layer/app/oip-science/composables/useCTInvestigators.ts +107 -0
  208. package/layer/app/oip-science/composables/useEstablishmentCrossData.ts +139 -0
  209. package/layer/app/oip-science/composables/useEstablishmentMatching.ts +176 -0
  210. package/layer/app/oip-science/composables/useEuct.ts +418 -0
  211. package/layer/app/oip-science/composables/useEuctCenter.ts +107 -0
  212. package/layer/app/oip-science/composables/useEuctInvestigators.ts +107 -0
  213. package/layer/app/oip-science/composables/useGlobalClinicalTrials.ts +624 -0
  214. package/layer/app/oip-science/composables/useLinkedTrials.ts +83 -0
  215. package/layer/app/oip-science/composables/useOipElastic.ts +658 -0
  216. package/layer/app/oip-science/composables/useOipSearchExplain.ts +166 -0
  217. package/layer/app/oip-science/composables/usePubmed.ts +487 -0
  218. package/layer/app/oip-science/composables/useSearchFields.ts +153 -0
  219. package/layer/app/oip-science/indexConfig.json +794 -0
  220. package/layer/app/oip-science/locales/en.json +483 -0
  221. package/layer/app/oip-science/locales/fr.json +483 -0
  222. package/layer/app/oip-science/science.css +1182 -0
  223. package/layer/app/oip-science/utils/a-openCard.ts +23 -0
  224. package/layer/app/oip-science/utils/b-openCard.ts +35 -0
  225. package/layer/app/oip-science/utils/c-filterContext.ts +81 -0
  226. package/layer/app/oip-science/utils/f-types.ts +241 -0
  227. package/layer/app/oip-science/utils/frDiseaseTerms.ts +269 -0
  228. package/layer/app/oip-science/utils/matchMethod.ts +53 -0
  229. package/layer/app/oip-science/utils/sliderTabs.ts +13 -0
  230. package/layer/app/oip-science/utils/sources.ts +15 -0
  231. package/layer/app/oip-science/utils/styleAndFormat.ts +608 -0
  232. package/layer/app/oip-science/utils/toPresets.ts +7 -0
  233. package/layer/app/oip-science/utils/valueTable.ts +126 -0
  234. package/layer/app/plugins/oip-science-i18n.ts +17 -0
  235. package/layer/app/utils/oipFicheRoutes.ts +118 -0
  236. package/layer/app/utils/oipResources.ts +440 -0
  237. package/layer/nuxt.config.ts +22 -2
  238. package/layer/public/reports/blincyto-has.html +292 -0
  239. package/layer/public/reports/blincyto-has.pdf +0 -0
  240. package/layer/public/reports/darzalex-has.html +279 -0
  241. package/layer/public/reports/darzalex-has.pdf +0 -0
  242. package/layer/public/reports/dupixent-has.html +217 -0
  243. package/layer/public/reports/dupixent-has.pdf +0 -0
  244. package/layer/public/reports/enhertu-has.html +283 -0
  245. package/layer/public/reports/enhertu-has.pdf +0 -0
  246. package/layer/public/reports/has-sein-2023.html +1639 -0
  247. package/layer/public/reports/ibrance-has.html +280 -0
  248. package/layer/public/reports/ibrance-has.pdf +0 -0
  249. package/layer/public/reports/imfinzi-has.html +297 -0
  250. package/layer/public/reports/imfinzi-has.pdf +0 -0
  251. package/layer/public/reports/keytruda-has.html +337 -0
  252. package/layer/public/reports/keytruda-has.pdf +0 -0
  253. package/layer/public/reports/kisqali-has.html +202 -0
  254. package/layer/public/reports/kisqali-has.pdf +0 -0
  255. package/layer/public/reports/opdivo-has.html +232 -0
  256. package/layer/public/reports/opdivo-has.pdf +0 -0
  257. package/layer/public/reports/ozempic-has.html +188 -0
  258. package/layer/public/reports/ozempic-has.pdf +0 -0
  259. package/layer/public/reports/tecentriq-has.html +315 -0
  260. package/layer/public/reports/tecentriq-has.pdf +0 -0
  261. package/layer/public/reports/yescarta-has.html +275 -0
  262. package/layer/public/reports/yescarta-has.pdf +0 -0
  263. package/layer/server/api/oip/es.post.ts +99 -0
  264. package/layer/server/api/oip/pdf.get.ts +70 -0
  265. package/layer/server/api/oip/reports.get.ts +98 -0
  266. package/layer/server/api/oip/resource-types.get.ts +22 -0
  267. package/package.json +1 -1
@@ -0,0 +1,775 @@
1
+ <!--
2
+ Fiche d'une association de patients, portee de la page
3
+ `hubr/heart/associations/[id]` de fr_drugs_app : identite dans le bandeau,
4
+ puis quatre onglets (contributions HAS, debats HAS, comites ANSM,
5
+ Assemblee nationale).
6
+
7
+ Montee par la page de fr_drugs_app et par le tiroir des projets. L'export et
8
+ le bouton Projet de la page passent par le slot `actions` ; le tiroir pose
9
+ son lien « Ouvrir dans... » sous le titre par le slot `title-link`.
10
+ -->
11
+ <template>
12
+ <div class="oip-drugs arg_page_layout">
13
+ <RmPageHeader
14
+ :have-return="haveReturn"
15
+ :eyebrow="t('oipDrugs.heart.associations.title')"
16
+ :tabs="headerTabs"
17
+ :tabs-label="t('oipDrugs.heart.associations.detail.tabsLabel')"
18
+ @tab="selectTab"
19
+ >
20
+ <template #title>
21
+ <span class="oip-drugs-fiche__title">{{ label }}</span>
22
+ <slot name="title-link" />
23
+ </template>
24
+ <!-- La ligne de l'annuaire passe au slot : le bouton Projet de la page de
25
+ fr_drugs_app ne s'affiche qu'une fois l'association reconnue. -->
26
+ <template v-if="$slots.actions" #actions>
27
+ <slot name="actions" :directory="directory" :label="label" />
28
+ </template>
29
+ <!-- L'identite tient sous le nom, dans le bandeau. -->
30
+ <div v-if="description || otherNames || tags.length" class="assoc_identity oip_list gap-2">
31
+ <p v-if="description">{{ description }}</p>
32
+ <p v-if="otherNames" class="assoc_muted">
33
+ {{ t("oipDrugs.heart.associations.card.alsoKnownAs") }} {{ otherNames }}
34
+ </p>
35
+ <div v-if="tags.length > 0" class="oip_row gap-8 wrap">
36
+ <RmTag v-for="tag in tags" :key="tag.label" :variant="tag.variant">{{ tag.label }}</RmTag>
37
+ </div>
38
+ </div>
39
+ </RmPageHeader>
40
+
41
+ <div class="oip_list gap-12 full assoc_detail">
42
+ <OipDrugsHeartElasticSourceContainerElastic
43
+ :uuid="HEART_SOURCE_UUIDS.ASSOCIATIONS"
44
+ :last-label="lastActivity.label"
45
+ :last-date="lastActivity.dates"
46
+ />
47
+
48
+ <RmLoadingState v-if="loading" />
49
+
50
+ <RmEmptyState
51
+ v-else-if="!directory"
52
+ :title="t('oipDrugs.heart.associations.detail.notFound')"
53
+ icon="Prohibit"
54
+ />
55
+
56
+ <template v-else>
57
+ <!-- Contributions ecrites aux evaluations HAS. -->
58
+ <div v-if="activeTab === 1" class="oip_list gap-12 full">
59
+ <RmEmptyState
60
+ v-if="contributions.length === 0"
61
+ :title="t('oipDrugs.heart.associations.detail.noContributions')"
62
+ icon="Prohibit"
63
+ />
64
+ <div
65
+ v-for="contribution in contributions"
66
+ :key="contribution.contribution_url || contribution.has_code"
67
+ class="oip_card oip_list gap-12 oip_body full"
68
+ >
69
+ <div class="oip_row v-center gap-8 wrap">
70
+ <p class="oip_heading">
71
+ {{ brands[contribution.has_code] || contribution.has_code || t("oipDrugs.heart.associations.detail.tabs.contributions") }}
72
+ </p>
73
+ <span class="oip_label">
74
+ <RmDate :date="contribution.contribution_date" :lang="dateLang" />
75
+ </span>
76
+ <RmTag v-if="contribution.has_code" variant="gray">{{ contribution.has_code }}</RmTag>
77
+ <RmTag v-if="contribution.request_nature" variant="violet">
78
+ {{ contribution.request_nature }}
79
+ </RmTag>
80
+ </div>
81
+
82
+ <p v-if="contribution.synthesis" class="assoc_field_text oip_body assoc_clamp">
83
+ {{ contribution.synthesis }}
84
+ </p>
85
+
86
+ <div class="oip_row gap-8 wrap">
87
+ <RmButton
88
+ v-if="contributionSections(contribution).length > 0"
89
+ variant="secondary"
90
+ prefix-icon="ListBullets"
91
+ @click="openContribution(contribution)"
92
+ >
93
+ {{ t("oipDrugs.heart.associations.detail.contributionDetail") }}
94
+ </RmButton>
95
+ <!-- Vers l'avis que la contribution accompagne : la fiche marque,
96
+ ouverte sur ce code, quand la marque est resolue. -->
97
+ <RmButton
98
+ v-if="opinionPath(contribution)"
99
+ variant="secondary"
100
+ prefix-icon="Tag"
101
+ @click="goToOpinion(opinionPath(contribution))"
102
+ >
103
+ {{
104
+ t("oipDrugs.heart.associations.detail.seeLinkedOpinion", {
105
+ brand: brands[contribution.has_code],
106
+ })
107
+ }}
108
+ </RmButton>
109
+ <RmButton
110
+ v-if="contribution.contribution_url"
111
+ variant="tertiary"
112
+ ghost
113
+ prefix-icon="ArrowSquareOut"
114
+ @click="openLink(contribution.contribution_url)"
115
+ >
116
+ {{ t("oipDrugs.heart.associations.detail.seeOnHas") }}
117
+ </RmButton>
118
+ </div>
119
+ </div>
120
+ </div>
121
+
122
+ <!-- Debats de la commission de la transparence. -->
123
+ <div v-else-if="activeTab === 2" class="oip_list gap-12 full">
124
+ <RmEmptyState
125
+ v-if="transcriptions.length === 0"
126
+ :title="t('oipDrugs.heart.associations.detail.noTranscriptions')"
127
+ icon="Prohibit"
128
+ />
129
+ <OipDrugsHeartAssociationsTranscriptionCard
130
+ v-for="transcription in transcriptions"
131
+ :key="transcription.transcription_url"
132
+ :transcription="transcription"
133
+ @open="openThread"
134
+ @pdf="openPdf($event.tekkare_url, $event.brand || t('oipDrugs.heart.associations.detail.debate'))"
135
+ />
136
+ </div>
137
+
138
+ <!-- Comptes rendus de commission de l'Assemblee nationale qui la citent. -->
139
+ <div v-else-if="activeTab === 4" class="oip_list gap-12 full">
140
+ <RmEmptyState
141
+ v-if="nationalAssembly.length === 0"
142
+ :title="t('oipDrugs.heart.associations.detail.noNationalAssembly')"
143
+ icon="Prohibit"
144
+ />
145
+ <OipDrugsHeartAssociationsNationalAssemblyCard
146
+ v-for="report in nationalAssembly"
147
+ :key="report.document_id"
148
+ :report="report"
149
+ :store-search-bar="highlight"
150
+ :current-association="label"
151
+ @read="openReport"
152
+ />
153
+ </div>
154
+
155
+ <!-- Seances du comite d'interface ANSM. -->
156
+ <div v-else class="oip_list gap-12 full">
157
+ <RmEmptyState
158
+ v-if="sessions.length === 0"
159
+ :title="t('oipDrugs.heart.associations.detail.noSessions')"
160
+ icon="Prohibit"
161
+ />
162
+ <div
163
+ v-for="session in sessions"
164
+ :key="session.session_url"
165
+ class="oip_card oip_list gap-12 oip_body full"
166
+ >
167
+ <div class="oip_row v-center gap-8 wrap">
168
+ <p class="oip_heading">{{ session.title || t("oipDrugs.heart.associations.detail.committee") }}</p>
169
+ <span class="oip_label">
170
+ <RmDate :date="session.session_date" :lang="dateLang" />
171
+ </span>
172
+ </div>
173
+
174
+ <!-- Les autres associations de la seance : chacune ouvre sa fiche. -->
175
+ <div v-if="otherAttendees(session).length > 0" class="oip_list gap-4">
176
+ <p class="oip_label">{{ t("oipDrugs.heart.associations.detail.otherAttendees") }}</p>
177
+ <div class="oip_row gap-8 wrap">
178
+ <a
179
+ v-for="name in otherAttendees(session)"
180
+ :key="name"
181
+ :href="nav.appHref('fr_drugs_app', drugsAssociationPath(name))"
182
+ class="assoc_attendee"
183
+ @click="openAssociation($event, name)"
184
+ >
185
+ {{ name }}
186
+ </a>
187
+ </div>
188
+ </div>
189
+
190
+ <div class="oip_row gap-8 wrap">
191
+ <RmButton
192
+ v-if="session.minutes_text"
193
+ variant="secondary"
194
+ prefix-icon="FileText"
195
+ @click="openMinutes(session)"
196
+ >
197
+ {{ t("oipDrugs.heart.associations.detail.minutesText") }}
198
+ </RmButton>
199
+ <RmButton
200
+ v-if="session.session_url"
201
+ variant="tertiary"
202
+ ghost
203
+ prefix-icon="ArrowSquareOut"
204
+ @click="openLink(session.session_url)"
205
+ >
206
+ {{ t("oipDrugs.heart.associations.detail.seeOnAnsm") }}
207
+ </RmButton>
208
+ <RmButton
209
+ v-if="session.agenda_tekkare_url || session.agenda_url"
210
+ variant="tertiary"
211
+ ghost
212
+ prefix-icon="FilePdf"
213
+ @click="
214
+ openPdf(
215
+ session.agenda_tekkare_url || session.agenda_url,
216
+ t('oipDrugs.heart.associations.detail.agenda'),
217
+ )
218
+ "
219
+ >
220
+ {{ t("oipDrugs.heart.associations.detail.agenda") }}
221
+ </RmButton>
222
+ <RmButton
223
+ v-if="session.minutes_tekkare_url || session.minutes_url"
224
+ variant="tertiary"
225
+ ghost
226
+ prefix-icon="FilePdf"
227
+ @click="
228
+ openPdf(
229
+ session.minutes_tekkare_url || session.minutes_url,
230
+ t('oipDrugs.heart.associations.detail.minutes'),
231
+ )
232
+ "
233
+ >
234
+ {{ t("oipDrugs.heart.associations.detail.minutes") }}
235
+ </RmButton>
236
+ </div>
237
+ </div>
238
+ </div>
239
+ </template>
240
+ </div>
241
+
242
+ <!-- Le detail d'une contribution, pose une fois pour la liste entiere.
243
+ Teleporte dans <body> : chaque zone reprend la classe `oip-drugs`. -->
244
+ <RmDrawer
245
+ v-model="contributionOpen"
246
+ size="min(760px, 94vw)"
247
+ :label="t('oipDrugs.heart.associations.detail.contributionDetail')"
248
+ :close-label="dateLang === 'en' ? 'Close' : 'Fermer'"
249
+ >
250
+ <template #header>
251
+ <div class="oip-drugs oip_list gap-4">
252
+ <p class="oip_heading">{{ t("oipDrugs.heart.associations.detail.contributionDetail") }}</p>
253
+ <div class="oip_row v-center gap-8 wrap">
254
+ <span class="oip_label">
255
+ <RmDate :date="selectedContribution?.contribution_date" :lang="dateLang" />
256
+ </span>
257
+ <RmTag v-if="selectedContribution?.has_code" variant="gray">
258
+ {{ selectedContribution.has_code }}
259
+ </RmTag>
260
+ <RmTag v-if="selectedContribution?.request_nature" variant="violet">
261
+ {{ selectedContribution.request_nature }}
262
+ </RmTag>
263
+ </div>
264
+ </div>
265
+ </template>
266
+
267
+ <!-- Sections repliables : la premiere est ouverte, les autres se
268
+ replient independamment. -->
269
+ <div v-if="openSections.length > 0" class="oip-drugs oip_list full">
270
+ <RmCollapse
271
+ v-for="section in openSections"
272
+ :key="section.key"
273
+ v-model="sectionOpen[section.key]"
274
+ :title="section.label"
275
+ >
276
+ <p class="assoc_field_text oip_body">{{ section.value }}</p>
277
+ </RmCollapse>
278
+ </div>
279
+
280
+ <template #footer>
281
+ <div class="oip-drugs oip_row gap-8 wrap">
282
+ <RmButton
283
+ v-if="linkedOpinionUrl"
284
+ variant="primary"
285
+ prefix-icon="Tag"
286
+ @click="goToOpinion(linkedOpinionUrl)"
287
+ >
288
+ {{ t("oipDrugs.heart.associations.detail.seeLinkedOpinion", { brand: linkedBrand }) }}
289
+ </RmButton>
290
+ <RmButton
291
+ v-if="selectedContribution?.contribution_url"
292
+ variant="secondary"
293
+ prefix-icon="ArrowSquareOut"
294
+ @click="openLink(selectedContribution.contribution_url)"
295
+ >
296
+ {{ t("oipDrugs.heart.associations.detail.seeOnHas") }}
297
+ </RmButton>
298
+ </div>
299
+ </template>
300
+ </RmDrawer>
301
+
302
+ <!-- Le fil d'un debat, tour de parole par tour de parole. -->
303
+ <RmDrawer
304
+ v-model="threadOpen"
305
+ size="min(760px, 94vw)"
306
+ :label="t('oipDrugs.heart.associations.detail.debateThread')"
307
+ :close-label="dateLang === 'en' ? 'Close' : 'Fermer'"
308
+ >
309
+ <template #header>
310
+ <div class="oip-drugs oip_list gap-4">
311
+ <p class="oip_heading">
312
+ {{ selectedTranscription?.brand || t("oipDrugs.heart.associations.detail.debate") }}
313
+ </p>
314
+ <div class="oip_row v-center gap-8 wrap">
315
+ <span class="oip_label">
316
+ <RmDate :date="selectedTranscription?.session_date" :lang="dateLang" />
317
+ </span>
318
+ <RmTag v-if="selectedTranscription?.has_code" variant="gray">
319
+ {{ selectedTranscription.has_code }}
320
+ </RmTag>
321
+ </div>
322
+ </div>
323
+ </template>
324
+
325
+ <div class="oip-drugs">
326
+ <RmLoadingState v-if="threadLoading" />
327
+ <RmEmptyState
328
+ v-else-if="threadBlocks.length === 0"
329
+ :title="t('oipDrugs.heart.associations.detail.noThread')"
330
+ icon="Prohibit"
331
+ />
332
+ <div v-else class="oip_list gap-16">
333
+ <div v-for="block in threadBlocks" :key="block.block_index" class="oip_list gap-2">
334
+ <p v-if="block.speaker" class="oip_label">{{ block.speaker }}</p>
335
+ <p class="assoc_field_text oip_body">{{ block.block_text }}</p>
336
+ </div>
337
+ </div>
338
+ </div>
339
+
340
+ <template v-if="selectedTranscription?.transcription_url" #footer>
341
+ <div class="oip-drugs oip_row gap-8 wrap">
342
+ <RmButton
343
+ variant="secondary"
344
+ prefix-icon="ArrowSquareOut"
345
+ @click="openLink(selectedTranscription.transcription_url)"
346
+ >
347
+ {{ t("oipDrugs.heart.associations.detail.seeOnHas") }}
348
+ </RmButton>
349
+ <RmButton
350
+ v-if="selectedTranscription?.tekkare_url"
351
+ variant="tertiary"
352
+ ghost
353
+ prefix-icon="FilePdf"
354
+ @click="
355
+ openPdf(
356
+ selectedTranscription.tekkare_url,
357
+ selectedTranscription.brand || t('oipDrugs.heart.associations.detail.debate'),
358
+ )
359
+ "
360
+ >
361
+ {{ t("oipDrugs.heart.associations.detail.seePdf") }}
362
+ </RmButton>
363
+ </div>
364
+ </template>
365
+ </RmDrawer>
366
+
367
+ <!-- Le compte rendu d'une seance du comite d'interface ANSM. -->
368
+ <RmDrawer
369
+ v-model="minutesOpen"
370
+ size="min(760px, 94vw)"
371
+ :label="t('oipDrugs.heart.associations.detail.minutesText')"
372
+ :close-label="dateLang === 'en' ? 'Close' : 'Fermer'"
373
+ >
374
+ <template #header>
375
+ <div class="oip-drugs oip_list gap-4">
376
+ <p class="oip_heading">
377
+ {{ selectedSession?.title || t("oipDrugs.heart.associations.detail.committee") }}
378
+ </p>
379
+ <span class="oip_label">
380
+ <RmDate :date="selectedSession?.session_date" :lang="dateLang" />
381
+ </span>
382
+ </div>
383
+ </template>
384
+
385
+ <div class="oip-drugs">
386
+ <p class="assoc_field_text oip_body">{{ selectedSession?.minutes_text }}</p>
387
+ </div>
388
+
389
+ <template #footer>
390
+ <div class="oip-drugs oip_row gap-8 wrap">
391
+ <RmButton
392
+ v-if="selectedSession?.minutes_tekkare_url || selectedSession?.minutes_url"
393
+ variant="secondary"
394
+ prefix-icon="FilePdf"
395
+ @click="
396
+ openPdf(
397
+ selectedSession.minutes_tekkare_url || selectedSession.minutes_url,
398
+ t('oipDrugs.heart.associations.detail.minutes'),
399
+ )
400
+ "
401
+ >
402
+ {{ t("oipDrugs.heart.associations.detail.minutes") }}
403
+ </RmButton>
404
+ <RmButton
405
+ v-if="selectedSession?.session_url"
406
+ variant="tertiary"
407
+ ghost
408
+ prefix-icon="ArrowSquareOut"
409
+ @click="openLink(selectedSession.session_url)"
410
+ >
411
+ {{ t("oipDrugs.heart.associations.detail.seeOnAnsm") }}
412
+ </RmButton>
413
+ </div>
414
+ </template>
415
+ </RmDrawer>
416
+
417
+ <!-- Les PDF et la copie HTML d'un compte rendu de commission s'ouvrent
418
+ dans la visionneuse des documents du rail. -->
419
+ <OipDocumentPreview
420
+ v-model="pdfOpen"
421
+ :src="pdfSrc"
422
+ :title="pdfTitle"
423
+ :external-src="pdfExternal"
424
+ :download-src="pdfExternal"
425
+ />
426
+ </div>
427
+ </template>
428
+
429
+ <script setup lang="ts">
430
+ import { HEART_SOURCE_UUIDS } from "../../../oip-drugs/utils/sourceUuids";
431
+ import {
432
+ ASSOCIATION_FIELDS,
433
+ ASSOCIATION_FLAG_ON,
434
+ NATIONAL_ASSEMBLY_FIELDS,
435
+ associationDomains,
436
+ } from "../../../oip-drugs/utils/associationFields";
437
+ import { useAssociationDetail } from "../../../oip-drugs/composables/useAssociationDetail";
438
+ import { drugsAssociationPath, drugsBrandPath } from "../../../oip-drugs/kinds";
439
+
440
+ const props = withDefaults(
441
+ defineProps<{
442
+ /** Nom regroupe de l'association, `_id` de l'annuaire (l'id de la route de fr_drugs_app). */
443
+ label: string;
444
+ /** Onglet ouvert : "1" contributions, "2" debats, "3" comites ANSM, "4" Assemblee nationale. */
445
+ tab?: string;
446
+ lang?: "fr" | "en";
447
+ /** Termes de recherche, surlignes dans les titres des comptes rendus. */
448
+ highlight?: string[];
449
+ /** Fleche de retour du bandeau : la page la demande, pas le tiroir. */
450
+ haveReturn?: boolean;
451
+ }>(),
452
+ { tab: "1", lang: undefined, highlight: () => [], haveReturn: false },
453
+ );
454
+
455
+ const emit = defineEmits<{ "update:tab": [key: string] }>();
456
+
457
+ const { t, locale } = useI18n();
458
+ const nav = useOipResourceNav();
459
+
460
+ const label = computed(() => props.label);
461
+ const dateLang = computed(() => props.lang ?? (locale.value === "en" ? "en" : "fr"));
462
+
463
+ const {
464
+ directory,
465
+ contributions,
466
+ transcriptions,
467
+ sessions,
468
+ nationalAssembly,
469
+ sessionAttendees,
470
+ loading,
471
+ load,
472
+ loadBlocks,
473
+ brands,
474
+ } = useAssociationDetail(label);
475
+
476
+ const activeTab = ref(Number(props.tab) || 1);
477
+ watch(
478
+ () => props.tab,
479
+ (value) => {
480
+ activeTab.value = Number(value) || 1;
481
+ },
482
+ );
483
+
484
+ function selectTab(key: string) {
485
+ activeTab.value = Number(key) || 1;
486
+ emit("update:tab", key);
487
+ }
488
+
489
+ /** Les onglets portent leur volumetrie en pastille. */
490
+ const headerTabs = computed(() =>
491
+ [
492
+ {
493
+ key: "1",
494
+ label: t("oipDrugs.heart.associations.detail.tabs.contributions"),
495
+ count: contributions.value.length,
496
+ },
497
+ {
498
+ key: "2",
499
+ label: t("oipDrugs.heart.associations.detail.tabs.transcriptions"),
500
+ count: transcriptions.value.length,
501
+ },
502
+ {
503
+ key: "3",
504
+ label: t("oipDrugs.heart.associations.detail.tabs.sessions"),
505
+ count: sessions.value.length,
506
+ },
507
+ {
508
+ key: "4",
509
+ label: t("oipDrugs.heart.associations.detail.tabs.nationalAssembly"),
510
+ count: nationalAssembly.value.length,
511
+ },
512
+ ].map((tab) => ({ ...tab, active: String(activeTab.value) === tab.key })),
513
+ );
514
+
515
+ /** La contribution ouverte dans le tiroir. */
516
+ const selectedContribution = ref<any>(null);
517
+ const contributionOpen = ref(false);
518
+
519
+ /** Sections depliees dans le tiroir, par cle de champ. */
520
+ const sectionOpen = ref<Record<string, boolean>>({});
521
+
522
+ /**
523
+ * Le chemin de l'avis auquel se rattache une contribution : la fiche marque
524
+ * de fr_drugs_app, ouverte sur son onglet des contributions et sur ce code.
525
+ */
526
+ function opinionPath(contribution: any) {
527
+ const brand = brands.value[contribution?.has_code];
528
+ if (!brand) return null;
529
+ return `${drugsBrandPath(brand)}?tab=contributions&code=${encodeURIComponent(contribution.has_code)}`;
530
+ }
531
+
532
+ const linkedBrand = computed(() => brands.value[selectedContribution.value?.has_code] ?? null);
533
+
534
+ const linkedOpinionUrl = computed(() => opinionPath(selectedContribution.value));
535
+
536
+ function openContribution(contribution: any) {
537
+ selectedContribution.value = contribution;
538
+ sectionOpen.value = Object.fromEntries(
539
+ contributionSections(contribution).map((section, index) => [section.key, index === 0]),
540
+ );
541
+ contributionOpen.value = true;
542
+ }
543
+
544
+ const openSections = computed(() =>
545
+ selectedContribution.value ? contributionSections(selectedContribution.value) : [],
546
+ );
547
+
548
+ const description = computed(() => directory.value?.[ASSOCIATION_FIELDS.description] || "");
549
+
550
+ const otherNames = computed(() => {
551
+ const raw = directory.value?.[ASSOCIATION_FIELDS.labelVariants];
552
+ if (typeof raw !== "string") return "";
553
+ const seen = new Set<string>([label.value.toLowerCase()]);
554
+ const variants: string[] = [];
555
+ raw.split(";").forEach((value) => {
556
+ const name = value.trim();
557
+ if (!name || seen.has(name.toLowerCase())) return;
558
+ seen.add(name.toLowerCase());
559
+ variants.push(name);
560
+ });
561
+ return variants.join(", ");
562
+ });
563
+
564
+ const tags = computed(() => {
565
+ const out: { label: string; variant: "blue" | "violet" | "teal" | "amber" | "gray" }[] = [];
566
+ if (isOn(ASSOCIATION_FIELDS.fasMember)) {
567
+ out.push({ label: t("oipDrugs.heart.associations.tags.fasMember"), variant: "blue" });
568
+ }
569
+ if (isOn(ASSOCIATION_FIELDS.fasBoard)) {
570
+ out.push({ label: t("oipDrugs.heart.associations.tags.fasBoard"), variant: "violet" });
571
+ }
572
+ if (isOn(ASSOCIATION_FIELDS.fasExecutive)) {
573
+ out.push({ label: t("oipDrugs.heart.associations.tags.fasExecutive"), variant: "teal" });
574
+ }
575
+ if (isOn(ASSOCIATION_FIELDS.ansmCommittee)) {
576
+ out.push({ label: t("oipDrugs.heart.associations.card.ansmCommittee"), variant: "amber" });
577
+ }
578
+ // Les domaines d'intervention France Assos Sante, en gris apres les statuts.
579
+ associationDomains(directory.value).forEach((domain: string) => out.push({ label: domain, variant: "gray" }));
580
+ return out;
581
+ });
582
+
583
+ function isOn(field: string) {
584
+ return directory.value?.[field] === ASSOCIATION_FLAG_ON;
585
+ }
586
+
587
+ /** Les champs renseignes d'une contribution, dans l'ordre du questionnaire HAS. */
588
+ function contributionSections(contribution: any) {
589
+ const field = (key: string, value: unknown) => ({
590
+ key,
591
+ label: t(`oipDrugs.heart.associations.detail.fields.${key}`),
592
+ value,
593
+ });
594
+ return [
595
+ field("synthesis", contribution.synthesis),
596
+ field("drugIndication", contribution.drug_indication),
597
+ field("method", contribution.method),
598
+ field("experienceDrug", contribution.experience_drug),
599
+ field("experienceCurrentTreatment", contribution.experience_current_treatment),
600
+ field("impact", contribution.impact),
601
+ field("additionalInfo", contribution.additional_info),
602
+ ].filter((entry) => typeof entry.value === "string" && entry.value.trim());
603
+ }
604
+
605
+ /** Le fil d'un debat : les blocs ne partent qu'a l'ouverture du tiroir. */
606
+ const selectedTranscription = ref<any>(null);
607
+ const threadOpen = ref(false);
608
+ const threadBlocks = ref<any[]>([]);
609
+ const threadLoading = ref(false);
610
+
611
+ async function openThread(transcription: any) {
612
+ selectedTranscription.value = transcription;
613
+ threadBlocks.value = [];
614
+ threadOpen.value = true;
615
+ threadLoading.value = true;
616
+ threadBlocks.value = await loadBlocks(
617
+ transcription.has_code,
618
+ transcription.transcription_url,
619
+ );
620
+ threadLoading.value = false;
621
+ }
622
+
623
+ /** Le dernier mouvement de l'onglet ouvert, pour la ligne source. */
624
+ const lastActivity = computed(() => {
625
+ if (activeTab.value === 1) {
626
+ return {
627
+ label: t("oipDrugs.heart.sources.lastContribution"),
628
+ dates: contributions.value.map((row: any) => row?.contribution_date),
629
+ };
630
+ }
631
+ if (activeTab.value === 2) {
632
+ return {
633
+ label: t("oipDrugs.heart.sources.lastDebate"),
634
+ dates: transcriptions.value.map((row: any) => row?.session_date),
635
+ };
636
+ }
637
+ if (activeTab.value === 4) {
638
+ return {
639
+ label: t("oipDrugs.heart.sources.lastSession"),
640
+ dates: nationalAssembly.value.map((row: any) => row?.[NATIONAL_ASSEMBLY_FIELDS.sessionDate]),
641
+ };
642
+ }
643
+ return {
644
+ label: t("oipDrugs.heart.sources.lastSession"),
645
+ dates: sessions.value.map((row: any) => row?.session_date),
646
+ };
647
+ });
648
+
649
+ /** Les autres associations presentes a une seance, par nom regroupe. */
650
+ function otherAttendees(session: any) {
651
+ return sessionAttendees.value[session?.session_url] ?? [];
652
+ }
653
+
654
+ /** Le Ctrl/Cmd-clic garde le lien : il ouvre un onglet. */
655
+ function openAssociation(event: MouseEvent, name: string) {
656
+ if (event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) return;
657
+ event.preventDefault();
658
+ nav.openApp("fr_drugs_app", drugsAssociationPath(name));
659
+ }
660
+
661
+ /** Le compte rendu d'une seance de comite : un seul bloc de texte, deja charge. */
662
+ const selectedSession = ref<any>(null);
663
+ const minutesOpen = ref(false);
664
+
665
+ function openMinutes(session: any) {
666
+ selectedSession.value = session;
667
+ minutesOpen.value = true;
668
+ }
669
+
670
+ /**
671
+ * Apercu d'un PDF, par le proxy du layer qui le sert en `application/pdf`.
672
+ * Les sorties de l'entete pointent le document chez son producteur.
673
+ */
674
+ const pdfOpen = ref(false);
675
+ const pdfSrc = ref<string | null>(null);
676
+ const pdfTitle = ref("");
677
+ const pdfExternal = ref<string | null>(null);
678
+
679
+ function openPdf(url: string, title: string) {
680
+ if (!url) return;
681
+ pdfExternal.value = url;
682
+ pdfSrc.value = `/api/oip/pdf?url=${encodeURIComponent(url)}`;
683
+ pdfTitle.value = title;
684
+ pdfOpen.value = true;
685
+ }
686
+
687
+ /** Un compte rendu de commission : la copie HTML de Tekkare s'affiche telle quelle. */
688
+ function openReport(report: any) {
689
+ const src = report?.[NATIONAL_ASSEMBLY_FIELDS.tekkareUrl];
690
+ if (!src) return;
691
+ pdfExternal.value = report[NATIONAL_ASSEMBLY_FIELDS.htmlUrl] || null;
692
+ pdfSrc.value = src;
693
+ pdfTitle.value =
694
+ report[NATIONAL_ASSEMBLY_FIELDS.agenda] ||
695
+ t("oipDrugs.heart.associations.nationalAssembly.card.untitled");
696
+ pdfOpen.value = true;
697
+ }
698
+
699
+ function openLink(url: string) {
700
+ if (url) window.open(url, "_blank");
701
+ }
702
+
703
+ /** La fiche marque, sur son onglet Contributions ; le tiroir se ferme au passage. */
704
+ function goToOpinion(path: string | null) {
705
+ if (!path) return;
706
+ contributionOpen.value = false;
707
+ nav.openApp("fr_drugs_app", path);
708
+ }
709
+
710
+ watch(label, () => load(), { immediate: true });
711
+
712
+ // La page de fr_drugs_app declare l'export du cadre depuis son script : elle
713
+ // relit ici les listes deja chargees plutot que de les redemander.
714
+ defineExpose({
715
+ directory,
716
+ contributions,
717
+ transcriptions,
718
+ sessions,
719
+ nationalAssembly,
720
+ sessionAttendees,
721
+ brands,
722
+ activeTab,
723
+ });
724
+ </script>
725
+
726
+ <style scoped>
727
+ .oip-drugs-fiche__title {
728
+ display: block;
729
+ }
730
+
731
+ .assoc_detail {
732
+ padding-left: 24px;
733
+ }
734
+
735
+ /* Le slot par defaut du bandeau ne porte aucune typo : l'identite prend
736
+ celle du corps de page. */
737
+ .assoc_identity {
738
+ gap: 2px;
739
+ color: var(--text-primary);
740
+ font-size: 14px;
741
+ line-height: 160%;
742
+ max-width: 900px;
743
+ }
744
+
745
+ .assoc_muted {
746
+ color: var(--dark, #6c6c8a);
747
+ font-size: 13px;
748
+ }
749
+
750
+ /* Les participants d'une seance : des liens discrets, poses en ligne. */
751
+ .assoc_attendee {
752
+ color: var(--text-primary);
753
+ font-size: 13px;
754
+ text-decoration: none;
755
+ border-bottom: 1px solid var(--border-default);
756
+ }
757
+
758
+ .assoc_attendee:hover {
759
+ color: var(--primary);
760
+ border-bottom-color: currentColor;
761
+ }
762
+
763
+ /* Le resume d'une contribution, borne dans la liste. */
764
+ .assoc_clamp {
765
+ display: -webkit-box;
766
+ -webkit-line-clamp: 3;
767
+ -webkit-box-orient: vertical;
768
+ overflow: hidden;
769
+ }
770
+
771
+ /* Les textes arrivent en un seul bloc, avec leurs retours a la ligne. */
772
+ .assoc_field_text {
773
+ white-space: pre-line;
774
+ }
775
+ </style>