diff --git a/src/app/labs/page.tsx b/src/app/labs/page.tsx index 1899669fd..69ca8f41e 100644 --- a/src/app/labs/page.tsx +++ b/src/app/labs/page.tsx @@ -192,7 +192,10 @@ export default function LabsPage() { title={t("labs.addResult")} description={t("labs.addDescription")} footer={ -
+
} > {pendingAction === "saveAndAddAnother" ? ( diff --git a/src/components/labs/lab-history-list.tsx b/src/components/labs/lab-history-list.tsx index 55b397519..3dce4fa67 100644 --- a/src/components/labs/lab-history-list.tsx +++ b/src/components/labs/lab-history-list.tsx @@ -311,103 +311,148 @@ export function LabHistoryList({ readings }: { readings: LabResultDto[] }) { }); }, [readings, sortBy, sortDir]); + // One action pair per reading, shared by the phone list and the table. + const renderActions = (r: LabResultDto) => ( +
+ {canManageLabs && ( + + )} + deleteMutation.mutate(r.id)} + title={t("labs.deleteConfirmTitle")} + description={t("labs.deleteConfirmDescription")} + confirmLabel={t("labs.deleteReading")} + className="size-11 sm:size-9" + iconClassName="h-4 w-4" + /> +
+ ); + return ( <> - - - - - - - - - {t("labs.editReading")} - - - - - {ordered.map((r) => ( - - -
- {formatLabReading(r)} - -
-
- - {formatDateShort(r.takenAt, true)} - - -
- - -
-
- - {r.hasNote ? t("labs.hasNote") : ""} - - -
- {canManageLabs && ( - - )} - deleteMutation.mutate(r.id)} - title={t("labs.deleteConfirmTitle")} - description={t("labs.deleteConfirmDescription")} - confirmLabel={t("labs.deleteReading")} - className="size-11 sm:size-9" - iconClassName="h-4 w-4" - /> -
-
+ {/* Phones get one stacked row per reading. The table needs ~510 px for + its five columns, so on a phone it panned sideways inside its + container and parked the edit / delete buttons off-screen, while the + range bar's end labels were clipped by the same container. */} +
    + {ordered.map((r) => ( +
  • +
    +
    + {formatLabReading(r)} +
    + +
    + + {formatDateShort(r.takenAt, true)} + + + {r.hasNote ? ( + {t("labs.hasNote")} + ) : null} +
    + +
    + {renderActions(r)} +
  • + ))} +
+
+
+ + + + + + + + {t("labs.editReading")} + - ))} - -
+ + + {ordered.map((r) => ( + + +
+ {formatLabReading(r)} + +
+
+ + {formatDateShort(r.takenAt, true)} + + +
+ + +
+
+ + {r.hasNote ? t("labs.hasNote") : ""} + + + {renderActions(r)} + +
+ ))} +
+ +
+
void } = {}) { const { t } = useTranslations(); const { canWriteDomain } = useRecordCapabilities(); @@ -212,12 +241,15 @@ export function LabList({ onAddFirst }: { onAddFirst?: () => void } = {}) {

) : null} - + {groups.map((group) => { const inner = ( -
+
- + {group.analyte}
@@ -234,47 +266,57 @@ export function LabList({ onAddFirst }: { onAddFirst?: () => void } = {}) { {inner} -
+
reading.value)} referenceLow={group.latest.referenceLow} referenceHigh={group.latest.referenceHigh} />
- + ) : ( // Un-linked group (not backfilled to a catalog biomarker): // render inert but say so, so it doesn't read as a broken // link next to its clickable neighbours. -
+
{inner} -
+
reading.value)} referenceLow={group.latest.referenceLow} referenceHigh={group.latest.referenceHigh} />
- + {t("labs.notLinkedYet")}
diff --git a/src/components/labs/ocr-row-editor.tsx b/src/components/labs/ocr-row-editor.tsx index ea1a06281..e63388a55 100644 --- a/src/components/labs/ocr-row-editor.tsx +++ b/src/components/labs/ocr-row-editor.tsx @@ -129,9 +129,17 @@ export function OcrRowEditor({ {fieldError("analyte", "labs.ocr.errorAnalyte")}
{row.biomarkerMatch === "existing" ? ( - + // The chip repeats the analyte, so a long panel name ran past + // the row on a phone; it truncates inside the row instead. + - {t("labs.ocr.linksExisting", { name: row.analyte })} + + {t("labs.ocr.linksExisting", { name: row.analyte })} + ) : (