'use client' import { useState, useEffect, useRef } from 'react' import { createClient } from '@/lib/supabase/client' import { Hash, Users2 } from 'lucide-react' interface Props { member: any space: any channels: any[] } export default function CommsClient({ member, space, channels }: Props) { const [selectedChannel, setSelectedChannel] = useState(channels[0] || null) const [messages, setMessages] = useState([]) const [newMessage, setNewMessage] = useState('') const [sending, setSending] = useState(false) const messagesEndRef = useRef(null) useEffect(() => { if (!selectedChannel) return loadMessages() const supabase = createClient() const subscription = supabase .channel(`channel:${selectedChannel.id}`) .on('postgres_changes', { event: '*', schema: 'public', table: 'comms_messages', filter: `channel_id=eq.${selectedChannel.id}` }, payload => { if (payload.eventType === 'INSERT') { setMessages(prev => [...prev, payload.new]) } }) .subscribe() return () => { subscription.unsubscribe() } }, [selectedChannel]) useEffect(() => { messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' }) }, [messages]) async function loadMessages() { const supabase = createClient() const { data } = await supabase .from('comms_messages') .select('*') .eq('channel_id', selectedChannel.id) .order('created_at') .limit(100) setMessages(data ?? []) } async function sendMessage(e: React.FormEvent) { e.preventDefault() if (!newMessage.trim() || sending) return setSending(true) const supabase = createClient() await supabase.from('comms_messages').insert({ channel_id: selectedChannel.id, space_id: space?.id ?? member.space_id, user_id: member.user_id, display_name: member.display_name, handle: member.handle, content: newMessage.trim(), }) setNewMessage('') setSending(false) } const generalChannels = channels.filter(c => c.channel_type === 'general') const areaChannels = channels.filter(c => c.channel_type === 'area') const projectChannels = channels.filter(c => c.channel_type === 'project') return (

Comms

{/* Channels sidebar */} {/* Messages area */} {selectedChannel ? (
{/* Channel header */}

{selectedChannel.name}

{selectedChannel.description && (

{selectedChannel.description}

)}
{selectedChannel.member_count && ( {selectedChannel.member_count} members )}
{/* Messages */}
{messages.map((msg, i) => { const showAvatar = i === 0 || messages[i - 1]?.user_id !== msg.user_id return (
{showAvatar && (
{(msg.display_name || 'U').split(' ').map((n: string) => n[0]).join('').toUpperCase().slice(0, 2)}
)}
{showAvatar && (
{msg.display_name || 'Unknown'} {msg.handle && @{msg.handle}} {new Date(msg.created_at).toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit' })}
)}

{(msg.content || '').split(/(@\w+|#\w+)/g).map((part: string, j: number) => { if (part.startsWith('@')) return {part} if (part.startsWith('#')) return {part} return part })}

) })}
{/* Input */}
setNewMessage(e.target.value)} placeholder={`Message #${selectedChannel.name}`} className="flex-1 bg-muted border border-border rounded px-3 py-2 font-sans text-sm text-foreground placeholder:text-muted-foreground focus:outline-none focus:border-primary transition" />
) : (

Select a channel to view messages

)}
) }