24f9e54283
Co-authored-by: Cursor <cursoragent@cursor.com>
628 lines
54 KiB
HTML
628 lines
54 KiB
HTML
{% 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>
|