diff --git a/backend/static/css/components/request-list.css b/backend/static/css/components/request-list.css
index b9805397..b0091356 100644
--- a/backend/static/css/components/request-list.css
+++ b/backend/static/css/components/request-list.css
@@ -285,3 +285,122 @@
}
}
+/* ========================================
+ AJAX-режим: стили для req-item
+ ======================================== */
+
+.req-item {
+ border-bottom: 1px solid var(--bs-border-color);
+ padding: 1rem;
+ transition: background-color 0.2s;
+}
+
+.req-item:hover {
+ background-color: var(--bs-light);
+}
+
+.req-item:last-child {
+ border-bottom: none;
+}
+
+.req-header {
+ margin-bottom: 0.75rem;
+}
+
+.req-title-row {
+ display: flex;
+ align-items: center;
+ justify-content: space-between;
+ gap: 0.75rem;
+ margin-bottom: 0.5rem;
+}
+
+.req-link {
+ display: flex;
+ align-items: center;
+ gap: 0.5rem;
+ text-decoration: none;
+ color: var(--bs-body-color);
+ font-weight: 500;
+ flex: 1;
+ min-width: 0;
+}
+
+.req-link:hover {
+ color: var(--bs-primary);
+}
+
+.req-link strong {
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+}
+
+.req-meta {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 1rem;
+ font-size: 0.875rem;
+ color: var(--bs-secondary-color);
+}
+
+.req-meta > span {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+}
+
+.req-comment {
+ margin: 0.5rem 0;
+ padding: 0.5rem;
+ background-color: var(--bs-light);
+ border-radius: 0.375rem;
+ font-size: 0.875rem;
+ color: var(--bs-secondary-color);
+}
+
+.req-footer {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0.75rem;
+ align-items: center;
+ padding-top: 0.75rem;
+ border-top: 1px solid var(--bs-border-color-translucent);
+ font-size: 0.875rem;
+}
+
+.req-approver,
+.req-recipients {
+ display: flex;
+ align-items: center;
+ gap: 0.25rem;
+ color: var(--bs-secondary-color);
+}
+
+/* Badge стили для статусов */
+.badge-warning {
+ background-color: #ffc107;
+ color: #000;
+}
+
+.badge-success {
+ background-color: #198754;
+ color: #fff;
+}
+
+.badge-danger {
+ background-color: #dc3545;
+ color: #fff;
+}
+
+.badge-secondary {
+ background-color: #6c757d;
+ color: #fff;
+}
+
+/* Спиннер загрузки */
+.load-more-trigger {
+ visibility: hidden;
+}
+
+
diff --git a/backend/static/js/components/requestListHandler.js b/backend/static/js/components/requestListHandler.js
index 93e6df05..e1ccc471 100644
--- a/backend/static/js/components/requestListHandler.js
+++ b/backend/static/js/components/requestListHandler.js
@@ -22,11 +22,11 @@ export function initRequestListHandler(options) {
headers = {}
} = options;
- const listElement = document.getElementById('requestList');
+ const listElement = document.getElementById('reqList');
const searchInput = document.getElementById('reqFilter');
if (!listElement) {
- console.warn('initRequestListHandler: #requestList not found');
+ console.warn('initRequestListHandler: #reqList not found');
return { load: () => {}, destroy: () => {} };
}
@@ -281,62 +281,177 @@ export function initRequestListHandler(options) {
* @returns {string} HTML
*/
function renderRequestRow(req) {
- const statusClass = getStatusClass(req.status);
- const statusText = getStatusText(req.status);
- const detailUrl = detailUrlTemplate.replace('{id}', req.id);
+ const type = (req.type || '').toLowerCase();
+ const status = (req.status || '').toLowerCase();
+
+ // Иконка типа
+ let typeIcon = 'bi-clipboard-check text-secondary';
+ if (type === 'vacation') typeIcon = 'bi-calendar-check text-primary';
+ else if (type === 'sick_leave') typeIcon = 'bi-capsule text-danger';
+ else if (type === 'transfer') typeIcon = 'bi-box-arrow-right text-info';
+ else if (type === 'dismissal') typeIcon = 'bi-door-open text-warning';
+
+ // Текст типа
+ const typeText = {
+ 'vacation': 'Отпуск',
+ 'sick_leave': 'Больничный',
+ 'transfer': 'Перевод',
+ 'dismissal': 'Увольнение',
+ 'other': 'Другое'
+ }[type] || req.type;
+
+ // Класс и текст статуса
+ let statusBadgeClass = 'text-bg-light';
+ let statusText = req.status;
+ if (status === 'draft') { statusBadgeClass = 'text-bg-info'; statusText = 'Черновик'; }
+ else if (status === 'pending') { statusBadgeClass = 'text-bg-warning'; statusText = 'На рассмотр.'; }
+ else if (status === 'approved') { statusBadgeClass = 'text-bg-success'; statusText = 'Одобрено'; }
+ else if (status === 'rejected') { statusBadgeClass = 'text-bg-danger'; statusText = 'Отклонено'; }
+ else if (status === 'cancelled') { statusBadgeClass = 'text-bg-secondary'; statusText = 'Отменено'; }
+
+ // URL для сотрудника
+ const employeeUrl = req.employee?.id === userId ? '/employees/profile/' : `/employees/${req.employee?.id}/`;
+ const employeeName = req.employee?.id === userId ? 'Вы' : (req.employee?.full_name || req.employee?.display_name || 'Сотрудник');
+
+ // Кнопки действий
+ let actionButtons = '';
+ if (req.employee?.id !== userId && canProcess) {
+ actionButtons = `
+
+
+ `;
+ } else if (req.employee?.id === userId) {
+ actionButtons = `
+
+
+ `;
+ }
return `
-
-