import { Brain, ChevronRight, Loader2, Plus, Send, Sparkles, Square, Trash2 } from "lucide-react"; import type { FormEvent } from "react"; import { getBstHour } from "../lib/greeting"; import type { CoachSession } from "../lib/useCoachSession"; import { OLLAMA_MODEL } from "../lib/useCoachSession"; import type { CoachMessage } from "../types"; type CoachPanelProps = { session: CoachSession; mode: "compact" | "full"; dashboard: { todayCans: string; todayCaffeine: string; favouriteFlavour: string; }; userInitials: string; onExpand?: () => void; }; const QUICK_PROMPTS = [ "what's my favourite flavour historically?", "how should i pace caffeine for the rest of the day?", "suggest a lower-sugar swap", ]; export function CoachPanel({ session, mode, dashboard, userInitials, onExpand }: CoachPanelProps) { const { busy, chats, error, input, activeChatId, removeChat, sendPrompt, setActiveChatId, setInput, startNewChat, stopThinking, storageReady, storageStatus, visibleMessages, } = session; const displayMessages = mode === "compact" ? visibleMessages.slice(-4) : visibleMessages; const compact = mode === "compact"; async function submit(event: FormEvent) { event.preventDefault(); await sendPrompt(input); } if (!storageReady) { return (
); } return (

coach

{dashboard.todayCans} cans today · {dashboard.favouriteFlavour}

{busy ? "thinking" : storageStatus} {!compact && {OLLAMA_MODEL}} {compact && onExpand && ( )}
{!compact && chats.length > 1 && (
{chats.map((chat) => (
))}
)}
{dashboard.todayCaffeine} caffeine bst {getBstHour()}:00
{!displayMessages.length ? (
) : ( displayMessages.map((message) => ( )) )}
{error &&

{error}

}
{!compact && ( )} setInput(event.target.value)} placeholder="ask coach anything..." disabled={busy} /> {busy ? ( ) : ( )}
); } function CoachLine({ message, userInitials }: { message: CoachMessage; userInitials: string }) { const isAssistant = message.role === "assistant"; const isThinking = isAssistant && message.pending && !message.content.trim(); return (
{isAssistant ? : userInitials}
{isThinking && } {message.content ?

{message.content}

: !isThinking ? ... : null} {isAssistant && !message.pending && message.thinking?.trim() ? (
reasoning
{message.thinking}
) : null}
); } function ThinkingPill({ stopped }: { stopped?: boolean }) { return (
); }