mirror of
https://git.v0id.ovh/n3wt-innov/n3wt-school.git
synced 2026-01-28 23:43:22 +00:00
feat: mise en place de la messagerie [#17]
This commit is contained in:
133
Front-End/src/components/Chat/MessageBubble.js
Normal file
133
Front-End/src/components/Chat/MessageBubble.js
Normal file
@ -0,0 +1,133 @@
|
||||
import React from 'react';
|
||||
import { format, isToday, isYesterday } from 'date-fns';
|
||||
import { fr } from 'date-fns/locale';
|
||||
import { Check, CheckCheck } from 'lucide-react';
|
||||
import FileAttachment from './FileAttachment';
|
||||
import { getGravatarUrl } from '@/utils/gravatar';
|
||||
|
||||
const MessageBubble = ({
|
||||
message,
|
||||
isOwnMessage,
|
||||
showAvatar = true,
|
||||
isRead = false,
|
||||
senderName = '',
|
||||
senderEmail = '', // Nouveau prop pour l'email du sender
|
||||
isFirstInGroup = true,
|
||||
isLastInGroup = true,
|
||||
showTime = true,
|
||||
}) => {
|
||||
const formatMessageTime = (dateString) => {
|
||||
if (!dateString) return '';
|
||||
|
||||
const date = new Date(dateString);
|
||||
|
||||
if (isToday(date)) {
|
||||
return format(date, 'HH:mm', { locale: fr });
|
||||
} else if (isYesterday(date)) {
|
||||
return `Hier ${format(date, 'HH:mm', { locale: fr })}`;
|
||||
} else {
|
||||
return format(date, 'dd/MM HH:mm', { locale: fr });
|
||||
}
|
||||
};
|
||||
|
||||
const getMessageContent = () => {
|
||||
return message.content || message.corpus || '';
|
||||
};
|
||||
|
||||
const getMessageTime = () => {
|
||||
return message.created_at || message.date_envoi;
|
||||
};
|
||||
|
||||
const hasAttachment = () => {
|
||||
return (
|
||||
message.attachment &&
|
||||
(message.attachment.fileName || message.attachment.fileUrl)
|
||||
);
|
||||
};
|
||||
|
||||
const isFileOnlyMessage = () => {
|
||||
return hasAttachment() && !getMessageContent().trim();
|
||||
};
|
||||
|
||||
return (
|
||||
<div
|
||||
className={`group hover:bg-gray-50 px-4 py-1 ${isFirstInGroup ? 'mt-4' : 'mt-0.5'} message-appear`}
|
||||
onMouseEnter={() => {
|
||||
/* Peut ajouter des actions au hover */
|
||||
}}
|
||||
>
|
||||
<div className="flex">
|
||||
{/* Avatar - affiché seulement pour le premier message du groupe */}
|
||||
{showAvatar && isFirstInGroup && (
|
||||
<img
|
||||
src={getGravatarUrl(senderEmail || senderName, 40)}
|
||||
alt={`Avatar de ${senderName || 'Utilisateur'}`}
|
||||
className="w-10 h-10 rounded-full object-cover shadow-sm mr-3 flex-shrink-0 mt-0.5"
|
||||
/>
|
||||
)}
|
||||
|
||||
{/* Espace pour aligner avec l'avatar quand il n'est pas affiché */}
|
||||
{(!showAvatar || !isFirstInGroup) && (
|
||||
<div className="w-10 mr-3 flex-shrink-0"></div>
|
||||
)}
|
||||
|
||||
{/* Contenu du message */}
|
||||
<div className="flex-1 min-w-0">
|
||||
{/* En-tête du message (nom + heure) - seulement pour le premier message du groupe */}
|
||||
{isFirstInGroup && (
|
||||
<div className="flex items-baseline space-x-2 mb-1">
|
||||
<span className="font-semibold text-gray-900 text-sm">
|
||||
{senderName || (isOwnMessage ? 'Moi' : 'Utilisateur')}
|
||||
</span>
|
||||
<span className="text-xs text-gray-500">
|
||||
{formatMessageTime(getMessageTime())}
|
||||
</span>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Fichier attaché */}
|
||||
{hasAttachment() && (
|
||||
<div className={`${getMessageContent().trim() ? 'mb-2' : ''}`}>
|
||||
<FileAttachment
|
||||
fileName={message.attachment.fileName}
|
||||
fileSize={message.attachment.fileSize}
|
||||
fileType={message.attachment.fileType}
|
||||
fileUrl={message.attachment.fileUrl}
|
||||
/>
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Contenu du message */}
|
||||
{getMessageContent().trim() && (
|
||||
<div className="text-sm leading-relaxed whitespace-pre-wrap break-words text-gray-800">
|
||||
{getMessageContent()}
|
||||
</div>
|
||||
)}
|
||||
|
||||
{/* Indicateurs de lecture et heure pour les messages non-groupés */}
|
||||
<div className="flex items-center space-x-2 mt-1">
|
||||
{/* Heure pour les messages qui ne sont pas le premier du groupe */}
|
||||
{!isFirstInGroup && (
|
||||
<span className="text-xs text-gray-400 opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
{formatMessageTime(getMessageTime())}
|
||||
</span>
|
||||
)}
|
||||
|
||||
{/* Indicateurs de lecture (uniquement pour nos messages) */}
|
||||
{isOwnMessage && (
|
||||
<div className="flex items-center opacity-0 group-hover:opacity-100 transition-opacity">
|
||||
{isRead ? (
|
||||
<CheckCheck className="w-3 h-3 text-green-500" title="Lu" />
|
||||
) : (
|
||||
<Check className="w-3 h-3 text-gray-400" title="Envoyé" />
|
||||
)}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default MessageBubble;
|
||||
Reference in New Issue
Block a user