Spaces:
Running
Running
| <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> |