mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
176 lines
5.9 KiB
JavaScript
176 lines
5.9 KiB
JavaScript
import React, { useState, useRef, useEffect } from 'react';
|
|
import { SendHorizontal, Plus } from 'lucide-react';
|
|
import Image from 'next/image';
|
|
import {
|
|
fetchConversations,
|
|
fetchMessages,
|
|
sendMessage,
|
|
markAsRead,
|
|
} from '@/app/actions/messagerieAction';
|
|
|
|
export default function Chat({
|
|
userProfileId,
|
|
establishmentId,
|
|
discussions: discussionsProp,
|
|
setDiscussions: setDiscussionsProp,
|
|
onCreateDiscussion,
|
|
onShowCreateDiscussion,
|
|
}) {
|
|
const [discussions, setDiscussions] = useState(discussionsProp || []);
|
|
const [selectedDiscussion, setSelectedDiscussion] = useState(null);
|
|
const [messages, setMessages] = useState([]);
|
|
const [newMessage, setNewMessage] = useState('');
|
|
const messagesEndRef = useRef(null);
|
|
|
|
useEffect(() => {
|
|
if (userProfileId) {
|
|
fetchConversations(userProfileId).then(setDiscussions);
|
|
}
|
|
}, [userProfileId]);
|
|
|
|
useEffect(() => {
|
|
if (selectedDiscussion) {
|
|
fetchMessages(selectedDiscussion.conversation_id).then(setMessages);
|
|
// Marquer comme lu
|
|
markAsRead(selectedDiscussion.conversation_id, userProfileId);
|
|
}
|
|
}, [selectedDiscussion, userProfileId]);
|
|
|
|
const handleSendMessage = async () => {
|
|
if (newMessage.trim() && selectedDiscussion) {
|
|
await sendMessage({
|
|
conversation_id: selectedDiscussion.conversation_id,
|
|
emetteur: userProfileId,
|
|
destinataire: selectedDiscussion.interlocuteur.id,
|
|
corpus: newMessage,
|
|
objet: '',
|
|
});
|
|
setNewMessage('');
|
|
fetchMessages(selectedDiscussion.conversation_id).then(setMessages);
|
|
fetchConversations(userProfileId).then(setDiscussions);
|
|
}
|
|
};
|
|
|
|
const handleKeyPress = (event) => {
|
|
if (event.key === 'Enter') {
|
|
handleSendMessage();
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className="flex h-full w-full">
|
|
{/* Bandeau droit : Liste des discussions */}
|
|
<div className="w-1/4 min-w-[280px] bg-gray-100 border-r border-gray-300 p-4 flex flex-col">
|
|
<div className="flex items-center justify-between mb-4">
|
|
<h2 className="text-lg font-bold">Discussions</h2>
|
|
<button
|
|
className="p-2 rounded-full bg-blue-500 hover:bg-blue-600 text-white shadow"
|
|
title="Nouvelle discussion"
|
|
onClick={onShowCreateDiscussion}
|
|
>
|
|
<Plus size={20} />
|
|
</button>
|
|
</div>
|
|
<div className="flex-1 overflow-y-auto">
|
|
{discussions && discussions.length > 0 ? (
|
|
discussions.map((discussion) => (
|
|
<div
|
|
key={discussion.id}
|
|
className={`flex items-center p-2 mb-2 cursor-pointer rounded transition-colors ${
|
|
selectedDiscussion?.id === discussion.id
|
|
? 'bg-blue-100'
|
|
: 'hover:bg-gray-200'
|
|
}`}
|
|
onClick={() => setSelectedDiscussion(discussion)}
|
|
>
|
|
<Image
|
|
src={discussion.profilePic}
|
|
alt={`${discussion.name}'s profile`}
|
|
className="w-10 h-10 rounded-full mr-3"
|
|
width={40}
|
|
height={40}
|
|
/>
|
|
<div className="flex-1">
|
|
<p className="font-medium">{discussion.name}</p>
|
|
<p className="text-sm text-gray-500 truncate">
|
|
{discussion.lastMessage}
|
|
</p>
|
|
</div>
|
|
<span className="text-xs text-gray-400">
|
|
{discussion.lastMessageDate &&
|
|
new Date(discussion.lastMessageDate).toLocaleTimeString()}
|
|
</span>
|
|
</div>
|
|
))
|
|
) : (
|
|
<p className="text-gray-500">Aucune discussion disponible.</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
|
|
{/* Zone de chat */}
|
|
<div className="flex-1 flex flex-col bg-white">
|
|
{/* En-tête du chat */}
|
|
{selectedDiscussion && (
|
|
<div className="flex items-center p-4 border-b border-gray-300">
|
|
<Image
|
|
src={selectedDiscussion.profilePic}
|
|
alt={`${selectedDiscussion.name}'s profile`}
|
|
className="w-10 h-10 rounded-full mr-3"
|
|
width={40}
|
|
height={40}
|
|
/>
|
|
<h2 className="text-lg font-bold">{selectedDiscussion.name}</h2>
|
|
</div>
|
|
)}
|
|
{/* Messages */}
|
|
<div className="flex-1 overflow-y-auto p-4">
|
|
{selectedDiscussion &&
|
|
messages.map((message) => (
|
|
<div
|
|
key={message.id}
|
|
className={`flex mb-4 ${
|
|
message.isResponse ? 'justify-start' : 'justify-end'
|
|
}`}
|
|
>
|
|
<div
|
|
className={`p-3 rounded-lg max-w-xs ${
|
|
message.isResponse
|
|
? 'bg-gray-200 text-gray-800'
|
|
: 'bg-blue-500 text-white'
|
|
}`}
|
|
>
|
|
<p>{message.corpus}</p>
|
|
<span className="text-xs text-gray-500 block mt-1">
|
|
{message.date &&
|
|
new Date(message.date).toLocaleTimeString()}
|
|
</span>
|
|
</div>
|
|
</div>
|
|
))}
|
|
<div ref={messagesEndRef} />
|
|
</div>
|
|
{/* Champ de saisie */}
|
|
{selectedDiscussion && (
|
|
<div className="p-4 border-t border-gray-300 flex items-center">
|
|
<input
|
|
type="text"
|
|
value={newMessage}
|
|
onChange={(e) => setNewMessage(e.target.value)}
|
|
className="flex-1 p-2 border border-gray-300 rounded-lg mr-2"
|
|
placeholder="Écrire un message..."
|
|
onKeyDown={(e) => e.key === 'Enter' && handleSendMessage()}
|
|
/>
|
|
<button
|
|
onClick={handleSendMessage}
|
|
className="p-2 bg-blue-500 text-white rounded-lg"
|
|
>
|
|
<SendHorizontal />
|
|
</button>
|
|
</div>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|