91a87199c4
Co-authored-by: Walidoux <ma.walidkorchi@icloud.com>
179 lines
5.7 KiB
TypeScript
179 lines
5.7 KiB
TypeScript
import { useState, useRef } from 'react'
|
|
import Image from 'next/image'
|
|
import Link from 'next/link'
|
|
import date from 'date-and-time'
|
|
import TextareaAutosize from 'react-textarea-autosize'
|
|
import useTranslation from 'next-translate/useTranslation'
|
|
|
|
import { MessageWithMember } from '../../../../models/Message'
|
|
import { MessageText } from './MessageText'
|
|
import { Loader } from '../../../design/Loader'
|
|
import { MessageFile } from './MessageFile'
|
|
import { Emoji } from '../../../Emoji'
|
|
import { useAuthentication } from '../../../../tools/authentication'
|
|
|
|
export interface MessageProps {
|
|
message: MessageWithMember
|
|
}
|
|
|
|
export const Message: React.FC<MessageProps> = (props) => {
|
|
const { message } = props
|
|
|
|
const textareaReference = useRef<HTMLTextAreaElement>(null)
|
|
const [isEditing, setIsEditing] = useState(false)
|
|
const { t } = useTranslation()
|
|
const { authentication, user } = useAuthentication()
|
|
|
|
const handleDeleteMessage = async (): Promise<void> => {
|
|
try {
|
|
await authentication.api.delete(`/messages/${message.id}`)
|
|
} catch {}
|
|
}
|
|
|
|
const handleTextareaKeyDown: React.KeyboardEventHandler<HTMLFormElement> = (
|
|
event
|
|
) => {
|
|
if (event.key === 'Enter' && !event.shiftKey) {
|
|
event.preventDefault()
|
|
event.currentTarget.dispatchEvent(
|
|
new Event('submit', { cancelable: true, bubbles: true })
|
|
)
|
|
}
|
|
}
|
|
|
|
const handleEdit = async (): Promise<void> => {
|
|
const newMessage = textareaReference.current?.value ?? message.value
|
|
if (
|
|
typeof newMessage === 'string' &&
|
|
newMessage.length > 0 &&
|
|
newMessage !== message.value
|
|
) {
|
|
try {
|
|
await authentication.api.put(`/messages/${message.id}`, {
|
|
value: newMessage
|
|
})
|
|
} catch {}
|
|
}
|
|
handleEditMode()
|
|
}
|
|
|
|
const handleEditSubmit: React.FormEventHandler<HTMLFormElement> = async (
|
|
event
|
|
) => {
|
|
event.preventDefault()
|
|
await handleEdit()
|
|
}
|
|
|
|
const handleEditMode = (): void => {
|
|
setIsEditing((oldIsEditing) => {
|
|
return !oldIsEditing
|
|
})
|
|
}
|
|
|
|
return (
|
|
<div
|
|
className='group flex w-full p-4 transition hover:bg-gray-200 dark:hover:bg-gray-900'
|
|
data-cy={`message-${message.id}`}
|
|
>
|
|
<Link href={`/application/users/${message.member.user.id}`}>
|
|
<a>
|
|
<div className='mr-4 flex h-12 w-12 flex-shrink-0 items-center justify-center'>
|
|
<div className='h-10 w-10 drop-shadow-md'>
|
|
<Image
|
|
quality={100}
|
|
className='rounded-full'
|
|
src={
|
|
message.member.user.logo == null
|
|
? '/images/data/user-default.png'
|
|
: message.member.user.logo
|
|
}
|
|
alt={"Users's profil picture"}
|
|
width={50}
|
|
height={50}
|
|
draggable={false}
|
|
/>
|
|
</div>
|
|
</div>
|
|
</a>
|
|
</Link>
|
|
<div className='relative w-full whitespace-pre-wrap break-words break-all'>
|
|
<div className='flex w-max items-center'>
|
|
<Link href={`/application/users/${message.member.user.id}`}>
|
|
<a>
|
|
<span
|
|
data-cy='message-member-user-name'
|
|
className='font-bold text-gray-900 dark:text-gray-200'
|
|
>
|
|
{message.member.user.name}
|
|
</span>
|
|
</a>
|
|
</Link>
|
|
<span
|
|
data-cy='message-date'
|
|
className='ml-4 select-none text-xs text-gray-500 dark:text-gray-200'
|
|
>
|
|
{date.format(new Date(message.createdAt), 'DD/MM/YYYY - HH:mm:ss')}
|
|
</span>
|
|
</div>
|
|
{message.member.userId === user.id ? (
|
|
<div className='absolute right-6 -top-8 flex opacity-0 transition-opacity group-hover:opacity-100'>
|
|
{message.type === 'text' ? (
|
|
<div
|
|
className='message-options rounded-l-lg border-l-slate-600'
|
|
title={t('application:edit')}
|
|
onClick={isEditing ? handleEdit : handleEditMode}
|
|
>
|
|
<Emoji
|
|
value={isEditing ? ':white_check_mark:' : ':pencil2:'}
|
|
size={18}
|
|
/>
|
|
</div>
|
|
) : null}
|
|
<div
|
|
className='message-options rounded-r-lg border-r-slate-600'
|
|
title={t('application:delete')}
|
|
onClick={handleDeleteMessage}
|
|
>
|
|
<Emoji value=':wastebasket:' size={18} />
|
|
</div>
|
|
</div>
|
|
) : null}
|
|
{message.type === 'text' ? (
|
|
<>
|
|
{isEditing ? (
|
|
<form
|
|
className='flex h-full w-full items-center'
|
|
onSubmit={handleEditSubmit}
|
|
onKeyDown={handleTextareaKeyDown}
|
|
>
|
|
<TextareaAutosize
|
|
className='scrollbar-firefox-support w-full resize-none bg-transparent p-2 tracking-wide outline-none'
|
|
placeholder={t('application:write-a-message')}
|
|
wrap='soft'
|
|
maxRows={6}
|
|
name='message'
|
|
defaultValue={message.value}
|
|
ref={textareaReference}
|
|
autoFocus
|
|
onFocus={(event) => {
|
|
event.currentTarget.setSelectionRange(
|
|
event.currentTarget.value.length,
|
|
event.currentTarget.value.length
|
|
)
|
|
}}
|
|
/>
|
|
</form>
|
|
) : (
|
|
<MessageText message={message} />
|
|
)}
|
|
</>
|
|
) : message.type === 'file' ? (
|
|
<MessageFile message={message} />
|
|
) : (
|
|
<Loader />
|
|
)}
|
|
</div>
|
|
</div>
|
|
)
|
|
}
|