feat(chat): Integrate chatbot API for dynamic responses
This commit replaces the static, simulated chat functionality with a live integration to a chatbot backend API. The chat page now sends user messages to a webhook endpoint using the `fetch` API. It implements session management by generating and storing a `sessionId` in `localStorage` to maintain conversation context between requests. Key changes: - Implement `async` `sendMessage` function to post to the chatbot API. - Add session ID generation and persistence. - Dynamically render text and image responses from the API. - Remove hardcoded example messages from the HTML. - Update the virtual assistant's name to "Maya". - Fix navigation links from the dashboard to the chat page.
This commit is contained in:
@@ -16,31 +16,31 @@
|
||||
<link rel="stylesheet" href="styles/main.css">
|
||||
</head>
|
||||
<body style="font-family: Inter, 'Noto Sans', sans-serif; display: flex; flex-direction: column; min-height: 100vh; padding: 0; background: linear-gradient(135deg, #0077b6, #023e8a) !important;">
|
||||
<header>
|
||||
<div class="mobile-header-user-info">
|
||||
<div
|
||||
<header>
|
||||
<div class="mobile-header-user-info">
|
||||
<div
|
||||
class="mobile-header-avatar"
|
||||
style='background-image: url("https://lh3.googleusercontent.com/aida-public/AB6AXuDdsEbNptWuGWnUFVjxjJbETG3Ux0dsBq6vJXBqGqxirKQZ5h08CrhYiwt89C2-bjXZjh3bpwhhheIQH7TY4OfQvZjIE93FvpVViGxSvYuMDJylveD2lc-daeSlCOr8t64jpRbHrEXM0JGuM-CGz99i7dCKdfgcBu7EEecYOxvaPyTNOskRBL3yUkN9tJ659LAKvkEeum2-SYZ1htR83YgVFVP-n8-XoZBoQaa5W7vOC0TZtlOldU-Cq8EkbxM_HQH3prpaomyTJdCF");'
|
||||
></div>
|
||||
<h2 class="mobile-header-title">BeautyBot Analytics</h2>
|
||||
</div>
|
||||
<div class="mobile-header-right">
|
||||
<button class="mobile-header-menu-button">
|
||||
></div>
|
||||
<h2 class="mobile-header-title">BeautyBot Analytics</h2>
|
||||
</div>
|
||||
<div class="mobile-header-right">
|
||||
<button class="mobile-header-menu-button">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" fill="currentColor" viewBox="0 0 256 256">
|
||||
<path
|
||||
d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM40,72H216a8,8,0,0,0,0-16H40a8,8,0,0,0,0,16ZM216,184H40a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Z"
|
||||
></path>
|
||||
<path
|
||||
d="M224,128a8,8,0,0,1-8,8H40a8,8,0,0,1,0-16H216A8,8,0,0,1,224,128ZM40,72H216a8,8,0,0,0,0-16H40a8,8,0,0,0,0,16ZM216,184H40a8,8,0,0,0,0,16H216a8,8,0,0,0,0-16Z"
|
||||
></path>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="dropdown-menu hidden">
|
||||
</button>
|
||||
<div class="dropdown-menu hidden">
|
||||
<button class="control-button">
|
||||
<span class="truncate">Ekspor Data</span>
|
||||
<span class="truncate">Ekspor Data</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<main>
|
||||
<main class="container mx-auto px-4">
|
||||
<div class="layout-content-container">
|
||||
<h2 class="text-[#141414] tracking-light text-[28px] font-bold leading-tight px-4 text-left pb-3 pt-5">Chatbot Performance Overview</h2>
|
||||
<div class="controls-container">
|
||||
@@ -229,6 +229,7 @@
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<script src="scripts/main.js"></script>
|
||||
<!-- Floating circles background -->
|
||||
<ul class="floating-circles">
|
||||
<li></li><li></li><li></li><li></li><li></li>
|
||||
|
||||
@@ -4,13 +4,13 @@ const dropdownMenu = document.querySelector('.dropdown-menu');
|
||||
|
||||
if (menuButton && dropdownMenu) {
|
||||
menuButton.addEventListener('click', function() {
|
||||
dropdownMenu.classList.toggle('visible');
|
||||
dropdownMenu.classList.toggle('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
// Close dropdown when clicking outside
|
||||
document.addEventListener('click', function(event) {
|
||||
if (!event.target.closest('.mobile-header-right') && dropdownMenu) {
|
||||
dropdownMenu.classList.remove('visible');
|
||||
dropdownMenu.classList.add('hidden');
|
||||
}
|
||||
});
|
||||
|
||||
@@ -18,6 +18,14 @@ body {
|
||||
padding: 0 20px; /* Tambahan padding horizontal */
|
||||
}
|
||||
|
||||
/* Container for responsive design */
|
||||
.container {
|
||||
width: 100%;
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
padding: 0 15px;
|
||||
}
|
||||
|
||||
/* Universal Header (works for both desktop and mobile) */
|
||||
header {
|
||||
position: sticky;
|
||||
@@ -27,18 +35,19 @@ header {
|
||||
backdrop-filter: blur(35px);
|
||||
border-radius: 0 0 20px 20px;
|
||||
margin: 0;
|
||||
padding: 20px 25px; /* Increased vertical padding */
|
||||
padding: 20px 25px;
|
||||
box-shadow: 0 5px 25px rgba(0, 0, 0, 0.15);
|
||||
min-height: 110px; /* Significantly taller header */
|
||||
min-height: 110px;
|
||||
width: 100%;
|
||||
max-width: 100%;
|
||||
display: flex;
|
||||
flex-wrap: wrap; /* Allow elements to wrap on smaller screens */
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
gap: 15px; /* Consistent spacing between elements */
|
||||
gap: 15px;
|
||||
}
|
||||
|
||||
|
||||
/* Universal Header Elements */
|
||||
.mobile-header-user-info {
|
||||
display: flex;
|
||||
@@ -253,12 +262,37 @@ th:nth-child(3), td:nth-child(3) { width: 30%; }
|
||||
|
||||
/* Responsivitas */
|
||||
@media (max-width: 768px) {
|
||||
/* Show mobile elements, hide desktop nav */
|
||||
.mobile-header-user-info,
|
||||
.mobile-header-right {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.desktop-nav {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* Stack cards vertically on mobile */
|
||||
#stat-cards, #secondary-stats {
|
||||
grid-template-columns: 1fr;
|
||||
}
|
||||
|
||||
/* Adjust header layout for mobile */
|
||||
header {
|
||||
flex-direction: column;
|
||||
align-items: flex-start;
|
||||
padding: 15px;
|
||||
}
|
||||
|
||||
.mobile-header-right {
|
||||
align-self: flex-end;
|
||||
margin-top: -50px;
|
||||
}
|
||||
|
||||
body {
|
||||
padding: 0 10px;
|
||||
}
|
||||
|
||||
/* Removed mobile-specific scaling as we now have universal styles */
|
||||
|
||||
/* Stat Cards */
|
||||
#stat-cards, #secondary-stats {
|
||||
flex-direction: column;
|
||||
@@ -285,24 +319,35 @@ th:nth-child(3), td:nth-child(3) { width: 30%; }
|
||||
}
|
||||
}
|
||||
|
||||
@media (min-width: 769px) {
|
||||
/* Adjust header layout for desktop */
|
||||
header {
|
||||
padding: 15px 25px;
|
||||
}
|
||||
|
||||
.mobile-header-user-info {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
.mobile-header-right {
|
||||
display: flex;
|
||||
}
|
||||
}
|
||||
|
||||
/* Definitive Vertical Layout */
|
||||
.controls-container,
|
||||
.card-container {
|
||||
display: block;
|
||||
}
|
||||
|
||||
/* Definitive Horizontal Layout for Stat Cards */
|
||||
/* Responsive Layout for Cards */
|
||||
#stat-cards, #secondary-stats {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 20px;
|
||||
}
|
||||
|
||||
#stat-cards > div, #secondary-stats > div {
|
||||
flex: 1; /* Ensure cards share space equally */
|
||||
}
|
||||
|
||||
/* Ensure cards within the container stack vertically */
|
||||
.card-container > div {
|
||||
margin-bottom: 20px; /* Add space between vertical cards */
|
||||
|
||||
Reference in New Issue
Block a user