34591-vm/index.php
Flatlogic Bot 113170fe4d latest 123
2025-10-02 13:51:23 +00:00

594 lines
22 KiB
PHP
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Marketplace Business Assistant</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=Poppins:wght@300;400;500;600&display=swap" rel="stylesheet">
<script src="https://cdn.jsdelivr.net/npm/chart.js"></script>
<style>
:root {
--font-family: 'Poppins', sans-serif;
--pastel-grey: #EAEAEA;
--pastel-blue: #d1e3f3;
--text-light: #888;
--text-dark: #333;
--card-bg: rgba(255, 255, 255, 0.85);
}
body {
font-family: var(--font-family);
margin: 0;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
color: var(--text-dark);
overflow: hidden;
background: linear-gradient(45deg, var(--pastel-grey), var(--pastel-blue));
}
.background-container {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
z-index: -1;
}
#lava-canvas {
position: absolute;
width: 100%;
height: 100%;
z-index: 0;
top: 0;
left: 0;
}
.chat-container {
width: 100%;
max-width: 800px;
height: 90vh;
max-height: 800px;
display: flex;
background: var(--card-bg);
backdrop-filter: blur(10px);
border-radius: 24px;
box-shadow: 0 8px 32px 0 rgba(31, 38, 135, 0.2);
border: 1px solid rgba(255, 255, 255, 0.18);
overflow: hidden;
z-index: 1;
transition: all 0.5s ease;
}
.chat-container.sidebar-active {
max-width: 1200px;
}
.quick-actions-sidebar {
width: 0;
overflow: hidden;
flex-shrink: 0;
background: rgba(255, 255, 255, 0.5);
transition: all 0.5s ease;
border-right: 1px solid rgba(255, 255, 255, 0.3);
}
.chat-container.sidebar-active .quick-actions-sidebar {
width: 220px;
padding: 1.5rem 1rem;
}
.quick-actions-sidebar h3 {
margin-top: 0;
font-weight: 600;
font-size: 1.1rem;
padding-bottom: 0.5rem;
border-bottom: 1px solid #ddd;
margin-bottom: 1rem;
}
.quick-actions {
display: flex;
flex-direction: column;
gap: 0.75rem;
}
.quick-action {
background-color: rgba(255, 255, 255, 0.7);
border: 1px solid transparent;
color: var(--text-dark);
padding: 0.6rem 1.1rem;
border-radius: 12px;
cursor: pointer;
font-size: 0.85rem;
font-weight: 500;
transition: all 0.3s ease;
box-shadow: 0 1px 4px rgba(0,0,0,0.05);
text-align: left;
width: 100%;
}
.quick-action:hover {
transform: translateY(-2px);
box-shadow: 0 4px 12px rgba(0,0,0,0.1);
background: white;
}
.chat-main {
display: flex;
flex-direction: column;
flex-grow: 1;
overflow: hidden;
}
.chat-header {
background: rgba(255, 255, 255, 0.5);
padding: 1rem 1.5rem;
text-align: center;
font-size: 1.2rem;
font-weight: 600;
border-bottom: 1px solid rgba(255, 255, 255, 0.3);
flex-shrink: 0;
}
.chat-messages {
flex-grow: 1;
padding: 1.5rem;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 1rem;
}
.message {
padding: 0.75rem 1.25rem;
border-radius: 18px;
max-width: 85%;
line-height: 1.6;
font-weight: 400;
box-shadow: 0 2px 8px rgba(0,0,0,0.05);
}
.message.assistant {
background-color: rgba(255, 255, 255, 0.9);
align-self: flex-start;
border-bottom-left-radius: 4px;
}
.message.user {
background: linear-gradient(45deg, #a8e6cf, #bde6d9);
color: var(--text-dark);
align-self: flex-end;
border-bottom-right-radius: 4px;
}
.initial-quick-actions {
padding: 1rem 1.5rem 0.5rem;
border-top: 1px solid rgba(255, 255, 255, 0.3);
flex-shrink: 0;
}
.initial-quick-actions .quick-actions {
flex-direction: row;
flex-wrap: wrap;
justify-content: flex-start;
}
.chat-input-container {
padding: 1rem 1.5rem;
border-top: 1px solid rgba(255, 255, 255, 0.2);
flex-shrink: 0;
}
.chat-input {
display: flex;
align-items: center;
background: white;
border-radius: 25px;
padding: 0.25rem;
box-shadow: 0 2px 10px rgba(0,0,0,0.08);
}
.chat-input input[type="text"] {
flex-grow: 1;
border: none;
background: transparent;
border-radius: 20px;
padding: 0.75rem 1rem;
font-size: 1rem;
outline: none;
color: var(--text-dark);
}
.chat-input input[type="file"] {
display: none;
}
.chat-input button, .chat-input .file-upload-label {
background: linear-gradient(45deg, #ffd3b6, #d2b4de);
color: white;
border: none;
border-radius: 50%;
width: 40px;
height: 40px;
cursor: pointer;
font-size: 1.5rem;
display: flex;
justify-content: center;
align-items: center;
transition: transform 0.2s ease;
margin-left: 5px;
}
.chat-input button:hover, .chat-input .file-upload-label:hover {
transform: scale(1.1);
}
.file-upload-label {
background: transparent;
color: #888;
font-size: 1.2rem;
}
.file-upload-label:hover {
color: #333;
}
</style>
</head>
<body>
<div class="background-container">
<canvas id="lava-canvas"></canvas>
</div>
<div class="chat-container" id="chat-container">
<div class="quick-actions-sidebar" id="quick-actions-sidebar">
<h3>Quick Actions</h3>
<div class="quick-actions" id="sidebar-quick-actions">
<!-- Quick actions will be moved here -->
</div>
</div>
<div class="chat-main">
<div class="chat-header">
Marketplace Business Assistant
</div>
<div class="chat-messages" id="chat-messages">
<div class="message assistant">
Hello! I'm your Marketplace Assistant. How can I help you today? You can select one of the quick actions below or upload a file to analyze.
</div>
</div>
<div class="initial-quick-actions" id="initial-quick-actions">
<div class="quick-actions">
<button class="quick-action" data-task="summarize_feedback_weekly">Summarize feedback</button>
<button class="quick-action" data-task="analyze_complaints">Analyze complaints</button>
<button class="quick-action" data-task="generate_seller_dashboard">Generate seller dashboard</button>
<button class="quick-action" data-task="summarize_refunds">Summarize refunds</button>
<button class="quick-action" data-task="draft_response_templates">Draft response templates</button>
<button class="quick-action" data-task="generate_sales_chart">Generate sales report chart</button>
</div>
</div>
<div class="chat-input-container">
<div class="chat-input">
<input type="file" id="file-input" accept=".txt,.csv">
<label for="file-input" class="file-upload-label">
<svg xmlns="http://www.w3.org/2000/svg" width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48"></path></svg>
</label>
<input type="text" id="user-input" placeholder="Type your message...">
<button id="send-button">
<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
</button>
</div>
</div>
</div>
</div>
<script>
const chatContainer = document.getElementById('chat-container');
const chatMessages = document.getElementById('chat-messages');
const userInput = document.getElementById('user-input');
const sendButton = document.getElementById('send-button');
const initialQuickActions = document.getElementById('initial-quick-actions');
const sidebarQuickActions = document.getElementById('sidebar-quick-actions');
const fileInput = document.getElementById('file-input');
let firstInteraction = false;
const assistantResponses = {
summarize_feedback_weekly: "This weeks customer feedback summary: Top 5 issues are 1. Late deliveries (23%), 2. Incorrect item received (15%), 3. Product not as described (12%), 4. Difficulty applying discounts (8%), 5. Slow seller response time (7%).",
draft_response_templates: "Here are some automated response templates: \n**Refunds:** 'Weve received your refund request for order #[Order ID] and are processing it. Youll receive an update within 2-3 business days.' \n**Shipping Delays:** 'We apologize for the delay in your order #[Order ID]. We are looking into it and will provide a status update shortly.'",
analyze_complaints: "Analysis of customer complaints shows that 65% of delivery time issues are concentrated in the West region, primarily with one shipping carrier. I recommend diversifying our shipping partners in that region.",
generate_seller_dashboard: "Weekly Seller Performance Dashboard: \n**Top Performers:** SellerA (99% positive feedback), SellerB (fastest shipping), SellerC (most new products). \n**Needs Attention:** SellerX (rating dropped to 85%), SellerY (2 open disputes).",
summarize_refunds: "Monthly Refund Summary: A total of 152 refunds were processed this month. Top reasons: 1. Item arrived damaged (45%), 2. Item not as described (30%), 3. Accidental order (15%). There is a 20% increase in 'damaged item' refunds for electronics.",
generate_sales_chart: 'Here is the sales report for the last 6 months:<br><canvas id="salesChart" width="400" height="200"></canvas>',
generate_pie_chart: 'Here is a pie chart based on your request:<br><canvas id="pieChart" width="400" height="200"></canvas>'
};
const taskMap = {};
document.querySelectorAll('.quick-action').forEach(button => {
taskMap[button.textContent] = button.dataset.task;
});
function activateSidebar() {
if (firstInteraction) return;
firstInteraction = true;
chatContainer.classList.add('sidebar-active');
const actions = initialQuickActions.querySelectorAll('.quick-action');
actions.forEach(action => {
sidebarQuickActions.appendChild(action.cloneNode(true));
});
initialQuickActions.style.display = 'none';
// Re-bind events for the new sidebar actions
sidebarQuickActions.addEventListener('click', handleQuickActionClick);
}
function renderChart(type = 'bar', canvasId = 'salesChart', data = {}) {
const observer = new MutationObserver((mutationsList, observer) => {
for(const mutation of mutationsList) {
if (mutation.type === 'childList') {
const chartCanvas = document.getElementById(canvasId);
if (chartCanvas) {
const ctx = chartCanvas.getContext('2d');
let chartConfig;
if (type === 'pie') {
chartConfig = {
type: 'pie',
data: {
labels: data.labels || ['Red', 'Blue', 'Yellow'],
datasets: [{
label: 'My First Dataset',
data: data.values || [300, 50, 100],
backgroundColor: [
'rgb(255, 99, 132)',
'rgb(54, 162, 235)',
'rgb(255, 205, 86)'
],
hoverOffset: 4
}]
}
};
} else { // default to bar
chartConfig = {
type: 'bar',
data: {
labels: data.labels || ['January', 'February', 'March', 'April', 'May', 'June'],
datasets: [{
label: 'Sales',
data: data.values || [12, 19, 3, 5, 2, 3],
backgroundColor: 'rgba(75, 192, 192, 0.2)',
borderColor: 'rgba(75, 192, 192, 1)',
borderWidth: 1
}]
},
options: { scales: { y: { beginAtZero: true } } }
};
}
new Chart(ctx, chartConfig);
observer.disconnect();
return;
}
}
}
});
observer.observe(chatMessages, { childList: true, subtree: true });
}
function addMessage(text, sender) {
const messageElement = document.createElement('div');
messageElement.classList.add('message', sender);
if (sender === 'assistant' && text.includes('<canvas')) {
messageElement.innerHTML = text;
} else {
messageElement.innerHTML = text.replace(/\n/g, '<br>');
}
chatMessages.appendChild(messageElement);
chatMessages.scrollTop = chatMessages.scrollHeight;
}
function processMessage(text) {
const trimmedText = text.trim();
const lowerCaseText = trimmedText.toLowerCase();
if (!trimmedText) return;
activateSidebar();
addMessage(trimmedText, 'user');
userInput.value = '';
let task = taskMap[trimmedText] || Object.keys(taskMap).find(key => key.includes(trimmedText));
let response = assistantResponses[task];
let chartType = null;
let chartData = {};
if (!task) {
if (lowerCaseText.includes('pie chart')) {
chartType = 'pie';
task = 'generate_pie_chart';
response = assistantResponses[task];
} else if (lowerCaseText.includes('chart') || lowerCaseText.includes('graph') || lowerCaseText.includes('report')) {
chartType = 'bar';
task = 'generate_sales_chart';
response = assistantResponses[task];
} else if (lowerCaseText === 'hello' || lowerCaseText === 'hi') {
response = 'Hello! How can I help you today?';
}
}
setTimeout(() => {
response = response || "I'm a demo assistant. My capabilities are limited to the quick actions for now. Please select one of the options or upload a file.";
if (task === 'generate_sales_chart' || chartType === 'bar') {
renderChart('bar', 'salesChart', chartData);
} else if (task === 'generate_pie_chart' || chartType === 'pie') {
renderChart('pie', 'pieChart', chartData);
}
addMessage(response, 'assistant');
}, 1200);
}
function handleQuickActionClick(event) {
if (event.target.classList.contains('quick-action')) {
processMessage(event.target.textContent);
}
}
function analyzeFile(file) {
activateSidebar();
const reader = new FileReader();
reader.onload = (e) => {
const content = e.target.result;
let analysis = '';
if (file.type === 'text/csv') {
const lines = content.split('\n').filter(line => line.trim() !== '');
const rowCount = lines.length;
const columnCount = lines.length > 0 ? lines[0].split(',').length : 0;
analysis = `**File Analysis: ${file.name}**\n- **Type:** CSV\n- **Rows:** ${rowCount}\n- **Columns:** ${columnCount}`;
} else { // Default to text
const lineCount = content.split('\n').length;
const wordCount = content.split(/\s+/).filter(Boolean).length;
analysis = `**File Analysis: ${file.name}**\n- **Type:** Text File\n- **Lines:** ${lineCount}\n- **Words:** ${wordCount}`;
}
addMessage(analysis, 'assistant');
};
reader.readAsText(file);
}
fileInput.addEventListener('change', (event) => {
const file = event.target.files[0];
if (file) {
addMessage(`You uploaded ${file.name}. Analyzing...`, 'user');
setTimeout(() => analyzeFile(file), 1200);
}
});
initialQuickActions.addEventListener('click', handleQuickActionClick);
sendButton.addEventListener('click', () => processMessage(userInput.value));
userInput.addEventListener('keypress', (event) => {
if (event.key === 'Enter') {
processMessage(userInput.value);
}
});
// Lava lamp animation script
const canvas = document.getElementById('lava-canvas');
const ctx = canvas.getContext('2d');
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
class Blob {
constructor(x, y, size, color) {
this.x = x;
this.y = y;
this.size = size;
this.color = color;
this.vx = (Math.random() - 0.5) * 0.8;
this.vy = (Math.random() - 0.5) * 0.8;
this.numPoints = Math.floor(Math.random() * 5) + 5;
this.radii = [];
this.angles = [];
this.angleOffsets = [];
for (let i = 0; i < this.numPoints; i++) {
this.radii.push(Math.random() * 0.2 + 0.9);
this.angles.push((i / this.numPoints) * Math.PI * 2);
this.angleOffsets.push(Math.random() * Math.PI * 2);
}
this.time = Math.random() * 1000;
}
update() {
this.x += this.vx;
this.y += this.vy;
this.time += 0.01;
if (this.x < this.size || this.x > canvas.width - this.size) this.vx *= -1;
if (this.y < this.size || this.y > canvas.height - this.size) this.vy *= -1;
for (let i = 0; i < this.numPoints; i++) {
const phase = Math.sin(this.time + this.angleOffsets[i]);
this.radii[i] = 0.9 + 0.1 * phase;
}
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.fillStyle = this.color;
ctx.beginPath();
const startAngle = this.angles[this.numPoints - 1];
const startRadius = this.radii[this.numPoints - 1] * this.size;
ctx.moveTo(Math.cos(startAngle) * startRadius, Math.sin(startAngle) * startRadius);
for (let i = 0; i < this.numPoints; i++) {
const radius = this.radii[i] * this.size;
const nextRadius = this.radii[(i + 1) % this.numPoints] * this.size;
const angle = this.angles[i];
const nextAngle = this.angles[(i + 1) % this.numPoints];
const xc = (Math.cos(angle) * radius + Math.cos(nextAngle) * nextRadius) / 2;
const yc = (Math.sin(angle) * radius + Math.sin(nextAngle) * nextRadius) / 2;
ctx.quadraticCurveTo(Math.cos(angle) * radius, Math.sin(angle) * radius, xc, yc);
}
ctx.closePath();
ctx.fill();
ctx.restore();
}
}
let blobs = [];
const colors = [
'rgba(234, 234, 234, 0.4)',
'rgba(209, 227, 243, 0.4)',
'rgba(192, 217, 234, 0.4)',
'rgba(175, 207, 225, 0.4)'
];
function init() {
blobs = [];
let numBlobs = Math.floor(window.innerWidth / 150);
for (let i = 0; i < numBlobs; i++) {
let size = Math.random() * 80 + 80;
let x = Math.random() * (canvas.width - size * 2) + size;
let y = Math.random() * (canvas.height - size * 2) + size;
let color = colors[i % colors.length];
blobs.push(new Blob(x, y, size, color));
}
}
function animate() {
requestAnimationFrame(animate);
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.globalCompositeOperation = 'lighter';
blobs.forEach(blob => {
blob.update();
blob.draw();
});
}
window.addEventListener('resize', () => {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
init();
});
init();
animate();
</script>
</body>
</html>