mirror of
https://github.com/MBombeck/HealthLog.git
synced 2026-11-14 22:50:51 +00:00
fix(coach): default to new chat and never dead-end on conversations
Reverse the resume-most-recent entry default: opening the Coach now lands on the new-chat hero. The only exception is an unread coach-initiated message (nudge-status `unread`), which auto-opens the most-recent thread so the user sees what the Coach wrote. The `?c=<id>` deep-link is unchanged. Add a dedicated, always-visible Conversations button (plus a New chat button) to the page surface so reaching past conversations no longer hides in the composer menu. The drawer's Conversations handoff now routes to `/coach?view=conversations`, which opens the history drawer on arrival, so the side-view to full-view path always shows the list instead of a blank pane.
This commit is contained in:
1 parent
a86abd3662
commit
c6f4772606
4 files changed
+120
-18
No files matched your search
@@ -135,4 +135,25 @@ describe("<CoachConversation> page deep-link (#67)", () => {
|
||||
// though recent conversations exist in the cache.
|
||||
expect(html).toContain('data-slot="coach-hero"');
|
||||
});
|
||||
|
||||
// v1.19.1 (C2) — a dedicated, always-visible Conversations button on the
|
||||
// page surface (not buried in the composer `+` menu).
|
||||
it("renders the dedicated Conversations button on the page surface", () => {
|
||||
const html = render(<CoachConversation surface="page" />, makeClient());
|
||||
expect(html).toContain('data-slot="coach-page-conversations"');
|
||||
expect(html).toContain('data-slot="coach-page-new-chat"');
|
||||
});
|
||||
|
||||
// v1.19.1 (C5) — entering via the drawer handoff (`?view=conversations`)
|
||||
// keeps the new-chat hero (no thread auto-resumed) while opening the
|
||||
// history drawer; the toolbar + button stay present so the pane is never
|
||||
// a blank dead-end.
|
||||
it("keeps the hero and toolbar when opened with openHistoryOnMount", () => {
|
||||
const html = render(
|
||||
<CoachConversation surface="page" openHistoryOnMount />,
|
||||
makeClient(),
|
||||
);
|
||||
expect(html).toContain('data-slot="coach-hero"');
|
||||
expect(html).toContain('data-slot="coach-page-conversations"');
|
||||
});
|
||||
});
|
||||
@@ -3,7 +3,7 @@
|
||||
import { useEffect, useReducer, useState } from "react";
|
||||
import Link from "next/link";
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query";
|
||||
import { Plus, Settings, Sparkles } from "lucide-react";
|
||||
import { MessagesSquare, Plus, Settings, Sparkles } from "lucide-react";
|
||||
import { toast } from "sonner";
|
||||
|
||||
import { Button } from "@/components/ui/button";
|
||||
@@ -137,6 +137,13 @@ export interface CoachConversationProps {
|
||||
* "new chat" or thread switch is never overridden.
|
||||
*/
|
||||
autoOpenMostRecent?: boolean;
|
||||
/**
|
||||
* v1.19.1 (C5) — page surface only: open the conversation-history drawer
|
||||
* once on mount. The drawer's "Conversations" handoff routes to
|
||||
* `/coach?view=conversations`, which sets this so the user always sees the
|
||||
* conversation list on arrival instead of a blank new-chat pane.
|
||||
*/
|
||||
openHistoryOnMount?: boolean;
|
||||
}
|
||||
|
||||
export function CoachConversation({
|
||||
@@ -152,6 +159,7 @@ export function CoachConversation({
|
||||
surface,
|
||||
initialConversationId,
|
||||
autoOpenMostRecent = false,
|
||||
openHistoryOnMount = false,
|
||||
}: CoachConversationProps) {
|
||||
const { t } = useTranslations();
|
||||
|
||||
@@ -165,7 +173,12 @@ export function CoachConversation({
|
||||
// the composer's `+` actions menu. Replaces the old inline collapsible
|
||||
// rail + top rail-tray strip; the top header bar is gone entirely on the
|
||||
// page so the composer is the single control hub.
|
||||
const [historyDrawerOpen, setHistoryDrawerOpen] = useState(false);
|
||||
// v1.19.1 (C5) — seed the history drawer open when the page is entered via
|
||||
// the drawer's "Conversations" handoff (`?view=conversations`), so the
|
||||
// list is on screen immediately rather than a blank hero.
|
||||
const [historyDrawerOpen, setHistoryDrawerOpen] = useState(
|
||||
() => openHistoryOnMount,
|
||||
);
|
||||
const [inputValue, setInputValue] = useResettableValue(prefill ?? "");
|
||||
// v1.16.4 — self-context backflow: `pendingAdopt` raises a quiet
|
||||
// offer to fold a clarifying-question answer back into the
|
||||
@@ -484,6 +497,37 @@ export function CoachConversation({
|
||||
data-variant={surface}
|
||||
className={cn("flex min-h-0 flex-1 flex-col", className)}
|
||||
>
|
||||
{/* v1.19.1 (C2) — a clear, always-visible "Conversations" button on
|
||||
the page surface. The composer's `+` menu still carries the same
|
||||
action, but the maintainer wanted an obvious, dedicated affordance
|
||||
to reach past conversations rather than one buried in a menu. */}
|
||||
<div
|
||||
data-slot="coach-page-toolbar"
|
||||
className="flex shrink-0 items-center justify-between gap-2 px-4 pt-2 sm:px-6"
|
||||
>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={() => setHistoryDrawerOpen(true)}
|
||||
data-slot="coach-page-conversations"
|
||||
className="text-muted-foreground hover:text-foreground -ml-1 gap-1.5"
|
||||
>
|
||||
<MessagesSquare className="size-4" aria-hidden="true" />
|
||||
{t("insights.coach.historyTitle")}
|
||||
</Button>
|
||||
<Button
|
||||
type="button"
|
||||
variant="ghost"
|
||||
size="sm"
|
||||
onClick={handleNewChat}
|
||||
data-slot="coach-page-new-chat"
|
||||
className="text-muted-foreground hover:text-foreground -mr-1 gap-1.5"
|
||||
>
|
||||
<Plus className="size-4" aria-hidden="true" />
|
||||
{t("insights.coach.newChat")}
|
||||
</Button>
|
||||
</div>
|
||||
{heroActive ? (
|
||||
<CoachHero composer={composerNode} />
|
||||
) : (
|
||||
|
||||
@@ -88,6 +88,17 @@ export function CoachDrawer({ open, onOpenChange, prefill }: CoachDrawerProps) {
|
||||
router.push("/coach");
|
||||
}, [onOpenChange, router]);
|
||||
|
||||
// v1.19.1 (C5) — the drawer's "Conversations" affordance hands off to the
|
||||
// full page WITH the `?view=conversations` flag so the page opens the
|
||||
// conversation-history drawer on arrival. Previously it shared
|
||||
// `handleMaximize` and, after the v1.19.1 new-chat default (C1), landed on
|
||||
// a blank hero with no list — the dead-end the maintainer reported.
|
||||
const handleOpenConversations = useCallback(() => {
|
||||
onOpenChange(false);
|
||||
resetRef.current?.();
|
||||
router.push("/coach?view=conversations");
|
||||
}, [onOpenChange, router]);
|
||||
|
||||
return (
|
||||
<Sheet open={open} onOpenChange={handleOpenChange}>
|
||||
<SheetContent
|
||||
@@ -118,9 +129,10 @@ export function CoachDrawer({ open, onOpenChange, prefill }: CoachDrawerProps) {
|
||||
autoFocusComposer
|
||||
registerReset={registerReset}
|
||||
// v1.16.1 — the "Conversations" affordance hands off to the
|
||||
// full-page route (same path as maximize) instead of opening
|
||||
// the broken in-panel left tray.
|
||||
onRequestFullView={handleMaximize}
|
||||
// full-page route instead of opening the broken in-panel left
|
||||
// tray. v1.19.1 (C5) — it now carries `?view=conversations` so the
|
||||
// page opens the history list on arrival, never a blank hero.
|
||||
onRequestFullView={handleOpenConversations}
|
||||
// Radix requires an accessible name + description on the
|
||||
// dialog content. Mount them through the title/description
|
||||
// render-props so the page can swap in a plain heading.
|
||||
|
||||
Reference in new issue
Block a user