2025-12-17 06:20:46 +02:00

189 lines
5.9 KiB
JavaScript

import React, { useState, useEffect, useRef } from 'react'
import { chatAPI, API_BASE_URL } from '../api'
import '../styles/chat.css'
export default function Chat({ conversationId, onNotificationsUpdate }) {
const [conversations, setConversations] = useState([])
const [selectedConversation, setSelectedConversation] = useState(conversationId || null)
const [messages, setMessages] = useState([])
const [newMessage, setNewMessage] = useState('')
const [isLoading, setIsLoading] = useState(true)
const [error, setError] = useState('')
const [isSending, setIsSending] = useState(false)
const messageInputRef = useRef(null)
const currentUserId = localStorage.getItem('user_id')
useEffect(() => {
loadConversations()
}, [])
useEffect(() => {
if (selectedConversation) {
loadMessages()
// Poll for new messages every 2 seconds
const interval = setInterval(loadMessages, 2000)
return () => clearInterval(interval)
}
}, [selectedConversation])
const loadConversations = async () => {
try {
setIsLoading(true)
const response = await chatAPI.getConversations()
setConversations(response.data || [])
// Notify parent about notifications update
if (onNotificationsUpdate) {
onNotificationsUpdate()
}
} catch (err) {
setError('Failed to load conversations')
} finally {
setIsLoading(false)
}
}
const loadMessages = async () => {
if (!selectedConversation) return
try {
const response = await chatAPI.getMessages(selectedConversation)
setMessages(response.data || [])
// Mark messages as read
await chatAPI.markAsRead(selectedConversation)
// Update unread_count to 0 for this conversation immediately
setConversations(prev =>
prev.map(conv =>
conv.id === selectedConversation
? { ...conv, unread_count: 0 }
: conv
)
)
// Update parent notifications
if (onNotificationsUpdate) {
onNotificationsUpdate()
}
} catch (err) {
setError('Failed to load messages')
}
}
const handleSendMessage = async (e) => {
e.preventDefault()
if (!newMessage.trim() || !selectedConversation) return
setIsSending(true)
try {
const response = await chatAPI.sendMessage(selectedConversation, newMessage)
setMessages((prev) => [...prev, response.data])
setNewMessage('')
// Auto-focus back to input field after sending
setTimeout(() => messageInputRef.current?.focus(), 0)
} catch (err) {
setError('Failed to send message')
} finally {
setIsSending(false)
}
}
if (isLoading) {
return <div className="chat">Loading conversations...</div>
}
if (conversations.length === 0) {
return (
<div className="chat">
<div className="empty-state">
<h2>No conversations yet</h2>
<p>Match with someone to start chatting!</p>
<a href="/discover">Discover</a>
</div>
</div>
)
}
return (
<div className="chat">
<div className="chat-container">
<div className="conversations-list">
<h2>Conversations</h2>
{conversations.map((conv) => (
<div
key={conv.id}
className={`conversation-item ${selectedConversation === conv.id ? 'active' : ''}`}
onClick={() => setSelectedConversation(conv.id)}
>
<div className="conversation-header">
{conv.other_user_photo ? (
<img
src={`${API_BASE_URL}/media/${conv.other_user_photo}`}
alt={conv.other_user_display_name}
className="conversation-avatar"
/>
) : (
<div className="conversation-avatar-placeholder">
{conv.other_user_display_name.charAt(0).toUpperCase()}
</div>
)}
<div className="conversation-info">
<h4>{conv.other_user_display_name}</h4>
<p className="latest-msg">{conv.latest_message || 'No messages yet'}</p>
</div>
{conv.unread_count > 0 && (
<span className="unread-badge">{conv.unread_count}</span>
)}
</div>
</div>
))}
</div>
<div className="messages-pane">
{selectedConversation ? (
<>
<div className="messages-header">
<h3>
{conversations.find((c) => c.id === selectedConversation)?.other_user_display_name}
</h3>
</div>
<div className="messages-list">
{messages.map((msg) => (
<div
key={msg.id}
className={`message ${msg.sender_id == currentUserId ? 'sent' : 'received'}`}
>
<p>{msg.content}</p>
<span className="timestamp">
{new Date(msg.created_at).toLocaleTimeString()}
</span>
</div>
))}
</div>
<form onSubmit={handleSendMessage} className="message-form">
<input
ref={messageInputRef}
type="text"
value={newMessage}
onChange={(e) => setNewMessage(e.target.value)}
placeholder="Type a message..."
disabled={isSending}
autoFocus
/>
<button type="submit" disabled={isSending || !newMessage.trim()}>
Send
</button>
</form>
</>
) : (
<div className="no-conversation">Select a conversation to start messaging</div>
)}
</div>
</div>
</div>
)
}