nov 20th, 2025 V.2
This commit is contained in:
parent
e6fd5f2ecb
commit
aab4f05548
229
chat.php
229
chat.php
@ -10,117 +10,153 @@ if (!is_logged_in()) {
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
|
||||
<!-- SEO & Meta Tags -->
|
||||
<title>AI Chat - FinMox</title>
|
||||
<meta name="description" content="FinMox Flow - a multi-tenant SaaS platform for HR and Operations teams. Built with Flatlogic Generator.">
|
||||
<meta name="keywords" content="finmox, hr, operations, saas, candidate tracking, onboarding, automations, ai copilot, flatlogic">
|
||||
|
||||
<!-- Social Media Meta Tags -->
|
||||
<meta property="og:title" content="FinMox Flow">
|
||||
<meta property="og:description" content="A multi-tenant SaaS platform for HR and Operations teams.">
|
||||
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
||||
<meta name="twitter:card" content="summary_large_image">
|
||||
<meta name="twitter:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? '', ENT_QUOTES, 'UTF-8'); ?>">
|
||||
|
||||
<!-- Stylesheets -->
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
||||
<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>
|
||||
#chat-container {
|
||||
max-width: 800px;
|
||||
margin: 2rem auto;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 8px;
|
||||
padding: 1rem;
|
||||
height: 70vh;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
|
||||
* {
|
||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;
|
||||
}
|
||||
#chat-messages {
|
||||
flex-grow: 1;
|
||||
overflow-y: auto;
|
||||
padding: 1rem;
|
||||
border-bottom: 1px solid #ddd;
|
||||
body {
|
||||
-webkit-font-smoothing: antialiased;
|
||||
}
|
||||
.message {
|
||||
margin-bottom: 1rem;
|
||||
.chat-container {
|
||||
height: calc(100vh - 80px);
|
||||
}
|
||||
.message .sender {
|
||||
font-weight: bold;
|
||||
.message-bubble {
|
||||
max-width: 75%;
|
||||
}
|
||||
.message .content {
|
||||
padding: 0.5rem 1rem;
|
||||
border-radius: 8px;
|
||||
display: inline-block;
|
||||
.user-message {
|
||||
background-color: #3B82F6;
|
||||
color: white;
|
||||
}
|
||||
.user-message .content {
|
||||
background-color: #e9f5ff;
|
||||
.ai-message {
|
||||
background-color: #E5E7EB;
|
||||
color: #1F2937;
|
||||
}
|
||||
.ai-message .content {
|
||||
background-color: #f8f9fa;
|
||||
#chat-input:focus {
|
||||
outline: none;
|
||||
box-shadow: none;
|
||||
border-color: #3B82F6;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<header class="header d-flex justify-content-between align-items-center">
|
||||
<div class="logo">
|
||||
<a href="app.php">
|
||||
<img src="assets/pasted-20251120-051320-b2b0cdfa.png" alt="FinMox Logo" style="height: 32px;">
|
||||
</a>
|
||||
</div>
|
||||
<nav class="d-flex align-items-center">
|
||||
<a href="app.php" class="btn btn-outline-primary me-2">Home</a>
|
||||
<a href="chat.php" class="btn btn-outline-primary me-2">Chat</a>
|
||||
<a href="dashboard.php" class="btn btn-outline-primary me-2">Dashboard</a>
|
||||
<a href="workflows.php" class="btn btn-outline-primary me-3">Workflows</a>
|
||||
<div class="dropdown">
|
||||
<button class="btn btn-outline-secondary dropdown-toggle" type="button" id="userDropdown" data-bs-toggle="dropdown" aria-expanded="false">
|
||||
<?php echo htmlspecialchars($_SESSION['username']); ?>
|
||||
</button>
|
||||
<ul class="dropdown-menu dropdown-menu-end" aria-labelledby="userDropdown">
|
||||
<?php if (hasPermission('manage_roles')): ?>
|
||||
<li><a class="dropdown-item" href="roles.php">Manage Roles</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<?php endif; ?>
|
||||
<li><a class="dropdown-item" href="logout.php">Logout</a></li>
|
||||
</ul>
|
||||
<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>
|
||||
</nav>
|
||||
</header>
|
||||
|
||||
<main class="main-content">
|
||||
<div id="chat-container">
|
||||
<div id="chat-messages"></div>
|
||||
<div class="input-group mt-3">
|
||||
<input type="text" id="user-input" class="form-control" placeholder="Ask the AI Assistant...">
|
||||
<button id="send-btn" class="btn btn-primary">Send</button>
|
||||
<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>
|
||||
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/js/bootstrap.bundle.min.js"></script>
|
||||
<!-- 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('user-input');
|
||||
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 messageDiv = document.createElement('div');
|
||||
messageDiv.classList.add('message', sender + '-message');
|
||||
const messageWrapper = document.createElement('div');
|
||||
messageWrapper.classList.add('flex', 'mb-4');
|
||||
|
||||
const senderDiv = document.createElement('div');
|
||||
senderDiv.classList.add('sender');
|
||||
senderDiv.textContent = sender === 'user' ? 'You' : 'AI Assistant';
|
||||
const avatar = document.createElement('div');
|
||||
avatar.classList.add('w-8', 'h-8', 'rounded-full', 'flex', 'items-center', 'justify-center', 'text-white', 'font-bold');
|
||||
|
||||
const contentDiv = document.createElement('div');
|
||||
contentDiv.classList.add('content');
|
||||
contentDiv.textContent = content;
|
||||
const messageBubble = document.createElement('div');
|
||||
messageBubble.classList.add('p-3', 'rounded-lg', 'message-bubble');
|
||||
|
||||
messageDiv.appendChild(senderDiv);
|
||||
messageDiv.appendChild(contentDiv);
|
||||
chatMessages.appendChild(messageDiv);
|
||||
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;
|
||||
}
|
||||
|
||||
@ -130,7 +166,9 @@ if (!is_logged_in()) {
|
||||
|
||||
addMessage('user', message);
|
||||
userInput.value = '';
|
||||
charCounter.textContent = '0 / 4000';
|
||||
sendBtn.disabled = true;
|
||||
typingIndicator.classList.remove('hidden');
|
||||
|
||||
try {
|
||||
const response = await fetch('api/chat.php', {
|
||||
@ -154,15 +192,28 @@ if (!is_logged_in()) {
|
||||
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') {
|
||||
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>
|
||||
Loading…
x
Reference in New Issue
Block a user