- Заменен лишний div.container на стандартный container для единообразия - Заменен класс .card на .ios-card в секции активности для устранения конфликтов стилей - Добавлен card-list.css в base.html для корректного отображения карточек новостей - Добавлены CSS правила для правильного поведения .row и колонок в grid-layout - Исправлена проблема с выходом календаря за границы страницы - Убраны видимые скроллбары у modal-body и modal-content для чистого UI
302 lines
9.2 KiB
JavaScript
302 lines
9.2 KiB
JavaScript
/**
|
||
* @module requestCrudHandler
|
||
* @description Обработчик CRUD операций для заявлений через API
|
||
*/
|
||
|
||
/**
|
||
* Инициализирует обработчики CRUD операций для заявлений
|
||
* @param {Object} options - Опции инициализации
|
||
* @param {string} options.apiListUrl - URL API для списка заявлений
|
||
* @param {string} options.apiDetailBase - Базовый URL для операций с конкретным заявлением
|
||
* @param {Object} [options.headers={}] - HTTP заголовки для запросов
|
||
* @returns {Object} API с методом destroy
|
||
*/
|
||
export function initRequestCrudHandler(options) {
|
||
const {
|
||
apiListUrl,
|
||
apiDetailBase,
|
||
headers = {}
|
||
} = options;
|
||
|
||
// Формы
|
||
const createForm = document.getElementById('reqCreateForm');
|
||
const editForm = document.getElementById('reqEditForm');
|
||
const deleteForm = document.getElementById('reqDeleteForm');
|
||
const approveForm = document.getElementById('reqApproveForm');
|
||
const rejectForm = document.getElementById('reqRejectForm');
|
||
const cancelForm = document.getElementById('reqCancelForm');
|
||
const commentForm = document.getElementById('reqCommentForm');
|
||
|
||
if (!createForm) {
|
||
console.warn('initRequestCrudHandler: required forms not found');
|
||
return { destroy: () => {} };
|
||
}
|
||
|
||
/**
|
||
* Обработчик создания заявления
|
||
*/
|
||
async function handleCreate(e) {
|
||
e.preventDefault();
|
||
|
||
const saveAs = e.submitter?.value || 'submit'; // 'draft' or 'submit'
|
||
const formData = new FormData(createForm);
|
||
|
||
// Удаляем пустые поля для черновика
|
||
if (saveAs === 'draft') {
|
||
for (const [key, value] of Array.from(formData.entries())) {
|
||
if (!value || value === '') {
|
||
formData.delete(key);
|
||
}
|
||
}
|
||
}
|
||
|
||
try {
|
||
const url = saveAs === 'draft' ? `${apiListUrl}?save_as=draft` : apiListUrl;
|
||
const response = await fetch(url, {
|
||
method: 'POST',
|
||
headers: headers,
|
||
body: formData
|
||
});
|
||
|
||
if (!response.ok) {
|
||
const error = await response.json();
|
||
throw new Error(error.detail || 'HTTP ' + response.status);
|
||
}
|
||
|
||
await response.json();
|
||
|
||
// Показываем сообщение и перезагружаем
|
||
const message = saveAs === 'draft' ? 'Черновик сохранён.' : 'Заявление отправлено на рассмотрение.';
|
||
alert(message); // TODO: заменить на toast-уведомление
|
||
window.location.reload();
|
||
} catch (error) {
|
||
alert('Не удалось создать заявление: ' + error.message);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обработчик редактирования заявления
|
||
*/
|
||
async function handleEdit(e) {
|
||
e.preventDefault();
|
||
|
||
const reqId = editForm.elements.id.value;
|
||
const saveAs = e.submitter?.value || 'submit';
|
||
const formData = new FormData(editForm);
|
||
|
||
// Удаляем пустые поля
|
||
for (const [key, value] of Array.from(formData.entries())) {
|
||
if (!value || value === '') {
|
||
formData.delete(key);
|
||
}
|
||
}
|
||
|
||
try {
|
||
let url = `${apiDetailBase}${reqId}/`;
|
||
if (saveAs === 'draft' || saveAs === 'submit') {
|
||
url += `?save_as=${saveAs}`;
|
||
}
|
||
|
||
const response = await fetch(url, {
|
||
method: 'PATCH',
|
||
headers: headers,
|
||
body: formData
|
||
});
|
||
|
||
if (!response.ok) {
|
||
const error = await response.json();
|
||
throw new Error(error.detail || 'HTTP ' + response.status);
|
||
}
|
||
|
||
await response.json();
|
||
alert('Заявление обновлено.');
|
||
window.location.reload();
|
||
} catch (error) {
|
||
alert('Не удалось обновить заявление: ' + error.message);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обработчик удаления заявления
|
||
*/
|
||
async function handleDelete(e) {
|
||
e.preventDefault();
|
||
|
||
const reqId = deleteForm.elements.id.value;
|
||
|
||
if (!confirm('Вы уверены, что хотите удалить это заявление?')) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${apiDetailBase}${reqId}/`, {
|
||
method: 'DELETE',
|
||
headers: headers
|
||
});
|
||
|
||
if (!response.ok && response.status !== 204) {
|
||
const error = await response.json();
|
||
throw new Error(error.detail || 'HTTP ' + response.status);
|
||
}
|
||
|
||
alert('Заявление удалено.');
|
||
window.location.reload();
|
||
} catch (error) {
|
||
alert('Не удалось удалить заявление: ' + error.message);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обработчик одобрения заявления
|
||
*/
|
||
async function handleApprove(e) {
|
||
e.preventDefault();
|
||
|
||
const reqId = approveForm.elements.id.value;
|
||
|
||
try {
|
||
const response = await fetch(`${apiDetailBase}${reqId}/approve/`, {
|
||
method: 'POST',
|
||
headers: headers
|
||
});
|
||
|
||
if (!response.ok) {
|
||
const error = await response.json();
|
||
throw new Error(error.detail || 'HTTP ' + response.status);
|
||
}
|
||
|
||
await response.json();
|
||
alert('Заявление одобрено.');
|
||
window.location.reload();
|
||
} catch (error) {
|
||
alert('Не удалось одобрить заявление: ' + error.message);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обработчик отклонения заявления
|
||
*/
|
||
async function handleReject(e) {
|
||
e.preventDefault();
|
||
|
||
const reqId = rejectForm.elements.id.value;
|
||
|
||
try {
|
||
const response = await fetch(`${apiDetailBase}${reqId}/reject/`, {
|
||
method: 'POST',
|
||
headers: headers
|
||
});
|
||
|
||
if (!response.ok) {
|
||
const error = await response.json();
|
||
throw new Error(error.detail || 'HTTP ' + response.status);
|
||
}
|
||
|
||
await response.json();
|
||
alert('Заявление отклонено.');
|
||
window.location.reload();
|
||
} catch (error) {
|
||
alert('Не удалось отклонить заявление: ' + error.message);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обработчик отмены заявления (пользователем)
|
||
*/
|
||
async function handleCancel(e) {
|
||
e.preventDefault();
|
||
|
||
const reqId = cancelForm.elements.id.value;
|
||
|
||
if (!confirm('Вы уверены, что хотите отменить это заявление?')) {
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${apiDetailBase}${reqId}/cancel/`, {
|
||
method: 'POST',
|
||
headers: headers
|
||
});
|
||
|
||
if (!response.ok) {
|
||
const error = await response.json();
|
||
throw new Error(error.detail || 'HTTP ' + response.status);
|
||
}
|
||
|
||
await response.json();
|
||
alert('Заявление отменено.');
|
||
window.location.reload();
|
||
} catch (error) {
|
||
alert('Не удалось отменить заявление: ' + error.message);
|
||
}
|
||
}
|
||
|
||
/**
|
||
* Обработчик добавления комментария
|
||
*/
|
||
async function handleComment(e) {
|
||
e.preventDefault();
|
||
|
||
const reqId = commentForm.elements.id.value;
|
||
const text = (commentForm.elements.text.value || '').trim();
|
||
|
||
if (!text) {
|
||
alert('Комментарий не может быть пустым.');
|
||
return;
|
||
}
|
||
|
||
try {
|
||
const response = await fetch(`${apiDetailBase}${reqId}/comments/`, {
|
||
method: 'POST',
|
||
headers: {
|
||
...headers,
|
||
'Content-Type': 'application/json'
|
||
},
|
||
body: JSON.stringify({ text })
|
||
});
|
||
|
||
if (!response.ok && response.status !== 201) {
|
||
const error = await response.json();
|
||
throw new Error(error.detail || 'HTTP ' + response.status);
|
||
}
|
||
|
||
await response.json();
|
||
alert('Комментарий добавлен.');
|
||
window.location.reload();
|
||
} catch (error) {
|
||
alert('Не удалось добавить комментарий: ' + error.message);
|
||
}
|
||
}
|
||
|
||
// Установка обработчиков
|
||
createForm?.addEventListener('submit', handleCreate);
|
||
editForm?.addEventListener('submit', handleEdit);
|
||
deleteForm?.addEventListener('submit', handleDelete);
|
||
approveForm?.addEventListener('submit', handleApprove);
|
||
rejectForm?.addEventListener('submit', handleReject);
|
||
cancelForm?.addEventListener('submit', handleCancel);
|
||
commentForm?.addEventListener('submit', handleComment);
|
||
|
||
/**
|
||
* Функция для удаления всех обработчиков
|
||
*/
|
||
function destroy() {
|
||
createForm?.removeEventListener('submit', handleCreate);
|
||
editForm?.removeEventListener('submit', handleEdit);
|
||
deleteForm?.removeEventListener('submit', handleDelete);
|
||
approveForm?.removeEventListener('submit', handleApprove);
|
||
rejectForm?.removeEventListener('submit', handleReject);
|
||
cancelForm?.removeEventListener('submit', handleCancel);
|
||
commentForm?.removeEventListener('submit', handleComment);
|
||
}
|
||
|
||
console.log('Request CRUD handler initialized');
|
||
|
||
return { destroy };
|
||
}
|
||
|
||
// Экспорт для совместимости с неModular кодом
|
||
if (typeof window !== 'undefined') {
|
||
window.initRequestCrudHandler = initRequestCrudHandler;
|
||
}
|