From 24c04f742263f82760df0995d8f3f8ab0d3b06ee Mon Sep 17 00:00:00 2001 From: subash Date: Wed, 14 Aug 2024 22:22:07 -0700 Subject: [PATCH] feat : chat bot integrated with queries --- package.json | 9 ++-- server/routes/student.js | 6 --- src/components/Chatbot/Actionprovider.js | 56 ++++++++++++++++++++++++ src/components/Chatbot/Chatmain.js | 45 +++++++++++++++++++ src/components/Chatbot/Messageparser.js | 34 ++++++++++++++ src/components/Chatbot/ProductOption.js | 55 +++++++++++++++++++++++ src/components/Chatbot/chat.css | 27 ++++++++++++ src/components/Chatbot/config.js | 28 ++++++++++++ src/pages/Home.jsx | 2 + src/pages/SectionPage.jsx | 2 + 10 files changed, 255 insertions(+), 9 deletions(-) create mode 100644 src/components/Chatbot/Actionprovider.js create mode 100644 src/components/Chatbot/Chatmain.js create mode 100644 src/components/Chatbot/Messageparser.js create mode 100644 src/components/Chatbot/ProductOption.js create mode 100644 src/components/Chatbot/chat.css create mode 100644 src/components/Chatbot/config.js diff --git a/package.json b/package.json index 924e778..eb5f95f 100644 --- a/package.json +++ b/package.json @@ -4,9 +4,10 @@ "private": true, "dependencies": { "@emailjs/browser": "^4.3.3", - "@emotion/react": "^11.11.4", - "@emotion/styled": "^11.11.5", - "@mui/material": "^5.16.1", + "@emotion/react": "^11.13.0", + "@emotion/styled": "^11.13.0", + "@mui/icons-material": "^5.16.7", + "@mui/material": "^5.16.7", "@react-icons/all-files": "^4.1.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", @@ -17,6 +18,7 @@ "framer-motion": "^11.3.2", "jwt-decode": "^4.0.0", "react": "^18.2.0", + "react-chatbot-kit": "^2.2.2", "react-dom": "^18.2.0", "react-hot-toast": "^2.4.1", "react-icons": "^4.12.0", @@ -26,6 +28,7 @@ "react-scripts": "5.0.1", "react-spinners": "^0.13.8", "react-toastify": "^9.1.3", + "styled-components": "^6.1.12", "tailwind-merge": "^2.4.0", "web-vitals": "^2.1.4" }, diff --git a/server/routes/student.js b/server/routes/student.js index bd70acc..9b4eaf9 100644 --- a/server/routes/student.js +++ b/server/routes/student.js @@ -2,11 +2,8 @@ const express = require("express"); const { auth, studentAuth, isCanteen } = require("../middlewares/auth"); const router = express.Router(); const authController = require("../controllers/Auth"); -<<<<<<< HEAD const { getCanteenData } = require("../controllers/canteenController"); -======= const feedbackController = require("../controllers/feedbackController"); ->>>>>>> 56cd98b40c82e9849270fe2c43ef735b8fe058bc router.post("/studentSignup", authController.studentSignup); router.post("/studentLogin", authController.studentLogin); @@ -17,12 +14,9 @@ router.get("/resetPassword/:id/:token", authController.verifyLink); router.post("/newPassword/:id/:token", authController.resetPassword); router.get("/studentLogout", studentAuth, authController.studentLogout); router.get("/canteenLogout", auth, authController.canteenLogout); -<<<<<<< HEAD router.get("/canteen/:id", getCanteenData); -======= router.post('/submitFeedback', feedbackController.submitFeedback); ->>>>>>> 56cd98b40c82e9849270fe2c43ef735b8fe058bc router.post( "/changeStudentPassword", studentAuth, diff --git a/src/components/Chatbot/Actionprovider.js b/src/components/Chatbot/Actionprovider.js new file mode 100644 index 0000000..c5e75ed --- /dev/null +++ b/src/components/Chatbot/Actionprovider.js @@ -0,0 +1,56 @@ +class ActionProvider { + constructor(createChatBotMessage, setStateFunc) { + this.createChatBotMessage = createChatBotMessage; + this.setState = setStateFunc; + } + + handleMenu = () => { + const message = this.createChatBotMessage("You can explore our canteen menus with various food options tailored to your taste. Would you like to see today's menu?"); + this.updateChatbotState(message); + }; + + handleOrder = () => { + const message = this.createChatBotMessage("You can place an order directly from the menu. Let me guide you through the process."); + this.updateChatbotState(message); + }; + + handleDelivery = () => { + const message = this.createChatBotMessage("You can track your order status in real-time. Would you like to check your current order?"); + this.updateChatbotState(message); + }; + + handleDiscounts = () => { + const message = this.createChatBotMessage("We have special offers available today! Want to hear about them?"); + this.updateChatbotState(message); + }; + + handlePayment = () => { + const message = this.createChatBotMessage("We accept multiple payment methods. Need help with the checkout process?"); + this.updateChatbotState(message); + }; + + handleAccount = () => { + const message = this.createChatBotMessage("You can manage your account settings or update your profile. Need assistance with something?"); + this.updateChatbotState(message); + }; + + handleSupport = () => { + const message = this.createChatBotMessage("If you need any help, our support team is here for you. How can I assist you?"); + this.updateChatbotState(message); + }; + + handleUnknown = () => { + const message = this.createChatBotMessage("I'm sorry, I didn't understand that. Could you please rephrase?"); + this.updateChatbotState(message); + }; + + updateChatbotState(message) { + this.setState((prevState) => ({ + ...prevState, + messages: [...prevState.messages, message], + })); + } + } + + export default ActionProvider; + \ No newline at end of file diff --git a/src/components/Chatbot/Chatmain.js b/src/components/Chatbot/Chatmain.js new file mode 100644 index 0000000..677011b --- /dev/null +++ b/src/components/Chatbot/Chatmain.js @@ -0,0 +1,45 @@ +import React from 'react' +import Chatbot from 'react-chatbot-kit' +import { useState } from 'react' +import 'react-chatbot-kit/build/main.css' +import config from './config' +import MessageParser from './Messageparser' +import ActionProvider from './Actionprovider' +import MarkUnreadChatAltIcon from '@mui/icons-material/MarkUnreadChatAlt'; +import CloseIcon from '@mui/icons-material/Close'; +import './chat.css' +import { createChatBotMessage } from 'react-chatbot-kit' + + +export const Chatmain = () => { + + const [showchat , setShowchat] = useState(false) + const initialMessages = [ + createChatBotMessage(`Hello! 👋 Welcome to Foodies . How can I help you today?`, { + widget: "productOptions", + }), + ] + + const botName = 'Foodies bot' + const updatedconfig = { + ...config , + botName , + initialMessages + } + return ( + <> +
+ +
setShowchat(prev => !prev)} className='chat-toggle-button mr-3 bg-blue-500 fixed p-2 rounded-full cursor-pointer hover:shadow-lg hover:scale-105 ease-in-out bottom-6'> + {!showchat ? : } +
+ +
+ + +
+ +
+ + ) +} diff --git a/src/components/Chatbot/Messageparser.js b/src/components/Chatbot/Messageparser.js new file mode 100644 index 0000000..b6820f5 --- /dev/null +++ b/src/components/Chatbot/Messageparser.js @@ -0,0 +1,34 @@ +class MessageParser { + constructor(actionProvider) { + this.actionProvider = actionProvider; + } + + parse(message) { + const lowerCaseMessage = message.toLowerCase(); + + if (this.containsKeywords(lowerCaseMessage, ["menu", "food", "canteen", "dining"])) { + this.actionProvider.handleMenu(); + } else if (this.containsKeywords(lowerCaseMessage, ["order", "place order", "buy"])) { + this.actionProvider.handleOrder(); + } else if (this.containsKeywords(lowerCaseMessage, ["delivery", "track order", "status"])) { + this.actionProvider.handleDelivery(); + } else if (this.containsKeywords(lowerCaseMessage, ["discount", "offer", "deal"])) { + this.actionProvider.handleDiscounts(); + } else if (this.containsKeywords(lowerCaseMessage, ["payment", "checkout", "billing"])) { + this.actionProvider.handlePayment(); + } else if (this.containsKeywords(lowerCaseMessage, ["account", "profile", "settings"])) { + this.actionProvider.handleAccount(); + } else if (this.containsKeywords(lowerCaseMessage, ["support", "help", "contact"])) { + this.actionProvider.handleSupport(); + } else { + this.actionProvider.handleUnknown(); + } + } + + containsKeywords(message, keywords) { + return keywords.some(keyword => message.includes(keyword)); + } + } + + export default MessageParser; + \ No newline at end of file diff --git a/src/components/Chatbot/ProductOption.js b/src/components/Chatbot/ProductOption.js new file mode 100644 index 0000000..bb9da12 --- /dev/null +++ b/src/components/Chatbot/ProductOption.js @@ -0,0 +1,55 @@ +import React from 'react'; +import LaunchRoundedIcon from '@mui/icons-material/LaunchRounded'; +import styled from 'styled-components'; + +const Button = styled.button` + + background-color: #A9A9A9; /* Change to a more vibrant color */ + color: white; + border: none; + border-radius: 5px; + padding: 4px 10px; + margin: 8px; + font-size: 12px; + font-weight: 400; + cursor: pointer; + transition: background-color 0.3s, transform 0.2s; + + + &:hover { + background-color: #808080; /* Slightly darker shade on hover */ + transform: scale(1.05); /* Slight zoom effect */ + } + + &:focus { + outline: none; + } + + svg { + margin-right:3px; /* Space between icon and text */ + } +`; + +const OptionsContainer = styled.div` + margin-left : 80px +`; + +const ProductOptions = (props) => { + //"menu", "food", "canteen", "dining" + const options = [ + { text: "Menu", handler: props.actionProvider.handleMenu, id: 1 }, + { text: "Order", handler: props.actionProvider.handleOrder, id: 2 }, + { text: "Status", handler: props.actionProvider.handleDelivery, id: 3 }, + { text: "Help", handler: props.actionProvider.handleSupport, id: 4 }, + ]; + + const optionsMarkup = options.map((option) => ( + + )); + + return {optionsMarkup}; +}; + +export default ProductOptions; \ No newline at end of file diff --git a/src/components/Chatbot/chat.css b/src/components/Chatbot/chat.css new file mode 100644 index 0000000..246253c --- /dev/null +++ b/src/components/Chatbot/chat.css @@ -0,0 +1,27 @@ + +.chatbot-container { + transition: transform 0.3s ease-in-out, opacity 0.3s ease-in-out; + transform: translateY(100%); + opacity: 0; + z-index: 1000; /* Ensure the chatbot is on top */ + border-radius: 8px; + /* Add border radius if needed */ + } + + .chatbot-show { + transform: translateY(0); + opacity: 1; + } + + .chatbot-hide { + transform: translateY(100%); + opacity: 0; + } + + .chat-toggle-button { + z-index: 1100; + /* Higher than chatbot-container */ + } + + + diff --git a/src/components/Chatbot/config.js b/src/components/Chatbot/config.js new file mode 100644 index 0000000..32911ff --- /dev/null +++ b/src/components/Chatbot/config.js @@ -0,0 +1,28 @@ +import { createChatBotMessage } from 'react-chatbot-kit'; +import ProductOptions from './ProductOption'; + + +const config = { + botName: "Leads Bot", + initialMessages: [ + createChatBotMessage("Hello! Welcome to Leads . How can I help you today?", { + widget: "productOptions", + }), + ], + widgets: [ + { + widgetName: "productOptions", + widgetFunc: (props) => , + }, + ], + customStyles: { + botMessageBox: { + backgroundColor: "#007FFF" + }, + chatButton: { + backgroundColor: "", + }, + } +} + +export default config \ No newline at end of file diff --git a/src/pages/Home.jsx b/src/pages/Home.jsx index 903e96d..d0adaca 100644 --- a/src/pages/Home.jsx +++ b/src/pages/Home.jsx @@ -10,6 +10,7 @@ import Footer from "../components/Footer"; import FloatBtn from "../components/FloatBtn/FloatBtn"; import { useAuth } from "../authContext"; import { useNavigate } from "react-router-dom"; +import { Chatmain } from "../components/Chatbot/Chatmain"; function Home() { const navigate = useNavigate(); const { isAuthenticated } = useAuth(); @@ -136,6 +137,7 @@ function Home() {
+