shtat-sok-employees/index.html

1014 lines
37 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">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Карточки сотрудников СОК-1 СД</title>
<style>
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
body {
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
background: #f5f7fa;
min-height: 100vh;
color: #333;
}
.container {
max-width: 1400px;
margin: 0 auto;
padding: 20px;
}
header {
background: linear-gradient(135deg, #0066cc 0%, #0052a3 100%);
padding: 25px 30px;
margin-bottom: 30px;
box-shadow: 0 2px 10px rgba(0, 102, 204, 0.2);
border-bottom: 3px solid #00a0e3;
}
header h1 {
color: #fff;
font-size: 1.8rem;
margin-bottom: 5px;
font-weight: 600;
}
header p {
color: #e6f0ff;
font-size: 0.95rem;
}
.filters {
background: #fff;
padding: 20px;
border-radius: 4px;
margin-bottom: 25px;
display: flex;
flex-wrap: wrap;
gap: 15px;
align-items: center;
border: 1px solid #e0e6ed;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.filter-group {
display: flex;
flex-direction: column;
gap: 6px;
}
.filter-group label {
font-size: 0.8rem;
color: #555;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.filter-group input,
.filter-group select {
padding: 10px 14px;
border: 1px solid #d0d9e2;
border-radius: 4px;
background: #fff;
color: #333;
font-size: 0.95rem;
transition: border-color 0.2s;
}
.filter-group input:focus,
.filter-group select:focus {
outline: none;
border-color: #0066cc;
box-shadow: 0 0 0 3px rgba(0, 102, 204, 0.1);
}
.stats {
display: grid;
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
gap: 15px;
margin-bottom: 25px;
}
.archive-toggle {
background: #fff;
padding: 15px 20px;
border-radius: 4px;
margin-bottom: 20px;
border: 1px solid #e0e6ed;
display: flex;
align-items: center;
gap: 12px;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.archive-toggle input[type="checkbox"] {
width: 20px;
height: 20px;
cursor: pointer;
}
.archive-toggle label {
font-size: 0.95rem;
color: #333;
font-weight: 500;
cursor: pointer;
}
.stat-card {
background: #fff;
padding: 20px;
border-radius: 4px;
text-align: center;
border-left: 4px solid #0066cc;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.stat-card h3 {
font-size: 2.2rem;
margin-bottom: 5px;
color: #0066cc;
font-weight: 700;
}
.stat-card p {
font-size: 0.85rem;
color: #666;
text-transform: uppercase;
letter-spacing: 0.5px;
}
.employees-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(480px, 1fr));
gap: 20px;
}
.employee-card {
background: #fff;
border-radius: 4px;
padding: 22px;
border: 1px solid #e0e6ed;
transition: all 0.2s;
box-shadow: 0 1px 3px rgba(0, 0, 0, 0.08);
}
.employee-card:hover {
box-shadow: 0 4px 12px rgba(0, 102, 204, 0.15);
border-color: #0066cc;
}
.employee-header {
display: flex;
justify-content: space-between;
align-items: flex-start;
margin-bottom: 18px;
padding-bottom: 15px;
border-bottom: 2px solid #e0e6ed;
}
.employee-name {
font-size: 1.3rem;
color: #0066cc;
margin-bottom: 6px;
font-weight: 600;
}
.employee-position {
color: #666;
font-size: 0.95rem;
font-weight: 500;
}
.employee-number {
background: #0066cc;
color: #fff;
padding: 6px 14px;
border-radius: 4px;
font-size: 0.85rem;
font-weight: 600;
}
.info-grid {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 12px;
}
.info-item {
padding: 12px;
background: #f8fafc;
border-radius: 4px;
border: 1px solid #eef2f6;
}
.info-label {
font-size: 0.7rem;
color: #8898aa;
text-transform: uppercase;
letter-spacing: 0.8px;
margin-bottom: 6px;
font-weight: 600;
}
.info-value {
font-size: 0.95rem;
color: #333;
font-weight: 500;
}
.highlight-1class {
background: #fff8e6 !important;
border-left: 3px solid #f0ad4e;
}
.highlight-11class {
background: #e8f5e9 !important;
border-left: 3px solid #4caf50;
}
.children-section {
margin-top: 18px;
padding: 15px;
background: #f8fafc;
border-radius: 4px;
border: 1px solid #eef2f6;
}
.children-section h4 {
color: #0066cc;
margin-bottom: 12px;
font-size: 0.95rem;
font-weight: 600;
}
.child-item {
padding: 10px;
margin-bottom: 8px;
background: #fff;
border-radius: 4px;
font-size: 0.9rem;
border: 1px solid #eef2f6;
}
.vacation-section {
margin-top: 18px;
padding: 15px;
background: #e8f4fd;
border-radius: 4px;
border: 1px solid #b3d9f2;
}
.vacation-section h4 {
color: #0066cc;
margin-bottom: 12px;
font-size: 0.95rem;
font-weight: 600;
}
.vacation-item {
padding: 10px;
margin-bottom: 8px;
background: #fff;
border-radius: 4px;
font-size: 0.9rem;
display: flex;
justify-content: space-between;
border: 1px solid #eef2f6;
}
.location-badge {
display: inline-block;
background: #e8f4fd;
color: #0066cc;
padding: 6px 12px;
border-radius: 4px;
font-size: 0.85rem;
font-weight: 500;
margin-top: 15px;
border: 1px solid #b3d9f2;
}
.decoration-badge {
display: inline-block;
background: #fff3cd;
color: #856404;
padding: 6px 12px;
border-radius: 4px;
font-size: 0.85rem;
font-weight: 500;
margin-top: 10px;
border: 1px solid #ffc107;
}
.substitute-info {
margin-top: 12px;
padding: 12px;
background: #e8f5e9;
border-radius: 4px;
border: 1px solid #a5d6a7;
font-size: 0.9rem;
color: #2e7d32;
}
.substitute-info strong {
display: block;
margin-bottom: 4px;
}
.modal-overlay {
display: none;
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.5);
z-index: 1000;
justify-content: center;
align-items: center;
}
.modal-overlay.active {
display: flex;
}
.modal {
background: #fff;
border-radius: 8px;
max-width: 600px;
width: 90%;
max-height: 80vh;
overflow-y: auto;
box-shadow: 0 10px 40px rgba(0, 0, 0, 0.3);
}
.modal-header {
background: linear-gradient(135deg, #0066cc 0%, #0052a3 100%);
color: #fff;
padding: 20px;
border-radius: 8px 8px 0 0;
display: flex;
justify-content: space-between;
align-items: center;
}
.modal-header h3 {
font-size: 1.2rem;
font-weight: 600;
}
.modal-close {
background: none;
border: none;
color: #fff;
font-size: 1.5rem;
cursor: pointer;
padding: 0;
line-height: 1;
}
.modal-body {
padding: 20px;
}
.notification-item {
padding: 15px;
margin-bottom: 12px;
border-radius: 6px;
border-left: 4px solid;
}
.notification-item.urgent {
background: #fff3cd;
border-color: #ffc107;
color: #856404;
}
.notification-item.warning {
background: #f8d7da;
border-color: #dc3545;
color: #721c24;
}
.notification-item.info {
background: #d1ecf1;
border-color: #17a2b8;
color: #0c5460;
}
.notification-item h4 {
margin-bottom: 5px;
font-size: 1rem;
}
.notification-item p {
font-size: 0.9rem;
}
.no-results {
text-align: center;
padding: 60px;
color: #8898aa;
font-size: 1.1rem;
grid-column: 1 / -1;
background: #fff;
border-radius: 4px;
border: 1px solid #e0e6ed;
}
@media (max-width: 768px) {
.employees-grid {
grid-template-columns: 1fr;
}
.info-grid {
grid-template-columns: 1fr;
}
.filters {
flex-direction: column;
}
.filter-group {
width: 100%;
}
.filter-group input,
.filter-group select {
width: 100%;
}
header h1 {
font-size: 1.4rem;
}
}
</style>
</head>
<body>
<div class="container">
<header>
<h1>📋 Карточки сотрудников СОК-1 СД</h1>
<p>Корпоративная система управления персоналом | АО «Казахтелеком»</p>
</header>
<div class="archive-toggle">
<input type="checkbox" id="archiveFilter" onchange="applyFilters()">
<label for="archiveFilter">📁 Показать архив (уволенные сотрудники)</label>
</div>
<div class="filters">
<div class="filter-group">
<label>🔍 Поиск</label>
<input type="text" id="searchInput" placeholder="ФИО, должность, телефон...">
</div>
<div class="filter-group">
<label>📍 Дислокация</label>
<select id="locationFilter">
<option value="">Все</option>
</select>
</div>
<div class="filter-group">
<label>👶 Дети до 14 лет</label>
<select id="childrenFilter">
<option value="">Все</option>
<option value="has-children">Есть дети до 14</option>
<option value="1class">1 класс (6-7 лет)</option>
<option value="11class">11 класс (17-18 лет)</option>
</select>
</div>
<div class="filter-group">
<label>📊 Стаж</label>
<select id="experienceFilter">
<option value="">Все</option>
<option value="0-3">До 3 лет</option>
<option value="3-10">3-10 лет</option>
<option value="10+">10+ лет</option>
</select>
</div>
<div class="filter-group">
<label>🏠 Семейное</label>
<select id="familyFilter">
<option value="">Все</option>
<option value="married">Женат/Замужем</option>
<option value="single">Не женат/Не замужем</option>
</select>
</div>
</div>
<div class="stats">
<div class="stat-card">
<h3 id="totalEmployees">0</h3>
<p>Всего сотрудников</p>
</div>
<div class="stat-card">
<h3 id="withChildren">0</h3>
<p>С детьми до 14 лет</p>
</div>
<div class="stat-card">
<h3 id="firstGraders">0</h3>
<p>Дети в 1 класс</p>
</div>
<div class="stat-card">
<h3 id="eleventhGraders">0</h3>
<p>Выпускники 11 класс</p>
</div>
</div>
<div class="employees-grid" id="employeesGrid">
</div>
</div>
<!-- Modal для уведомлений -->
<div class="modal-overlay" id="notificationModal">
<div class="modal">
<div class="modal-header">
<h3>🔔 Уведомления</h3>
<button class="modal-close" onclick="closeModal()">×</button>
</div>
<div class="modal-body" id="notificationBody">
</div>
</div>
</div>
<script>
const employees = [
{
id: 1,
tabNumber: "001234",
fullName: "Иванов Иван Иванович",
birthDate: "15.03.1985",
age: 41,
position: "Старший тренер",
familyStatus: "Женат",
children: [
{ name: "Иванова Анна", age: 7, school: "1 класс" },
{ name: "Иванов Пётр", age: 15, school: "9 класс" }
],
address: "г. Алматы, ул. Абая 123, кв. 45",
phone: "+7 (777) 123-45-67",
experience: "12 лет",
experienceYears: 12,
vacations: [
{ start: "01.06.2025", end: "14.06.2025" },
{ start: "01.12.2025", end: "14.12.2025" }
],
location: "Главный корпус"
},
{
id: 2,
tabNumber: "001235",
fullName: "Петрова Мария Сергеевна",
birthDate: "22.07.1990",
age: 36,
position: "Инструктор по фитнесу",
familyStatus: "Замужем",
children: [
{ name: "Петров Артём", age: 6, school: "1 класс" },
{ name: "Петрова Елена", age: 3, school: "Детский сад" },
{ name: "Петров Дмитрий", age: 18, school: "11 класс" }
],
address: "г. Алматы, пр. Достык 45, кв. 12",
phone: "+7 (777) 234-56-78",
experience: "8 лет",
experienceYears: 8,
vacations: [
{ start: "15.07.2025", end: "28.07.2025" }
],
location: "Фитнес-зал"
},
{
id: 3,
tabNumber: "001236",
fullName: "Сидоров Алексей Петрович",
birthDate: "10.11.1978",
age: 47,
position: "Директор СОК-1",
familyStatus: "Женат",
children: [
{ name: "Сидорова Ольга", age: 20, school: "ВУЗ" }
],
address: "г. Алматы, ул. Казыбек би 78, кв. 90",
phone: "+7 (777) 345-67-89",
experience: "22 года",
experienceYears: 22,
vacations: [
{ start: "10.05.2025", end: "24.05.2025" },
{ start: "10.11.2025", end: "24.11.2025" }
],
location: "Администрация"
},
{
id: 4,
tabNumber: "001237",
fullName: "Ахметова Гульнара Ерлановна",
birthDate: "05.04.1995",
age: 31,
position: "Администратор",
familyStatus: "Не замужем",
children: [],
address: "г. Алматы, ул. Сатпаева 22, кв. 156",
phone: "+7 (777) 456-78-90",
experience: "4 года",
experienceYears: 4,
vacations: [
{ start: "20.08.2025", end: "02.09.2025" }
],
location: "Ресепшн"
},
{
id: 5,
tabNumber: "001238",
fullName: "Козлов Дмитрий Александрович",
birthDate: "18.09.1988",
age: 37,
position: "Тренер по плаванию",
familyStatus: "Женат",
children: [
{ name: "Козлов Максим", age: 7, school: "1 класс" },
{ name: "Козлова Дарья", age: 5, school: "Детский сад" }
],
address: "г. Алматы, ул. Байтурсынова 55, кв. 78",
phone: "+7 (777) 567-89-01",
experience: "10 лет",
experienceYears: 10,
vacations: [
{ start: "05.06.2025", end: "18.06.2025" },
{ start: "05.12.2025", end: "18.12.2025" }
],
location: "Бассейн"
},
{
id: 6,
tabNumber: "001239",
fullName: "Омаров Ержан Болатович",
birthDate: "30.01.1982",
age: 44,
position: "Завхоз",
familyStatus: "Женат",
children: [
{ name: "Омаров Асет", age: 17, school: "11 класс" },
{ name: "Омарова Зарина", age: 12, school: "6 класс" }
],
address: "г. Алматы, ул. Толе би 101, кв. 34",
phone: "+7 (777) 678-90-12",
experience: "15 лет",
experienceYears: 15,
vacations: [
{ start: "15.09.2025", end: "28.09.2025" }
],
location: "Хозяйственный отдел"
},
{
id: 7,
tabNumber: "001240",
fullName: "Нурова Айгуль Ержановна",
birthDate: "12.06.1992",
age: 34,
position: "Менеджер по кадрам",
familyStatus: "Замужем",
children: [
{ name: "Нуров Али", age: 2, school: "До 3 лет" }
],
address: "г. Алматы, ул. Абылай хана 33, кв. 67",
phone: "+7 (777) 789-01-23",
experience: "6 лет",
experienceYears: 6,
vacations: [
{ start: "01.09.2025", end: "14.09.2025", type: "Ежегодный" },
{ start: "15.01.2026", end: "15.07.2026", type: "Декретный" }
],
location: "Отдел кадров",
onDecree: true,
substitute: "Ахметова Гульнара Ерлановна"
},
{
id: 8,
tabNumber: "001241",
fullName: "Ибраев Болатбек Серикович",
birthDate: "25.03.1975",
age: 51,
position: "Главный бухгалтер",
familyStatus: "Женат",
children: [
{ name: "Ибраева Сауле", age: 25, school: "Работает" }
],
address: "г. Алматы, ул. Желтоксан 88, кв. 12",
phone: "+7 (777) 890-12-34",
experience: "28 лет",
experienceYears: 28,
vacations: [
{ start: "10.06.2025", end: "24.06.2025" }
],
location: "Бухгалтерия",
dismissed: true,
dismissDate: "15.01.2025",
dismissReason: "По собственному желанию"
}
];
function calculateAge(birthDate) {
const today = new Date();
const birth = new Date(birthDate.split('.').reverse().join('-'));
let age = today.getFullYear() - birth.getFullYear();
const monthDiff = today.getMonth() - birth.getMonth();
if (monthDiff < 0 || (monthDiff === 0 && today.getDate() < birth.getDate())) {
age--;
}
return age;
}
function parseDate(dateStr) {
const parts = dateStr.split('.');
return new Date(parts[2], parts[1] - 1, parts[0]);
}
function isWithinMonth(dateStr) {
if (!dateStr) return false;
const targetDate = parseDate(dateStr);
const today = new Date();
const oneMonthFromNow = new Date();
oneMonthFromNow.setMonth(oneMonthFromNow.getMonth() + 1);
return targetDate >= today && targetDate <= oneMonthFromNow;
}
function getUpcomingNotifications() {
const notifications = [];
const today = new Date();
employees.forEach(emp => {
if (emp.dismissed) return; // Не показывать уведомления для уволенных
// Проверка отпусков
if (emp.vacations) {
emp.vacations.forEach(vac => {
// Уведомление за месяц до начала отпуска
if (isWithinMonth(vac.start)) {
notifications.push({
type: 'urgent',
title: `Отпуск: ${emp.fullName}`,
message: `Начало отпуска ${vac.start} (${vac.type || 'ежегодный'}). Табельный № ${emp.tabNumber}`
});
}
// Уведомление о выходе из декрета
if (vac.type === 'Декретный' && vac.end) {
if (isWithinMonth(vac.end)) {
notifications.push({
type: 'warning',
title: `Выход из декрета: ${emp.fullName}`,
message: `Выход на работу ${vac.end}. Замещающий: ${emp.substitute || 'не назначен'}`
});
}
}
});
}
// Уведомление о декрете за месяц до начала
if (emp.onDecree) {
const decreeStart = emp.vacations?.find(v => v.type === 'Декретный')?.start;
if (decreeStart && isWithinMonth(decreeStart)) {
notifications.push({
type: 'info',
title: `Декретный отпуск: ${emp.fullName}`,
message: `Начало декрета ${decreeStart}. Замещает: ${emp.substitute || 'не назначен'}`
});
}
}
});
return notifications;
}
function showNotifications() {
const notifications = getUpcomingNotifications();
const modal = document.getElementById('notificationModal');
const body = document.getElementById('notificationBody');
if (notifications.length === 0) {
body.innerHTML = '<p style="color: #28a745; text-align: center; padding: 20px;">✅ Новых уведомлений нет</p>';
} else {
body.innerHTML = notifications.map(n => `
<div class="notification-item ${n.type}">
<h4>${n.title}</h4>
<p>${n.message}</p>
</div>
`).join('');
}
modal.classList.add('active');
}
function closeModal() {
document.getElementById('notificationModal').classList.remove('active');
}
function renderEmployees(data) {
const grid = document.getElementById('employeesGrid');
grid.innerHTML = '';
if (data.length === 0) {
const archiveFilter = document.getElementById('archiveFilter');
const showArchived = archiveFilter ? archiveFilter.checked : false;
grid.innerHTML = '<div class="no-results">' + (showArchived ? '😕 В архиве нет сотрудников' : '😕 Сотрудники не найдены') + '</div>';
return;
}
data.forEach(emp => {
const childrenUnder14 = emp.children ? emp.children.filter(c => c.age < 14) : [];
const firstGraders = emp.children ? emp.children.filter(c => c.age >= 6 && c.age <= 7) : [];
const eleventhGraders = emp.children ? emp.children.filter(c => c.age >= 17 && c.age <= 18) : [];
let childrenHtml = '';
if (emp.children && emp.children.length > 0) {
childrenHtml = '<div class="children-section"><h4>👶 Дети (' + emp.children.length + ')</h4>';
emp.children.forEach(child => {
let childClass = '';
if (child.age >= 6 && child.age <= 7) {
childClass = 'highlight-1class';
} else if (child.age >= 17 && child.age <= 18) {
childClass = 'highlight-11class';
}
childrenHtml += '<div class="child-item ' + childClass + '">' +
child.name + ' (' + child.age + ' лет, ' + child.school + ')';
if (child.age >= 6 && child.age <= 7) {
childrenHtml += ' <strong>🔔 1 класс</strong>';
} else if (child.age >= 17 && child.age <= 18) {
childrenHtml += ' <strong>🎓 Выпускник</strong>';
}
childrenHtml += '</div>';
});
childrenHtml += '</div>';
}
let vacationHtml = '';
if (emp.vacations && emp.vacations.length > 0) {
vacationHtml = '<div class="vacation-section"><h4>🏖 Отпуска</h4>';
emp.vacations.forEach(vac => {
vacationHtml += '<div class="vacation-item"><span>📅 ' + vac.start + ' — ' + vac.end + (vac.type ? ' (' + vac.type + ')' : '') + '</span></div>';
});
vacationHtml += '</div>';
}
let decreeBadge = '';
if (emp.onDecree) {
decreeBadge = '<div class="decoration-badge">🤰 В декретном отпуске</div>';
}
let substituteHtml = '';
if (emp.substitute) {
substituteHtml = '<div class="substitute-info"><strong>👤 Временно замещает:</strong>' + emp.substitute + '</div>';
}
let dismissInfo = '';
if (emp.dismissed) {
dismissInfo = '<div class="vacation-section" style="background: #f8d7da; border-color: #dc3545;"><h4 style="color: #dc3545;">❌ Уволен</h4><div class="vacation-item"><span>📅 Дата: ' + emp.dismissDate + '</span></div><div class="vacation-item"><span>📝 Причина: ' + emp.dismissReason + '</span></div></div>';
}
const card = document.createElement('div');
card.className = 'employee-card';
card.innerHTML = `
<div class="employee-header">
<div>
<div class="employee-name">${emp.fullName}</div>
<div class="employee-position">${emp.position}</div>
</div>
<div class="employee-number">№ ${emp.tabNumber}</div>
</div>
<div class="info-grid">
<div class="info-item">
<div class="info-label">Дата рождения</div>
<div class="info-value">${emp.birthDate} (${emp.age} лет)</div>
</div>
<div class="info-item">
<div class="info-label">Семейное положение</div>
<div class="info-value">${emp.familyStatus}</div>
</div>
<div class="info-item">
<div class="info-label">Стаж работы</div>
<div class="info-value">${emp.experience}</div>
</div>
<div class="info-item">
<div class="info-label">Телефон</div>
<div class="info-value">${emp.phone}</div>
</div>
<div class="info-item" style="grid-column: 1 / -1;">
<div class="info-label">Адрес</div>
<div class="info-value">${emp.address}</div>
</div>
</div>
${childrenHtml}
${vacationHtml}
${dismissInfo}
${decreeBadge}
${substituteHtml}
<div class="location-badge">📍 ${emp.location}</div>
`;
grid.appendChild(card);
});
}
function updateStats(data) {
const total = data.length;
const withChildren = data.filter(e => e.children.some(c => c.age < 14)).length;
const firstGraders = data.filter(e => e.children.some(c => c.age >= 6 && c.age <= 7)).length;
const eleventhGraders = data.filter(e => e.children.some(c => c.age >= 17 && c.age <= 18)).length;
document.getElementById('totalEmployees').textContent = total;
document.getElementById('withChildren').textContent = withChildren;
document.getElementById('firstGraders').textContent = firstGraders;
document.getElementById('eleventhGraders').textContent = eleventhGraders;
}
function populateLocationFilter() {
const locations = [...new Set(employees.map(e => e.location))].sort();
const select = document.getElementById('locationFilter');
locations.forEach(loc => {
const option = document.createElement('option');
option.value = loc;
option.textContent = loc;
select.appendChild(option);
});
}
function applyFilters() {
const searchTerm = document.getElementById('searchInput').value.toLowerCase();
const location = document.getElementById('locationFilter').value;
const childrenFilter = document.getElementById('childrenFilter').value;
const experienceFilter = document.getElementById('experienceFilter').value;
const familyFilter = document.getElementById('familyFilter').value;
const archiveFilter = document.getElementById('archiveFilter');
const showArchived = archiveFilter ? archiveFilter.checked : false;
// Сначала фильтруем по архиву
let baseFiltered = employees.filter(emp => {
return showArchived ? emp.dismissed : !emp.dismissed;
});
let filtered = baseFiltered.filter(emp => {
const matchSearch = emp.fullName.toLowerCase().includes(searchTerm) ||
emp.position.toLowerCase().includes(searchTerm) ||
emp.phone.includes(searchTerm) ||
emp.tabNumber.includes(searchTerm);
const matchLocation = !location || emp.location === location;
let matchChildren = true;
if (childrenFilter === 'has-children') {
matchChildren = emp.children.some(c => c.age < 14);
} else if (childrenFilter === '1class') {
matchChildren = emp.children.some(c => c.age >= 6 && c.age <= 7);
} else if (childrenFilter === '11class') {
matchChildren = emp.children.some(c => c.age >= 17 && c.age <= 18);
}
let matchExperience = true;
if (experienceFilter === '0-3') {
matchExperience = emp.experienceYears < 3;
} else if (experienceFilter === '3-10') {
matchExperience = emp.experienceYears >= 3 && emp.experienceYears < 10;
} else if (experienceFilter === '10+') {
matchExperience = emp.experienceYears >= 10;
}
let matchFamily = true;
if (familyFilter === 'married') {
matchFamily = emp.familyStatus.includes('Женат') || emp.familyStatus.includes('Замужем');
} else if (familyFilter === 'single') {
matchFamily = !matchFamily;
}
return matchSearch && matchLocation && matchChildren && matchExperience && matchFamily;
});
renderEmployees(filtered);
updateStats(filtered);
}
document.getElementById('searchInput').addEventListener('input', applyFilters);
document.getElementById('locationFilter').addEventListener('change', applyFilters);
document.getElementById('childrenFilter').addEventListener('change', applyFilters);
document.getElementById('experienceFilter').addEventListener('change', applyFilters);
document.getElementById('familyFilter').addEventListener('change', applyFilters);
// Показываем уведомления при загрузке
window.addEventListener('load', function() {
setTimeout(function() {
showNotifications();
}, 500);
});
populateLocationFilter();
renderEmployees(employees.filter(emp => !emp.dismissed));
updateStats(employees.filter(emp => !emp.dismissed));
</script>
</body>
</html>