Add AI Elements-inspired chat primitives
This commit is contained in:
@@ -1,14 +1,17 @@
|
||||
import { type FormEvent, useEffect, useMemo, useRef, useState } from "react";
|
||||
import { useAction, useMutation, usePaginatedQuery, useQuery } from "convex/react";
|
||||
import { MessageCircle, Send, Loader2 } from "lucide-react";
|
||||
import { MessageCircle } from "lucide-react";
|
||||
import { api } from "../../convex/_generated/api";
|
||||
import type { Id } from "../../convex/_generated/dataModel";
|
||||
import { useAccountFilterId } from "@/components/layout/AccountFilter";
|
||||
import { useFilters } from "@/context/FilterContext";
|
||||
import { Button } from "@/components/ui/button";
|
||||
import { Input } from "@/components/ui/input";
|
||||
import { Card, CardContent, CardHeader, CardTitle } from "@/components/ui/card";
|
||||
import { Separator } from "@/components/ui/separator";
|
||||
import {
|
||||
AgentConversation,
|
||||
AgentPromptInput,
|
||||
type AgentChatMessage,
|
||||
} from "@/components/chat/AgentChat";
|
||||
import { ChatHistory, type ChatHistoryItem } from "@/components/chat/ChatHistory";
|
||||
import { toast } from "sonner";
|
||||
|
||||
@@ -163,6 +166,18 @@ export function SavingsChatPage() {
|
||||
[messagesQuery.results],
|
||||
);
|
||||
const displayMessages = activeSessionId && messages.length > 0 ? messages : fallbackMessages;
|
||||
const agentMessages: AgentChatMessage[] = useMemo(
|
||||
() =>
|
||||
displayMessages.map((message) => ({
|
||||
id: message._id,
|
||||
role: message.role,
|
||||
content: message.content,
|
||||
...(message.role === "assistant" && message.toolTrace
|
||||
? { toolTrace: message.toolTrace }
|
||||
: {}),
|
||||
})),
|
||||
[displayMessages],
|
||||
);
|
||||
|
||||
const context = useQuery(api.savingsChat.getContext, {
|
||||
from,
|
||||
@@ -186,8 +201,6 @@ export function SavingsChatPage() {
|
||||
? legacyImportResult.importedCount
|
||||
: 0;
|
||||
|
||||
const buttonDisabled = isSubmitting || draft.trim().length === 0 || !activeSessionId;
|
||||
|
||||
const formatAmount = (amount: number) =>
|
||||
new Intl.NumberFormat("de-DE", {
|
||||
style: "currency",
|
||||
@@ -353,60 +366,20 @@ export function SavingsChatPage() {
|
||||
</CardContent>
|
||||
</Card>
|
||||
|
||||
<Card>
|
||||
<CardContent className="p-4">
|
||||
<div className="h-[52vh] overflow-y-auto" ref={listRef}>
|
||||
<div className="space-y-3">
|
||||
{displayMessages.map((message) => (
|
||||
<div
|
||||
key={message._id}
|
||||
className={`rounded-lg border p-3 ${
|
||||
message.role === "user" ? "bg-muted/50" : "bg-background"
|
||||
}`}
|
||||
>
|
||||
<p className="text-xs uppercase text-muted-foreground">{message.role}</p>
|
||||
<p className="whitespace-pre-wrap text-sm">{message.content}</p>
|
||||
{message.role === "assistant" && message.toolTrace && message.toolTrace.length > 0 && (
|
||||
<div className="mt-3 rounded-md border bg-muted/30 p-2">
|
||||
<p className="text-xs font-medium text-muted-foreground">
|
||||
Verwendete Werkzeuge
|
||||
</p>
|
||||
<div className="mt-2 space-y-2">
|
||||
{message.toolTrace.map((tool, toolIndex) => (
|
||||
<div key={`${tool.name}-${toolIndex}`} className="text-xs">
|
||||
<p className="font-medium">{tool.name}</p>
|
||||
<p className="text-muted-foreground">{tool.resultSummary}</p>
|
||||
</div>
|
||||
))}
|
||||
</div>
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
))}
|
||||
{isSubmitting && (
|
||||
<div className="flex items-center gap-2 text-sm text-muted-foreground">
|
||||
<Loader2 className="h-4 w-4 animate-spin" />
|
||||
Denk mit der KI nach…
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</CardContent>
|
||||
</Card>
|
||||
<AgentConversation
|
||||
messages={agentMessages}
|
||||
isSubmitting={isSubmitting}
|
||||
scrollRef={listRef}
|
||||
/>
|
||||
|
||||
<form className="flex gap-2" onSubmit={submit}>
|
||||
<Input
|
||||
value={draft}
|
||||
onChange={(event) => setDraft(event.target.value)}
|
||||
placeholder={activeSession ? "Welche Auswertung soll ich machen?" : "Chat wird vorbereitet…"}
|
||||
disabled={isSubmitting || !activeSessionId}
|
||||
autoFocus
|
||||
/>
|
||||
<Button type="submit" disabled={buttonDisabled}>
|
||||
<Send className="h-4 w-4" />
|
||||
Senden
|
||||
</Button>
|
||||
</form>
|
||||
<AgentPromptInput
|
||||
value={draft}
|
||||
onChange={setDraft}
|
||||
onSubmit={submit}
|
||||
placeholder={activeSession ? "Welche Auswertung soll ich machen?" : "Chat wird vorbereitet..."}
|
||||
disabled={isSubmitting || !activeSessionId}
|
||||
isSubmitting={isSubmitting}
|
||||
/>
|
||||
|
||||
<Separator />
|
||||
<p className="text-xs text-muted-foreground">
|
||||
|
||||
Reference in New Issue
Block a user