Skip to content

Commit 068372a

Browse files
authored
Merge pull request #79 from AET-DevOps25/genai/group-chat-and-document-processing
Genai/group chat and document processing
2 parents 80d290f + 2758c2b commit 068372a

File tree

22 files changed

+1876
-269
lines changed

22 files changed

+1876
-269
lines changed

client/src/pages/group_info/GroupPage.tsx

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ import { GroupInfo } from "./components/GroupInfo";
77
import { Material } from "./Material";
88
import "./group_page.css";
99
import AIChat from "./components/AIChat";
10+
import { Chat } from "./components/GroupChat";
11+
import { HandwrittenDocuments } from "./components/HandwrittenDocuments";
1012

1113
export default function GroupPage() {
1214
const { groupId } = useParams<{ groupId: string }>();
@@ -95,7 +97,7 @@ export default function GroupPage() {
9597
useEffect(() => {
9698
const base = ["Group Info"];
9799
if (hasAccess()) {
98-
base.push("Materials", "Chats", "AI Bot");
100+
base.push("Materials", "Handwritten Docs", "Chats", "AI Bot");
99101
}
100102
setTabs(base);
101103

@@ -176,9 +178,19 @@ export default function GroupPage() {
176178
)
177179
)}
178180

181+
{activeTab === "Handwritten Docs" && (
182+
hasAccess() ? (
183+
<HandwrittenDocuments />
184+
) : (
185+
<p className="access-message">
186+
You must be a member (or owner) to access Handwritten Documents.
187+
</p>
188+
)
189+
)}
190+
179191
{activeTab === "Chats" && (
180192
hasAccess() ? (
181-
<p>(Your Chats UI…)</p>
193+
<Chat />
182194
) : (
183195
<p className="access-message">
184196
You must be a member (or owner) to access Chats.
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
//TODO: implement a page to chat with people in the study group
2-
export function Create() {
3-
return <></>;
4-
}
1+
//TODO: implement a page to chat with people in the study group
2+
export function Create() {
3+
return <></>;
4+
}
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
import { useEffect, useState, useRef } from "react";
2+
import { useParams } from "react-router-dom";
3+
import { useAuth } from "../../../auth/AuthProvider";
4+
import { ChatMessage, getGroupChatMessages, sendChatMessage, deleteGroupChat } from "../../../services/groupApi";
5+
import { useGroup } from "../../home/components/GroupProvider";
6+
import "./group_chat.css";
7+
8+
export const Chat = () => {
9+
const { groupId } = useParams<{ groupId: string }>();
10+
const { user, token } = useAuth();
11+
const { currentGroup } = useGroup();
12+
const [messages, setMessages] = useState<ChatMessage[]>([]);
13+
const [newMessage, setNewMessage] = useState("");
14+
const [error, setError] = useState<string | null>(null);
15+
const messagesEndRef = useRef<HTMLDivElement>(null);
16+
17+
const scrollToBottom = () => {
18+
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
19+
};
20+
21+
useEffect(() => {
22+
if (groupId && token) {
23+
getGroupChatMessages(groupId, token)
24+
.then(setMessages)
25+
.catch(() => setError("Failed to load messages."));
26+
}
27+
}, [groupId, token]);
28+
29+
useEffect(scrollToBottom, [messages]);
30+
31+
const handleSendMessage = async (e: React.FormEvent) => {
32+
e.preventDefault();
33+
if (!newMessage.trim() || !groupId || !token) return;
34+
35+
try {
36+
const sentMessage = await sendChatMessage(groupId, newMessage, token);
37+
setMessages([...messages, sentMessage]);
38+
setNewMessage("");
39+
} catch {
40+
setError("Failed to send message.");
41+
}
42+
};
43+
44+
const handleDeleteChat = async () => {
45+
if (!groupId || !token) return;
46+
47+
if (window.confirm("Are you sure you want to delete the entire chat history for this group? This cannot be undone.")) {
48+
try {
49+
await deleteGroupChat(groupId, token);
50+
setMessages([]);
51+
} catch {
52+
setError("Failed to delete chat.");
53+
}
54+
}
55+
};
56+
57+
return (
58+
<div className="chat-container">
59+
<h3>Group Chat</h3>
60+
{error && <p className="error-message">{error}</p>}
61+
<div className="messages-list">
62+
{messages.map((msg) => (
63+
<div key={msg.id} className={`message-item ${msg.username === user ? "sent" : "received"}`}>
64+
<div className="message-content">
65+
<strong>{msg.username}</strong>
66+
<p>{msg.content}</p>
67+
<span className="timestamp">{new Date(msg.timestamp).toLocaleTimeString()}</span>
68+
</div>
69+
</div>
70+
))}
71+
<div ref={messagesEndRef} />
72+
</div>
73+
<form onSubmit={handleSendMessage} className="message-form">
74+
<input
75+
type="text"
76+
value={newMessage}
77+
onChange={(e) => setNewMessage(e.target.value)}
78+
placeholder="Type a message..."
79+
/>
80+
<button type="submit">Send</button>
81+
</form>
82+
{currentGroup?.ownerUsername === user && (
83+
<button onClick={handleDeleteChat} className="delete-chat-btn">
84+
Delete Chat History
85+
</button>
86+
)}
87+
</div>
88+
);
89+
};

0 commit comments

Comments
 (0)