hiring: вакансии и найм, HR-портал
Модель вакансий, флоу рекрутинга и панели HR-портала (заявки/вакансии). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
+95
-155
@@ -1,11 +1,18 @@
|
||||
{% load common_tags %}
|
||||
{% load i18n %}
|
||||
{% trans "Должность не указана" as no_post %}
|
||||
<div class="page-content" data-hr-active-tab="{{ hr_active_tab|default:'employees' }}">
|
||||
<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 %}>
|
||||
{% 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;">{% trans "Управление персоналом и кадровые процессы" %}</p>
|
||||
<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 %}
|
||||
@@ -36,7 +43,21 @@
|
||||
</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;">
|
||||
@@ -83,8 +104,8 @@
|
||||
<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;">3</div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.375rem;">1 {% 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">
|
||||
@@ -94,6 +115,7 @@
|
||||
</div>
|
||||
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<!-- Пошук + Створити -->
|
||||
<div style="display:flex; gap:0.75rem; margin-bottom:1rem;">
|
||||
@@ -116,19 +138,25 @@
|
||||
<!-- Вкладки -->
|
||||
<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 hr-tab-active" 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; 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-tab-btn" 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; background:transparent; color:var(--color-muted-foreground);">{% trans "На испытании" %} ({{ employees_probation }})</button>
|
||||
<button type="button" class="hr-tab-btn" 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; background:transparent; color:var(--color-muted-foreground);">{% trans "Заявки и отпуска" %}</button>
|
||||
<button type="button" class="hr-tab-btn" 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; background:transparent; color:var(--color-muted-foreground);">{% trans "Тренинги" %}</button>
|
||||
<button type="button" class="hr-tab-btn" 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; background:transparent; color:var(--color-muted-foreground);">{% trans "Вакансии" %}</button>
|
||||
<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:flex; gap:0.25rem; background:var(--color-muted); border-radius:var(--radius); padding:0.25rem; width:fit-content;">
|
||||
<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>
|
||||
@@ -143,7 +171,7 @@
|
||||
</div>
|
||||
|
||||
<!-- Панель: Працівники -->
|
||||
<div id="hr-panel-employees" class="hr-panel">
|
||||
<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;">
|
||||
@@ -220,11 +248,15 @@
|
||||
</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;">{{ employee.email|default:"—" }}</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;">{{ employee.phone|default:"—" }}</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;"
|
||||
@@ -293,14 +325,10 @@
|
||||
</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 style="margin-top:1rem;">
|
||||
<a href="#" hx-get="/employees/" hx-target="#main-content" hx-push-url="/employees/" hx-indicator="#loader" style="font-size:0.8125rem; color:var(--color-primary); text-decoration:none; font-weight:500;">{% trans "Полный список сотрудников →" %}</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Панель: На испытании (заявки найма + сотрудники с probation_end_date) -->
|
||||
<div id="hr-panel-probation" class="hr-panel" style="display:none;">
|
||||
<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;">
|
||||
@@ -343,7 +371,13 @@
|
||||
<div>{{ hr.intern_account.label }} · {{ hr.intern_account.username }}</div>
|
||||
{% else %}—{% endif %}
|
||||
{% if hr.granted_ticket %}
|
||||
<div style="margin-top:0.125rem;"><a href="/it-manager/" style="color:var(--color-primary); text-decoration:none;">{{ hr.granted_ticket.number }}</a></div>
|
||||
<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>
|
||||
@@ -403,122 +437,10 @@
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Панель: Заявки та відпустки -->
|
||||
<div id="hr-panel-requests" class="hr-panel" style="display:none;">
|
||||
<!-- Швидкі дії -->
|
||||
<div style="display:grid; grid-template-columns:repeat(4,1fr); gap:1rem; margin-bottom:1.25rem;">
|
||||
<button style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); padding:1.25rem; text-align:center; cursor:pointer; transition:box-shadow 150ms, border-color 150ms;" onmouseover="this.style.borderColor='var(--color-primary)'; this.style.boxShadow='0 0 0 2px hsl(0 72% 44% / 0.1)'" onmouseout="this.style.borderColor=''; this.style.boxShadow=''">
|
||||
<div style="width:2.5rem; height:2.5rem; border-radius:0.625rem; background:hsl(0 72% 44% / 0.1); color:hsl(0 72% 38%); display:flex; align-items:center; justify-content:center; margin:0 auto 0.75rem;">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M14 22v-4a2 2 0 1 0-4 0v4"/><path d="m18 10 3.447 1.724a1 1 0 0 1 .553.894V20a2 2 0 0 1-2 2H4a2 2 0 0 1-2-2v-7.382a1 1 0 0 1 .553-.894L6 10"/><path d="M18 5v17"/><path d="m6 5 6-3 6 3"/><path d="M6 5v17"/><rect width="10" height="12" x="7" y="10" rx="1"/></svg>
|
||||
</div>
|
||||
<div style="font-size:0.875rem; font-weight:500; color:var(--color-foreground);">{% trans "Отпуск" %}</div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Подать заявку" %}</div>
|
||||
</button>
|
||||
<button style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); padding:1.25rem; text-align:center; cursor:pointer; transition:box-shadow 150ms, border-color 150ms;" onmouseover="this.style.borderColor='var(--color-primary)'; this.style.boxShadow='0 0 0 2px hsl(0 72% 44% / 0.1)'" onmouseout="this.style.borderColor=''; this.style.boxShadow=''">
|
||||
<div style="width:2.5rem; height:2.5rem; border-radius:0.625rem; background:hsl(205 80% 55% / 0.12); color:hsl(205 80% 45%); display:flex; align-items:center; justify-content:center; margin:0 auto 0.75rem;">
|
||||
<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 style="font-size:0.875rem; font-weight:500; color:var(--color-foreground);">{% trans "Справка" %}</div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Заказать документ" %}</div>
|
||||
</button>
|
||||
<button style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); padding:1.25rem; text-align:center; cursor:pointer; transition:box-shadow 150ms, border-color 150ms;" onmouseover="this.style.borderColor='var(--color-primary)'; this.style.boxShadow='0 0 0 2px hsl(0 72% 44% / 0.1)'" onmouseout="this.style.borderColor=''; this.style.boxShadow=''">
|
||||
<div style="width:2.5rem; height:2.5rem; border-radius:0.625rem; background:hsl(152 55% 45% / 0.12); color:hsl(152 55% 35%); display:flex; align-items:center; justify-content:center; margin:0 auto 0.75rem;">
|
||||
<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 10h18M8 14h.01M12 14h.01M16 14h.01M8 18h.01M12 18h.01M16 18h.01"/></svg>
|
||||
</div>
|
||||
<div style="font-size:0.875rem; font-weight:500; color:var(--color-foreground);">{% trans "Табель" %}</div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Учёт рабочего времени" %}</div>
|
||||
</button>
|
||||
<button style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); padding:1.25rem; text-align:center; cursor:pointer; transition:box-shadow 150ms, border-color 150ms;" onmouseover="this.style.borderColor='var(--color-primary)'; this.style.boxShadow='0 0 0 2px hsl(0 72% 44% / 0.1)'" onmouseout="this.style.borderColor=''; this.style.boxShadow=''">
|
||||
<div style="width:2.5rem; height:2.5rem; border-radius:0.625rem; background:hsl(270 60% 55% / 0.12); color:hsl(270 60% 42%); display:flex; align-items:center; justify-content:center; margin:0 auto 0.75rem;">
|
||||
<svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M12 1v22M17 5H9.5a3.5 3.5 0 0 0 0 7h5a3.5 3.5 0 0 1 0 7H6"/></svg>
|
||||
</div>
|
||||
<div style="font-size:0.875rem; font-weight:500; color:var(--color-foreground);">{% trans "Начисления" %}</div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Зарплата и премии" %}</div>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div style="display:grid; grid-template-columns:1fr 1fr; gap:1.25rem;">
|
||||
|
||||
<!-- Мої заявки -->
|
||||
<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="padding:0.875rem 1.25rem; border-bottom:1px solid var(--color-border); display:flex; align-items:center; justify-content:space-between;">
|
||||
<span style="font-size:0.8125rem; font-weight:500; color:var(--color-foreground);">{% trans "Мои заявки" %}</span>
|
||||
<button class="btn btn-ghost" style="font-size:0.75rem; padding:0.25rem 0.625rem;">+ {% trans "Новая" %}</button>
|
||||
</div>
|
||||
<div>
|
||||
<div style="padding:0.875rem 1.25rem; border-bottom:1px solid var(--color-border); display:flex; align-items:center; justify-content:space-between;" class="li-hover">
|
||||
<div>
|
||||
<div style="font-size:0.8125rem; font-weight:500; color:var(--color-foreground);">{% trans "Отпуск 01–14 мая" %}</div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{% trans "Подано 10.04.2026" %}</div>
|
||||
</div>
|
||||
<span class="badge badge-warning">{% trans "На рассмотрении" %}</span>
|
||||
</div>
|
||||
<div style="padding:0.875rem 1.25rem; border-bottom:1px solid var(--color-border); display:flex; align-items:center; justify-content:space-between;" class="li-hover">
|
||||
<div>
|
||||
<div style="font-size:0.8125rem; font-weight:500; color:var(--color-foreground);">{% trans "Справка о зарплате" %}</div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{% trans "Подано 05.04.2026" %}</div>
|
||||
</div>
|
||||
<span class="badge badge-success">{% trans "Готово" %}</span>
|
||||
</div>
|
||||
<div style="padding:0.875rem 1.25rem; display:flex; align-items:center; justify-content:space-between;" class="li-hover">
|
||||
<div>
|
||||
<div style="font-size:0.8125rem; font-weight:500; color:var(--color-foreground);">{% trans "Больничный 28–29 марта" %}</div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{% trans "Подано 01.04.2026" %}</div>
|
||||
</div>
|
||||
<span class="badge badge-success">{% trans "Утверждено" %}</span>
|
||||
</div>
|
||||
</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="padding:0.875rem 1.25rem; border-bottom:1px solid var(--color-border);">
|
||||
<span style="font-size:0.8125rem; font-weight:500; color:var(--color-foreground);">{% trans "Баланс отпусков — 2026" %}</span>
|
||||
</div>
|
||||
<div style="padding:1.25rem; display:flex; flex-direction:column; gap:1rem;">
|
||||
|
||||
<div>
|
||||
<div style="display:flex; justify-content:space-between; margin-bottom:0.375rem;">
|
||||
<span style="font-size:0.8125rem; color:var(--color-foreground);">{% trans "Основной отпуск" %}</span>
|
||||
<span style="font-size:0.8125rem; font-weight:600; color:var(--color-foreground);">14 / 24 {% trans "дн." %}</span>
|
||||
</div>
|
||||
<div class="progress"><div class="progress-bar" style="width:58%;"></div></div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Остаток: 10 дней" %}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div style="display:flex; justify-content:space-between; margin-bottom:0.375rem;">
|
||||
<span style="font-size:0.8125rem; color:var(--color-foreground);">{% trans "Дополнительный отпуск" %}</span>
|
||||
<span style="font-size:0.8125rem; font-weight:600; color:var(--color-foreground);">0 / 7 {% trans "дн." %}</span>
|
||||
</div>
|
||||
<div class="progress"><div class="progress-bar" style="width:0%;"></div></div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Остаток: 7 дней" %}</div>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<div style="display:flex; justify-content:space-between; margin-bottom:0.375rem;">
|
||||
<span style="font-size:0.8125rem; color:var(--color-foreground);">{% trans "Больничные" %}</span>
|
||||
<span style="font-size:0.8125rem; font-weight:600; color:var(--color-foreground);">2 / 30 {% trans "дн." %}</span>
|
||||
</div>
|
||||
<div class="progress"><div class="progress-bar" style="width:7%; background:hsl(38 80% 45%);"></div></div>
|
||||
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Остаток: 28 дней" %}</div>
|
||||
</div>
|
||||
|
||||
<div style="padding:0.875rem 1rem; background:hsl(214 60% 98%); border-radius:0.625rem; border:1px solid var(--color-border); margin-top:0.25rem;">
|
||||
<div style="font-size:0.75rem; font-weight:600; color:var(--color-foreground); margin-bottom:0.5rem;">{% trans "Следующий отпуск" %}</div>
|
||||
<div style="display:flex; justify-content:space-between; font-size:0.8125rem;">
|
||||
<span style="color:var(--color-muted-foreground);">01.05 – 14.05.2026</span>
|
||||
<span class="badge badge-warning">{% trans "На рассмотрении" %}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
{% include "partials/hr-requests-panel.html" %}
|
||||
|
||||
<!-- Панель: Тренінги -->
|
||||
<div id="hr-panel-trainings" class="hr-panel" style="display:none;">
|
||||
<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>
|
||||
@@ -528,20 +450,20 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Панель: Вакансії -->
|
||||
<div id="hr-panel-vacancies" class="hr-panel" style="display:none;">
|
||||
<!-- Панель: Вакансии -->
|
||||
<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="width:2.75rem; height:2.75rem; border-radius:50%; background:hsl(205 80% 55% / 0.12); color:hsl(205 80% 45%); 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="M16 21v-2a4 4 0 0 0-4-4H6a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><line x1="19" x2="19" y1="8" y2="14"/><line x1="22" x2="16" y1="11" y2="11"/></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 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" style="display:none;">
|
||||
<div id="hr-panel-hiring" class="hr-panel"{% if hr_tab != 'hiring' %} style="display:none;"{% endif %}>
|
||||
|
||||
<!-- Нова заявка -->
|
||||
<form hx-post="/hiring/" hx-target="#main-content" hx-indicator="#loader, find .btn-label-loading" hx-disabled-elt="find button[type=submit]"
|
||||
@@ -586,12 +508,15 @@
|
||||
</div>
|
||||
<div id="hr-hiring-department-field" style="display:none;">
|
||||
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">{% trans "Отдел " %}<span class="hr-req-office" style="color:var(--color-destructive); display:none;">*</span></label>
|
||||
<select name="department_id" id="hr-hiring-department-select" class="input" style="width:100%;">
|
||||
<option value="">—</option>
|
||||
{% for dept in hr_departments_flat %}
|
||||
<option value="{{ dept.id }}">{{ dept.name }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<div class="hr-dept-picker" style="position:relative;">
|
||||
<input type="hidden" name="department_id" id="hr-hiring-department-select" value="">
|
||||
<button type="button" onclick="hrHiringDeptPickerToggle(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; width:100%; cursor:pointer; text-align:left;">
|
||||
<span id="hr-hiring-dept-picker-label" data-empty-label="{% trans 'Выберите отдел' %}" 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-hiring-dept-picker-panel" style="display:none; position:absolute; top:calc(100% + 0.25rem); left:0; right:0; z-index:30; 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); max-height:16rem; overflow-y:auto; padding:0.375rem;"></div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="hr-hiring-pharmacy-field">
|
||||
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">{% trans "Аптека " %}<span style="color:var(--color-destructive);">*</span></label>
|
||||
@@ -716,7 +641,11 @@
|
||||
{% 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>
|
||||
@@ -759,6 +688,18 @@
|
||||
{% 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>
|
||||
@@ -781,6 +722,5 @@
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<script>hrPortalInit();</script>
|
||||
|
||||
{% endwith %}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user