diff --git a/backend/src/models/index.js b/backend/src/models/index.js
index 699fb1d..4213727 100644
--- a/backend/src/models/index.js
+++ b/backend/src/models/index.js
@@ -34,6 +34,11 @@ const chatMessageSchema = new mongoose.Schema({
default: Date.now,
index: true,
},
+ userReaction:{
+ type:String,
+ enum:['like','dislike','none'],
+ default:'none'
+ },
metadata: {
processingTime: Number,
tokensUsed: Number,
diff --git a/backend/src/routes/chat.js b/backend/src/routes/chat.js
index 7af5a09..8f73452 100644
--- a/backend/src/routes/chat.js
+++ b/backend/src/routes/chat.js
@@ -938,6 +938,34 @@ router.post("/documents/train", async (req, res) => {
}
});
+/**
+ * PUT /api/chat/userreaction/:messageId
+ * Update the reaction (like or dislike) for a chat message.
+ */
+router.put('/userreaction/:messageId',async(req,res)=>{
+ try{
+
+ const {messageId}=req.params
+ const {userReaction}=req.body
+
+ if (!messageId){
+ return res.status(404).json({
+ success: false,
+ error: "Message Id is not found",
+ });}
+ const updateMessage=await ChatMessage.findByIdAndUpdate(messageId,{userReaction},{new:true})
+ res.status(200).json(updateMessage);
+
+ }
+ catch(error){
+ logger.error("Error update message reaction", { error: error.message });
+ res.status(500).json({
+ success: false,
+ error: "Failed to update message reaction",
+ });
+ }
+})
+
/**
* GET /api/chat/stats
* Get chatbot statistics
diff --git a/frontend/src/containers/ChatBot/ChatBotWidget.jsx b/frontend/src/containers/ChatBot/ChatBotWidget.jsx
index a8ea556..95f56be 100644
--- a/frontend/src/containers/ChatBot/ChatBotWidget.jsx
+++ b/frontend/src/containers/ChatBot/ChatBotWidget.jsx
@@ -6,15 +6,17 @@ import {
CommentOutlined,
BookOutlined,
QuestionCircleOutlined,
- ClockCircleOutlined ,
+ LikeOutlined,
+ DislikeOutlined
} from "@ant-design/icons";
import { Button, Input, AutoComplete, Dropdown, Menu,Tabs } from "antd";
-import { useEffect, useRef, useState } from "react";
+import { useEffect, useRef, useState,useCallback } from "react";
import ReactMarkdown from "react-markdown";
import { useDispatch, useSelector } from "react-redux";
import styled, { keyframes } from "styled-components";
import { clearMessages, sendMessage } from "./actions";
+import { updateUserReaction } from "./actions";
import {
ADD_MESSAGE,
CLEAR_MESSAGES,
@@ -53,6 +55,16 @@ const FloatingButton = styled(Button)`
}
`;
+const LikeIconsWrapper=styled.div`
+ display:flex;
+ margin-top:10px;
+ align-items:center;
+ gap:15px;
+ margin-left:5px;
+ font-size:16px;
+ font-weight:bold;
+ ;`
+
const ChatPanel = styled.div`
position: fixed;
bottom: 60px;
@@ -347,6 +359,28 @@ const Icon = styled.img`
object-fit: cover;
`;
+const ReactionButton = styled.button`
+ background: none;
+ border: none;
+ cursor: pointer;
+ padding: 4px;
+ border-radius: 4px;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+ transition: all 0.2s ease;
+ color: ${props => props.active ? '#1890ff' : '#666'};
+
+ &:hover {
+ background: #f0f0f0;
+ transform: scale(1.1);
+ }
+
+ &:active {
+ transform: scale(0.95);
+ }
+`;
+
const ActiveIndicator = styled.div`
position: absolute;
bottom: 2px;
@@ -740,6 +774,13 @@ const ChatBotWidget = () => {
setShowSmartSuggestions(value.length === 0 && messages.length > 0);
};
+ const handleReaction = useCallback((messageId, reaction, event) => {
+ event?.preventDefault();
+ dispatch(updateUserReaction(messageId, reaction));
+ }, [dispatch]);
+
+
+
const handleAutoCompleteSelect = (value) => {
setInputValue(value);
setAutoCompleteData([]);
@@ -1042,7 +1083,33 @@ const ChatBotWidget = () => {
>
{message.text}
+
+ handleReaction(message.id, "like", e)}
+ title="Like this response"
+>
+
+
+
+
+ handleReaction(message.id, "dislike")}
+ title="Dislike this response"
+ >
+
+
+
+
{formatTime(
message.timestamp
diff --git a/frontend/src/containers/ChatBot/actions.js b/frontend/src/containers/ChatBot/actions.js
index 1f597af..556aaff 100644
--- a/frontend/src/containers/ChatBot/actions.js
+++ b/frontend/src/containers/ChatBot/actions.js
@@ -6,6 +6,7 @@ import {
SEND_MESSAGE_SUCCESS,
SEND_MESSAGE_ERROR,
CLEAR_MESSAGES,
+ UPDATE_USER_REACTION
} from "./constants";
export function sendMessage(message) {
@@ -55,3 +56,11 @@ export function clearMessages() {
type: CLEAR_MESSAGES,
};
}
+
+export function updateUserReaction(messageId,reaction){
+
+ return {
+ type:UPDATE_USER_REACTION,
+ payload:{messageId,reaction}
+ }
+}
diff --git a/frontend/src/containers/ChatBot/constants.js b/frontend/src/containers/ChatBot/constants.js
index 452cff3..e0a6fc9 100644
--- a/frontend/src/containers/ChatBot/constants.js
+++ b/frontend/src/containers/ChatBot/constants.js
@@ -5,5 +5,6 @@ export const SET_TYPING = "app/ChatBot/SET_TYPING";
export const SEND_MESSAGE_SUCCESS = "app/ChatBot/SEND_MESSAGE_SUCCESS";
export const SEND_MESSAGE_ERROR = "app/ChatBot/SEND_MESSAGE_ERROR";
export const CLEAR_MESSAGES = "app/ChatBot/CLEAR_MESSAGES";
+export const UPDATE_USER_REACTION="app/ChatBot/UPDATE_USER_REACTION"
export const LOAD_MESSAGES_FROM_STORAGE =
"app/ChatBot/LOAD_MESSAGES_FROM_STORAGE";
diff --git a/frontend/src/containers/ChatBot/reducer.js b/frontend/src/containers/ChatBot/reducer.js
index 0881fa6..d29b800 100644
--- a/frontend/src/containers/ChatBot/reducer.js
+++ b/frontend/src/containers/ChatBot/reducer.js
@@ -6,6 +6,7 @@ import {
SEND_MESSAGE_ERROR,
CLEAR_MESSAGES,
LOAD_MESSAGES_FROM_STORAGE,
+ UPDATE_USER_REACTION,
} from "./constants";
export const initialState = {
@@ -48,6 +49,16 @@ const chatBotReducer = (state = initialState, action) =>
draft.sessionId = null;
draft.error = null;
break;
+ case UPDATE_USER_REACTION: {
+ const { messageId, reaction } = action.payload;
+ const msg = draft.messages.find((m) => m.id === messageId);
+ if (msg) {
+ msg.userReaction = reaction;
+ }
+ break;
+ }
+
+
}
});
diff --git a/frontend/src/containers/ChatBot/saga.js b/frontend/src/containers/ChatBot/saga.js
index 84306ce..11c2956 100644
--- a/frontend/src/containers/ChatBot/saga.js
+++ b/frontend/src/containers/ChatBot/saga.js
@@ -1,5 +1,5 @@
import { takeLatest, put, call, select } from "redux-saga/effects";
-import { SEND_MESSAGE, SEND_BOT_MESSAGE } from "./constants";
+import { SEND_MESSAGE, SEND_BOT_MESSAGE,UPDATE_USER_REACTION } from "./constants";
import {
addMessage,
setTyping,
@@ -47,7 +47,7 @@ export function* handleSendMessage(action) {
if (response.success) {
// Add bot response to chat
const botMessage = {
- id: Date.now() + 1,
+ id: response.data.message.id,
text:
response.data.message.content ||
"I received your message!",
@@ -132,7 +132,7 @@ export function* handleSendMessage(action) {
export function* handleSendBotMessage(action) {
const botMessage = {
- id: Date.now(),
+ id: response.data.message.id,
text: action.payload,
sender: "bot",
timestamp: new Date().toISOString(),
@@ -140,7 +140,32 @@ export function* handleSendBotMessage(action) {
yield put(addMessage(botMessage));
}
+
+export function* handleUpdateUserReaction(action) {
+ const { messageId, reaction } = action.payload;
+
+ try {
+ const response = yield call(chatService.updateReaction, messageId, reaction);
+
+
+ if (response.success) {
+ yield put({
+ type: "UPDATE_USER_REACTION_SUCCESS",
+ payload: { messageId, reaction },
+ });
+}
+
+else {
+ console.error("Failed to update reaction:", response.error);
+ }
+ } catch (error) {
+ console.error("Error updating reaction:", error);
+ }
+}
+
+
export default function* chatBotSaga() {
yield takeLatest(SEND_MESSAGE, handleSendMessage);
yield takeLatest(SEND_BOT_MESSAGE, handleSendBotMessage);
+ yield takeLatest(UPDATE_USER_REACTION, handleUpdateUserReaction);
}
diff --git a/frontend/src/services/chatService.js b/frontend/src/services/chatService.js
index 91261d8..08c626f 100644
--- a/frontend/src/services/chatService.js
+++ b/frontend/src/services/chatService.js
@@ -24,27 +24,19 @@ export const chatService = {
) {
throw new Error("Message cannot be empty");
}
-
- // Prepare the request data, excluding undefined values
const requestData = {
message: messageData.message.trim(),
provider: messageData.provider || "gemini",
- useRag:
- messageData.useRag !== undefined
- ? messageData.useRag
- : true,
+ useRag: messageData.useRag !== undefined ? messageData.useRag : true,
topK: messageData.topK || 5,
- };
-
+ };
// Only include sessionId if it exists
if (messageData.sessionId) {
requestData.sessionId = messageData.sessionId;
}
-
- console.log("Sending request data:", requestData); // Debug log
-
+
const response = await api.post("/chat/message", requestData);
-
+
return {
success: true,
data: response.data,
@@ -57,7 +49,6 @@ export const chatService = {
};
}
},
-
/**
* Get chat history for a session
* @param {string} sessionId - The session ID
@@ -79,6 +70,29 @@ export const chatService = {
}
},
+
+ /**
+ * updated user reaction
+ * @param {string} messageId, - The message Id
+ */
+
+ async updateReaction(messageId, reaction) {
+ try {
+ const res = await api.put(`/chat/userreaction/${messageId}`, { userReaction: reaction });
+ return {
+ success: true,
+ data: res.data,
+ };
+ } catch (error) {
+ console.error("Error updating reaction:", error);
+ return {
+ success: false,
+ error: error.response?.data?.message || error.message,
+ };
+ }
+ },
+
+
/**
* Create a new chat session
* @returns {Promise