From 4493eb2cacb2e631ba48092759beb00a8c7b8c2a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Marc-Andr=C3=A9=20Bombeck?=
Date: Fri, 12 Jun 2026 20:27:59 +0200
Subject: [PATCH] feat(medications,coach): the take-now prompt joins the
schedule grammar and the coach opens in place
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
An open take-window renders as the right-aligned value of the next-
intake row — same label/value columns as every other card line —
instead of a standalone line above the slot; the escalation tiers
(late, very late, taken-early) keep the top line. The coach launcher
opens the side drawer on the page you are on instead of navigating to
the chat page, and grows to the standard FAB size.
---
src/components/insights/layout-coach-fab.tsx | 12 ++++---
.../card-parts/medication-card-body.tsx | 33 +++++++++++++++++--
.../card-parts/medication-status-pill.tsx | 18 +++++++---
3 files changed, 51 insertions(+), 12 deletions(-)
diff --git a/src/components/insights/layout-coach-fab.tsx b/src/components/insights/layout-coach-fab.tsx
index bfade4a0d..ef0f73f83 100644
--- a/src/components/insights/layout-coach-fab.tsx
+++ b/src/components/insights/layout-coach-fab.tsx
@@ -1,7 +1,7 @@
"use client";
import { useEffect, useRef, useState } from "react";
-import { usePathname, useRouter } from "next/navigation";
+import { usePathname } from "next/navigation";
import { useQuery } from "@tanstack/react-query";
import { Sparkles } from "lucide-react";
@@ -58,7 +58,6 @@ export function isNudgeUnread(
export function LayoutCoachFab() {
const { t } = useTranslations();
- const router = useRouter();
const pathname = usePathname();
const launch = useCoachLaunch();
const flags = useFeatureFlags();
@@ -137,7 +136,10 @@ export function LayoutCoachFab() {
// Best effort — see above.
}
}
- router.push("/insights/coach");
+ // v1.16.11 — open the side drawer in place (the launch context the
+ // layout mount consumes) instead of navigating to the chat page;
+ // the conversation arrives without losing the page underneath.
+ launch?.askCoach();
};
return (
@@ -157,7 +159,7 @@ export function LayoutCoachFab() {
// not `lg:` — keeps the FAB from floating mid-air 768-1023px).
// The right inset mirrors the desktop bottom inset so the
// corner gap is even.
- "fixed right-6 z-40 size-12 rounded-full shadow-lg",
+ "fixed right-6 z-40 size-14 rounded-full shadow-lg",
"bottom-[calc(env(safe-area-inset-bottom,0px)+5rem)] md:bottom-6",
// Dark glyph on the purple/pink gradient — white sat at
// ≈2.3:1 against the gradient midpoint; the background token
@@ -185,7 +187,7 @@ export function LayoutCoachFab() {
"[body:has([data-testid=onboarding-tour])_&]:invisible",
)}
>
-
+
{unread ? (
{overdueLabel}
- ) : windowStatus ? (
+ ) : windowStatus && !takeNowOnNextLine ? (
- {/* Next / last intake — the two decisive lines, each shown once. */}
-
+ {/* Next / last intake — the two decisive lines, each shown once.
+ An open take-window renders as the next-intake value. */}
+
+ ) : (
+ nextLine
+ )
+ }
+ last={lastLine}
+ />
{/* Compliance bars — always two rows; constant-height skeleton holds
the slot while the query is in flight so the grid row stays even.
diff --git a/src/components/medications/card-parts/medication-status-pill.tsx b/src/components/medications/card-parts/medication-status-pill.tsx
index b937e315d..65bb96660 100644
--- a/src/components/medications/card-parts/medication-status-pill.tsx
+++ b/src/components/medications/card-parts/medication-status-pill.tsx
@@ -26,6 +26,14 @@ interface MedicationStatusPillProps {
* with the card pill — only the suffix is dropped.
*/
compact?: boolean;
+ /**
+ * v1.16.11 — inline variant: renders a `` root instead of the
+ * block `` so the pill can sit as the right-aligned VALUE of the
+ * "next intake" row (the take-now prompt lives on that row now, not
+ * on its own line above the slot). A `
` inside the row's ``
+ * would be invalid nesting.
+ */
+ inline?: boolean;
}
/**
@@ -42,12 +50,14 @@ export function MedicationStatusPill({
windowEnd,
takenEarlyDaysAgo = null,
compact = false,
+ inline = false,
}: MedicationStatusPillProps) {
const { t, locale } = useTranslations();
+ const Root = inline ? "span" : "p";
if (takenEarlyDaysAgo != null) {
return (
-
+
{takenEarlyDaysAgo === 1
@@ -60,12 +70,12 @@ export function MedicationStatusPill({
— {formatTimeWindowRange(windowStart, windowEnd, locale)}
)}
-
+
);
}
return (
-
+
)}
-
+
);
}