Spaces:
Running
Running
File size: 23,462 Bytes
ead5792 db2676d ead5792 db2676d ead5792 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat | Admin Pulse</title>
<link rel="stylesheet" href="style.css">
<script src="https://cdn.tailwindcss.com"></script>
<script src="https://cdn.jsdelivr.net/npm/feather-icons/dist/feather.min.js"></script>
<script src="https://unpkg.com/feather-icons"></script>
<script src="components/navbar.js"></script>
<script src="components/sidebar.js"></script>
</head>
<body class="bg-gray-100">
<custom-header></custom-header>
<custom-navbar></custom-navbar>
<div class="flex">
<custom-sidebar></custom-sidebar>
<main class="flex-1 p-8">
<div class="flex justify-between items-center mb-6">
<h1 class="text-2xl font-bold">AI Assistant Chat</h1>
<div class="flex items-center space-x-4">
<span class="text-gray-600">Session: <span id="currentSession" class="font-bold">1</span></span>
<button id="newChatBtn" class="bg-green-600 text-white px-4 py-2 rounded-lg flex items-center hover:bg-green-700 transition">
<i data-feather="plus" class="mr-2"></i>
New Chat
</button>
</div>
</div>
<div class="grid grid-cols-1 lg:grid-cols-4 gap-6 h-[calc(100vh-180px)]">
<!-- Left sidebar for topics and history -->
<div class="lg:col-span-1 flex flex-col space-y-6">
<!-- Topics Section -->
<div class="bg-white rounded-lg shadow p-4 h-1/2 overflow-hidden flex flex-col">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-semibold text-gray-800">Topics</h3>
<i data-feather="tag" class="text-green-500"></i>
</div>
<div class="overflow-y-auto flex-1 pr-2" id="topicsContainer">
<!-- Topics will be loaded via API -->
<div class="space-y-2">
<div class="text-center py-4 text-gray-500" id="topicsLoading">
<i data-feather="loader" class="animate-spin mx-auto"></i>
<p class="mt-2">Loading topics...</p>
</div>
</div>
</div>
</div>
<!-- Chat History -->
<div class="bg-white rounded-lg shadow p-4 h-1/2 overflow-hidden flex flex-col">
<div class="flex items-center justify-between mb-3">
<h3 class="text-lg font-semibold text-gray-800">Your Chats</h3>
<i data-feather="clock" class="text-blue-500"></i>
</div>
<div class="overflow-y-auto flex-1 pr-2" id="chatHistory">
<div class="space-y-2">
<button class="session-btn w-full text-left p-3 rounded-lg bg-green-50 border border-green-200 text-green-700 font-medium" data-session="1">
<div class="flex justify-between items-center">
<span>Chat 1</span>
<span class="text-xs text-gray-500">Just now</span>
</div>
<p class="text-sm text-gray-600 truncate">Welcome to the assistant</p>
</button>
</div>
</div>
</div>
</div>
<!-- Chat Area -->
<div class="lg:col-span-3 flex flex-col">
<div class="bg-white rounded-lg shadow flex-1 overflow-hidden flex flex-col">
<!-- Chat Header -->
<div class="bg-gradient-to-r from-green-500 to-green-600 p-4 text-white">
<div class="flex items-center space-x-3">
<div class="w-10 h-10 rounded-full bg-white flex items-center justify-center">
<i data-feather="message-circle" class="text-green-600"></i>
</div>
<div>
<h2 class="text-xl font-bold">FoodSave AI Assistant</h2>
<p class="text-green-100 text-sm">Online - Ready to help with food waste reduction</p>
</div>
</div>
</div>
<!-- Chat Messages -->
<div class="flex-1 p-6 overflow-y-auto" id="chatMessages">
<div class="message bot mb-4 max-w-[80%]">
<div class="bg-gray-100 p-4 rounded-2xl rounded-tl-none">
<div class="flex items-center mb-1">
<div class="w-6 h-6 rounded-full bg-green-500 flex items-center justify-center mr-2">
<i data-feather="bot" class="w-3 h-3 text-white"></i>
</div>
<span class="font-semibold text-gray-700">Assistant</span>
</div>
<p class="text-gray-800">Hello! 👋 Welcome to the Admin Pulse AI Assistant. I'm here to help you with food waste reduction, analytics, and admin tasks. How can I assist you today?</p>
</div>
<span class="text-xs text-gray-500 mt-1 block">Just now</span>
</div>
</div>
<!-- Chat Input -->
<div class="border-t p-4">
<div class="flex space-x-3">
<input type="text" id="userInput" placeholder="Type your message here..."
class="flex-1 border border-gray-300 rounded-xl px-4 py-3 focus:outline-none focus:ring-2 focus:ring-green-500 focus:border-transparent">
<button id="sendBtn" class="bg-green-600 text-white px-6 py-3 rounded-xl hover:bg-green-700 transition flex items-center">
<i data-feather="send" class="mr-2"></i>
Send
</button>
</div>
<div class="flex flex-wrap gap-2 mt-3">
<button class="quick-question bg-gray-100 hover:bg-gray-200 text-gray-700 px-3 py-1 rounded-lg text-sm" data-question="How can I reduce food waste?">
How can I reduce food waste?
</button>
<button class="quick-question bg-gray-100 hover:bg-gray-200 text-gray-700 px-3 py-1 rounded-lg text-sm" data-question="Show me analytics dashboard">
Show me analytics dashboard
</button>
<button class="quick-question bg-gray-100 hover:bg-gray-200 text-gray-700 px-3 py-1 rounded-lg text-sm" data-question="Generate sustainability report">
Generate sustainability report
</button>
<button class="quick-question bg-gray-100 hover:bg-gray-200 text-gray-700 px-3 py-1 rounded-lg text-sm" data-question="What are today's stats?">
What are today's stats?
</button>
</div>
</div>
</div>
</div>
</div>
</main>
</div>
<script>
feather.replace();
document.addEventListener('DOMContentLoaded', function() {
// Current session management
let currentSession = 1;
const chatMessages = document.getElementById('chatMessages');
const userInput = document.getElementById('userInput');
const sendBtn = document.getElementById('sendBtn');
const newChatBtn = document.getElementById('newChatBtn');
const currentSessionSpan = document.getElementById('currentSession');
const topicsContainer = document.getElementById('topicsContainer');
const chatHistory = document.getElementById('chatHistory');
// Load topics from public API (using a food/trivia API as example)
async function loadTopics() {
const topicsLoading = document.getElementById('topicsLoading');
try {
// Using Open Food Facts API for food-related topics
const response = await fetch('https://world.openfoodfacts.org/categories.json');
const data = await response.json();
// Clear loading
topicsLoading.innerHTML = '';
// Display first 10 categories as topics
const categories = data.tags.slice(0, 10);
categories.forEach(category => {
const topicBtn = document.createElement('button');
topicBtn.className = 'w-full text-left p-3 rounded-lg mb-2 hover:bg-green-50 border border-transparent hover:border-green-200 transition';
topicBtn.innerHTML = `
<div class="flex items-center">
<i data-feather="folder" class="w-4 h-4 mr-2 text-green-500"></i>
<span class="text-gray-700">${category.name}</span>
</div>
`;
topicBtn.onclick = () => {
sendMessage(`Tell me about ${category.name} and food waste`);
};
topicsContainer.appendChild(topicBtn);
});
// Add a few generic topics
const genericTopics = [
"Food Preservation Techniques",
"Composting Methods",
"Inventory Management",
"Donation Guidelines",
"Expiry Date Tracking"
];
genericTopics.forEach(topic => {
const topicBtn = document.createElement('button');
topicBtn.className = 'w-full text-left p-3 rounded-lg mb-2 hover:bg-blue-50 border border-transparent hover:border-blue-200 transition';
topicBtn.innerHTML = `
<div class="flex items-center">
<i data-feather="help-circle" class="w-4 h-4 mr-2 text-blue-500"></i>
<span class="text-gray-700">${topic}</span>
</div>
`;
topicBtn.onclick = () => {
sendMessage(topic);
};
topicsContainer.appendChild(topicBtn);
});
feather.replace();
} catch (error) {
topicsLoading.innerHTML = '<p class="text-gray-500">Failed to load topics. Using default topics.</p>';
// Add fallback topics
const fallbackTopics = ["Reducing Food Waste", "Sustainable Practices", "Analytics Dashboard", "User Management", "Report Generation"];
fallbackTopics.forEach(topic => {
const topicBtn = document.createElement('button');
topicBtn.className = 'w-full text-left p-3 rounded-lg mb-2 hover:bg-green-50 border border-green-100 transition';
topicBtn.textContent = topic;
topicBtn.onclick = () => {
sendMessage(topic);
};
topicsContainer.appendChild(topicBtn);
});
}
}
// Send message function
function sendMessage(messageText) {
if (!messageText.trim()) return;
// Add user message
const userMsg = document.createElement('div');
userMsg.className = 'message user mb-4 max-w-[80%] ml-auto';
userMsg.innerHTML = `
<div class="bg-green-500 text-white p-4 rounded-2xl rounded-tr-none">
<div class="flex items-center mb-1 justify-end">
<span class="font-semibold">You</span>
<div class="w-6 h-6 rounded-full bg-green-600 flex items-center justify-center ml-2">
<i data-feather="user" class="w-3 h-3"></i>
</div>
</div>
<p>${messageText}</p>
</div>
<span class="text-xs text-gray-500 mt-1 block text-right">Just now</span>
`;
chatMessages.appendChild(userMsg);
// Clear input if from input field
if (userInput.value === messageText) {
userInput.value = '';
}
// Scroll to bottom
chatMessages.scrollTop = chatMessages.scrollHeight;
// Simulate bot response (in real app, this would be an API call)
setTimeout(() => {
const botResponses = [
"I can help with that! Food waste reduction involves proper inventory tracking, donation coordination, and consumer education. Would you like me to generate a report on current waste metrics?",
"Based on your dashboard data, I can see opportunities to reduce waste by 23% through better inventory rotation. Shall I create an action plan?",
"Great question! The key strategies include: 1) First-in-first-out inventory, 2) Dynamic pricing for near-expiry items, 3) Partnering with local food banks, and 4) Consumer education campaigns.",
"I've analyzed your recent data and found that produce accounts for 65% of your food waste. Implementing a composting program could reduce landfill contribution by 40%.",
"Let me pull up the sustainability dashboard. I can show you metrics on carbon footprint reduction, cost savings from waste reduction, and community impact from donations."
];
const randomResponse = botResponses[Math.floor(Math.random() * botResponses.length)];
const botMsg = document.createElement('div');
botMsg.className = 'message bot mb-4 max-w-[80%]';
botMsg.innerHTML = `
<div class="bg-gray-100 p-4 rounded-2xl rounded-tl-none">
<div class="flex items-center mb-1">
<div class="w-6 h-6 rounded-full bg-green-500 flex items-center justify-center mr-2">
<i data-feather="bot" class="w-3 h-3 text-white"></i>
</div>
<span class="font-semibold text-gray-700">Assistant</span>
</div>
<p class="text-gray-800">${randomResponse}</p>
</div>
<span class="text-xs text-gray-500 mt-1 block">Just now</span>
`;
chatMessages.appendChild(botMsg);
// Update feather icons
feather.replace();
// Scroll to bottom
chatMessages.scrollTop = chatMessages.scrollHeight;
// Add to chat history if new session
updateChatHistory();
}, 1000);
}
// Update chat history
function updateChatHistory() {
// In a real app, this would update the session list
// For demo, we'll just ensure current session is highlighted
document.querySelectorAll('.session-btn').forEach(btn => {
btn.classList.remove('bg-green-50', 'border-green-200', 'text-green-700');
btn.classList.add('bg-gray-50', 'text-gray-600');
});
const currentBtn = document.querySelector(`.session-btn[data-session="${currentSession}"]`);
if (currentBtn) {
currentBtn.classList.remove('bg-gray-50', 'text-gray-600');
currentBtn.classList.add('bg-green-50', 'border-green-200', 'text-green-700');
}
}
// New chat function
function startNewChat() {
currentSession++;
currentSessionSpan.textContent = currentSession;
// Clear chat messages
chatMessages.innerHTML = `
<div class="message bot mb-4 max-w-[80%]">
<div class="bg-gray-100 p-4 rounded-2xl rounded-tl-none">
<div class="flex items-center mb-1">
<div class="w-6 h-6 rounded-full bg-green-500 flex items-center justify-center mr-2">
<i data-feather="bot" class="w-3 h-3 text-white"></i>
</div>
<span class="font-semibold text-gray-700">Assistant</span>
</div>
<p class="text-gray-800">Hello! 👋 Welcome to a new chat session. I'm your FoodSave AI Assistant. How can I help you with food waste reduction today?</p>
</div>
<span class="text-xs text-gray-500 mt-1 block">Just now</span>
</div>
`;
// Add to chat history
const historyItem = document.createElement('button');
historyItem.className = 'session-btn w-full text-left p-3 rounded-lg bg-green-50 border border-green-200 text-green-700 font-medium';
historyItem.dataset.session = currentSession;
historyItem.innerHTML = `
<div class="flex justify-between items-center">
<span>Chat ${currentSession}</span>
<span class="text-xs text-gray-500">Just now</span>
</div>
<p class="text-sm text-gray-600 truncate">New session started</p>
`;
historyItem.onclick = () => {
// In a real app, this would load the session
document.querySelectorAll('.session-btn').forEach(btn => {
btn.classList.remove('bg-green-50', 'border-green-200', 'text-green-700');
btn.classList.add('bg-gray-50', 'text-gray-600');
});
historyItem.classList.remove('bg-gray-50', 'text-gray-600');
historyItem.classList.add('bg-green-50', 'border-green-200', 'text-green-700');
currentSession = currentSession;
currentSessionSpan.textContent = currentSession;
};
chatHistory.prepend(historyItem);
// Update feather icons
feather.replace();
}
// Event listeners
sendBtn.addEventListener('click', () => {
sendMessage(userInput.value);
});
userInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
sendMessage(userInput.value);
}
});
newChatBtn.addEventListener('click', startNewChat);
// Quick question buttons
document.querySelectorAll('.quick-question').forEach(btn => {
btn.addEventListener('click', (e) => {
sendMessage(e.target.dataset.question);
});
});
// Session buttons in history
document.querySelectorAll('.session-btn').forEach(btn => {
btn.addEventListener('click', (e) => {
const sessionId = e.currentTarget.dataset.session;
currentSession = parseInt(sessionId);
currentSessionSpan.textContent = sessionId;
// Update UI
document.querySelectorAll('.session-btn').forEach(b => {
b.classList.remove('bg-green-50', 'border-green-200', 'text-green-700');
b.classList.add('bg-gray-50', 'text-gray-600');
});
e.currentTarget.classList.remove('bg-gray-50', 'text-gray-600');
e.currentTarget.classList.add('bg-green-50', 'border-green-200', 'text-green-700');
// In a real app, load the session messages here
chatMessages.innerHTML = `
<div class="message bot mb-4 max-w-[80%]">
<div class="bg-gray-100 p-4 rounded-2xl rounded-tl-none">
<div class="flex items-center mb-1">
<div class="w-6 h-6 rounded-full bg-green-500 flex items-center justify-center mr-2">
<i data-feather="bot" class="w-3 h-3 text-white"></i>
</div>
<span class="font-semibold text-gray-700">Assistant</span>
</div>
<p class="text-gray-800">Loaded session ${sessionId}. This is where previous conversation would appear.</p>
</div>
<span class="text-xs text-gray-500 mt-1 block">Session loaded</span>
</div>
`;
});
});
// Load topics on startup
loadTopics();
});
</script>
<script src="script.js"></script>
</body>
</html> |