302 lines
14 KiB
JavaScript
302 lines
14 KiB
JavaScript
const VIDEOS = [
|
||
{ title: "Кодекс этики: основные принципы", duration: "4:32", category: "Этика" },
|
||
{ title: "Конфликт интересов: как распознать", duration: "3:45", category: "Этика" },
|
||
{ title: "Антикоррупционная политика", duration: "5:18", category: "Антикоррупция" },
|
||
{ title: "Подарки и вознаграждения", duration: "3:20", category: "Антикоррупция" },
|
||
{ title: "Конфиденциальная информация", duration: "4:55", category: "Информация" },
|
||
{ title: "Работа с документами", duration: "3:10", category: "Информация" },
|
||
{ title: "Внутренняя инсайдерская информация", duration: "4:02", category: "Информация" },
|
||
{ title: "Борьба с отмыванием денег", duration: "5:45", category: "Антикоррупция" },
|
||
{ title: "Харассмент и дискриминация", duration: "4:28", category: "Этика" },
|
||
{ title: "Защита персональных данных", duration: "3:55", category: "Информация" },
|
||
{ title: "Взаимодействие с госорганами", duration: "4:15", category: "Антикоррупция" },
|
||
{ title: "Социальные сети: правила поведения", duration: "3:38", category: "Этика" }
|
||
];
|
||
|
||
const NEWS = [
|
||
{
|
||
date: "10 августа 2026",
|
||
title: "Обновлён кодекс корпоративной этики",
|
||
excerpt: "Внесены изменения в раздел о конфликте интересов. Всем сотрудникам необходимо ознакомиться до 1 сентября.",
|
||
tag: "Важно"
|
||
},
|
||
{
|
||
date: "5 августа 2026",
|
||
title: "Ежегодное комплаенс-тестирование",
|
||
excerpt: "Прохождение обязательно для всех сотрудников до 30 сентября. Результаты будут учтены при аттестации.",
|
||
tag: "Обязательно"
|
||
},
|
||
{
|
||
date: "1 августа 2026",
|
||
title: "Новый канал связи для анонимных обращений",
|
||
excerpt: "Запущен телефон доверия для сообщений о нарушениях. Круглосуточно, анонимно.",
|
||
tag: "Новости"
|
||
},
|
||
{
|
||
date: "25 июля 2026",
|
||
title: "Изменения в законодательстве РК",
|
||
excerpt: "Обзор новых требований по противодействию коррупции и отмыванию доходов.",
|
||
tag: "Законодательство"
|
||
}
|
||
];
|
||
|
||
const FAQ = [
|
||
{
|
||
q: "Могу ли я принять подарок от партнёра?",
|
||
a: "Подарки стоимостью до 5 МРП принимать можно без ограничений. Подарки дороже 5 МРП необходимо задекларировать и передать организации. Деньги в любой сумме принимать запрещено."
|
||
},
|
||
{
|
||
q: "Что делать при возникновении конфликта интересов?",
|
||
a: "Немедленно сообщите непосредственному руководителю и в службу комплаенс. Воздержитесь от участия в решении вопроса до урегулирования ситуации."
|
||
},
|
||
{
|
||
q: "Кому сообщать о фактах коррупции?",
|
||
a: "Сообщения принимаются через телефон доверия, email службы комплаенс или через руководителя. Гарантируем конфиденциальность и защиту от преследования."
|
||
},
|
||
{
|
||
q: "Можно ли работать в другой компании по совместительству?",
|
||
a: "Внешнее совместительство разрешено, если не создаёт конфликт интересов. Необходимо получить письменное согласие руководителя и задекларировать в службе комплаенс."
|
||
},
|
||
{
|
||
q: "Как часто нужно проходить комплаенс-обучение?",
|
||
a: "Обязательное обучение — ежегодно. Дополнительно — при изменении законодательства или должностных обязанностей."
|
||
},
|
||
{
|
||
q: "Что считается конфиденциальной информацией?",
|
||
a: "Финансовые данные, персональные данные сотрудников, коммерческие тайны, договоры, стратегические планы. Передача третьим лицам без разрешения запрещена."
|
||
}
|
||
];
|
||
|
||
const QUESTIONS = [
|
||
{
|
||
q: "Максимальная стоимость подарка, который можно принять без декларации:",
|
||
options: ["5 МРП", "10 МРП", "20 МРП", "Любая стоимость"],
|
||
correct: 0
|
||
},
|
||
{
|
||
q: "При возникновении конфликта интересов вы должны:",
|
||
options: ["Решить вопрос самостоятельно", "Сообщить руководителю и в службу комплаенс", "Игнорировать ситуацию", "Уволиться"],
|
||
correct: 1
|
||
},
|
||
{
|
||
q: "Как часто необходимо проходить комплаенс-тестирование?",
|
||
options: ["Раз в 3 года", "По желанию", "Ежегодно", "Только при приёме на работу"],
|
||
correct: 2
|
||
},
|
||
{
|
||
q: "Можно ли принимать денежные подарки от партнёров?",
|
||
options: ["До 10 000 тенге можно", "Можно с разрешения руководителя", "Запрещено в любой сумме", "Можно, если задекларировать"],
|
||
correct: 2
|
||
},
|
||
{
|
||
q: "Что делать с подарком дороже 5 МРП?",
|
||
options: ["Оставить себе", "Передать коллегам", "Задекларировать и передать организации", "Вернуть дарителю"],
|
||
correct: 2
|
||
},
|
||
{
|
||
q: "Конфиденциальная информация включает:",
|
||
options: ["Только финансовые отчёты", "Только персональные данные", "Финансовые данные, ПД, коммерческие тайны", "Только договоры"],
|
||
correct: 2
|
||
},
|
||
{
|
||
q: "Внешнее совместительство:",
|
||
options: ["Полностью запрещено", "Разрешено без ограничений", "Разрешено с согласия руководителя", "Разрешено только в выходные"],
|
||
correct: 2
|
||
},
|
||
{
|
||
q: "Каналы для сообщения о коррупции:",
|
||
options: ["Только лично руководителю", "Телефон доверия, email, руководитель", "Только анонимно", "Сообщать нельзя"],
|
||
correct: 1
|
||
},
|
||
{
|
||
q: "Антикоррупционное обучение обязательно для:",
|
||
options: ["Только руководителей", "Только новых сотрудников", "Всех сотрудников", "Только бухгалтерии"],
|
||
correct: 2
|
||
},
|
||
{
|
||
q: "Нарушение комплаенс-политики может привести к:",
|
||
options: ["Устному замечанию", "Дисциплинарной ответственности вплоть до увольнения", "Никаким последствиям", "Только штрафу"],
|
||
correct: 1
|
||
}
|
||
];
|
||
|
||
let currentQuestion = 0;
|
||
let score = 0;
|
||
let testTaken = false;
|
||
let stats = { lessons: 0, tests: 0, totalScore: 0, lastActivity: null };
|
||
|
||
function loadStats() {
|
||
const saved = localStorage.getItem("complianceStats");
|
||
if (saved) {
|
||
stats = JSON.parse(saved);
|
||
}
|
||
updateStatsDisplay();
|
||
}
|
||
|
||
function saveStats() {
|
||
localStorage.setItem("complianceStats", JSON.stringify(stats));
|
||
updateStatsDisplay();
|
||
}
|
||
|
||
function updateStatsDisplay() {
|
||
document.getElementById("stat-lessons").textContent = stats.lessons;
|
||
document.getElementById("stat-tests").textContent = stats.tests;
|
||
const avg = stats.tests > 0 ? Math.round(stats.totalScore / stats.tests) : 0;
|
||
document.getElementById("stat-average").textContent = avg + "%";
|
||
document.getElementById("stat-last").textContent = stats.lastActivity ? new Date(stats.lastActivity).toLocaleDateString("ru-RU") : "—";
|
||
}
|
||
|
||
function renderVideos() {
|
||
const grid = document.getElementById("video-grid");
|
||
grid.innerHTML = VIDEOS.map(v => `
|
||
<div class="video-card" onclick="watchVideo('${v.title}')">
|
||
<div class="video-thumbnail"></div>
|
||
<div class="video-info">
|
||
<div class="video-title">${v.title}</div>
|
||
<div class="video-meta">
|
||
<span>${v.category}</span>
|
||
<span class="video-duration">${v.duration}</span>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
`).join("");
|
||
}
|
||
|
||
function watchVideo(title) {
|
||
stats.lessons++;
|
||
stats.lastActivity = new Date().toISOString();
|
||
saveStats();
|
||
alert(`▶️ Видео "${title}"\n\nВ реальной версии здесь будет видеоплеер.`);
|
||
}
|
||
|
||
function renderNews() {
|
||
const list = document.getElementById("news-list");
|
||
list.innerHTML = NEWS.map(n => `
|
||
<div class="news-item">
|
||
<div class="news-date">${n.date}</div>
|
||
<div class="news-title">${n.title}</div>
|
||
<div class="news-excerpt">${n.excerpt}</div>
|
||
<span class="news-tag">${n.tag}</span>
|
||
</div>
|
||
`).join("");
|
||
}
|
||
|
||
function renderFAQ() {
|
||
const list = document.getElementById("faq-list");
|
||
list.innerHTML = FAQ.map((item, i) => `
|
||
<div class="faq-item">
|
||
<button class="faq-question" onclick="toggleFAQ(${i})">${item.q}</button>
|
||
<div class="faq-answer">${item.a}</div>
|
||
</div>
|
||
`).join("");
|
||
}
|
||
|
||
function toggleFAQ(index) {
|
||
const items = document.querySelectorAll(".faq-item");
|
||
items[index].classList.toggle("active");
|
||
}
|
||
|
||
function startTest() {
|
||
currentQuestion = 0;
|
||
score = 0;
|
||
testTaken = false;
|
||
document.getElementById("test-start").style.display = "none";
|
||
document.getElementById("test-quiz").style.display = "block";
|
||
document.getElementById("test-result").style.display = "none";
|
||
showQuestion();
|
||
}
|
||
|
||
function showQuestion() {
|
||
const q = QUESTIONS[currentQuestion];
|
||
document.getElementById("q-current").textContent = currentQuestion + 1;
|
||
document.getElementById("q-total").textContent = QUESTIONS.length;
|
||
document.getElementById("question-text").textContent = q.q;
|
||
document.getElementById("test-feedback").textContent = "";
|
||
|
||
const options = document.getElementById("test-options");
|
||
options.innerHTML = q.options.map((opt, i) => `
|
||
<button class="test-option" onclick="answer(${i})">${opt}</button>
|
||
`).join("");
|
||
}
|
||
|
||
function answer(selectedIndex) {
|
||
if (testTaken) return;
|
||
testTaken = true;
|
||
|
||
const q = QUESTIONS[currentQuestion];
|
||
const options = document.querySelectorAll(".test-option");
|
||
const feedback = document.getElementById("test-feedback");
|
||
|
||
if (selectedIndex === q.correct) {
|
||
options[selectedIndex].classList.add("correct");
|
||
feedback.textContent = "✅ Правильно!";
|
||
feedback.style.color = "#48bb78";
|
||
score++;
|
||
} else {
|
||
options[selectedIndex].classList.add("wrong");
|
||
options[q.correct].classList.add("correct");
|
||
feedback.textContent = "❌ Неправильно";
|
||
feedback.style.color = "#f56565";
|
||
}
|
||
|
||
setTimeout(() => {
|
||
currentQuestion++;
|
||
if (currentQuestion < QUESTIONS.length) {
|
||
testTaken = false;
|
||
showQuestion();
|
||
} else {
|
||
finishTest();
|
||
}
|
||
}, 2000);
|
||
}
|
||
|
||
function finishTest() {
|
||
const percent = Math.round((score / QUESTIONS.length) * 100);
|
||
|
||
stats.tests++;
|
||
stats.totalScore += percent;
|
||
stats.lastActivity = new Date().toISOString();
|
||
saveStats();
|
||
|
||
document.getElementById("test-quiz").style.display = "none";
|
||
document.getElementById("test-result").style.display = "block";
|
||
document.getElementById("result-score").textContent = `${score} из ${QUESTIONS.length}`;
|
||
document.getElementById("result-percent").textContent = `${percent}%`;
|
||
|
||
let message = "";
|
||
if (percent >= 90) {
|
||
message = "🎉 Отличный результат! Вы хорошо знаете комплаенс-политику.";
|
||
} else if (percent >= 70) {
|
||
message = "👍 Хороший результат. Рекомендуется повторить отдельные темы.";
|
||
} else {
|
||
message = "⚠️ Рекомендуем пройти обучение заново и изучить материалы.";
|
||
}
|
||
document.getElementById("result-message").textContent = message;
|
||
}
|
||
|
||
function resetStats() {
|
||
if (confirm("Сбросить всю статистику?")) {
|
||
stats = { lessons: 0, tests: 0, totalScore: 0, lastActivity: null };
|
||
saveStats();
|
||
}
|
||
}
|
||
|
||
document.getElementById("start-test-btn").addEventListener("click", startTest);
|
||
document.getElementById("restart-test-btn").addEventListener("click", startTest);
|
||
document.getElementById("reset-stats-btn").addEventListener("click", resetStats);
|
||
|
||
document.querySelectorAll(".nav-link").forEach(link => {
|
||
link.addEventListener("click", function(e) {
|
||
e.preventDefault();
|
||
document.querySelectorAll(".nav-link").forEach(l => l.classList.remove("active"));
|
||
this.classList.add("active");
|
||
const target = this.getAttribute("href");
|
||
document.querySelector(target).scrollIntoView({ behavior: "smooth" });
|
||
});
|
||
});
|
||
|
||
loadStats();
|
||
renderVideos();
|
||
renderNews();
|
||
renderFAQ();
|