35428-vm/assets/js/main.js
Flatlogic Bot 2e3424ad5c v.2
2025-11-02 19:42:55 +00:00

290 lines
12 KiB
JavaScript

// Screen Test - Main JS
document.addEventListener('DOMContentLoaded', function () {
// --- Element Selectors ---
const form = document.getElementById('idea-form');
const submitButton = form.querySelector('button[type="submit"]');
const personasContainer = document.getElementById('personas-container');
const personasGrid = document.getElementById('personas-grid');
const chatContainer = document.getElementById('chat-container');
const chatCard = document.querySelector('.chat-card');
const chatPersonaName = document.getElementById('chat-persona-name');
const chatPersonaIcon = document.getElementById('chat-persona-icon');
const closeChatBtn = document.getElementById('close-chat');
const chatLog = document.getElementById('chat-log');
const chatForm = document.getElementById('chat-form');
const chatMessageInput = document.getElementById('chat-message-input');
const sendMessageBtn = document.getElementById('send-message-btn');
const analysisSection = document.getElementById('analysis-section');
const generateAnalysisBtn = document.getElementById('generate-analysis-btn');
const analysisContainer = document.getElementById('analysis-container');
const analysisContent = document.getElementById('analysis-content');
// --- State Variables ---
let currentSessionId = null;
let personasData = [];
let activePersona = null;
let chatHistory = [];
// --- Event Listeners ---
// Main form submission -> Generate Personas & Create Session
if (form) {
form.addEventListener('submit', function (e) {
e.preventDefault();
const audience = document.getElementById('target-audience').value;
const idea = document.getElementById('business-idea').value;
if (!audience || !idea) {
alert('Please fill out both Target Audience and Business Idea fields.');
return;
}
// --- Reset UI and Set Loading State ---
personasContainer.classList.add('d-none');
chatContainer.classList.add('d-none');
analysisSection.classList.add('d-none');
analysisContainer.classList.add('d-none');
personasGrid.innerHTML = '';
const originalButtonText = submitButton.innerHTML;
submitButton.disabled = true;
submitButton.innerHTML = `<span class="spinner-border spinner-border-sm"></span> Generating...`;
// --- Fetch Personas & Create Session ---
fetch('api/generate_personas.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ audience, idea }),
})
.then(response => {
if (!response.ok) return response.json().then(err => { throw new Error(err.error || 'Unknown error generating personas.') });
return response.json();
})
.then(data => {
if (data.session_id && data.personas && data.personas.length > 0) {
// --- Store Session and Persona Data ---
currentSessionId = data.session_id;
personasData = data.personas; // Now contains DB IDs
renderPersonas(personasData);
personasContainer.classList.remove('d-none');
setTimeout(() => personasContainer.scrollIntoView({ behavior: 'smooth', block: 'start' }), 100);
} else {
throw new Error('The AI did not return valid session data. Please try again.');
}
})
.catch(error => {
console.error('Error:', error);
alert(`An error occurred: ${error.message}`);
})
.finally(() => {
submitButton.disabled = false;
submitButton.innerHTML = originalButtonText;
});
});
}
// Persona card click -> Open Chat
personasGrid.addEventListener('click', function(e) {
const card = e.target.closest('.persona-card');
if (card) {
const personaIndex = card.dataset.personaIndex;
activePersona = personasData[personaIndex]; // activePersona now has the DB ID
const gradientIndex = card.classList.contains('persona-gradient-1') ? 1 : card.classList.contains('persona-gradient-2') ? 2 : 3;
openChat(activePersona, gradientIndex);
}
});
// Close chat button
closeChatBtn.addEventListener('click', function() {
chatContainer.classList.add('d-none');
analysisSection.classList.add('d-none');
analysisContainer.classList.add('d-none');
activePersona = null;
});
// Chat form submission -> Send message
chatForm.addEventListener('submit', function(e) {
e.preventDefault();
const message = chatMessageInput.value.trim();
if (message && activePersona && currentSessionId) {
addMessageToChatLog(message, 'user');
chatHistory.push({ sender: 'user', message: message });
chatMessageInput.value = '';
chatMessageInput.style.height = 'auto';
showTypingIndicator();
// --- Fetch Chat Response ---
fetch('api/chat.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
session_id: currentSessionId,
message: message,
persona: activePersona, // persona object now includes the ID
history: chatHistory.slice(0, -1)
}),
})
.then(response => {
if (!response.ok) return response.json().then(err => { throw new Error(err.error || 'An API error occurred.') });
return response.json();
})
.then(data => {
if (data.response) {
addMessageToChatLog(data.response, 'persona');
chatHistory.push({ sender: 'persona', message: data.response });
} else {
throw new Error('Empty response from AI.');
}
})
.catch(error => {
console.error('Chat Error:', error);
addMessageToChatLog(`Sorry, I encountered an error: ${error.message}`, 'persona', true);
})
.finally(() => {
hideTypingIndicator();
});
}
});
// Analysis button click -> Generate Analysis
generateAnalysisBtn.addEventListener('click', function() {
if (!activePersona || !currentSessionId || chatHistory.length < 5) return;
const originalButtonText = this.innerHTML;
this.disabled = true;
this.innerHTML = `<span class="spinner-border spinner-border-sm"></span> Analyzing...`;
// --- Fetch Analysis ---
fetch('api/analyze_chat.php', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
session_id: currentSessionId,
persona: activePersona,
history: chatHistory
}),
})
.then(response => {
if (!response.ok) return response.json().then(err => { throw new Error(err.error || 'An API error occurred during analysis.') });
return response.json();
})
.then(data => {
if (data.analysis) {
analysisContent.innerHTML = data.analysis;
analysisContainer.classList.remove('d-none');
analysisContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
} else {
throw new Error('Empty analysis from AI.');
}
})
.catch(error => {
console.error('Analysis Error:', error);
analysisContent.innerHTML = `<div class="alert alert-danger">Sorry, an error occurred during analysis: ${error.message}</div>`;
analysisContainer.classList.remove('d-none');
})
.finally(() => {
this.disabled = false;
this.innerHTML = originalButtonText;
});
});
// Auto-resize textarea for chat input
chatMessageInput.addEventListener('input', function () {
this.style.height = 'auto';
this.style.height = (this.scrollHeight) + 'px';
});
// --- Functions ---
function renderPersonas(personas) {
const personaGradients = ['persona-gradient-1', 'persona-gradient-2', 'persona-gradient-3'];
personasGrid.innerHTML = personas.map((persona, index) => `
<div class="col-lg-4 col-md-6">
<div class="card persona-card h-100 rounded-4 shadow-lg border-0 ${personaGradients[index % 3]}" data-persona-index="${index}" style="cursor: pointer;">
<div class="card-body p-4">
<h3 class="card-title fw-bold">${persona.name}</h3>
<p class="card-subtitle mb-2 text-white-75">${persona.age}, ${persona.occupation}</p>
<div class="mt-4">
<h6 class="fw-semibold">Traits:</h6><p>${persona.traits}</p>
<h6 class="fw-semibold">Concerns:</h6><p>${persona.concerns}</p>
<h6 class="fw-semibold">Style:</h6><p>${persona.style}</p>
</div>
</div>
</div>
</div>
`).join('');
}
function openChat(persona, gradientIndex) {
chatPersonaName.textContent = persona.name;
const cardGradientClass = `persona-gradient-${gradientIndex}`;
chatCard.querySelector('.card-header').className = `card-header d-flex justify-content-between align-items-center p-3 rounded-top-5 ${cardGradientClass}`;
chatPersonaIcon.className = "bi bi-person-circle fs-3 me-3";
chatLog.innerHTML = '';
const welcomeMessage = `Hello! I'm ${persona.name}. Ask me anything about the business idea.`;
addMessageToChatLog(welcomeMessage, 'persona');
chatHistory = [{ sender: 'persona', message: welcomeMessage }];
chatContainer.classList.remove('d-none');
analysisSection.classList.add('d-none');
analysisContainer.classList.add('d-none');
generateAnalysisBtn.disabled = true;
chatContainer.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
function addMessageToChatLog(message, sender, isError = false) {
const messageElement = document.createElement('div');
messageElement.className = `chat-message ${sender === 'user' ? 'user' : 'persona'}`;
const bubble = document.createElement('div');
bubble.className = 'message-bubble';
if (isError) bubble.classList.add('bg-danger', 'text-white');
bubble.textContent = message;
const time = document.createElement('div');
time.className = 'message-time';
time.textContent = new Date().toLocaleTimeString([], { hour: '2-digit', minute: '2-digit' });
messageElement.appendChild(bubble);
messageElement.appendChild(time);
chatLog.appendChild(messageElement);
chatLog.scrollTop = chatLog.scrollHeight;
// Check to enable analysis button (user messages count towards total)
if (sender === 'user' && chatHistory.filter(m => m.sender === 'user').length >= 2) {
analysisSection.classList.remove('d-none');
generateAnalysisBtn.disabled = false;
}
}
function showTypingIndicator() {
sendMessageBtn.disabled = true;
let indicator = chatLog.querySelector('.typing-indicator');
if (!indicator) {
indicator = document.createElement('div');
indicator.className = 'chat-message persona typing-indicator';
indicator.innerHTML = `
<div class="message-bubble">
<div class="spinner-grow spinner-grow-sm" role="status"></div>
<div class="spinner-grow spinner-grow-sm mx-1" role="status"></div>
<div class="spinner-grow spinner-grow-sm" role="status"></div>
</div>
`;
chatLog.appendChild(indicator);
}
chatLog.scrollTop = chatLog.scrollHeight;
}
function hideTypingIndicator() {
sendMessageBtn.disabled = false;
const indicator = chatLog.querySelector('.typing-indicator');
if (indicator) {
indicator.remove();
}
}
});