sozsoft-platform/ui/src/views/admin/videoroom/ChatPanel.tsx

215 lines
7.2 KiB
TypeScript
Raw Normal View History

2026-05-08 05:34:29 +00:00
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'
2026-05-08 05:34:29 +00:00
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}
>
2026-05-08 05:34:29 +00:00
<FaTimes className="text-gray-500" size={16} />
</Button>
2026-05-08 05:34:29 +00:00
</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"
2026-05-08 05:34:29 +00:00
onClick={() => {
setMessageMode('public')
setSelectedRecipient(null)
}}
className={`!inline-flex !h-auto items-center gap-1 rounded-full !px-3 py-1 text-xs ${
2026-05-08 05:34:29 +00:00
messageMode === 'public'
? '!bg-blue-600 text-white'
: '!bg-gray-200 text-gray-700 hover:!bg-gray-300'
2026-05-08 05:34:29 +00:00
}`}
>
<FaUsers size={12} />
<span>Herkese</span>
</Button>
2026-05-08 05:34:29 +00:00
{classSettings.allowPrivateMessages && (
<Button
type="button"
variant="plain"
shape="none"
2026-05-08 05:34:29 +00:00
onClick={() => setMessageMode('private')}
className={`!inline-flex !h-auto items-center gap-1 rounded-full !px-3 py-1 text-xs ${
2026-05-08 05:34:29 +00:00
messageMode === 'private'
? '!bg-green-600 text-white'
: '!bg-gray-200 text-gray-700 hover:!bg-gray-300'
2026-05-08 05:34:29 +00:00
}`}
>
<FaUser size={12} />
<span>Özel</span>
</Button>
2026-05-08 05:34:29 +00:00
)}
{user.role === 'teacher' && (
<Button
type="button"
variant="plain"
shape="none"
2026-05-08 05:34:29 +00:00
onClick={() => {
setMessageMode('announcement')
setSelectedRecipient(null)
}}
className={`!inline-flex !h-auto items-center gap-1 rounded-full !px-3 py-1 text-xs ${
2026-05-08 05:34:29 +00:00
messageMode === 'announcement'
? '!bg-red-600 text-white'
: '!bg-gray-200 text-gray-700 hover:!bg-gray-300'
2026-05-08 05:34:29 +00:00
}`}
>
<FaBullhorn size={12} />
<span>Duyuru</span>
</Button>
2026-05-08 05:34:29 +00:00
)}
</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
2026-05-08 05:34:29 +00:00
type="submit"
variant="plain"
shape="none"
2026-05-08 05:34:29 +00:00
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"
2026-05-08 05:34:29 +00:00
>
<FaPaperPlane size={16} />
</Button>
2026-05-08 05:34:29 +00:00
</div>
</form>
</div>
)
}
export default ChatPanel