'use client' import { useRef, useState, useEffect } from 'react' import { useChat } from '@ai-sdk/react' import { DefaultChatTransport, type UIMessage } from 'ai' import { Button } from '~/components/ui/button' import { Textarea } from '~/components/ui/textarea' import { cn } from '~/lib/utils' type DBMessage = { id: string role: 'user' | 'assistant' content: string } interface ChatInterfaceProps { sessionId: string initialMessages: DBMessage[] } function toUIMessages(dbMessages: DBMessage[]): UIMessage[] { return dbMessages.map((m) => ({ id: m.id, role: m.role, parts: [{ type: 'text' as const, text: m.content }], })) } export default function ChatInterface({ sessionId, initialMessages }: ChatInterfaceProps) { const [input, setInput] = useState('') const messagesEndRef = useRef(null) const { messages, sendMessage, status } = useChat({ transport: new DefaultChatTransport({ api: '/api/chat', body: { sessionId }, }), messages: toUIMessages(initialMessages), }) const isLoading = status === 'submitted' || status === 'streaming' useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [messages]) const handleSend = () => { const text = input.trim() if (!text || isLoading) return setInput('') sendMessage({ text }) } return (
{messages.length === 0 && (

Hi! I'm Gregor's AI recruiter assistant.

Ask me about his skills and experience, or schedule a meeting!

)} {messages.map((message) => (
{message.parts.map((part, i) => { if (part.type === 'text') { return (

{part.text}

) } if (part.type === 'tool-scheduleMeeting') { const toolPart = part as unknown as { type: 'tool-scheduleMeeting' state: string input: unknown output?: { success: boolean; message?: string; htmlLink?: string; error?: string } } if (toolPart.state === 'input-available' || toolPart.state === 'input-streaming') { return (

Scheduling meeting…

) } if (toolPart.state === 'output-available' && toolPart.output) { const result = toolPart.output return (
{result.success ? ( ✓ {result.message}{' '} {result.htmlLink && ( View event )} ) : ( ✗ {result.error} )}
) } } return null })}
))} {isLoading && (
Thinking…
)}