PageSourceSearch

https://macalculatriceenligne.com/apps/bilan-sante/js/screens/export.js

js macalculatriceenligne.com collected 2026-10-05 07:58:31 UTC 10,925 bytes, 237 lines download raw bytes

1/**
2 * Screen: export (Export PDF)
3 * Route: 'export'
4 * FULL PREMIUM — aperçu du rapport + bouton impression + contenu print-friendly
5 */
6(function () {
7  'use strict';
8
9  function render(el) {
10    App.trackEvent('pdf_export', {});
11
12    var profile      = Storage.getProfile();
13    var calculations = Storage.getCalculations() || [];
14    var today        = _formatDate(new Date());
15
16    var hasProfile = profile && profile.weight_kg && profile.height_cm && profile.age;
17
18    // Calculs pour le rapport
19    var reportData = hasProfile ? _buildReportData(profile, calculations) : null;
20
21    el.innerHTML =
22      '<div class="bsc-export">' +
23
24        '<header class="bsc-screen-header">' +
25          '<button class="bsc-back-btn" id="bsc-exp-back" aria-label="Retour">←</button>' +
26          '<h1 class="bsc-screen-title">Exporter mon bilan</h1>' +
27        '</header>' +
28
29        // Carte aperçu
30        '<section class="bsc-card bsc-exp-preview">' +
31          '<h2 class="bsc-card-title">Aperçu du rapport</h2>' +
32          '<div class="bsc-exp-preview-card">' +
33            '<div class="bsc-exp-preview-header">' +
34              '<div class="bsc-exp-preview-logo">BSC</div>' +
35              '<div class="bsc-exp-preview-meta">' +
36                '<strong>Bilan Santé Complet</strong>' +
37                '<span>' + today + '</span>' +
38              '</div>' +
39            '</div>' +
40            '<div class="bsc-exp-preview-author">Préparé avec MaCalculatriceEnLigne — document indicatif, ne remplace pas l\'avis d\'un professionnel de santé</div>' +
41            (reportData
42              ? _renderPreviewContent(reportData)
43              : '<p class="bsc-exp-no-profile">Complétez votre profil pour générer un bilan complet.</p>'
44            ) +
45          '</div>' +
46        '</section>' +
47
48        '<section class="bsc-card bsc-exp-actions">' +
49          '<button class="bsc-btn bsc-btn--primary bsc-btn--full bsc-btn--cta" id="bsc-exp-print">' +
50            '🖨 Imprimer / Sauvegarder en PDF' +
51          '</button>' +
52          '<p class="bsc-exp-print-hint">Astuce\u00a0: dans la boîte de dialogue d\'impression, choisissez «\u00a0Enregistrer au format PDF\u00a0» comme destination.</p>' +
53        '</section>' +
54
55        _ymyl() +
56
57      '</div>' +
58
59      // Contenu masqué destiné à l'impression
60      (reportData ? _buildPrintContent(reportData, today) : '');
61
62    el.querySelector('#bsc-exp-back').addEventListener('click', function () { App.navigate('home'); });
63    el.querySelector('#bsc-exp-print').addEventListener('click', function () {
64      window.print();
65    });
66  }
67
68  function _buildReportData(profile, calculations) {
69    var imc      = Formulas.imcStandard(profile.weight_kg, profile.height_cm);
70    var category = Formulas.omsCategoryLabel(imc);
71    var ageInterp = Formulas.ageAdjustedInterpretation(imc, profile.age);
72    var bmr      = Formulas.bmrMifflin(profile.weight_kg, profile.height_cm, profile.age, profile.sex);
73    var pal      = Formulas.getPalMultiplier(profile.activity_level);
74    var tdeeVal  = Formulas.tdee(bmr, pal);
75    var goal     = profile.goal || 'maintain';
76    var calories = Formulas.calorieTarget(tdeeVal, goal, profile.deficit_kcal || 500);
77    var score    = Formulas.healthScore(profile);
78    var lancet   = score.lancet;
79
80    var hM       = profile.height_cm / 100;
81    var omsLow   = Math.round(18.5 * hM * hM * 10) / 10;
82    var omsHigh  = Math.round(24.9 * hM * hM * 10) / 10;
83
84    // Projection
85    var projData = null;
86    if (goal !== 'maintain') {
87      var target = profile.target_weight || (goal === 'lose' ? Math.max(profile.weight_kg - 10, 40) : profile.weight_kg + 5);
88      var projRaw = Formulas.weightProjection(profile, target, profile.deficit_kcal || 500, 52);
89      if (projRaw.length > 0) {
90        projData = { weeks: projRaw[projRaw.length - 1].week, target: target };
91      }
92    }
93
94    return {
95      profile:   profile,
96      imc:       Math.round(imc * 10) / 10,
97      category:  category,
98      ageInterp: ageInterp,
99      bmr:       Math.round(bmr),
100      tdee:      Math.round(tdeeVal),
101      calories:  Math.round(calories),
102      goal:      goal,
103      score:     score,
104      lancet:    lancet,
105      omsLow:    omsLow,
106      omsHigh:   omsHigh,
107      projection: projData
108    };
109  }
110
111  function _renderPreviewContent(d) {
112    var rows = [
113      ['IMC standard (OMS)',          d.imc + ' — ' + _esc(d.category)],
114      ['IMC (classification OMS)',    d.ageInterp.label],
115      ['Métabolisme basal (Mifflin, estimation)', d.bmr + ' kcal/j'],
116      ['Dépense totale (TDEE, estimation)',       d.tdee + ' kcal/j'],
117      ['Objectif calorique (estimation)',         d.calories + ' kcal/j'],
118      ['Score santé global',           d.score.total + '/100 — ' + d.score.interpretation],
119      ['Commission du Lancet 2025',    d.lancet.label],
120      ['Poids correspondant à l\'éventail normal de l\'OMS (IMC 18,5–24,9)', d.omsLow + ' – ' + d.omsHigh + ' kg']
121    ];
122
123    if (d.projection) {
124      rows.push(['Projection objectif (estimation)', d.projection.target + ' kg en ' + d.projection.weeks + ' sem.']);
125    }
126
127    return (
128      '<table class="bsc-exp-preview-table">' +
129        rows.map(function (r) {
130          return '<tr><td class="bsc-exp-preview-key">' + _esc(r[0]) + '</td><td class="bsc-exp-preview-val">' + _esc(r[1]) + '</td></tr>';
131        }).join('') +
132      '</table>'
133    );
134  }
135
136  function _buildPrintContent(d, today) {
137    var profile = d.profile;
138    var sexLabel = profile.sex === 'male' ? 'Homme' : 'Femme';
139
140    return (
141      '<div class="bsc-print-content" aria-hidden="true">' +
142        '<div class="bsc-print-header">' +
143          '<h1>Bilan Santé Complet</h1>' +
144          '<p>Généré le ' + today + '</p>' +
145          '<p>Préparé avec MaCalculatriceEnLigne — document indicatif, ne remplace pas l\'avis d\'un professionnel de santé</p>' +
146        '</div>' +
147
148        '<section class="bsc-print-section">' +
149          '<h2>Profil</h2>' +
150          '<table class="bsc-print-table">' +
151            '<tr><td>Sexe</td><td>' + _esc(sexLabel) + '</td></tr>' +
152            '<tr><td>Âge</td><td>' + profile.age + ' ans</td></tr>' +
153            '<tr><td>Taille</td><td>' + profile.height_cm + ' cm</td></tr>' +
154            '<tr><td>Poids actuel</td><td>' + profile.weight_kg + ' kg</td></tr>' +
155            (profile.waist_cm ? '<tr><td>Tour de taille</td><td>' + profile.waist_cm + ' cm</td></tr>' : '') +
156            (profile.body_fat_pct ? '<tr><td>Masse grasse</td><td>' + profile.body_fat_pct + ' %</td></tr>' : '') +
157          '</table>' +
158        '</section>' +
159
160        '<section class="bsc-print-section">' +
161          '<h2>IMC</h2>' +
162          '<table class="bsc-print-table">' +
163            '<tr><td>IMC standard (OMS)</td><td>' + d.imc + ' — ' + _esc(d.category) + '</td></tr>' +
164            '<tr><td>IMC (classification OMS)</td><td>' + _esc(d.ageInterp.label) + '</td></tr>' +
165          '</table>' +
166          '<p>Selon la classification de l\'adulte de l\'OMS (rapport technique n° 894, 2000), un IMC de ' + d.imc + ' correspond à la catégorie « ' + _esc(d.category) + ' ». Cette classification n\'est pas un diagnostic.</p>' +
167        '</section>' +
168
169        '<section class="bsc-print-section">' +
170          '<h2>Métabolisme &amp; Calories</h2>' +
171          '<table class="bsc-print-table">' +
172            '<tr><td>Métabolisme basal (Mifflin-St Jeor, estimation)</td><td>' + d.bmr + ' kcal/j</td></tr>' +
173            '<tr><td>Dépense énergétique totale (TDEE, estimation)</td><td>' + d.tdee + ' kcal/j</td></tr>' +
174            '<tr><td>Objectif calorique (' + _goalLabel(d.goal) + ', estimation)</td><td>' + d.calories + ' kcal/j</td></tr>' +
175            '<tr><td>Poids correspondant à l\'éventail normal de l\'OMS (IMC 18,5–24,9)</td><td>' + d.omsLow + ' – ' + d.omsHigh + ' kg</td></tr>' +
176          '</table>' +
177        '</section>' +
178
179        '<section class="bsc-print-section">' +
180          '<h2>Score Santé — ' + d.score.total + '/100 (' + _esc(d.score.interpretation) + ')</h2>' +
181          '<table class="bsc-print-table">' +
182            d.score.components.map(function (c) {
183              return '<tr><td>' + _esc(c.name) + '</td><td>' + c.score + '/' + c.max + ' — ' + _esc(c.interpretation) + '</td></tr>';
184            }).join('') +
185          '</table>' +
186        '</section>' +
187
188        '<section class="bsc-print-section">' +
189          '<h2>Commission du Lancet 2025</h2>' +
190          '<p><strong>' + _esc(d.lancet.label) + '</strong></p>' +
191          '<p>' + _esc(d.lancet.description) + '</p>' +
192        '</section>' +
193
194        (d.projection
195          ? '<section class="bsc-print-section">' +
196              '<h2>Projection de poids</h2>' +
197              '<p>Objectif : ' + d.projection.target + ' kg en environ ' + d.projection.weeks + ' semaines (estimation).</p>' +
198              '<p>Cette projection repose sur une règle simplifiée (7 700 kcal ≈ 1 kg). Selon Hall et al. (Lancet 2011), une prédiction précise de l\'évolution du poids doit tenir compte de l\'adaptation de la dépense énergétique, et la réponse du poids à un changement d\'apport est lente : le résultat réel peut différer.</p>' +
199            '</section>'
200          : ''
201        ) +
202
203        '<footer class="bsc-print-footer">' +
204          '<p><strong>Avertissement médical :</strong> Ce rapport fournit des estimations à titre informatif uniquement. ' +
205          'Il ne constitue pas un avis médical, un diagnostic ou un traitement. ' +
206          'Seul un médecin (ou un diététicien) peut interpréter ces résultats.</p>' +
207          '<p>Généré par macalculatriceenligne.com — Données stockées uniquement sur votre appareil (RGPD).</p>' +
208        '</footer>' +
209
210      '</div>'
211    );
212  }
213
214  function _formatDate(d) {
215    var day   = String(d.getDate()).padStart(2, '0');
216    var month = String(d.getMonth() + 1).padStart(2, '0');
217    var year  = d.getFullYear();
218    return day + '/' + month + '/' + year;
219  }
220
221  function _goalLabel(goal) {
222    var map = { maintain: 'maintien', lose: 'perte de poids', gain: 'prise de poids' };
223    return map[goal] || goal;
224  }
225
226  function _esc(str) {
227    if (str == null) return '';
228    return String(str).replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;');
229  }
230
231  function _ymyl() {
232    return '<p class="bsc-ymyl-disclaimer">Ce rapport fournit des estimations à titre informatif uniquement. Il ne constitue pas un avis médical, un diagnostic ou un traitement. Seul un médecin (ou un diététicien) peut interpréter ces résultats.</p>';
233  }
234
235  App.registerScreen('export', render);
236
237})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.