// Bloc connecté des traitements du résumé patient. Il réunit le traitement et // son éventuel arrêt dans la même ligne ; la décision reste saisie par le // praticien et le serveur ne fait que mémoriser la consigne et son rappel. // Prefixe TSTOP_ et non TS_ : 'toast.jsx' de la reference figee declare deja // TS_VT, TS_INK et TS_HAIR2 au sommet de cette meme portee globale. const TSTOP_VT = window.VT || {}; const TSTOP_INK = TSTOP_VT.ink || '#0a0a0a'; const TSTOP_SUB = TSTOP_VT.sub || '#6b7280'; const TSTOP_HAIR = TSTOP_VT.hair || 'rgba(10,10,10,0.08)'; const TSTOP_HAIR2 = TSTOP_VT.hair2 || 'rgba(10,10,10,0.14)'; const TSTOP_SURFACE = TSTOP_VT.surface || '#f6f5f1'; const TSTOP_DANGER = TSTOP_VT.danger || '#b91c1c'; const TreatmentStopChoice = window.VascoUI?.SimpleSelect; function treatmentStopControlStyle(multiline = false) { return { width: '100%', minHeight: multiline ? 76 : 44, resize: multiline ? 'vertical' : undefined, padding: multiline ? '10px 12px' : '0 12px', background: '#fff', border: `1px solid ${TSTOP_HAIR2}`, borderRadius: 16, color: TSTOP_INK, outline: 'none', fontFamily: 'inherit', fontSize: 14, lineHeight: multiline ? 1.45 : undefined, }; } function TreatmentStopField({ id, label, required = false, error, children }) { return (
{React.cloneElement(children, { id, 'aria-required': required || undefined, 'aria-invalid': error ? 'true' : undefined, 'aria-describedby': error ? `${id}-error` : undefined, })} {error && }
); } function treatmentStopError(failure, fallback) { if (failure?.status === 401) return 'Votre session a expiré. Reconnectez-vous avant de réessayer.'; if (failure?.status === 403) return 'Vous n’êtes pas autorisé à modifier ces consignes.'; if (failure?.status === 404) return 'Cette programmation ou ce dossier n’existe plus.'; if (failure?.status === 0 || failure?.code === 'network_error' || failure?.code === 'request_timeout') { return 'Connexion au serveur impossible. Vérifiez le réseau puis réessayez.'; } return failure?.message || fallback; } function treatmentStopConflict(failure) { return failure?.status === 409 || failure?.code === 'version_conflict' || failure?.code === 'idempotency_conflict'; } function treatmentStopDate(value) { const match = /^(\d{4})-(\d{2})-(\d{2})$/.exec(value || ''); if (!match) return value || '–'; const date = new Date(Date.UTC(Number(match[1]), Number(match[2]) - 1, Number(match[3]))); return new Intl.DateTimeFormat('fr-FR', { day: 'numeric', month: 'long', year: 'numeric', timeZone: 'UTC', }).format(date); } function treatmentStopReminder(value) { const date = new Date(value); if (Number.isNaN(date.getTime())) return 'date indisponible'; return new Intl.DateTimeFormat('fr-FR', { day: 'numeric', month: 'long', year: 'numeric', hour: '2-digit', minute: '2-digit', }).format(date).replace(' à ', ' · '); } function TreatmentStopEditor({ patient, editor, accent, busy, fieldErrors, error, conflict, onChange, onClose, onSubmit, onReload }) { const isEdit = editor.mode === 'edit'; const values = editor.values; const { BottomSheet, Button, InlineAction, DayPicker } = window.VascoUI; return
onChange('treatment', value)} placeholder="Sélectionner" options={[["", "Sélectionner"], ...(patient.treatments || []).map( (treatment) => [treatment, treatment], )]} /> {/* Le calendrier de l'application, jamais celui du navigateur : il vient par-dessus l'écran et se lit comme le reste. */} onChange('stop_date', value)} /> onChange('reason', event.target.value)} placeholder="Facultatif" style={treatmentStopControlStyle()} />