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