HormoneTrack-web/js/ui/treatments.js
Siphonight 0dd5fa7dfd v1.11.0 (web) : inactifs regroupés en bas de la page Traitements + cartes atténuées — miroir Android
- Helper pur treatmentsForDisplay dans js/data/models.js (miroir du Kotlin,
  tri STABLE : actifs d'abord, inactifs après, ordre relatif conservé dans
  chaque groupe) — demande : « peu discernables, à placer à la fin ».
- Rendu : en-tête « Traitements inactifs » (seulement s'il en existe),
  cartes opacity 0.55 en plus du badge — lisibles et cliquables.
- Clés i18n inactive_section FR/EN ; WEB_VERSION alignée sur 1.11.0.
- 4 tests treatments-display.test.js (miroir TreatmentsDisplayTest.kt).

184 tests + E2E verts (check.sh).
2026-09-29 07:30:59 +02:00

91 lines
3.9 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/**
* ─────────────────────────────────────────────────────────────────────────────
* Écran Traitements (portage de `ui/screens/TreatmentsScreen.kt`).
*
* Cartes (nom, voie, dose, chips ester·modèle / Tmax / ×scale / ⏰ rappel,
* badge inactif) → tap = éditeur. ⚠️ Le chip modèle passe par modelLabelKey
* (fix #59 : un ternaire à 2 branches affichait « Estrannaise » pour WHSAH).
*
* v1.11.0 (demande utilisatrice, miroir Android) : les ACTIFS d'abord, les
* INACTIFS regroupés TOUT EN BAS sous un en-tête de section, cartes
* ATTÉNUÉES (opacity 0.55) en plus du badge — « peu discernables ».
* ─────────────────────────────────────────────────────────────────────────────
*/
import { store } from '../data/store.js';
import { modelLabelKey, routeLabelKey, treatmentFlags, treatmentsForDisplay } from '../data/models.js';
import { t } from '../util/i18n.js';
import { formatDose } from '../util/format.js';
import { el, assistChip, fab } from './components.js';
/**
* Rend l'écran Traitements.
* @param {HTMLElement} container
* @param {object} ctx { openEditor: (id:number)=>void, openNew: ()=>void }
*/
export function renderTreatments(container, ctx) {
// v1.11.0 : actifs d'abord, inactifs regroupés en bas (cf treatmentsForDisplay)
const treatments = treatmentsForDisplay(store.getTreatments());
const active = treatments.filter((tr) => tr.isActive);
const inactive = treatments.filter((tr) => !tr.isActive);
const col = el('div', {});
container.appendChild(col);
if (treatments.length === 0) {
col.appendChild(el('p', {}, t('no_data')));
}
/**
* Rend UNE carte traitement. @param {object} tr @param {boolean} dimmed
* carte inactive → opacité réduite (second signal visuel au-delà du
* badge ; reste lisible et cliquable).
*/
const renderCard = (tr, dimmed) => {
const flags = treatmentFlags(tr); // miroir des getters Kotlin
const card = el('div', {
class: 'card',
style: `cursor:pointer;${dimmed ? 'opacity:0.55;' : ''}`,
onclick: () => ctx.openEditor(tr.id),
});
const titleRow = el('div', { class: 'row' });
titleRow.appendChild(el('span', { style: 'font-weight:600;flex:1;' }, tr.name));
if (!tr.isActive) titleRow.appendChild(el('span', { class: 'small' }, t('inactive')));
card.appendChild(titleRow);
card.appendChild(el('div', { class: 'sub' },
`${t(routeLabelKey(tr.route))} · ${formatDose(tr.doseAmount)} ${tr.doseUnit}`));
const chipRow = el('div', { class: 'chip-row wrap', style: 'margin-top:6px;' });
if (flags.usesProfileModel) {
// v1.4.7 (fix #59) : label via modelLabelKey — pas de ternaire à 2 branches
chipRow.appendChild(assistChip(`${tr.esterType} · ${t(modelLabelKey(tr.pkModel))}`));
} else {
chipRow.appendChild(assistChip(`${t('pk_absorption')} ${formatDose(tr.absorptionHours)}h`));
}
if (tr.scaleFactor !== 1.0) chipRow.appendChild(assistChip(`×${tr.scaleFactor.toFixed(2)}`));
if (tr.reminderEnabled) {
const hh = String(tr.reminderHour ?? 0).padStart(2, '0');
const mm = String(tr.reminderMinute ?? 0).padStart(2, '0');
chipRow.appendChild(assistChip(`⏰ ${hh}:${mm}`));
}
card.appendChild(chipRow);
return card;
};
for (const tr of active) {
col.appendChild(renderCard(tr, false));
}
// En-tête de section SEULEMENT s'il existe des inactifs (miroir Android)
if (inactive.length > 0) {
col.appendChild(el('p', { class: 'sub', style: 'margin:14px 0 4px;' }, t('inactive_section')));
}
for (const tr of inactive) {
col.appendChild(renderCard(tr, true));
}
container.appendChild(fab(ctx.openNew));
}