'use client' import { useRef, useEffect } from 'react' import { formatMessageDate, getContactInitials, getRoleLabel, getRoleColor, type Conversation, type Message, type Contact, } from '@/lib/MessagesContext' import { EmojiPicker } from './EmojiPicker' import { TemplatesDropdown } from './TemplatesDropdown' interface ChatAreaProps { isDark: boolean currentConversation: Conversation | null | undefined currentContact: Contact | undefined groupedMessages: { date: string; messages: Message[] }[] messageInput: string sendWithEmail: boolean isSending: boolean showEmojiPicker: boolean showTemplates: boolean templates: { id: string; name: string; content: string }[] setMessageInput: (val: string) => void setSendWithEmail: (val: boolean) => void setShowEmojiPicker: (val: boolean) => void setShowTemplates: (val: boolean) => void setShowContactInfo: (val: boolean) => void showContactInfo: boolean handleSendMessage: () => void handleEmojiSelect: (emoji: string) => void handleContextMenu: (e: React.MouseEvent, messageId: string) => void getSenderName: (senderId: string) => string pinConversation: (id: string) => void muteConversation: (id: string) => void setShowNewConversation: (val: boolean) => void } export function ChatArea({ isDark, currentConversation, currentContact, groupedMessages, messageInput, sendWithEmail, isSending, showEmojiPicker, showTemplates, templates, setMessageInput, setSendWithEmail, setShowEmojiPicker, setShowTemplates, setShowContactInfo, showContactInfo, handleSendMessage, handleEmojiSelect, handleContextMenu, getSenderName, pinConversation, muteConversation, setShowNewConversation, }: ChatAreaProps) { const messagesEndRef = useRef(null) const inputRef = useRef(null) useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [groupedMessages]) const handleKeyDown = (e: React.KeyboardEvent) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault() handleSendMessage() } } return (
{currentConversation ? ( <> {/* Chat Header */} {/* Messages */}
{groupedMessages.length === 0 ? (
👋

Noch keine Nachrichten

Starten Sie die Konversation!

) : ( groupedMessages.map((group, groupIndex) => ( )) )}
{/* Message Input */} ) : ( )}
) } // ============================================ // SUB-COMPONENTS // ============================================ function ChatHeader({ isDark, conversation, contact, showContactInfo, setShowContactInfo, pinConversation, muteConversation }: { isDark: boolean; conversation: Conversation; contact: Contact | undefined showContactInfo: boolean; setShowContactInfo: (val: boolean) => void pinConversation: (id: string) => void; muteConversation: (id: string) => void }) { return (
{conversation.title ? getContactInitials(conversation.title) : '?'}
{!conversation.is_group && contact?.online && ( )}

{conversation.title || 'Unbenannt'}

{conversation.typing ? ( schreibt... ) : contact ? ( <> {getRoleLabel(contact.role)} {contact.student_name && ( • {contact.student_name} )} {contact.online && ( • Online )} ) : conversation.is_group && ( {conversation.participant_ids.length} Mitglieder )}
{/* Actions */}
pinConversation(conversation.id)} title={conversation.pinned ? 'Nicht mehr anheften' : 'Anheften'}> muteConversation(conversation.id)} title={conversation.muted ? 'Ton aktivieren' : 'Stummschalten'}> {conversation.muted ? ( ) : ( )} setShowContactInfo(!showContactInfo)}>
) } function HeaderButton({ isDark, active, activeColor, onClick, title, children }: { isDark: boolean; active: boolean; activeColor: string onClick: () => void; title?: string; children: React.ReactNode }) { const activeClasses: Record = { amber: isDark ? 'bg-amber-500/20 text-amber-300' : 'bg-amber-100 text-amber-700', red: isDark ? 'bg-red-500/20 text-red-300' : 'bg-red-100 text-red-700', green: isDark ? 'bg-green-500/20 text-green-300' : 'bg-green-100 text-green-700', } return ( ) } function MessageGroup({ isDark, group, currentConversation, getSenderName, handleContextMenu }: { isDark: boolean; group: { date: string; messages: Message[] } currentConversation: Conversation getSenderName: (id: string) => string handleContextMenu: (e: React.MouseEvent, id: string) => void }) { return (
{group.date}
{group.messages.map((msg) => { const isSelf = msg.sender_id === 'self' const isGroupMsg = currentConversation.is_group && !isSelf return (
handleContextMenu(e, msg.id)}>
{isGroupMsg && ( {getSenderName(msg.sender_id)} )}

{msg.content}

{msg.reactions && msg.reactions.length > 0 && (
{msg.reactions.map((r, i) => ( {r.emoji} ))}
)}
{new Date(msg.timestamp).toLocaleTimeString('de-DE', { hour: '2-digit', minute: '2-digit' })} {isSelf && ( <> {msg.delivered && ( )} {msg.email_sent && ✉️} )}
) })}
) } function MessageInput({ isDark, messageInput, sendWithEmail, isSending, showEmojiPicker, showTemplates, templates, inputRef, setMessageInput, setSendWithEmail, setShowEmojiPicker, setShowTemplates, handleSendMessage, handleEmojiSelect, handleKeyDown }: { isDark: boolean; messageInput: string; sendWithEmail: boolean; isSending: boolean showEmojiPicker: boolean; showTemplates: boolean templates: { id: string; name: string; content: string }[] inputRef: React.RefObject setMessageInput: (val: string) => void; setSendWithEmail: (val: boolean) => void setShowEmojiPicker: (val: boolean) => void; setShowTemplates: (val: boolean) => void handleSendMessage: () => void; handleEmojiSelect: (emoji: string) => void handleKeyDown: (e: React.KeyboardEvent) => void }) { return (
{showEmojiPicker && ( setShowEmojiPicker(false)} isDark={isDark} /> )}
{showTemplates && ( { setMessageInput(content); setShowTemplates(false); inputRef.current?.focus() }} isDark={isDark} /> )}