chto-ty-umeesh/index.html

262 lines
10 KiB
HTML
Raw Permalink 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">
<title>HR Onboarding — приём сотрудников</title>
<style>
* { margin: 0; box-sizing: border-box; }
body { font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif; background: #f5f7fa; color: #1a1a1a; padding: 24px; }
.container { max-width: 1200px; margin: 0 auto; }
h1 { font-size: 28px; margin-bottom: 8px; color: #0f141f; }
.subtitle { color: #6b7280; margin-bottom: 32px; }
.layout { display: grid; grid-template-columns: 1fr 1fr; gap: 32px; }
@media (max-width: 900px) { .layout { grid-template-columns: 1fr; } }
.card { background: white; border-radius: 12px; padding: 24px; box-shadow: 0 1px 3px rgba(0,0,0,0.1); }
.card h2 { font-size: 20px; margin-bottom: 20px; color: #0f141f; display: flex; align-items: center; gap: 8px; }
.form-group { margin-bottom: 16px; }
.form-group label { display: block; font-size: 14px; font-weight: 500; margin-bottom: 6px; color: #374151; }
.form-group input, .form-group select { width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: 14px; transition: border-color 0.2s; }
.form-group input:focus, .form-group select:focus { outline: none; border-color: #3b82f6; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.btn { background: #3b82f6; color: white; border: none; padding: 12px 24px; border-radius: 8px; font-size: 14px; font-weight: 500; cursor: pointer; width: 100%; transition: background 0.2s; }
.btn:hover { background: #2563eb; }
.btn:disabled { background: #9ca3af; cursor: not-allowed; }
.status { margin-top: 16px; padding: 12px; border-radius: 8px; font-size: 14px; display: none; }
.status.success { background: #dcfce7; color: #166534; border: 1px solid #86efac; display: block; }
.status.error { background: #fee2e2; color: #991b1b; border: 1px solid #fca5a5; display: block; }
.status.loading { background: #dbeafe; color: #1e40af; border: 1px solid #93c5fd; display: block; }
.search-box { margin-bottom: 16px; }
.search-box input { width: 100%; padding: 10px 12px; border: 1px solid #d1d5db; border-radius: 8px; font-size: 14px; }
table { width: 100%; border-collapse: collapse; }
th, td { padding: 12px; text-align: left; border-bottom: 1px solid #e5e7eb; font-size: 14px; }
th { font-weight: 600; color: #6b7280; background: #f9fafb; }
tr:hover { background: #f9fafb; }
.empty { text-align: center; color: #9ca3af; padding: 40px; }
.badge { display: inline-block; padding: 4px 10px; border-radius: 999px; font-size: 12px; font-weight: 500; }
.badge-new { background: #dbeafe; color: #1e40af; }
.badge-sap { background: #dcfce7; color: #166534; }
.emp-number { font-family: monospace; font-size: 15px; font-weight: 600; color: #059669; }
</style>
</head>
<body>
<div class="container">
<h1>HR Onboarding</h1>
<p class="subtitle">Приём новых сотрудников в систему</p>
<div class="layout">
<div class="card">
<h2>📝 Новый сотрудник</h2>
<form id="employeeForm">
<div class="form-group">
<label>ФИО полностью</label>
<input type="text" name="fullName" placeholder="Иванов Иван Иванович" required>
</div>
<div class="form-row">
<div class="form-group">
<label>Дата рождения</label>
<input type="date" name="birthDate" required>
</div>
<div class="form-group">
<label>ИНН</label>
<input type="text" name="inn" placeholder="123456789012" pattern="\d{12}" required>
</div>
</div>
<div class="form-group">
<label>Подразделение</label>
<select name="department" required>
<option value="">Выберите подразделение</option>
<option value="IT">IT-департамент</option>
<option value="HR">HR-отдел</option>
<option value="Finance">Финансовый отдел</option>
<option value="Sales">Отдел продаж</option>
<option value="Marketing">Маркетинг</option>
<option value="Operations">Операционный отдел</option>
<option value="Legal">Юридический отдел</option>
</select>
</div>
<div class="form-group">
<label>Должность</label>
<input type="text" name="position" placeholder="Менеджер по продажам" required>
</div>
<div class="form-row">
<div class="form-group">
<label>Дата приёма</label>
<input type="date" name="hireDate" required>
</div>
<div class="form-group">
<label>Тип договора</label>
<select name="contractType" required>
<option value="permanent">Бессрочный</option>
<option value="fixed">Срочный</option>
<option value="parttime">Частичная занятость</option>
</select>
</div>
</div>
<button type="submit" class="btn" id="submitBtn">Отправить в SAP</button>
<div id="status" class="status"></div>
</form>
</div>
<div class="card">
<h2>📋 Сотрудники</h2>
<div class="search-box">
<input type="text" id="search" placeholder="Поиск по ФИО, должности, подразделению...">
</div>
<table>
<thead>
<tr>
<th>Табельный</th>
<th>ФИО</th>
<th>Должность</th>
<th>Подразделение</th>
<th>Статус</th>
</tr>
</thead>
<tbody id="employeesTable">
<tr class="empty"><td colspan="5">Сотрудников пока нет</td></tr>
</tbody>
</table>
</div>
</div>
</div>
<script>
// Мок-данные — имитация базы сотрудников
let employees = [];
let nextId = 1001;
// Имитация отправки в SAP
async function sendToSap(employeeData) {
// Имитация задержки сети
await new Promise(resolve => setTimeout(resolve, 1500));
// Генерация табельного номера (как в SAP)
const tabNumber = String(nextId++).padStart(8, '0');
return {
success: true,
tabNumber: tabNumber,
sapId: 'SAP-' + Math.random().toString(36).slice(2, 10).toUpperCase()
};
}
// Отрисовка таблицы
function renderTable(data = employees) {
const tbody = document.getElementById('employeesTable');
if (data.length === 0) {
tbody.innerHTML = '<tr class="empty"><td colspan="5">Сотрудников не найдено</td></tr>';
return;
}
tbody.innerHTML = data.map(emp => `
<tr>
<td><span class="emp-number">${emp.tabNumber}</span></td>
<td>${emp.fullName}</td>
<td>${emp.position}</td>
<td>${emp.department}</td>
<td><span class="badge badge-sap">✓ В SAP</span></td>
</tr>
`).join('');
}
// Поиск
function search(query) {
const q = query.toLowerCase();
const filtered = employees.filter(emp =>
emp.fullName.toLowerCase().includes(q) ||
emp.position.toLowerCase().includes(q) ||
emp.department.toLowerCase().includes(q)
);
renderTable(filtered);
}
// Обработка формы
document.getElementById('employeeForm').addEventListener('submit', async (e) => {
e.preventDefault();
const form = e.target;
const btn = document.getElementById('submitBtn');
const status = document.getElementById('status');
// Сбор данных
const employeeData = {
fullName: form.fullName.value,
birthDate: form.birthDate.value,
inn: form.inn.value,
department: form.department.value,
position: form.position.value,
hireDate: form.hireDate.value,
contractType: form.contractType.value
};
// UI: загрузка
btn.disabled = true;
btn.textContent = 'Отправка в SAP...';
status.className = 'status loading';
status.textContent = '⏳ Подключение к SAP...';
try {
// Отправка в SAP (мок)
const result = await sendToSap(employeeData);
// Добавление в базу
const newEmployee = {
...employeeData,
tabNumber: result.tabNumber,
sapId: result.sapId,
createdAt: new Date().toISOString()
};
employees.unshift(newEmployee);
// UI: успех
status.className = 'status success';
status.innerHTML = `✅ Сотрудник успешно добавлен! <strong>Табельный номер: ${result.tabNumber}</strong>`;
// Сброс формы
form.reset();
renderTable();
} catch (error) {
// UI: ошибка
status.className = 'status error';
status.textContent = '❌ Ошибка подключения к SAP. Попробуйте позже.';
} finally {
btn.disabled = false;
btn.textContent = 'Отправить в SAP';
// Скрыть статус через 5 сек
setTimeout(() => {
status.className = 'status';
}, 5000);
}
});
// Поиск
document.getElementById('search').addEventListener('input', (e) => {
search(e.target.value);
});
// Установка сегодняшней даты по умолчанию
document.querySelector('[name="hireDate"]').valueAsDate = new Date();
</script>
</body>
</html>