mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-12 14:16:12 +00:00
feat(documents): open the doc-scoped Coach in the side drawer, not a full page
"Ask the Coach" on a document used to navigate to /coach?doc=<id> — a full-page jump away from the vault. It now opens the real, doc-scoped conversation in the shared side drawer, and the drawer's maximize control expands it to the full /coach page while preserving scope. - Thread an optional documentId through the launch context: askCoach gains a fourth argument, the provider tracks it alongside prefill/scope and clears it on close, and LayoutCoachMount forwards it to the drawer as initialDocumentId. The open-state precedence moves into a pure resolveLaunchState helper. - The vault detail sheet closes itself and calls askCoach(..., doc.id) instead of routing away, so the drawer owns the surface. - Maximize preserves continuity: the drawer reads the live conversation id via a new imperative getter out of the conversation surface (parallel to the reset registration) and hands off to /coach?c=<id> once a thread exists, falling back to /coach?doc=<id> for a chat maximized before its first turn. The send path is untouched: every document turn still routes through the hardened fenced endpoint keyed on documentId — only where the conversation renders (drawer vs page) changed. The documents-chat e2e now asserts the drawer opens in place, doc-scoped, rather than a URL change.
This commit is contained in:
1 parent
7c96abc8ec
commit
d72f078764
9 files changed
+390
-51
No files matched your search
@@ -0,0 +1,66 @@
|
||||
import { describe, expect, it } from "vitest";
|
||||
import { readFileSync } from "node:fs";
|
||||
import { join } from "node:path";
|
||||
|
||||
/**
|
||||
* v1.28.52 (Documents R3) — "Ask the Coach" opens the REAL fenced coach
|
||||
* conversation in the shared SIDE DRAWER, scoped to the document, instead of a
|
||||
* full-page nav to `/coach?doc=<id>` (the v1.28.51 behaviour Marc corrected).
|
||||
*
|
||||
* The wiring is source-structural (the send-path fence itself is covered by the
|
||||
* coach-send-target unit tests — untouched here). These guards pin:
|
||||
* 1. the detail sheet drives the drawer via `askCoach(..., doc.id)`, closing
|
||||
* the sheet first, and no longer navigates to `/coach?doc=`;
|
||||
* 2. the launch context → mount → drawer → conversation `documentId` thread
|
||||
* stays connected end-to-end.
|
||||
*/
|
||||
const ROOT = join(__dirname, "../../../..");
|
||||
const DETAIL_SHEET = join(
|
||||
ROOT,
|
||||
"src/components/documents/document-detail-sheet.tsx",
|
||||
);
|
||||
const MOUNT = join(ROOT, "src/components/insights/layout-coach-mount.tsx");
|
||||
const DRAWER = join(
|
||||
ROOT,
|
||||
"src/components/insights/coach-panel/coach-drawer.tsx",
|
||||
);
|
||||
|
||||
function load(path: string): string {
|
||||
return readFileSync(path, "utf8");
|
||||
}
|
||||
|
||||
describe("document detail sheet — Ask the Coach opens the drawer", () => {
|
||||
const src = load(DETAIL_SHEET);
|
||||
|
||||
it("launches the doc-scoped coach drawer via askCoach(..., doc.id)", () => {
|
||||
expect(src).toContain("useCoachLaunch");
|
||||
expect(src).toMatch(/askCoach\(null,\s*undefined,\s*false,\s*doc\.id\)/);
|
||||
});
|
||||
|
||||
it("closes the detail sheet when handing off to the drawer", () => {
|
||||
// The Ask-the-Coach onClick closes the sheet before opening the drawer so
|
||||
// the drawer owns the surface (no stacked dialogs).
|
||||
expect(src).toMatch(
|
||||
/onClick=\{\(\)\s*=>\s*\{[\s\S]*?onOpenChange\(false\);[\s\S]*?askCoach\(null,\s*undefined,\s*false,\s*doc\.id\)/,
|
||||
);
|
||||
});
|
||||
|
||||
it("no longer navigates to the full-page /coach?doc= route", () => {
|
||||
expect(src).not.toContain("/coach?doc=");
|
||||
expect(src).not.toContain('from "next/navigation"');
|
||||
});
|
||||
});
|
||||
|
||||
describe("documentId threads launch context → mount → drawer", () => {
|
||||
it("the mount forwards launch.documentId to the drawer", () => {
|
||||
expect(load(MOUNT)).toContain("documentId={launch.documentId}");
|
||||
});
|
||||
|
||||
it("the drawer seeds CoachConversation with initialDocumentId + a conversation-id getter", () => {
|
||||
const src = load(DRAWER);
|
||||
expect(src).toContain("initialDocumentId={documentId}");
|
||||
expect(src).toContain(
|
||||
"registerConversationIdGetter={registerConversationIdGetter}",
|
||||
);
|
||||
});
|
||||
});
|
||||
Reference in new issue
Block a user