privet-mozhesh-sozdat-veb-sa/index.html

558 lines
26 KiB
HTML
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.

<!DOCTYPE html>
<html lang="ru" data-theme="light">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1">
<title>TechConf 2026 — Регистрация на мероприятие</title>
<link rel="icon" href="design-system/brand/kt-ai-logo.png">
<link rel="stylesheet" href="design-system/kt-ai-fonts.css">
<link rel="stylesheet" href="design-system/kt-ai-tokens.css">
<link rel="stylesheet" href="design-system/kt-ai-components.css">
<link rel="stylesheet" href="design-system/kt-ai-page.css">
<style>
.kt-ai-hero { background: var(--kt-ai-bg-soft); }
.speaker-card { text-align: center; padding: var(--kt-ai-space-6); }
.speaker-avatar { width: 120px; height: 120px; border-radius: var(--kt-ai-radius-full); object-fit: cover; margin-bottom: var(--kt-ai-space-4); }
.schedule-item { display: flex; gap: var(--kt-ai-space-4); padding: var(--kt-ai-space-4) 0; border-bottom: 1px solid var(--kt-ai-border); }
.schedule-time { min-width: 80px; font-weight: var(--kt-ai-weight-semibold); color: var(--kt-ai-primary); }
.participant-row { display: grid; grid-template-columns: 2fr 1.5fr 1fr 1fr auto; gap: var(--kt-ai-space-3); align-items: center; padding: var(--kt-ai-space-3) 0; }
.participant-header { font-weight: var(--kt-ai-weight-semibold); color: var(--kt-ai-fg-muted); padding-bottom: var(--kt-ai-space-2); border-bottom: 2px solid var(--kt-ai-border-strong); }
.filters-row { display: flex; gap: var(--kt-ai-space-3); flex-wrap: wrap; margin-bottom: var(--kt-ai-space-5); }
.stats-strip { display: flex; gap: var(--kt-ai-space-4); flex-wrap: wrap; margin-bottom: var(--kt-ai-space-6); }
.stat-card { flex: 1; min-width: 140px; background: var(--kt-ai-card-bg); border: 1px solid var(--kt-ai-card-border); border-radius: var(--kt-ai-radius-xl); padding: var(--kt-ai-space-4); text-align: center; }
.stat-value { font-size: var(--kt-ai-text-3xl); font-weight: var(--kt-ai-weight-bold); color: var(--kt-ai-primary); }
.stat-label { font-size: var(--kt-ai-text-sm); color: var(--kt-ai-fg-muted); margin-top: var(--kt-ai-space-1); }
a.kt-ai-btn { text-decoration: none; }
.modal-overlay { position: fixed; inset: 0; background: rgba(0,0,0,0.5); display: none; align-items: center; justify-content: center; z-index: 1000; }
.modal-overlay.active { display: flex; }
.modal-content { background: var(--kt-ai-bg); border-radius: var(--kt-ai-radius-2xl); padding: var(--kt-ai-space-6); max-width: 500px; width: 90%; max-height: 90vh; overflow-y: auto; }
.form-section { margin-bottom: var(--kt-ai-space-5); }
.form-section-title { font-weight: var(--kt-ai-weight-semibold); margin-bottom: var(--kt-ai-space-3); color: var(--kt-ai-fg); }
@media (max-width: 768px) {
.participant-row { grid-template-columns: 1fr; gap: var(--kt-ai-space-2); }
.stats-strip { flex-direction: column; }
}
</style>
</head>
<body class="kt-ai-app">
<header class="kt-ai-pagehead">
<div class="kt-ai-wrap kt-ai-pagehead-in">
<div style="display:flex;align-items:center;gap:var(--kt-ai-space-3)">
<img src="https://code.vibe42.kz/tore/aitu/kt-logo.svg" alt="Казахтелеком" height="28">
<strong>TechConf 2026</strong>
</div>
<span class="kt-ai-spacer"></span>
<span class="kt-ai-chip" data-tone="orange" id="dataModeChip">Демо-данные</span>
<button class="kt-ai-btn" data-variant="ghost" id="themeToggle" title="Переключить тему">
<svg class="kt-icon kt-icon-sm" aria-hidden="true"><use href="#moon"></use></svg>
</button>
<a class="kt-ai-btn" data-variant="primary" href="#register">Зарегистрироваться</a>
</div>
</header>
<section class="kt-ai-hero" data-align="center">
<div class="kt-ai-wrap">
<h1>TechConf 2026</h1>
<p class="kt-ai-hero-sub">Ежегодная технологическая конференция для IT-специалистов, разработчиков и инноваторов Казахстана</p>
<div class="kt-ai-hero-actions">
<a class="kt-ai-btn" data-variant="primary" data-size="lg" href="#register">Зарегистрироваться</a>
<a class="kt-ai-btn" data-size="lg" href="#about">О мероприятии</a>
</div>
</div>
</section>
<section id="about" class="kt-ai-section" data-divider="true">
<div class="kt-ai-wrap">
<div class="kt-ai-section-head">
<h2>О мероприятии</h2>
<p>Два дня интенсивного обмена опытом, нетворкинга и инсайтов от лидеров индустрии</p>
</div>
<div class="kt-ai-grid" style="margin-top:var(--kt-ai-space-9)" data-cols="3">
<article class="kt-ai-tile">
<div class="kt-ai-tile-icon"><svg class="kt-icon kt-icon-lg" aria-hidden="true"><use href="#users"></use></svg></div>
<h3>200+ участников</h3>
<p>Разработчики, менеджеры, предприниматели со всего Казахстана</p>
</article>
<article class="kt-ai-tile">
<div class="kt-ai-tile-icon"><svg class="kt-icon kt-icon-lg" aria-hidden="true"><use href="#sparkles"></use></svg></div>
<h3>15 спикеров</h3>
<p>Эксперты из ведущих технологических компаний</p>
</article>
<article class="kt-ai-tile">
<div class="kt-ai-tile-icon"><svg class="kt-icon kt-icon-lg" aria-hidden="true"><use href="#lightbulb"></use></svg></div>
<h3>10 секций</h3>
<p>AI, веб-разработка, кибербезопасность, управление продуктами</p>
</article>
</div>
</div>
</section>
<section id="schedule" class="kt-ai-section" data-divider="true">
<div class="kt-ai-wrap">
<div class="kt-ai-section-head">
<h2>Программа</h2>
<p>Расписание докладов и активностей</p>
</div>
<div style="margin-top:var(--kt-ai-space-6)">
<div class="schedule-item">
<div class="schedule-time">09:00</div>
<div>
<strong>Регистрация и утренний кофе</strong>
<p style="color:var(--kt-ai-fg-muted);margin-top:var(--kt-ai-space-1)">Зал регистрации</p>
</div>
</div>
<div class="schedule-item">
<div class="schedule-time">10:00</div>
<div>
<strong>Открытие конференции</strong>
<p style="color:var(--kt-ai-fg-muted);margin-top:var(--kt-ai-space-1)">Приветственное слово от организаторов</p>
</div>
</div>
<div class="schedule-item">
<div class="schedule-time">10:30</div>
<div>
<strong>«Будущее AI в Казахстане»</strong>
<p style="color:var(--kt-ai-fg-muted);margin-top:var(--kt-ai-space-1)">Алексей Ким — CEO AI Solutions</p>
</div>
</div>
<div class="schedule-item">
<div class="schedule-time">12:00</div>
<div>
<strong>Обед и нетворкинг</strong>
<p style="color:var(--kt-ai-fg-muted);margin-top:var(--kt-ai-space-1)">Фуд-корт</p>
</div>
</div>
<div class="schedule-item">
<div class="schedule-time">14:00</div>
<div>
<strong>«Микросервисы в продакшене»</strong>
<p style="color:var(--kt-ai-fg-muted);margin-top:var(--kt-ai-space-1)">Мария Петрова — Tech Lead, KazakhTelecom</p>
</div>
</div>
<div class="schedule-item">
<div class="schedule-time">16:00</div>
<div>
<strong>Панельная дискуссия «Карьера в IT»</strong>
<p style="color:var(--kt-ai-fg-muted);margin-top:var(--kt-ai-space-1)">Главная сцена</p>
</div>
</div>
</div>
</div>
</section>
<section id="speakers" class="kt-ai-section" data-divider="true">
<div class="kt-ai-wrap">
<div class="kt-ai-section-head">
<h2>Спикеры</h2>
<p>Эксперты, которые поделятся опытом</p>
</div>
<div class="kt-ai-grid" style="margin-top:var(--kt-ai-space-9)" data-cols="3">
<article class="kt-ai-card speaker-card">
<img src="https://picsum.photos/seed/speaker1/120/120" alt="Алексей Ким" class="speaker-avatar">
<h3>Алексей Ким</h3>
<p style="color:var(--kt-ai-fg-muted)">CEO, AI Solutions</p>
<span class="kt-ai-chip" style="margin-top:var(--kt-ai-space-2)">AI/ML</span>
</article>
<article class="kt-ai-card speaker-card">
<img src="https://picsum.photos/seed/speaker2/120/120" alt="Мария Петрова" class="speaker-avatar">
<h3>Мария Петрова</h3>
<p style="color:var(--kt-ai-fg-muted)">Tech Lead, KazakhTelecom</p>
<span class="kt-ai-chip" style="margin-top:var(--kt-ai-space-2)">Backend</span>
</article>
<article class="kt-ai-card speaker-card">
<img src="https://picsum.photos/seed/speaker3/120/120" alt="Ержан Асанов" class="speaker-avatar">
<h3>Ержан Асанов</h3>
<p style="color:var(--kt-ai-fg-muted)">Product Director, Kaspi</p>
<span class="kt-ai-chip" style="margin-top:var(--kt-ai-space-2)">Product</span>
</article>
</div>
</div>
</section>
<section id="participants" class="kt-ai-section" data-divider="true">
<div class="kt-ai-wrap">
<div class="kt-ai-section-head">
<h2>Участники</h2>
<p>Список зарегистрированных участников</p>
</div>
<div class="stats-strip" style="margin-top:var(--kt-ai-space-6)">
<div class="stat-card">
<div class="stat-value" id="totalParticipants">0</div>
<div class="stat-label">Всего участников</div>
</div>
<div class="stat-card">
<div class="stat-value" id="confirmedCount">0</div>
<div class="stat-label">Подтвердили</div>
</div>
<div class="stat-card">
<div class="stat-value" id="pendingCount">0</div>
<div class="stat-label">Ожидают</div>
</div>
</div>
<div class="filters-row">
<select class="kt-ai-select" id="statusFilter">
<option value="">Все статусы</option>
<option value="confirmed">Подтвердили</option>
<option value="pending">Ожидают</option>
<option value="cancelled">Отменили</option>
</select>
<select class="kt-ai-select" id="companyFilter">
<option value="">Все компании</option>
<option value="KazakhTelecom">KazakhTelecom</option>
<option value="Kaspi">Kaspi</option>
<option value="AI Solutions">AI Solutions</option>
<option value="Freelance">Freelance</option>
</select>
<button class="kt-ai-btn" data-variant="ghost" id="exportBtn">
<svg class="kt-icon kt-icon-sm" aria-hidden="true"><use href="#download"></use></svg>
Экспорт
</button>
</div>
<div class="kt-ai-card" style="padding:var(--kt-ai-space-4)">
<div class="participant-row participant-header">
<div>ФИО</div>
<div>Компания</div>
<div>Статус</div>
<div>Дата</div>
<div></div>
</div>
<div id="participantsList">
<!-- Участники загружаются через JS -->
</div>
<div id="emptyState" class="kt-ai-empty" style="display:none;padding:var(--kt-ai-space-8);text-align:center">
<svg class="kt-icon kt-icon-lg" aria-hidden="true" style="color:var(--kt-ai-fg-faint)"><use href="#users"></use></svg>
<p style="margin-top:var(--kt-ai-space-3);color:var(--kt-ai-fg-muted)">Пока нет участников с выбранными фильтрами</p>
</div>
</div>
</div>
</section>
<section id="register" class="kt-ai-cta">
<div class="kt-ai-wrap" data-width="narrow">
<h2>Регистрация участника</h2>
<p>Заполните форму, чтобы зарегистрироваться на мероприятие</p>
<form id="registrationForm" style="margin-top:var(--kt-ai-space-6);text-align:left">
<div class="form-section">
<div class="form-section-title">Личные данные</div>
<div class="kt-ai-field">
<label>ФИО *</label>
<input class="kt-ai-input" name="fullName" placeholder="Иванов Иван Иванович" required>
</div>
<div class="kt-ai-field">
<label>Email *</label>
<input class="kt-ai-input" name="email" type="email" placeholder="ivan@example.kz" required>
</div>
<div class="kt-ai-field">
<label>Телефон *</label>
<input class="kt-ai-input" name="phone" type="tel" placeholder="+7 777 123 45 67" required>
</div>
</div>
<div class="form-section">
<div class="form-section-title">Профессиональная информация</div>
<div class="kt-ai-field">
<label>Компания *</label>
<input class="kt-ai-input" name="company" placeholder="Название компании" required>
</div>
<div class="kt-ai-field">
<label>Должность *</label>
<input class="kt-ai-input" name="position" placeholder="Разработчик" required>
</div>
<div class="kt-ai-field">
<label>Секция интереса</label>
<select class="kt-ai-select" name="track">
<option value="ai">AI / Machine Learning</option>
<option value="web">Веб-разработка</option>
<option value="security">Кибербезопасность</option>
<option value="product">Управление продуктами</option>
<option value="management">IT-менеджмент</option>
</select>
</div>
</div>
<div class="kt-ai-field" style="display:flex;gap:var(--kt-ai-space-2);align-items:flex-start">
<input type="checkbox" name="consent" id="consent" required style="margin-top:var(--kt-ai-space-1)">
<label for="consent" style="color:var(--kt-ai-fg-muted;font-size:var(--kt-ai-text-sm)">
Я согласен на обработку персональных данных и получение информации о мероприятии *
</label>
</div>
<button type="submit" class="kt-ai-btn" data-variant="primary" data-size="lg" style="width:100%;margin-top:var(--kt-ai-space-4)">
Зарегистрироваться
</button>
</form>
</div>
</section>
<footer class="kt-ai-wrap kt-ai-pagefoot">
<span>© 2026 TechConf Kazakhstan</span>
<span class="kt-ai-spacer"></span>
<span style="color:var(--kt-ai-fg-muted)">Astana, Казахстан</span>
</footer>
<!-- Модальное окно подтверждения -->
<div class="modal-overlay" id="successModal">
<div class="modal-content" style="text-align:center">
<div style="width:64px;height:64px;border-radius:var(--kt-ai-radius-full);background:var(--kt-ai-bg-soft);display:flex;align-items:center;justify-content:center;margin:0 auto var(--kt-ai-space-4)">
<svg class="kt-icon kt-icon-lg" aria-hidden="true" style="color:var(--kt-ai-primary)"><use href="#check"></use></svg>
</div>
<h2 style="margin-bottom:var(--kt-ai-space-2)">Регистрация успешна!</h2>
<p style="color:var(--kt-ai-fg-muted);margin-bottom:var(--kt-ai-space-4)">Вы зарегистрированы на TechConf 2026. Письмо с подтверждением отправлено на ваш email.</p>
<button class="kt-ai-btn" data-variant="primary" id="closeModal">Отлично</button>
</div>
</div>
<!-- Модальное окно редактирования -->
<div class="modal-overlay" id="editModal">
<div class="modal-content">
<h2 style="margin-bottom:var(--kt-ai-space-4)">Редактирование участника</h2>
<form id="editForm">
<input type="hidden" name="id">
<div class="kt-ai-field">
<label>ФИО</label>
<input class="kt-ai-input" name="fullName" required>
</div>
<div class="kt-ai-field">
<label>Email</label>
<input class="kt-ai-input" name="email" type="email" required>
</div>
<div class="kt-ai-field">
<label>Компания</label>
<input class="kt-ai-input" name="company" required>
</div>
<div class="kt-ai-field">
<label>Статус</label>
<select class="kt-ai-select" name="status">
<option value="pending">Ожидает</option>
<option value="confirmed">Подтверждён</option>
<option value="cancelled">Отменён</option>
</select>
</div>
<div style="display:flex;gap:var(--kt-ai-space-3);margin-top:var(--kt-ai-space-5)">
<button type="button" class="kt-ai-btn" data-variant="ghost" id="cancelEdit">Отмена</button>
<button type="submit" class="kt-ai-btn" data-variant="primary">Сохранить</button>
</div>
</form>
</div>
</div>
<script src="design-system/icons/kt-ai-icons.js"></script>
<script>
// === Демо-данные для начального заполнения ===
const DEMO_PARTICIPANTS = [
{ id: 1, fullName: "Иванов Иван", email: "ivan@kazakhtelecom.kz", phone: "+7 777 111 22 33", company: "KazakhTelecom", position: "Разработчик", track: "web", status: "confirmed", registeredAt: "2026-09-10" },
{ id: 2, fullName: "Петрова Мария", email: "maria@kaspi.kz", phone: "+7 777 222 33 44", company: "Kaspi", position: "Product Manager", track: "product", status: "confirmed", registeredAt: "2026-09-11" },
{ id: 3, fullName: "Асанов Ержан", email: "erjan@aisolutions.kz", phone: "+7 777 333 44 55", company: "AI Solutions", position: "Data Scientist", track: "ai", status: "pending", registeredAt: "2026-09-12" },
{ id: 4, fullName: "Смирнов Алексей", email: "alex@freelance.kz", phone: "+7 777 444 55 66", company: "Freelance", position: "Frontend Dev", track: "web", status: "confirmed", registeredAt: "2026-09-13" },
{ id: 5, fullName: "Ким Ольга", email: "olga@kazakhtelecom.kz", phone: "+7 777 555 66 77", company: "KazakhTelecom", position: "QA Engineer", track: "security", status: "pending", registeredAt: "2026-09-14" },
];
// === Работа с localStorage ===
function getParticipants() {
const stored = localStorage.getItem('techconf_participants');
if (stored) return JSON.parse(stored);
// Первый заход — сохраняем демо-данные
localStorage.setItem('techconf_participants', JSON.stringify(DEMO_PARTICIPANTS));
return DEMO_PARTICIPANTS;
}
function saveParticipants(participants) {
localStorage.setItem('techconf_participants', JSON.stringify(participants));
}
function addParticipant(data) {
const participants = getParticipants();
const newParticipant = {
id: Date.now(),
...data,
status: 'pending',
registeredAt: new Date().toISOString().split('T')[0]
};
participants.push(newParticipant);
saveParticipants(participants);
return newParticipant;
}
function updateParticipant(id, data) {
const participants = getParticipants();
const index = participants.findIndex(p => p.id === id);
if (index !== -1) {
participants[index] = { ...participants[index], ...data };
saveParticipants(participants);
}
}
function deleteParticipant(id) {
const participants = getParticipants();
const filtered = participants.filter(p => p.id !== id);
saveParticipants(filtered);
}
// === Рендеринг ===
function getStatusChip(status) {
const config = {
confirmed: { text: 'Подтверждён', tone: 'green' },
pending: { text: 'Ожидает', tone: 'orange' },
cancelled: { text: 'Отменён', tone: 'red' }
};
const c = config[status] || config.pending;
return `<span class="kt-ai-chip" data-tone="${c.tone}">${c.text}</span>`;
}
function renderParticipants() {
const participants = getParticipants();
const statusFilter = document.getElementById('statusFilter').value;
const companyFilter = document.getElementById('companyFilter').value;
let filtered = participants;
if (statusFilter) filtered = filtered.filter(p => p.status === statusFilter);
if (companyFilter) filtered = filtered.filter(p => p.company === companyFilter);
const listEl = document.getElementById('participantsList');
const emptyEl = document.getElementById('emptyState');
if (filtered.length === 0) {
listEl.innerHTML = '';
emptyEl.style.display = 'block';
} else {
emptyEl.style.display = 'none';
listEl.innerHTML = filtered.map(p => `
<div class="participant-row" data-id="${p.id}">
<div>
<div style="font-weight:var(--kt-ai-weight-medium)">${escapeHtml(p.fullName)}</div>
<div style="font-size:var(--kt-ai-text-sm);color:var(--kt-ai-fg-muted)">${escapeHtml(p.email)}</div>
</div>
<div style="color:var(--kt-ai-fg-muted)">${escapeHtml(p.company)}</div>
<div>${getStatusChip(p.status)}</div>
<div style="color:var(--kt-ai-fg-muted);font-size:var(--kt-ai-text-sm)">${p.registeredAt}</div>
<div style="display:flex;gap:var(--kt-ai-space-2)">
<button class="kt-ai-btn" data-variant="ghost" title="Редактировать" onclick="openEditModal(${p.id})">
<svg class="kt-icon kt-icon-sm" aria-hidden="true"><use href="#pencil"></use></svg>
</button>
<button class="kt-ai-btn" data-variant="ghost" title="Удалить" onclick="confirmDelete(${p.id})">
<svg class="kt-icon kt-icon-sm" aria-hidden="true"><use href="#trash"></use></svg>
</button>
</div>
</div>
`).join('');
}
// Статистика
document.getElementById('totalParticipants').textContent = participants.length;
document.getElementById('confirmedCount').textContent = participants.filter(p => p.status === 'confirmed').length;
document.getElementById('pendingCount').textContent = participants.filter(p => p.status === 'pending').length;
}
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// === Обработчики формы регистрации ===
document.getElementById('registrationForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const data = {
fullName: formData.get('fullName'),
email: formData.get('email'),
phone: formData.get('phone'),
company: formData.get('company'),
position: formData.get('position'),
track: formData.get('track')
};
addParticipant(data);
renderParticipants();
// Показать модальное окно
document.getElementById('successModal').classList.add('active');
this.reset();
});
document.getElementById('closeModal').addEventListener('click', function() {
document.getElementById('successModal').classList.remove('active');
});
// === Фильтры ===
document.getElementById('statusFilter').addEventListener('change', renderParticipants);
document.getElementById('companyFilter').addEventListener('change', renderParticipants);
// === Экспорт (имитация) ===
document.getElementById('exportBtn').addEventListener('click', function() {
const participants = getParticipants();
const csv = 'ФИО,Email,Телефон,Компания,Должность,Статус,Дата\n' +
participants.map(p => `"${p.fullName}","${p.email}","${p.phone}","${p.company}","${p.position}","${p.status}","${p.registeredAt}"`).join('\n');
const blob = new Blob([csv], { type: 'text/csv' });
const url = URL.createObjectURL(blob);
const a = document.createElement('a');
a.href = url;
a.download = 'participants.csv';
a.click();
URL.revokeObjectURL(url);
});
// === Редактирование ===
window.openEditModal = function(id) {
const participants = getParticipants();
const p = participants.find(x => x.id === id);
if (!p) return;
const form = document.getElementById('editForm');
form.id.value = p.id;
form.fullName.value = p.fullName;
form.email.value = p.email;
form.company.value = p.company;
form.status.value = p.status;
document.getElementById('editModal').classList.add('active');
};
document.getElementById('cancelEdit').addEventListener('click', function() {
document.getElementById('editModal').classList.remove('active');
});
document.getElementById('editForm').addEventListener('submit', function(e) {
e.preventDefault();
const formData = new FormData(this);
const id = parseInt(formData.get('id'));
updateParticipant(id, {
fullName: formData.get('fullName'),
email: formData.get('email'),
company: formData.get('company'),
status: formData.get('status')
});
renderParticipants();
document.getElementById('editModal').classList.remove('active');
});
window.confirmDelete = function(id) {
if (confirm('Удалить этого участника?')) {
deleteParticipant(id);
renderParticipants();
}
};
// === Переключатель темы ===
document.getElementById('themeToggle').addEventListener('click', function() {
const html = document.documentElement;
const current = html.getAttribute('data-theme');
const next = current === 'light' ? 'dark' : 'light';
html.setAttribute('data-theme', next);
this.innerHTML = next === 'light'
? '<svg class="kt-icon kt-icon-sm" aria-hidden="true"><use href="#moon"></use></svg>'
: '<svg class="kt-icon kt-icon-sm" aria-hidden="true"><use href="#sun"></use></svg>';
});
// === Инициализация ===
renderParticipants();
</script>
</body>
</html>