'use client'; import { motion } from 'framer-motion'; import { User, Bot } from 'lucide-react'; export type ChatRole = 'user' | 'assistant' | 'system'; export interface ChatMessageData { id?: string; role: ChatRole; content: string; created_at?: string; isStreaming?: boolean; } interface ChatMessageProps { message: ChatMessageData; index?: number; } /** * Formats a timestamp for display */ function formatTime(timestamp?: string): string { if (!timestamp) return ''; try { const date = new Date(timestamp); return date.toLocaleTimeString(undefined, { hour: '2-digit', minute: '2-digit', }); } catch { return ''; } } /** * ChatMessage component for displaying individual chat messages * Styled differently based on message role (user vs assistant) */ export function ChatMessage({ message, index = 0 }: ChatMessageProps) { const { role, content, created_at, isStreaming } = message; // Don't render system messages if (role === 'system') { return null; } const isUser = role === 'user'; const formattedTime = formatTime(created_at); return ( {/* Avatar */} {isUser ? ( ) : ( )} {/* Message Content */} {content} {isStreaming && ( )} {/* Timestamp */} {formattedTime && !isStreaming && ( {formattedTime} )} ); } /** * Typing indicator shown when assistant is generating a response */ export function TypingIndicator() { return ( {/* Avatar */} {/* Typing dots */} {[0, 1, 2].map((i) => ( ))} ); } /** * Welcome message component for empty chat state */ export function WelcomeMessage() { return ( Hi, I'm Damjan's AI Assistant I can help you learn about Damjan's skills, services, and experience. Feel free to ask me anything! ); } export default ChatMessage;
{content} {isStreaming && ( )}
I can help you learn about Damjan's skills, services, and experience. Feel free to ask me anything!