na-kakuyu-temu-mozhno-sozdat/app.js

333 lines
10 KiB
JavaScript
Raw 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.

// Kazakhtelecom Website — JavaScript
const API = '/api/data';
let siteData = null;
let currentTariffCategory = 'internet';
// Initialize
window.addEventListener('DOMContentLoaded', async () => {
await loadData();
renderHero();
renderServices();
renderTariffs('internet');
renderBundles();
renderNews();
renderFAQ();
setupAnimations();
setupTariffTabs();
setupContactForm();
});
// Load data from JSON
async function loadData() {
try {
const res = await fetch(API);
const json = await res.json();
if (json.ok) {
siteData = json.data;
}
} catch (e) {
console.error('Failed to load data:', e);
}
}
// Render Hero
function renderHero() {
const { heroTitle, heroSubtitle, heroDescription } = siteData.siteSettings;
document.getElementById('heroTitle').textContent = heroTitle;
document.getElementById('heroSubtitle').textContent = heroSubtitle;
document.getElementById('heroDescription').textContent = heroDescription;
}
// Render Services
function renderServices() {
const grid = document.getElementById('servicesGrid');
grid.innerHTML = siteData.services.map(service => `
<div class="service-card" style="--service-color: ${service.color}">
<span class="service-icon">${service.icon}</span>
<h3>${service.name}</h3>
<p>${service.description}</p>
<div class="service-features">
${service.features.map(f => `<div class="service-feature">${f}</div>`).join('')}
</div>
</div>
`).join('');
}
// Render Tariffs
function renderTariffs(category) {
currentTariffCategory = category;
const grid = document.getElementById('tariffsGrid');
const tariffs = siteData.tariffs[category] || [];
if (tariffs.length === 0) {
grid.innerHTML = '<p style="text-align:center;color:var(--text-secondary);grid-column:1/-1">Тарифы загружаются...</p>';
return;
}
grid.innerHTML = tariffs.map(tariff => {
const speedOrChannels = tariff.speed || tariff.channels;
const priceLabel = category === 'smart' ? '/мес' : '';
return `
<div class="tariff-card ${tariff.popular ? 'popular' : ''}">
<h3 class="tariff-name">${tariff.name}</h3>
<div class="tariff-speed">${speedOrChannels}</div>
<div class="tariff-price">${tariff.price.toLocaleString()} ${tariff.currency}${priceLabel}</div>
<div class="tariff-features">
${tariff.features.map(f => `<div class="tariff-feature">${f}</div>`).join('')}
</div>
<button class="btn-tariff" onclick="selectTariff('${tariff.id}')">Подключить</button>
</div>
`;
}).join('');
}
// Setup Tariff Tabs
function setupTariffTabs() {
const tabs = document.querySelectorAll('.tab');
tabs.forEach(tab => {
tab.addEventListener('click', () => {
tabs.forEach(t => t.classList.remove('active'));
tab.classList.add('active');
renderTariffs(tab.dataset.category);
});
});
}
// Render Bundles
function renderBundles() {
const grid = document.getElementById('bundlesGrid');
grid.innerHTML = siteData.bundles.map(bundle => `
<div class="bundle-card ${bundle.popular ? 'popular' : ''}">
<h3 class="bundle-name">${bundle.name}</h3>
<p class="bundle-description">${bundle.description}</p>
<div class="bundle-pricing">
<div class="bundle-original">${bundle.originalPrice.toLocaleString()} ₸</div>
<div class="bundle-price">
${bundle.bundlePrice.toLocaleString()} ₸
<span class="bundle-discount">-${bundle.discount}%</span>
</div>
</div>
<div class="bundle-includes">
${bundle.includes.map(item => `<div class="bundle-item">${item}</div>`).join('')}
</div>
<button class="btn-tariff" onclick="selectBundle('${bundle.id}')">Выбрать пакет</button>
</div>
`).join('');
}
// Render News
function renderNews() {
const grid = document.getElementById('newsGrid');
grid.innerHTML = siteData.news.map(news => `
<div class="news-card">
<img src="${news.image}" alt="${news.title}" class="news-image">
<div class="news-content">
<div class="news-meta">
<span class="news-category">${news.category}</span>
<span>${formatDate(news.date)}</span>
</div>
<h3>${news.title}</h3>
<p>${news.excerpt}</p>
</div>
</div>
`).join('');
}
// Render FAQ
function renderFAQ() {
const container = document.getElementById('faqContainer');
container.innerHTML = siteData.faq.map((item, index) => `
<div class="faq-item">
<button class="faq-question" onclick="toggleFaq(${index})">
${item.question}
<span class="faq-icon">+</span>
</button>
<div class="faq-answer">
<p>${item.answer}</p>
</div>
</div>
`).join('');
}
// Toggle FAQ
function toggleFaq(index) {
const items = document.querySelectorAll('.faq-item');
items.forEach((item, i) => {
if (i === index) {
item.classList.toggle('active');
} else {
item.classList.remove('active');
}
});
}
// 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 (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);
}
e.target.value = value;
});
}
async function submitContact(event) {
event.preventDefault();
const name = document.getElementById('contactName').value;
const phone = document.getElementById('contactPhone').value;
const service = document.getElementById('contactService').value;
try {
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) {
alert('✅ ' + json.message);
document.getElementById('contactForm').reset();
} else {
alert('Ошибка: ' + json.error);
}
} catch (e) {
alert('Ошибка отправки: ' + e.message);
}
}
// 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' });
}
}
// 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');
}
});
// 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);
}
});
}, { threshold: 0.5 });
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);
});
}
// 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);
}
// 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);
return date.toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' });
}
// Open personal cabinet (placeholder)
function openPersonal() {
alert('Личный кабинет в разработке 🔜\n\nВы можете войти через:\n• Мобильное приложение\n• my.kazakhtelecom.kz');
}