Compare commits
No commits in common. "ai-dev" and "master" have entirely different histories.
@ -1,207 +0,0 @@
|
|||||||
/* General Body Styling */
|
|
||||||
body {
|
|
||||||
background-color: #F3F4F6;
|
|
||||||
font-family: 'Inter', -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
||||||
color: #111827;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
min-height: 100vh;
|
|
||||||
margin: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Main Chat Container */
|
|
||||||
.chat-container {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 768px;
|
|
||||||
height: 90vh;
|
|
||||||
max-height: 800px;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
overflow: hidden;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Chat Header */
|
|
||||||
.chat-header {
|
|
||||||
padding: 1rem 1.5rem;
|
|
||||||
background: linear-gradient(45deg, #4F46E5, #6366F1);
|
|
||||||
color: white;
|
|
||||||
border-bottom: 1px solid #E5E7EB;
|
|
||||||
text-align: center;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.chat-header h1 {
|
|
||||||
margin: 0;
|
|
||||||
font-size: 1.25rem;
|
|
||||||
font-weight: 600;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Message List */
|
|
||||||
.message-list {
|
|
||||||
flex-grow: 1;
|
|
||||||
padding: 1.5rem;
|
|
||||||
overflow-y: auto;
|
|
||||||
display: flex;
|
|
||||||
flex-direction: column;
|
|
||||||
gap: 1rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Individual Message Styling */
|
|
||||||
.message {
|
|
||||||
display: flex;
|
|
||||||
align-items: flex-end;
|
|
||||||
gap: 0.75rem;
|
|
||||||
max-width: 85%;
|
|
||||||
animation: fadeIn 0.3s ease-out;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message .avatar {
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
border-radius: 50%;
|
|
||||||
background-color: #E5E7EB;
|
|
||||||
display: flex;
|
|
||||||
justify-content: center;
|
|
||||||
align-items: center;
|
|
||||||
font-weight: 600;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message .message-content {
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
line-height: 1.5;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* AI (Bot) Message */
|
|
||||||
.message.bot {
|
|
||||||
align-self: flex-start;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message.bot .avatar {
|
|
||||||
background-color: #4F46E5;
|
|
||||||
color: white;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message.bot .message-content {
|
|
||||||
background-color: #EEF2FF;
|
|
||||||
color: #3730A3;
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* User Message */
|
|
||||||
.message.user {
|
|
||||||
align-self: flex-end;
|
|
||||||
}
|
|
||||||
|
|
||||||
.message.user .message-content {
|
|
||||||
background-color: #10B981;
|
|
||||||
color: white;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
}
|
|
||||||
.message.user .avatar {
|
|
||||||
display: none; /* Hide avatar for user messages for a cleaner look */
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Input Area */
|
|
||||||
.input-area {
|
|
||||||
padding: 1rem 1.5rem;
|
|
||||||
border-top: 1px solid #E5E7EB;
|
|
||||||
background-color: #F9FAFB;
|
|
||||||
display: flex;
|
|
||||||
gap: 0.75rem;
|
|
||||||
flex-shrink: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-area input {
|
|
||||||
flex-grow: 1;
|
|
||||||
padding: 0.75rem 1rem;
|
|
||||||
border: 1px solid #D1D5DB;
|
|
||||||
border-radius: 0.375rem;
|
|
||||||
font-size: 1rem;
|
|
||||||
transition: border-color 0.2s, box-shadow 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-area input:focus {
|
|
||||||
outline: none;
|
|
||||||
border-color: #4F46E5;
|
|
||||||
box-shadow: 0 0 0 3px rgba(79, 70, 229, 0.2);
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-area button {
|
|
||||||
padding: 0.75rem 1.5rem;
|
|
||||||
border: none;
|
|
||||||
background-color: #4F46E5;
|
|
||||||
color: white;
|
|
||||||
border-radius: 0.375rem;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-area button:hover {
|
|
||||||
background-color: #4338CA;
|
|
||||||
}
|
|
||||||
|
|
||||||
.input-area button:disabled {
|
|
||||||
background-color: #A5B4FC;
|
|
||||||
cursor: not-allowed;
|
|
||||||
}
|
|
||||||
|
|
||||||
#analyze-button {
|
|
||||||
width: 100%;
|
|
||||||
padding: 1rem;
|
|
||||||
border: none;
|
|
||||||
background-color: #10B981; /* Emerald Green */
|
|
||||||
color: white;
|
|
||||||
border-radius: 0.375rem;
|
|
||||||
font-size: 1rem;
|
|
||||||
font-weight: 600;
|
|
||||||
cursor: pointer;
|
|
||||||
transition: background-color 0.2s;
|
|
||||||
}
|
|
||||||
|
|
||||||
#analyze-button:hover {
|
|
||||||
background-color: #059669;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Typing indicator */
|
|
||||||
.typing-indicator {
|
|
||||||
display: flex;
|
|
||||||
align-items: center;
|
|
||||||
padding: 5px 0;
|
|
||||||
}
|
|
||||||
.typing-indicator span {
|
|
||||||
height: 8px;
|
|
||||||
width: 8px;
|
|
||||||
float: left;
|
|
||||||
margin: 0 2px;
|
|
||||||
background-color: #9E9E9E;
|
|
||||||
display: block;
|
|
||||||
border-radius: 50%;
|
|
||||||
opacity: 0.4;
|
|
||||||
animation: 1s blink infinite;
|
|
||||||
}
|
|
||||||
.typing-indicator span:nth-child(2) { animation-delay: .2s; }
|
|
||||||
.typing-indicator span:nth-child(3) { animation-delay: .4s; }
|
|
||||||
|
|
||||||
@keyframes blink {
|
|
||||||
50% { opacity: 1; }
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fadeIn {
|
|
||||||
from {
|
|
||||||
opacity: 0;
|
|
||||||
transform: translateY(10px);
|
|
||||||
}
|
|
||||||
to {
|
|
||||||
opacity: 1;
|
|
||||||
transform: translateY(0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,135 +0,0 @@
|
|||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const questions = [
|
|
||||||
"I wake up feeling tired, even after a full night’s sleep.",
|
|
||||||
"By midday, I already feel mentally drained and out of energy.",
|
|
||||||
"I feel emotionally numb, detached, or “on autopilot” most of the time.",
|
|
||||||
"Things that used to excite me now feel pointless or like a chore.",
|
|
||||||
"I feel irritated or cynical about people I work or study with.",
|
|
||||||
"I struggle to focus and constantly procrastinate, even on important tasks.",
|
|
||||||
"I feel guilty for not doing “enough”, no matter how much I actually do.",
|
|
||||||
"I often think about quitting everything for a while or disappearing from social media and work.",
|
|
||||||
"I use caffeine, sugar, nicotine, alcohol, or scrolling to “numb out” instead of resting.",
|
|
||||||
"I feel like my life is just surviving, not really living."
|
|
||||||
];
|
|
||||||
|
|
||||||
const messageList = document.getElementById('message-list');
|
|
||||||
const inputArea = document.getElementById('input-area');
|
|
||||||
const userInput = document.getElementById('user-input');
|
|
||||||
const sendButton = document.getElementById('send-button');
|
|
||||||
|
|
||||||
let currentQuestionIndex = 0;
|
|
||||||
const userAnswers = [];
|
|
||||||
|
|
||||||
function addMessage(text, sender) {
|
|
||||||
const messageElement = document.createElement('div');
|
|
||||||
messageElement.classList.add('message', sender);
|
|
||||||
|
|
||||||
const avatar = document.createElement('div');
|
|
||||||
avatar.classList.add('avatar');
|
|
||||||
avatar.textContent = sender === 'bot' ? 'AI' : 'You';
|
|
||||||
|
|
||||||
const messageContent = document.createElement('div');
|
|
||||||
messageContent.classList.add('message-content');
|
|
||||||
messageContent.textContent = text;
|
|
||||||
|
|
||||||
if (sender === 'bot') {
|
|
||||||
messageElement.appendChild(avatar);
|
|
||||||
}
|
|
||||||
messageElement.appendChild(messageContent);
|
|
||||||
|
|
||||||
messageList.appendChild(messageElement);
|
|
||||||
messageList.scrollTop = messageList.scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
function showTypingIndicator() {
|
|
||||||
const typingElement = document.createElement('div');
|
|
||||||
typingElement.id = 'typing-indicator';
|
|
||||||
typingElement.classList.add('message', 'bot');
|
|
||||||
typingElement.innerHTML = `
|
|
||||||
<div class="avatar">AI</div>
|
|
||||||
<div class="message-content">
|
|
||||||
<div class="typing-indicator">
|
|
||||||
<span></span><span></span><span></span>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
`;
|
|
||||||
messageList.appendChild(typingElement);
|
|
||||||
messageList.scrollTop = messageList.scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
function removeTypingIndicator() {
|
|
||||||
const typingElement = document.getElementById('typing-indicator');
|
|
||||||
if (typingElement) {
|
|
||||||
typingElement.remove();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function askNextQuestion() {
|
|
||||||
if (currentQuestionIndex < questions.length) {
|
|
||||||
showTypingIndicator();
|
|
||||||
setTimeout(() => {
|
|
||||||
removeTypingIndicator();
|
|
||||||
addMessage(questions[currentQuestionIndex], 'bot');
|
|
||||||
userInput.disabled = false;
|
|
||||||
sendButton.disabled = false;
|
|
||||||
userInput.focus();
|
|
||||||
}, 1000); // Simulate AI "thinking"
|
|
||||||
} else {
|
|
||||||
showTypingIndicator();
|
|
||||||
setTimeout(() => {
|
|
||||||
removeTypingIndicator();
|
|
||||||
addMessage("Thank you for your responses. Click the button below to see your analysis.", 'bot');
|
|
||||||
|
|
||||||
// Create a form to submit the results
|
|
||||||
const form = document.createElement('form');
|
|
||||||
form.method = 'POST';
|
|
||||||
form.action = 'results.php';
|
|
||||||
|
|
||||||
const hiddenInput = document.createElement('input');
|
|
||||||
hiddenInput.type = 'hidden';
|
|
||||||
hiddenInput.name = 'conversation';
|
|
||||||
hiddenInput.value = JSON.stringify(userAnswers);
|
|
||||||
form.appendChild(hiddenInput);
|
|
||||||
|
|
||||||
const submitButton = document.createElement('button');
|
|
||||||
submitButton.type = 'submit';
|
|
||||||
submitButton.textContent = 'Analyze My Results';
|
|
||||||
submitButton.id = 'analyze-button';
|
|
||||||
form.appendChild(submitButton);
|
|
||||||
|
|
||||||
inputArea.innerHTML = ''; // Clear the input field and send button
|
|
||||||
inputArea.appendChild(form);
|
|
||||||
inputArea.style.display = 'flex';
|
|
||||||
|
|
||||||
}, 1500);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleUserInput() {
|
|
||||||
const text = userInput.value.trim();
|
|
||||||
if (text === '') return;
|
|
||||||
|
|
||||||
addMessage(text, 'user');
|
|
||||||
userAnswers.push({ question: questions[currentQuestionIndex], answer: text });
|
|
||||||
|
|
||||||
userInput.value = '';
|
|
||||||
userInput.disabled = true;
|
|
||||||
sendButton.disabled = true;
|
|
||||||
|
|
||||||
currentQuestionIndex++;
|
|
||||||
askNextQuestion();
|
|
||||||
}
|
|
||||||
|
|
||||||
sendButton.addEventListener('click', handleUserInput);
|
|
||||||
userInput.addEventListener('keydown', (event) => {
|
|
||||||
if (event.key === 'Enter') {
|
|
||||||
handleUserInput();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// Start the conversation
|
|
||||||
setTimeout(() => {
|
|
||||||
addMessage("Hello! I'm here to help you assess your level of burnout. I'll ask you 10 questions. Please answer them honestly.", 'bot');
|
|
||||||
askNextQuestion();
|
|
||||||
}, 500);
|
|
||||||
});
|
|
||||||
40
followup.php
40
followup.php
@ -1,40 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/ai/LocalAIApi.php';
|
|
||||||
|
|
||||||
$request_body = file_get_contents('php://input');
|
|
||||||
$data = json_decode($request_body, true);
|
|
||||||
|
|
||||||
$conversation = $data['conversation'] ?? null;
|
|
||||||
$analysis = $data['analysis'] ?? null;
|
|
||||||
$follow_up_question = $data['follow_up_question'] ?? null;
|
|
||||||
|
|
||||||
if ($conversation && $analysis && $follow_up_question) {
|
|
||||||
$prompt = "The user has received an initial burnout analysis and has a follow-up question. Here is the context:\n\n";
|
|
||||||
$prompt .= "**Original Survey Answers:**\n";
|
|
||||||
foreach ($conversation as $item) {
|
|
||||||
$prompt .= "Q: " . $item['question'] . "\nA: " . $item['answer'] . "\n";
|
|
||||||
}
|
|
||||||
$prompt .= "\n**Initial AI Analysis:**\n" . strip_tags($analysis) . "\n";
|
|
||||||
$prompt .= "\n**User's Follow-up Question:**\n" . $follow_up_question . "\n";
|
|
||||||
$prompt .= "Please provide a concise and helpful response to the user's question, keeping the context in mind. Format the response as simple HTML.";
|
|
||||||
|
|
||||||
$resp = LocalAIApi::createResponse(
|
|
||||||
[
|
|
||||||
'input' => [
|
|
||||||
['role' => 'system', 'content' => 'You are a helpful assistant specializing in mental health and burnout analysis.'],
|
|
||||||
['role' => 'user', 'content' => $prompt],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($resp['success'])) {
|
|
||||||
echo LocalAIApi::extractText($resp);
|
|
||||||
} else {
|
|
||||||
echo "Sorry, I couldn't process your request. Please try again later.";
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
http_response_code(400);
|
|
||||||
echo "Invalid request. Missing data.";
|
|
||||||
}
|
|
||||||
|
|
||||||
172
index.php
172
index.php
@ -1,42 +1,150 @@
|
|||||||
<?php
|
<?php
|
||||||
?><!DOCTYPE html>
|
declare(strict_types=1);
|
||||||
|
@ini_set('display_errors', '1');
|
||||||
|
@error_reporting(E_ALL);
|
||||||
|
@date_default_timezone_set('UTC');
|
||||||
|
|
||||||
|
$phpVersion = PHP_VERSION;
|
||||||
|
$now = date('Y-m-d H:i:s');
|
||||||
|
?>
|
||||||
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="utf-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
|
<title>New Style</title>
|
||||||
<title>Burnout Survey & Analysis</title>
|
<?php
|
||||||
<meta name="description" content="AI-driven burnout survey that asks questions conversationally, analyzes responses, and provides structured results and charts. Built with Flatlogic Generator.">
|
// Read project preview data from environment
|
||||||
<meta name="keywords" content="burnout survey, mental health, ai chatbot, stress analysis, employee wellness, self-assessment, mental wellbeing, burnout prevention, ai health, personalized advice, Flatlogic Generator">
|
$projectDescription = $_SERVER['PROJECT_DESCRIPTION'] ?? '';
|
||||||
|
$projectImageUrl = $_SERVER['PROJECT_IMAGE_URL'] ?? '';
|
||||||
<meta property="og:title" content="Burnout Survey & Analysis">
|
?>
|
||||||
<meta property="og:description" content="AI-driven burnout survey that asks questions conversationally, analyzes responses, and provides structured results and charts.">
|
<?php if ($projectDescription): ?>
|
||||||
<meta property="og:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
|
<!-- Meta description -->
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
<meta name="description" content='<?= htmlspecialchars($projectDescription) ?>' />
|
||||||
<meta name="twitter:image" content="<?php echo htmlspecialchars($_SERVER['PROJECT_IMAGE_URL'] ?? ''); ?>">
|
<!-- Open Graph meta tags -->
|
||||||
|
<meta property="og:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||||
|
<!-- Twitter meta tags -->
|
||||||
|
<meta property="twitter:description" content="<?= htmlspecialchars($projectDescription) ?>" />
|
||||||
|
<?php endif; ?>
|
||||||
|
<?php if ($projectImageUrl): ?>
|
||||||
|
<!-- Open Graph image -->
|
||||||
|
<meta property="og:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||||
|
<!-- Twitter image -->
|
||||||
|
<meta property="twitter:image" content="<?= htmlspecialchars($projectImageUrl) ?>" />
|
||||||
|
<?php endif; ?>
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
|
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;700&display=swap" rel="stylesheet">
|
||||||
|
<style>
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
:root {
|
||||||
|
--bg-color-start: #6a11cb;
|
||||||
|
--bg-color-end: #2575fc;
|
||||||
|
--text-color: #ffffff;
|
||||||
|
--card-bg-color: rgba(255, 255, 255, 0.01);
|
||||||
|
--card-border-color: rgba(255, 255, 255, 0.1);
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Inter', sans-serif;
|
||||||
|
background: linear-gradient(45deg, var(--bg-color-start), var(--bg-color-end));
|
||||||
|
color: var(--text-color);
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
min-height: 100vh;
|
||||||
|
text-align: center;
|
||||||
|
overflow: hidden;
|
||||||
|
position: relative;
|
||||||
|
}
|
||||||
|
body::before {
|
||||||
|
content: '';
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
background-image: url('data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="100" height="100" viewBox="0 0 100 100"><path d="M-10 10L110 10M10 -10L10 110" stroke-width="1" stroke="rgba(255,255,255,0.05)"/></svg>');
|
||||||
|
animation: bg-pan 20s linear infinite;
|
||||||
|
z-index: -1;
|
||||||
|
}
|
||||||
|
@keyframes bg-pan {
|
||||||
|
0% { background-position: 0% 0%; }
|
||||||
|
100% { background-position: 100% 100%; }
|
||||||
|
}
|
||||||
|
main {
|
||||||
|
padding: 2rem;
|
||||||
|
}
|
||||||
|
.card {
|
||||||
|
background: var(--card-bg-color);
|
||||||
|
border: 1px solid var(--card-border-color);
|
||||||
|
border-radius: 16px;
|
||||||
|
padding: 2rem;
|
||||||
|
backdrop-filter: blur(20px);
|
||||||
|
-webkit-backdrop-filter: blur(20px);
|
||||||
|
box-shadow: 0 8px 32px 0 rgba(0, 0, 0, 0.1);
|
||||||
|
}
|
||||||
|
.loader {
|
||||||
|
margin: 1.25rem auto 1.25rem;
|
||||||
|
width: 48px;
|
||||||
|
height: 48px;
|
||||||
|
border: 3px solid rgba(255, 255, 255, 0.25);
|
||||||
|
border-top-color: #fff;
|
||||||
|
border-radius: 50%;
|
||||||
|
animation: spin 1s linear infinite;
|
||||||
|
}
|
||||||
|
@keyframes spin {
|
||||||
|
from { transform: rotate(0deg); }
|
||||||
|
to { transform: rotate(360deg); }
|
||||||
|
}
|
||||||
|
.hint {
|
||||||
|
opacity: 0.9;
|
||||||
|
}
|
||||||
|
.sr-only {
|
||||||
|
position: absolute;
|
||||||
|
width: 1px; height: 1px;
|
||||||
|
padding: 0; margin: -1px;
|
||||||
|
overflow: hidden;
|
||||||
|
clip: rect(0, 0, 0, 0);
|
||||||
|
white-space: nowrap; border: 0;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
font-size: 3rem;
|
||||||
|
font-weight: 700;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
letter-spacing: -1px;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
margin: 0.5rem 0;
|
||||||
|
font-size: 1.1rem;
|
||||||
|
}
|
||||||
|
code {
|
||||||
|
background: rgba(0,0,0,0.2);
|
||||||
|
padding: 2px 6px;
|
||||||
|
border-radius: 4px;
|
||||||
|
font-family: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;
|
||||||
|
}
|
||||||
|
footer {
|
||||||
|
position: absolute;
|
||||||
|
bottom: 1rem;
|
||||||
|
font-size: 0.8rem;
|
||||||
|
opacity: 0.7;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<main>
|
||||||
<div class="chat-container">
|
<div class="card">
|
||||||
<header class="chat-header">
|
<h1>Analyzing your requirements and generating your website…</h1>
|
||||||
<h1>Burnout Assessment</h1>
|
<div class="loader" role="status" aria-live="polite" aria-label="Applying initial changes">
|
||||||
</header>
|
<span class="sr-only">Loading…</span>
|
||||||
<main id="message-list" class="message-list">
|
|
||||||
<!-- Messages will be dynamically inserted here -->
|
|
||||||
</main>
|
|
||||||
<footer id="input-area" class="input-area">
|
|
||||||
<input type="text" id="user-input" placeholder="Type your answer..." autocomplete="off" disabled>
|
|
||||||
<button id="send-button" disabled>Send</button>
|
|
||||||
</footer>
|
|
||||||
</div>
|
</div>
|
||||||
|
<p class="hint"><?= ($_SERVER['HTTP_HOST'] ?? '') === 'appwizzy.com' ? 'AppWizzy' : 'Flatlogic' ?> AI is collecting your requirements and applying the first changes.</p>
|
||||||
<script src="assets/js/main.js?v=<?php echo time(); ?>"></script>
|
<p class="hint">This page will update automatically as the plan is implemented.</p>
|
||||||
|
<p>Runtime: PHP <code><?= htmlspecialchars($phpVersion) ?></code> — UTC <code><?= htmlspecialchars($now) ?></code></p>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
Page updated: <?= htmlspecialchars($now) ?> (UTC)
|
||||||
|
</footer>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
254
results.php
254
results.php
@ -1,254 +0,0 @@
|
|||||||
<?php
|
|
||||||
// results.php
|
|
||||||
|
|
||||||
require_once __DIR__ . '/ai/LocalAIApi.php';
|
|
||||||
|
|
||||||
$conversation_json = $_POST['conversation'] ?? '';
|
|
||||||
$conversation = json_decode($conversation_json, true);
|
|
||||||
|
|
||||||
$ai_response_text = '';
|
|
||||||
$chart_data_json = '';
|
|
||||||
$error_message = '';
|
|
||||||
|
|
||||||
if ($conversation) {
|
|
||||||
$prompt = "Analyze the following conversation for signs of burnout. The user was asked 10 questions related to burnout. Based on their answers, provide a thoughtful analysis and actionable recommendations. Return a JSON object with two keys: 'analysis_html' and 'chart_data'.\n\n1. `analysis_html`: An HTML string containing a detailed analysis, identifying key themes (e.g., exhaustion, cynicism, inefficacy), a summary of the user's burnout level, and 3-5 actionable recommendations. Use headings, lists, and bold text for readability. Do not include `<html>` or `<body>` tags.\n2. `chart_data`: A JSON object with two keys: `labels` (an array of strings for the chart categories, e.g., ['Exhaustion', 'Cynicism', 'Inefficacy']) and `scores` (an array of integers from 0 to 10 representing the user's score in each category).\n\nHere is the conversation:
|
|
||||||
";
|
|
||||||
foreach ($conversation as $item) {
|
|
||||||
$prompt .= "Q: " . $item['question'] . "\nA: " . $item['answer'] . "\n\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
$resp = LocalAIApi::createResponse(
|
|
||||||
[
|
|
||||||
'input' => [
|
|
||||||
['role' => 'system', 'content' => 'You are a helpful assistant specializing in mental health and burnout analysis. You always respond with a valid JSON object.'],
|
|
||||||
['role' => 'user', 'content' => $prompt],
|
|
||||||
],
|
|
||||||
]
|
|
||||||
);
|
|
||||||
|
|
||||||
if (!empty($resp['success'])) {
|
|
||||||
$ai_response_raw = LocalAIApi::extractText($resp);
|
|
||||||
$ai_response_data = json_decode($ai_response_raw, true);
|
|
||||||
if ($ai_response_data && isset($ai_response_data['analysis_html']) && isset($ai_response_data['chart_data'])) {
|
|
||||||
$ai_response_text = $ai_response_data['analysis_html'];
|
|
||||||
$chart_data_json = json_encode($ai_response_data['chart_data']);
|
|
||||||
} else {
|
|
||||||
$error_message = 'AI response was not in the expected format. Please try again.';
|
|
||||||
// For debugging: $error_message .= "<br>Raw response: " . htmlspecialchars($ai_response_raw);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$error_message = 'Failed to get response from AI. Error: ' . ($resp['error'] ?? 'Unknown error');
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
$error_message = 'No conversation data received.';
|
|
||||||
}
|
|
||||||
|
|
||||||
?><!DOCTYPE html>
|
|
||||||
<html lang="en">
|
|
||||||
<head>
|
|
||||||
<meta charset="UTF-8">
|
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
||||||
<title>Your Burnout Analysis Results</title>
|
|
||||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
||||||
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
|
|
||||||
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600&display=swap" rel="stylesheet">
|
|
||||||
<link rel="stylesheet" href="assets/css/custom.css?v=<?php echo time(); ?>">
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
|
|
||||||
<style>
|
|
||||||
.results-container {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 768px;
|
|
||||||
background-color: #FFFFFF;
|
|
||||||
border-radius: 0.75rem;
|
|
||||||
box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
|
|
||||||
padding: 2rem;
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
.loader {
|
|
||||||
border: 4px solid #f3f4f6;
|
|
||||||
border-radius: 50%;
|
|
||||||
border-top: 4px solid #4F46E5;
|
|
||||||
width: 40px;
|
|
||||||
height: 40px;
|
|
||||||
animation: spin 1s linear infinite;
|
|
||||||
margin: 2rem auto;
|
|
||||||
}
|
|
||||||
@keyframes spin {
|
|
||||||
0% { transform: rotate(0deg); }
|
|
||||||
100% { transform: rotate(360deg); }
|
|
||||||
}
|
|
||||||
.ai-content h2 {
|
|
||||||
font-size: 1.5rem;
|
|
||||||
color: #4F46E5;
|
|
||||||
margin-top: 1.5rem;
|
|
||||||
margin-bottom: 1rem;
|
|
||||||
}
|
|
||||||
.ai-content ul {
|
|
||||||
list-style-position: inside;
|
|
||||||
padding-left: 0;
|
|
||||||
}
|
|
||||||
.ai-content li {
|
|
||||||
margin-bottom: 0.75rem;
|
|
||||||
line-height: 1.6;
|
|
||||||
}
|
|
||||||
#burnoutChart {
|
|
||||||
margin-top: 2rem;
|
|
||||||
margin-bottom: 2rem;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
</head>
|
|
||||||
<body>
|
|
||||||
<div class="chat-container">
|
|
||||||
<header class="chat-header">
|
|
||||||
<h1>Your Burnout Analysis</h1>
|
|
||||||
</header>
|
|
||||||
<main class="message-list" id="results-main">
|
|
||||||
<div class="results-container">
|
|
||||||
<?php if ($error_message): ?>
|
|
||||||
<p style="color: red;"><?php echo htmlspecialchars($error_message); ?></p>
|
|
||||||
<?php elseif ($ai_response_text): ?>
|
|
||||||
<canvas id="burnoutChart"></canvas>
|
|
||||||
<div class="ai-content">
|
|
||||||
<?php echo $ai_response_text; ?>
|
|
||||||
</div>
|
|
||||||
<?php else: ?>
|
|
||||||
<p>Analyzing your responses...</p>
|
|
||||||
<div class="loader"></div>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
</main>
|
|
||||||
<?php if (!$error_message && $ai_response_text): ?>
|
|
||||||
<footer id="input-area" class="input-area">
|
|
||||||
<input type="text" id="user-input" placeholder="Ask a follow-up question..." autocomplete="off">
|
|
||||||
<button id="send-button">Send</button>
|
|
||||||
</footer>
|
|
||||||
<?php endif; ?>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<?php if ($chart_data_json): ?>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const chartData = <?php echo $chart_data_json; ?>;
|
|
||||||
const ctx = document.getElementById('burnoutChart').getContext('2d');
|
|
||||||
|
|
||||||
new Chart(ctx, {
|
|
||||||
type: 'radar',
|
|
||||||
data: {
|
|
||||||
labels: chartData.labels,
|
|
||||||
datasets: [{
|
|
||||||
label: 'Burnout Score',
|
|
||||||
data: chartData.scores,
|
|
||||||
backgroundColor: 'rgba(79, 70, 229, 0.2)',
|
|
||||||
borderColor: '#4F46E5',
|
|
||||||
pointBackgroundColor: '#4F46E5',
|
|
||||||
pointBorderColor: '#fff',
|
|
||||||
pointHoverBackgroundColor: '#fff',
|
|
||||||
pointHoverBorderColor: '#4F46E5'
|
|
||||||
}]
|
|
||||||
},
|
|
||||||
options: {
|
|
||||||
responsive: true,
|
|
||||||
maintainAspectRatio: true,
|
|
||||||
scales: {
|
|
||||||
r: {
|
|
||||||
angleLines: {
|
|
||||||
color: '#E5E7EB'
|
|
||||||
},
|
|
||||||
grid: {
|
|
||||||
color: '#E5E7EB'
|
|
||||||
},
|
|
||||||
pointLabels: {
|
|
||||||
font: {
|
|
||||||
size: 14,
|
|
||||||
family: 'Inter'
|
|
||||||
},
|
|
||||||
color: '#111827'
|
|
||||||
},
|
|
||||||
ticks: {
|
|
||||||
backdropColor: '#f3f4f6',
|
|
||||||
color: '#6B7280',
|
|
||||||
stepSize: 2,
|
|
||||||
beginAtZero: true,
|
|
||||||
max: 10
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
plugins: {
|
|
||||||
legend: {
|
|
||||||
display: false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
<?php if (!$error_message && $ai_response_text): ?>
|
|
||||||
<script>
|
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
|
||||||
const sendButton = document.getElementById('send-button');
|
|
||||||
const userInput = document.getElementById('user-input');
|
|
||||||
const mainContainer = document.getElementById('results-main');
|
|
||||||
const originalConversation = <?php echo json_encode($conversation); ?>;
|
|
||||||
const originalAnalysis = <?php echo json_encode($ai_response_text); ?>;
|
|
||||||
|
|
||||||
function addMessageToUI(text, sender) {
|
|
||||||
const messageElement = document.createElement('div');
|
|
||||||
messageElement.classList.add('message', sender);
|
|
||||||
|
|
||||||
const avatar = document.createElement('div');
|
|
||||||
avatar.classList.add('avatar');
|
|
||||||
avatar.textContent = sender === 'bot' ? 'AI' : 'You';
|
|
||||||
|
|
||||||
const messageContent = document.createElement('div');
|
|
||||||
messageContent.classList.add('message-content');
|
|
||||||
messageContent.innerHTML = text; // Use innerHTML to render formatted AI responses
|
|
||||||
|
|
||||||
if (sender === 'bot') {
|
|
||||||
messageElement.appendChild(avatar);
|
|
||||||
}
|
|
||||||
messageElement.appendChild(messageContent);
|
|
||||||
|
|
||||||
mainContainer.appendChild(messageElement);
|
|
||||||
mainContainer.scrollTop = mainContainer.scrollHeight;
|
|
||||||
}
|
|
||||||
|
|
||||||
async function handleFollowUp() {
|
|
||||||
const userText = userInput.value.trim();
|
|
||||||
if (userText === '') return;
|
|
||||||
|
|
||||||
addMessageToUI(userText, 'user');
|
|
||||||
userInput.value = '';
|
|
||||||
sendButton.disabled = true;
|
|
||||||
|
|
||||||
const response = await fetch('followup.php', {
|
|
||||||
method: 'POST',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json'
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
conversation: originalConversation,
|
|
||||||
analysis: originalAnalysis,
|
|
||||||
follow_up_question: userText
|
|
||||||
})
|
|
||||||
});
|
|
||||||
|
|
||||||
const aiResponseText = await response.text();
|
|
||||||
addMessageToUI(aiResponseText, 'bot');
|
|
||||||
sendButton.disabled = false;
|
|
||||||
userInput.focus();
|
|
||||||
}
|
|
||||||
|
|
||||||
sendButton.addEventListener('click', handleFollowUp);
|
|
||||||
userInput.addEventListener('keydown', (e) => {
|
|
||||||
if (e.key === 'Enter') {
|
|
||||||
handleFollowUp();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
<?php endif; ?>
|
|
||||||
|
|
||||||
</body>
|
|
||||||
</html>
|
|
||||||
Loading…
x
Reference in New Issue
Block a user