@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.
- package/dist/module.json +1 -1
- package/dist/runtime/utils/projects.d.ts +8 -0
- package/dist/runtime/utils/projects.js +8 -5
- package/layer/app/app.config.ts +6 -0
- package/layer/app/components/OipPubmedSummary.vue +223 -0
- package/layer/app/components/OipResourceDrawer.vue +331 -0
- package/layer/app/components/OipResourceDrawerLink.vue +40 -0
- package/layer/app/components/OipResourceField.vue +41 -0
- package/layer/app/components/OipResourceGenericCard.vue +54 -0
- package/layer/app/components/OipResourceSource.vue +50 -0
- package/layer/app/components/OipResourceTags.vue +65 -0
- package/layer/app/components/OipResourceView.vue +107 -0
- package/layer/app/components/oip-drugs/fiches/AssociationFiche.vue +775 -0
- package/layer/app/components/oip-drugs/fiches/BrandFiche.vue +1111 -0
- package/layer/app/components/oip-drugs/fiches/IndicationFiche.vue +182 -0
- package/layer/app/components/oip-drugs/fiches/JoFiche.vue +101 -0
- package/layer/app/components/oip-drugs/fiches/PndsFiche.vue +279 -0
- package/layer/app/components/oip-drugs/heart/JoCard.vue +314 -0
- package/layer/app/components/oip-drugs/heart/TextHighlight.vue +326 -0
- package/layer/app/components/oip-drugs/heart/ansm/BrandCard.vue +187 -0
- package/layer/app/components/oip-drugs/heart/ansm/CisDetail.vue +363 -0
- package/layer/app/components/oip-drugs/heart/ansm/CisTable.vue +167 -0
- package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyCard.vue +373 -0
- package/layer/app/components/oip-drugs/heart/associations/NationalAssemblyFiche.vue +372 -0
- package/layer/app/components/oip-drugs/heart/associations/TranscriptionCard.vue +55 -0
- package/layer/app/components/oip-drugs/heart/elastic/SourceContainerElastic.vue +103 -0
- package/layer/app/components/oip-drugs/heart/france/BrandGroupCard.vue +450 -0
- package/layer/app/components/oip-drugs/heart/mitm/Card.vue +199 -0
- package/layer/app/components/oip-drugs/heart/mitm/Source.vue +23 -0
- package/layer/app/components/oip-drugs/heart/mitm/details/Overview.vue +381 -0
- package/layer/app/components/oip-drugs/heart/put/Card.vue +212 -0
- package/layer/app/components/oip-drugs/heart/results/AccesCard.vue +696 -0
- package/layer/app/components/oip-drugs/heart/results/AlertCard.vue +342 -0
- package/layer/app/components/oip-drugs/heart/results/AsmrCursor.vue +229 -0
- package/layer/app/components/oip-drugs/heart/results/EvalCard.vue +370 -0
- package/layer/app/components/oip-drugs/heart/results/IndicCard.vue +743 -0
- package/layer/app/components/oip-drugs/heart/results/MatchExplain.vue +243 -0
- package/layer/app/components/oip-drugs/heart/results/PrefRows.vue +105 -0
- package/layer/app/components/oip-drugs/heart/results/details/HasHistory.vue +487 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalCountryCard.vue +461 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalOverview.vue +200 -0
- package/layer/app/components/oip-drugs/heart/results/details/InternationalPriceDrawer.vue +647 -0
- package/layer/app/components/oip-drugs/heart/results/details/Monograph.vue +128 -0
- package/layer/app/components/oip-drugs/heart/results/details/OpinionDrawer.vue +535 -0
- package/layer/app/components/oip-drugs/heart/results/details/PresentationDrawer.vue +738 -0
- package/layer/app/components/oip-drugs/heart/results/details/Price.vue +227 -0
- package/layer/app/components/oip-drugs/heart/results/details/PriceOverview.vue +1261 -0
- package/layer/app/components/oip-drugs/heart/results/details/RecordDrawer.vue +494 -0
- package/layer/app/components/oip-drugs/heart/results/details/RecordList.vue +426 -0
- package/layer/app/components/oip-drugs/heart/results/les/Card.vue +340 -0
- package/layer/app/components/oip-drugs/heart/results/les/Drawer.vue +67 -0
- package/layer/app/components/oip-drugs/heart/results/les/IndicationDetail.vue +149 -0
- package/layer/app/components/oip-drugs/heart/results/les/Source.vue +20 -0
- package/layer/app/components/oip-drugs/heart/results/les/SourceTag.vue +39 -0
- package/layer/app/components/oip-drugs/heart/searchPage/DynamicSource.vue +29 -0
- package/layer/app/components/oip-drugs/medicam/market/Chart.vue +121 -0
- package/layer/app/components/oip-drugs/outpatient/ProductEvolution.vue +236 -0
- package/layer/app/components/oip-drugs/resources/Ansm.vue +75 -0
- package/layer/app/components/oip-drugs/resources/Association.vue +30 -0
- package/layer/app/components/oip-drugs/resources/Brand.vue +65 -0
- package/layer/app/components/oip-drugs/resources/Contribution.vue +216 -0
- package/layer/app/components/oip-drugs/resources/Hospital.vue +151 -0
- package/layer/app/components/oip-drugs/resources/Indication.vue +54 -0
- package/layer/app/components/oip-drugs/resources/Jo.vue +57 -0
- package/layer/app/components/oip-drugs/resources/Medicam.vue +140 -0
- package/layer/app/components/oip-drugs/resources/Mitm.vue +84 -0
- package/layer/app/components/oip-drugs/resources/NationalAssembly.vue +93 -0
- package/layer/app/components/oip-drugs/resources/Outpatient.vue +97 -0
- package/layer/app/components/oip-drugs/resources/Pnds.vue +24 -0
- package/layer/app/components/oip-drugs/resources/Price.vue +106 -0
- package/layer/app/components/oip-drugs/resources/Put.vue +143 -0
- package/layer/app/components/oip-science/appel-a-projet/Cards.vue +162 -0
- package/layer/app/components/oip-science/clinical-trials/Cards.vue +382 -0
- package/layer/app/components/oip-science/clinical-trials/CardsGlobal.vue +273 -0
- package/layer/app/components/oip-science/clinical-trials/LinkedList.vue +366 -0
- package/layer/app/components/oip-science/clinical-trials/PairBadge.vue +25 -0
- package/layer/app/components/oip-science/clinical-trials/PairBody.vue +182 -0
- package/layer/app/components/oip-science/clinical-trials/SitesDrawer.vue +95 -0
- package/layer/app/components/oip-science/common/Form.vue +73 -0
- package/layer/app/components/oip-science/common/MatchAvgTag.vue +283 -0
- package/layer/app/components/oip-science/common/NoData.vue +16 -0
- package/layer/app/components/oip-science/common/ScoreBadge.vue +35 -0
- package/layer/app/components/oip-science/common/Source.vue +31 -0
- package/layer/app/components/oip-science/common/TableTags.vue +279 -0
- package/layer/app/components/oip-science/common/Timeline.vue +104 -0
- package/layer/app/components/oip-science/common/ToolTips.vue +89 -0
- package/layer/app/components/oip-science/cross/publicationPubmed.vue +484 -0
- package/layer/app/components/oip-science/crossData/CrossDataLocations.vue +71 -0
- package/layer/app/components/oip-science/ctgov/Investigators.vue +148 -0
- package/layer/app/components/oip-science/ctgov/Locations.vue +102 -0
- package/layer/app/components/oip-science/ctgov/Publications.vue +52 -0
- package/layer/app/components/oip-science/ctgov/Sponsors.vue +66 -0
- package/layer/app/components/oip-science/ctgov/StudyDescription.vue +1136 -0
- package/layer/app/components/oip-science/ctgov-centers/ClinicalTrials.vue +40 -0
- package/layer/app/components/oip-science/ctgov-centers/Publications.vue +50 -0
- package/layer/app/components/oip-science/ctgov-investigators/ClinicalTrials.vue +43 -0
- package/layer/app/components/oip-science/ctgov-investigators/Informations.vue +171 -0
- package/layer/app/components/oip-science/ctgov-investigators/Publications.vue +44 -0
- package/layer/app/components/oip-science/elastic/DateRangeFilter.vue +209 -0
- package/layer/app/components/oip-science/elastic/Filter.vue +719 -0
- package/layer/app/components/oip-science/elastic/MatchExplain.vue +152 -0
- package/layer/app/components/oip-science/establishments/Cards.vue +183 -0
- package/layer/app/components/oip-science/establishments/ClinicalTrials.vue +62 -0
- package/layer/app/components/oip-science/establishments/Hcps.vue +227 -0
- package/layer/app/components/oip-science/establishments/Informations.vue +263 -0
- package/layer/app/components/oip-science/establishments/LinkedList.vue +153 -0
- package/layer/app/components/oip-science/establishments/MatchedLabels.vue +194 -0
- package/layer/app/components/oip-science/establishments/PublicFinance.vue +62 -0
- package/layer/app/components/oip-science/euct/Investigators.vue +125 -0
- package/layer/app/components/oip-science/euct/Locations.vue +102 -0
- package/layer/app/components/oip-science/euct/Products.vue +101 -0
- package/layer/app/components/oip-science/euct/Publications.vue +89 -0
- package/layer/app/components/oip-science/euct/Sponsors.vue +86 -0
- package/layer/app/components/oip-science/euct/StudyDescription.vue +1075 -0
- package/layer/app/components/oip-science/euct-centers/ClinicalTrials.vue +40 -0
- package/layer/app/components/oip-science/euct-centers/Publications.vue +55 -0
- package/layer/app/components/oip-science/euct-investigators/ClinicalTrials.vue +41 -0
- package/layer/app/components/oip-science/euct-investigators/Informations.vue +171 -0
- package/layer/app/components/oip-science/euct-investigators/Publications.vue +51 -0
- package/layer/app/components/oip-science/hcps/AppelsAProjet.vue +62 -0
- package/layer/app/components/oip-science/hcps/Cards.vue +237 -0
- package/layer/app/components/oip-science/hcps/ClinicalTrials.vue +78 -0
- package/layer/app/components/oip-science/hcps/Informations.vue +296 -0
- package/layer/app/components/oip-science/hcps/LinkedList.vue +153 -0
- package/layer/app/components/oip-science/hcps/MatchedLabels.vue +207 -0
- package/layer/app/components/oip-science/hcps/Pubmed.vue +128 -0
- package/layer/app/components/oip-science/local/SliderTabs.vue +99 -0
- package/layer/app/components/oip-science/local/SliderTabsFull.vue +135 -0
- package/layer/app/components/oip-science/pubmed/Authors.vue +128 -0
- package/layer/app/components/oip-science/pubmed/Cards.vue +417 -0
- package/layer/app/components/oip-science/pubmed/ClinicalTrials.vue +71 -0
- package/layer/app/components/oip-science/resources/Phrc.vue +39 -0
- package/layer/app/composables/useOipChapterScroll.ts +43 -0
- package/layer/app/composables/useOipResourceHooks.ts +27 -0
- package/layer/app/composables/useOipResourceNav.ts +66 -0
- package/layer/app/composables/useOipResourceViews.ts +117 -0
- package/layer/app/composables/useOipResources.ts +83 -0
- package/layer/app/oip-drugs/PORTING.md +120 -0
- package/layer/app/oip-drugs/composables/useAssociationDetail.ts +220 -0
- package/layer/app/oip-drugs/composables/useAssociationExport.ts +63 -0
- package/layer/app/oip-drugs/composables/useAssociationLookup.ts +105 -0
- package/layer/app/oip-drugs/composables/useCardPrefOptions.ts +201 -0
- package/layer/app/oip-drugs/composables/useCurrency.ts +121 -0
- package/layer/app/oip-drugs/composables/useDirectusSources.ts +224 -0
- package/layer/app/oip-drugs/composables/useHeartBrandMatches.ts +112 -0
- package/layer/app/oip-drugs/composables/useHeartDetailSearches.ts +479 -0
- package/layer/app/oip-drugs/composables/useHeartIntlApprovals.ts +661 -0
- package/layer/app/oip-drugs/composables/useHeartLesIndication.ts +168 -0
- package/layer/app/oip-drugs/composables/useHeartMatchExplain.ts +231 -0
- package/layer/app/oip-drugs/composables/useHeartReports.ts +239 -0
- package/layer/app/oip-drugs/composables/useHeartSearchFields.ts +233 -0
- package/layer/app/oip-drugs/composables/useMergeByKey.ts +23 -0
- package/layer/app/oip-drugs/composables/useOipDrugsElastic.ts +621 -0
- package/layer/app/oip-drugs/composables/usePageEmpty.ts +58 -0
- package/layer/app/oip-drugs/composables/v-useSalesSource.ts +64 -0
- package/layer/app/oip-drugs/drugs.css +500 -0
- package/layer/app/oip-drugs/esIndices.ts +322 -0
- package/layer/app/oip-drugs/kinds.ts +264 -0
- package/layer/app/oip-drugs/locales/en.json +1571 -0
- package/layer/app/oip-drugs/locales/fr.json +1571 -0
- package/layer/app/oip-drugs/monographs/blincyto-has.vue +289 -0
- package/layer/app/oip-drugs/monographs/darzalex-has.vue +276 -0
- package/layer/app/oip-drugs/monographs/dupixent-has.vue +216 -0
- package/layer/app/oip-drugs/monographs/enhertu-has.vue +280 -0
- package/layer/app/oip-drugs/monographs/has-sein-2023.vue +1649 -0
- package/layer/app/oip-drugs/monographs/ibrance-has.vue +277 -0
- package/layer/app/oip-drugs/monographs/imfinzi-has.vue +293 -0
- package/layer/app/oip-drugs/monographs/keytruda-has.vue +334 -0
- package/layer/app/oip-drugs/monographs/kisqali-has.vue +201 -0
- package/layer/app/oip-drugs/monographs/opdivo-has.vue +231 -0
- package/layer/app/oip-drugs/monographs/ozempic-has.vue +186 -0
- package/layer/app/oip-drugs/monographs/tecentriq-has.vue +312 -0
- package/layer/app/oip-drugs/monographs/yescarta-has.vue +272 -0
- package/layer/app/oip-drugs/types/elastic.ts +113 -0
- package/layer/app/oip-drugs/types/es/agencies.ts +152 -0
- package/layer/app/oip-drugs/types/es/directory.ts +54 -0
- package/layer/app/oip-drugs/types/es/docByIndex.ts +151 -0
- package/layer/app/oip-drugs/types/es/openmedic.ts +67 -0
- package/layer/app/oip-drugs/types/es/outpatient.ts +71 -0
- package/layer/app/oip-drugs/types/es/portal.ts +130 -0
- package/layer/app/oip-drugs/types/es/retail.ts +107 -0
- package/layer/app/oip-drugs/types/es/statistics.ts +29 -0
- package/layer/app/oip-drugs/types/heart/CurrencyRate.ts +16 -0
- package/layer/app/oip-drugs/types/heart/ansm.ts +106 -0
- package/layer/app/oip-drugs/types/heart/tag.ts +29 -0
- package/layer/app/oip-drugs/utils/associationFields.ts +118 -0
- package/layer/app/oip-drugs/utils/contributions.ts +36 -0
- package/layer/app/oip-drugs/utils/countryMapping.ts +387 -0
- package/layer/app/oip-drugs/utils/esHighlight.ts +21 -0
- package/layer/app/oip-drugs/utils/exportSheets.ts +57 -0
- package/layer/app/oip-drugs/utils/heartIntlPrice.ts +228 -0
- package/layer/app/oip-drugs/utils/heartStyleAndFormat.ts +262 -0
- package/layer/app/oip-drugs/utils/heartStyleAnsm.ts +71 -0
- package/layer/app/oip-drugs/utils/latestDate.ts +31 -0
- package/layer/app/oip-drugs/utils/p-heartCardTags.ts +53 -0
- package/layer/app/oip-drugs/utils/priceExport.ts +269 -0
- package/layer/app/oip-drugs/utils/q-hasRatings.ts +43 -0
- package/layer/app/oip-drugs/utils/s-openCard.ts +20 -0
- package/layer/app/oip-drugs/utils/sourceUuids.ts +155 -0
- package/layer/app/oip-drugs/utils/styleAndFormat.ts +40 -0
- package/layer/app/oip-drugs/utils/v-salesSeries.ts +156 -0
- package/layer/app/oip-drugs/utils/v-scopeTags.ts +23 -0
- package/layer/app/oip-science/PORTING.md +93 -0
- package/layer/app/oip-science/assets/smartSelection.json +428 -0
- package/layer/app/oip-science/composables/useAuthorMatching.ts +342 -0
- package/layer/app/oip-science/composables/useCTCenter.ts +107 -0
- package/layer/app/oip-science/composables/useCTInvestigators.ts +107 -0
- package/layer/app/oip-science/composables/useEstablishmentCrossData.ts +139 -0
- package/layer/app/oip-science/composables/useEstablishmentMatching.ts +176 -0
- package/layer/app/oip-science/composables/useEuct.ts +418 -0
- package/layer/app/oip-science/composables/useEuctCenter.ts +107 -0
- package/layer/app/oip-science/composables/useEuctInvestigators.ts +107 -0
- package/layer/app/oip-science/composables/useGlobalClinicalTrials.ts +624 -0
- package/layer/app/oip-science/composables/useLinkedTrials.ts +83 -0
- package/layer/app/oip-science/composables/useOipElastic.ts +658 -0
- package/layer/app/oip-science/composables/useOipSearchExplain.ts +166 -0
- package/layer/app/oip-science/composables/usePubmed.ts +487 -0
- package/layer/app/oip-science/composables/useSearchFields.ts +153 -0
- package/layer/app/oip-science/indexConfig.json +794 -0
- package/layer/app/oip-science/locales/en.json +483 -0
- package/layer/app/oip-science/locales/fr.json +483 -0
- package/layer/app/oip-science/science.css +1182 -0
- package/layer/app/oip-science/utils/a-openCard.ts +23 -0
- package/layer/app/oip-science/utils/b-openCard.ts +35 -0
- package/layer/app/oip-science/utils/c-filterContext.ts +81 -0
- package/layer/app/oip-science/utils/f-types.ts +241 -0
- package/layer/app/oip-science/utils/frDiseaseTerms.ts +269 -0
- package/layer/app/oip-science/utils/matchMethod.ts +53 -0
- package/layer/app/oip-science/utils/sliderTabs.ts +13 -0
- package/layer/app/oip-science/utils/sources.ts +15 -0
- package/layer/app/oip-science/utils/styleAndFormat.ts +608 -0
- package/layer/app/oip-science/utils/toPresets.ts +7 -0
- package/layer/app/oip-science/utils/valueTable.ts +126 -0
- package/layer/app/plugins/oip-science-i18n.ts +17 -0
- package/layer/app/utils/oipFicheRoutes.ts +118 -0
- package/layer/app/utils/oipResources.ts +440 -0
- package/layer/nuxt.config.ts +22 -2
- package/layer/public/reports/blincyto-has.html +292 -0
- package/layer/public/reports/blincyto-has.pdf +0 -0
- package/layer/public/reports/darzalex-has.html +279 -0
- package/layer/public/reports/darzalex-has.pdf +0 -0
- package/layer/public/reports/dupixent-has.html +217 -0
- package/layer/public/reports/dupixent-has.pdf +0 -0
- package/layer/public/reports/enhertu-has.html +283 -0
- package/layer/public/reports/enhertu-has.pdf +0 -0
- package/layer/public/reports/has-sein-2023.html +1639 -0
- package/layer/public/reports/ibrance-has.html +280 -0
- package/layer/public/reports/ibrance-has.pdf +0 -0
- package/layer/public/reports/imfinzi-has.html +297 -0
- package/layer/public/reports/imfinzi-has.pdf +0 -0
- package/layer/public/reports/keytruda-has.html +337 -0
- package/layer/public/reports/keytruda-has.pdf +0 -0
- package/layer/public/reports/kisqali-has.html +202 -0
- package/layer/public/reports/kisqali-has.pdf +0 -0
- package/layer/public/reports/opdivo-has.html +232 -0
- package/layer/public/reports/opdivo-has.pdf +0 -0
- package/layer/public/reports/ozempic-has.html +188 -0
- package/layer/public/reports/ozempic-has.pdf +0 -0
- package/layer/public/reports/tecentriq-has.html +315 -0
- package/layer/public/reports/tecentriq-has.pdf +0 -0
- package/layer/public/reports/yescarta-has.html +275 -0
- package/layer/public/reports/yescarta-has.pdf +0 -0
- package/layer/server/api/oip/es.post.ts +99 -0
- package/layer/server/api/oip/pdf.get.ts +70 -0
- package/layer/server/api/oip/reports.get.ts +98 -0
- package/layer/server/api/oip/resource-types.get.ts +22 -0
- package/package.json +1 -1
|
@@ -0,0 +1,275 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="fr">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8">
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
6
|
+
<title>Yescarta (axicabtagene ciloleucel) : historique reglementaire HAS | Tekkare Intelligence</title>
|
|
7
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
8
|
+
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
9
|
+
<link href="https://fonts.googleapis.com/css2?family=Caudex:ital,wght@0,400;0,700;1,400;1,700&family=Figtree:ital,wght@0,300..900;1,300..900&display=swap" rel="stylesheet">
|
|
10
|
+
<script src="https://unpkg.com/@phosphor-icons/web"></script>
|
|
11
|
+
<style>
|
|
12
|
+
:root{
|
|
13
|
+
--primary:#2100AD; --secondary:#B485FF; --darkest:#1E293B; --dark:#525670;
|
|
14
|
+
--medium:#878CA6; --light:#DBDEF0; --lightest:#F5F5F9; --bg:#F9F9FA; --white:#FFFFFF;
|
|
15
|
+
--success:#16A34A; --warning:#D97706; --error:#E53535;
|
|
16
|
+
--db:#EE5599;
|
|
17
|
+
}
|
|
18
|
+
*{box-sizing:border-box;margin:0;padding:0;}
|
|
19
|
+
sup{font-size:0.6em;vertical-align:super;line-height:0;}
|
|
20
|
+
body{font-family:'Figtree',Avenir,Arial,sans-serif;color:var(--darkest);background:var(--bg);line-height:1.55;-webkit-font-smoothing:antialiased;}
|
|
21
|
+
.wrap{max-width:920px;margin:0 auto;padding:0 24px 64px;}
|
|
22
|
+
em{font-family:'Caudex',Georgia,serif;font-style:normal;font-weight:700;color:var(--primary);}
|
|
23
|
+
|
|
24
|
+
.hero{background:url("https://rcd-media.com/skills/Background_Degrade_Blanc.png") center/cover no-repeat;padding:48px 24px 40px;border-bottom:1px solid var(--light);}
|
|
25
|
+
.hero-inner{max-width:920px;margin:0 auto;}
|
|
26
|
+
.hero img{height:32px;margin-bottom:28px;}
|
|
27
|
+
.eyebrow{font-size:11px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--primary);margin-bottom:10px;}
|
|
28
|
+
.hero-top{display:flex;justify-content:space-between;align-items:center;gap:16px;margin-bottom:26px;flex-wrap:wrap;}
|
|
29
|
+
.hero-date{font-family:'Figtree';font-size:12px;font-weight:600;color:var(--dark);white-space:nowrap;}
|
|
30
|
+
.eyebrow-row{display:flex;align-items:center;gap:12px;margin-bottom:12px;flex-wrap:wrap;}
|
|
31
|
+
.ti-badge{display:inline-flex;align-items:center;gap:7px;font-family:'Figtree';font-weight:700;font-size:11px;letter-spacing:.1em;text-transform:uppercase;padding:5px 13px;border-radius:4px;color:#fff;background:linear-gradient(90deg,#4DCCF7,#A06BF5,#FF5CF0);}
|
|
32
|
+
.eyebrow-row .eyebrow{margin-bottom:0;}
|
|
33
|
+
.produced{margin-top:20px;font-size:12px;font-weight:500;color:var(--dark);display:flex;align-items:center;gap:8px;flex-wrap:wrap;}
|
|
34
|
+
h1{font-family:'Figtree';font-weight:700;font-size:34px;color:var(--darkest);line-height:1.15;margin-bottom:8px;}
|
|
35
|
+
h1 .mol{font-family:'Caudex';font-weight:700;color:var(--primary);}
|
|
36
|
+
.sub{font-size:15px;color:var(--dark);max-width:640px;}
|
|
37
|
+
|
|
38
|
+
.kpis{display:grid;grid-template-columns:repeat(4,1fr);gap:14px;margin:-28px auto 0;max-width:920px;padding:0 24px;position:relative;z-index:2;}
|
|
39
|
+
.kpi{background:var(--white);border:1px solid var(--light);border-radius:8px;padding:16px 18px;box-shadow:0 2px 8px rgba(30,41,59,0.06);}
|
|
40
|
+
.kpi .n{font-family:'Caudex';font-weight:700;font-size:34px;color:var(--primary);line-height:1;}
|
|
41
|
+
.kpi .l{font-size:11px;color:var(--dark);margin-top:6px;line-height:1.3;}
|
|
42
|
+
.kpi.good .n{color:var(--success);}
|
|
43
|
+
|
|
44
|
+
section{margin-top:44px;}
|
|
45
|
+
h2{font-family:'Figtree';font-weight:600;font-size:23px;color:var(--darkest);margin-bottom:6px;display:flex;align-items:center;gap:10px;}
|
|
46
|
+
h2 i{color:var(--primary);font-size:22px;}
|
|
47
|
+
.lead{font-size:14px;color:var(--dark);margin-bottom:20px;max-width:720px;}
|
|
48
|
+
|
|
49
|
+
.tl{position:relative;padding-left:26px;}
|
|
50
|
+
.tl::before{content:"";position:absolute;left:7px;top:6px;bottom:6px;width:2px;background:linear-gradient(180deg,#4DCCF7,#A06BF5,#FF5CF0);border-radius:2px;}
|
|
51
|
+
.yr{font-family:'Caudex';font-weight:700;font-size:15px;color:var(--primary);margin:22px 0 10px -26px;padding-left:26px;position:relative;}
|
|
52
|
+
.ev{position:relative;background:var(--white);border:1px solid var(--light);border-radius:8px;padding:12px 15px;margin-bottom:10px;box-shadow:0 2px 8px rgba(30,41,59,0.05);}
|
|
53
|
+
.ev::before{content:"";position:absolute;left:-22px;top:16px;width:9px;height:9px;border-radius:999px;background:var(--primary);border:2px solid var(--white);box-shadow:0 0 0 2px var(--light);}
|
|
54
|
+
.ev-top{display:flex;flex-wrap:wrap;align-items:center;gap:8px;margin-bottom:4px;}
|
|
55
|
+
.date{font-size:11px;font-weight:700;color:var(--medium);letter-spacing:.03em;min-width:78px;}
|
|
56
|
+
.ind{font-size:14px;font-weight:600;color:var(--darkest);flex:1;min-width:180px;}
|
|
57
|
+
.code{font-size:10px;color:var(--medium);font-family:'Figtree';white-space:nowrap;}
|
|
58
|
+
.code a{color:inherit;text-decoration:none;border-bottom:1px dotted currentColor;}
|
|
59
|
+
.code a:hover{color:var(--primary);border-bottom-color:var(--primary);}
|
|
60
|
+
.badges{display:flex;gap:6px;flex-wrap:wrap;}
|
|
61
|
+
.b{font-size:10px;font-weight:700;padding:3px 8px;border-radius:4px;letter-spacing:.02em;white-space:nowrap;}
|
|
62
|
+
.b-smr{background:var(--lightest);color:var(--dark);border:1px solid var(--light);}
|
|
63
|
+
.b-a3{background:#E7F6EE;color:#0B7A38;}
|
|
64
|
+
.b-a4{background:#FEF4E6;color:#9A5B04;}
|
|
65
|
+
.b-a5{background:#FCE9E9;color:#A11B1B;}
|
|
66
|
+
.b-na{background:var(--lightest);color:var(--medium);border:1px solid var(--light);}
|
|
67
|
+
.ctx{font-size:11px;color:var(--medium);margin-top:2px;}
|
|
68
|
+
|
|
69
|
+
.restrict{background:#FEF7EC;border:1px solid #F3D9B0;border-left:4px solid var(--warning);border-radius:8px;padding:18px 20px;margin-bottom:14px;}
|
|
70
|
+
.restrict h3{font-family:'Figtree';font-weight:700;font-size:15px;color:#9A5B04;margin-bottom:4px;display:flex;align-items:center;gap:8px;}
|
|
71
|
+
.restrict .meta{font-size:11px;color:var(--dark);margin-bottom:8px;}
|
|
72
|
+
.restrict p{font-size:13px;color:var(--darkest);}
|
|
73
|
+
.infobox{background:#EEF1FE;border:1px solid #C7D0F5;border-left:4px solid var(--primary);border-radius:8px;padding:18px 20px;margin-bottom:14px;}
|
|
74
|
+
.infobox h3{font-family:'Figtree';font-weight:700;font-size:15px;color:#183BA8;margin-bottom:4px;display:flex;align-items:center;gap:8px;}
|
|
75
|
+
.infobox p{font-size:13px;color:var(--darkest);}
|
|
76
|
+
|
|
77
|
+
.dist{background:var(--white);border:1px solid var(--light);border-radius:8px;padding:20px;box-shadow:0 2px 8px rgba(30,41,59,0.05);}
|
|
78
|
+
.row{display:flex;align-items:center;gap:12px;margin-bottom:12px;}
|
|
79
|
+
.row:last-child{margin-bottom:0;}
|
|
80
|
+
.row .lab{font-size:12px;font-weight:600;color:var(--dark);width:150px;}
|
|
81
|
+
.bar{flex:1;height:22px;background:var(--lightest);border-radius:4px;overflow:hidden;}
|
|
82
|
+
.fill{height:100%;border-radius:4px;display:flex;align-items:center;justify-content:flex-end;padding-right:8px;color:var(--white);font-size:11px;font-weight:700;}
|
|
83
|
+
|
|
84
|
+
.takeaway{background:var(--white);border:1px solid var(--light);border-left:4px solid transparent;border-image:linear-gradient(180deg,#4DCCF7,#A06BF5,#FF5CF0) 1;border-radius:8px;padding:20px 22px;margin-top:36px;box-shadow:0 2px 8px rgba(30,41,59,0.06);}
|
|
85
|
+
.takeaway .tk-lab{font-size:11px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--primary);margin-bottom:8px;display:flex;align-items:center;gap:8px;}
|
|
86
|
+
.takeaway p{font-size:14.5px;color:var(--darkest);line-height:1.6;}
|
|
87
|
+
.takeaway em{font-family:'Caudex',Georgia,serif;font-weight:700;color:var(--primary);font-style:normal;}
|
|
88
|
+
|
|
89
|
+
.price-wrap{background:var(--white);border:1px solid var(--light);border-radius:8px;padding:22px;box-shadow:0 2px 8px rgba(30,41,59,0.05);}
|
|
90
|
+
.price-row{display:flex;align-items:center;gap:14px;margin-bottom:10px;}
|
|
91
|
+
.price-row:last-child{margin-bottom:0;}
|
|
92
|
+
.price-row .py{font-size:12px;font-weight:700;color:var(--dark);width:52px;}
|
|
93
|
+
.price-bar{flex:1;height:26px;background:var(--lightest);border-radius:4px;overflow:hidden;}
|
|
94
|
+
.price-fill{height:100%;border-radius:4px;background:linear-gradient(90deg,#2100AD,#B485FF);display:flex;align-items:center;justify-content:flex-end;padding-right:10px;color:#fff;font-size:11px;font-weight:700;}
|
|
95
|
+
.price-note{font-size:12px;color:var(--dark);margin-top:14px;}
|
|
96
|
+
.pill-sus{display:inline-block;font-size:10px;font-weight:700;padding:3px 9px;border-radius:4px;background:#EEF1FE;color:#183BA8;}
|
|
97
|
+
.sku-table{width:100%;border-collapse:collapse;margin-bottom:18px;font-size:12.5px;background:var(--white);border:1px solid var(--light);border-radius:8px;overflow:hidden;box-shadow:0 2px 8px rgba(30,41,59,0.05);}
|
|
98
|
+
.sku-table thead th{background:var(--lightest);color:var(--dark);font-weight:700;font-size:11px;letter-spacing:.02em;text-align:left;padding:10px 12px;border-bottom:1px solid var(--light);}
|
|
99
|
+
.sku-table td{padding:10px 12px;border-bottom:1px solid var(--light);color:var(--darkest);vertical-align:top;}
|
|
100
|
+
.sku-table tr:last-child td{border-bottom:none;}
|
|
101
|
+
.sku-table td.num{font-family:'Caudex',Georgia,serif;font-weight:700;color:var(--primary);white-space:nowrap;}
|
|
102
|
+
.sku-table td .rg{font-size:10px;font-weight:700;color:var(--dark);}
|
|
103
|
+
.sku-cap{font-size:11px;color:var(--medium);margin:-8px 0 20px;}
|
|
104
|
+
|
|
105
|
+
.disclaimer{max-width:920px;margin:16px auto 0;padding:0 24px;}
|
|
106
|
+
.disclaimer-inner{display:flex;gap:10px;align-items:flex-start;background:var(--lightest);border:1px solid var(--light);border-radius:6px;padding:11px 14px;font-size:11.5px;color:var(--dark);line-height:1.5;}
|
|
107
|
+
.disclaimer-inner i{color:var(--primary);font-size:15px;margin-top:1px;flex-shrink:0;}
|
|
108
|
+
|
|
109
|
+
.b-pre{background:#EDE7FF;color:#3B1E8F;}
|
|
110
|
+
.b-post{background:#EEF1FE;color:#183BA8;}
|
|
111
|
+
.b-ongoing{background:#FEF4E6;color:#9A5B04;}
|
|
112
|
+
.b-closed{background:var(--lightest);color:var(--dark);border:1px solid var(--light);}
|
|
113
|
+
.ap-stats{display:flex;gap:22px;flex-wrap:wrap;margin:4px 0 22px;}
|
|
114
|
+
.ap-stat{display:flex;flex-direction:column;gap:2px;}
|
|
115
|
+
.ap-stat .v{font-family:'Caudex',Georgia,serif;font-weight:700;font-size:26px;color:var(--primary);line-height:1;}
|
|
116
|
+
.ap-stat .k{font-size:11px;color:var(--dark);}
|
|
117
|
+
|
|
118
|
+
footer{margin-top:48px;padding-top:22px;border-top:1px solid var(--light);font-size:11px;color:var(--dark);}
|
|
119
|
+
footer .src{display:flex;align-items:flex-start;gap:8px;margin-bottom:14px;}
|
|
120
|
+
footer i{color:var(--primary);font-size:15px;margin-top:1px;}
|
|
121
|
+
.legal{display:flex;gap:11px;align-items:flex-start;margin-top:20px;padding:14px 16px;background:var(--lightest);border:1px solid var(--light);border-left:4px solid var(--primary);border-radius:6px;font-size:12px;color:var(--dark);line-height:1.55;}
|
|
122
|
+
.legal i{color:var(--primary);font-size:18px;margin-top:1px;flex-shrink:0;}
|
|
123
|
+
.legal strong{color:var(--darkest);}
|
|
124
|
+
.sig{font-size:10px;font-weight:700;letter-spacing:.12em;color:var(--medium);text-transform:uppercase;line-height:1.6;margin-top:18px;}
|
|
125
|
+
.db-tag{display:inline-block;font-size:10px;font-weight:700;padding:3px 8px;border-radius:4px;background:#FFF0F7;color:#991144;}
|
|
126
|
+
|
|
127
|
+
@media(max-width:640px){
|
|
128
|
+
.kpis{grid-template-columns:repeat(2,1fr);}
|
|
129
|
+
h1{font-size:26px;}
|
|
130
|
+
.row .lab{width:120px;}
|
|
131
|
+
}
|
|
132
|
+
</style>
|
|
133
|
+
</head>
|
|
134
|
+
<body>
|
|
135
|
+
<a href="/reports/yescarta-has.pdf" download class="tk-dl-pdf" style="position:fixed;top:20px;right:20px;z-index:9999;display:inline-flex;align-items:center;gap:8px;padding:10px 16px;background:#2100AD;color:#fff;font-family:'Figtree',Avenir,Arial,sans-serif;font-size:13px;font-weight:700;text-decoration:none;border-radius:8px;box-shadow:0 4px 14px rgba(33,0,173,0.32);"><i class="ph-fill ph-file-pdf" style="font-size:16px;"></i>Télécharger le PDF</a>
|
|
136
|
+
|
|
137
|
+
<div class="hero">
|
|
138
|
+
<div class="hero-inner">
|
|
139
|
+
<div class="hero-top">
|
|
140
|
+
<img src="https://rcd-media.com/skills/Tekkare_Baseline_Bleu.svg" alt="Tekkare, Inspired by Healthcare" height="32">
|
|
141
|
+
<span class="hero-date">16 juillet 2026</span>
|
|
142
|
+
</div>
|
|
143
|
+
<div class="eyebrow-row">
|
|
144
|
+
<span class="ti-badge"><i class="ph-fill ph-sparkle" style="font-size:14px;"></i>Tekkare Intelligence</span>
|
|
145
|
+
<span class="eyebrow">Monographie réglementaire</span>
|
|
146
|
+
</div>
|
|
147
|
+
<h1><span class="mol">Yescarta</span> (axicabtagene ciloleucel)</h1>
|
|
148
|
+
<p class="sub">Le parcours HAS du premier CAR-T anti-CD19 remboursé en France : de la troisième ligne du lymphome B agressif jusqu'à la deuxième ligne, avec les niveaux de SMR / ASMR et un accès précoce dense, cartographiés à partir des données structurées OIP.</p>
|
|
149
|
+
<div class="produced"><i class="ph-fill ph-database" style="color:var(--db);font-size:15px;"></i>Produced with <span class="db-tag">OIP Databank<sup>®</sup></span></div>
|
|
150
|
+
</div>
|
|
151
|
+
</div>
|
|
152
|
+
|
|
153
|
+
<div class="kpis">
|
|
154
|
+
<div class="kpi"><div class="n">6</div><div class="l">avis de la Commission de la Transparence avec SMR / ASMR</div></div>
|
|
155
|
+
<div class="kpi"><div class="n">2018</div><div class="l">Première indication : LDGCB et LMPGCB réfractaire ou en rechute après au moins deux lignes (5 déc. 2018)</div></div>
|
|
156
|
+
<div class="kpi"><div class="n">5</div><div class="l">avis notés ASMR III (modéré), le niveau maximal atteint et jamais dépassé</div></div>
|
|
157
|
+
<div class="kpi good"><div class="n">0</div><div class="l">refus thérapeutique : SMR jugé Important dans les six avis</div></div>
|
|
158
|
+
</div>
|
|
159
|
+
|
|
160
|
+
<div class="wrap">
|
|
161
|
+
|
|
162
|
+
<div class="legal" style="margin-top:28px;"><i class="ph-fill ph-warning-circle"></i><div><strong>Avertissement.</strong> Ce rapport est une aide à l'analyse. Il doit être validé par l'utilisateur avant tout usage officiel. Tekkare ne saurait être tenue responsable de son utilisation.</div></div>
|
|
163
|
+
|
|
164
|
+
<div class="takeaway">
|
|
165
|
+
<div class="tk-lab"><i class="ph-fill ph-lightbulb"></i>À retenir</div>
|
|
166
|
+
<p>Premier <em>CAR-T anti-CD19</em> inscrit au remboursement en France (2018), Yescarta a bâti sa valeur sur une seule maladie dominante, le lymphome B agressif, où il a été reconnu <em>ASMR III</em> d'emblée puis de façon constante sur toute la trajectoire. La dynamique tient à un déplacement du produit vers l'amont : de la troisième ligne (post au moins deux lignes) vers la <em>deuxième ligne</em> des rechutes précoces, adossé à l'essai comparatif ZUMA-7 (gain de survie sans événement, puis de survie globale confirmée en 2026). L'extension au lymphome folliculaire raconte une histoire inverse : faute de comparaison directe et dans l'attente de l'essai ZUMA-22, la Commission n'y a accordé qu'une <em>ASMR V</em> (absence d'amélioration démontrée), sans pour autant fermer l'accès puisque le SMR y reste Important. Aucun refus de prise en charge sur la période. L'accès précoce a été particulièrement mobilisé (six décisions, dont un protocole Pré-AMM pour la deuxième ligne), servant de rampe vers le remboursement en environ sept à neuf mois. Le prix se lit par traitement : une PFHT unique de 244 800 € la poche, financée en sus des séjours hospitaliers.</p>
|
|
167
|
+
</div>
|
|
168
|
+
|
|
169
|
+
<section>
|
|
170
|
+
<h2><i class="ph-fill ph-chart-line-up"></i>Synthèse</h2>
|
|
171
|
+
<p class="lead">Depuis son inscription initiale dans le lymphome diffus à grandes cellules B (LDGCB) et le lymphome médiastinal primitif à grandes cellules B (LMPGCB) réfractaire ou en rechute après au moins deux lignes de traitement systémique, en décembre 2018, l'axicabtagene ciloleucel a consolidé sa place dans les lymphomes B agressifs par des réévaluations successives (données à long terme de ZUMA-1 en 2021 et 2023), toujours confirmées à <em>ASMR III</em>. Le tournant stratégique est l'obtention, en février 2023, d'une nouvelle indication en deuxième ligne dans les rechutes précoces (moins de douze mois) ou réfractaires, portée par l'essai comparatif de phase III ZUMA-7 : un rare cas d'ASMR III adossé à une démonstration de supériorité, confirmé en mai 2026 par l'atteinte d'un bénéfice de survie globale statistiquement significatif. En parallèle, l'entrée dans le lymphome folliculaire réfractaire ou en rechute après au moins trois lignes (janvier 2023) n'a obtenu qu'une <em>ASMR V</em>, la Commission jugeant les données non comparatives insuffisantes dans un contexte où une comparaison robuste était possible. Le service médical rendu a été jugé Important dans les six avis chiffrés : il n'y a <em>aucun refus thérapeutique</em> sur la trajectoire, l'ASMR V du folliculaire traduisant une absence de plus-value démontrée, non une fermeture de l'accès.</p>
|
|
172
|
+
</section>
|
|
173
|
+
|
|
174
|
+
<section>
|
|
175
|
+
<h2><i class="ph-fill ph-shield-check"></i>Prise en charge : aucun refus, une plus-value non démontrée dans le folliculaire</h2>
|
|
176
|
+
<p class="lead">Aucun avis ne constitue un refus de prise en charge : le SMR est resté Important dans toutes les indications évaluées. Un avis mérite une lecture attentive, l'ASMR V accordée dans le lymphome folliculaire, qui restreint la reconnaissance de la valeur ajoutée sans fermer l'accès au remboursement.</p>
|
|
177
|
+
|
|
178
|
+
<div class="infobox">
|
|
179
|
+
<h3><i class="ph-fill ph-shield-check"></i>Aucun refus thérapeutique</h3>
|
|
180
|
+
<p>Sur les six avis assortis d'un SMR, aucun n'a conclu à un service médical rendu insuffisant. Chaque indication évaluée, du lymphome B agressif en troisième puis deuxième ligne jusqu'au lymphome folliculaire avancé, a été jugée d'un service médical rendu Important, traduisant une valeur clinique reconnue dans des situations engageant le pronostic vital et aux options limitées.</p>
|
|
181
|
+
</div>
|
|
182
|
+
|
|
183
|
+
<div class="restrict">
|
|
184
|
+
<h3><i class="ph-fill ph-minus-circle"></i>Une ASMR V dans le lymphome folliculaire, sans refus</h3>
|
|
185
|
+
<div class="meta">CT-19896 · 18 janv. 2023 · lymphome folliculaire réfractaire ou en rechute après au moins trois lignes de traitement systémique · SMR Important · ASMR V</div>
|
|
186
|
+
<p>Sur la base d'une étude de phase II non comparative (réponse objective de 94 % chez les patients lourdement prétraités), et faute de comparaison directe robuste à une alternative disponible alors qu'elle était jugée possible, la Commission a conclu à une absence d'amélioration du service médical rendu (ASMR V) dans le lymphome folliculaire, dans l'attente notamment de l'essai de phase III randomisé ZUMA-22. Le service médical rendu restant Important, la prise en charge n'est pas fermée : ce n'est pas un refus, mais une reconnaissance de valeur ajoutée suspendue à des données comparatives.</p>
|
|
187
|
+
</div>
|
|
188
|
+
</section>
|
|
189
|
+
|
|
190
|
+
<section>
|
|
191
|
+
<h2><i class="ph-fill ph-chart-bar"></i>Répartition des SMR et ASMR</h2>
|
|
192
|
+
<div class="dist" style="margin-bottom:14px;">
|
|
193
|
+
<div class="row"><span class="lab">SMR Important</span><div class="bar"><div class="fill" style="width:100%;background:var(--success);">6</div></div></div>
|
|
194
|
+
</div>
|
|
195
|
+
<div class="dist">
|
|
196
|
+
<div class="row"><span class="lab">ASMR III (modéré)</span><div class="bar"><div class="fill" style="width:100%;background:var(--success);">5</div></div></div>
|
|
197
|
+
<div class="row"><span class="lab">ASMR V (absence)</span><div class="bar"><div class="fill" style="width:20%;background:var(--error);">1</div></div></div>
|
|
198
|
+
</div>
|
|
199
|
+
<p class="sku-cap" style="margin-top:12px;">Les six avis de la Commission de la Transparence assortis d'un niveau chiffré portent tous un SMR Important. L'ASMR atteint son maximum à III (modéré), obtenu à cinq reprises dans les lymphomes B agressifs ; l'unique ASMR V correspond au lymphome folliculaire.</p>
|
|
200
|
+
</section>
|
|
201
|
+
|
|
202
|
+
<section>
|
|
203
|
+
<h2><i class="ph-fill ph-currency-eur"></i>Prix et remboursement</h2>
|
|
204
|
+
<p class="lead">Yescarta est financé à l'hôpital <span class="pill-sus">inscrit sur la liste en sus</span>, en dehors des tarifs de séjour. C'est une immunothérapie cellulaire autologue à administration unique : les lymphocytes T du patient sont prélevés, modifiés pour exprimer un récepteur antigénique chimérique anti-CD19, puis réinjectés. Le produit se présente en une référence unique, une poche de dispersion pour perfusion. Le tableau récapitule le prix à jour de la présentation commercialisée.</p>
|
|
205
|
+
|
|
206
|
+
<table class="sku-table">
|
|
207
|
+
<thead>
|
|
208
|
+
<tr><th>Présentation</th><th>Régime</th><th>PFHT</th><th>Prix public</th><th>Dernière mise à jour</th></tr>
|
|
209
|
+
</thead>
|
|
210
|
+
<tbody>
|
|
211
|
+
<tr><td>Poche 0,4 à 2 × 10<sup>8</sup> cellules (68 mL)<br><span class="rg">dispersion pour perfusion, administration unique</span></td><td>Liste en sus</td><td class="num">244 800,00 €</td><td class="num">n.d.</td><td>1<sup>er</sup> mars 2026</td></tr>
|
|
212
|
+
</tbody>
|
|
213
|
+
</table>
|
|
214
|
+
<p class="sku-cap">PFHT (prix fabricant HT) de la présentation commercialisée, à la date de la dernière publication enregistrée dans les données OIP. Aucun prix public officine n'est renseigné, cohérent avec un produit hospitalier financé en sus des séjours. Yescarta étant une thérapie cellulaire dosée en cellules et administrée en une seule perfusion, le prix par traitement (par poche) est l'unité pertinente : le prix au milligramme n'a pas de sens pour ce produit.</p>
|
|
215
|
+
|
|
216
|
+
<p class="lead">La barre ci-dessous situe la <strong>PFHT (prix fabricant HT)</strong> de la poche, seule valeur de prix publiée dans les données OIP pour ce produit.</p>
|
|
217
|
+
<div class="price-wrap">
|
|
218
|
+
<div class="price-row"><span class="py">2026</span><div class="price-bar"><div class="price-fill" style="width:100.0%;">244 800,00 €</div></div></div>
|
|
219
|
+
<div class="price-note"><strong>PFHT (prix fabricant HT)</strong> de la <strong>poche unique</strong>. Les données OIP ne comportent qu'un seul point de prix publié (1<sup>er</sup> mars 2026) : aucune trajectoire d'évolution ne peut être tracée. Le produit avait d'abord relevé d'un circuit de rétrocession début 2019 (sans prix chiffré dans les données), avant d'être financé sur la liste en sus. Aucune révision de prix antérieure ou postérieure n'est publiée dans les données OIP.</div>
|
|
220
|
+
</div>
|
|
221
|
+
<p class="lead" style="margin-top:16px;">Lecture pour l'accès au marché : à la différence des cytotoxiques ou des anticorps à dosage récurrent, le coût s'apprécie par traitement administré une seule fois, ce qui simplifie la modélisation budgétaire mais concentre la dépense sur un acte unique et coûteux. L'absence de série historique dans les données OIP suggère une stabilité tarifaire à ce stade, l'essentiel de la négociation portant vraisemblablement sur des dispositifs conventionnels non publics.</p>
|
|
222
|
+
</section>
|
|
223
|
+
|
|
224
|
+
<section>
|
|
225
|
+
<h2><i class="ph-fill ph-rocket-launch"></i>Accès précoce</h2>
|
|
226
|
+
<p class="lead">L'accès précoce a joué un rôle central pour ce produit, notamment pour amener la deuxième ligne au remboursement avant l'AMM. Le suivi porte sur trois protocoles d'utilisation thérapeutique autorisés, au sein de six décisions d'accès précoce recensées au catalogue.</p>
|
|
227
|
+
<div class="ap-stats">
|
|
228
|
+
<div class="ap-stat"><span class="v">3</span><span class="k">protocoles d'accès précoce (PUT)</span></div>
|
|
229
|
+
<div class="ap-stat"><span class="v">1</span><span class="k">Pré-AMM (avant autorisation)</span></div>
|
|
230
|
+
<div class="ap-stat"><span class="v">2</span><span class="k">Post-AMM (après autorisation)</span></div>
|
|
231
|
+
<div class="ap-stat"><span class="v">6</span><span class="k">décisions d'accès précoce au catalogue</span></div>
|
|
232
|
+
</div>
|
|
233
|
+
<div class="tl">
|
|
234
|
+
<div class="yr">2022</div>
|
|
235
|
+
<div class="ev"><div class="ev-top"><span class="date">14 avr. 2022</span><span class="ind">Lymphome folliculaire en rechute ou réfractaire, après au moins trois lignes de traitement systémique <span class="code"><a href="https://www.has-sante.fr/jcms/p_3333446/fr/yescarta-axicabtagene-ciloleucel-lymphome-folliculaire" target="_blank" rel="noopener">· AP-3333446</a></span></span><div class="badges"><span class="b b-post">Post-AMM</span><span class="b b-ongoing">En cours</span></div></div><div class="ctx">Remboursement de droit commun <strong style="color:var(--primary);">environ 9 mois</strong> après (avis CT-19896, 18 janv. 2023, ASMR V)</div></div>
|
|
236
|
+
<div class="ev"><div class="ev-top"><span class="date">13 juil. 2022</span><span class="ind">LDGCB réfractaire ou en rechute dans les 12 mois après une première ligne, éligible à une chimiothérapie de rattrapage puis à une autogreffe de cellules souches (deuxième ligne) <span class="code"><a href="https://www.has-sante.fr/jcms/p_3358972/fr/yescarta-axicabtagene-ciloleucel-lymphome-diffus-a-grandes-cellules-b" target="_blank" rel="noopener">· AP-3358972</a></span></span><div class="badges"><span class="b b-pre">Pré-AMM</span><span class="b b-ongoing">En cours</span></div></div><div class="ctx">Remboursement de droit commun <strong style="color:var(--primary);">environ 7 mois</strong> après (avis CT-20056, 15 févr. 2023, ASMR III)</div></div>
|
|
237
|
+
|
|
238
|
+
<div class="yr">2023</div>
|
|
239
|
+
<div class="ev"><div class="ev-top"><span class="date">16 févr. 2023</span><span class="ind">LHGCB éligibles à une autogreffe, et LDGCB / LHGCB non éligibles, ayant rechuté dans les 12 mois après la première ligne ou réfractaires <span class="code"><a href="https://www.has-sante.fr/jcms/p_3418585/fr/yescarta-axicabtagene-ciloleucel-lymphome-ldgcb-lhgcb" target="_blank" rel="noopener">· AP-3418585</a></span></span><div class="badges"><span class="b b-post">Post-AMM</span><span class="b b-closed">Clôturé</span></div></div><div class="ctx">Protocole clôturé au moment même du basculement vers le remboursement de droit commun de la deuxième ligne (avis CT-20056, 15 févr. 2023) : délai non exploitable (avis concomitant)</div></div>
|
|
240
|
+
</div>
|
|
241
|
+
<div class="disclaimer" style="padding:0;margin-top:14px;"><div class="disclaimer-inner"><i class="ph-fill ph-info"></i><div>Délais estimés par rapprochement d'indication entre chaque protocole d'accès précoce et le premier avis de la Commission de la Transparence portant la même situation clinique (fourchette d'environ 7 à 9 mois, médiane proche de 8 mois sur les deux cas exploitables). Le protocole clôturé de février 2023 est écarté du calcul, son autorisation étant concomitante de l'avis d'inscription correspondant. Au-delà de ces trois protocoles structurés, trois décisions d'accès précoce supplémentaires figurent au catalogue (AP-3426769, AP-3455507, AP-3506813, 2023 à 2024), correspondant à des renouvellements ou continuités de prise en charge ; leur sens décisionnel n'a pas été recoupé pièce à pièce. La première indication de 2018 est antérieure au régime actuel d'accès précoce et ne porte pas de code AP dans les données OIP.</div></div></div>
|
|
242
|
+
</section>
|
|
243
|
+
|
|
244
|
+
<section>
|
|
245
|
+
<h2><i class="ph-fill ph-clock-countdown"></i>Frise complète des avis de la Transparence</h2>
|
|
246
|
+
<p class="lead">Chaque avis de la Commission de la Transparence, par ordre chronologique. Les libellés d'indication sont repris du texte des avis structurés.</p>
|
|
247
|
+
|
|
248
|
+
<div class="tl">
|
|
249
|
+
|
|
250
|
+
<div class="yr">2018</div>
|
|
251
|
+
<div class="ev"><div class="ev-top"><span class="date">05 déc.</span><span class="ind">LDGCB et LMPGCB réfractaire ou en rechute, après au moins deux lignes de traitement systémique (adultes) <span class="code"><a href="https://www.has-sante.fr/jcms/c_2888882/fr/yescarta-axicabtagene-ciloleucel-car-t-anti-cd19" target="_blank" rel="noopener">· CT-17214</a></span></span><div class="badges"><span class="b b-smr">SMR Important</span><span class="b b-a3">ASMR III</span></div></div><div class="ctx">Inscription initiale, première indication remboursée : premier CAR-T anti-CD19 en France</div></div>
|
|
252
|
+
|
|
253
|
+
<div class="yr">2021</div>
|
|
254
|
+
<div class="ev"><div class="ev-top"><span class="date">24 mars</span><span class="ind">LDGCB et LMPGCB réfractaire ou en rechute, après au moins deux lignes : réévaluation SMR et ASMR <span class="code"><a href="https://www.has-sante.fr/jcms/p_3262244/fr/yescarta-axicabtagene-ciloleucel" target="_blank" rel="noopener">· CT-19018</a></span></span><div class="badges"><span class="b b-smr">SMR Important</span><span class="b b-a3">ASMR III</span></div></div><div class="ctx">Conclusions antérieures maintenues : ASMR III confirmée</div></div>
|
|
255
|
+
|
|
256
|
+
<div class="yr">2023</div>
|
|
257
|
+
<div class="ev"><div class="ev-top"><span class="date">18 janv.</span><span class="ind">Lymphome folliculaire réfractaire ou en rechute, après au moins trois lignes de traitement systémique <span class="code"><a href="https://www.has-sante.fr/jcms/p_3407522/fr/yescarta-axicabtagene-ciloleucel-lymphome-folliculaire" target="_blank" rel="noopener">· CT-19896</a></span></span><div class="badges"><span class="b b-smr">SMR Important</span><span class="b b-a5">ASMR V</span></div></div><div class="ctx">Absence d'amélioration démontrée, données non comparatives, dans l'attente de l'étude ZUMA-22</div></div>
|
|
258
|
+
<div class="ev"><div class="ev-top"><span class="date">15 févr.</span><span class="ind">LDGCB et LHGCB ayant rechuté dans les 12 mois après la première ligne de chimio-immunothérapie, ou réfractaires (deuxième ligne) <span class="code"><a href="https://www.has-sante.fr/jcms/p_3419176/fr/yescarta-axicabtagene-ciloleucel-lymphome-diffus-a-grandes-cellules-b-ldgcb-et-lymphome-de-haut-grade-a-cellules-b-lhgcb" target="_blank" rel="noopener">· CT-20056</a></span></span><div class="badges"><span class="b b-smr">SMR Important</span><span class="b b-a3">ASMR III</span></div></div><div class="ctx">Extension à la deuxième ligne, adossée à l'essai comparatif ZUMA-7 (supériorité en survie sans événement)</div></div>
|
|
259
|
+
<div class="ev"><div class="ev-top"><span class="date">06 sept.</span><span class="ind">LDGCB et LMPGCB réfractaire ou en rechute, après au moins deux lignes : réévaluation post-inscription (ZUMA-1, suivi 63 mois) <span class="code"><a href="https://www.has-sante.fr/jcms/p_3467529/fr/yescarta-axicabtagene-ciloleucel-lymphome-diffus-a-grandes-cellules-b-ldgcb-lymphome-mediastinal-primitif-a-grandes-cellules-b-lmpgcb" target="_blank" rel="noopener">· CT-20263</a></span></span><div class="badges"><span class="b b-smr">SMR Important</span><span class="b b-a3">ASMR III</span></div></div><div class="ctx">Données à long terme confirmant l'appréciation : ASMR III maintenue</div></div>
|
|
260
|
+
|
|
261
|
+
<div class="yr">2026</div>
|
|
262
|
+
<div class="ev"><div class="ev-top"><span class="date">06 mai</span><span class="ind">LDGCB et LHGCB ayant rechuté dans les 12 mois après la première ligne, ou réfractaires (deuxième ligne) : réévaluation post-inscription (ZUMA-7, analyse finale) <span class="code"><a href="https://www.has-sante.fr/jcms/p_4052286/fr/yescarta-axicabtagene-ciloleucel-lymphome-diffus-a-grandes-cellules-b-ldgcb-et-lymphome-de-haut-grade-a-cellules-b-lhgcb" target="_blank" rel="noopener">· CT-21445</a></span></span><div class="badges"><span class="b b-smr">SMR Important</span><span class="b b-a3">ASMR III</span></div></div><div class="ctx">Bénéfice de survie globale désormais statistiquement significatif (HR = 0,73) : ASMR III maintenue. Dernière évaluation enregistrée</div></div>
|
|
263
|
+
|
|
264
|
+
</div>
|
|
265
|
+
</section>
|
|
266
|
+
|
|
267
|
+
<footer>
|
|
268
|
+
<div class="src"><i class="ph-fill ph-database"></i><div><strong>Source :</strong> avis de la HAS (Commission de la Transparence) et décisions d'accès précoce, consolidés et structurés dans <span class="db-tag">OIP Databank<sup>®</sup></span>. Les niveaux de SMR et d'ASMR proviennent de données déjà structurées, garantissant une lecture fidèle des avis officiels. Données arrêtées à juillet 2026.</div></div>
|
|
269
|
+
<div class="src"><i class="ph-fill ph-info"></i><div><strong>Périmètre :</strong> 6 avis de la Commission de la Transparence assortis d'un SMR et d'un ASMR (2018 à 2026), couvrant inscriptions, extensions d'indication et réévaluations post-inscription. L'accès précoce comprend 3 protocoles d'utilisation thérapeutique structurés (1 Pré-AMM, 2 Post-AMM), au sein de 6 décisions au catalogue.</div></div>
|
|
270
|
+
<div class="sig">TEKKARE<br>INSPIRED BY HEALTHCARE</div>
|
|
271
|
+
</footer>
|
|
272
|
+
|
|
273
|
+
</div>
|
|
274
|
+
</body>
|
|
275
|
+
</html>
|
|
Binary file
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { createError, defineEventHandler, getQuery, readBody } from "h3";
|
|
2
|
+
import { requireOipSession } from "../../utils/oipAuth";
|
|
3
|
+
import { findOipEsIndex, resolveOipEsIndex } from "../../utils/oipEsIndices";
|
|
4
|
+
import { oipResourceIndexes, type OipEsCluster } from "../../../app/utils/oipResources";
|
|
5
|
+
import { ES_INDEX } from "../../../app/oip-drugs/esIndices";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* POST /api/oip/es?cluster=&index=, servi par le layer OIP.
|
|
9
|
+
*
|
|
10
|
+
* Le proxy Elasticsearch des fiches de ressources (cf. utils/oipResources) :
|
|
11
|
+
* une publication s'affiche dans fr_drugs_app comme dans France Augmented
|
|
12
|
+
* Science, et une fiche marque dans France Augmented Science comme dans
|
|
13
|
+
* fr_drugs_app, donc chaque app lit les index des autres. Les cles restent
|
|
14
|
+
* cote serveur (`runtimeConfig.oipEs`) et seuls les index des fiches passent :
|
|
15
|
+
* la cle d'un cluster ne sert pas a lire le reste.
|
|
16
|
+
*
|
|
17
|
+
* Cluster `drugs` : les index se designent par id Directus (ou par nom), comme
|
|
18
|
+
* dans fr_drugs_app. Ses associations et ses registres d'autorisation
|
|
19
|
+
* etrangers demandent une autre cle sur le meme domaine (`authAssociations`,
|
|
20
|
+
* `authApprovals`) ; a defaut, la cle principale.
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
type DrugsKeyGroup = "auth" | "authAssociations" | "authApprovals";
|
|
24
|
+
|
|
25
|
+
const DRUG_IDS = new Set<string>(Object.values(ES_INDEX) as string[]);
|
|
26
|
+
const ASSOCIATION_IDS = new Set<string>(
|
|
27
|
+
Object.entries(ES_INDEX)
|
|
28
|
+
.filter(([key]) => key.startsWith("ASSOCIATION_"))
|
|
29
|
+
.map(([, value]) => value as string),
|
|
30
|
+
);
|
|
31
|
+
const APPROVAL_IDS = new Set<string>(
|
|
32
|
+
Object.entries(ES_INDEX)
|
|
33
|
+
.filter(([key]) => key.startsWith("APPROVAL_"))
|
|
34
|
+
.map(([, value]) => value as string),
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* La reference d'un index de fr_drugs_app telle que son catalogue l'ecrit :
|
|
39
|
+
* l'id Directus, ou le nom pour les index que le catalogue designe par nom.
|
|
40
|
+
* Vide si l'index n'est pas au catalogue.
|
|
41
|
+
*/
|
|
42
|
+
async function drugsKeyOf(ref: string): Promise<string> {
|
|
43
|
+
if (DRUG_IDS.has(ref)) return ref;
|
|
44
|
+
const id = (await findOipEsIndex(ref).catch(() => undefined))?.id;
|
|
45
|
+
return id && DRUG_IDS.has(id) ? id : "";
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function drugsKeyGroup(id: string): DrugsKeyGroup {
|
|
49
|
+
if (ASSOCIATION_IDS.has(id)) return "authAssociations";
|
|
50
|
+
if (APPROVAL_IDS.has(id)) return "authApprovals";
|
|
51
|
+
return "auth";
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
/** Le nom a interroger : l'index physique du registre, sinon le nom tel quel. */
|
|
55
|
+
async function physicalOf(ref: string): Promise<string> {
|
|
56
|
+
try {
|
|
57
|
+
return await resolveOipEsIndex(ref);
|
|
58
|
+
} catch (error: any) {
|
|
59
|
+
if (error?.statusCode !== 503 && error?.status !== 503) throw error;
|
|
60
|
+
return ref;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export default defineEventHandler(async (event) => {
|
|
65
|
+
await requireOipSession(event);
|
|
66
|
+
|
|
67
|
+
const { cluster, index } = getQuery(event) as { cluster?: string; index?: string };
|
|
68
|
+
const clusters = (useRuntimeConfig().oipEs ?? {}) as Record<string, Record<string, string | undefined>>;
|
|
69
|
+
const target = cluster ? clusters[cluster] : undefined;
|
|
70
|
+
if (!cluster || !target) throw createError({ status: 400, message: "Unknown cluster" });
|
|
71
|
+
if (!index || !/^[A-Za-z0-9_.,-]+$/.test(index)) throw createError({ status: 400, message: "Invalid index" });
|
|
72
|
+
|
|
73
|
+
const refs = index.split(",");
|
|
74
|
+
let authKey: DrugsKeyGroup = "auth";
|
|
75
|
+
if (cluster === "drugs") {
|
|
76
|
+
// Une requete multi-index part avec une seule cle : ses index en relevent tous.
|
|
77
|
+
const ids = await Promise.all(refs.map(drugsKeyOf));
|
|
78
|
+
if (ids.some((id) => !id)) throw createError({ status: 403, message: "Index not allowed" });
|
|
79
|
+
const groups = new Set(ids.map(drugsKeyGroup));
|
|
80
|
+
if (groups.size > 1) throw createError({ status: 400, message: "Indexes require different credentials" });
|
|
81
|
+
authKey = [...groups][0]!;
|
|
82
|
+
} else {
|
|
83
|
+
const allowed = oipResourceIndexes(cluster as OipEsCluster);
|
|
84
|
+
if (refs.some((ref) => !allowed.includes(ref))) throw createError({ status: 403, message: "Index not allowed" });
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
const auth = target[authKey] || target.auth;
|
|
88
|
+
if (!target.domain || !auth) {
|
|
89
|
+
throw createError({ status: 503, message: `Elasticsearch cluster not configured: ${cluster}` });
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
const physical = (await Promise.all(refs.map(physicalOf))).join(",");
|
|
93
|
+
const domain = target.domain.replace(/^https?:\/\//, "").replace(/\/+$/, "");
|
|
94
|
+
return await $fetch(`https://${domain}/${physical}/_search`, {
|
|
95
|
+
method: "POST",
|
|
96
|
+
headers: { authorization: `ApiKey ${auth}`, "content-type": "application/json" },
|
|
97
|
+
body: await readBody(event),
|
|
98
|
+
});
|
|
99
|
+
});
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { defineEventHandler, getQuery, getHeader, createError } from "h3";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GET /api/oip/pdf?url=, servi par le layer OIP (porte de /api/pdf de
|
|
5
|
+
* fr_drugs_app, pour les fiches medicament du layer).
|
|
6
|
+
*
|
|
7
|
+
* Sert un PDF distant pour l'apercu en cadre.
|
|
8
|
+
*
|
|
9
|
+
* Deux raisons de ne pas pointer l'iframe sur l'URL d'origine. Les copies
|
|
10
|
+
* Tekkare des documents (S3) sortent en `binary/octet-stream` : un navigateur
|
|
11
|
+
* les telecharge au lieu de les afficher. Et une source publique peut refuser
|
|
12
|
+
* d'etre encadree.
|
|
13
|
+
*
|
|
14
|
+
* Ce n'est pas un proxy ouvert : seuls les hotes qui servent nos documents
|
|
15
|
+
* sont acceptes, en https, et l'hote est reverifie apres les redirections. Le
|
|
16
|
+
* header Range est relaye — c'est lui qui permet d'ouvrir un PDF page par
|
|
17
|
+
* page.
|
|
18
|
+
*/
|
|
19
|
+
const ALLOWED_HOSTS = new Set([
|
|
20
|
+
"oip-images.s3.eu-west-3.amazonaws.com",
|
|
21
|
+
// Copies des referentiels du Dossier Playbook (sans en-tete CORS).
|
|
22
|
+
"oipcontent.s3.eu-west-3.amazonaws.com",
|
|
23
|
+
"ansm.sante.fr",
|
|
24
|
+
"has-sante.fr",
|
|
25
|
+
"www.has-sante.fr",
|
|
26
|
+
]);
|
|
27
|
+
|
|
28
|
+
const PASS_THROUGH = ["content-length", "content-range", "accept-ranges", "etag", "last-modified"];
|
|
29
|
+
|
|
30
|
+
function allowed(raw: string) {
|
|
31
|
+
let parsed: URL;
|
|
32
|
+
try {
|
|
33
|
+
parsed = new URL(raw);
|
|
34
|
+
} catch {
|
|
35
|
+
return null;
|
|
36
|
+
}
|
|
37
|
+
if (parsed.protocol !== "https:" || !ALLOWED_HOSTS.has(parsed.hostname)) return null;
|
|
38
|
+
return parsed;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export default defineEventHandler(async (event) => {
|
|
42
|
+
const { url } = getQuery(event) as { url?: string };
|
|
43
|
+
const target = url ? allowed(url) : null;
|
|
44
|
+
|
|
45
|
+
if (!target) {
|
|
46
|
+
throw createError({ status: 400, message: "Unsupported document URL" });
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const range = getHeader(event, "range");
|
|
50
|
+
const upstream = await fetch(target.toString(), { headers: range ? { range } : {} });
|
|
51
|
+
|
|
52
|
+
if (!allowed(upstream.url || target.toString())) {
|
|
53
|
+
throw createError({ status: 400, message: "Unsupported document URL" });
|
|
54
|
+
}
|
|
55
|
+
if (!upstream.ok && upstream.status !== 206) {
|
|
56
|
+
throw createError({ status: upstream.status, message: "Document unavailable" });
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
setResponseStatus(event, upstream.status);
|
|
60
|
+
// Le type d'origine n'est pas fiable, c'est tout l'objet de cette route.
|
|
61
|
+
setResponseHeader(event, "content-type", "application/pdf");
|
|
62
|
+
setResponseHeader(event, "content-disposition", "inline");
|
|
63
|
+
setResponseHeader(event, "cache-control", "private, max-age=3600");
|
|
64
|
+
for (const header of PASS_THROUGH) {
|
|
65
|
+
const value = upstream.headers.get(header);
|
|
66
|
+
if (value) setResponseHeader(event, header, value);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
return upstream.body;
|
|
70
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { defineEventHandler } from "h3";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* GET /api/oip/reports, servi par le layer OIP (porte de /api/reports de
|
|
5
|
+
* fr_drugs_app, pour les fiches medicament du layer). Meme reglage :
|
|
6
|
+
* runtimeConfig directusReportsUrl, directusReportsToken, reportsUuids.
|
|
7
|
+
*
|
|
8
|
+
* Rapports cures de la section « Rapports » du rail (collection Directus
|
|
9
|
+
* `Artifacts`), avec leur document HTML.
|
|
10
|
+
*
|
|
11
|
+
* L'appel se faisait depuis le navigateur, du temps ou l'app etait un SPA
|
|
12
|
+
* statique sans serveur : le token Directus partait dans le bundle, et la
|
|
13
|
+
* requete echouait de toute facon en CORS, l'instance n'autorisant pas
|
|
14
|
+
* l'origine de l'app. Le serveur s'en charge maintenant, comme pour les
|
|
15
|
+
* sources, les favoris et les documents.
|
|
16
|
+
*
|
|
17
|
+
* `?skip=` retire des uuids de la liste : les rapports livres dans
|
|
18
|
+
* `public/reports` l'emportent sur leur jumeau Directus (souvent depublie), et
|
|
19
|
+
* aller le chercher pour le jeter ensuite ne sert a rien.
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
interface ArtifactRow {
|
|
23
|
+
id: string;
|
|
24
|
+
Name: string | null;
|
|
25
|
+
HTML_file: string | null;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const list = (raw: unknown) =>
|
|
29
|
+
String(raw ?? "")
|
|
30
|
+
.split(",")
|
|
31
|
+
.map((value) => value.trim())
|
|
32
|
+
.filter(Boolean);
|
|
33
|
+
|
|
34
|
+
export default defineEventHandler(async (event) => {
|
|
35
|
+
const config = useRuntimeConfig();
|
|
36
|
+
const url = (config.directusReportsUrl as string | undefined)?.replace(/\/+$/, "");
|
|
37
|
+
const token = config.directusReportsToken as string | undefined;
|
|
38
|
+
const uuids = list(config.reportsUuids);
|
|
39
|
+
|
|
40
|
+
// Integration facultative : sans configuration, la section du rail se
|
|
41
|
+
// contente des rapports livres avec l'app.
|
|
42
|
+
if (!url || !token || !uuids.length) return [];
|
|
43
|
+
|
|
44
|
+
const { skip } = getQuery(event) as { skip?: string };
|
|
45
|
+
const skipped = new Set(list(skip));
|
|
46
|
+
|
|
47
|
+
// Un uuid fautif (404, droit retire, faute de frappe) ne doit pas emporter
|
|
48
|
+
// toute la liste : chaque rapport tombe pour son compte.
|
|
49
|
+
const reports = await Promise.all(
|
|
50
|
+
uuids
|
|
51
|
+
.filter((uuid) => !skipped.has(uuid))
|
|
52
|
+
.map((uuid) => fetchArtifact(url, token, uuid)),
|
|
53
|
+
);
|
|
54
|
+
|
|
55
|
+
return reports.filter((report) => report !== null);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
async function fetchArtifact(baseUrl: string, token: string, uuid: string) {
|
|
59
|
+
try {
|
|
60
|
+
const res = await $fetch<{ data?: ArtifactRow }>(
|
|
61
|
+
`${baseUrl}/items/Artifacts/${uuid}`,
|
|
62
|
+
{
|
|
63
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
64
|
+
query: { fields: "id,Name,HTML_file" },
|
|
65
|
+
},
|
|
66
|
+
);
|
|
67
|
+
const row = res?.data;
|
|
68
|
+
if (!row?.Name || !row.HTML_file) return null;
|
|
69
|
+
|
|
70
|
+
const html = await fetchHtmlAsset(baseUrl, token, row.HTML_file);
|
|
71
|
+
if (!html) return null;
|
|
72
|
+
|
|
73
|
+
return { id: row.id, title: row.Name, html, category: "report" as const };
|
|
74
|
+
} catch (err: any) {
|
|
75
|
+
console.warn(`[api/oip/reports] ${uuid} indisponible:`, err?.message || err);
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/**
|
|
81
|
+
* Le document lui-meme. Lu en texte quel que soit le type annonce : `$fetch`
|
|
82
|
+
* tenterait de parser du `text/html` en JSON et calerait sur le `<!DOCTYPE>`.
|
|
83
|
+
*/
|
|
84
|
+
async function fetchHtmlAsset(baseUrl: string, token: string, fileId: string) {
|
|
85
|
+
try {
|
|
86
|
+
const res = await fetch(`${baseUrl}/assets/${fileId}`, {
|
|
87
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
88
|
+
});
|
|
89
|
+
if (!res.ok) {
|
|
90
|
+
console.warn(`[api/oip/reports] asset ${fileId} HTTP ${res.status}`);
|
|
91
|
+
return null;
|
|
92
|
+
}
|
|
93
|
+
return await res.text();
|
|
94
|
+
} catch (err: any) {
|
|
95
|
+
console.warn(`[api/oip/reports] asset ${fileId} illisible:`, err?.message || err);
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { createError, defineEventHandler } from "h3";
|
|
2
|
+
import { getOipAccessToken } from "../../utils/oipAuth";
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* GET /api/oip/resource-types, servi par le layer OIP.
|
|
6
|
+
*
|
|
7
|
+
* Le registre des types de l'API Virtual Lab, avec leur affichage
|
|
8
|
+
* (`display`) : la carte generique du tiroir s'en sert pour un type que le
|
|
9
|
+
* layer n'a pas de vue pour montrer. Lu avec le jeton de l'utilisateur.
|
|
10
|
+
*/
|
|
11
|
+
export default defineEventHandler(async (event) => {
|
|
12
|
+
const token = await getOipAccessToken(event);
|
|
13
|
+
if (!token) throw createError({ status: 401, message: "Not authenticated" });
|
|
14
|
+
|
|
15
|
+
const apiUrl = (useRuntimeConfig().oipVirtualLabApiUrl as string) || process.env.VIRTUAL_LAB_API_URL;
|
|
16
|
+
if (!apiUrl) throw createError({ status: 500, message: "VIRTUAL_LAB_API_URL is not set" });
|
|
17
|
+
|
|
18
|
+
const response = await $fetch<{ resourceTypes?: unknown[] }>(`${apiUrl.replace(/\/+$/, "")}/resource-types`, {
|
|
19
|
+
headers: { Authorization: `Bearer ${token}` },
|
|
20
|
+
});
|
|
21
|
+
return response?.resourceTypes ?? [];
|
|
22
|
+
});
|