your message

This commit is contained in:
root
2026-02-06 14:53:52 +00:00
parent c809d049fe
commit 3d488f22b7
47 changed files with 3127 additions and 425 deletions

View File

@ -0,0 +1,100 @@
'use client';
import { useEffect, useRef, useState } from 'react';
import { useParams } from 'next/navigation';
import { io, Socket } from 'socket.io-client';
import { Send } from 'lucide-react';
import { Button } from '@/components/ui/button';
import { Card, CardContent, CardHeader, CardTitle } from '@/components/ui/card';
import { api } from '@/lib/api';
import { getWsBaseUrl } from '@/lib/ws';
export default function InviteGroupPage() {
const params = useParams();
const groupId = params?.groupId as string;
const [messages, setMessages] = useState<any[]>([]);
const [members, setMembers] = useState<any[]>([]);
const [message, setMessage] = useState('');
const socketRef = useRef<Socket | null>(null);
useEffect(() => {
if (!groupId) return;
(async () => {
await api.joinGroupByInvite(groupId).catch(() => null);
const [msgs, mbrs] = await Promise.all([
api.getGroupMessages(groupId).catch(() => []),
api.getGroupMembers(groupId).catch(() => []),
]);
setMessages(msgs);
setMembers(mbrs);
})();
}, [groupId]);
useEffect(() => {
if (!groupId) return;
const token =
typeof window !== 'undefined' ? sessionStorage.getItem('coursecraft_api_token') || undefined : undefined;
const socket = io(`${getWsBaseUrl()}/ws/course-groups`, {
transports: ['websocket'],
auth: { token },
});
socketRef.current = socket;
socket.emit('groups:join', { groupId });
socket.on('groups:new-message', (msg: any) => setMessages((prev) => [...prev, msg]));
return () => {
socket.disconnect();
socketRef.current = null;
};
}, [groupId]);
const send = async () => {
if (!groupId || !message.trim()) return;
await api.sendGroupMessage(groupId, message.trim());
setMessage('');
};
return (
<div className="grid gap-4 lg:grid-cols-[1fr_320px]">
<Card className="min-h-[460px]">
<CardHeader>
<CardTitle>Групповой чат курса</CardTitle>
</CardHeader>
<CardContent className="flex h-[400px] flex-col">
<div className="flex-1 overflow-auto space-y-2 pr-2">
{messages.map((msg) => (
<div key={msg.id} className="rounded-md border p-2 text-sm">
<p className="font-medium">{msg.user?.name || 'Участник'}</p>
<p>{msg.content}</p>
</div>
))}
</div>
<div className="mt-3 flex gap-2">
<input
value={message}
onChange={(e) => setMessage(e.target.value)}
className="flex-1 rounded-md border bg-background px-3 py-2 text-sm"
placeholder="Сообщение"
/>
<Button onClick={send}>
<Send className="h-4 w-4" />
</Button>
</div>
</CardContent>
</Card>
<Card>
<CardHeader>
<CardTitle>Участники ({members.length})</CardTitle>
</CardHeader>
<CardContent className="space-y-2">
{members.map((member) => (
<div key={member.id} className="rounded-md border p-2 text-sm">
<p className="font-medium">{member.user?.name || member.user?.email}</p>
<p className="text-xs text-muted-foreground">{member.role}</p>
</div>
))}
</CardContent>
</Card>
</div>
);
}