214 lines
7.2 KiB
TypeScript
214 lines
7.2 KiB
TypeScript
import {
|
|
VideoroomChatDto,
|
|
VideoroomParticipantDto,
|
|
VideoroomSettingsDto,
|
|
MessageType,
|
|
} from '@/proxy/videoroom/models'
|
|
import React, { useRef, useEffect } from 'react'
|
|
import { FaTimes, FaUsers, FaUser, FaBullhorn, FaPaperPlane } from 'react-icons/fa'
|
|
import { Button } from '@/components/ui'
|
|
|
|
interface ChatPanelProps {
|
|
user: { id: string; name: string; role: string }
|
|
participants: VideoroomParticipantDto[]
|
|
chatMessages: VideoroomChatDto[]
|
|
newMessage: string
|
|
setNewMessage: (msg: string) => void
|
|
messageMode: MessageType
|
|
setMessageMode: (mode: MessageType) => void
|
|
selectedRecipient: { id: string; name: string } | null
|
|
setSelectedRecipient: (recipient: { id: string; name: string } | null) => void
|
|
onSendMessage: (e: React.FormEvent) => void
|
|
onClose: () => void
|
|
formatTime: (timestamp: string) => string
|
|
classSettings: VideoroomSettingsDto
|
|
}
|
|
|
|
const ChatPanel: React.FC<ChatPanelProps> = ({
|
|
user,
|
|
participants,
|
|
chatMessages,
|
|
newMessage,
|
|
setNewMessage,
|
|
messageMode,
|
|
setMessageMode,
|
|
selectedRecipient,
|
|
setSelectedRecipient,
|
|
onSendMessage,
|
|
onClose,
|
|
formatTime,
|
|
classSettings,
|
|
}) => {
|
|
const messagesEndRef = useRef<HTMLDivElement>(null)
|
|
|
|
useEffect(() => {
|
|
messagesEndRef.current?.scrollIntoView({ behavior: 'smooth' })
|
|
}, [chatMessages])
|
|
|
|
const availableRecipients = participants.filter((p) => p.id !== user.id)
|
|
|
|
return (
|
|
<div className="h-full bg-white flex flex-col text-gray-900">
|
|
{/* Header */}
|
|
<div className="p-3 sm:p-4 border-b border-gray-200 flex justify-between items-center">
|
|
<h3 className="text-base sm:text-lg font-semibold">Sohbet</h3>
|
|
<Button
|
|
type="button"
|
|
variant="plain"
|
|
shape="none"
|
|
className="!inline-flex !h-auto items-center justify-center !bg-transparent !p-1 hover:!bg-gray-100 active:!bg-gray-100"
|
|
onClick={onClose}
|
|
>
|
|
<FaTimes className="text-gray-500" size={16} />
|
|
</Button>
|
|
</div>
|
|
|
|
{/* Mesaj Modu */}
|
|
<div className="p-3 border-b border-gray-200 bg-gray-50">
|
|
<div className="flex space-x-2 mb-2">
|
|
<Button
|
|
type="button"
|
|
variant="plain"
|
|
shape="none"
|
|
onClick={() => {
|
|
setMessageMode('public')
|
|
setSelectedRecipient(null)
|
|
}}
|
|
className={`!inline-flex !h-auto items-center gap-1 rounded-full !px-3 py-1 text-xs ${
|
|
messageMode === 'public'
|
|
? '!bg-blue-600 text-white'
|
|
: '!bg-gray-200 text-gray-700 hover:!bg-gray-300'
|
|
}`}
|
|
>
|
|
<FaUsers size={12} />
|
|
<span>Herkese</span>
|
|
</Button>
|
|
|
|
{classSettings.allowPrivateMessages && (
|
|
<Button
|
|
type="button"
|
|
variant="plain"
|
|
shape="none"
|
|
onClick={() => setMessageMode('private')}
|
|
className={`!inline-flex !h-auto items-center gap-1 rounded-full !px-3 py-1 text-xs ${
|
|
messageMode === 'private'
|
|
? '!bg-green-600 text-white'
|
|
: '!bg-gray-200 text-gray-700 hover:!bg-gray-300'
|
|
}`}
|
|
>
|
|
<FaUser size={12} />
|
|
<span>Özel</span>
|
|
</Button>
|
|
)}
|
|
{user.role === 'teacher' && (
|
|
<Button
|
|
type="button"
|
|
variant="plain"
|
|
shape="none"
|
|
onClick={() => {
|
|
setMessageMode('announcement')
|
|
setSelectedRecipient(null)
|
|
}}
|
|
className={`!inline-flex !h-auto items-center gap-1 rounded-full !px-3 py-1 text-xs ${
|
|
messageMode === 'announcement'
|
|
? '!bg-red-600 text-white'
|
|
: '!bg-gray-200 text-gray-700 hover:!bg-gray-300'
|
|
}`}
|
|
>
|
|
<FaBullhorn size={12} />
|
|
<span>Duyuru</span>
|
|
</Button>
|
|
)}
|
|
</div>
|
|
|
|
{messageMode === 'private' && (
|
|
<select
|
|
value={selectedRecipient?.id || ''}
|
|
onChange={(e) => {
|
|
const recipient = availableRecipients.find((p) => p.id === e.target.value)
|
|
setSelectedRecipient(recipient ? { id: recipient.id, name: recipient.name } : null)
|
|
}}
|
|
className="w-full px-2 py-1 text-xs border border-gray-300 rounded"
|
|
>
|
|
<option value="">Kişi seçin...</option>
|
|
{availableRecipients.map((p) => (
|
|
<option key={p.id} value={p.id}>
|
|
{p.name} {p.isTeacher ? '(Öğretmen)' : ''}
|
|
</option>
|
|
))}
|
|
</select>
|
|
)}
|
|
</div>
|
|
|
|
{/* Mesaj Listesi */}
|
|
<div className="flex-1 overflow-y-auto p-4 space-y-3">
|
|
{chatMessages.length === 0 ? (
|
|
<div className="text-center text-gray-500 text-sm">Henüz mesaj yok.</div>
|
|
) : (
|
|
chatMessages.map((m) => (
|
|
<div
|
|
key={m.id}
|
|
className={`${
|
|
m.messageType === 'announcement'
|
|
? 'w-full'
|
|
: m.senderId === user.id
|
|
? 'flex justify-end'
|
|
: 'flex justify-start'
|
|
}`}
|
|
>
|
|
<div
|
|
className={`max-w-xs px-3 py-2 rounded-lg ${
|
|
m.messageType === 'announcement'
|
|
? 'bg-red-100 text-red-800 border border-red-200 w-full text-center'
|
|
: m.messageType === 'private'
|
|
? m.senderId === user.id
|
|
? 'bg-green-600 text-white'
|
|
: 'bg-green-100 text-green-800 border'
|
|
: m.senderId === user.id
|
|
? 'bg-blue-600 text-white'
|
|
: m.isTeacher
|
|
? 'bg-yellow-100 text-yellow-800 border'
|
|
: 'bg-gray-100 text-gray-800'
|
|
}`}
|
|
>
|
|
{m.senderId !== user.id && (
|
|
<div className="text-xs font-semibold mb-1">
|
|
{m.senderName}
|
|
{m.isTeacher && ' (Öğretmen)'}
|
|
</div>
|
|
)}
|
|
<div className="text-sm">{m.message}</div>
|
|
<div className="text-xs mt-1 opacity-75">{formatTime(m.timestamp)}</div>
|
|
</div>
|
|
</div>
|
|
))
|
|
)}
|
|
<div ref={messagesEndRef} />
|
|
</div>
|
|
|
|
{/* Mesaj Gönderme */}
|
|
<form onSubmit={onSendMessage} className="p-4 border-t border-gray-200">
|
|
<div className="flex space-x-2">
|
|
<input
|
|
type="text"
|
|
value={newMessage}
|
|
onChange={(e) => setNewMessage(e.target.value)}
|
|
placeholder="Mesaj yaz..."
|
|
className="flex-1 px-3 py-2 border border-gray-300 rounded-lg text-sm"
|
|
/>
|
|
<Button
|
|
type="submit"
|
|
variant="plain"
|
|
shape="none"
|
|
disabled={!newMessage.trim()}
|
|
className="!inline-flex !h-auto items-center justify-center rounded-lg !bg-blue-600 !px-3 py-2 text-white hover:!bg-blue-700 disabled:!bg-gray-400"
|
|
>
|
|
<FaPaperPlane size={16} />
|
|
</Button>
|
|
</div>
|
|
</form>
|
|
</div>
|
|
)
|
|
}
|
|
|
|
export default ChatPanel
|