i18n: перевод страницы hr-portal (ru/uk/en)

HR-портал: метрики, вкладки (сотрудники/заявки/тренинги/вакансии/стажировка),
форма найма, отпуска/больничные, документы — помечены {% trans %} и
переведены на uk/en (включая строчные/смешанные строки, кнопки, hx-confirm).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-07-27 16:20:55 +03:00
parent 611f0e1fdd
commit e34c45c20b
5 changed files with 853 additions and 185 deletions
Binary file not shown.
+366 -33
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-07-27 12:27+0300\n"
"POT-Creation-Date: 2026-07-27 16:17+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -19,6 +19,7 @@ msgstr ""
#: apps/ad_connector/models.py:10 apps/employees/models/base.py:186
#: apps/employees/models/permissions.py:47 templates/pages/employees.html:103
#: templates/pages/hr-portal.html:215
msgid "Сотрудник"
msgstr "Employee"
@@ -48,7 +49,8 @@ msgstr ""
#: apps/locations/models/pharmacies.py:128 apps/mail_connector/models.py:24
#: apps/tasks/models.py:40 apps/visit_manager/admin.py:199 core/admin.py:32
#: templates/pages/dislocation.html:122 templates/pages/employees.html:107
#: templates/pages/pharmacies.html:119 templates/pages/pharmacy-detail.html:195
#: templates/pages/hr-portal.html:535 templates/pages/pharmacies.html:119
#: templates/pages/pharmacy-detail.html:195
#: templates/pages/pharmacy-detail.html:245 templates/pages/structure.html:63
msgid "Статус"
msgstr "Status"
@@ -77,7 +79,8 @@ msgid "Журнал синхронизации AD"
msgstr ""
#: apps/employees/admin.py:37 apps/employees/admin.py:244
#: apps/employees/models/base.py:112 templates/pages/structure.html:59
#: apps/employees/models/base.py:112 templates/pages/hr-portal.html:446
#: templates/pages/structure.html:59
msgid "Отдел"
msgstr "Department"
@@ -175,9 +178,9 @@ msgstr ""
msgid "Имя"
msgstr "First name"
#: apps/employees/models/base.py:43
#: apps/employees/models/base.py:43 templates/pages/hr-portal.html:430
msgid "Отчество"
msgstr ""
msgstr "Patronymic"
#: apps/employees/models/base.py:45
msgid "Доступ к панели администратора"
@@ -189,7 +192,8 @@ msgstr ""
#: apps/employees/models/base.py:47 core/models/directories.py:29
#: core/models/directories.py:121 templates/pages/employee-detail.html:38
#: templates/pages/employees.html:148 templates/pages/structure.html:89
#: templates/pages/employees.html:148 templates/pages/hr-portal.html:174
#: templates/pages/structure.html:89
msgid "Активный"
msgstr "Active"
@@ -255,16 +259,20 @@ msgstr "Relationship"
#: apps/locations/models/pharmacies.py:349 apps/mail_connector/models.py:12
#: apps/utilities/models.py:17 templates/pages/dislocation.html:116
#: templates/pages/employees.html:64 templates/pages/employees.html:90
#: templates/pages/hr-portal.html:126 templates/pages/hr-portal.html:441
#: templates/pages/hr-portal.html:455 templates/pages/hr-portal.html:459
msgid "Аптека"
msgstr "Pharmacy"
#: apps/employees/models/base.py:82 apps/hiring/models.py:35
#: apps/locations/models/base.py:30
#: apps/locations/models/base.py:30 templates/pages/hr-portal.html:128
#: templates/pages/hr-portal.html:442
msgid "Склад"
msgstr ""
msgstr "Warehouse"
#: apps/employees/models/base.py:83 apps/locations/models/base.py:31
#: templates/pages/employees.html:56
#: templates/pages/employees.html:56 templates/pages/hr-portal.html:124
#: templates/pages/hr-portal.html:440
msgid "Офис"
msgstr "Office"
@@ -295,7 +303,8 @@ msgid "Заполняется для office / warehouse"
msgstr ""
#: apps/employees/models/base.py:119 templates/pages/dislocation.html:297
#: templates/pages/employees.html:104
#: templates/pages/employees.html:104 templates/pages/hr-portal.html:216
#: templates/pages/hr-portal.html:467
msgid "Должность"
msgstr "Position"
@@ -317,9 +326,10 @@ msgid "Конец испытательного срока"
msgstr ""
#: apps/employees/models/base.py:133 apps/visit_manager/admin.py:262
#: apps/visit_manager/admin.py:289
#: apps/visit_manager/admin.py:289 templates/pages/hr-portal.html:165
#: templates/pages/hr-portal.html:234
msgid "Фото"
msgstr ""
msgstr "Photo"
#: apps/employees/models/base.py:137
msgid "ID Mattermost"
@@ -398,7 +408,7 @@ msgstr ""
#: apps/employees/models/base.py:187 templates/index.html:250
#: templates/pages/dashboard.html:174 templates/pages/employees.html:8
#: templates/pages/employees.html:24
#: templates/pages/employees.html:24 templates/pages/hr-portal.html:92
msgid "Сотрудники"
msgstr "Employees"
@@ -593,9 +603,9 @@ msgstr ""
msgid "Особистий email кандидата"
msgstr ""
#: apps/hiring/models.py:29
#: apps/hiring/models.py:29 templates/pages/hr-portal.html:495
msgid "Телефон кандидата"
msgstr ""
msgstr "Candidate phone"
#: apps/hiring/models.py:36
msgid "Офіс"
@@ -668,8 +678,9 @@ msgstr ""
#: apps/it_manager/admin.py:34 apps/it_manager/admin.py:464
#: apps/it_manager/admin.py:567 apps/it_manager/admin.py:581
#: apps/locations/models/base.py:65 apps/visit_manager/admin.py:227
#: templates/pages/hr-portal.html:218
msgid "Локация"
msgstr ""
msgstr "Location"
#: apps/it_manager/admin.py:91
msgid "Экземпляров"
@@ -1726,7 +1737,7 @@ msgstr "Utilities"
msgid "Рекрутинг"
msgstr "Recruiting"
#: templates/index.html:410
#: templates/index.html:410 templates/pages/hr-portal.html:292
msgid "Учёт рабочего времени"
msgstr "Time tracking"
@@ -1734,9 +1745,9 @@ msgstr "Time tracking"
msgid "Поддержка"
msgstr "Support"
#: templates/index.html:428
#: templates/index.html:428 templates/pages/hr-portal.html:284
msgid "Справка"
msgstr "Help"
msgstr "Reference"
#: templates/index.html:438 templates/pages/dashboard.html:193
msgid "Поддержка IT"
@@ -1758,7 +1769,7 @@ msgstr "Search..."
msgid "Язык"
msgstr "Language"
#: templates/index.html:607
#: templates/index.html:607 templates/pages/hr-portal.html:199
msgid "Профиль"
msgstr "Profile"
@@ -1875,7 +1886,7 @@ msgstr "Directory"
msgid "адрес не указан"
msgstr "address not specified"
#: templates/pages/dislocation.html:3
#: templates/pages/dislocation.html:3 templates/pages/hr-portal.html:3
msgid "Должность не указана"
msgstr "Position not specified"
@@ -1954,7 +1965,7 @@ msgstr "All cities/regions"
msgid "Все статусы"
msgstr "All statuses"
#: templates/pages/dislocation.html:98
#: templates/pages/dislocation.html:98 templates/pages/hr-portal.html:110
msgid "Таблица"
msgstr "Table"
@@ -2092,7 +2103,7 @@ msgstr "Internal number"
msgid "Подчинённых"
msgstr "Subordinates"
#: templates/pages/employee-detail.html:105
#: templates/pages/employee-detail.html:105 templates/pages/hr-portal.html:219
msgid "Дата приёма"
msgstr "Hire date"
@@ -2146,7 +2157,8 @@ msgstr "Add employee"
msgid "сотрудников, из них"
msgstr "employees, of them"
#: templates/pages/employees.html:48 templates/pages/tasks.html:60
#: templates/pages/employees.html:48 templates/pages/hr-portal.html:122
#: templates/pages/tasks.html:60
msgid "Все"
msgstr "All"
@@ -2155,7 +2167,7 @@ msgstr "All"
msgid "Все аптеки"
msgstr "All pharmacies"
#: templates/pages/employees.html:105
#: templates/pages/employees.html:105 templates/pages/hr-portal.html:217
msgid "Отдел / Аптека"
msgstr "Department / Pharmacy"
@@ -2167,6 +2179,335 @@ msgstr "Start date"
msgid "Список сотрудников пуст."
msgstr "Employee list is empty."
#: templates/pages/hr-portal.html:7
msgid "HR Портал"
msgstr "HR Portal"
#: templates/pages/hr-portal.html:8
msgid "Управление персоналом и кадровые процессы"
msgstr "HR management and personnel processes"
#: templates/pages/hr-portal.html:16
msgid "Всего сотрудников"
msgstr "Total employees"
#: templates/pages/hr-portal.html:18
msgid "за последний месяц"
msgstr "in the last month"
#: templates/pages/hr-portal.html:31
msgid "На испытательном сроке"
msgstr "On probation"
#: templates/pages/hr-portal.html:33
msgid "требуют оценки"
msgstr "require evaluation"
#: templates/pages/hr-portal.html:44
msgid "Запланированные тренинги"
msgstr "Scheduled trainings"
#: templates/pages/hr-portal.html:46
msgid "раздел в разработке"
msgstr "section under development"
#: templates/pages/hr-portal.html:57
msgid "Заявки на отпуск"
msgstr "Vacation requests"
#: templates/pages/hr-portal.html:59
msgid "ожидает решения"
msgstr "awaiting decision"
#: templates/pages/hr-portal.html:76
msgid "Поиск работников, вакансий, тренингов..."
msgstr "Search employees, vacancies, trainings..."
#: templates/pages/hr-portal.html:83
msgid "Создать"
msgstr "Create"
#: templates/pages/hr-portal.html:94
msgid "Заявки и отпуска"
msgstr "Requests and vacations"
#: templates/pages/hr-portal.html:96
msgid "Тренинги"
msgstr "Trainings"
#: templates/pages/hr-portal.html:98
msgid "Вакансии"
msgstr "Vacancies"
#: templates/pages/hr-portal.html:105
msgid "Карточки"
msgstr "Cards"
#: templates/pages/hr-portal.html:136
msgid "Все отделы"
msgstr "All departments"
#: templates/pages/hr-portal.html:143
msgid "Все должности"
msgstr "All positions"
#: templates/pages/hr-portal.html:176
msgid "На испытании до"
msgstr "On probation until"
#: templates/pages/hr-portal.html:182
msgid "Отдел:"
msgstr "Department:"
#: templates/pages/hr-portal.html:186
msgid "Дата приёма:"
msgstr "Hire date:"
#: templates/pages/hr-portal.html:194
msgid "Телефон:"
msgstr "Phone:"
#: templates/pages/hr-portal.html:202 templates/pages/hr-portal.html:255
msgid "Активных сотрудников пока нет"
msgstr "No active employees yet"
#: templates/pages/hr-portal.html:206 templates/pages/hr-portal.html:261
msgid "Ничего не найдено по заданным фильтрам"
msgstr "Nothing found for the given filters"
#: templates/pages/hr-portal.html:242 templates/pages/hr-portal.html:559
msgid "На испытании"
msgstr "On probation"
#: templates/pages/hr-portal.html:265
msgid "Полный список сотрудников →"
msgstr "Full employee list →"
#: templates/pages/hr-portal.html:277
msgid "Отпуск"
msgstr "Vacation"
#: templates/pages/hr-portal.html:278
msgid "Подать заявку"
msgstr "Submit request"
#: templates/pages/hr-portal.html:285
msgid "Заказать документ"
msgstr "Order document"
#: templates/pages/hr-portal.html:291
msgid "Табель"
msgstr "Timesheet"
#: templates/pages/hr-portal.html:298
msgid "Начисления"
msgstr "Accruals"
#: templates/pages/hr-portal.html:299
msgid "Зарплата и премии"
msgstr "Salary and bonuses"
#: templates/pages/hr-portal.html:308
msgid "Мои заявки"
msgstr "My requests"
#: templates/pages/hr-portal.html:309
msgid "Новая"
msgstr "New"
#: templates/pages/hr-portal.html:314
msgid "Отпуск 01–14 мая"
msgstr "Vacation May 01–14"
#: templates/pages/hr-portal.html:315
msgid "Подано 10.04.2026"
msgstr "Submitted 10.04.2026"
#: templates/pages/hr-portal.html:317 templates/pages/hr-portal.html:374
msgid "На рассмотрении"
msgstr "Under review"
#: templates/pages/hr-portal.html:321
msgid "Справка о зарплате"
msgstr "Salary certificate"
#: templates/pages/hr-portal.html:322
msgid "Подано 05.04.2026"
msgstr "Submitted 05.04.2026"
#: templates/pages/hr-portal.html:324
msgid "Готово"
msgstr "Done"
#: templates/pages/hr-portal.html:328
msgid "Больничный 28–29 марта"
msgstr "Sick leave March 28–29"
#: templates/pages/hr-portal.html:329
msgid "Подано 01.04.2026"
msgstr "Submitted 01.04.2026"
#: templates/pages/hr-portal.html:331 templates/pages/hr-portal.html:562
msgid "Утверждено"
msgstr "Approved"
#: templates/pages/hr-portal.html:339
msgid "Баланс отпусков — 2026"
msgstr "Vacation balance — 2026"
#: templates/pages/hr-portal.html:345
msgid "Основной отпуск"
msgstr "Main vacation"
#: templates/pages/hr-portal.html:346 templates/pages/hr-portal.html:355
#: templates/pages/hr-portal.html:364 templates/pages/hr-portal.html:483
msgid "дн."
msgstr "days"
#: templates/pages/hr-portal.html:349
msgid "Остаток: 10 дней"
msgstr "Balance: 10 days"
#: templates/pages/hr-portal.html:354
msgid "Дополнительный отпуск"
msgstr "Additional vacation"
#: templates/pages/hr-portal.html:358
msgid "Остаток: 7 дней"
msgstr "Balance: 7 days"
#: templates/pages/hr-portal.html:363
msgid "Больничные"
msgstr "Sick leaves"
#: templates/pages/hr-portal.html:367
msgid "Остаток: 28 дней"
msgstr "Balance: 28 days"
#: templates/pages/hr-portal.html:371
msgid "Следующий отпуск"
msgstr "Next vacation"
#: templates/pages/hr-portal.html:389 templates/pages/hr-portal.html:400
msgid "Раздел в разработке"
msgstr "Section under development"
#: templates/pages/hr-portal.html:390
msgid "Планирование тренингов и обучения появится в ближайшее время"
msgstr "Training and learning planning coming soon"
#: templates/pages/hr-portal.html:401
msgid "Управление открытыми вакансиями появится в ближайшее время"
msgstr "Open vacancies management coming soon"
#: templates/pages/hr-portal.html:415
msgid "Новая заявка на найм"
msgstr "New hiring request"
#: templates/pages/hr-portal.html:416
msgid "Сразу создаёт личный учётный запис кандидата на срок испытания."
msgstr "Immediately creates a personal candidate account for the probation period."
#: templates/pages/hr-portal.html:422
msgid "Фамилия "
msgstr "Last name "
#: templates/pages/hr-portal.html:426
msgid "Имя "
msgstr "First name "
#: templates/pages/hr-portal.html:437
msgid "Тип локации "
msgstr "Location type "
#: templates/pages/hr-portal.html:439
msgid "Выберите..."
msgstr "Select..."
#: templates/pages/hr-portal.html:476
msgid "Дата выхода"
msgstr "Start date"
#: templates/pages/hr-portal.html:480
msgid "Срок испытания"
msgstr "Probation period"
#: templates/pages/hr-portal.html:491
msgid "Email кандидата"
msgstr "Candidate email"
#: templates/pages/hr-portal.html:501
msgid "Требуются доступы (после утверждения — заявка в IT)"
msgstr "Required access (after approval — IT request)"
#: templates/pages/hr-portal.html:513
msgid "Примечание по доступам"
msgstr "Note on access"
#: templates/pages/hr-portal.html:514
msgid "Например: 1С Бухгалтерия — только просмотр"
msgstr "e.g. 1C Accounting — read only"
#: templates/pages/hr-portal.html:520
msgid "Создать заявку и временный аккаунт"
msgstr "Create request and temporary account"
#: templates/pages/hr-portal.html:521
msgid "Создание учётной записи…"
msgstr "Creating account…"
#: templates/pages/hr-portal.html:533
msgid "Кандидат"
msgstr "Candidate"
#: templates/pages/hr-portal.html:534
msgid "Должность / локация"
msgstr "Position / location"
#: templates/pages/hr-portal.html:536
msgid "Испытание до"
msgstr "Probation until"
#: templates/pages/hr-portal.html:537 templates/pages/pharmacy-detail.html:300
msgid "Подал"
msgstr "Submitted by"
#: templates/pages/hr-portal.html:538 templates/pages/task-detail.html:138
msgid "Действия"
msgstr "Actions"
#: templates/pages/hr-portal.html:557
msgid "Просрочено"
msgstr "Overdue"
#: templates/pages/hr-portal.html:564
msgid "Отклонено"
msgstr "Rejected"
#: templates/pages/hr-portal.html:572
msgid "Утвердить кандидата"
msgstr "Approve candidate"
#: templates/pages/hr-portal.html:575
msgid "Утвердить"
msgstr "Approve"
#: templates/pages/hr-portal.html:581
msgid "Причина отказа"
msgstr "Reason for rejection"
#: templates/pages/hr-portal.html:583
msgid "Отклонить"
msgstr "Reject"
#: templates/pages/hr-portal.html:591
msgid "Заявка IT:"
msgstr "IT request:"
#: templates/pages/hr-portal.html:598
msgid "Заявок на найм пока нет"
msgstr "No hiring requests yet"
#: templates/pages/pharmacies.html:38
msgid "Средняя ФА на аптеку"
msgstr "Avg pharmacists per pharmacy"
@@ -2288,10 +2629,6 @@ msgstr "Readings"
msgid "Расход"
msgstr "Consumption"
#: templates/pages/pharmacy-detail.html:300
msgid "Подал"
msgstr "Submitted by"
#: templates/pages/pharmacy-detail.html:301
msgid "Комментарий"
msgstr "Comment"
@@ -2460,10 +2797,6 @@ msgstr "Write a comment..."
msgid "Отправить"
msgstr "Send"
#: templates/pages/task-detail.html:138
msgid "Действия"
msgstr "Actions"
#: templates/pages/task-detail.html:156
msgid "Вернуть в работу"
msgstr "Return to progress"
Binary file not shown.
+366 -33
View File
@@ -7,7 +7,7 @@ msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"Report-Msgid-Bugs-To: \n"
"POT-Creation-Date: 2026-07-27 12:27+0300\n"
"POT-Creation-Date: 2026-07-27 16:17+0300\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
@@ -22,6 +22,7 @@ msgstr ""
#: apps/ad_connector/models.py:10 apps/employees/models/base.py:186
#: apps/employees/models/permissions.py:47 templates/pages/employees.html:103
#: templates/pages/hr-portal.html:215
msgid "Сотрудник"
msgstr "Співробітник"
@@ -51,7 +52,8 @@ msgstr ""
#: apps/locations/models/pharmacies.py:128 apps/mail_connector/models.py:24
#: apps/tasks/models.py:40 apps/visit_manager/admin.py:199 core/admin.py:32
#: templates/pages/dislocation.html:122 templates/pages/employees.html:107
#: templates/pages/pharmacies.html:119 templates/pages/pharmacy-detail.html:195
#: templates/pages/hr-portal.html:535 templates/pages/pharmacies.html:119
#: templates/pages/pharmacy-detail.html:195
#: templates/pages/pharmacy-detail.html:245 templates/pages/structure.html:63
msgid "Статус"
msgstr "Статус"
@@ -80,7 +82,8 @@ msgid "Журнал синхронизации AD"
msgstr ""
#: apps/employees/admin.py:37 apps/employees/admin.py:244
#: apps/employees/models/base.py:112 templates/pages/structure.html:59
#: apps/employees/models/base.py:112 templates/pages/hr-portal.html:446
#: templates/pages/structure.html:59
msgid "Отдел"
msgstr "Відділ"
@@ -178,9 +181,9 @@ msgstr ""
msgid "Имя"
msgstr "Ім'я"
#: apps/employees/models/base.py:43
#: apps/employees/models/base.py:43 templates/pages/hr-portal.html:430
msgid "Отчество"
msgstr ""
msgstr "По батькові"
#: apps/employees/models/base.py:45
msgid "Доступ к панели администратора"
@@ -192,7 +195,8 @@ msgstr ""
#: apps/employees/models/base.py:47 core/models/directories.py:29
#: core/models/directories.py:121 templates/pages/employee-detail.html:38
#: templates/pages/employees.html:148 templates/pages/structure.html:89
#: templates/pages/employees.html:148 templates/pages/hr-portal.html:174
#: templates/pages/structure.html:89
msgid "Активный"
msgstr "Активний"
@@ -258,16 +262,20 @@ msgstr "Ступінь спорідненості"
#: apps/locations/models/pharmacies.py:349 apps/mail_connector/models.py:12
#: apps/utilities/models.py:17 templates/pages/dislocation.html:116
#: templates/pages/employees.html:64 templates/pages/employees.html:90
#: templates/pages/hr-portal.html:126 templates/pages/hr-portal.html:441
#: templates/pages/hr-portal.html:455 templates/pages/hr-portal.html:459
msgid "Аптека"
msgstr "Аптека"
#: apps/employees/models/base.py:82 apps/hiring/models.py:35
#: apps/locations/models/base.py:30
#: apps/locations/models/base.py:30 templates/pages/hr-portal.html:128
#: templates/pages/hr-portal.html:442
msgid "Склад"
msgstr ""
msgstr "Склад"
#: apps/employees/models/base.py:83 apps/locations/models/base.py:31
#: templates/pages/employees.html:56
#: templates/pages/employees.html:56 templates/pages/hr-portal.html:124
#: templates/pages/hr-portal.html:440
msgid "Офис"
msgstr "Офіс"
@@ -298,7 +306,8 @@ msgid "Заполняется для office / warehouse"
msgstr ""
#: apps/employees/models/base.py:119 templates/pages/dislocation.html:297
#: templates/pages/employees.html:104
#: templates/pages/employees.html:104 templates/pages/hr-portal.html:216
#: templates/pages/hr-portal.html:467
msgid "Должность"
msgstr "Посада"
@@ -320,9 +329,10 @@ msgid "Конец испытательного срока"
msgstr ""
#: apps/employees/models/base.py:133 apps/visit_manager/admin.py:262
#: apps/visit_manager/admin.py:289
#: apps/visit_manager/admin.py:289 templates/pages/hr-portal.html:165
#: templates/pages/hr-portal.html:234
msgid "Фото"
msgstr ""
msgstr "Фото"
#: apps/employees/models/base.py:137
msgid "ID Mattermost"
@@ -401,9 +411,9 @@ msgstr ""
#: apps/employees/models/base.py:187 templates/index.html:250
#: templates/pages/dashboard.html:174 templates/pages/employees.html:8
#: templates/pages/employees.html:24
#: templates/pages/employees.html:24 templates/pages/hr-portal.html:92
msgid "Сотрудники"
msgstr "Співробітники"
msgstr "Працівники"
#: apps/employees/models/permissions.py:14
msgid "Группа"
@@ -596,9 +606,9 @@ msgstr ""
msgid "Особистий email кандидата"
msgstr ""
#: apps/hiring/models.py:29
#: apps/hiring/models.py:29 templates/pages/hr-portal.html:495
msgid "Телефон кандидата"
msgstr ""
msgstr "Телефон кандидата"
#: apps/hiring/models.py:36
msgid "Офіс"
@@ -671,8 +681,9 @@ msgstr ""
#: apps/it_manager/admin.py:34 apps/it_manager/admin.py:464
#: apps/it_manager/admin.py:567 apps/it_manager/admin.py:581
#: apps/locations/models/base.py:65 apps/visit_manager/admin.py:227
#: templates/pages/hr-portal.html:218
msgid "Локация"
msgstr ""
msgstr "Локація"
#: apps/it_manager/admin.py:91
msgid "Экземпляров"
@@ -1729,7 +1740,7 @@ msgstr "Комунальні послуги"
msgid "Рекрутинг"
msgstr "Рекрутинг"
#: templates/index.html:410
#: templates/index.html:410 templates/pages/hr-portal.html:292
msgid "Учёт рабочего времени"
msgstr "Облік робочого часу"
@@ -1737,7 +1748,7 @@ msgstr "Облік робочого часу"
msgid "Поддержка"
msgstr "Підтримка"
#: templates/index.html:428
#: templates/index.html:428 templates/pages/hr-portal.html:284
msgid "Справка"
msgstr "Довідка"
@@ -1761,7 +1772,7 @@ msgstr "Пошук..."
msgid "Язык"
msgstr "Мова"
#: templates/index.html:607
#: templates/index.html:607 templates/pages/hr-portal.html:199
msgid "Профиль"
msgstr "Профіль"
@@ -1878,7 +1889,7 @@ msgstr "Довідник"
msgid "адрес не указан"
msgstr "адресу не вказано"
#: templates/pages/dislocation.html:3
#: templates/pages/dislocation.html:3 templates/pages/hr-portal.html:3
msgid "Должность не указана"
msgstr "Посада не вказана"
@@ -1957,7 +1968,7 @@ msgstr "Всі міста/регіони"
msgid "Все статусы"
msgstr "Всі статуси"
#: templates/pages/dislocation.html:98
#: templates/pages/dislocation.html:98 templates/pages/hr-portal.html:110
msgid "Таблица"
msgstr "Таблиця"
@@ -2095,7 +2106,7 @@ msgstr "Внутрішній номер"
msgid "Подчинённых"
msgstr "Підлеглих"
#: templates/pages/employee-detail.html:105
#: templates/pages/employee-detail.html:105 templates/pages/hr-portal.html:219
msgid "Дата приёма"
msgstr "Дата прийняття"
@@ -2149,7 +2160,8 @@ msgstr "Додати співробітника"
msgid "сотрудников, из них"
msgstr "співробітників, з них"
#: templates/pages/employees.html:48 templates/pages/tasks.html:60
#: templates/pages/employees.html:48 templates/pages/hr-portal.html:122
#: templates/pages/tasks.html:60
msgid "Все"
msgstr "Всі"
@@ -2158,7 +2170,7 @@ msgstr "Всі"
msgid "Все аптеки"
msgstr "Всі аптеки"
#: templates/pages/employees.html:105
#: templates/pages/employees.html:105 templates/pages/hr-portal.html:217
msgid "Отдел / Аптека"
msgstr "Відділ / Аптека"
@@ -2170,6 +2182,335 @@ msgstr "Дата початку"
msgid "Список сотрудников пуст."
msgstr "Список співробітників порожній."
#: templates/pages/hr-portal.html:7
msgid "HR Портал"
msgstr "HR Портал"
#: templates/pages/hr-portal.html:8
msgid "Управление персоналом и кадровые процессы"
msgstr "Управління персоналом та кадрові процеси"
#: templates/pages/hr-portal.html:16
msgid "Всего сотрудников"
msgstr "Всього співробітників"
#: templates/pages/hr-portal.html:18
msgid "за последний месяц"
msgstr "за останній місяць"
#: templates/pages/hr-portal.html:31
msgid "На испытательном сроке"
msgstr "На випробувальному терміні"
#: templates/pages/hr-portal.html:33
msgid "требуют оценки"
msgstr "потребують оцінки"
#: templates/pages/hr-portal.html:44
msgid "Запланированные тренинги"
msgstr "Заплановані тренінги"
#: templates/pages/hr-portal.html:46
msgid "раздел в разработке"
msgstr "розділ у розробці"
#: templates/pages/hr-portal.html:57
msgid "Заявки на отпуск"
msgstr "Заявки на відпустку"
#: templates/pages/hr-portal.html:59
msgid "ожидает решения"
msgstr "очікує рішення"
#: templates/pages/hr-portal.html:76
msgid "Поиск работников, вакансий, тренингов..."
msgstr "Пошук працівників, вакансій, тренінгів..."
#: templates/pages/hr-portal.html:83
msgid "Создать"
msgstr "Створити"
#: templates/pages/hr-portal.html:94
msgid "Заявки и отпуска"
msgstr "Заявки та відпустки"
#: templates/pages/hr-portal.html:96
msgid "Тренинги"
msgstr "Тренінги"
#: templates/pages/hr-portal.html:98
msgid "Вакансии"
msgstr "Вакансії"
#: templates/pages/hr-portal.html:105
msgid "Карточки"
msgstr "Картки"
#: templates/pages/hr-portal.html:136
msgid "Все отделы"
msgstr "Всі відділи"
#: templates/pages/hr-portal.html:143
msgid "Все должности"
msgstr "Всі посади"
#: templates/pages/hr-portal.html:176
msgid "На испытании до"
msgstr "На випробуванні до"
#: templates/pages/hr-portal.html:182
msgid "Отдел:"
msgstr "Відділ:"
#: templates/pages/hr-portal.html:186
msgid "Дата приёма:"
msgstr "Дата прийняття:"
#: templates/pages/hr-portal.html:194
msgid "Телефон:"
msgstr "Телефон:"
#: templates/pages/hr-portal.html:202 templates/pages/hr-portal.html:255
msgid "Активных сотрудников пока нет"
msgstr "Активних співробітників поки немає"
#: templates/pages/hr-portal.html:206 templates/pages/hr-portal.html:261
msgid "Ничего не найдено по заданным фильтрам"
msgstr "Нічого не знайдено за заданими фільтрами"
#: templates/pages/hr-portal.html:242 templates/pages/hr-portal.html:559
msgid "На испытании"
msgstr "На випробуванні"
#: templates/pages/hr-portal.html:265
msgid "Полный список сотрудников →"
msgstr "Повний список співробітників →"
#: templates/pages/hr-portal.html:277
msgid "Отпуск"
msgstr "Відпустка"
#: templates/pages/hr-portal.html:278
msgid "Подать заявку"
msgstr "Подати заявку"
#: templates/pages/hr-portal.html:285
msgid "Заказать документ"
msgstr "Замовити документ"
#: templates/pages/hr-portal.html:291
msgid "Табель"
msgstr "Табель"
#: templates/pages/hr-portal.html:298
msgid "Начисления"
msgstr "Нарахування"
#: templates/pages/hr-portal.html:299
msgid "Зарплата и премии"
msgstr "Зарплата та премії"
#: templates/pages/hr-portal.html:308
msgid "Мои заявки"
msgstr "Мої заявки"
#: templates/pages/hr-portal.html:309
msgid "Новая"
msgstr "Нова"
#: templates/pages/hr-portal.html:314
msgid "Отпуск 01–14 мая"
msgstr "Відпустка 01–14 травня"
#: templates/pages/hr-portal.html:315
msgid "Подано 10.04.2026"
msgstr "Подано 10.04.2026"
#: templates/pages/hr-portal.html:317 templates/pages/hr-portal.html:374
msgid "На рассмотрении"
msgstr "На розгляді"
#: templates/pages/hr-portal.html:321
msgid "Справка о зарплате"
msgstr "Довідка про зарплату"
#: templates/pages/hr-portal.html:322
msgid "Подано 05.04.2026"
msgstr "Подано 05.04.2026"
#: templates/pages/hr-portal.html:324
msgid "Готово"
msgstr "Готово"
#: templates/pages/hr-portal.html:328
msgid "Больничный 28–29 марта"
msgstr "Лікарняний 28–29 березня"
#: templates/pages/hr-portal.html:329
msgid "Подано 01.04.2026"
msgstr "Подано 01.04.2026"
#: templates/pages/hr-portal.html:331 templates/pages/hr-portal.html:562
msgid "Утверждено"
msgstr "Затверджено"
#: templates/pages/hr-portal.html:339
msgid "Баланс отпусков — 2026"
msgstr "Баланс відпусток — 2026"
#: templates/pages/hr-portal.html:345
msgid "Основной отпуск"
msgstr "Основна відпустка"
#: templates/pages/hr-portal.html:346 templates/pages/hr-portal.html:355
#: templates/pages/hr-portal.html:364 templates/pages/hr-portal.html:483
msgid "дн."
msgstr "дн."
#: templates/pages/hr-portal.html:349
msgid "Остаток: 10 дней"
msgstr "Залишок: 10 днів"
#: templates/pages/hr-portal.html:354
msgid "Дополнительный отпуск"
msgstr "Додаткова відпустка"
#: templates/pages/hr-portal.html:358
msgid "Остаток: 7 дней"
msgstr "Залишок: 7 днів"
#: templates/pages/hr-portal.html:363
msgid "Больничные"
msgstr "Лікарняні"
#: templates/pages/hr-portal.html:367
msgid "Остаток: 28 дней"
msgstr "Залишок: 28 днів"
#: templates/pages/hr-portal.html:371
msgid "Следующий отпуск"
msgstr "Наступна відпустка"
#: templates/pages/hr-portal.html:389 templates/pages/hr-portal.html:400
msgid "Раздел в разработке"
msgstr "Розділ у розробці"
#: templates/pages/hr-portal.html:390
msgid "Планирование тренингов и обучения появится в ближайшее время"
msgstr "Планування тренінгів та навчання з'явиться найближчим часом"
#: templates/pages/hr-portal.html:401
msgid "Управление открытыми вакансиями появится в ближайшее время"
msgstr "Управління відкритими вакансіями з'явиться найближчим часом"
#: templates/pages/hr-portal.html:415
msgid "Новая заявка на найм"
msgstr "Нова заявка на найм"
#: templates/pages/hr-portal.html:416
msgid "Сразу создаёт личный учётный запис кандидата на срок испытания."
msgstr "Одразу створює особистий обліковий запис кандидата на термін випробування."
#: templates/pages/hr-portal.html:422
msgid "Фамилия "
msgstr "Прізвище "
#: templates/pages/hr-portal.html:426
msgid "Имя "
msgstr "Ім'я "
#: templates/pages/hr-portal.html:437
msgid "Тип локации "
msgstr "Тип локації "
#: templates/pages/hr-portal.html:439
msgid "Выберите..."
msgstr "Оберіть..."
#: templates/pages/hr-portal.html:476
msgid "Дата выхода"
msgstr "Дата виходу"
#: templates/pages/hr-portal.html:480
msgid "Срок испытания"
msgstr "Термін випробування"
#: templates/pages/hr-portal.html:491
msgid "Email кандидата"
msgstr "Email кандидата"
#: templates/pages/hr-portal.html:501
msgid "Требуются доступы (после утверждения — заявка в IT)"
msgstr "Потрібні доступи (після затвердження — заявка в IT)"
#: templates/pages/hr-portal.html:513
msgid "Примечание по доступам"
msgstr "Примітка щодо доступів"
#: templates/pages/hr-portal.html:514
msgid "Например: 1С Бухгалтерия — только просмотр"
msgstr "Наприклад: 1С Бухгалтерія — лише перегляд"
#: templates/pages/hr-portal.html:520
msgid "Создать заявку и временный аккаунт"
msgstr "Створити заявку та тимчасовий акаунт"
#: templates/pages/hr-portal.html:521
msgid "Создание учётной записи…"
msgstr "Створення облікового запису…"
#: templates/pages/hr-portal.html:533
msgid "Кандидат"
msgstr "Кандидат"
#: templates/pages/hr-portal.html:534
msgid "Должность / локация"
msgstr "Посада / локація"
#: templates/pages/hr-portal.html:536
msgid "Испытание до"
msgstr "Випробування до"
#: templates/pages/hr-portal.html:537 templates/pages/pharmacy-detail.html:300
msgid "Подал"
msgstr "Подав"
#: templates/pages/hr-portal.html:538 templates/pages/task-detail.html:138
msgid "Действия"
msgstr "Дії"
#: templates/pages/hr-portal.html:557
msgid "Просрочено"
msgstr "Прострочено"
#: templates/pages/hr-portal.html:564
msgid "Отклонено"
msgstr "Відхилено"
#: templates/pages/hr-portal.html:572
msgid "Утвердить кандидата"
msgstr "Затвердити кандидата"
#: templates/pages/hr-portal.html:575
msgid "Утвердить"
msgstr "Затвердити"
#: templates/pages/hr-portal.html:581
msgid "Причина отказа"
msgstr "Причина відмови"
#: templates/pages/hr-portal.html:583
msgid "Отклонить"
msgstr "Відхилити"
#: templates/pages/hr-portal.html:591
msgid "Заявка IT:"
msgstr "Заявка IT:"
#: templates/pages/hr-portal.html:598
msgid "Заявок на найм пока нет"
msgstr "Заявок на найм поки немає"
#: templates/pages/pharmacies.html:38
msgid "Средняя ФА на аптеку"
msgstr "Середня ФА на аптеку"
@@ -2291,10 +2632,6 @@ msgstr "Показання"
msgid "Расход"
msgstr "Витрата"
#: templates/pages/pharmacy-detail.html:300
msgid "Подал"
msgstr "Подав"
#: templates/pages/pharmacy-detail.html:301
msgid "Комментарий"
msgstr "Коментар"
@@ -2463,10 +2800,6 @@ msgstr "Написати коментар..."
msgid "Отправить"
msgstr "Надіслати"
#: templates/pages/task-detail.html:138
msgid "Действия"
msgstr "Дії"
#: templates/pages/task-detail.html:156
msgid "Вернуть в работу"
msgstr "Повернути в роботу"
+121 -119
View File
@@ -1,9 +1,11 @@
{% load common_tags %}
{% load i18n %}
{% trans "Должность не указана" as no_post %}
<div class="page-content">
<div style="margin-bottom:1.5rem;">
<h1 style="font-size:1.25rem; font-weight:500; color:var(--color-foreground);">HR Портал</h1>
<p style="font-size:0.875rem; color:var(--color-muted-foreground); margin-top:0.25rem;">Управління персоналом та кадрові процеси</p>
<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>
</div>
<!-- Метрики -->
@@ -11,9 +13,9 @@
<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;">Всього співробітників</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 }} за останній місяць</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">
@@ -26,9 +28,9 @@
<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;">На випробувальному терміні</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;">потребують оцінки</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">
@@ -39,9 +41,9 @@
<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;">Заплановані тренінги</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;">розділ у розробці</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">
@@ -52,9 +54,9 @@
<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;">Заявки на відпустку</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 очікує рішення</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.375rem;">1 {% trans "ожидает решения" %}</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">
@@ -71,14 +73,14 @@
<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="Пошук працівників, вакансій, тренінгів..." class="input" style="border:none; background:transparent; padding:0; box-shadow:none; font-size:0.8125rem;">
<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 request.user.is_staff %}
<button type="button" class="btn btn-primary" style="white-space:nowrap;" onclick="hrTabSwitch('hiring')">
<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>
@@ -87,25 +89,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);">Працівники</button>
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="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);">Заявки та відпустки</button>
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);">Тренінги</button>
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);">Вакансії</button>
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>
</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;">
<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>
@@ -117,13 +119,13 @@
<div style="display:flex; align-items:center; gap:0.75rem; flex-wrap:wrap; margin-bottom:1rem;">
<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);">Всі</button>
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);">Офіс</button>
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);">Аптека</button>
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);">Склад</button>
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" }}
@@ -131,14 +133,14 @@
<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;">Всі відділи</span>
<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="">Всі посади</option>
<option value="">{% trans "Все должности" %}</option>
{% for post in hr_posts %}
<option value="{{ post.id }}">{{ post.name }}</option>
{% endfor %}
@@ -160,28 +162,28 @@
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="Фото {{ employee.last_name }}" style="width:3.5rem; height:3.5rem; border-radius:50%; object-fit:cover; margin-bottom:0.625rem;">
<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:"Посада не вказана" }}</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">Активний</span>
<span class="badge badge-success">{% trans "Активный" %}</span>
{% if employee.is_on_probation %}
<span class="badge badge-warning">На випробуванні до {{ employee.probation_end_date|date:"d.m" }}</span>
<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);">Відділ:</span>
<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);">Дата прийняття:</span>
<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;">
@@ -189,19 +191,19 @@
<span style="color:var(--color-card-foreground); font-weight:500; text-align:right; overflow-wrap:anywhere;">{{ employee.email|default:"—" }}</span>
</div>
<div style="display:flex; justify-content:space-between; gap:0.5rem;">
<span style="color:var(--color-muted-foreground);">Телефон:</span>
<span style="color:var(--color-muted-foreground);">{% trans "Телефон:" %}</span>
<span style="color:var(--color-card-foreground); font-weight:500;">{{ employee.phone|default:"—" }}</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">Профіль</button>
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;">Активних співробітників поки немає</div>
<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;">Нічого не знайдено за заданими фільтрами</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>
<!-- Таблиця -->
@@ -210,11 +212,11 @@
<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;">Співробітник</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Посада</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Відділ / Аптека</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Локація</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Дата прийняття</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>
<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>
@@ -229,7 +231,7 @@
<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="Фото {{ employee.last_name }}" style="width:1.75rem; height:1.75rem; border-radius:50%; object-fit:cover; display:block;">
<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 }}
@@ -237,7 +239,7 @@
{% endif %}
<span style="font-weight:500; color:var(--color-card-foreground);">{{ employee.last_name }} {{ employee.first_name }}</span>
{% if employee.is_on_probation %}
<span class="badge badge-warning">На випробуванні</span>
<span class="badge badge-warning">{% trans "На испытании" %}</span>
{% endif %}
</div>
</td>
@@ -250,17 +252,17 @@
</tr>
{% empty %}
<tr>
<td colspan="5" style="padding:1.25rem; text-align:center; color:var(--color-muted-foreground);">Активних співробітників поки немає</td>
<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;">Нічого не знайдено за заданими фільтрами</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;">Повний список співробітників →</a>
<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>
@@ -272,29 +274,29 @@
<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);">Відпустка</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">Подати заявку</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);">Довідка</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">Замовити документ</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);">Табель</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">Облік робочого часу</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);">Нарахування</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.25rem;">Зарплата та премії</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>
@@ -303,30 +305,30 @@
<!-- Мої заявки -->
<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);">Мої заявки</span>
<button class="btn btn-ghost" style="font-size:0.75rem; padding:0.25rem 0.625rem;">+ Нова</button>
<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);">Відпустка 01–14 травня</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">Подано 10.04.2026</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">На розгляді</span>
<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);">Довідка про зарплату</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">Подано 05.04.2026</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">Готово</span>
<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);">Лікарняний 28–29 березня</div>
<div style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">Подано 01.04.2026</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">Затверджено</span>
<span class="badge badge-success">{% trans "Утверждено" %}</span>
</div>
</div>
</div>
@@ -334,42 +336,42 @@
<!-- Залишок відпусток -->
<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);">Баланс відпусток — 2026</span>
<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);">Основна відпустка</span>
<span style="font-size:0.8125rem; font-weight:600; color:var(--color-foreground);">14 / 24 дні</span>
<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;">Залишок: 10 днів</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);">Додаткова відпустка</span>
<span style="font-size:0.8125rem; font-weight:600; color:var(--color-foreground);">0 / 7 днів</span>
<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;">Залишок: 7 днів</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);">Лікарняні</span>
<span style="font-size:0.8125rem; font-weight:600; color:var(--color-foreground);">2 / 30 днів</span>
<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;">Залишок: 28 днів</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;">Наступна відпустка</div>
<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">На розгляді</span>
<span class="badge badge-warning">{% trans "На рассмотрении" %}</span>
</div>
</div>
</div>
@@ -384,8 +386,8 @@
<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;">Розділ у розробці</div>
<div style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.375rem;">Планування тренінгів та навчання з'явиться найближчим часом</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>
@@ -395,8 +397,8 @@
<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;">Розділ у розробці</div>
<div style="font-size:0.8125rem; color:var(--color-muted-foreground); margin-top:0.375rem;">Управління відкритими вакансіями з'явиться найближчим часом</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>
@@ -410,38 +412,38 @@
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; margin-bottom:1.25rem;">
{% csrf_token %}
<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);">Нова заявка на найм</span>
<p style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">Одразу створює особистий обліковий запис кандидата на термін випробування.</p>
<span style="font-size:0.8125rem; font-weight:500; color:var(--color-foreground);">{% trans "Новая заявка на найм" %}</span>
<p style="font-size:0.75rem; color:var(--color-muted-foreground); margin-top:0.125rem;">{% trans "Сразу создаёт личный учётный запис кандидата на срок испытания." %}</p>
</div>
<div style="padding:1.25rem; display:flex; flex-direction:column; gap:1rem;">
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:0.75rem;">
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Прізвище <span style="color:var(--color-destructive);">*</span></label>
<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>
<input type="text" name="last_name" required class="input" style="width:100%;">
</div>
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Ім'я <span style="color:var(--color-destructive);">*</span></label>
<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>
<input type="text" name="first_name" required class="input" style="width:100%;">
</div>
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">По батькові</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">{% trans "Отчество" %}</label>
<input type="text" name="middle_name" class="input" style="width:100%;">
</div>
</div>
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:0.75rem;">
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Тип локації <span style="color:var(--color-destructive);">*</span></label>
<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>
<select name="user_location_type" required class="input" style="width:100%;" onchange="hrHiringLocToggle(this.value)">
<option value="">Оберіть...</option>
<option value="office">Офіс</option>
<option value="pharmacy">Аптека</option>
<option value="warehouse">Склад</option>
<option value="">{% trans "Выберите..." %}</option>
<option value="office">{% trans "Офис" %}</option>
<option value="pharmacy">{% trans "Аптека" %}</option>
<option value="warehouse">{% trans "Склад" %}</option>
</select>
</div>
<div id="hr-hiring-department-field">
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Відділ</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">{% trans "Отдел" %}</label>
<select name="department_id" class="input" style="width:100%;">
<option value="">—</option>
{% for dept in hr_departments_flat %}
@@ -450,11 +452,11 @@
</select>
</div>
<div id="hr-hiring-pharmacy-field" style="display:none;">
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Аптека</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">{% trans "Аптека" %}</label>
<select name="pharmacy_id" class="input" style="width:100%;">
<option value="">—</option>
{% for pharmacy in hr_pharmacies %}
<option value="{{ pharmacy.id }}">Аптека №{{ pharmacy.pharmacy_number }} — {{ pharmacy.address }}</option>
<option value="{{ pharmacy.id }}">{% trans "Аптека" %} №{{ pharmacy.pharmacy_number }} — {{ pharmacy.address }}</option>
{% endfor %}
</select>
</div>
@@ -462,7 +464,7 @@
<div style="display:grid; grid-template-columns:repeat(3,1fr); gap:0.75rem;">
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Посада</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); 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 %}
@@ -471,14 +473,14 @@
</select>
</div>
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Дата виходу</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); 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; color:var(--color-foreground); margin-bottom:0.375rem;">Термін випробування</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); 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 }} дн.</option>
<option value="{{ n }}" {% if n == 3 %}selected{% endif %}>{{ n }} {% trans "дн." %}</option>
{% endfor %}
</select>
</div>
@@ -486,17 +488,17 @@
<div style="display:grid; grid-template-columns:1fr 1fr; gap:0.75rem;">
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Email кандидата</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); 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; color:var(--color-foreground); margin-bottom:0.375rem;">Телефон кандидата</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">{% trans "Телефон кандидата" %}</label>
<input type="text" name="candidate_phone" placeholder="+380..." class="input" style="width:100%;">
</div>
</div>
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Потрібні доступи (після затвердження — заявка в IT)</label>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">{% trans "Требуются доступы (после утверждения — заявка в IT)" %}</label>
<div style="display:flex; flex-wrap:wrap; gap:0.5rem 1.25rem;">
{% for access in hr_access_systems %}
<label style="display:flex; align-items:center; gap:0.375rem; font-size:0.8125rem; color:var(--color-foreground); cursor:pointer;">
@@ -508,15 +510,15 @@
</div>
<div>
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); margin-bottom:0.375rem;">Примітка щодо доступів</label>
<textarea name="access_note" placeholder="Наприклад: 1С Бухгалтерія — лише перегляд"
<label style="display:block; font-size:0.8125rem; font-weight:500; color:var(--color-foreground); 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>
<button type="submit" class="btn btn-primary">
Створити заявку та тимчасовий акаунт
<span class="btn-label-loading htmx-indicator">Створення облікового запису…</span>
{% trans "Создать заявку и временный аккаунт" %}
<span class="btn-label-loading htmx-indicator">{% trans "Создание учётной записи…" %}</span>
</button>
</div>
</div>
@@ -528,12 +530,12 @@
<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;">Кандидат</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Посада / локація</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Статус</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Випробування до</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Подав</th>
<th style="padding:0.75rem 1rem; text-align:left; color:var(--color-muted-foreground); font-weight:600; font-size:0.8125rem;">Дії</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>
<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>
@@ -552,14 +554,14 @@
<td style="padding:0.75rem 1rem;">
{% if hr.status == 'trial' %}
{% if hr.is_overdue %}
<span class="badge badge-danger">Прострочено</span>
<span class="badge badge-danger">{% trans "Просрочено" %}</span>
{% else %}
<span class="badge badge-warning">На випробуванні</span>
<span class="badge badge-warning">{% trans "На испытании" %}</span>
{% endif %}
{% elif hr.status == 'approved' %}
<span class="badge badge-success">Затверджено</span>
<span class="badge badge-success">{% trans "Утверждено" %}</span>
{% else %}
<span class="badge badge-danger">Відхилено</span>
<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>
@@ -567,18 +569,18 @@
<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="Затвердити кандидата {{ hr.last_name }} {{ hr.first_name }}?">
<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="Причина відмови" class="input" style="font-size:0.75rem; padding:0.3rem 0.5rem;">
<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>
@@ -586,14 +588,14 @@
{% 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>
{% if hr.granted_ticket %}
<div style="font-size:0.75rem; margin-top:0.25rem;">Заявка IT: {{ hr.granted_ticket.number }}</div>
<div style="font-size:0.75rem; margin-top:0.25rem;">{% trans "Заявка IT:" %} {{ hr.granted_ticket.number }}</div>
{% endif %}
{% endif %}
</td>
</tr>
{% empty %}
<tr>
<td colspan="6" style="padding:1.25rem; text-align:center; color:var(--color-muted-foreground);">Заявок на найм поки немає</td>
<td colspan="6" style="padding:1.25rem; text-align:center; color:var(--color-muted-foreground);">{% trans "Заявок на найм пока нет" %}</td>
</tr>
{% endfor %}
</tbody>