mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2026-02-04 09:56:47 +00:00
feat: add TranscriptChatModal and TranscriptChatButton components
This commit is contained in:
@@ -1,14 +1,23 @@
|
|||||||
{
|
{
|
||||||
"assignee": null,
|
"assignee": "igor.loskutoff@gmail.com",
|
||||||
"claim_note": "",
|
"claim_note": "",
|
||||||
"claimed_at": null,
|
"claimed_at": "2026-01-13T00:52:01.366013Z",
|
||||||
"created_at": "2026-01-12T22:41:17.835044Z",
|
"created_at": "2026-01-12T22:41:17.835044Z",
|
||||||
"depends_on": [],
|
"depends_on": [],
|
||||||
"epic": "fn-1",
|
"epic": "fn-1",
|
||||||
|
"evidence": {
|
||||||
|
"commits": [
|
||||||
|
"d5a77087594b3b54150e78466132f2dfa001901b"
|
||||||
|
],
|
||||||
|
"prs": [],
|
||||||
|
"tests": [
|
||||||
|
"pnpm tsc --noEmit"
|
||||||
|
]
|
||||||
|
},
|
||||||
"id": "fn-1.6",
|
"id": "fn-1.6",
|
||||||
"priority": null,
|
"priority": null,
|
||||||
"spec_path": ".flow/tasks/fn-1.6.md",
|
"spec_path": ".flow/tasks/fn-1.6.md",
|
||||||
"status": "todo",
|
"status": "done",
|
||||||
"title": "Chat dialog component",
|
"title": "Chat dialog component",
|
||||||
"updated_at": "2026-01-12T22:41:17.835218Z"
|
"updated_at": "2026-01-13T00:58:52.502248Z"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,9 +7,11 @@ TBD
|
|||||||
- [ ] TBD
|
- [ ] TBD
|
||||||
|
|
||||||
## Done summary
|
## Done summary
|
||||||
TBD
|
- Created TranscriptChatModal component with Dialog UI
|
||||||
|
- Added TranscriptChatButton floating action button
|
||||||
|
- Implemented message display with streaming indicator
|
||||||
|
- Added input field with Enter key support
|
||||||
## Evidence
|
## Evidence
|
||||||
- Commits:
|
- Commits: d5a77087594b3b54150e78466132f2dfa001901b
|
||||||
- Tests:
|
- Tests: pnpm tsc --noEmit
|
||||||
- PRs:
|
- PRs:
|
||||||
93
www/app/(app)/transcripts/TranscriptChatModal.tsx
Normal file
93
www/app/(app)/transcripts/TranscriptChatModal.tsx
Normal file
@@ -0,0 +1,93 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { useState } from "react";
|
||||||
|
import { Box, Dialog, Input, IconButton } from "@chakra-ui/react";
|
||||||
|
import { MessageCircle } from "lucide-react";
|
||||||
|
import type { Message } from "./useTranscriptChat";
|
||||||
|
|
||||||
|
interface TranscriptChatModalProps {
|
||||||
|
open: boolean;
|
||||||
|
onClose: () => void;
|
||||||
|
messages: Message[];
|
||||||
|
sendMessage: (text: string) => void;
|
||||||
|
isStreaming: boolean;
|
||||||
|
currentStreamingText: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TranscriptChatModal({
|
||||||
|
open,
|
||||||
|
onClose,
|
||||||
|
messages,
|
||||||
|
sendMessage,
|
||||||
|
isStreaming,
|
||||||
|
currentStreamingText,
|
||||||
|
}: TranscriptChatModalProps) {
|
||||||
|
const [input, setInput] = useState("");
|
||||||
|
|
||||||
|
const handleSend = () => {
|
||||||
|
if (!input.trim()) return;
|
||||||
|
sendMessage(input);
|
||||||
|
setInput("");
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Dialog.Root open={open} onOpenChange={(e) => !e.open && onClose()}>
|
||||||
|
<Dialog.Backdrop />
|
||||||
|
<Dialog.Positioner>
|
||||||
|
<Dialog.Content maxW="500px" h="600px">
|
||||||
|
<Dialog.Header>Transcript Chat</Dialog.Header>
|
||||||
|
|
||||||
|
<Dialog.Body overflowY="auto">
|
||||||
|
{messages.map((msg) => (
|
||||||
|
<Box
|
||||||
|
key={msg.id}
|
||||||
|
p={3}
|
||||||
|
mb={2}
|
||||||
|
bg={msg.role === "user" ? "blue.50" : "gray.50"}
|
||||||
|
borderRadius="md"
|
||||||
|
>
|
||||||
|
{msg.text}
|
||||||
|
</Box>
|
||||||
|
))}
|
||||||
|
|
||||||
|
{isStreaming && (
|
||||||
|
<Box p={3} bg="gray.50" borderRadius="md">
|
||||||
|
{currentStreamingText}
|
||||||
|
<Box as="span" className="animate-pulse">
|
||||||
|
▊
|
||||||
|
</Box>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
</Dialog.Body>
|
||||||
|
|
||||||
|
<Dialog.Footer>
|
||||||
|
<Input
|
||||||
|
value={input}
|
||||||
|
onChange={(e) => setInput(e.target.value)}
|
||||||
|
onKeyDown={(e) => e.key === "Enter" && handleSend()}
|
||||||
|
placeholder="Ask about transcript..."
|
||||||
|
disabled={isStreaming}
|
||||||
|
/>
|
||||||
|
</Dialog.Footer>
|
||||||
|
</Dialog.Content>
|
||||||
|
</Dialog.Positioner>
|
||||||
|
</Dialog.Root>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function TranscriptChatButton({ onClick }: { onClick: () => void }) {
|
||||||
|
return (
|
||||||
|
<IconButton
|
||||||
|
position="fixed"
|
||||||
|
bottom="24px"
|
||||||
|
right="24px"
|
||||||
|
onClick={onClick}
|
||||||
|
size="lg"
|
||||||
|
colorPalette="blue"
|
||||||
|
borderRadius="full"
|
||||||
|
aria-label="Open chat"
|
||||||
|
>
|
||||||
|
<MessageCircle />
|
||||||
|
</IconButton>
|
||||||
|
);
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user