Files
ACORE/templates/pages/hr-portal.html
T

628 lines
54 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.
{% load common_tags %}
{% load i18n %}
{% trans "Должность не указана" as no_post %}
<div class="page-content" data-hr-active-tab="{{ hr_active_tab|default:'employees' }}"{% if hr_request_form_open %} data-hr-request-form-open="1"{% endif %}{% if hiring_form_open %} data-hr-hiring-open="1"{% endif %}>
{% with hr_tab=hr_active_tab|default:'employees' %}
<div style="margin-bottom:1.5rem;">
<h1 style="font-size:1.25rem; font-weight:500; color:var(--color-foreground);">{% trans "HR Портал" %}</h1>
<p style="font-size:0.875rem; color:var(--color-muted-foreground); margin-top:0.25rem;">
{% if can_manage_hiring %}
{% trans "Управление персоналом и кадровые процессы" %}
{% else %}
{% trans "Справочник сотрудников и кадровые заявки" %}
{% endif %}
</p>
</div>
{% if hiring_just_created %}
<div style="margin-bottom:1rem; padding:0.875rem 1rem; border-radius:0.75rem; border:1px solid hsl(152 40% 70%); background:hsl(152 45% 96%); color:var(--color-foreground); font-size:0.875rem;">
<div style="font-weight:600; margin-bottom:0.25rem;">{% trans "Заявку створено" %}</div>
{% with intern=hiring_just_created.intern_account %}
{% if intern %}
<div>{% trans "Інтерн-слот" %}: <strong>{{ intern.label }}</strong> · {% trans "логін" %} <code>{{ intern.username }}</code></div>
<div style="margin-top:0.25rem; color:var(--color-muted-foreground);">{% trans "Пароль інтерн-обліку — у заявці IT (для підготовки робочого місця)." %}</div>
{% endif %}
{% endwith %}
{% if hiring_just_created.granted_ticket %}
<div style="margin-top:0.25rem; color:var(--color-muted-foreground);">{% trans "Заявка IT" %}: {{ hiring_just_created.granted_ticket.number }}</div>
{% endif %}
</div>
{% endif %}
{% if hiring_form_errors %}
<div style="margin-bottom:1rem; padding:0.75rem 1rem; border-radius:0.5rem; background:hsl(0 70% 96%); border:1px solid hsl(0 70% 85%); color:hsl(0 55% 35%); font-size:0.8125rem;">
<div style="font-weight:600; margin-bottom:0.35rem;">{% trans "Не удалось создать заявку" %}</div>
<ul style="margin:0; padding-left:1.1rem;">
{% for field, messages in hiring_form_errors.items %}
{% for msg in messages %}
<li>{{ msg }}</li>
{% endfor %}
{% endfor %}
</ul>
</div>
{% endif %}
{% if hr_request_created %}
<div style="margin-bottom:1rem; padding:0.875rem 1rem; border-radius:0.75rem; border:1px solid hsl(152 40% 70%); background:hsl(152 45% 96%); color:var(--color-foreground); font-size:0.875rem;">
{% trans "Заявку подано" %}: <strong>{{ hr_request_created.summary }}</strong>
</div>
{% endif %}
{% if hr_request_errors %}
<div style="margin-bottom:1rem; padding:0.75rem 1rem; border-radius:0.5rem; background:hsl(0 70% 96%); border:1px solid hsl(0 70% 85%); color:hsl(0 55% 35%); font-size:0.8125rem;">
<div style="font-weight:600; margin-bottom:0.35rem;">{% trans "Не удалось подать заявку" %}</div>
{% for err in hr_request_errors %}<div>{{ err }}</div>{% endfor %}
</div>
{% endif %}
{% if can_manage_hiring %}
<!-- Метрики (только HR) -->
<div style="display:grid; grid-template-columns:repeat(4,minmax(0,1fr)); gap:0.75rem; margin-bottom:1.5rem;">
<div class="stat-card" style="display:flex; justify-content:space-between; align-items:flex-start;">
<div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-bottom:0.5rem;">{% trans "Всего сотрудников" %}</div>
<div style="font-size:1.75rem; font-weight:700; color:var(--color-foreground); line-height:1;">{{ employees_total }}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.375rem;">+{{ employees_new }} {% trans "за последний месяц" %}</div>
</div>
<div style="width:2.5rem; height:2.5rem; border-radius:0.5rem; background:hsl(205 80% 55% / 0.12); color:hsl(205 80% 45%); display:flex; align-items:center; justify-content:center; flex-shrink:0;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/>
<circle cx="9" cy="7" r="4"/>
<path d="M22 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/>
</svg>
</div>
</div>
<div class="stat-card" style="display:flex; justify-content:space-between; align-items:flex-start; cursor:pointer;" onclick="hrTabSwitch('probation')" title="{% trans 'Открыть список на испытании' %}">
<div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-bottom:0.5rem;">{% trans "На испытательном сроке" %}</div>
<div style="font-size:1.75rem; font-weight:700; color:var(--color-foreground); line-height:1;">{{ employees_probation }}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.375rem;">{% trans "требуют оценки" %}</div>
</div>
<div style="width:2.5rem; height:2.5rem; border-radius:0.5rem; background:hsl(270 60% 55% / 0.12); color:hsl(270 60% 45%); display:flex; align-items:center; justify-content:center; flex-shrink:0;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M14.5 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V7.5L14.5 2z"/><polyline points="14 2 14 8 20 8"/><line x1="16" x2="8" y1="13" y2="13"/><line x1="16" x2="8" y1="17" y2="17"/><line x1="10" x2="8" y1="9" y2="9"/>
</svg>
</div>
</div>
<div class="stat-card" style="display:flex; justify-content:space-between; align-items:flex-start;">
<div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-bottom:0.5rem;">{% trans "Запланированные тренинги" %}</div>
<div style="font-size:1.75rem; font-weight:700; color:var(--color-foreground); line-height:1;">—</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.375rem;">{% trans "раздел в разработке" %}</div>
</div>
<div style="width:2.5rem; height:2.5rem; border-radius:0.5rem; background:hsl(152 55% 45% / 0.12); color:hsl(152 55% 35%); display:flex; align-items:center; justify-content:center; flex-shrink:0;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/>
</svg>
</div>
</div>
<div class="stat-card" style="display:flex; justify-content:space-between; align-items:flex-start;">
<div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-bottom:0.5rem;">{% trans "Заявки на отпуск" %}</div>
<div style="font-size:1.75rem; font-weight:700; color:var(--color-foreground); line-height:1;">{{ hr_pending_leave_count }}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.375rem;">{% trans "ожидают решения HR" %}</div>
</div>
<div style="width:2.5rem; height:2.5rem; border-radius:0.5rem; background:hsl(0 72% 44% / 0.12); color:hsl(0 72% 38%); display:flex; align-items:center; justify-content:center; flex-shrink:0;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<rect width="18" height="18" x="3" y="4" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/>
</svg>
</div>
</div>
</div>
{% endif %}
<!-- Пошук + Створити -->
<div style="display:flex; gap:0.75rem; margin-bottom:1rem;">
<div style="flex:1; display:flex; align-items:center; gap:0.5rem; background:var(--color-card); border:1px solid var(--color-border); border-radius:var(--radius); padding:0.5rem 0.875rem;">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="color:var(--color-muted-foreground); flex-shrink:0;">
<circle cx="11" cy="11" r="8"/><path d="m21 21-4.35-4.35"/>
</svg>
<input type="text" id="hr-search-input" oninput="hrFilterEmployees()" placeholder="{% trans "Поиск работников, вакансий, тренингов..." %}" class="input" style="border:none; background:transparent; padding:0; box-shadow:none; font-size:0.8125rem;">
</div>
{% if can_manage_hiring %}
<button type="button" class="btn btn-primary" style="white-space:nowrap;" onclick="hrHiringOpen()">
<svg width="14" height="14" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<line x1="12" x2="12" y1="5" y2="19"/><line x1="5" x2="19" y1="12" y2="12"/>
</svg>
{% trans "Создать" %}
</button>
{% endif %}
</div>
<!-- Вкладки -->
<div style="display:flex; align-items:center; justify-content:space-between; gap:0.75rem; margin-bottom:1rem; flex-wrap:wrap;">
<div style="display:flex; gap:0.25rem; background:var(--color-muted); border-radius:var(--radius); padding:0.25rem; width:fit-content;">
<button type="button" class="hr-tab-btn{% if hr_tab == 'employees' %} hr-tab-active{% endif %}" data-tab="employees" onclick="hrTabSwitch('employees')"
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer;{% if hr_tab == 'employees' %} background:var(--color-card); color:var(--color-card-foreground); box-shadow:0 1px 2px rgb(0 0 0/0.08);{% else %} background:transparent; color:var(--color-muted-foreground);{% endif %}">{% trans "Сотрудники" %}</button>
{% if can_manage_hiring %}
<button type="button" class="hr-tab-btn{% if hr_tab == 'probation' %} hr-tab-active{% endif %}" data-tab="probation" onclick="hrTabSwitch('probation')"
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer;{% if hr_tab == 'probation' %} background:var(--color-card); color:var(--color-card-foreground); box-shadow:0 1px 2px rgb(0 0 0/0.08);{% else %} background:transparent; color:var(--color-muted-foreground);{% endif %}">{% trans "На испытании" %} ({{ employees_probation }})</button>
{% endif %}
<button type="button" class="hr-tab-btn{% if hr_tab == 'requests' %} hr-tab-active{% endif %}" data-tab="requests" onclick="hrTabSwitch('requests')"
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer;{% if hr_tab == 'requests' %} background:var(--color-card); color:var(--color-card-foreground); box-shadow:0 1px 2px rgb(0 0 0/0.08);{% else %} background:transparent; color:var(--color-muted-foreground);{% endif %}">{% trans "Заявки и отпуска" %}</button>
{% if can_manage_hiring %}
<button type="button" class="hr-tab-btn{% if hr_tab == 'trainings' %} hr-tab-active{% endif %}" data-tab="trainings" onclick="hrTabSwitch('trainings')"
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer;{% if hr_tab == 'trainings' %} background:var(--color-card); color:var(--color-card-foreground); box-shadow:0 1px 2px rgb(0 0 0/0.08);{% else %} background:transparent; color:var(--color-muted-foreground);{% endif %}">{% trans "Тренинги" %}</button>
{% endif %}
{% if can_view_recruiting %}
<button type="button" class="hr-tab-btn{% if hr_tab == 'vacancies' %} hr-tab-active{% endif %}" data-tab="vacancies" onclick="hrTabSwitch('vacancies')"
style="padding:0.375rem 1rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer;{% if hr_tab == 'vacancies' %} background:var(--color-card); color:var(--color-card-foreground); box-shadow:0 1px 2px rgb(0 0 0/0.08);{% else %} background:transparent; color:var(--color-muted-foreground);{% endif %}">{% trans "Вакансии" %} ({{ vacancies_open }})</button>
{% endif %}
</div>
<div id="hr-view-toggle" style="display:{% if hr_tab == 'employees' %}flex{% else %}none{% endif %}; gap:0.25rem; background:var(--color-muted); border-radius:var(--radius); padding:0.25rem; width:fit-content;">
<button type="button" class="hr-view-btn hr-view-active" data-view="cards" onclick="hrViewSwitch('cards')"
style="display:inline-flex; align-items:center; gap:0.375rem; padding:0.375rem 0.75rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer; background:var(--color-card); color:var(--color-card-foreground); box-shadow:0 1px 2px rgb(0 0 0/0.08);">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><rect width="7" height="7" x="3" y="3" rx="1"/><rect width="7" height="7" x="14" y="3" rx="1"/><rect width="7" height="7" x="14" y="14" rx="1"/><rect width="7" height="7" x="3" y="14" rx="1"/></svg>
{% trans "Карточки" %}
</button>
<button type="button" class="hr-view-btn" data-view="table" onclick="hrViewSwitch('table')"
style="display:inline-flex; align-items:center; gap:0.375rem; padding:0.375rem 0.75rem; font-size:0.8125rem; font-weight:500; border:none; border-radius:calc(var(--radius) - 2px); cursor:pointer; background:transparent; color:var(--color-muted-foreground);">
<svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M3 3h18v18H3z"/><path d="M3 9h18M3 15h18M9 3v18"/></svg>
{% trans "Таблица" %}
</button>
</div>
</div>
<!-- Панель: Працівники -->
<div id="hr-panel-employees" class="hr-panel"{% if hr_tab != 'employees' %} style="display:none;"{% endif %}>
<!-- Фільтри -->
<div style="display:flex; align-items:center; gap:0.75rem; flex-wrap:wrap; margin-bottom:1rem;">
{{ hr_post_location_types|json_script:"hr-post-loc-types-data" }}
<div style="display:flex; gap:0.25rem; background:var(--color-muted); border-radius:var(--radius); padding:0.25rem;">
<button type="button" class="hr-loc-btn hr-loc-active" data-loc="" onclick="hrLocFilter('')"
style="padding:0.25rem 0.875rem; font-size:0.8125rem; border-radius:calc(var(--radius) - 2px); font-weight:500; border:none; cursor:pointer; background:var(--color-card); color:var(--color-card-foreground); box-shadow:0 1px 2px rgb(0 0 0/0.08);">{% trans "Все" %}</button>
<button type="button" class="hr-loc-btn" data-loc="office" onclick="hrLocFilter('office')"
style="padding:0.25rem 0.875rem; font-size:0.8125rem; border-radius:calc(var(--radius) - 2px); font-weight:500; border:none; cursor:pointer; background:transparent; color:var(--color-muted-foreground);">{% trans "Офис" %}</button>
<button type="button" class="hr-loc-btn" data-loc="pharmacy" onclick="hrLocFilter('pharmacy')"
style="padding:0.25rem 0.875rem; font-size:0.8125rem; border-radius:calc(var(--radius) - 2px); font-weight:500; border:none; cursor:pointer; background:transparent; color:var(--color-muted-foreground);">{% trans "Аптека" %}</button>
<button type="button" class="hr-loc-btn" data-loc="warehouse" onclick="hrLocFilter('warehouse')"
style="padding:0.25rem 0.875rem; font-size:0.8125rem; border-radius:calc(var(--radius) - 2px); font-weight:500; border:none; cursor:pointer; background:transparent; color:var(--color-muted-foreground);">{% trans "Склад" %}</button>
</div>
{{ hr_department_tree|json_script:"hr-dept-tree-data" }}
<div class="hr-dept-picker" style="position:relative;">
<input type="hidden" id="hr-department-select" value="">
<button type="button" onclick="hrDeptPickerToggle(event)" class="input"
style="display:flex; align-items:center; justify-content:space-between; gap:0.5rem; font-size:0.8125rem; padding:0.3rem 0.75rem; height:auto; min-width:12rem; cursor:pointer; text-align:left;">
<span id="hr-dept-picker-label" style="overflow:hidden; text-overflow:ellipsis; white-space:nowrap;">{% trans "Все отделы" %}</span>
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" style="flex-shrink:0; color:var(--color-muted-foreground);"><path d="m6 9 6 6 6-6"/></svg>
</button>
<div id="hr-dept-picker-panel" style="display:none; position:absolute; top:calc(100% + 0.25rem); left:0; z-index:20; background:var(--color-card); border:1px solid var(--color-border); border-radius:0.625rem; box-shadow:0 4px 16px rgb(0 0 0/0.12); width:20rem; max-height:22rem; overflow-y:auto; padding:0.375rem;"></div>
</div>
<select id="hr-post-select" class="input" onchange="hrFilterEmployees()" style="font-size:0.8125rem; padding:0.3rem 0.75rem; height:auto; min-width:11rem;">
<option value="">{% trans "Все должности" %}</option>
{% for post in hr_posts %}
<option value="{{ post.id }}">{{ post.name }}</option>
{% endfor %}
</select>
<select id="hr-employment-select" class="input" onchange="hrFilterEmployees()" style="font-size:0.8125rem; padding:0.3rem 0.75rem; height:auto; min-width:11rem;">
<option value="">{% trans "Все оформления" %}</option>
<option value="staff">{% trans "Официально" %}</option>
<option value="contract">{% trans "По договору" %}</option>
</select>
<span id="hr-filter-count" style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-left:auto;"></span>
</div>
<!-- Картки -->
<div id="hr-emp-cards-view">
<div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(15rem, 1fr)); gap:1rem;">
{% for employee in employees %}
<div class="hr-emp-card"
data-name="{{ employee.last_name }} {{ employee.first_name }} {{ employee.middle_name }}"
data-department="{{ employee.department_id|default:'' }}"
data-post="{{ employee.post_id|default:'' }}"
data-loc="{{ employee.user_location_type|default:'' }}"
data-employment="{{ employee.employment_type|default:'staff' }}"
data-probation="{% if employee.is_on_probation %}1{% else %}0{% endif %}"
style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); padding:1.25rem;">
<div style="display:flex; flex-direction:column; align-items:center; text-align:center; margin-bottom:1rem;">
{% if employee.photo %}
<img src="{{ employee.photo.url }}" alt="{% trans 'Фото' %} {{ employee.last_name }}" style="width:3.5rem; height:3.5rem; border-radius:50%; object-fit:cover; margin-bottom:0.625rem;">
{% else %}
<span style="width:3.5rem; height:3.5rem; border-radius:50%; background:var(--color-primary); color:var(--color-primary-foreground); display:flex; align-items:center; justify-content:center; font-size:1rem; font-weight:600; margin-bottom:0.625rem;">
{{ employee|initials }}
</span>
{% endif %}
<div style="font-weight:600; color:var(--color-card-foreground); font-size:0.9375rem;">{{ employee.last_name }} {{ employee.first_name }}</div>
<div style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{{ employee.post.name|default:no_post }}</div>
<div style="display:flex; gap:0.375rem; margin-top:0.5rem;">
<span class="badge badge-success">{% trans "Активный" %}</span>
{% if employee.employment_type == 'contract' %}
<span class="badge badge-muted">{% trans "По договору" %}</span>
{% else %}
<span class="badge badge-info">{% trans "Официально" %}</span>
{% endif %}
{% if employee.is_on_probation %}
<span class="badge badge-warning">{% trans "На испытании до" %} {{ employee.probation_end_date|date:"d.m" }}</span>
{% endif %}
</div>
</div>
<div style="display:flex; flex-direction:column; gap:0.5rem; font-size:0.8125rem; margin-bottom:1rem;">
<div style="display:flex; justify-content:space-between; gap:0.5rem;">
<span style="color:var(--color-muted-foreground);">{% trans "Отдел:" %}</span>
<span style="color:var(--color-card-foreground); font-weight:500; text-align:right;">{{ employee.department.name|default:"—" }}</span>
</div>
<div style="display:flex; justify-content:space-between; gap:0.5rem;">
<span style="color:var(--color-muted-foreground);">{% trans "Дата приёма:" %}</span>
<span style="color:var(--color-card-foreground); font-weight:500;">{{ employee.hire_date|date:"d.m.Y" }}</span>
</div>
<div style="display:flex; justify-content:space-between; gap:0.5rem;">
<span style="color:var(--color-muted-foreground);">Email:</span>
<span style="color:var(--color-card-foreground); font-weight:500; text-align:right; overflow-wrap:anywhere;">
{% if request.user|can_view_employee_pii:employee %}{{ employee.email|default:"—" }}{% else %}—{% endif %}
</span>
</div>
<div style="display:flex; justify-content:space-between; gap:0.5rem;">
<span style="color:var(--color-muted-foreground);">{% trans "Телефон:" %}</span>
<span style="color:var(--color-card-foreground); font-weight:500;">
{% if request.user|can_view_employee_pii:employee %}{{ employee.phone|default:"—" }}{% else %}—{% endif %}
</span>
</div>
</div>
<button class="btn btn-secondary" style="width:100%; border:1px solid var(--color-border); font-size:0.8125rem;"
hx-get="/employees/{{ employee.pk }}/" hx-target="#main-content" hx-push-url="/employees/{{ employee.pk }}/" hx-indicator="#loader">{% trans "Профиль" %}</button>
</div>
{% empty %}
<div style="grid-column:1 / -1; padding:2rem; text-align:center; color:var(--color-muted-foreground); font-size:0.8125rem;">{% trans "Активных сотрудников пока нет" %}</div>
{% endfor %}
</div>
<div id="hr-search-empty" style="display:none; padding:2rem; text-align:center; color:var(--color-muted-foreground); font-size:0.8125rem;">{% trans "Ничего не найдено по заданным фильтрам" %}</div>
</div>
<!-- Таблиця -->
<div id="hr-emp-table-view" style="display:none; background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); overflow:hidden;">
<div style="overflow-x:auto;">
<table style="width:100%; border-collapse:collapse; font-size:0.875rem;">
<thead>
<tr style="border-bottom:1px solid var(--color-border);">
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Сотрудник" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Должность" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Отдел / Аптека" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Локация" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Дата приёма" %}</th>
</tr>
</thead>
<tbody>
{% for employee in employees %}
<tr class="hr-emp-row tr-hover"
data-name="{{ employee.last_name }} {{ employee.first_name }} {{ employee.middle_name }}"
data-department="{{ employee.department_id|default:'' }}"
data-post="{{ employee.post_id|default:'' }}"
data-loc="{{ employee.user_location_type|default:'' }}"
data-employment="{{ employee.employment_type|default:'staff' }}"
data-probation="{% if employee.is_on_probation %}1{% else %}0{% endif %}"
style="border-bottom:1px solid var(--color-border); cursor:pointer;"
hx-get="/employees/{{ employee.pk }}/" hx-target="#main-content" hx-push-url="/employees/{{ employee.pk }}/" hx-indicator="#loader">
<td style="padding:0.75rem 1rem; vertical-align:middle;">
<div style="display:flex; align-items:center; gap:0.625rem;">
{% if employee.photo %}
<img src="{{ employee.photo.url }}" alt="{% trans 'Фото' %} {{ employee.last_name }}" style="width:1.75rem; height:1.75rem; border-radius:50%; object-fit:cover; display:block;">
{% else %}
<span style="width:1.75rem; height:1.75rem; border-radius:50%; background:color-mix(in srgb, var(--color-primary) 10%, transparent); color:var(--color-primary); display:flex; align-items:center; justify-content:center; font-size:0.6875rem; font-weight:500; flex-shrink:0;">
{{ employee|initials }}
</span>
{% endif %}
<span style="font-weight:500; color:var(--color-card-foreground);">{{ employee.last_name }} {{ employee.first_name }}</span>
{% if employee.employment_type == 'contract' %}
<span class="badge badge-muted">{% trans "По договору" %}</span>
{% endif %}
{% if employee.is_on_probation %}
<span class="badge badge-warning">{% trans "На испытании" %}</span>
{% endif %}
</div>
</td>
<td style="padding:0.75rem 1rem; vertical-align:middle; color:var(--color-muted-foreground);">{{ employee.post.name|default:"—" }}</td>
<td style="padding:0.75rem 1rem; vertical-align:middle; color:var(--color-muted-foreground);">
{% if employee.department %}{{ employee.department.name }}{% elif employee.user_pharmacy %}{{ employee.user_pharmacy.name }}{% else %}—{% endif %}
</td>
<td style="padding:0.75rem 1rem; vertical-align:middle; color:var(--color-muted-foreground);">{{ employee.get_user_location_type_display|default:"—" }}</td>
<td style="padding:0.75rem 1rem; vertical-align:middle; color:var(--color-muted-foreground);">{{ employee.hire_date|date:"d.m.Y" }}</td>
</tr>
{% empty %}
<tr>
<td colspan="5" style="padding:1.25rem; text-align:center; color:var(--color-muted-foreground);">{% trans "Активных сотрудников пока нет" %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<div id="hr-search-empty-table" style="display:none; padding:1.5rem; text-align:center; color:var(--color-muted-foreground); font-size:0.8125rem;">{% trans "Ничего не найдено по заданным фильтрам" %}</div>
</div>
</div>
<!-- Панель: На испытании (заявки найма + сотрудники с probation_end_date) -->
<div id="hr-panel-probation" class="hr-panel"{% if hr_tab != 'probation' %} style="display:none;"{% endif %}>
{% if can_manage_hiring %}
<div style="margin-bottom:1.25rem;">
<div style="display:flex; align-items:center; justify-content:space-between; gap:0.75rem; margin-bottom:0.75rem; flex-wrap:wrap;">
<div>
<div style="font-size:0.9375rem; font-weight:600; color:var(--color-foreground);">{% trans "Кандидаты на испытании" %}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{% trans "Заявки на найм до утверждения персонального аккаунта" %}</div>
</div>
<div style="display:flex; gap:0.5rem; flex-wrap:wrap;">
<button type="button" class="btn btn-secondary" style="font-size:0.8125rem; border:1px solid var(--color-border);" onclick="hrTabSwitch('hiring')">{% trans "Все заявки" %}</button>
<button type="button" class="btn btn-primary" style="font-size:0.8125rem;" onclick="hrHiringOpen()">{% trans "Новая заявка" %}</button>
</div>
</div>
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); overflow:hidden;">
<div style="overflow-x:auto;">
<table style="width:100%; border-collapse:collapse; font-size:0.875rem;">
<thead>
<tr style="border-bottom:1px solid var(--color-border);">
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Кандидат" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Должность / локация" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Інтерн / IT" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Испытание до" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Действия" %}</th>
</tr>
</thead>
<tbody>
{% for hr in trial_hiring_requests %}
<tr style="border-bottom:1px solid var(--color-border); vertical-align:top;">
<td style="padding:0.75rem 1rem;">
<div style="font-weight:500; color:var(--color-card-foreground);">{{ hr.last_name }} {{ hr.first_name }}</div>
{% if hr.inn_code %}<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{% trans "ИНН" %} {{ hr.inn_code }}</div>{% endif %}
{% if hr.employment_type == 'contract' %}
<span class="badge badge-muted" style="margin-top:0.25rem;">{% trans "По договору" %}</span>
{% else %}
<span class="badge badge-info" style="margin-top:0.25rem;">{% trans "Официально" %}</span>
{% endif %}
{% if hr.is_overdue %}
<span class="badge badge-danger" style="margin-top:0.25rem;">{% trans "Просрочено" %}</span>
{% else %}
<span class="badge badge-warning" style="margin-top:0.25rem;">{% trans "На испытании" %}</span>
{% endif %}
</td>
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">
{{ hr.post.name|default:"—" }}<br>
<span style="font-size:0.75rem;">{{ hr.get_user_location_type_display }}{% if hr.department %} · {{ hr.department.name }}{% elif hr.user_pharmacy %} · {{ hr.user_pharmacy.name }}{% endif %}</span>
</td>
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-size:0.8125rem;">
{% if hr.intern_account %}
<div>{{ hr.intern_account.label }} · {{ hr.intern_account.username }}</div>
{% else %}—{% endif %}
{% if hr.granted_ticket %}
<div style="margin-top:0.125rem;">
{% if request.user|can_section:'it_manager' %}
<a href="/it-manager/" style="color:var(--color-primary); text-decoration:none;">{{ hr.granted_ticket.number }}</a>
{% else %}
<span style="color:var(--color-muted-foreground);">{% trans "Заявка IT" %}: {{ hr.granted_ticket.number }}</span>
{% endif %}
</div>
{% endif %}
</td>
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">{{ hr.trial_end_date|date:"d.m.Y" }}</td>
<td style="padding:0.75rem 1rem;">
<div style="display:flex; flex-direction:column; gap:0.375rem; min-width:12rem;">
<form hx-post="/hiring/{{ hr.pk }}/approve/" hx-target="#main-content" hx-indicator="#loader, find .btn-label-loading" hx-disabled-elt="find button[type=submit]" hx-confirm="{% trans 'Утвердить кандидата' %} {{ hr.last_name }} {{ hr.first_name }}?">
{% csrf_token %}
<button type="submit" class="btn btn-secondary" style="width:100%; font-size:0.75rem; padding:0.3rem 0.625rem; border:1px solid var(--color-border); color:hsl(152 55% 30%);">
{% trans "Утвердить" %}
<span class="btn-label-loading htmx-indicator">…</span>
</button>
</form>
<form hx-post="/hiring/{{ hr.pk }}/reject/" hx-target="#main-content" hx-indicator="#loader, find .btn-label-loading" hx-disabled-elt="find button[type=submit]" style="display:flex; gap:0.375rem;">
{% csrf_token %}
<input type="text" name="note" placeholder="{% trans "Причина отказа" %}" class="input" style="font-size:0.75rem; padding:0.3rem 0.5rem;">
<button type="submit" class="btn btn-secondary" style="font-size:0.75rem; padding:0.3rem 0.625rem; border:1px solid var(--color-border); color:var(--color-destructive); white-space:nowrap;">
{% trans "Отклонить" %}
<span class="btn-label-loading htmx-indicator">…</span>
</button>
</form>
</div>
</td>
</tr>
{% empty %}
<tr>
<td colspan="5" style="padding:1.25rem; text-align:center; color:var(--color-muted-foreground);">{% trans "Нет кандидатов на испытании" %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
</div>
{% endif %}
{% if employees_on_probation %}
<div>
<div style="font-size:0.9375rem; font-weight:600; color:var(--color-foreground); margin-bottom:0.25rem;">{% trans "Сотрудники с испытательным сроком" %}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-bottom:0.75rem;">{% trans "Учётные записи с заполненной датой окончания испытания" %}</div>
<div style="display:grid; grid-template-columns:repeat(auto-fill, minmax(15rem, 1fr)); gap:1rem;">
{% for employee in employees_on_probation %}
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); padding:1.25rem;">
<div style="font-weight:600; color:var(--color-card-foreground);">{{ employee.last_name }} {{ employee.first_name }}</div>
<div style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{{ employee.post.name|default:no_post }}</div>
<span class="badge badge-warning" style="margin-top:0.5rem;">{% trans "На испытании до" %} {{ employee.probation_end_date|date:"d.m.Y" }}</span>
<button class="btn btn-secondary" style="width:100%; margin-top:0.75rem; border:1px solid var(--color-border); font-size:0.8125rem;"
hx-get="/employees/{{ employee.pk }}/" hx-target="#main-content" hx-push-url="/employees/{{ employee.pk }}/" hx-indicator="#loader">{% trans "Профиль" %}</button>
</div>
{% endfor %}
</div>
</div>
{% elif not can_manage_hiring %}
<div style="padding:2rem; text-align:center; color:var(--color-muted-foreground); font-size:0.875rem;">
{% trans "Нет сотрудников на испытательном сроке" %}
</div>
{% endif %}
</div>
{% include "partials/hr-requests-panel.html" %}
<!-- Панель: Тренінги -->
<div id="hr-panel-trainings" class="hr-panel"{% if hr_tab != 'trainings' %} style="display:none;"{% endif %}>
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); padding:2.5rem; text-align:center;">
<div style="width:2.75rem; height:2.75rem; border-radius:50%; background:hsl(152 55% 45% / 0.12); color:hsl(152 55% 35%); display:flex; align-items:center; justify-content:center; margin:0 auto 0.875rem;">
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M22 10v6M2 10l10-5 10 5-10 5z"/><path d="M6 12v5c3 3 9 3 12 0v-5"/></svg>
</div>
<div style="font-weight:500; color:var(--color-foreground); font-size:0.9375rem;">{% trans "Раздел в разработке" %}</div>
<div style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.375rem;">{% trans "Планирование тренингов и обучения появится в ближайшее время" %}</div>
</div>
</div>
<!-- Панель: Вакансии -->
<div id="hr-panel-vacancies" class="hr-panel"{% if hr_tab != 'vacancies' %} style="display:none;"{% endif %}>
{% if can_view_recruiting %}
{% include "partials/hr-vacancies-panel.html" %}
{% else %}
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); padding:2.5rem; text-align:center;">
<div style="font-weight:500; color:var(--color-foreground); font-size:0.9375rem;">{% trans "Нет доступа к вакансиям" %}</div>
</div>
{% endif %}
</div>
{% if can_manage_hiring %}
<!-- Панель: Стажування -->
<div id="hr-panel-hiring" class="hr-panel"{% if hr_tab != 'hiring' %} style="display:none;"{% endif %}>
<div style="display:flex; align-items:center; justify-content:space-between; gap:0.75rem; margin-bottom:0.75rem; flex-wrap:wrap;">
<div>
<div style="font-size:0.9375rem; font-weight:600; color:var(--color-foreground);">{% trans "Все заявки на найм" %}</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{% trans "История испытательных заявок" %}</div>
</div>
<button type="button" class="btn btn-primary" style="font-size:0.8125rem;" onclick="hrHiringOpen()">{% trans "Новая заявка" %}</button>
</div>
<!-- Список заявок -->
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 1px 2px rgb(0 0 0/0.05); overflow:hidden;">
<div style="overflow-x:auto;">
<table style="width:100%; border-collapse:collapse; font-size:0.875rem;">
<thead>
<tr style="border-bottom:1px solid var(--color-border);">
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Кандидат" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Должность / локация" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Інтерн / IT" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Статус" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Испытание до" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Подал" %}</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">{% trans "Действия" %}</th>
</tr>
</thead>
<tbody>
{% for hr in hiring_requests %}
<tr style="border-bottom:1px solid var(--color-border); vertical-align:top;">
<td style="padding:0.75rem 1rem;">
<div style="font-weight:500; color:var(--color-card-foreground);">{{ hr.last_name }} {{ hr.first_name }}</div>
{% if hr.inn_code %}<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{% trans "ИНН" %} {{ hr.inn_code }}</div>{% endif %}
{% if hr.employment_type == 'contract' %}
<span class="badge badge-muted" style="margin-top:0.25rem;">{% trans "По договору" %}</span>
{% else %}
<span class="badge badge-info" style="margin-top:0.25rem;">{% trans "Официально" %}</span>
{% endif %}
{% if hr.candidate_email or hr.candidate_phone %}
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{{ hr.candidate_email }} {{ hr.candidate_phone }}</div>
{% endif %}
</td>
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">
{{ hr.post.name|default:"—" }}<br>
<span style="font-size:0.75rem;">{{ hr.get_user_location_type_display }}{% if hr.department %} · {{ hr.department.name }}{% elif hr.user_pharmacy %} · {{ hr.user_pharmacy.name }}{% endif %}</span>
</td>
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground); font-size:0.8125rem;">
{% if hr.intern_account %}
<div>{{ hr.intern_account.label }} · {{ hr.intern_account.username }}</div>
{% elif hr.employee %}
<div>{{ hr.employee.username }}</div>
{% else %}
<div>—</div>
{% endif %}
{% if hr.granted_ticket %}
<div style="margin-top:0.125rem;">
{% if request.user|can_section:'it_manager' %}
<a href="/it-manager/" style="color:var(--color-primary); text-decoration:none;">{{ hr.granted_ticket.number }}</a>
{% else %}
<span style="color:var(--color-muted-foreground);">{% trans "Заявка IT" %}: {{ hr.granted_ticket.number }}</span>
{% endif %}
</div>
{% endif %}
</td>
<td style="padding:0.75rem 1rem;">
{% if hr.status == 'trial' %}
{% if hr.is_overdue %}
<span class="badge badge-danger">{% trans "Просрочено" %}</span>
{% else %}
<span class="badge badge-warning">{% trans "На испытании" %}</span>
{% endif %}
{% elif hr.status == 'approved' %}
<span class="badge badge-success">{% trans "Утверждено" %}</span>
{% else %}
<span class="badge badge-danger">{% trans "Отклонено" %}</span>
{% endif %}
</td>
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">{{ hr.trial_end_date|date:"d.m.Y" }}</td>
<td style="padding:0.75rem 1rem; color:var(--color-muted-foreground);">{{ hr.requested_by.short_name }}</td>
<td style="padding:0.75rem 1rem;">
{% if hr.status == 'trial' %}
<div style="display:flex; flex-direction:column; gap:0.375rem; min-width:12rem;">
<form hx-post="/hiring/{{ hr.pk }}/approve/" hx-target="#main-content" hx-indicator="#loader, find .btn-label-loading" hx-disabled-elt="find button[type=submit]" hx-confirm="{% trans 'Утвердить кандидата' %} {{ hr.last_name }} {{ hr.first_name }}?">
{% csrf_token %}
<button type="submit" class="btn btn-secondary" style="width:100%; font-size:0.75rem; padding:0.3rem 0.625rem; border:1px solid var(--color-border); color:hsl(152 55% 30%);">
{% trans "Утвердить" %}
<span class="btn-label-loading htmx-indicator">…</span>
</button>
</form>
<form hx-post="/hiring/{{ hr.pk }}/reject/" hx-target="#main-content" hx-indicator="#loader, find .btn-label-loading" hx-disabled-elt="find button[type=submit]" style="display:flex; gap:0.375rem;">
{% csrf_token %}
<input type="text" name="note" placeholder="{% trans "Причина отказа" %}" class="input" style="font-size:0.75rem; padding:0.3rem 0.5rem;">
<button type="submit" class="btn btn-secondary" style="font-size:0.75rem; padding:0.3rem 0.625rem; border:1px solid var(--color-border); color:var(--color-destructive); white-space:nowrap;">
{% trans "Отклонить" %}
<span class="btn-label-loading htmx-indicator">…</span>
</button>
</form>
</div>
{% elif hr.status == 'approved' and hr.employee %}
<div style="display:flex; flex-direction:column; gap:0.375rem;">
{% if hr.decision_at %}
<span style="font-size:0.75rem; color:var(--color-muted-foreground);">{{ hr.decision_at|date:"d.m.Y" }} · {{ hr.decision_by.short_name }}</span>
{% endif %}
{% if hr.password_invite_url %}
<div style="font-size:0.6875rem; color:var(--color-muted-foreground); word-break:break-all; padding:0.375rem 0.5rem; background:var(--color-muted); border-radius:0.375rem;">
{% trans "Посилання для пароля" %}:<br>
<a href="{{ hr.password_invite_url }}" style="color:var(--color-primary);">{{ hr.password_invite_url }}</a>
</div>
<form hx-post="/hiring/{{ hr.pk }}/invite/" hx-target="#main-content" hx-indicator="#loader" style="margin:0;">
{% csrf_token %}
<button type="submit" class="btn btn-secondary" style="font-size:0.75rem; padding:0.3rem 0.625rem; border:1px solid var(--color-border); width:100%;">
{% trans "Нове посилання" %}
</button>
</form>
{% endif %}
<a href="/hiring/{{ hr.pk }}/credentials.pdf/" class="btn btn-secondary" style="font-size:0.75rem; padding:0.3rem 0.625rem; border:1px solid var(--color-border); text-align:center; text-decoration:none;">
{% trans "PDF з даними" %}
</a>
</div>
{% elif hr.decision_at %}
<span style="font-size:0.75rem; color:var(--color-muted-foreground);">{{ hr.decision_at|date:"d.m.Y" }} · {{ hr.decision_by.short_name }}</span>
{% endif %}
</td>
</tr>
{% empty %}
<tr>
<td colspan="7" style="padding:1.25rem; text-align:center; color:var(--color-muted-foreground);">{% trans "Заявок на найм пока нет" %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% include "partials/pagination.html" with page=hiring_requests base_url="/hr-portal/" page_param="hiring_page" size_param="hiring_per_page" item_label="заявок" %}
</div>
</div>
{% include "partials/hr-hiring-modal.html" %}
{% endif %}
{% endwith %}
</div>