- ${msg.senderId !== currentUser.id ? `
${msg.senderName}
` : ''}
-
${escapeHtml(msg.text)}
-
${formatTime(msg.createdAt)}
+// Render News
+function renderNews() {
+ const grid = document.getElementById('newsGrid');
+ grid.innerHTML = siteData.news.map(news => `
+
+

+
+
+ ${news.category}
+ ${formatDate(news.date)}
+
+
${news.title}
+
${news.excerpt}
`).join('');
-
- // Scroll to bottom
- const container = document.getElementById('messagesContainer');
- container.scrollTop = container.scrollHeight;
}
-// Send message
-async function sendMessage() {
- const input = document.getElementById('messageInput');
- const text = input.value.trim();
-
- if (!text || !currentChat) return;
+// Render FAQ
+function renderFAQ() {
+ const container = document.getElementById('faqContainer');
+ container.innerHTML = siteData.faq.map((item, index) => `
+
+
+
+
+ `).join('');
+}
- try {
- const token = localStorage.getItem('vibechat_token');
- const res = await fetch(`${API.chats}/${currentChat.id}/messages`, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${token}`
- },
- body: JSON.stringify({ text })
- });
- const json = await res.json();
-
- if (json.ok) {
- input.value = '';
- await loadMessages(currentChat.id);
- await loadChats(); // Update last message
+// Toggle FAQ
+function toggleFaq(index) {
+ const items = document.querySelectorAll('.faq-item');
+ items.forEach((item, i) => {
+ if (i === index) {
+ item.classList.toggle('active');
} else {
- alert('Ошибка отправки: ' + json.error);
+ item.classList.remove('active');
}
- } catch (e) {
- alert('Ошибка: ' + e.message);
- }
+ });
}
-// Handle enter key
-function handleKeyPress(event) {
- if (event.key === 'Enter') {
- sendMessage();
- }
-}
-
-// Emoji picker
-function toggleEmojiPicker() {
- const picker = document.getElementById('emojiPicker');
- picker.classList.toggle('active');
-}
-
-function insertEmoji(emoji) {
- const input = document.getElementById('messageInput');
- input.value += emoji;
- input.focus();
- document.getElementById('emojiPicker').classList.remove('active');
-}
-
-// Close emoji picker on outside click
-document.addEventListener('click', (e) => {
- const picker = document.getElementById('emojiPicker');
- const btn = document.querySelector('.btn-emoji');
- if (!picker.contains(e.target) && !btn.contains(e.target)) {
- picker.classList.remove('active');
- }
-});
-
-// New chat modal
-function showNewChatModal() {
- document.getElementById('newChatModal').classList.add('active');
- loadUsers();
-}
-
-function closeNewChatModal() {
- document.getElementById('newChatModal').classList.remove('active');
-}
-
-function switchTab(tab) {
- document.querySelectorAll('.tab').forEach(t => t.classList.remove('active'));
- event.target.classList.add('active');
-
- document.getElementById('chatTab').style.display = tab === 'chat' ? 'block' : 'none';
- document.getElementById('groupTab').style.display = tab === 'group' ? 'block' : 'none';
- document.getElementById('channelTab').style.display = tab === 'channel' ? 'block' : 'none';
-}
-
-// Create private chat
-async function createPrivateChat(userId) {
- try {
- const token = localStorage.getItem('vibechat_token');
- const res = await fetch(API.chats, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${token}`
- },
- body: JSON.stringify({ type: 'private', participantId: userId })
- });
- const json = await res.json();
+// Contact Form
+function setupContactForm() {
+ // Phone mask
+ const phoneInput = document.getElementById('contactPhone');
+ phoneInput.addEventListener('input', (e) => {
+ let value = e.target.value.replace(/\D/g, '');
+ if (value.length > 11) value = value.slice(0, 11);
- if (json.ok) {
- closeNewChatModal();
- await loadChats();
- selectChat(json.chat.id);
+ if (value.length > 0) {
+ value = '+7 (' + value.slice(1, 4);
+ }
+ if (value.length > 6) {
+ value = value.slice(0, 6) + ') ' + value.slice(6, 9);
+ }
+ if (value.length > 11) {
+ value = value.slice(0, 11) + '-' + value.slice(11, 13);
+ }
+ if (value.length > 14) {
+ value = value.slice(0, 14) + '-' + value.slice(14, 16);
}
- } catch (e) {
- alert('Ошибка: ' + e.message);
- }
-}
-
-// Create group
-async function createGroup() {
- const name = document.getElementById('groupName').value.trim();
- if (!name) return alert('Введите название группы');
-
- try {
- const token = localStorage.getItem('vibechat_token');
- const res = await fetch(API.chats, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${token}`
- },
- body: JSON.stringify({ type: 'group', name })
- });
- const json = await res.json();
- if (json.ok) {
- closeNewChatModal();
- document.getElementById('groupName').value = '';
- await loadChats();
- selectChat(json.chat.id);
- }
- } catch (e) {
- alert('Ошибка: ' + e.message);
- }
+ e.target.value = value;
+ });
}
-// Create channel
-async function createChannel() {
- const name = document.getElementById('channelName').value.trim();
- if (!name) return alert('Введите название канала');
-
- try {
- const token = localStorage.getItem('vibechat_token');
- const res = await fetch(API.chats, {
- method: 'POST',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${token}`
- },
- body: JSON.stringify({ type: 'channel', name })
- });
- const json = await res.json();
-
- if (json.ok) {
- closeNewChatModal();
- document.getElementById('channelName').value = '';
- await loadChats();
- selectChat(json.chat.id);
- }
- } catch (e) {
- alert('Ошибка: ' + e.message);
- }
-}
-
-// Settings
-function openSettings() {
- const user = JSON.parse(localStorage.getItem('vibechat_user'));
- document.getElementById('settingsAvatar').src = user.avatar;
- document.getElementById('settingsUsername').value = user.username;
- document.getElementById('settingsBio').value = user.bio || '';
- document.getElementById('settingsModal').classList.add('active');
-}
-
-function closeSettings() {
- document.getElementById('settingsModal').classList.remove('active');
-}
-
-async function updateProfile(event) {
+async function submitContact(event) {
event.preventDefault();
- const username = document.getElementById('settingsUsername').value;
- const bio = document.getElementById('settingsBio').value;
+ const name = document.getElementById('contactName').value;
+ const phone = document.getElementById('contactPhone').value;
+ const service = document.getElementById('contactService').value;
try {
- const token = localStorage.getItem('vibechat_token');
- const res = await fetch(API.updateProfile, {
- method: 'PUT',
- headers: {
- 'Content-Type': 'application/json',
- 'Authorization': `Bearer ${token}`
- },
- body: JSON.stringify({ username, bio })
+ const res = await fetch('/api/contact', {
+ method: 'POST',
+ headers: { 'Content-Type': 'application/json' },
+ body: JSON.stringify({ name, phone, service })
});
const json = await res.json();
if (json.ok) {
- localStorage.setItem('vibechat_user', JSON.stringify(json.user));
- currentUser = json.user;
- document.getElementById('currentUserName').textContent = currentUser.username;
- document.getElementById('currentUserAvatar').src = currentUser.avatar;
- closeSettings();
- alert('Профиль обновлён! ✅');
+ alert('✅ ' + json.message);
+ document.getElementById('contactForm').reset();
+ } else {
+ alert('Ошибка: ' + json.error);
}
} catch (e) {
- alert('Ошибка: ' + e.message);
+ alert('Ошибка отправки: ' + e.message);
}
}
-function changeAvatar() {
- const url = prompt('Введите URL аватара:', currentUser.avatar);
- if (url) {
- updateProfile({ preventDefault: () => {} });
+// Select tariff
+function selectTariff(tariffId) {
+ const tariff = siteData.tariffs[currentTariffCategory].find(t => t.id === tariffId);
+ if (!tariff) return;
+
+ const service = currentTariffCategory === 'tv' ? 'Цифровое ТВ' :
+ currentTariffCategory === 'mobile' ? 'Мобильная связь' :
+ currentTariffCategory === 'smart' ? 'Умный дом' : 'Домашний интернет';
+
+ document.getElementById('contactService').value = currentTariffCategory;
+ document.getElementById('contactName').focus();
+
+ alert(`Вы выбрали тариф "${tariff.name}" за ${tariff.price} ₸\n\nЗаполните форму ниже, и мы свяжемся с вами для подключения!`);
+
+ scrollToSection('contacts');
+}
+
+// Select bundle
+function selectBundle(bundleId) {
+ const bundle = siteData.bundles.find(b => b.id === bundleId);
+ if (!bundle) return;
+
+ document.getElementById('contactService').value = 'bundle';
+ document.getElementById('contactName').focus();
+
+ alert(`Вы выбрали пакет "${bundle.name}" за ${bundle.bundlePrice} ₸ (экономия ${bundle.discount}%)\n\nЗаполните форму ниже для подключения!`);
+
+ scrollToSection('contacts');
+}
+
+// Scroll to section
+function scrollToSection(id) {
+ const element = document.getElementById(id);
+ if (element) {
+ element.scrollIntoView({ behavior: 'smooth', block: 'start' });
}
}
-// Logout
-async function logout() {
- if (!confirm('Вы уверены, что хотите выйти?')) return;
+// Setup animations
+function setupAnimations() {
+ // Nav scroll effect
+ window.addEventListener('scroll', () => {
+ const nav = document.getElementById('nav');
+ if (window.scrollY > 50) {
+ nav.classList.add('scrolled');
+ } else {
+ nav.classList.remove('scrolled');
+ }
+ });
- try {
- const token = localStorage.getItem('vibechat_token');
- await fetch(API.logout, {
- method: 'POST',
- headers: { 'Authorization': `Bearer ${token}` }
+ // Animate stats
+ const stats = document.querySelectorAll('.stat-number');
+ const observer = new IntersectionObserver((entries) => {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ const target = parseInt(entry.target.dataset.target);
+ animateNumber(entry.target, target);
+ observer.unobserve(entry.target);
+ }
});
- } catch (e) {}
+ }, { threshold: 0.5 });
- localStorage.removeItem('vibechat_token');
- localStorage.removeItem('vibechat_user');
- window.location.href = 'index.html';
+ stats.forEach(stat => observer.observe(stat));
+
+ // Reveal on scroll
+ const reveals = document.querySelectorAll('.service-card, .tariff-card, .bundle-card, .news-card');
+ const revealObserver = new IntersectionObserver((entries) => {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ entry.target.style.opacity = '1';
+ entry.target.style.transform = 'translateY(0)';
+ }
+ });
+ }, { threshold: 0.1 });
+
+ reveals.forEach(el => {
+ el.style.opacity = '0';
+ el.style.transform = 'translateY(30px)';
+ el.style.transition = 'all 0.6s cubic-bezier(0.25, 1, 0.5, 1)';
+ revealObserver.observe(el);
+ });
}
-// Filter chats
-function filterChats() {
- const query = document.getElementById('searchInput').value.toLowerCase();
- const filtered = allChats.filter(c => c.name.toLowerCase().includes(query));
-
- const chatList = document.getElementById('chatList');
- chatList.innerHTML = filtered.map(chat => `
-
-

-
-
${chat.name}
-
${chat.lastMessage ? chat.lastMessage.text : 'Нет сообщений'}
-
-
- `).join('');
+// Animate number
+function animateNumber(element, target) {
+ const duration = 2000;
+ const start = 0;
+ const increment = target / (duration / 16);
+ let current = start;
+
+ const timer = setInterval(() => {
+ current += increment;
+ if (current >= target) {
+ element.textContent = formatNumber(target);
+ clearInterval(timer);
+ } else {
+ element.textContent = formatNumber(Math.floor(current));
+ }
+ }, 16);
}
-// Helper functions
-function formatTime(isoString) {
+// Format number with spaces
+function formatNumber(num) {
+ return num.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ' ');
+}
+
+// Format date
+function formatDate(isoString) {
const date = new Date(isoString);
- const now = new Date();
- const diff = now - date;
-
- if (diff < 60000) return 'Только что';
- if (diff < 3600000) return Math.floor(diff / 60000) + ' мин назад';
- if (diff < 86400000) return Math.floor(diff / 3600000) + ' ч назад';
- if (diff < 604800000) return Math.floor(diff / 86400000) + ' дн назад';
-
- return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'short' });
+ return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' });
}
-function escapeHtml(text) {
- const div = document.createElement('div');
- div.textContent = text;
- return div.innerHTML;
+// Open personal cabinet (placeholder)
+function openPersonal() {
+ alert('Личный кабинет в разработке 🔜\n\nВы можете войти через:\n• Мобильное приложение\n• my.kazakhtelecom.kz');
}
diff --git a/data.json b/data.json
index 111e1c8..12fe48f 100644
--- a/data.json
+++ b/data.json
@@ -1,8 +1,286 @@
{
- "users": [],
- "chats": [],
- "messages": [],
- "groups": [],
- "channels": [],
- "sessions": []
+ "siteSettings": {
+ "heroTitle": "Kazakhtelecom",
+ "heroSubtitle": "Цифровое будущее Казахстана",
+ "heroDescription": "Высокоскоростной интернет, цифровое ТВ и инновационные технологии для вашего дома и бизнеса",
+ "primaryColor": "#0066CC",
+ "accentColor": "#00C9FF"
+ },
+
+ "services": [
+ {
+ "id": "internet",
+ "name": "Домашний интернет",
+ "icon": "🌐",
+ "description": "Высокоскоростной оптоволоконный интернет",
+ "features": ["Скорость до 1 Гбит/с", "Безлимитный трафик", "Стабильное соединение", "Поддержка 24/7"],
+ "color": "#0066CC"
+ },
+ {
+ "id": "tv",
+ "name": "Цифровое TV",
+ "icon": "📺",
+ "description": "Более 200 каналов в высоком качестве",
+ "features": ["4K Ultra HD", "Интерактивное ТВ", "Архив передач", "Родительский контроль"],
+ "color": "#7B2CBF"
+ },
+ {
+ "id": "mobile",
+ "name": "Мобильная связь",
+ "icon": "📱",
+ "description": "Современные тарифы для всей семьи",
+ "features": ["Безлимитные звонки", "5G интернет", "Семейные тарифы", "Роуминг по миру"],
+ "color": "#FF006E"
+ },
+ {
+ "id": "smart",
+ "name": "Умный дом",
+ "icon": "🏠",
+ "description": "Автоматизация и безопасность вашего дома",
+ "features": ["Видеонаблюдение", "Умные датчики", "Управление со смартфона", "Система безопасности"],
+ "color": "#00B4D8"
+ },
+ {
+ "id": "cloud",
+ "name": "Облачные сервисы",
+ "icon": "☁️",
+ "description": "Хранение данных и онлайн-сервисы",
+ "features": ["Облачное хранилище", "Онлайн-офис", "Резервное копирование", "Доступ отовсюду"],
+ "color": "#3A86FF"
+ },
+ {
+ "id": "business",
+ "name": "Бизнесу",
+ "icon": "💼",
+ "description": "Решения для корпоративных клиентов",
+ "features": ["Выделенные линии", "IP-телефония", "ЦОД услуги", "Техническая поддержка"],
+ "color": "#8338EC"
+ }
+ ],
+
+ "tariffs": {
+ "internet": [
+ {
+ "id": "net-start",
+ "name": "Старт",
+ "speed": "100 Мбит/с",
+ "price": 3990,
+ "currency": "₸",
+ "popular": false,
+ "features": ["Безлимитный трафик", "Wi-Fi роутер в аренду", "Антивирус в подарок", "Техподдержка 24/7"]
+ },
+ {
+ "id": "net-optimal",
+ "name": "Оптимальный",
+ "speed": "300 Мбит/с",
+ "price": 5990,
+ "currency": "₸",
+ "popular": true,
+ "features": ["Безлимитный трафик", "Двухдиапазонный роутер", "Антивирус + Родительский контроль", "Приоритетная поддержка"]
+ },
+ {
+ "id": "net-max",
+ "name": "Максимальный",
+ "speed": "1 Гбит/с",
+ "price": 8990,
+ "currency": "₸",
+ "popular": false,
+ "features": ["Гигабитный доступ", "Mesh-система", "Премиум защита", "Персональный менеджер"]
+ },
+ {
+ "id": "net-gamer",
+ "name": "Геймер",
+ "speed": "500 Мбит/с",
+ "price": 7490,
+ "currency": "₸",
+ "popular": false,
+ "features": ["Низкий пинг", "Игровой приоритет", "Защита от DDoS", "Бонусы от партнеров"]
+ }
+ ],
+
+ "tv": [
+ {
+ "id": "tv-light",
+ "name": "Лёгкий",
+ "channels": "100+ каналов",
+ "price": 2990,
+ "currency": "₸",
+ "popular": false,
+ "features": ["HD качество", "Архив 3 дня", "Базовые пакеты", "Пульт в комплекте"]
+ },
+ {
+ "id": "tv-standard",
+ "name": "Стандарт",
+ "channels": "150+ каналов",
+ "price": 4490,
+ "currency": "₸",
+ "popular": true,
+ "features": ["Full HD", "Архив 7 дней", "Премьеры и сериалы", "4K контент"]
+ },
+ {
+ "id": "tv-premium",
+ "name": "Премиум",
+ "channels": "200+ каналов",
+ "price": 6990,
+ "currency": "₸",
+ "popular": false,
+ "features": ["4K Ultra HD", "Архив 14 дней", "Все премиум пакеты", "Онлайн-кинотеатр"]
+ }
+ ],
+
+ "mobile": [
+ {
+ "id": "mobile-light",
+ "name": "Лёгкий",
+ "price": 2500,
+ "currency": "₸",
+ "popular": false,
+ "features": ["Безлимитные звонки по КЗ", "10 ГБ интернета", "SMS безлимит", "Соцсети без трафика"]
+ },
+ {
+ "id": "mobile-standard",
+ "name": "Стандарт",
+ "price": 4500,
+ "currency": "₸",
+ "popular": true,
+ "features": ["Безлимитные звонки", "30 ГБ интернета", "Безлимит на мессенджеры", "5G доступ"]
+ },
+ {
+ "id": "mobile-unlimited",
+ "name": "Безлимит",
+ "price": 7500,
+ "currency": "₸",
+ "popular": false,
+ "features": ["Всё безлимитно", "50 ГБ на высокой скорости", "Роуминг СНГ включён", "Приоритет в сети"]
+ },
+ {
+ "id": "mobile-family",
+ "name": "Семейный",
+ "price": 12000,
+ "currency": "₸",
+ "popular": false,
+ "features": ["4 сим-карты", "Общий пакет 100 ГБ", "Безлимит внутри семьи", "Детский контроль"]
+ }
+ ],
+
+ "smart": [
+ {
+ "id": "smart-basic",
+ "name": "Базовый",
+ "price": 4990,
+ "currency": "₸/мес",
+ "popular": false,
+ "features": ["2 умные лампочки", "1 датчик движения", "Управление со смартфона", "Базовые сценарии"]
+ },
+ {
+ "id": "smart-comfort",
+ "name": "Комфорт",
+ "price": 8990,
+ "currency": "₸/мес",
+ "popular": true,
+ "features": ["5 умных устройств", "Видеодомофон", "Датчики протечки", "Голосовое управление"]
+ },
+ {
+ "id": "smart-security",
+ "name": "Безопасность",
+ "price": 12990,
+ "currency": "₸/мес",
+ "popular": false,
+ "features": ["Видеонаблюдение 4 камеры", "Датчики открытия", "Сигнализация", "Мониторинг 24/7"]
+ }
+ ]
+ },
+
+ "bundles": [
+ {
+ "id": "bundle-family",
+ "name": "Семейный",
+ "description": "Интернет + ТВ + Мобильная связь для всей семьи",
+ "originalPrice": 15470,
+ "bundlePrice": 11990,
+ "discount": 23,
+ "includes": ["Интернет 300 Мбит/с", "Цифровое ТВ 150+ каналов", "2 мобильных тарифа Стандарт"],
+ "popular": true
+ },
+ {
+ "id": "bundle-max",
+ "name": "Максимальный",
+ "description": "Все услуги в одном пакете",
+ "originalPrice": 22970,
+ "bundlePrice": 17990,
+ "discount": 22,
+ "includes": ["Интернет 1 Гбит/с", "Цифровое ТВ Премиум", "Мобильный тариф Безлимит", "Умный дом Комфорт"],
+ "popular": false
+ },
+ {
+ "id": "bundle-gamer",
+ "name": "Геймер",
+ "description": "Для настоящих геймеров и стримеров",
+ "originalPrice": 14480,
+ "bundlePrice": 11490,
+ "discount": 21,
+ "includes": ["Интернет Геймер 500 Мбит/с", "ТВ Стандарт", "Мобильный тариф Стандарт", "Игровые бонусы"],
+ "popular": false
+ }
+ ],
+
+ "news": [
+ {
+ "id": 1,
+ "title": "Запущен 5G в Алматы",
+ "date": "2026-08-15",
+ "category": "technology",
+ "image": "https://picsum.photos/600/400?random=1",
+ "excerpt": "Теперь абоненты могут пользоваться сверхбыстрым интернетом пятого поколения"
+ },
+ {
+ "id": 2,
+ "title": "Новые тарифы на домашний интернет",
+ "date": "2026-08-10",
+ "category": "tariffs",
+ "image": "https://picsum.photos/600/400?random=2",
+ "excerpt": "Увеличили скорости без изменения стоимости для всех тарифов"
+ },
+ {
+ "id": 3,
+ "title": "Умный дом стал доступнее",
+ "date": "2026-08-05",
+ "category": "products",
+ "image": "https://picsum.photos/600/400?random=3",
+ "excerpt": "Скидки до 30% на оборудование для системы умный дом"
+ }
+ ],
+
+ "contacts": {
+ "phone": "123",
+ "phoneFormatted": "123 (бесплатно с городских)",
+ "mobile": "+7 (777) 123-45-67",
+ "email": "info@kazakhtelecom.kz",
+ "address": "г. Алматы, ул. Байтурсынова, 112Б",
+ "social": {
+ "instagram": "https://instagram.com/kazakhtelecom",
+ "facebook": "https://facebook.com/kazakhtelecom",
+ "telegram": "https://t.me/kazakhtelecom",
+ "youtube": "https://youtube.com/kazakhtelecom"
+ }
+ },
+
+ "faq": [
+ {
+ "question": "Как подключить домашний интернет?",
+ "answer": "Оставьте заявку на сайте или позвоните по номеру 123. Наш специалист свяжется с вами в течение 15 минут для уточнения деталей и назначения времени подключения."
+ },
+ {
+ "question": "Какая скорость интернета мне подойдет?",
+ "answer": "Для просмотра сайтов и соцсетей достаточно 100 Мбит/с. Для стриминга 4K и онлайн-игр рекомендуем от 300 Мбит/с. Для умного дома и множества устройств — 1 Гбит/с."
+ },
+ {
+ "question": "Можно ли заморозить услуги на время отъезда?",
+ "answer": "Да, вы можете приостановить действие тарифа на срок от 14 до 90 дней через личный кабинет или по звонку в контактный центр."
+ },
+ {
+ "question": "Предоставляете ли вы оборудование в аренду?",
+ "answer": "Да, мы предоставляем современные Wi-Fi роутеры и TV-приставки в аренду за символическую плату. Также возможна покупка оборудования в рассрочку."
+ }
+ ]
}
diff --git a/index.html b/index.html
index 845dc42..391fd1d 100644
--- a/index.html
+++ b/index.html
@@ -3,136 +3,224 @@
-
VibeChat — Мессенджер будущего
-
+
Kazakhtelecom — Цифровое будущее Казахстана
+
-
-
-