forked from Gerome-Elassaad/CodingIT
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchat.tsx
More file actions
94 lines (90 loc) · 3.37 KB
/
Copy pathchat.tsx
File metadata and controls
94 lines (90 loc) · 3.37 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { Message } from '@/lib/messages'
import { FragmentSchema } from '@/lib/schema'
import { ExecutionResult } from '@/lib/types'
import { DeepPartial } from 'ai'
import { LoaderIcon, Terminal, Sparkles } from 'lucide-react'
import { useEffect } from 'react'
export function Chat({
messages,
isLoading,
setCurrentPreview,
}: {
messages: Message[]
isLoading: boolean
setCurrentPreview: (preview: {
fragment: DeepPartial<FragmentSchema> | undefined
result: ExecutionResult | undefined
}) => void
}) {
useEffect(() => {
const chatContainer = document.getElementById('chat-container')
if (chatContainer) {
chatContainer.scrollTop = chatContainer.scrollHeight
}
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [JSON.stringify(messages)])
return (
<div
id="chat-container"
className="flex flex-col pb-12 gap-2 overflow-y-auto max-h-full"
>
{messages.length === 0 && !isLoading && (
<div className="flex items-center justify-center h-full text-muted-foreground text-lg font-serif">
Start a new conversation
</div>
)}
{messages.map((message: Message, index: number) => (
<div
className={`flex flex-col px-4 shadow-sm whitespace-pre-wrap ${message.role !== 'user' ? 'bg-accent dark:bg-white/5 border text-accent-foreground dark:text-muted-foreground py-4 rounded-2xl gap-4 w-full' : 'bg-gradient-to-b from-black/5 to-black/10 dark:from-black/30 dark:to-black/50 py-2 rounded-xl gap-2 w-fit'} font-serif text-primary`}
key={index}
>
{message.content.map((content, id) => {
if (content.type === 'text') {
return content.text
}
if (content.type === 'image') {
return (
// eslint-disable-next-line @next/next/no-img-element
<img
key={id}
src={content.image}
alt="fragment"
className="mr-2 inline-block w-12 h-12 object-cover rounded-lg bg-white mb-2"
/>
)
}
})}
{message.object && (
<div
onClick={() =>
setCurrentPreview({
fragment: message.object,
result: message.result,
})
}
className="py-2 pl-2 w-full md:w-max flex items-center border rounded-xl select-none hover:bg-black/5 dark:hover:bg-white/5 hover:cursor-pointer"
>
<div className="rounded-[0.5rem] w-10 h-10 bg-black/5 dark:bg-white/5 self-stretch flex items-center justify-center">
<Terminal strokeWidth={2} className="text-[#FF8800]" />
</div>
<div className="pl-2 pr-4 flex flex-col">
<span className="font-bold font-sans text-sm text-primary">
{message.object.title}
</span>
<span className="font-sans text-sm text-muted-foreground">
Click to see fragment
</span>
</div>
</div>
)}
</div>
))}
{isLoading && (
<div className="flex items-center gap-1 text-sm text-muted-foreground">
<LoaderIcon strokeWidth={2} className="animate-spin w-4 h-4" />
<span>Generating...</span>
</div>
)}
</div>
)
}