nexus-ai-bot / script.js
TopBoss's picture
now fix the full website and make it look nice, follow the rules
bbcee86 verified
document.addEventListener('DOMContentLoaded', () => {
// --- 1. Chat Simulation Logic ---
const chatContainer = document.getElementById('chat-display');
const chatData = {
'ru-RU': [
{ sender: 'customer', text: 'Привет, есть iPhone 15 Pro Max в наличии?' },
{ sender: 'bot', text: 'Привет! Да, iPhone 15 Pro Max в наличии. Есть варианты в цвете Natural Titanium и Blue Titanium с памятью 256GB и 512GB. Отправим сегодня.' },
{ sender: 'customer', text: 'Отлично, давай оформим заказ.' },
{ sender: 'bot', text: 'Принято. Подтверждаю заказ на iPhone 15 Pro Max. Напишите, какой цвет и объем памяти выбрать?' },
{ sender: 'typing' }
],
'en-US': [
{ sender: 'customer', text: 'Hi, is the iPhone 15 Pro Max available?' },
{ sender: 'bot', text: 'Hi! Yes, it\'s in stock. We have Natural Titanium and Blue Titanium, 256GB or 512GB. Shipping today.' },
{ sender: 'customer', text: 'Great, let\'s order it then.' },
{ sender: 'bot', text: 'Perfect. Confirming the iPhone 15 Pro Max order. Which color and storage would you like?' },
{ sender: 'typing' }
]
};
// Detect Language
let userLang = navigator.language || navigator.userLanguage;
if (!chatData[userLang]) {
userLang = 'ru-RU'; // Fallback
}
const conversation = chatData[userLang];
let msgIndex = 0;
function addMessage(msg) {
if (msg.sender === 'typing') {
const typingDiv = document.createElement('div');
typingDiv.className = 'chat-bubble bot typing-indicator';
typingDiv.innerHTML = '<div class="dot"></div><div class="dot"></div><div class="dot"></div>';
chatContainer.appendChild(typingDiv);
chatContainer.scrollTop = chatContainer.scrollHeight;
return;
}
const div = document.createElement('div');
div.className = `chat-bubble ${msg.sender}`;
div.textContent = msg.text;
chatContainer.appendChild(div);
chatContainer.scrollTop = chatContainer.scrollHeight;
}
function playConversation() {
if (msgIndex < conversation.length) {
const msg = conversation[msgIndex];
addMessage(msg);
msgIndex++;
const delay = msg.sender === 'typing' ? 1500 : (msg.text.length * 50 + 800);
setTimeout(playConversation, delay);
} else {
// Loop after a pause
setTimeout(() => {
chatContainer.innerHTML = '';
msgIndex = 0;
playConversation();
}, 4000);
}
}
// Start Chat
setTimeout(playConversation, 1000);
// --- 2. Three.js Scene (Floating Spheres) ---
const canvasContainer = document.getElementById('canvas-container');
// Scene Setup
const scene = new THREE.Scene();
// Light background handled by CSS, Three.js canvas is transparent
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
camera.position.z = 5;
const renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setPixelRatio(window.devicePixelRatio);
canvasContainer.appendChild(renderer.domElement);
// Lighting
const ambientLight = new THREE.AmbientLight(0xffffff, 0.6);
scene.add(ambientLight);
const pointLight = new THREE.PointLight(0xffffff, 1);
pointLight.position.set(10, 10, 10);
scene.add(pointLight);
const pointLight2 = new THREE.PointLight(0xD58A60, 0.8); // Copper tint light
pointLight2.position.set(-10, -10, 5);
scene.add(pointLight2);
// Spheres
const spheres = [];
const sphereGeometry = new THREE.SphereGeometry(1, 32, 32);
// Material: Polished Copper (using standard material with metalness/roughness for approximation)
const sphereMaterial = new THREE.MeshStandardMaterial({
color: 0xD58A60, // Copper
metalness: 0.7,
roughness: 0.2,
});
// Create multiple spheres
const sphereConfigs = [
{ x: -2, y: 0, z: -2, scale: 0.8, speedY: 0.002 },
{ x: 2.5, y: 1, z: -3, scale: 1.2, speedY: 0.003 },
{ x: 3, y: -1.5, z: -1, scale: 0.5, speedY: 0.001 },
{ x: -1.5, y: -2, z: -4, scale: 0.6, speedY: 0.0025 },
{ x: 0.5, y: 2, z: -5, scale: 1.0, speedY: 0.0015 },
];
sphereConfigs.forEach(config => {
const sphere = new THREE.Mesh(sphereGeometry, sphereMaterial);
sphere.position.set(config.x, config.y, config.z);
sphere.scale.setScalar(config.scale);
sphere.userData = {
baseY: config.y,
speedY: config.speedY,
offset: Math.random() * Math.PI * 2
};
scene.add(sphere);
spheres.push(sphere);
});
// Animation Loop
let time = 0;
function animate() {
requestAnimationFrame(animate);
time += 0.01;
spheres.forEach(sphere => {
// Float animation
sphere.position.y = sphere.userData.baseY + Math.sin(time + sphere.userData.offset) * 0.2;
// Rotation
sphere.rotation.x += 0.002;
sphere.rotation.y += 0.003;
});
renderer.render(scene, camera);
}
animate();
// Responsive Three.js
window.addEventListener('resize', () => {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
});
// --- 3. MacOS Window Tilt Interaction ---
const windowEl = document.querySelector('.mac-window');
const container = document.querySelector('.perspective-container');
if(container && windowEl) {
// Use requestAnimationFrame for smoother performance
let currentX = -8;
let currentY = 4;
let targetX = -8;
let targetY = 4;
const animateTilt = () => {
// Lerp (Linear Interpolation) for smooth movement
currentX += (targetX - currentX) * 0.1;
currentY += (targetY - currentY) * 0.1;
windowEl.style.transform = `rotateX(${currentY}deg) rotateY(${currentX}deg)`;
requestAnimationFrame(animateTilt);
};
animateTilt();
container.addEventListener('mousemove', (e) => {
const rect = container.getBoundingClientRect();
const x = e.clientX - rect.left;
const y = e.clientY - rect.top;
const centerX = rect.width / 2;
const centerY = rect.height / 2;
// Reduced intensity for a more premium feel
targetX = ((x - centerX) / centerX) * -4;
targetY = ((y - centerY) / centerY) * 4;
});
container.addEventListener('mouseleave', () => {
targetX = -8;
targetY = 4;
});
}
// --- 4. FAQ Accordion Logic ---
const faqData = [
{
q: "Зачем мне это нужно?",
a: "Твой бизнес ограничен только временем. Пока ты не отвечаешь, твои конкуренты забирают заказы. Nexus превращает твои чаты в автоматический конвейер продаж, увеличивая прибыль без необходимости нанимать персонал."
},
{
q: "Что делает вас уникальными и отличными от других?",
a: "Мы не используем дешевые скрипты или нестабильные расширения. Nexus строится на официальной интеграции через API Avito, что гарантирует безопасность и скорость. Наш AI использует реальный контекст магазина, обеспечивая качество общения, недоступное обычным ботам."
},
{
q: "Какая гарантия того, что то, что вы говорите, — правда?",
a: "Наша гарантия — это прозрачность технологий. Мы используем официальный API, что исключает риски блокировки аккаунта, а эффективность алгоритма можно оценить уже в первые дни использования по росту ответов и конверсии."
}
];
const faqContainer = document.getElementById('faq-container');
faqData.forEach((item, index) => {
const faqItem = document.createElement('div');
faqItem.className = 'border border-neutral-200 rounded-2xl bg-white overflow-hidden';
faqItem.innerHTML = `
<button class="w-full px-6 py-5 text-left flex justify-between items-center focus:outline-none group">
<span class="text-lg font-medium text-neutral-900 group-hover:text-primary transition-colors">${item.q}</span>
<i data-feather="chevron-down" class="text-neutral-400 transform transition-transform duration-300"></i>
</button>
<div class="accordion-content bg-neutral-50">
<div class="px-6 pb-6 pt-2 text-neutral-600 leading-relaxed">
${item.a}
</div>
</div>
`;
const btn = faqItem.querySelector('button');
const content = faqItem.querySelector('.accordion-content');
const icon = faqItem.querySelector('[data-feather="chevron-down"]');
btn.addEventListener('click', () => {
const isOpen = content.style.maxHeight;
// Close all others (optional, but cleaner)
document.querySelectorAll('.accordion-content').forEach(c => {
c.style.maxHeight = null;
c.classList.remove('open');
});
document.querySelectorAll('.chevron-down').forEach(i => i.style.transform = 'rotate(0deg)');
if (!isOpen) {
content.classList.add('open');
content.style.maxHeight = content.scrollHeight + "px";
icon.style.transform = 'rotate(180deg)';
}
});
faqContainer.appendChild(faqItem);
});
// Re-init icons for dynamic content
feather.replace();
});