35632-vm/chat.php
2025-11-20 05:18:32 +00:00

220 lines
9.3 KiB
PHP

<?php
require_once 'auth.php';
if (!is_logged_in()) {
header('Location: login.php');
exit();
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>AI Chat - FinMox</title>
<script src="https://cdn.tailwindcss.com"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<style>
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
* {
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
}
body {
-webkit-font-smoothing: antialiased;
}
.chat-container {
height: calc(100vh - 80px);
}
.message-bubble {
max-width: 75%;
}
.user-message {
background-color: #3B82F6;
color: white;
}
.ai-message {
background-color: #E5E7EB;
color: #1F2937;
}
#chat-input:focus {
outline: none;
box-shadow: none;
border-color: #3B82F6;
}
</style>
</head>
<body class="bg-gray-100">
<div class="flex h-screen">
<!-- Sidebar -->
<div class="w-1/4 bg-white border-r border-gray-200 flex flex-col">
<div class="p-4 border-b border-gray-200">
<a href="chat.php" class="w-full bg-black text-white px-4 py-2 rounded-lg text-sm font-medium flex items-center justify-center gap-2">
<i class="fas fa-plus"></i>
New Chat
</a>
</div>
<div class="flex-grow overflow-y-auto">
<!-- Conversation List -->
<div class="p-4">
<h2 class="text-xs text-gray-500 font-semibold uppercase mb-2">Past Conversations</h2>
<ul id="conversation-list">
<!-- Placeholder for conversation items -->
<li class="p-2 rounded-lg hover:bg-gray-100 cursor-pointer">
<p class="font-semibold text-sm truncate">Onboarding Workflow Ideas</p>
<p class="text-xs text-gray-500 truncate">Sure, here are some ideas for your onboarding...</p>
<p class="text-xs text-gray-400 mt-1">2 hours ago</p>
</li>
<li class="p-2 rounded-lg hover:bg-gray-100 cursor-pointer mt-2">
<p class="font-semibold text-sm truncate">Compliance Questions</p>
<p class="text-xs text-gray-500 truncate">Let's break down the compliance requirements...</p>
<p class="text-xs text-gray-400 mt-1">Yesterday</p>
</li>
</ul>
</div>
</div>
</div>
<!-- Main Chat Area -->
<div class="w-3/4 flex flex-col">
<header class="bg-white border-b border-gray-200 p-4 flex items-center justify-between">
<div class="flex items-center gap-2">
<a href="app.php">
<img src="assets/pasted-20251120-051320-b2b0cdfa.png" alt="FinMox Logo" style="height: 32px;">
</a>
</div>
<nav class="flex items-center gap-4">
<a href="app.php" class="text-sm text-gray-600 hover:text-gray-900">Home</a>
<a href="dashboard.php" class="text-sm text-gray-600 hover:text-gray-900">Dashboard</a>
<a href="workflows.php" class="text-sm text-gray-600 hover:text-gray-900">Workflows</a>
<a href="logout.php" class="text-sm text-gray-600 hover:text-gray-900">Logout</a>
</nav>
</header>
<main class="flex-grow p-6 overflow-y-auto" id="chat-messages">
<!-- Messages will be appended here -->
</main>
<div class="bg-white border-t border-gray-200 p-4">
<div class="typing-indicator text-sm text-gray-500 mb-2 hidden" id="typing-indicator">
AI is thinking...
</div>
<div class="relative">
<textarea id="chat-input" class="w-full border border-gray-300 rounded-lg p-4 pr-28" placeholder="Ask the AI Assistant..." rows="1"></textarea>
<div class="absolute bottom-3 right-3 flex items-center">
<button class="mr-2 text-gray-400 hover:text-gray-600">
<i class="fas fa-paperclip"></i>
</button>
<button id="send-btn" class="bg-black text-white px-4 py-2 rounded-lg text-sm font-medium">Send</button>
</div>
</div>
<div class="text-xs text-gray-400 mt-1 text-right" id="char-counter">0 / 4000</div>
</div>
</div>
</div>
<script>
const chatMessages = document.getElementById('chat-messages');
const userInput = document.getElementById('chat-input');
const sendBtn = document.getElementById('send-btn');
const typingIndicator = document.getElementById('typing-indicator');
const charCounter = document.getElementById('char-counter');
function addMessage(sender, content) {
const messageWrapper = document.createElement('div');
messageWrapper.classList.add('flex', 'mb-4');
const avatar = document.createElement('div');
avatar.classList.add('w-8', 'h-8', 'rounded-full', 'flex', 'items-center', 'justify-center', 'text-white', 'font-bold');
const messageBubble = document.createElement('div');
messageBubble.classList.add('p-3', 'rounded-lg', 'message-bubble');
const timestamp = document.createElement('div');
timestamp.classList.add('text-xs', 'text-gray-400', 'mt-1');
timestamp.textContent = new Date().toLocaleTimeString();
if (sender === 'user') {
messageWrapper.classList.add('justify-end');
avatar.classList.add('bg-blue-500', 'ml-3');
avatar.textContent = 'U';
messageBubble.classList.add('user-message');
messageBubble.textContent = content;
messageWrapper.appendChild(messageBubble);
messageWrapper.appendChild(avatar);
} else {
messageWrapper.classList.add('justify-start');
avatar.classList.add('bg-gray-700', 'mr-3');
avatar.textContent = 'AI';
messageBubble.classList.add('ai-message');
messageBubble.innerHTML = content; // Use innerHTML to render potential markdown
messageWrapper.appendChild(avatar);
messageWrapper.appendChild(messageBubble);
}
const messageContainer = document.createElement('div');
messageContainer.classList.add('flex', 'flex-col', (sender === 'user' ? 'items-end' : 'items-start'));
messageContainer.appendChild(messageBubble);
messageContainer.appendChild(timestamp);
messageWrapper.appendChild(messageContainer);
chatMessages.appendChild(messageWrapper);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
async function sendMessage() {
const message = userInput.value.trim();
if (!message) return;
addMessage('user', message);
userInput.value = '';
charCounter.textContent = '0 / 4000';
sendBtn.disabled = true;
typingIndicator.classList.remove('hidden');
try {
const response = await fetch('api/chat.php', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({ message })
});
if (!response.ok) {
throw new Error('Network response was not ok');
}
const data = await response.json();
const aiReply = data.reply || data.error || 'No reply from AI.';
addMessage('ai', aiReply);
} catch (error) {
console.error('Error:', error);
addMessage('ai', 'Sorry, something went wrong. Please check the console.');
} finally {
sendBtn.disabled = false;
typingIndicator.classList.add('hidden');
}
}
sendBtn.addEventListener('click', sendMessage);
userInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter' && !e.shiftKey) {
e.preventDefault();
sendMessage();
}
});
userInput.addEventListener('input', () => {
const count = userInput.value.length;
charCounter.textContent = `${count} / 4000`;
});
// Auto-resize textarea
userInput.addEventListener('input', () => {
userInput.style.height = 'auto';
userInput.style.height = (userInput.scrollHeight) + 'px';
});
</script>
</body>
</html>