Skip to content

Commit

Permalink
#IMPLEMENT THE CHAT BOT MODEL ON THE TUTOR DASHBOARD #190 (#201)
Browse files Browse the repository at this point in the history
* Implemented chat bot modal on tutor dashboard,employer and institution

* added chatbot icon base on figma

* build completed
  • Loading branch information
Agbeleshe authored Feb 28, 2025
1 parent e9e3d5c commit 6f5edd8
Show file tree
Hide file tree
Showing 6 changed files with 211 additions and 1 deletion.
3 changes: 3 additions & 0 deletions src/app/dashboard/employer/components/employer-sidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import homeIcon from "@/public/img/tutor icon/homeDashboard.svg";
import jobIcon from "@/public/img/permanent-job.svg";
import notificationIcon from "@/public/img/tutor icon/messageDashboard.svg";
import { DashBoardContext } from "@/app/useContext/dashboardContext";
import ChatBotButton from "@/components/ChatBotButton";

interface NavItemProps {
icon: ReactNode;
Expand Down Expand Up @@ -82,6 +83,8 @@ export function Sidebar() {
active={activeSection === "notifications"}
onClick={() => onSectionChange("notifications")}
/>

<ChatBotButton/>
</nav>
</div>
</aside>
Expand Down
5 changes: 4 additions & 1 deletion src/app/dashboard/institution/components/Sidebar.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
"use client";

import ChatBotButton from "@/components/ChatBotButton";
import avatar from "@/public/org-avatar.svg";
import CandidatesIcon from "@/svg/CandidatesIcon";
import CertificatesIcon from "@/svg/CertificatesIcon";
Expand Down Expand Up @@ -102,6 +103,7 @@ function Sidebar() {
const href = getRouteHref(route);

return (
<>
<Link
href={href}
className={`
Expand All @@ -119,9 +121,10 @@ function Sidebar() {
{route.icon}
</span>
<span className="font-medium">{route.label}</span>
</Link>
</Link></>
);
})}
<ChatBotButton/>
</nav>
<div className="mb-24">
<Link
Expand Down
3 changes: 3 additions & 0 deletions src/app/dashboard/tutor/component/TutorDashboardSidebar.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import notificationIcon from "@/public/img/tutor icon/messageDashboard.svg";
import coursesIcon from "@/public/img/tutor icon/courseDashboard.svg";
import earningIcon from "@/public/img/tutor icon/walletDashboard.svg";
import { DashBoardContext } from "@/app/useContext/dashboardContext";
import ChatBotButton from "@/components/ChatBotButton";

interface NavItemProps {
icon: ReactNode;
Expand Down Expand Up @@ -102,6 +103,8 @@ export function Sidebar() {
active={activeSection === "earnings"}
onClick={() => onSectionChange("earnings")}
/>

<ChatBotButton/>
</nav>
</div>

Expand Down
28 changes: 28 additions & 0 deletions src/components/ChatBotButton.jsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// components/ChatBotButton.tsx
import React, { useState } from 'react';
import ChatbotModal from './ChatbotModal';
import robotic from '../public/img/robotic.svg'
import Image from 'next/image';


const ChatBotButton = () => {
const [isModalOpen, setIsModalOpen] = useState(false);
const openModal = () => setIsModalOpen(true);
const closeModal = () => setIsModalOpen(false);

return (
<>
<button
onClick={openModal}
className="flex items-center px-4 py-2 text-gray-300 hover:text-white hover:bg-[#FFFFFF1A] rounded-lg transition-colors w-full"
>

<Image className='mr-3' alt='robot icon' src={robotic} size={20} />
<span>AI Chatbot</span>
</button>
<ChatbotModal isOpen={isModalOpen} onClose={closeModal} />
</>
);
};

export default ChatBotButton;
163 changes: 163 additions & 0 deletions src/components/ChatbotModal.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
import React, { useState, useRef, useEffect } from 'react';
import { ArrowLeft, Search, MoreVertical, Mic, Smile, Send } from 'lucide-react';
import clsx from 'clsx';

interface Message {
id: string;
text: string;
sender: 'user' | 'bot';
timestamp: string;
}

interface ChatbotModalProps {
isOpen: boolean;
onClose: () => void;
}

const ChatbotModal: React.FC<ChatbotModalProps> = ({ isOpen, onClose }) => {
const [messages, setMessages] = useState<Message[]>([
{
id: '1',
text: "Gm Gm, Satoshi. I have been following your teachings and it's been really helpful to me. I do have a thing to suggest regarding one of your programs",
sender: 'user',
timestamp: '12:43 AM',
},
{
id: '2',
text: "Oh that's awesome. I'm glad my resources have been helpful and I'm open to helpful suggestions.",
sender: 'bot',
timestamp: '12:45 AM',
},
]);
const [inputMessage, setInputMessage] = useState('');
const messagesEndRef = useRef<HTMLDivElement>(null);

// Autoscroll to bottom when messages update
useEffect(() => {
if (messagesEndRef.current) {
messagesEndRef.current.scrollIntoView({ behavior: 'smooth' });
}
}, [messages]);

const handleSendMessage = () => {
if (inputMessage.trim() === '') return;

const newMessage: Message = {
id: Date.now().toString(),
text: inputMessage,
sender: 'user',
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
};

setMessages((prevMessages) => [...prevMessages, newMessage]);
setInputMessage('');

// Simulate bot response (would be replaced with actual API call)
setTimeout(() => {
const botResponse: Message = {
id: (Date.now() + 1).toString(),
text: "I've received your message and will get back to you soon.",
sender: 'bot',
timestamp: new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' }),
};
setMessages((prevMessages) => [...prevMessages, botResponse]);
}, 1000);
};

if (!isOpen) return null;

return (
<>
{/* Blurred dark overlay with 0.5 opacity */}
<div className="fixed inset-0 bg-[#101110] bg-opacity-50 backdrop-blur-md z-40"></div>

{/* Modal container with new dimensions */}
<div className="fixed inset-0 z-50 flex items-center justify-center ">
<div className="bg-[#101110] h-[85%] w-[700px] border border-gray-800 flex flex-col rounded-lg overflow-hidden">
{/* Header */}
<div className="px-4 py-3 flex items-center justify-between border-b border-gray-800">
<div className="flex items-center">
<button onClick={onClose} className="mr-3 text-gray-400 hover:text-gray-300">
<ArrowLeft size={20} />
</button>
<span className="mr-5 text-gray-400">Back</span>
<div className="flex items-center">
<div className="w-6 h-6 bg-white rounded-full mr-2"></div>
<span className="font-medium text-white">Skillnet Chatbot</span>
</div>
</div>
<div className="flex items-center gap-4">
<button className="text-gray-400 hover:text-gray-300">
<Search size={20} />
</button>
<button className="text-gray-400 hover:text-gray-300">
<MoreVertical size={20} />
</button>
</div>
</div>

{/* Chat messages */}
<div className="flex-1 overflow-y-auto p-4 bg-[#101110]">
<div className="space-y-4 flex flex-col justify-end min-h-full">
<div className="mt-auto"></div>
{messages.map((message) => (
<div
key={message.id}
className={clsx(
"max-w-[90%] rounded-lg",
message.sender === 'user'
? "bg-[#202120] ml-auto p-4"
: "bg-[#161716] mr-auto p-4"
)}
>
<div className="text-gray-200">{message.text}</div>
<div className="text-xs text-gray-500 mt-1 text-right flex items-center justify-end">
{message.timestamp}
{message.sender === 'user' && (
<> <svg className="ml-1 w-4 h-4 text-gray-500" xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
<polyline points="20 6 9 17 4 12"></polyline>
</svg>
</>
)}
</div>
</div>
))}
<div ref={messagesEndRef} />
</div>
</div>

{/* Input area */}
<div className="p-4 bg-[#101110]">
<div className="flex items-center rounded-[8px] bg-[#40403E] px-4 py-2 border border-gray-500">
<button className="text-gray-400 mr-2">
<Mic size={20} />
</button>
<button className="text-gray-400 ml-2 mr-4">
<Smile size={20} />
</button>
<input
type="text"
placeholder="Type a message"
className="bg-transparent text-white flex-1 outline-none"
value={inputMessage}
onChange={(e) => setInputMessage(e.target.value)}
onKeyPress={(e) => {
if (e.key === 'Enter') handleSendMessage();
}}
/>

<button
onClick={handleSendMessage}
className="bg-[#A8C789] hover:bg-[#6d9b35] w-8 h-8 rounded-full flex items-center justify-center"
>
<Send size={16} color="black" />
</button>
</div>
</div>
</div>
</div>
</>
);
};

export default ChatbotModal;
10 changes: 10 additions & 0 deletions src/public/img/robotic.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.

0 comments on commit 6f5edd8

Please sign in to comment.