45d668a675
Co-authored-by: Cursor <cursoragent@cursor.com>
189 lines
17 KiB
HTML
189 lines
17 KiB
HTML
{% load i18n %}
|
||
<div id="hr-hiring-modal" role="dialog" aria-modal="true" aria-labelledby="hr-hiring-modal-title"
|
||
style="display:none; position:fixed; inset:0; z-index:80; background:rgba(0,0,0,0.4); align-items:flex-start; justify-content:center; padding:1.5rem 1rem; overflow-y:auto;"
|
||
onclick="if(event.target===this) hrHiringClose()">
|
||
<div style="background:var(--color-card); border-radius:0.75rem; border:1px solid var(--color-border); box-shadow:0 20px 60px rgb(0 0 0/0.2); width:100%; max-width:36rem; margin:auto;">
|
||
<form id="hr-hiring-form" novalidate hx-post="/hiring/" hx-target="#main-content" hx-indicator="#loader, find .btn-label-loading" hx-disabled-elt="find button[type=submit]">
|
||
{% csrf_token %}
|
||
<div style="padding:1rem 1.25rem; border-bottom:1px solid var(--color-border); display:flex; align-items:flex-start; justify-content:space-between; gap:0.75rem;">
|
||
<div>
|
||
<div id="hr-hiring-modal-title" style="font-size:1rem; font-weight:600; color:var(--color-foreground);">{% trans "Новая заявка на найм" %}</div>
|
||
<p style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "Интерн-учётка и заявка IT на время испытания. Персональный аккаунт — после утверждения." %}</p>
|
||
<p style="font-size:0.75rem; margin-top:0.25rem; {% if intern_slots_free %}color:hsl(152 45% 32%);{% else %}color:hsl(0 55% 40%); font-weight:600;{% endif %}">
|
||
{% blocktrans with free=intern_slots_free total=intern_slots_total %}Свободных интерн-слотов: {{ free }} из {{ total }}{% endblocktrans %}
|
||
</p>
|
||
</div>
|
||
<button type="button" class="btn btn-ghost btn-icon" onclick="hrHiringClose()" aria-label="{% trans 'Закрыть' %}">
|
||
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><line x1="18" y1="6" x2="6" y2="18"/><line x1="6" y1="6" x2="18" y2="18"/></svg>
|
||
</button>
|
||
</div>
|
||
|
||
<div style="display:flex; gap:0.5rem; padding:0.875rem 1.25rem 0;">
|
||
<button type="button" class="hr-hire-step-btn" data-step="1" onclick="hrHiringGo(1)" style="flex:1; border:none; background:transparent; cursor:pointer; padding:0;">
|
||
<div class="hr-hire-step-num" data-step="1" style="width:1.5rem; height:1.5rem; border-radius:999px; margin:0 auto 0.25rem; display:flex; align-items:center; justify-content:center; font-size:0.75rem; font-weight:600;">1</div>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground);">{% trans "Кандидат" %}</div>
|
||
</button>
|
||
<button type="button" class="hr-hire-step-btn" data-step="2" onclick="hrHiringGo(2)" style="flex:1; border:none; background:transparent; cursor:pointer; padding:0;">
|
||
<div class="hr-hire-step-num" data-step="2" style="width:1.5rem; height:1.5rem; border-radius:999px; margin:0 auto 0.25rem; display:flex; align-items:center; justify-content:center; font-size:0.75rem; font-weight:600;">2</div>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground);">{% trans "Место" %}</div>
|
||
</button>
|
||
<button type="button" class="hr-hire-step-btn" data-step="3" onclick="hrHiringGo(3)" style="flex:1; border:none; background:transparent; cursor:pointer; padding:0;">
|
||
<div class="hr-hire-step-num" data-step="3" style="width:1.5rem; height:1.5rem; border-radius:999px; margin:0 auto 0.25rem; display:flex; align-items:center; justify-content:center; font-size:0.75rem; font-weight:600;">3</div>
|
||
<div style="font-size:0.75rem; color:var(--color-muted-foreground);">{% trans "Доступы" %}</div>
|
||
</button>
|
||
</div>
|
||
|
||
<div id="hr-hire-step-error" style="display:none; margin:0.75rem 1.25rem 0; padding:0.5rem 0.75rem; 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>
|
||
{% if hiring_form_errors %}
|
||
<div style="margin:0.75rem 1.25rem 0; padding:0.5rem 0.75rem; 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.25rem;">{% 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 %}
|
||
|
||
<div style="padding:1.25rem; display:flex; flex-direction:column; gap:0.75rem; min-height:14rem;">
|
||
<div class="hr-hire-step" data-step="1">
|
||
<div style="display:grid; grid-template-columns:1fr 1fr; gap:0.75rem;">
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Фамилия " %}<span style="color:var(--color-destructive);">*</span></label>
|
||
<input type="text" name="last_name" class="input" style="width:100%;" autocomplete="family-name">
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Имя " %}<span style="color:var(--color-destructive);">*</span></label>
|
||
<input type="text" name="first_name" class="input" style="width:100%;" autocomplete="given-name">
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Отчество" %}</label>
|
||
<input type="text" name="middle_name" class="input" style="width:100%;">
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "ИНН " %}<span style="color:var(--color-destructive);">*</span></label>
|
||
<input type="text" name="inn_code" inputmode="numeric" maxlength="10" autocomplete="off"
|
||
class="input" style="width:100%;" placeholder="0000000000">
|
||
<p style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">{% trans "10 цифр. Нужен фоторегистратору." %}</p>
|
||
</div>
|
||
<div style="display:grid; grid-template-columns:1fr 1fr; gap:0.75rem;">
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Email кандидата" %}</label>
|
||
<input type="email" name="candidate_email" class="input" style="width:100%;">
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Телефон" %}</label>
|
||
<input type="text" name="candidate_phone" placeholder="+380..." class="input" style="width:100%;">
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="hr-hire-step" data-step="2" style="display:none;">
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Тип локации " %}<span style="color:var(--color-destructive);">*</span></label>
|
||
<select name="user_location_type" id="hr-hiring-loc-type" class="input" style="width:100%;" onchange="hrHiringLocToggle(this.value)">
|
||
<option value="">{% trans "Выберите..." %}</option>
|
||
<option value="office">{% trans "Офис" %}</option>
|
||
<option value="pharmacy" selected>{% trans "Аптека" %}</option>
|
||
<option value="warehouse">{% trans "Склад" %}</option>
|
||
</select>
|
||
</div>
|
||
<div id="hr-hiring-department-field" style="display:none;">
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Отдел " %}<span class="hr-req-office" style="color:var(--color-destructive); display:none;">*</span></label>
|
||
<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:40; 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; margin-bottom:0.375rem;">{% trans "Аптека " %}<span style="color:var(--color-destructive);">*</span></label>
|
||
<select name="pharmacy_id" id="hr-hiring-pharmacy-select" class="input" style="width:100%;">
|
||
<option value="">—</option>
|
||
{% for pharmacy in hr_pharmacies %}
|
||
<option value="{{ pharmacy.id }}">{% trans "Аптека" %} №{{ pharmacy.pharmacy_number }} — {{ pharmacy.address }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<div id="hr-hiring-location-field" style="display:none;">
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Офис / склад " %}<span style="color:var(--color-destructive);">*</span></label>
|
||
<select name="location_id" id="hr-hiring-location-select" class="input" style="width:100%;">
|
||
<option value="">—</option>
|
||
{% for loc in hr_locations %}
|
||
<option value="{{ loc.id }}" data-type="{{ loc.location_type }}">{{ loc.get_location_type_display }} — {{ loc.address|default:loc }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Должность" %}</label>
|
||
<select name="post_id" id="hr-hiring-post-select" class="input" style="width:100%;">
|
||
<option value="">—</option>
|
||
{% for post in hr_posts %}
|
||
<option value="{{ post.id }}">{{ post.name }}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
<div style="display:grid; grid-template-columns:1fr 1fr; gap:0.75rem;">
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Дата выхода" %}</label>
|
||
<input type="date" name="hire_date" value="{{ today|date:'Y-m-d' }}" class="input" style="width:100%;">
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Срок испытания" %}</label>
|
||
<select name="trial_days" class="input" style="width:100%;">
|
||
{% for n in hr_trial_days_choices %}
|
||
<option value="{{ n }}" {% if n == 3 %}selected{% endif %}>{{ n }} {% trans "дн." %}</option>
|
||
{% endfor %}
|
||
</select>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div class="hr-hire-step" data-step="3" style="display:none;">
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Требуются доступы" %}</label>
|
||
<p style="font-size:0.75rem; color:var(--color-muted-foreground); margin:0 0 0.5rem;">{% trans "IT подготовит рабочее место. Список зависит от типа локации." %}</p>
|
||
{{ hr_access_location_types|json_script:"hr-access-loc-types-data" }}
|
||
<div id="hr-hiring-access-list" style="display:flex; flex-wrap:wrap; gap:0.5rem 1.25rem;">
|
||
{% for access in hr_access_systems %}
|
||
<label class="hr-access-option" data-access-id="{{ access.id }}"
|
||
style="display:flex; align-items:center; gap:0.375rem; font-size:0.8125rem; color:var(--color-foreground); cursor:pointer;">
|
||
<input type="checkbox" name="requested_access" value="{{ access.id }}">
|
||
{{ access.name }}
|
||
</label>
|
||
{% endfor %}
|
||
</div>
|
||
</div>
|
||
<div>
|
||
<label style="display:block; font-size:0.8125rem; font-weight:500; margin-bottom:0.375rem;">{% trans "Примечание по доступам" %}</label>
|
||
<textarea name="access_note" placeholder="{% trans "Например: 1С Бухгалтерия — только просмотр" %}"
|
||
style="width:100%; min-height:4rem; resize:vertical; background:var(--color-card); border:1px solid var(--color-input); border-radius:var(--radius); padding:0.4375rem 0.75rem; font-size:0.875rem; color:var(--color-foreground); font-family:var(--font-sans); outline:none; box-sizing:border-box;"></textarea>
|
||
</div>
|
||
</div>
|
||
</div>
|
||
|
||
<div style="padding:0.875rem 1.25rem; border-top:1px solid var(--color-border); display:flex; justify-content:space-between; gap:0.5rem;">
|
||
<button type="button" id="hr-hire-back" class="btn btn-secondary" style="border:1px solid var(--color-border);" onclick="hrHiringGo(hrHireStep - 1)">{% trans "Назад" %}</button>
|
||
<div style="display:flex; gap:0.5rem;">
|
||
<button type="button" class="btn btn-secondary" style="border:1px solid var(--color-border);" onclick="hrHiringClose()">{% trans "Отмена" %}</button>
|
||
<button type="button" id="hr-hire-next" class="btn btn-primary" onclick="hrHiringNext()">{% trans "Далее" %}</button>
|
||
<button type="submit" id="hr-hire-submit" class="btn btn-primary" style="display:none;" {% if not intern_slots_free %}disabled{% endif %}>
|
||
{% trans "Создать заявку" %}
|
||
<span class="btn-label-loading htmx-indicator">{% trans "Создание…" %}</span>
|
||
</button>
|
||
</div>
|
||
</div>
|
||
</form>
|
||
</div>
|
||
</div>
|
||
<style>
|
||
.hr-hire-step-num { background: var(--color-muted); color: var(--color-muted-foreground); }
|
||
.hr-hire-step-num.is-active { background: var(--color-primary); color: #fff; }
|
||
.hr-hire-step-num.is-done { background: hsl(152 45% 90%); color: hsl(152 45% 28%); }
|
||
</style>
|