mbmal's picture
мне нужен портал проекта Технозаметки Малышева (канал в телеграме @tsingular)
29e58e3 verified
class AIAssistant extends HTMLElement {
constructor() {
super();
this.isOpen = false;
this.messages = [];
}
connectedCallback() {
this.attachShadow({ mode: 'open' });
this.render();
this.setupEventListeners();
this.loadInitialMessage();
}
render() {
this.shadowRoot.innerHTML = `
<style>
:host {
display: block;
position: fixed;
bottom: 20px;
right: 20px;
z-index: 1000;
}
.ai-toggle-button {
width: 60px;
height: 60px;
border-radius: 50%;
background: linear-gradient(45deg, #00ff88, #00a2ff);
border: none;
color: #050508;
cursor: pointer;
box-shadow: 0 5px 20px rgba(0, 255, 136, 0.4);
transition: all 0.3s ease;
display: flex;
align-items: center;
justify-content: center;
font-size: 1.5rem;
}
.ai-toggle-button:hover {
transform: scale(1.1);
box-shadow: 0 8px 25px rgba(0, 255, 136, 0.6);
}
.ai-chat-window {
position: absolute;
bottom: 70px;
right: 0;
width: 350px;
height: 500px;
background: #0a0a0f;
border: 1px solid #00ff88;
border-radius: 12px;
box-shadow: 0 10px 40px rgba(0, 255, 136, 0.3);
display: none;
flex-direction: column;
}
.ai-chat-window.active {
display: flex;
}
.ai-chat-header {
padding: 16px;
background: linear-gradient(45deg, #00ff88, #00a2ff);
border-radius: 12px 12px 0 0;
color: #050508;
font-weight: 600;
display: flex;
justify-content: space-between;
align-items: center;
}
.ai-chat-messages {
flex: 1;
padding: 16px;
overflow-y: auto;
display: flex;
flex-direction: column;
gap: 12px;
}
.ai-message {
padding: 12px;
border-radius: 8px;
max-width: 80%;
word-wrap: break-word;
}
.ai-message.user {
align-self: flex-end;
background: linear-gradient(45deg, #00a2ff, #00ff88);
color: #050508;
}
.ai-message.assistant {
align-self: flex-start;
background: #1a1a2e;
border: 1px solid #2a2a3e;
}
.ai-chat-input {
padding: 16px;
border-top: 1px solid #2a2a3e;
display: flex;
gap: 8px;
}
.ai-chat-input input {
flex: 1;
padding: 8px 12px;
background: #1a1a2e;
border: 1px solid #2a2a3e;
border-radius: 6px;
color: white;
}
.ai-chat-input button {
padding: 8px 16px;
background: #00ff88;
border: none;
border-radius: 6px;
color: #050508;
font-weight: 600;
cursor: pointer;
}
@media (max-width: 768px) {
.ai-chat-window {
width: 300px;
height: 400px;
right: -50px;
}
}
</style>
<div class="ai-assistant-container">
<button class="ai-toggle-button">
<i data-feather="message-circle"></i>
</button>
<div class="ai-chat-window">
<div class="ai-chat-header">
<span>AI Ассистент Nexus</span>
<button class="close-button">
<i data-feather="x"></i>
</button>
</div>
<div class="ai-chat-messages" id="chat-messages">
<!-- Messages will be added here -->
</div>
<div class="ai-chat-input">
<input type="text" id="chat-input" placeholder="Задайте вопрос...">
<button id="send-button">
<i data-feather="send"></i>
</button>
</div>
</div>
</div>
`;
setTimeout(() => {
if (typeof feather !== 'undefined') {
feather.replace();
}
}, 100);
}
setupEventListeners() {
const toggleButton = this.shadowRoot.querySelector('.ai-toggle-button');
const closeButton = this.shadowRoot.querySelector('.close-button');
const sendButton = this.shadowRoot.querySelector('#send-button');
const chatInput = this.shadowRoot.querySelector('#chat-input');
if (toggleButton) {
toggleButton.addEventListener('click', () => {
this.toggleChat();
});
}
if (closeButton) {
closeButton.addEventListener('click', () => {
this.closeChat();
});
}
if (sendButton && chatInput) {
sendButton.addEventListener('click', () => {
this.sendMessage();
});
chatInput.addEventListener('keypress', (e) => {
if (e.key === 'Enter') {
this.sendMessage();
}
});
}
}
loadInitialMessage() {
const welcomeMessage = {
type: 'assistant',
text: 'Привет! Я ваш AI ассистент Nexus. Могу помочь с информацией о портале, записать на консультацию или ответить на вопросы о технологиях. Чем могу помочь?'
};
this.addMessage(welcomeMessage);
}
toggleChat() {
this.isOpen = !this.isOpen;
const chatWindow = this.shadowRoot.querySelector('.ai-chat-window');
if (chatWindow) {
chatWindow.classList.toggle('active', this.isOpen);
if (this.isOpen) {
const input = this.shadowRoot.querySelector('#chat-input');
if (input) {
input.focus();
}
}
}
closeChat() {
this.isOpen = false;
const chatWindow = this.shadowRoot.querySelector('.ai-chat-window');
if (chatWindow) {
chatWindow.classList.remove('active');
}
}
async sendMessage() {
const input = this.shadowRoot.querySelector('#chat-input');
if (!input || !input.value.trim()) return;
const userMessage = {
type: 'user',
text: input.value.trim()
};
this.addMessage(userMessage);
const userText = input.value;
input.value = '';
// Simulate AI response
this.simulateAIResponse(userText);
}
async simulateAIResponse(userMessage) {
// Show typing indicator
this.showTypingIndicator();
// Simulate API call delay
setTimeout(async () => {
this.hideTypingIndicator();
let responseText = '';
if (userMessage.toLowerCase().includes('консультация') || userMessage.toLowerCase().includes('запись')) {
responseText = 'Отлично! Для записи на консультацию перейдите в раздел "Консультации" или свяжитесь напрямую через Telegram @tsingular. Хотите, чтобы я открыл соответствующий раздел?';
} else if (userMessage.toLowerCase().includes('новости')) {
responseText = 'В разделе "Новости" вы найдете свежие технологические тренды, аналитику и инсайты от Алексея Малышева.';
} else if (userMessage.toLowerCase().includes('обучение')) {
responseText = 'Раздел "Обучение" содержит образовательные материалы, курсы и руководства по современным технологиям.';
} else {
responseText = 'Интересный вопрос! Я могу помочь с информацией о различных разделах портала, технологиях или организации консультации. Что именно вас интересует?';
}
const assistantMessage = {
type: 'assistant',
text: responseText
};
this.addMessage(assistantMessage);
}, 1500);
}
showTypingIndicator() {
const messagesContainer = this.shadowRoot.querySelector('#chat-messages');
if (messagesContainer) {
const typingElement = document.createElement('div');
typingElement.className = 'ai-message assistant typing-indicator';
typingElement.innerHTML = '<div class="typing-dots"><span></span><span></span><span></span></div>';
messagesContainer.appendChild(typingElement);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
hideTypingIndicator() {
const messagesContainer = this.shadowRoot.querySelector('#chat-messages');
if (messagesContainer) {
const typingElement = messagesContainer.querySelector('.typing-indicator');
if (typingElement) {
typingElement.remove();
}
}
}
addMessage(message) {
const messagesContainer = this.shadowRoot.querySelector('#chat-messages');
if (messagesContainer) {
const messageElement = document.createElement('div');
messageElement.className = `ai-message ${message.type}`;
messageElement.textContent = message.text;
messagesContainer.appendChild(messageElement);
messagesContainer.scrollTop = messagesContainer.scrollHeight;
}
}
}
customElements.define('ai-assistant', AIAssistant);
// Global AI Assistant functions
function initializeAIAssistant() {
// AI Assistant is already initialized by the component
console.log('AI Assistant initialized');
}
function toggleAIAssistant() {
const assistant = document.querySelector('ai-assistant');
if (assistant) {
assistant.toggleChat();
}
}