исправил настройку временных слотов
This commit is contained in:
@@ -20,15 +20,14 @@ const DAY_SHORT_LABELS = {
|
||||
export async function initTimeSlotsSettings() {
|
||||
const scopeSelect = document.getElementById('time-slot-scope-select');
|
||||
const scopeSummary = document.getElementById('time-slot-scope-summary');
|
||||
const scopeOpenCreateButton = document.getElementById('time-slot-scope-open-create');
|
||||
const scopeModal = document.getElementById('time-slot-scope-modal');
|
||||
const scopeModalCloseButton = document.getElementById('time-slot-scope-modal-close');
|
||||
const scopeModalCancelButton = document.getElementById('time-slot-scope-modal-cancel');
|
||||
const scopeForm = document.getElementById('time-slot-scope-form');
|
||||
const scopeNameInput = document.getElementById('time-slot-scope-name');
|
||||
const scopeAddButton = document.getElementById('time-slot-scope-add');
|
||||
const scopeDeleteButton = document.getElementById('time-slot-scope-delete');
|
||||
|
||||
const assignmentForm = document.getElementById('time-slot-assignment-form');
|
||||
const assignmentDateInput = document.getElementById('time-slot-assignment-date');
|
||||
const assignmentScopeSelect = document.getElementById('time-slot-assignment-scope');
|
||||
const assignmentsTbody = document.getElementById('time-slot-assignments-tbody');
|
||||
|
||||
const form = document.getElementById('time-slot-form');
|
||||
const title = document.getElementById('time-slot-form-title');
|
||||
const idInput = document.getElementById('time-slot-id');
|
||||
@@ -42,37 +41,40 @@ export async function initTimeSlotsSettings() {
|
||||
|
||||
let scopes = [];
|
||||
let slots = [];
|
||||
let assignments = [];
|
||||
let activeScopeId = null;
|
||||
|
||||
scopeSelect?.addEventListener('change', () => {
|
||||
activeScopeId = Number(scopeSelect.value);
|
||||
resetForm();
|
||||
render();
|
||||
renderActiveScope();
|
||||
});
|
||||
scopeAddButton?.addEventListener('click', createScope);
|
||||
scopeOpenCreateButton?.addEventListener('click', openScopeModal);
|
||||
scopeModalCloseButton?.addEventListener('click', closeScopeModal);
|
||||
scopeModalCancelButton?.addEventListener('click', closeScopeModal);
|
||||
scopeModal?.addEventListener('click', (event) => {
|
||||
if (event.target === scopeModal) closeScopeModal();
|
||||
});
|
||||
scopeModal?.addEventListener('keydown', (event) => {
|
||||
if (event.key === 'Escape') closeScopeModal();
|
||||
});
|
||||
scopeForm?.addEventListener('submit', createScope);
|
||||
scopeDeleteButton?.addEventListener('click', deleteActiveScope);
|
||||
assignmentForm?.addEventListener('submit', saveAssignment);
|
||||
form?.addEventListener('submit', saveSlot);
|
||||
resetButton?.addEventListener('click', resetForm);
|
||||
refreshButton?.addEventListener('click', loadAll);
|
||||
startInput?.addEventListener('change', fillDurationIfEmpty);
|
||||
endInput?.addEventListener('change', fillDurationIfEmpty);
|
||||
tbody?.addEventListener('click', handleSlotTableClick);
|
||||
assignmentsTbody?.addEventListener('click', handleAssignmentTableClick);
|
||||
|
||||
await loadAll();
|
||||
|
||||
async function loadAll() {
|
||||
tbody.innerHTML = '<tr><td colspan="5" class="loading-row">Загрузка...</td></tr>';
|
||||
assignmentsTbody.innerHTML = '<tr><td colspan="3" class="loading-row">Загрузка...</td></tr>';
|
||||
hideAlert('time-slot-alert');
|
||||
hideAlert('time-slot-assignment-alert');
|
||||
try {
|
||||
[scopes, slots, assignments] = await Promise.all([
|
||||
[scopes, slots] = await Promise.all([
|
||||
api.get('/api/admin/time-slots/scopes'),
|
||||
api.get('/api/admin/time-slots'),
|
||||
api.get('/api/admin/time-slots/date-assignments')
|
||||
api.get('/api/admin/time-slots')
|
||||
]);
|
||||
if (!activeScopeId || !scopes.some(scope => scope.id === activeScopeId)) {
|
||||
activeScopeId = defaultScope()?.id || scopes[0]?.id || null;
|
||||
@@ -80,28 +82,30 @@ export async function initTimeSlotsSettings() {
|
||||
render();
|
||||
} catch (error) {
|
||||
tbody.innerHTML = `<tr><td colspan="5" class="loading-row">Ошибка загрузки: ${escapeHtml(error.message)}</td></tr>`;
|
||||
assignmentsTbody.innerHTML = '<tr><td colspan="3" class="loading-row">Нет данных</td></tr>';
|
||||
}
|
||||
}
|
||||
|
||||
function render() {
|
||||
renderScopeSelects();
|
||||
renderActiveScope();
|
||||
}
|
||||
|
||||
function renderActiveScope() {
|
||||
updateScopeActions();
|
||||
renderScopeSummary();
|
||||
renderSlots();
|
||||
renderAssignments();
|
||||
}
|
||||
|
||||
function renderScopeSelects() {
|
||||
scopeSelect.innerHTML = scopes.map(scope => `
|
||||
<option value="${scope.id}" ${scope.id === activeScopeId ? 'selected' : ''}>${escapeHtml(scopeOptionLabel(scope))}</option>
|
||||
<option value="${scope.id}">${escapeHtml(scopeOptionLabel(scope))}</option>
|
||||
`).join('');
|
||||
scopeSelect.value = activeScopeId ? String(activeScopeId) : '';
|
||||
|
||||
const manualScopes = scopes.filter(scope => scope.applyMode === 'MANUAL');
|
||||
assignmentScopeSelect.innerHTML = manualScopes.length
|
||||
? manualScopes.map(scope => `<option value="${scope.id}">${escapeHtml(scope.name)}</option>`).join('')
|
||||
: '<option value="">Нет ручных сеток</option>';
|
||||
assignmentScopeSelect.disabled = manualScopes.length === 0;
|
||||
updateScopeActions();
|
||||
}
|
||||
|
||||
function updateScopeActions() {
|
||||
const activeScope = selectedScope();
|
||||
scopeDeleteButton.disabled = !activeScope || activeScope.systemScope;
|
||||
}
|
||||
@@ -146,37 +150,35 @@ export async function initTimeSlotsSettings() {
|
||||
`).join('');
|
||||
}
|
||||
|
||||
function renderAssignments() {
|
||||
if (!assignments.length) {
|
||||
assignmentsTbody.innerHTML = '<tr><td colspan="3" class="loading-row">Ручных назначений нет</td></tr>';
|
||||
return;
|
||||
}
|
||||
|
||||
assignmentsTbody.innerHTML = assignments.map(assignment => `
|
||||
<tr>
|
||||
<td>${escapeHtml(formatDate(assignment.date))}</td>
|
||||
<td>${escapeHtml(assignment.scopeName || '-')}</td>
|
||||
<td class="actions-cell">
|
||||
<button type="button" class="btn-delete btn-delete-assignment" data-id="${assignment.id}">Убрать</button>
|
||||
</td>
|
||||
</tr>
|
||||
`).join('');
|
||||
function openScopeModal() {
|
||||
scopeForm.reset();
|
||||
hideAlert('time-slot-scope-alert');
|
||||
scopeModal.classList.add('open');
|
||||
scopeModal.setAttribute('aria-hidden', 'false');
|
||||
window.setTimeout(() => scopeNameInput?.focus(), 0);
|
||||
}
|
||||
|
||||
async function createScope() {
|
||||
function closeScopeModal() {
|
||||
scopeModal.classList.remove('open');
|
||||
scopeModal.setAttribute('aria-hidden', 'true');
|
||||
hideAlert('time-slot-scope-alert');
|
||||
}
|
||||
|
||||
async function createScope(event) {
|
||||
event.preventDefault();
|
||||
const name = scopeNameInput.value.trim();
|
||||
if (!name) {
|
||||
showAlert('time-slot-alert', 'Введите название ручной сетки', 'error');
|
||||
showAlert('time-slot-scope-alert', 'Введите название ручной сетки', 'error');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
const saved = await api.post('/api/admin/time-slots/scopes', { name });
|
||||
scopeNameInput.value = '';
|
||||
activeScopeId = saved.id;
|
||||
closeScopeModal();
|
||||
showAlert('time-slot-alert', 'Сетка времени создана', 'success');
|
||||
await loadAll();
|
||||
} catch (error) {
|
||||
showAlert('time-slot-alert', error.message || 'Ошибка создания сетки времени', 'error');
|
||||
showAlert('time-slot-scope-alert', error.message || 'Ошибка создания сетки времени', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,43 +197,6 @@ export async function initTimeSlotsSettings() {
|
||||
}
|
||||
}
|
||||
|
||||
async function saveAssignment(event) {
|
||||
event.preventDefault();
|
||||
hideAlert('time-slot-assignment-alert');
|
||||
|
||||
const payload = {
|
||||
date: assignmentDateInput.value,
|
||||
scopeId: assignmentScopeSelect.value ? Number(assignmentScopeSelect.value) : null
|
||||
};
|
||||
|
||||
if (!payload.date || !payload.scopeId) {
|
||||
showAlert('time-slot-assignment-alert', 'Выберите дату и ручную сетку', 'error');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await api.post('/api/admin/time-slots/date-assignments', payload);
|
||||
assignmentForm.reset();
|
||||
showAlert('time-slot-assignment-alert', 'Сетка применена к дате', 'success');
|
||||
await loadAll();
|
||||
} catch (error) {
|
||||
showAlert('time-slot-assignment-alert', error.message || 'Ошибка назначения сетки', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function handleAssignmentTableClick(event) {
|
||||
const deleteButton = event.target.closest('.btn-delete-assignment');
|
||||
if (!deleteButton) return;
|
||||
if (!confirm('Убрать ручное применение сетки на эту дату?')) return;
|
||||
try {
|
||||
await api.delete('/api/admin/time-slots/date-assignments/' + deleteButton.dataset.id);
|
||||
showAlert('time-slot-assignment-alert', 'Ручное назначение удалено', 'success');
|
||||
await loadAll();
|
||||
} catch (error) {
|
||||
showAlert('time-slot-assignment-alert', error.message || 'Ошибка удаления назначения', 'error');
|
||||
}
|
||||
}
|
||||
|
||||
async function saveSlot(event) {
|
||||
event.preventDefault();
|
||||
hideAlert('time-slot-alert');
|
||||
@@ -350,9 +315,3 @@ function dayShort(dayOfWeek) {
|
||||
function trimTime(value) {
|
||||
return value ? String(value).slice(0, 5) : '';
|
||||
}
|
||||
|
||||
function formatDate(value) {
|
||||
if (!value) return '-';
|
||||
const [year, month, day] = String(value).split('-');
|
||||
return `${day}.${month}.${year}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user