From 45e391c60a57183422796f0d76849f29c96d49a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?= Date: Fri, 12 Jun 2026 21:44:25 +0200 Subject: [PATCH] feat(medications): the table's stock column projects its runway MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Under the dose count the column now shows roughly how many days the remaining supply covers — the same coarse schedule-derived estimate the detail overview renders, so the refill question is answered at a glance. (#316) --- messages/de.json | 58 ++++++++++++++++++- messages/en.json | 58 ++++++++++++++++++- messages/es.json | 58 ++++++++++++++++++- messages/fr.json | 58 ++++++++++++++++++- messages/it.json | 58 ++++++++++++++++++- messages/pl.json | 58 ++++++++++++++++++- .../medications/medication-table.tsx | 45 ++++++++++---- 7 files changed, 375 insertions(+), 18 deletions(-) diff --git a/messages/de.json b/messages/de.json index 7d201e76a..5b09c708a 100644 --- a/messages/de.json +++ b/messages/de.json @@ -664,7 +664,58 @@ "bulkDeleteSuccess": "{count} Einträge gelöscht", "bulkDeleteError": "Fehler beim Löschen der ausgewählten Einträge", "bulkDeleteConfirmTitle": "{count} Einträge löschen?", - "bulkDeleteConfirmBody": "Die {count} ausgewählten Stimmungseinträge werden endgültig gelöscht." + "bulkDeleteConfirmBody": "Die {count} ausgewählten Stimmungseinträge werden endgültig gelöscht.", + "customize": "Stimmungs-Tags anpassen", + "addTagInline": "Tag hinzufügen", + "manage": { + "groupsTitle": "Gruppen", + "groupsDescription": "Lege eigene Gruppen an und bestimme ihre Reihenfolge in der Auswahl.", + "newGroup": "Neue Gruppe", + "groupLabel": "Gruppenname", + "groupIcon": "Symbol", + "groupCreated": "Gruppe erstellt", + "groupRenamed": "Gruppe gespeichert", + "groupDeleteTitle": "Gruppe löschen?", + "groupDeleteBody": "Tags aus dieser Gruppe wandern zurück in ihre ursprüngliche Gruppe. Es werden keine Einträge gelöscht.", + "groupDeleted": "Gruppe gelöscht", + "groupEmpty": "Noch keine eigenen Gruppen.", + "groupLimitReached": "Gruppen-Limit erreicht", + "tagsTitle": "Tags", + "tagsDescription": "Blende Tags aus, sortiere und verschiebe sie oder bearbeite sie.", + "newTag": "Neuer Tag", + "tagLabel": "Tag-Name", + "tagIcon": "Symbol", + "tagGroup": "Gruppe", + "usageCount": "{count} Einträge", + "hideTag": "Tag ausblenden", + "showTag": "Tag einblenden", + "moveToGroup": "In Gruppe verschieben", + "archive": "Archivieren", + "restore": "Wiederherstellen", + "archivedTitle": "Archivierte Tags", + "archivedDescription": "Archivierte Tags bleiben in deinen bisherigen Einträgen erhalten – sie verschwinden nur aus der Auswahl.", + "archivedEmpty": "Nichts archiviert.", + "purgeTitle": "Tag endgültig löschen?", + "purgeBody": "Der Tag wird aus {count} bisherigen Einträgen entfernt. Das lässt sich nicht rückgängig machen.", + "purgeAction": "Endgültig löschen", + "purged": "Tag gelöscht", + "tagLimitReached": "Tag-Limit erreicht", + "iconPickerTitle": "Symbol wählen", + "iconSearchPlaceholder": "Symbole durchsuchen…", + "iconSearchEmpty": "Kein passendes Symbol.", + "iconSearchClear": "Suche leeren", + "orderSave": "Reihenfolge speichern", + "orderSaved": "Reihenfolge gespeichert", + "moveUp": "Nach oben", + "moveDown": "Nach unten", + "iconGroupEmotions": "Gefühle", + "iconGroupActivities": "Aktivitäten", + "iconGroupHealth": "Gesundheit", + "iconGroupFood": "Essen & Trinken", + "iconGroupWeather": "Wetter", + "iconGroupPlaces": "Orte", + "iconGroupMisc": "Sonstiges" + } }, "medications": { "title": "Medikamente", @@ -1749,6 +1800,7 @@ "tableComplianceDays": "{days} T", "tableStockDoseOne": "1 Dosis", "tableStockDoses": "{count} Dosen", + "tableStockRunway": "≈ {days} Tage übrig", "takeActionFor": "Einnehmen – {name}", "skipActionFor": "Überspringen – {name}", "reorderTitle": "Reihenfolge anpassen", @@ -3789,6 +3841,10 @@ "medications": { "title": "Medikamente", "description": "Listenansicht und Reihenfolge der Medikamente." + }, + "mood": { + "title": "Stimmungs-Tags", + "description": "Gruppen, Tags und Reihenfolge der Tag-Auswahl." } }, "profile": "Profil", diff --git a/messages/en.json b/messages/en.json index 17a61bd74..6fdcb076b 100644 --- a/messages/en.json +++ b/messages/en.json @@ -664,7 +664,58 @@ "bulkDeleteSuccess": "{count} entries deleted", "bulkDeleteError": "Error deleting the selected entries", "bulkDeleteConfirmTitle": "Delete {count} entries?", - "bulkDeleteConfirmBody": "The {count} selected mood entries will be permanently deleted." + "bulkDeleteConfirmBody": "The {count} selected mood entries will be permanently deleted.", + "customize": "Customize mood tags", + "addTagInline": "Add tag", + "manage": { + "groupsTitle": "Groups", + "groupsDescription": "Create your own groups and set the order the picker shows them in.", + "newGroup": "New group", + "groupLabel": "Group name", + "groupIcon": "Icon", + "groupCreated": "Group created", + "groupRenamed": "Group saved", + "groupDeleteTitle": "Delete group?", + "groupDeleteBody": "Tags in this group move back to their original group. No entries are deleted.", + "groupDeleted": "Group deleted", + "groupEmpty": "No own groups yet.", + "groupLimitReached": "Group limit reached", + "tagsTitle": "Tags", + "tagsDescription": "Hide, rearrange, move, or edit the tags the picker shows.", + "newTag": "New tag", + "tagLabel": "Tag name", + "tagIcon": "Icon", + "tagGroup": "Group", + "usageCount": "{count} entries", + "hideTag": "Hide tag", + "showTag": "Show tag", + "moveToGroup": "Move to group", + "archive": "Archive", + "restore": "Restore", + "archivedTitle": "Archived tags", + "archivedDescription": "Archived tags stay in your past entries — they only disappear from the picker.", + "archivedEmpty": "Nothing archived.", + "purgeTitle": "Delete tag permanently?", + "purgeBody": "This removes the tag from {count} past entries. This cannot be undone.", + "purgeAction": "Delete permanently", + "purged": "Tag deleted", + "tagLimitReached": "Tag limit reached", + "iconPickerTitle": "Choose an icon", + "iconSearchPlaceholder": "Search icons…", + "iconSearchEmpty": "No icon matches.", + "iconSearchClear": "Clear search", + "orderSave": "Save order", + "orderSaved": "Order saved", + "moveUp": "Move up", + "moveDown": "Move down", + "iconGroupEmotions": "Emotions", + "iconGroupActivities": "Activities", + "iconGroupHealth": "Health", + "iconGroupFood": "Food & drink", + "iconGroupWeather": "Weather", + "iconGroupPlaces": "Places", + "iconGroupMisc": "Other" + } }, "medications": { "title": "Medications", @@ -1749,6 +1800,7 @@ "tableComplianceDays": "{days} d", "tableStockDoseOne": "1 dose", "tableStockDoses": "{count} doses", + "tableStockRunway": "≈ {days} days left", "takeActionFor": "Take – {name}", "skipActionFor": "Skip – {name}", "reorderTitle": "Adjust order", @@ -3789,6 +3841,10 @@ "medications": { "title": "Medications", "description": "List view and medication order." + }, + "mood": { + "title": "Mood tags", + "description": "Groups, tags, and order of the mood picker." } }, "profile": "Profile", diff --git a/messages/es.json b/messages/es.json index f42e61dc8..6b89d58f1 100644 --- a/messages/es.json +++ b/messages/es.json @@ -664,7 +664,58 @@ "bulkDeleteSuccess": "{count} entradas eliminadas", "bulkDeleteError": "Error al eliminar las entradas seleccionadas", "bulkDeleteConfirmTitle": "¿Eliminar {count} entradas?", - "bulkDeleteConfirmBody": "Las {count} entradas de estado de ánimo seleccionadas se eliminarán de forma permanente." + "bulkDeleteConfirmBody": "Las {count} entradas de estado de ánimo seleccionadas se eliminarán de forma permanente.", + "customize": "Personalizar etiquetas de ánimo", + "addTagInline": "Añadir etiqueta", + "manage": { + "groupsTitle": "Grupos", + "groupsDescription": "Crea tus propios grupos y define su orden en el selector.", + "newGroup": "Nuevo grupo", + "groupLabel": "Nombre del grupo", + "groupIcon": "Icono", + "groupCreated": "Grupo creado", + "groupRenamed": "Grupo guardado", + "groupDeleteTitle": "¿Eliminar grupo?", + "groupDeleteBody": "Las etiquetas de este grupo vuelven a su grupo original. No se elimina ninguna entrada.", + "groupDeleted": "Grupo eliminado", + "groupEmpty": "Aún no hay grupos propios.", + "groupLimitReached": "Límite de grupos alcanzado", + "tagsTitle": "Etiquetas", + "tagsDescription": "Oculta, reordena, mueve o edita las etiquetas del selector.", + "newTag": "Nueva etiqueta", + "tagLabel": "Nombre de la etiqueta", + "tagIcon": "Icono", + "tagGroup": "Grupo", + "usageCount": "{count} entradas", + "hideTag": "Ocultar etiqueta", + "showTag": "Mostrar etiqueta", + "moveToGroup": "Mover a grupo", + "archive": "Archivar", + "restore": "Restaurar", + "archivedTitle": "Etiquetas archivadas", + "archivedDescription": "Las etiquetas archivadas permanecen en tus entradas anteriores; solo desaparecen del selector.", + "archivedEmpty": "Nada archivado.", + "purgeTitle": "¿Eliminar etiqueta definitivamente?", + "purgeBody": "Esto elimina la etiqueta de {count} entradas anteriores. No se puede deshacer.", + "purgeAction": "Eliminar definitivamente", + "purged": "Etiqueta eliminada", + "tagLimitReached": "Límite de etiquetas alcanzado", + "iconPickerTitle": "Elegir icono", + "iconSearchPlaceholder": "Buscar iconos…", + "iconSearchEmpty": "Ningún icono coincide.", + "iconSearchClear": "Borrar búsqueda", + "orderSave": "Guardar orden", + "orderSaved": "Orden guardado", + "moveUp": "Subir", + "moveDown": "Bajar", + "iconGroupEmotions": "Emociones", + "iconGroupActivities": "Actividades", + "iconGroupHealth": "Salud", + "iconGroupFood": "Comida y bebida", + "iconGroupWeather": "Tiempo", + "iconGroupPlaces": "Lugares", + "iconGroupMisc": "Otros" + } }, "medications": { "title": "Medicamentos", @@ -1749,6 +1800,7 @@ "tableComplianceDays": "{days} d", "tableStockDoseOne": "1 dosis", "tableStockDoses": "{count} dosis", + "tableStockRunway": "≈ {days} días restantes", "takeActionFor": "Tomar – {name}", "skipActionFor": "Omitir – {name}", "reorderTitle": "Ajustar orden", @@ -3789,6 +3841,10 @@ "medications": { "title": "Medicamentos", "description": "Vista de lista y orden de los medicamentos." + }, + "mood": { + "title": "Etiquetas de ánimo", + "description": "Grupos, etiquetas y orden del selector de ánimo." } }, "profile": "Perfil", diff --git a/messages/fr.json b/messages/fr.json index c3f9db034..ac6e4091e 100644 --- a/messages/fr.json +++ b/messages/fr.json @@ -664,7 +664,58 @@ "bulkDeleteSuccess": "{count} entrées supprimées", "bulkDeleteError": "Erreur lors de la suppression des entrées sélectionnées", "bulkDeleteConfirmTitle": "Supprimer {count} entrées ?", - "bulkDeleteConfirmBody": "Les {count} entrées d'humeur sélectionnées seront définitivement supprimées." + "bulkDeleteConfirmBody": "Les {count} entrées d'humeur sélectionnées seront définitivement supprimées.", + "customize": "Personnaliser les étiquettes d’humeur", + "addTagInline": "Ajouter une étiquette", + "manage": { + "groupsTitle": "Groupes", + "groupsDescription": "Crée tes propres groupes et définis leur ordre dans le sélecteur.", + "newGroup": "Nouveau groupe", + "groupLabel": "Nom du groupe", + "groupIcon": "Icône", + "groupCreated": "Groupe créé", + "groupRenamed": "Groupe enregistré", + "groupDeleteTitle": "Supprimer le groupe ?", + "groupDeleteBody": "Les étiquettes de ce groupe reviennent dans leur groupe d’origine. Aucune saisie n’est supprimée.", + "groupDeleted": "Groupe supprimé", + "groupEmpty": "Pas encore de groupe personnel.", + "groupLimitReached": "Limite de groupes atteinte", + "tagsTitle": "Étiquettes", + "tagsDescription": "Masque, réordonne, déplace ou modifie les étiquettes du sélecteur.", + "newTag": "Nouvelle étiquette", + "tagLabel": "Nom de l’étiquette", + "tagIcon": "Icône", + "tagGroup": "Groupe", + "usageCount": "{count} saisies", + "hideTag": "Masquer l’étiquette", + "showTag": "Afficher l’étiquette", + "moveToGroup": "Déplacer vers un groupe", + "archive": "Archiver", + "restore": "Restaurer", + "archivedTitle": "Étiquettes archivées", + "archivedDescription": "Les étiquettes archivées restent dans tes saisies passées — elles disparaissent seulement du sélecteur.", + "archivedEmpty": "Rien d’archivé.", + "purgeTitle": "Supprimer l’étiquette définitivement ?", + "purgeBody": "L’étiquette sera retirée de {count} saisies passées. Cette action est irréversible.", + "purgeAction": "Supprimer définitivement", + "purged": "Étiquette supprimée", + "tagLimitReached": "Limite d’étiquettes atteinte", + "iconPickerTitle": "Choisir une icône", + "iconSearchPlaceholder": "Rechercher des icônes…", + "iconSearchEmpty": "Aucune icône ne correspond.", + "iconSearchClear": "Effacer la recherche", + "orderSave": "Enregistrer l’ordre", + "orderSaved": "Ordre enregistré", + "moveUp": "Monter", + "moveDown": "Descendre", + "iconGroupEmotions": "Émotions", + "iconGroupActivities": "Activités", + "iconGroupHealth": "Santé", + "iconGroupFood": "Nourriture et boissons", + "iconGroupWeather": "Météo", + "iconGroupPlaces": "Lieux", + "iconGroupMisc": "Autres" + } }, "medications": { "title": "Médicaments", @@ -1749,6 +1800,7 @@ "tableComplianceDays": "{days} j", "tableStockDoseOne": "1 dose", "tableStockDoses": "{count} doses", + "tableStockRunway": "≈ {days} jours restants", "takeActionFor": "Prendre – {name}", "skipActionFor": "Passer – {name}", "reorderTitle": "Modifier l'ordre", @@ -3789,6 +3841,10 @@ "medications": { "title": "Médicaments", "description": "Vue de la liste et ordre des médicaments." + }, + "mood": { + "title": "Étiquettes d’humeur", + "description": "Groupes, étiquettes et ordre du sélecteur d’humeur." } }, "profile": "Profil", diff --git a/messages/it.json b/messages/it.json index fc94d2431..eb6685894 100644 --- a/messages/it.json +++ b/messages/it.json @@ -664,7 +664,58 @@ "bulkDeleteSuccess": "{count} voci eliminate", "bulkDeleteError": "Errore durante l'eliminazione delle voci selezionate", "bulkDeleteConfirmTitle": "Eliminare {count} voci?", - "bulkDeleteConfirmBody": "Le {count} voci dell'umore selezionate verranno eliminate definitivamente." + "bulkDeleteConfirmBody": "Le {count} voci dell'umore selezionate verranno eliminate definitivamente.", + "customize": "Personalizza i tag dell’umore", + "addTagInline": "Aggiungi tag", + "manage": { + "groupsTitle": "Gruppi", + "groupsDescription": "Crea i tuoi gruppi e definisci il loro ordine nel selettore.", + "newGroup": "Nuovo gruppo", + "groupLabel": "Nome del gruppo", + "groupIcon": "Icona", + "groupCreated": "Gruppo creato", + "groupRenamed": "Gruppo salvato", + "groupDeleteTitle": "Eliminare il gruppo?", + "groupDeleteBody": "I tag di questo gruppo tornano nel loro gruppo originale. Nessuna voce viene eliminata.", + "groupDeleted": "Gruppo eliminato", + "groupEmpty": "Ancora nessun gruppo personale.", + "groupLimitReached": "Limite di gruppi raggiunto", + "tagsTitle": "Tag", + "tagsDescription": "Nascondi, riordina, sposta o modifica i tag del selettore.", + "newTag": "Nuovo tag", + "tagLabel": "Nome del tag", + "tagIcon": "Icona", + "tagGroup": "Gruppo", + "usageCount": "{count} voci", + "hideTag": "Nascondi tag", + "showTag": "Mostra tag", + "moveToGroup": "Sposta nel gruppo", + "archive": "Archivia", + "restore": "Ripristina", + "archivedTitle": "Tag archiviati", + "archivedDescription": "I tag archiviati restano nelle tue voci passate — scompaiono solo dal selettore.", + "archivedEmpty": "Niente in archivio.", + "purgeTitle": "Eliminare il tag definitivamente?", + "purgeBody": "Il tag verrà rimosso da {count} voci passate. L’operazione non può essere annullata.", + "purgeAction": "Elimina definitivamente", + "purged": "Tag eliminato", + "tagLimitReached": "Limite di tag raggiunto", + "iconPickerTitle": "Scegli un’icona", + "iconSearchPlaceholder": "Cerca icone…", + "iconSearchEmpty": "Nessuna icona corrisponde.", + "iconSearchClear": "Cancella ricerca", + "orderSave": "Salva ordine", + "orderSaved": "Ordine salvato", + "moveUp": "Sposta su", + "moveDown": "Sposta giù", + "iconGroupEmotions": "Emozioni", + "iconGroupActivities": "Attività", + "iconGroupHealth": "Salute", + "iconGroupFood": "Cibo e bevande", + "iconGroupWeather": "Meteo", + "iconGroupPlaces": "Luoghi", + "iconGroupMisc": "Altro" + } }, "medications": { "title": "Farmaci", @@ -1749,6 +1800,7 @@ "tableComplianceDays": "{days} g", "tableStockDoseOne": "1 dose", "tableStockDoses": "{count} dosi", + "tableStockRunway": "≈ {days} giorni rimanenti", "takeActionFor": "Assumi – {name}", "skipActionFor": "Salta – {name}", "reorderTitle": "Modifica ordine", @@ -3789,6 +3841,10 @@ "medications": { "title": "Farmaci", "description": "Vista elenco e ordine dei farmaci." + }, + "mood": { + "title": "Tag dell’umore", + "description": "Gruppi, tag e ordine del selettore dell’umore." } }, "profile": "Profilo", diff --git a/messages/pl.json b/messages/pl.json index 9bba252ae..ec1670839 100644 --- a/messages/pl.json +++ b/messages/pl.json @@ -664,7 +664,58 @@ "bulkDeleteSuccess": "Usunięto wpisy: {count}", "bulkDeleteError": "Błąd podczas usuwania wybranych wpisów", "bulkDeleteConfirmTitle": "Usunąć wpisy ({count})?", - "bulkDeleteConfirmBody": "Wybrane wpisy nastroju ({count}) zostaną trwale usunięte." + "bulkDeleteConfirmBody": "Wybrane wpisy nastroju ({count}) zostaną trwale usunięte.", + "customize": "Dostosuj tagi nastroju", + "addTagInline": "Dodaj tag", + "manage": { + "groupsTitle": "Grupy", + "groupsDescription": "Twórz własne grupy i ustal ich kolejność w wyborze.", + "newGroup": "Nowa grupa", + "groupLabel": "Nazwa grupy", + "groupIcon": "Ikona", + "groupCreated": "Grupa utworzona", + "groupRenamed": "Grupa zapisana", + "groupDeleteTitle": "Usunąć grupę?", + "groupDeleteBody": "Tagi z tej grupy wracają do swojej pierwotnej grupy. Żadne wpisy nie zostaną usunięte.", + "groupDeleted": "Grupa usunięta", + "groupEmpty": "Brak własnych grup.", + "groupLimitReached": "Osiągnięto limit grup", + "tagsTitle": "Tagi", + "tagsDescription": "Ukrywaj, porządkuj, przenoś lub edytuj tagi widoczne w wyborze.", + "newTag": "Nowy tag", + "tagLabel": "Nazwa tagu", + "tagIcon": "Ikona", + "tagGroup": "Grupa", + "usageCount": "{count} wpisów", + "hideTag": "Ukryj tag", + "showTag": "Pokaż tag", + "moveToGroup": "Przenieś do grupy", + "archive": "Archiwizuj", + "restore": "Przywróć", + "archivedTitle": "Zarchiwizowane tagi", + "archivedDescription": "Zarchiwizowane tagi pozostają w Twoich wcześniejszych wpisach — znikają tylko z wyboru.", + "archivedEmpty": "Nic nie zarchiwizowano.", + "purgeTitle": "Usunąć tag na zawsze?", + "purgeBody": "Tag zostanie usunięty z {count} wcześniejszych wpisów. Tej operacji nie można cofnąć.", + "purgeAction": "Usuń na zawsze", + "purged": "Tag usunięty", + "tagLimitReached": "Osiągnięto limit tagów", + "iconPickerTitle": "Wybierz ikonę", + "iconSearchPlaceholder": "Szukaj ikon…", + "iconSearchEmpty": "Brak pasującej ikony.", + "iconSearchClear": "Wyczyść wyszukiwanie", + "orderSave": "Zapisz kolejność", + "orderSaved": "Kolejność zapisana", + "moveUp": "W górę", + "moveDown": "W dół", + "iconGroupEmotions": "Emocje", + "iconGroupActivities": "Aktywności", + "iconGroupHealth": "Zdrowie", + "iconGroupFood": "Jedzenie i napoje", + "iconGroupWeather": "Pogoda", + "iconGroupPlaces": "Miejsca", + "iconGroupMisc": "Inne" + } }, "medications": { "title": "Leki", @@ -1749,6 +1800,7 @@ "tableComplianceDays": "{days} dni", "tableStockDoseOne": "1 dawka", "tableStockDoses": "Dawki: {count}", + "tableStockRunway": "≈ {days} dni zapasu", "takeActionFor": "Przyjmij – {name}", "skipActionFor": "Pomiń – {name}", "reorderTitle": "Zmień kolejność", @@ -3789,6 +3841,10 @@ "medications": { "title": "Leki", "description": "Widok listy i kolejność leków." + }, + "mood": { + "title": "Tagi nastroju", + "description": "Grupy, tagi i kolejność w wyborze nastroju." } }, "profile": "Profil", diff --git a/src/components/medications/medication-table.tsx b/src/components/medications/medication-table.tsx index 8ba319e71..3ab884d79 100644 --- a/src/components/medications/medication-table.tsx +++ b/src/components/medications/medication-table.tsx @@ -26,6 +26,7 @@ import { Skeleton } from "@/components/ui/skeleton"; import { MedicationStatusPill } from "@/components/medications/card-parts/medication-status-pill"; import { useWeekdayLabel } from "@/components/medications/card-parts/medication-next-last-slot"; import { resolveDisplayedSlotInstant } from "@/components/medications/card-parts/displayed-slot-instant"; +import { estimateRunwayDays } from "@/components/medications/detail/supply-runway"; import { useMedicationIntake } from "@/components/medications/use-medication-intake"; import { reduceCurrentWindowStatus, @@ -70,6 +71,9 @@ interface TableSchedule { daysOfWeek: string | null; timesOfDay?: string[]; doseWindows?: { timeOfDay: string; start: string; end: string }[] | null; + /** Cadence fields the supply-runway estimate reads (v1.16.11). */ + rrule?: string | null; + rollingIntervalDays?: number | null; } export interface TableMedication { @@ -547,23 +551,40 @@ function MedicationTableRowItem({ ); const stock = medication.stockDosesRemaining; + // Projected days the stock covers — the same coarse estimate the + // detail Übersicht renders, so the column answers "do I need a + // refill" without opening the medication. + const runwayDays = + stock === null || stock === undefined + ? null + : estimateRunwayDays(stock, medication.schedules); const stockCell = stock === null || stock === undefined ? ( – ) : ( - + + {stock === 1 + ? t("medications.tableStockDoseOne") + : t("medications.tableStockDoses", { count: stock })} + + {runwayDays !== null && ( + + {t("medications.tableStockRunway", { days: runwayDays })} + )} - > - {stock === 1 - ? t("medications.tableStockDoseOne") - : t("medications.tableStockDoses", { count: stock })} );